2012-07-06 72 views
1

這是我的視圖中的代碼:show.html.erb返回未定義的方法'each'for nil:NilClass?

<ul> 
<% @bullets.each do |r| %> 
    <li><%= r.content %></li> 
<% end %> 
</ul> 

這是我的代碼中,所述控制器:users_controller.rb

if cookies[:bullets].nil? 
    @bullets = Bullet.all.shuffle.first(4) 
    cookies[:bullets] = @bullets.collect(&:id) 
else 
@bullets = [] 
cookies[:bullets].each do |id| 
    @bullets << Bullet.find(id) 
end 
end 

這將返回未定義的方法「各自」的零: NilClass上

<% @bullets.each do |r| %> 

我想知道爲什麼它這樣做,我怎麼能解決這個問題,從命名數據庫(sqlite3的)表發佈4項隨機固定子彈內容「子彈」(列是內容)。

編輯:這是整個控制器:

class StudentsController < ApplicationController 
    #GET/
    def index 
     @students = Student.all 

     respond_to do |format| 
     format.html # index.html.erb 
     format.json { render json: @students } 
     end 
    end 

    #GET /new 
    def new 
     @student = Student.new 
    end 

    #POST 
    def create 
     @student = Student.new(params[:student]) 
      if @student.save 
     render :file => 'app/views/success' 
     else 
     render :file => 'app/views/students/fail' 
     end 
     end 

    #GET /students/{:id} 
    def show 
     @student = Student.find_by_url(params[:id]) 

      respond_to do |format| 
     format.html # show.html.erb 
     format.json { render json: @student } 
      end 
    end 

    #BULLETS Randomizing /students/new.html.erb 
    if cookies[:bullets].nil? 
     @bullets = Bullet.all.shuffle.first(4) 
     cookies[:bullets] = @bullets.collect(&:id) 
    else 
    @bullets = [] 
    cookies[:bullets].each do |id| 
     @bullets << Bullet.find(id) 
    end 
    end 

    #GET /students/1/edit 
    def edit 
     @student = Student.find_by_url(params[:id]) 
    end 

    def update 
     @student = Student.find_by_url(params[:id]) 
     respond_to do |format| 
     if @student.update_attributes(params[:student]) 
      format.html { redirect_to @student, notice: 'Student was successfully updated.'} 
     else 
      format.html { render action: "edit" } 
      format.json { render json: @student.errors, status: :unprocessable_entity } 
     end 
     end 
    end 

    #DELETE 
    def destroy 
    @student = Student.find_by_url(params[:id]) 
    @student.destroy 

     respond_to do |format| 
     format.html { redirect_to students_url } 
     format.json { head :no_content } 
     end 
    end 
end 

編輯#2:像這樣嗎?

#GET /students/{:id} 
    def show 
     @student = Student.find_by_url(params[:id]) 

     #BULLETS Randomizing /students/show.html.erb 
    if cookies[:bullets].nil? 
     @bullets = Bullet.all.shuffle.first(4) 
     cookies[:bullets] = @bullets.collect(&:id) 
    else 
    @bullets = [] 
    cookies[:bullets].each do |id| 
     @bullets << Bullet.find(id) 
    end 
    end 

      respond_to do |format| 
     format.html # show.html.erb 
     format.json { render json: @student } 
      end 
    end 
+2

你確定'子彈'表不是空的? – 2012-07-06 03:05:36

+0

150%肯定它不是空的。 編輯:它包含8個具有ID,名稱,內容和時間戳的項目符號。 – Evan 2012-07-06 03:09:06

+1

即使該表爲空,當Array#first返回一個空數組(而不是nil)時,它會收到一個整數參數,並且明確地將'@ bullets'初始化爲'if'語句另一分支中的數組。您的控制器操作或視圖中是否還有其他事情發生,您可以發佈? – Brandan 2012-07-06 03:12:37

回答

2

