More elegant replacement for global variables

M

Michael

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
 
D

dave.burt

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
 
T

Trans

Michael said:
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.
 
R

Robert Klemme

Michael said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,999
Messages
2,570,243
Members
46,835
Latest member
lila30

Latest Threads

Top