下面我在一个名为 Movie 的模型中创建了一个类方法,它应该返回一个数组:
def self.all_ratings
Array['G','PG','PG-13','R','NC-17']
end
在我的电影 Controller 中,我使用以下实例变量访问它:
@all_ratings = Movie.all_ratings
然而,当在我的索引 View 中使用它时,我收到以下错误:
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
我相信我正确地创建了数组,但我可能是错的。为什么会出现这些错误有什么建议吗?
下面是使用@all_ratings 的 View :
%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'
下面是我如何在 Controller 中实现@all_ratings
class MoviesController < ApplicationController
@all_ratings = Movie.all_ratings
最佳答案
初始化实例变量的代码需要在实例方法中。
(否则范围是类,而不是实例。)
class MoviesController < ApplicationController
def index # Or wherever
@all_ratings = Movie.all_ratings
end
end
如果您需要在多个方法中使用该值,您可以使用例如 before_filter
。
Ruby 不同于 Java 等语言。在 Java 中,实例变量是在实例方法之外定义的,并且在每个实例方法中都可用,无论它们是用什么值初始化的。
在 Ruby 中,有两种(主要)方法来处理实例变量:使用类似 attr_accessor
的方法来创建访问器方法,或者在实例方法中初始化它们,如上所示。
一旦一个实例变量被初始化,它的值就可以从任何其他实例方法中使用。例如,在您的评论中,您提到在 ratings
方法中对其进行初始化。除非显式调用 ratings
,否则 @all_ratings
将不会被初始化。换句话说,如果您向 index
发出 GET
请求,ratings
方法将不会被调用,并且@all_ratings
仍将是 nil
。
如果您从 index
显式调用 ratings
,那么 @all_ratings
将被初始化(由 ratings
方法)。一旦它在任何实例方法中初始化,该对象实例(在本例中为 Controller )就有一个初始化的@all_ratings
实例变量:
def index
ratings
end
现在 @all_ratings
的值在索引的模板中可用。
如果不将实例变量初始化放在实例方法中,您实际上在做的是在类 Foo
中创建一个实例变量,这是非常不同的:
[1] pry(main)> class Foo
[1] pry(main)* @wat = self.class
[1] pry(main)* end
=> Class
[2] pry(main)> f = Foo.new
=> #<Foo:0x007fbfba8efba8>
[5] pry(main)> f.instance_variables
=> []
[6] pry(main)> Foo.instance_variables
=> [:@wat]
[7] pry(main)> Foo.instance_eval "@wat"
=> Class
关于ruby-on-rails - 数组评估为零,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10906774/