2

下面我在一个名为 Movie 的模型中创建了一个类方法,它应该返回一个数组:

def self.all_ratings
  Array['G','PG','PG-13','R','NC-17']
end

在我的电影控制器中,我使用以下实例变量访问它:

@all_ratings = Movie.all_ratings

但是,当在我的索引视图中使用它时,我收到以下错误:

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 的视图:

%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'

这是我在控制器中实现@all_ratings 的方式

class MoviesController < ApplicationController

  @all_ratings = Movie.all_ratings
4

2 回答 2

5

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

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

class MoviesController < ApplicationController
  def index # Or wherever
    @all_ratings = Movie.all_ratings
  end
end

如果您在多种方法中需要该值,则可以使用 a before_filter

Ruby 与 Java 等语言不同。在 Java 中,实例变量是在实例方法之外定义的,并且在每个实例方法中都可用,无论它们的初始化值是什么。

在 Ruby 中,有两种(主要)方法来处理实例变量:使用方法如attr_accessor创建访问器方法,或在实例方法中初始化它们,如上所示。

一旦实例变量初始化,它的值就可以从任何其他实例方法中使用。例如,在您的评论中,您提到在ratings方法中对其进行初始化。除非ratings被显式调用,@all_ratings否则不会被初始化。换句话说,如果您向 发出GET请求index,该ratings方法将不会被调用,并且@all_ratings仍然会是nil

如果您显式调用 ratingsfrom index@all_ratings则将被初始化(通过ratings方法)。一旦在任何实例方法中初始化,该对象的实例(在本例中为控制器)就有一个初始化的@all_ratings实例变量:

def index
  ratings
end

现在 的值@all_ratings在索引的模板中可用。

如果不将实例变量初始化放在实例方法中,您实际上正在做的是在class 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
于 2012-06-06T00:45:49.890 回答
3

@all_ratings = Movie.all_ratings在控制器的 index 动作内移动。如果它对所有动作都是通用的,则将其放入 before 过滤器中,如下所示:

class MoviesController < ApplicationController

before_filter :load_ratings

def index
..
end

<other public methods>

private

def load_ratings
  @all_ratings = Movie.all_ratings
end
于 2012-06-06T00:47:47.590 回答