2012-06-06 63 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