我在产品和类别之间有一个非常常见的HABTM关系。我基于Railscasts Episode #17。我面临的问题与获取所有类别的方式有关,以便在产品表单中显示它们(这是R. Bates对它的看法):
<% for category in Category.find(:all) %>
<div>
<%= check_box_tag "product[category_ids][]", category.id, @product.categories.include?(category) %>
<%= category.name %>
</div>
<% end %>
但我想以这种方式实现它:
<% for category in @categories %>
我的控制器中定义了@categories
:
def edit
@categories = Categories.all
@product = Product.find params[:id]
end
一切顺利,直到某些验证失败。假设某些字段不能为空,因此重定向(在ProductsController
的更新操作上)将我发回edit
:
def update
@product = Product.find(params[:id])
@supplier.category_ids = params[:product][:industry_category_ids] ||= []
respond_to do |format|
if @product.update_attributes(params[:product])
format.html { redirect_to @supplier, notice: 'Profile was successfully updated.' }
format.json { head :ok }
else
format.html { render action: "edit" } <=== HERE
format.json { render json: @supplier.errors, status: :unprocessable_entity }
end
end
end
这一点我收到以下错误,说明相应表单中的@categories
为nil
:
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
...
<% for ic in @industry_categories %> <==== HERE
...
那么,有没有办法保持MVC最佳实践来实现这一目标?或者我只是要做贝特的方式?
换句话说,有可能form_for
说@product
带有“HABTM”相关对象的复选框,并在验证失败后被重定向到它但不在视图上获取东西( Category.all
)(即在我之前展示的相应控制器@categories = Category.all
上进行)
谢谢!
答案 0 :(得分:2)
验证失败时填充@categories:
def update
@product = Product.find(params[:id])
@supplier.category_ids = params[:product][:industry_category_ids] ||= []
respond_to do |format|
if @product.update_attributes(params[:product])
format.html { redirect_to @supplier, notice: 'Profile was successfully updated.' }
format.json { head :ok }
else
@categories = Categories.all <--- HERE
format.html { render action: "edit" }
format.json { render json: @supplier.errors, status: :unprocessable_entity }
end
end
end
当您调用“render:action”时,Rails只会继续处理当前请求并将视图映射呈现给您指定的:action。因此,在这种情况下,您将重新呈现“编辑”视图(因为您的验证失败),但由于“更新”操作中没有声明@categories变量,因此您将获得零引用异常。