Anc*_*nia 2 ruby arrays ruby-on-rails
下面我在一个名为Movie的模型中创建了一个类方法,它应该返回一个数组:
def self.all_ratings
Array['G','PG','PG-13','R','NC-17']
end
Run Code Online (Sandbox Code Playgroud)
在我的电影控制器中,我使用以下实例变量访问它:
@all_ratings = Movie.all_ratings
Run Code Online (Sandbox Code Playgroud)
但是,当我在索引视图中使用它时,我收到以下错误:
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
Run Code Online (Sandbox Code Playgroud)
我相信我正在正确地创建阵列,但我可能是错的.有关这些错误发生的原因吗?
以下是使用@all_ratings的视图:
%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'
Run Code Online (Sandbox Code Playgroud)
以下是我如何将@all_ratings实现到控制器中
class MoviesController < ApplicationController
@all_ratings = Movie.all_ratings
Run Code Online (Sandbox Code Playgroud)
初始化实例变量的代码需要在实例方法中.
(否则范围是类,而不是实例.)
class MoviesController < ApplicationController
def index # Or wherever
@all_ratings = Movie.all_ratings
end
end
Run Code Online (Sandbox Code Playgroud)
如果您需要在多种方法中使用该值,则可以使用,例如a before_filter.
Ruby与Java之类的语言不同.在Java中,实例变量是在实例方法之外定义的,并且在每个实例方法中都可用,具有初始化的任何值.
在Ruby中,有两种(主要)方法来处理实例变量:使用类似attr_accessor创建访问器方法的方法,或者在实例方法中初始化它们,如上所示.
初始化实例变量后,其值可从任何其他实例方法使用.例如,在您的评论中,您提到在ratings方法中初始化它.除非ratings明确调用,@all_ratings否则不会被初始化.换句话说,如果你发出GET请求index,该ratings方法将不会被调用,并且@all_ratings仍将是nil.
如果显式调用 ratings from index,@all_ratings则会初始化(通过ratings方法).一旦在任何实例方法中初始化,该对象的实例(在本例中为控制器)具有初始化的@all_ratings实例变量:
def index
ratings
end
Run Code Online (Sandbox Code Playgroud)
现在@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
Run Code Online (Sandbox Code Playgroud)