我是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
有人可以帮我解决问题吗?
答案 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