Forum: Ruby on Rails Ruby class variables and access from view templates

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Ross A. (Guest)
on 2006-02-16 18:58
I have an app that requires me to define a class variable (actually an
array) in a controller and then access it from within a view. It seems
that the class variables aren't working right. Here is an example of
what I'm trying to do.

class DisplayController < ApplicationController

@@thumbnail_array = Array.new

...

def some_method
  @@thumbnail_array = SomeModel.find_all
...
end

.....
end

Then in the view for some_method,

<% for thumb in @@thumbnail_array %>
...
do something interesting


But my app blows up at that point giving me an unitialized class
variable - @@thumbnail_array.

What am I doing wrong?
Ross A. (Guest)
on 2006-02-16 23:37
Ross Ashley wrote:
> class DisplayController < ApplicationController
>
> @@thumbnail_array = Array.new
>
> ...
>
> def some_method
>   @@thumbnail_array = SomeModel.find_all
> ...
> end
>
> .....
> end
>
> Then in the view for some_method,
>
> <% for thumb in @@thumbnail_array %>
> ...
> do something interesting
>
>
> But my app blows up at that point giving me an unitialized class
> variable - @@thumbnail_array.

Incidently, this works when I use an instance variable,
@thumbnail_array, But I have to modify the array from another method in
the controller which is why I am trying to get the class variable to
work.

Suggestions?
Tom M. (Guest)
on 2006-02-16 23:58
(Received via mailing list)
@thumbnail_array = @@thumbnail_array

or...better yet...

def thumbails
   @@thumbnail_array
end

<% for thumb in thumbnails %>

--
-- Tom M.
Ross A. (Guest)
on 2006-02-17 04:38
Tom M. wrote:
> @thumbnail_array = @@thumbnail_array

That allows me to access the instance variable from the view template.
Thanks.

> def thumbails
>    @@thumbnail_array
> end
>
> <% for thumb in thumbnails %>
>
> --
> -- Tom M.

I no longer need this info but I'm not sure how to map the call to
thumbnails back to the controller class. That is, how do you fix the
undefined local variable or method error in the controller.

But, this doesn't fix my real problem.

The reason I have go through this is that I have to access that class
variable from a different method within the same class.

So...

class DisplayController < ApplicationController

  @@thumbnail_array = Array.new

  def some_method
    @@thumbnail_array = SomeModel.find_all
  end

  def another_method
    @variable = @@thumbnail_array.size
  end

end

Now any call to DisplayController.another_method will cause an error. It
doesn't matter where I put the @@thumbnail_array definition, either in
the initialize method or at the top of the class.

This leads me to believe that class variables don't work in Rails. That
makes no sense.

Ross
Kevin O. (Guest)
on 2006-02-17 07:20
(Received via mailing list)
What is probably happening here is that your first method is setting up
the array properly.  At the end of the request, the entire controller
object goes out of scope and your class array with it.  When the
controller gets set up for the next request, it creates and
re-initializes the class variable.

You could set up a before_filter to populate an instance variable.

_Kevin
Ross A. (Guest)
on 2006-02-17 14:41
Kevin O. wrote:
> What is probably happening here is that your first method is setting up
> the array properly.  At the end of the request, the entire controller
> object goes out of scope and your class array with it.  When the
> controller gets set up for the next request, it creates and
> re-initializes the class variable.
>
> You could set up a before_filter to populate an instance variable.

That makes sense. I suppose a class variable in Ruby is not really the
same thing as a static variable in C++. It explains why I had to resort
to global variables in another section.

Thanks.
Ben M. (Guest)
on 2006-02-17 18:23
(Received via mailing list)
Ross Ashley wrote:
> That makes sense. I suppose a class variable in Ruby is not really the
> same thing as a static variable in C++. It explains why I had to resort
> to global variables in another section.

Hmm, why not? I thought "@@" variables are available to all instances.
How is that not
like "static"?

And you make a "static" method by defining it as MyClass.methodname or
self.methodname...

b
Tony C. (Guest)
on 2006-02-17 18:35
(Received via mailing list)
I asked about this once on the IRC channel and the answer was basically,
"use a database for this" .. I suspect it's a reasonable thing to
suggest.
I think it really has to do with the lifecycle of classes, when they are
created, destroyed, etc.

Tony
Ross A. (Guest)
on 2006-02-18 05:15
Tony C. wrote:
> I asked about this once on the IRC channel and the answer was basically,
> "use a database for this" .. I suspect it's a reasonable thing to
> suggest.
> I think it really has to do with the lifecycle of classes, when they are
> created, destroyed, etc.
>
> Tony

In C++ when you instantiate a class, if it has a static variable, that
variable is available to any instance of that class, regardless of
whether all instances of it go out of scope. That is, when a new object
is created, even if all previous instantiations have gone out of scope,
it has access to the static variable and to it's previously defined
value. I thought that was what @@ meant. But, apparently, if all
instances of a class are out of scope, when a new object is
instantiated, the class variable loses it's previously defined value.

I wish this weren't the case, but when a new controller class is
instantiated in Rails, any @@ variables get reinitialized.

So how is that not just a @ variable?

IOW, has anyone gotten @@ variables in a controller class to work?

--Ross
Ben M. (Guest)
on 2006-02-18 07:40
(Received via mailing list)
Ross Ashley wrote:
> instantiated in Rails, any @@ variables get reinitialized.
>
> So how is that not just a @ variable?
>
> IOW, has anyone gotten @@ variables in a controller class to work?
>
> --Ross

I've been wondering about this too. Here's what I just tried:

I put this in my environment.rb:

@@foo = ["Start foo: " + Time.now.to_s]

I put this in a controller:

logger.info("foo output: " + @@foo.to_s)
@@foo << "foo again: " + Time.now.to_s

When I hit that action the "foo output: ..." shows up in my log and on
each request I get
another addition to my array with the time on it.

However, if I move the initialization of @@foo into the controller, I
get just "Start
foo..." on every request. So, yes, rails somehow renders @@ variable
useless. Guess that's
why I never see them in code examples.

You can, however, put the global in environment.rb and it'll retain it's
state... at least
in webrick. Not sure how FastCGI handles that.

b
Kevin O. (Guest)
on 2006-02-18 09:13
(Received via mailing list)
I would be interested to see if there are differences in class variable
handling between development and production mode.  In development mode a
lot of the code gets reloaded every request, but in production mode this
doesn't happen so much.

As a general rule it is probably best to avoid using class variables to
store stuff.  If you scale your app to multiple web servers, the next
request might not go back to the same box and would not have access to
anything you put in the class variable.

You should probably use one of the following to get the same effect..

1. store it in the database
2. use the session hash
3. use a before_filter
4. write it to a temp file

An enterprising person could probably write a plugin that would emulate
the typical class variable behavior by using one the previously
mentioned methods to store the contents.

_Kevin
This topic is locked and can not be replied to.