Below I created a class method in a model called Movie that should return an array:
def self.all_ratings
Array['G','PG','PG-13','R','NC-17']
end
And in my movies controller I access it using the following instance variable:
@all_ratings = Movie.all_ratings
However when it comes time to use it in my index view I receive the following errors:
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each
I believe I am creating the array properly but I could be wrong. Any suggestions why these errors occur?
Below is the view where @all_ratings is used:
%h1 All Movies
= form_tag movies_path, :method => :get do
Include:
- @all_ratings.each do |rating|
= rating
= check_box_tag "ratings[#{rating}]"
= submit_tag 'Refresh'
And here is how I implemented @all_ratings into the controller
class MoviesController < ApplicationController
@all_ratings = Movie.all_ratings
The code to initialize an instance variable needs to be in an instance method.
(Otherwise the scope is the class, not an instance.)
If you need that value in several methods, you could use, say, a
before_filter.Ruby is different from languages like, say, Java. In Java, instance variables are defined outside instance methods, and are available in every instance method, with whatever value they were initialized with.
In Ruby, there are two (major) ways to handle instance variables: use a method like
attr_accessorto create accessor methods, or initialize them inside an instance method, as shown above.Once an instance variable has initialized, its value is usable from any other instance method. For example, in your comments you mention initializing it in a
ratingsmethod. Unlessratingsis explicitly called,@all_ratingswill not be initialized. In other words, if you make aGETrequest toindex, theratingsmethod will not be called, and@all_ratingswill still benil.If you explicitly call
ratingsfromindex, then@all_ratingswill be initialized (by theratingsmethod). Once it’s initialized in any instance method, that instance of the object (the controller in this case) has an initialized@all_ratingsinstance variable:Now the value of
@all_ratingsis available in index’s template.Without putting the instance variable initialization in an instance method what you’re actually doing is creating an instance variable in the class
Foo, which is something very different: