数组评估为零

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)

Dav*_*ton 5

初始化实例变量的代码需要在实例方法中.

(否则范围是类,而不是实例.)

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)

  • @Dylan只是有一个实例方法是不够的,该方法必须被*调用*.当您对索引url发出请求时,将调用index方法,因此将执行index方法,并初始化instanced变量.如果实例变量初始化发生在*different*方法中,在您的示例中为"rating",则在调用"index"方法时不会调用该方法 - 除非您从索引方法中明确调用"rating",因为我说明. (3认同)