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?
on 2006-02-16 17:58
on 2006-02-16 22: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?
on 2006-02-16 22:58
@thumbnail_array = @@thumbnail_array or...better yet... def thumbails @@thumbnail_array end <% for thumb in thumbnails %> -- -- Tom Mornini
on 2006-02-17 03:38
Tom Mornini 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 Mornini 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
on 2006-02-17 06:20
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
on 2006-02-17 13:41
Kevin Olbrich 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.
on 2006-02-17 17:23
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
on 2006-02-17 17:35
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
on 2006-02-18 04:15
Tony Collen 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
on 2006-02-18 06:40
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
on 2006-02-18 08:13
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