数组评估为零

时间:2012-06-06 00:23:05

标签: ruby-on-rails ruby arrays

下面我在一个名为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

2 个答案:

答案 0 :(得分:5)

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

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

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进行初始化。换句话说,如果您向GET发出index请求,ratings方法将被调用,而@all_ratings仍将是nil {1}}。

如果您从ratings明确调用 index,则@all_ratings将被初始化(通过ratings方法)。一旦在任何实例方法中初始化,该对象的实例(在本例中为控制器)具有初始化的@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

答案 1 :(得分:3)

请将@all_ratings = Movie.all_ratings移到控制器的索引操作中。如果它对所有操作都是通用的,那么将它放在before过滤器中,如下所示:

class MoviesController < ApplicationController

before_filter :load_ratings

def index
..
end

<other public methods>

private

def load_ratings
  @all_ratings = Movie.all_ratings
end