防止对特定操作进行活动记录关联验证的最佳方法



我有 2 个模型:UserPurchase。购买属于用户。

class User < ApplicationRecord
has_many :purchases
end

class Purchase < ApplicationRecord
belongs_to :user
enum status: %i[succeeded pending failed refunded]
end

在 Rails 5.2 中,当对没有关联UserPurchase进行任何修改时,会引发验证错误。这适用于新购买,但当只是尝试使用数据库中不再存在的用户保存现有购买的数据时,也会引发错误。

例如:

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 的名称。这些不应与ifunless关键字混淆 - 它们只是关键字参数。

belongs_tooptional:选项实际上只是添加一个没有选项的validates_presence_of验证。作为速记很好,但并不是那么灵活。

相关内容

  • 没有找到相关文章

最新更新