2012-06-06 61 views
2

下面我创建了一个模型被称为电影的一类方法应该返回一个数组:阵列评估为零

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 
+0

发布您的视图代码,您的数组创建功能。 –

+0

您可能需要提供更多信息;而'all_ratings'是多余的,这是正确的。 –

+0

刚刚更新了查看代码 – Anconia

回答

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

如果你明确电话ratingsindex,然后@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 
+0

当我将它添加到索引方法时,它正常工作!但是,当我创建一个自己的方法时,比如def评级; @all_ratings = Movie.all_ratings;结束;它失败。我很好奇这背后的科学是什么? – Anconia

+1

@Dylan该方法需要实际执行以使其中的任何内容都被执行。如果*从'index'方法调用*'ratings',效果将是相同的 - 实例变量将被初始化。除非你使用过滤器,否则它不会被魔法调用,正如我提到的(并且Anil给出了一个例子),或者你明确地调用它。 –

+0

我明白你的观点,必须有一个实例方法来执行;正如我所提到的,我创建了一个名为ratings的实例方法来放入实例变量。这导致了网页上的错误,但是当我将实例变量放入index方法中时,代码正确执行。我很好奇为什么它在实例方法索引中起作用,但没有评分。索引实例方法是否映射到索引视图,而实例方法评级没有? – Anconia

3

请将@all_ratings = Movie.all_ratings在控制器的索引操作中。如果对所有操作都很常见,则将其放入过滤前如下:

class MoviesController < ApplicationController 

before_filter :load_ratings 

def index 
.. 
end 

<other public methods> 

private 

def load_ratings 
    @all_ratings = Movie.all_ratings 
end 
+0

也适用,希望我可以同时接受!投了票,不管 – Anconia

+0

@Dylan谢谢你的感悟。分数并不重要。乐趣在于解决问题,帮助,最重要的是学习。 – Anil