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
| |
|
|
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
|
|
|
|
|