Rails 3:当相关模型的验证失败时,如何强制模型的验证失败?

时间:2010-12-18 10:39:11

标签: ruby-on-rails validation ruby-on-rails-3

我有以下两种模式:

class Product < ActiveRecord::Base
  belongs_to :shop      
  validates_numericality_of :price, :greater_than_or_equal_to => 0
end

class Shop < ActiveRecord::Base
  has_many :products
  validates_presence_of :name
end

以下是create的{​​{1}}方法:

ProductsController

当用户添加新产品时,他有一个选择框来选择商店。此选择框中的最后一个选项允许用户添加新商店(显示另一个输入文本字段)。最后一个选项的def create if params[:product][:shop_id] == "new_shop" @shop = Shop.find_by_name(params[:new_shop]) || Shop.create(:name => params[:new_shop]) # Is there a simpler method to do this ? params[:product][:shop_id] = @shop.id end @product = Product.new(params[:product]) if @product.save redirect_to(:action => 'index') else render('new') end end value

如果新输入的商店的验证失败,我希望产品的验证失败并显示适当的错误(目前只有在产品本身的验证失败时才会显示错误。)

实现这一目标的最“Rails 3方法”是什么?

2 个答案:

答案 0 :(得分:4)

我认为如果你使用accepts_nested_attributes_for会更简单。所以对你的Product模型添加:

accepts_nested_attributes_for :shop

然后在视图中,根据您的选择列表值,您可以修改表单(以js为单位),因此商店将有shop_id字段或整套文件:

<% f.fields_for :shop do |sf| %>
  ...
<% end %>

然后,如果用户选择现有商店,它只会传递shop_id,但如果用户选择新商店,那么表单也会传递新的关联对象。 如果您希望商店名称是唯一的,则只需将validates_uniqueness_of添加到Shop型号。

如果商店验证失败,则不会保存产品。基本上,你的控制器保持尽可能简单(只需从params创建新的产品对象 - 你不关心在那里购物)。

答案 1 :(得分:2)

我同意@klew,你应该使用accepts_nested_attributes_for

但是,对您的问题的简单直接回答是使用validates_associated

此外,更好的方式:

@shop = Shop.find_by_name(params[:new_shop]) || Shop.create(:name => params[:new_shop])

将是:

@shop = Shop.find_or_create_by_name(params[:new_shop])
相关问题