【问题标题】:Rails 3 - Association validation in the controller?Rails 3 - 控制器中的关联验证?
【发布时间】:2013-03-14 00:14:48
【问题描述】:
我有一个带有用户模型、信用卡模型和付款模型的 Rails 3 程序。 User has_many CreditCards,CreditCard has_many Payments。
在我的应用程序中,当用户进行新的付款时,他会从他的信用卡列表中选择他想使用哪个信用卡来付款。我想在代码中添加一个额外的验证,以确保提交给 Payment.create() 函数的 credit_card_id 实际上是当前用户拥有的。
感觉验证必须在控制器中进行,对吧?或者是否有处理这种情况的最佳做法?
【问题讨论】:
标签:
ruby-on-rails
ruby-on-rails-3
associations
【解决方案1】:
添加付款验证。付款很可能通过belongs_to 与用户相关联,因此我建议添加以下验证
# payment.rb
belongs_to :user
validate :validates_credit_card_belongs_to_user
private
def validates_credit_card_belongs_to_user
unless user.credit_card.where(id: credit_card_id).exists?
errors.add(:credit_card_id, 'is not owned by this user')
end
end
【解决方案2】:
您肯定希望在您的模型中进行此验证。保留controllers skinny 并拥有胖模型通常被认为是 Rails 最佳实践。
假设付款属于用户并且付款属于信用卡(我假设这是因为您的付款上有一个 credit_card_id 字段)您可以这样做。
Class Payment < ActiveRecord::Base
belongs_to :user
belongs_to :credit_card
validate :credit_card_belongs_to_user
def credit_card_belongs_to_user
errors.add(:credit_card, 'does not belong to you') unless user == credit_card.user
end
end
【解决方案3】:
您还可以在 PaymentsController 中 [在前置过滤器中] 获取这样的信用卡
@credit_card = current_user.credit_cards.find(params[:credit_card_id])
然后
@payment = @credit_card.payments.build(params[:payment])
这样您就可以确定它是 current_user 拥有的 credit_card。