Dynamically named variables or Constants


#1

Hi,

for each user I need to create and call
a dynamically named GLOBAL variable (or Constant)
labeled with the user name.
To make it clear what I mean:

begin “Ruby Pseudocode”

user_name = “tom”
$#{user_name}_dyn_var = “/path/to/nirvana”

end “Ruby Pseudocode”

Is there a way to do that?
How would I call that new variable ‘$#{user_name}_dyn_var’ ?
I tried “Module::const_set”:

begin Ruby

constant_name = “#{user_name.upcase}_VAR”
constant = self::class::const_set(constant_name, “/path/to/nirvana”)

end Ruby

but couldn’t find a way to call “#{user_name.upcase}_VAR”.

you may ask why I either need a global var or a Constant:
I am using the “live_tree” plugin
from http://www.epiphyte.ca/code/live_tree.html
to create a file system browser.
As far as I can tell,
the plugin requires either a global var or a Constant
to initialize the file system model.

If someone has tried this plugin before
and found another solution, let me know.
The author is not responding to my mails.

Thanks for your input,
Tom.


#2

Alle domenica 6 maggio 2007, Tom V. ha scritto:

end “Ruby Pseudocode”

but couldn’t find a way to call “#{user_name.upcase}_VAR”.
and found another solution, let me know.
The author is not responding to my mails.

Thanks for your input,
Tom.

I’m not sure about what you mean when saying 'a way to
call “#{user_name.upcase}_VAR”. If you mean how to get the value of the
constant, then you can use const_get, which works like const_set:

self.class.const_get( constant_name)
=> “/path/to/nirvana”

I hope this helps

Stefano


#3

Hi Stefano,

thanks for your advice.
However, when I try to call “self.const_get”
from another method (but same class), I get an error:

–> NameError (uninitialized constant MyClass::TOM_VAR)

Here is how I created ‘TOM_VAR’ (simplified):

def xyz_method

constant_name = "#{@user.name.upcase}_VAR"
logger.info("#{constant_name}")
# output: TOM_VAR

constant = MyClass.const_set(constant_name, "/path/to/nirvana")
logger.info("#{constant}")
# output: /path/to/nirvana

session[:constant_name] = constant_name

end

In the following method I get the error:

def abc_method

@constant = MyClass.const_get(session[:constant_name])
# ERROR

end

Thanks for helping me out
Tom.

On Sun, 6 May 2007 20:21:53 +0900


#4

Alle domenica 6 maggio 2007, Tom V. ha scritto:

def xyz_method

Thanks for helping me out
Tom.

I can’t understand why you get an error. I modified your code just a bit
(by
the way, what exactly is session?) to give the two methods some context
and
put it in a script:

class MyClass

def initialize
@user = ‘tom’
@session = {}
end

def xyz_method

  constant_name = "#{@user.upcase}_VAR"

  constant = MyClass.const_set(constant_name, "/path/to/nirvana")

  @session[:constant_name] = constant_name

end

def abc_method

  @constant = MyClass.const_get(@session[:constant_name])
  puts @constant

end
end

c = MyClass.new
c.xyz_method
c.abc_method

This works. Since I don’t know anything about rails and the live tree
plugin,
I may have missed something related to them. You can try using
MyClass.constants in the abc_method to get a list of the constants
defined
for MyClass; this could give you some hints about what’s happening.

Stefano


#5

Hi Stefano,

it’s not working for me.
MyClass.const_get always returns a NameError.
Trying:

MyClass.const_defined?(session[:constant_name])

always returns ‘false’
(except for the method where constant_name was defined…).

My guess is that ‘session’ cannot store Constants created the way I do
it.
However, storing other large and complex objects is not a problem.

‘session’ is the standard Rails hash-like collection
using key/values pairs to store information
during subsequent requests from the same browser.
@session’ is deprecated now.

Thanks for your input.
Tom.

My Ruby version is:
ruby 1.8.5 (2006-12-04 patchlevel 2) [i686-linux]

On Sun, 6 May 2007 22:05:42 +0900


#6

On 5/6/07, Tom V. removed_email_address@domain.invalid wrote:

My guess is that ‘session’ cannot store Constants created the way I do it.
However, storing other large and complex objects is not a problem.

You guess is in the territory, but it’s not really about session’s
capability. if xyz_method is a controller action for instance, and
abc_method is a controller action, there’s nothing guaranteeing per se
that you’re state is going to be persisted between user interactions
with the web app. What you really need to store in session is the name
of the constant, AND it’s value. and then you need to const_set it at
the beginning of every method where you make use of this live tree
thing.


#7

“Logan C.” removed_email_address@domain.invalid wrote:

