我有一个聚餐,我的朋友们过来了,他们将带来一件或多件食品。我有一个friend
模型,每个friend
has_many food_item
。但是,我不希望任何两个朋友带来相同的food_item
,因此food_item
必须具有唯一的验证。此外,我不希望friend
来(被创建),除非他们带来food_item
。
我认为进行所有这一切的最佳位置将在friend
模型中。看起来像这样:
has_many :food_items
before_create :make_food_item
def make_food_item
params = { "food_item" => food_item }
self.food_items.create(params)
end
我在food_item
模型中唯一的配置是:
belongs_to :friend
validates_uniqueness_of :food_item
我预见到很多这方面的问题,但是rails告诉我以下错误:You cannot call create unless the parent is saved
那么如何在检查验证的同时创建两个模型,这样如果food_item
不唯一,错误会正确报告给表单视图?
答案 0 :(得分:1)
如何使用nested_attributes_for
?
class Friend < ActiveRecord::Base
has_many :food_items
validates :food_items, :presence => true
accepts_nested_attributes_for :food_items, allow_destroy: true
end
答案 1 :(得分:0)
您收到错误是因为您还没有创建好友模型,因为您已经在before_create回调中。由于尚未创建Friend模型,因此您无法创建关联的FoodItem模型。这就是为什么你会收到错误的原因。
以下是您可以采取哪些措施来实现目标:
1)使用after_create回拨(我不建议这样做,因为你无法将params传递给回调)
您可以使用after_create回调代替before_create。以下是您可以做的一个示例:
class Friend
after_create :make_food_item
def make_food_item
food_params = # callbacks can't really take parameters so you shouldn't really do this
food = FoodItem.create food_params
if food.valid?
food_items << food
else
destroy
end
end
end
2)在控制器的创建路径中处理逻辑创建(可能是最佳选择)
在您的控制器路线中,对食物项目执行相同的检查,如果它有效(意味着它通过了唯一性测试),则创建好友模型并将两者关联起来。您可以这样做:
def create
friend_params = params['friend']
food_params = params['food']
food = FoodItem.create food_params
if food.valid?
Friend.create(friend_params).food_items << food
end
end
希望有所帮助。
答案 2 :(得分:0)
如上所述,您最好使用accepts_nested_attributes_for
:
accepts_nested_attributes_for :food_items, allow_destroy: true, reject_if: reject_if: proc { |attributes| attributes['foot_item'].blank? }
这将创建一个朋友,除非定义一个,否则不会传递foot_item
。如果你不想创建一个朋友,你应该这样做:
#app/models/food_item.rb
Class FootItem < ActiveRecord::Base
validates :[[attribute]], presence: { message: "Your Friend Needs To Bring Food Items!" }
end
例外情况下,这不会创建好友,而是会显示错误消息