Rails 基于另一个模型的属性更新验证
Rails Validation On Attribute Update Based on Another Model
我有三个相关模型,一个帐户有一个程序和一个配置文件。创建账号时,profile.email可以为nil,只要program.upgraded == 'f'
。但是在将 program.upgraded
设置为 't'.
之前,我该如何以及应该在哪里验证 profile.email 是否已设置,即不是零
所以我尝试创建自定义验证,但我可能没有正确实施。我有一项服务调用
program.update!(
upgraded: 't',
)
在异常救援的事务块内。这是我的验证:
class Account::Program < ApplicationRecord
validate :upgraded, :upgraded_email_present
...
private
def upgraded_email_present
return unless ppc_p == 't' && account.profile.auto_email.blank?
errors[:upgraded] << "profile auto_email must be set"
end
...
end
更新中!语句似乎失败了,它触发了救援,因为事务块中有正确的错误。然而,当我检查模型实例时,它仍然被升级了!完全搞不懂这里出了什么问题。
编辑
终于明白是怎么回事了。我在我的规范的上下文中测试验证并且必须对实例进行重新加载。此解决方案有效。
您可以使用自定义验证器 (Rails docs) 进行更复杂的验证,例如您所追求的。 ActiveModel::EachValidator
实现 .validate_each
,它接受以下参数:
- 正在验证的记录
- 正在验证的属性
- 该属性的当前值
class UpgradeEmailPresentValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
# All good if :upgraded is false or if the profile email is present
return unless value? && record.account.profile.email.blank?
record.errors[attribute] << (options[:message] || "profile email must be set")
end
end
class Program < ApplicationRecord
validates :upgraded, presence: true, upgrade_email_present: true
end
你没有说 Program
是否通过 has_one :through
与 Profile
关联,但如果是,你可以将 record.account.profile
缩短为 record.profile
.
编辑
我在原文中忘记提到您也可以在模型上使用自定义验证方法。
class Program < ApplicationRecord
validate :upgraded, :upgrade_email_present
def upgrade_email_present
return unless upgraded? && account.profile.email.blank?
errors[:upgraded] << "profile email must be set"
end
end
我有三个相关模型,一个帐户有一个程序和一个配置文件。创建账号时,profile.email可以为nil,只要program.upgraded == 'f'
。但是在将 program.upgraded
设置为 't'.
所以我尝试创建自定义验证,但我可能没有正确实施。我有一项服务调用
program.update!(
upgraded: 't',
)
在异常救援的事务块内。这是我的验证:
class Account::Program < ApplicationRecord
validate :upgraded, :upgraded_email_present
...
private
def upgraded_email_present
return unless ppc_p == 't' && account.profile.auto_email.blank?
errors[:upgraded] << "profile auto_email must be set"
end
...
end
更新中!语句似乎失败了,它触发了救援,因为事务块中有正确的错误。然而,当我检查模型实例时,它仍然被升级了!完全搞不懂这里出了什么问题。
编辑
终于明白是怎么回事了。我在我的规范的上下文中测试验证并且必须对实例进行重新加载。此解决方案有效。
您可以使用自定义验证器 (Rails docs) 进行更复杂的验证,例如您所追求的。 ActiveModel::EachValidator
实现 .validate_each
,它接受以下参数:
- 正在验证的记录
- 正在验证的属性
- 该属性的当前值
class UpgradeEmailPresentValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
# All good if :upgraded is false or if the profile email is present
return unless value? && record.account.profile.email.blank?
record.errors[attribute] << (options[:message] || "profile email must be set")
end
end
class Program < ApplicationRecord
validates :upgraded, presence: true, upgrade_email_present: true
end
你没有说 Program
是否通过 has_one :through
与 Profile
关联,但如果是,你可以将 record.account.profile
缩短为 record.profile
.
编辑
我在原文中忘记提到您也可以在模型上使用自定义验证方法。
class Program < ApplicationRecord
validate :upgraded, :upgrade_email_present
def upgrade_email_present
return unless upgraded? && account.profile.email.blank?
errors[:upgraded] << "profile email must be set"
end
end