On Apr 11, 2006, at 4:10 PM, Wes G. wrote:
Create a class variable in my helper class and use that?
How do you reference a class variable from an object of another class?
Thanks,
Wes
Wes-
I posted this as a tip a few days ago but no-one seemed to notice
it. The follwing is a nice way to get application wide context hashes
or even custom classes. Hope it helps you.
-Ezra
-----Easy AppServer----------------
An easy way to get yourself an application wide context is to use
drb. Ara Howard has written an awesome library called slave that
takes care of forking a child process to run your drb server in and
then doing a heartbeat back and forth from your rails app to the
application wide classes(AppServer from here on out.). This heartbeat
is needed so that when rails starts, the AppServer starts and when
rails stops the AppServer stops because the heartbeat doesn’t respond
anymore.
This slave library allows you to publish whatever class you want as
an application wide class. This means that all your requests can get
the same application wide vars or objects no matter how many fcgi’s
or mongrel’s you have serving up requests. You could also just as
easily serve up an app wide array or hash. Lets look at a small
example of this.
Get the slave library here:
http://codeforpeople.com/lib/ruby/slave/slave-0.0.0/README
http://codeforpeople.com/lib/ruby/slave/slave-0.0.0.tgz
Now lets publish a simple hash that we can use application wide. Put
the following in your environment.rb file so it starts up when rails
starts up.
$application_wide_hash = Slave.new(Hash.new).object
Thats all. Now you can use $application_wide_hash anywhere in your
rails apps and it will behave just like a hash. So you are still
responsible for making suitable hash keys that you can use between
requests and still distinguish from one another. But since you can
store any object in a ruby hash you can store anything you want in
this $application_wide_hash. Just make a unique key and store it in
the users session. Maybe something like this:
key = "#{current_user.id}-#{Time.now}-#{rand}
session[:app_server_key] = key
$application_wide_hash[key] =
SomeObjectOrValueYouWantToStoreInApplicationWideStorage
Then on the next request you can get that object back with this:
$application_wide_hash[session[:app_server_key]]
This approach allows for a very flexible application wide context.
It’s uses are only limited to your creativity Of course you might
want to publish a different class then a hash in this AppServer. If
you want to do that then just replace this:
$application_wide_hash = Slave.new(Hash.new).object
with this:
$application_wide_hash = Slave.new(MyAppServerObject.new).object
The slave library will take care of forking a background process and
starting a drb server inside said process. Then the heartbeat takes
care of shutting down the AppServer when you shut down rails so you
don’t get orphaned AppServers. Of course all the context in your
$application_wide_hash will be lost when you restart or shutdown
rails and you are responsible for deleting things out of the
$application_wide_hash when you are done with them.
If you really want the $application_wide_hash to be persistent
between restarts of rails then you will need to do a little custom
coding yourself. With a bit of hacking you can hook into the
heartbeat code and marshall the $application_wide_hash to disk as
Yaml or binary and then reload that when rails starts back up.
The objects or classes that you put in the AppServer cannot contain
procs, lambdas or anything else that cannot be marshalled by ruby and
drb. The way around this is to use DrbUndumped. I won’t go into
detail about that here but you can look up resources on how to do
this with google
I have a full chapter on this technique in my forthcoming book that
goes into detail of what this process can be used for and what is
shouldn’t be used for. As well as concrete examples and code that
folks might find useful if they need to do this kind of thing.
Cheers-
-Ezra