You guess is in the territory, but it’s not really about session’s
capability. if xyz_method is a controller action for instance, and
abc_method is a controller action, there’s nothing guaranteeing per se
that you’re state is going to be persisted between user interactions
with the web app. What you really need to store in session is the name
of the constant, AND it’s value. and then you need to const_set it at
the beginning of every method where you make use of this live tree
thing.

Hi,
Creating a new constant from session data still doesn’t work.
As you said I now store both constant_name and constant_value in
session.

However, when trying to test the new Constant (const_defined?),
I get a NameError (see below).

Also, when printing it, its value is printed, not its name:
“{@new_constant}” --> “/path/to/nirvana”.
How do I access its name?

Maybe you find an error in code.
Or maybe you know of another way
to create dynamically named variables…?

class AbcController < ApplicationController

before_filter :get_constants, :except => :define_constants

def define_constants
@user = “tom”
constant_name = “#{@user.upcase}_PATH”
logger.info("#{constant_name}")
# output: TOM_PATH

constant_value = self::class::const_set(constant_name, 

“/path/to/nirvana”)
logger.info("#{constant_value}")
# output: /path/to/nirvana

session[:constant_name] = constant_name
session[:constant_value] = constant_value

end

def get_constants
if session[:constant_name]
@constant_name = session[:constant_name]
logger.info("#{@constant_name}")
# output: TOM_PATH

  if session[:constant_value]
    @constant_value = session[:constant_value]
    logger.info("#{@constant_value}")
    # output: /path/to/nirvana

    @new_constant = self::class::const_set(@constant_name, 

@constant_value)
logger.info("#{@new_constant}")
# output: /path/to/nirvana

    evaluate_constant = self::class::const_defined?(@new_constant)
    # output: NameError (wrong constant name /path/to/nirvana)

  end
end

end

end

Thanks for your input,
Tom.


#8

Hi Logan,

thanks for the hint.
However that did not get me too far.

So now I use simple instance variables
and the session storage utility.

But I always get a strange error that let me to the idea
of using constants in the first place…

Although this is a rails project using a plugin,
the error I get is from using std ruby libraries.
so maybe you can enlighten me…
Please have a quick look:

Constructor for creating a new “live_tree”:

class MyController

live_tree :fstree, :find_item_proc =>
Proc.new { |x| FileSystemItem.new(x, @user_path) }

end

class FileSystemItem
def initialize(path, root)
@path = path
log << “root = #{root} - class = #{root.class}\n”
# output:
# root = /user/path/ - class = String

@root = File.expand_path(root)
# ERROR:
# TypeError (can't convert nil into String):
#  .//app/models/file_system_item.rb:17:in `expand_path'
#  .//app/models/file_system_item.rb:17:in `initialize'
#  .//app/controllers/my_controller.rb:452:in `new'

end
end

“root” contains the user path and is of type String.
However, when calling File.expand_path,
I get the NameError.

When using a constant or a global variable
this error does not occur…

Any ideas?

Thanks for your time,
Tom.

On Mon, 7 May 2007 03:53:12 +0900


#9

On 5/6/07, Tom V. removed_email_address@domain.invalid wrote:

thing.
“{@new_constant}” --> “/path/to/nirvana”.

  if session[:constant_value]
    @constant_value = session[:constant_value]
    logger.info("#{@constant_value}")
    # output: /path/to/nirvana

    @new_constant = self::class::const_set(@constant_name,

@constant_value)
logger.info("#{@new_constant}")
# output: /path/to/nirvana

    evaluate_constant = self::class::const_defined?(@new_constant)

should be self::class:const_defined?(@constant_name) of course.
@new_constant is gonna hold the value of the constant, not the name.

    # output: NameError (wrong constant name /path/to/nirvana)

#10

On Mon, 7 May 2007 20:26:10 +0900
“Logan C.” removed_email_address@domain.invalid wrote:

That seems really weird. Maybe ruby is not being as clear with reporting the
error as it could be. At this point I’d try using a debugger to get to the
bottom of it.

ok, thanks.
do you happen to know a decent ruby debugger…?
haven’t found one so far.
I am using linux.
Tom.


#11

On 5/7/07, Tom V. removed_email_address@domain.invalid wrote:

haven’t found one so far.
I am using linux.

My weapon of choice when I want to pull out the big guns is
ruby-debug, it’s available as a gem.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/


#12

On 5/7/07, Tom V. removed_email_address@domain.invalid wrote:

of using constants in the first place…
live_tree :fstree, :find_item_proc =>

However, when calling File.expand_path,
I get the NameError.

When using a constant or a global variable
this error does not occur…

Any ideas?

That seems really weird. Maybe ruby is not being as clear with reporting
the
error as it could be. At this point I’d try using a debugger to get to
the
bottom of it.

Thanks for your time,