通过验证同时创建两个模型

时间:2014-04-10 07:56:22

标签: ruby-on-rails

我有一个聚餐,我的朋友们过来了,他们将带来一件或多件食品。我有一个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不唯一,错误会正确报告给表单视图?

3 个答案:

答案 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

例外情况下,这不会创建好友,而是会显示错误消息