Rails-使用父级范围父级验证嵌套属性的唯一性 [英] Rails - Validate Nested Attributes Uniqueness with scope parent of parent
问题描述
我在Rails中对具有父项的父项的嵌套属性的范围唯一性验证存在问题.
I have a problem with the scoped uniqueness validation in Rails for nested attributes with a parent of parent.
背景
我有3种型号的Rails 4应用程序:
I have a rails 4 application with 3 models :
#app/models/account.rb
class Account < ActiveRecord::Base
has_many :contacts, dependent: :destroy
end
#app/models/contact.rb
class Contact < ActiveRecord::Base
belongs_to :account
has_many :email_addresses, dependent: :destroy, validate: :true, inverse_of: :contact
accepts_nested_attributes_for :email_addresses,allow_destroy: true
validates :email_addresses, presence: true
end
#app/models/email_address.rb
class EmailAddress < ActiveRecord::Base
belongs_to :contact, inverse_of: :email_addresses
validates :label, presence: true
validates :contact, presence: true
validates :email, uniqueness: true, presence: true
validates_email_format_of :email
end
问题
我想确定一个范围,以确保属性:模型EmailAddress 的电子邮件在帐户级别上是唯一的(帐户是联系人"的父级,本身是EmailAddress的父级.)
I want make a scope, so as to make sure the attribute :email of the model EmailAddress is unique at the Account Level (Account is parent of Contact, which is itself parent of EmailAddress).
我在 http://guides.rubyonrails.org/active_record_validations.html 中建议,尝试过:
class EmailAddress < ActiveRecord::Base
belongs_to :contact, inverse_of: :email_addresses
validates :label, presence: true
validates :contact, presence: true
validates :email, presence: true, uniqueness: { scope: :account,
message: "This contact email is already taken" }
validates_email_format_of :email
end
这将引发错误列email_addresses.account不存在" 我该怎么办 ?
This raises the error "column email_addresses.account does not exist" What should I do ?
感谢您的帮助!
推荐答案
下面将介绍一种在性能方面更好的选择.经过测试,效果很好.
A better option in terms of performances is described below. It is tested and works just fine.
为什么?
映射大量电子邮件时,映射电子邮件会消耗大量资源,因此最好直接在数据库中执行作用域.
Mapping emails can consume a lot of ressources when a lot of emails are at stake, so its better to perform the scope directly with the database.
如何?
在EmailAddress模型中兑现account_id并执行之前验证方法.
Cashing the account_id in the EmailAddress model and performing a before validation method.
1)创建迁移:
change_table :email_addresses do |t|
t.references :account, index: true
end
add_index :email_addresses, [:account_id, :email], unique: true
2)迁移
3)更新EmailAddress模型
3) Update the EmailAddress model
#app/models/email_address.rb
class EmailAddress < ActiveRecord::Base
belongs_to :contact, inverse_of: :email_addresses
belongs_to :account
validates :label, presence: true
validates :contact, presence: true
validates_email_format_of :email
validates_uniqueness_of :email, allow_blank: false, scope: :account
before_validation do
self.account = contact.account if contact
end
end
这篇关于Rails-使用父级范围父级验证嵌套属性的唯一性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!