验证失败后,如何在表单上获取HABTM相关对象?

时间:2011-08-04 17:57:27

标签: ruby-on-rails validation redirect rendering has-and-belongs-to-many

我在产品和类别之间有一个非常常见的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

这一点我收到以下错误,说明相应表单中的@categoriesnil

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上进行)

谢谢!

1 个答案:

答案 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变量,因此您将获得零引用异常。