看起來應該是:

#GET /students/{:id} 
def show 

    @student = Student.find_by_url(params[:id]) 

    #BULLETS Randomizing /students/new.html.erb 
    if cookies[:bullets].nil? 
    @bullets = Bullet.all.shuffle.first(4) 
    cookies[:bullets] = @bullets.collect(&:id) 
    else 
    # simpler to use an 'in list' for only 4 id's 
    Bullet.where("id in (?)", cookies[:bullets]) 
    end 

    respond_to do |format| 
    format.html # show.html.erb 
    format.json { render json: @student } 
    end 
end 

通知我轉換你的循環在cookies陣列分爲單個語句的「列表」 - 應該簡化生成的SQL查找。

雖然,這是值得商榷的,這個碼應該被推到模型:

class Bullet < ActiveRecord::Base 

    NUM_USER_BULLETS = 4 
    # fetch a random set of 
    def self.user_bullets 
    Bullet.all.shuffle.first(NUM_USER_BULLETS) 
    end 
end 

或者類似的東西。那麼你的控制器就更簡單了:

#GET /students/{:id} 
def show 

    @student = Student.find_by_url(params[:id]) 

    #BULLETS Randomizing /students/new.html.erb 
    if cookies[:bullets].nil? 
    @bullets = Bullet.user_bullets 
    cookies[:bullets] = @bullets.collect(&:id) 
    else 
    # simpler to use an 'in list' for only 4 id's 
    Bullet.where("id in (?)", cookies[:bullets]) 
    end 

    respond_to do |format| 
    format.html # show.html.erb 
    format.json { render json: @student } 
    end 
end 

隨着代碼遷移到你的模型中,你的控制器就更簡單了。

+0

而「(?)」中的「id」。它需要一些東西來代替'?'嗎? – Evan 2012-07-06 03:45:05

+1

語法'where(「id in(?)「,cookies [:bullets])''基本上是指在實際查詢中替換'''變量'cookies [:bullets]'*。 – 2012-07-06 03:53:25

+0

Ohhh好的,謝謝。問題第一次工作,但不是第二次(刷新後)? – Evan 2012-07-06 04:00:15

1
class StudentsController < ApplicationController 
    before_filter :get_bullets, :only => [:show] 


    def show 

    end 

    ... 


    protected 

    def get_bullets 
    #BULLETS Randomizing /students/new.html.erb 
    if cookies[:bullets].nil? 
     @bullets = Bullet.all.shuffle.first(4) 
     cookies[:bullets] = @bullets.collect(&:id) 
    else 
    @bullets = [] 
    cookies[:bullets].each do |id| 
     @bullets << Bullet.find(id) 
    end 
    end 

    end 



end 
1

我建議重構你的「隨機子彈」的代碼放到一個before_filtershow行動,並在數據庫中進行隨機化,這將是比加載整個表,並執行在Ruby中隨機化速度快:

class UsersController < ApplicationController 
    before_filter :assign_bullets, :only => :show 

    # ... 

private 

    def assign_bullets 
    if cookies[:bullets] 
     @bullets = cookies[:bullets].map { |id| Bullet.find(id) } 
    else 
     @bullets = Bullet.order('RANDOM()').limit(4) 
     cookies[:bullets] = @bullets.map(&:id) 
    end 
    end 
end 
+1

小心使用'RANDOM()' - 它的格式可以是數據庫特定的。另外,如果表格變大,它可能會減慢速度。在這裏看到更多的信息:http://stackoverflow.com/questions/2752231/random-record-in-activerecord – 2012-07-06 03:36:32

+1

謝謝@KevinBedell。那個線程絕對值得一讀。在決定解決方案之前,OP應該根據他的數據對這些不同的方法進行基準測試。 – Brandan 2012-07-06 13:19:46

+0

肯定這樣做。謝謝布蘭丹。 – Evan 2012-07-06 19:28:15

相關問題