[英]Best way to prevent ActiveRecord association validations on specific actions
我有 2 个模型: User
和Purchase
。 购买属于用户。
class User < ApplicationRecord
has_many :purchases
end
class Purchase < ApplicationRecord
belongs_to :user
enum status: %i[succeeded pending failed refunded]
end
在 Rails 5.2 中,当对没有关联User
的Purchase
进行任何修改时,会引发验证错误。 这对于新购买非常有用,但是当简单地尝试保存数据库中不再存在的用户的现有购买数据时,它也会引发错误。
例如:
user = User.find(1)
# Fails because no user is passed
purchase = Purchase.create(status: 'succeeded')
# Succeeds
purchase = Purchase.create(user: user, status: 'succeeded')
purchase.status = 'failed'
purchase.save
user.destroy
# Fails because user doesn't exist
purchase.status = 'refunded'
purchase.save
我知道我可以通过在购买模型中将关联与belongs_to :user, optional: true
设为可选来防止第二次更新失败,但这也会取消购买创建的第一次验证。
我也可以为用户关联构建我自己的自定义验证,但我正在寻找一种更传统的 Rails 方式来做到这一点。
您可以使用验证上下文https://guides.rubyonrails.org/active_record_validations.html#on
您可以将关系设为可选,然后仅在创建时添加验证,而不是在更新时添加验证(默认行为是保存时):
belongs_to :user, optional: true
validates :user, presence: true, on: :create
您可以使用if:
和unless:
选项使验证有条件:
class Purchase < ApplicationRecord
belongs_to :user, optional: true # suppress generation of the default validation
validates_presence_of :user, unless: :refunded?
enum status: %i[succeeded pending failed refunded]
end
您可以传递方法或 lambda 的名称。 这些不应该与if
和unless
关键字混淆——它们只是关键字参数。
optional:
belongs_to
选项实际上只是添加了一个没有选项的validates_presence_of
验证。 这是一个很好的速记,但不是那么灵活。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.