未定义的方法`map' for nil:提交选择标记时的NilClass

时间:2015-04-28 20:26:05

标签: ruby-on-rails

我是Rails的新手。现在提交表格时我有一个问题。 提交表单后,将显示

NoMethodError in Foods#new, Showing ..../new.html.erb where line #16 raised:
undefined method `map' for nil:NilClass

而第16行是:

<%= select_tag(:category_id, options_for_select(@categories), :prompt => "Please select") %>

我对方法地图有点困惑,是否需要将其添加到创建操作中?

这是我的新动作

def new
@food = Food.new    
@categories = Category.all.map{|c| [ c.name, c.id ] }
end

这是我的创作动作

def create
@food = Food.new(food_params)
@food.category_id = params[:category_id]

if @food.save
  flash[:success] = "Adding Successful!"
  redirect_to @food
else
  render 'new'
end
end

def food_params
params.require(:food).permit(:name, :price, :category_id, :description, :picture)
end

有人可以帮我解决问题吗?

3 个答案:

答案 0 :(得分:1)

我在您的create方法中看到一个问题。

在@ food.save == false的情况下,你没有建立

@categories = Category.all.map{|c| [ c.name, c.id ] }

之前

render 'new'

很可能你的表单没有获得构建select语句所需的@categories信息。

答案 1 :(得分:1)

您可能在数据库中没有任何类别,更安全的方法是使用collection_select,它应该优雅地处理空集合。

首先是控制器

def new
  @food = Food.new    
  @categories = Category.all
end

然后是视图

collection_select(:food, :category_id, @categories, :id, :name)

另一个问题是,当@categories未保存时,创建操作中的@food缺失,并且在表单构建下拉列表时失败,如果您想简化你可以添加一个准备这个

的方法
def prepare_form_data
  @categories = Category.all
end

def new
  @food = Food.new
  prepare_form_data
end
def create
  @food = Food.new(food_params)
  if @food.save
    # do stuff
  else
    prepare_form_data # prepare the data for the second form
    render :new
  end
end

答案 2 :(得分:0)

执行render 'new'时,它会将实例变量复制到ERB渲染中。在新操作中,您创建一个实例变量@categories = Category.all.map{|c| [ c.name, c.id ] },然后引用它。您需要在create操作中以及else中定义它。最好采用共享方法。

如:

before_action ->{ @categories = Category.all.map { |c| [c.name, c.id] } }, only: %i[new create]

def new
  @food = Food.new
end

def create
  @food = Food.new(food_params)
  @food.category_id = params[:category_id]

  if @food.save
    flash[:success] = 'Adding successful!'
    redirect_to @food
  else
    render 'new'
  end
end