For Programmers: Free Programming Magazines  


Home > Archive > Ruby > August 2005 > More elegant replacement for global variables









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author More elegant replacement for global variables
Michael

2005-08-31, 3:59 am

I'm playing around with a ruby app using XML-RPC. Currently I'm using
global variables so I can create multiple objects without having to log
in for each and every object.

class Base
def initialize(user, pass)
$user, $pass = user, pass
end

def login()
$client = XMLRPC::Client.new(...)
$sessionid = $client.call("xmlrpc.method", $user, $pass)
return $sessionid
end
end

Derived classes look like this:

class Object1 < Base
def initialize()
if not $sessionid then self.login end
end
end

This way I can log in once with the first object created without having
to log in each time. However, this seems inelegant to me. Is there a
more elegant, or just more rubyish, way of doing this? Also, I'd have
potential problems if I wanted to log on as multiple users.

Would it make more sense just to pass around an instance of the Base object:

class Object2
def initialize(xmlrpc_client)
if not xmlrpc_client.sessionid then xmlrpc_client.login
end

def call_xmlrpc_method(method, params)
results = xmlrpc_client.call(method, params)
return results
end
end

xmlrpc_client = Base.new
o2 = Object2.new(xmlrpc_client)

Pro: no global variables. Con: coupling between Object2 and Base classes.
--Michael
dave.burt@gmail.com

2005-08-31, 3:59 am

Constants are a kind of global variable. Classes get free constants.
You can use something like the Singeton pattern:

module XmlRpc
def self.login(user, pass)
@user = user
@client = = XMLRPC::Client.new(...)
@session_id = @client.call("xmlrpc.method", $user, $pass)
end
def self.user() @user or raise "Not initialized" end
def self.client() @user or raise "Not initialized" end
def self.session_id() @session_id or raise "Not initialized" end
end

Then you can login globally like so:
XmlRpc.login("me", "my_password")

Then elsewhere you can use:
client = XmlRpc.client
session_id = XmlRpc.session_id
(Which will throw an exception if you're not logged in yet)

What do you think? It's still global.

Of course another idea is to use a single global, a Hash or OpenStruct,
for these related data points: $xmlrpc[:session_id]

Cheers,
Dave

Trans

2005-08-31, 3:59 am


Michael wrote:
> I'm playing around with a ruby app using XML-RPC. Currently I'm using
> global variables so I can create multiple objects without having to log
> in for each and every object.
>
> class Base
> def initialize(user, pass)
> $user, $pass = user, pass
> end
>
> def login()
> $client = XMLRPC::Client.new(...)
> $sessionid = $client.call("xmlrpc.method", $user, $pass)
> return $sessionid
> end
> end
>
> Derived classes look like this:
>
> class Object1 < Base
> def initialize()
> if not $sessionid then self.login end
> end
> end
>
> This way I can log in once with the first object created without having
> to log in each time. However, this seems inelegant to me. Is there a
> more elegant, or just more rubyish, way of doing this? Also, I'd have
> potential problems if I wanted to log on as multiple users.
>
> Would it make more sense just to pass around an instance of the Base object:
>
> class Object2
> def initialize(xmlrpc_client)
> if not xmlrpc_client.sessionid then xmlrpc_client.login
> end
>
> def call_xmlrpc_method(method, params)
> results = xmlrpc_client.call(method, params)
> return results
> end
> end
>
> xmlrpc_client = Base.new
> o2 = Object2.new(xmlrpc_client)
>
> Pro: no global variables. Con: coupling between Object2 and Base classes.
> --Michael


Avoid globals by using container classes/modules. In your cace you
might use the base class itself.

class Base
class << self
attr_accessor :user, :pass
attr_reader :client, :sessionid
def login(user=nil,pass=nil)
@user = user if user
@pass = pass if pass
@client = XMLRPC::Client.new(...)
@sessionid = @client.call("xmlrpc.method", @user, @pass)
return @sessionid
end
end

def initialize
if not self.class.sessionid then self.class.login end
end
end

class Object1 < Base
def initialize()
super
end
end

Then use

Base.login('name','password')

or

Base.user = 'name'
Base.pass = 'password'
Base.login

And go from there. Hope I understood the intent of your code correctly.

T.

Robert Klemme

2005-08-31, 3:59 am

Michael wrote:
> I'm playing around with a ruby app using XML-RPC. Currently I'm using
> global variables so I can create multiple objects without having to
> log
> in for each and every object.
>
> class Base
> def initialize(user, pass)
> $user, $pass = user, pass
> end
>
> def login()
> $client = XMLRPC::Client.new(...)
> $sessionid = $client.call("xmlrpc.method", $user, $pass)
> return $sessionid
> end
> end
>
> Derived classes look like this:
>
> class Object1 < Base
> def initialize()
> if not $sessionid then self.login end
> end
> end
>
> This way I can log in once with the first object created without
> having
> to log in each time. However, this seems inelegant to me. Is there a
> more elegant, or just more rubyish, way of doing this? Also, I'd have
> potential problems if I wanted to log on as multiple users.
>
> Would it make more sense just to pass around an instance of the Base
> object:
>
> class Object2
> def initialize(xmlrpc_client)
> if not xmlrpc_client.sessionid then xmlrpc_client.login
> end
>
> def call_xmlrpc_method(method, params)
> results = xmlrpc_client.call(method, params)
> return results
> end
> end
>
> xmlrpc_client = Base.new
> o2 = Object2.new(xmlrpc_client)
>
> Pro: no global variables. Con: coupling between Object2 and Base
> classes. --Michael


Although your scenario is not fully clear to me, I'd have a session
instance that stores all session related information. Also I would not
have your classes (Object1) inherit the session class but instead pass it
around.

Kind regards

robert

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com