2012-07-06 53 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

相关问题