事情是这样的。假设我有一个用户模型、订单模型和地址模型。
class User < ActiveRecord::Base
belongs_to :address, :foreign_key => :address_id, :class_name => "Address"
end
class Order < ActiveRecord::Base
belongs_to :address, :foreign_key => :address_id, :class_name => "Address"
end
class Address < ActiveRecord::Base
attr_accessible :email, :address
end
现在在用户模型上,我想仅验证地址模型的电子邮件字段。
但在订单模型上,我只想验证地址模型的地址字段。
我已经尝试过这个:
class User < ActiveRecord::Base
belongs_to :address, :foreign_key => :address_id, :class_name => "Address"
validate :address_fields
def address_fields
self.address.errors.add 'email' unless self.address.email.present?
end
end
它确实可以在控制台中工作,但简单表单看不到错误并且不会显示它。
有什么正确的想法吗?
最佳答案
听起来你已经很接近了,但是根据你想要做什么,有一些微妙之处。
通常,Rails 是为以模型为中心的验证而设置的 - 也就是说,模型要么有效,要么无效。 Rails 期望您的验证出现在您正在验证的模型上,并提供 validates_associated
validator来帮助解决这个问题。下面是一个示例,我在 Address
上设置了一些规则,并告诉 User
和 Order
模型在保存时验证它们。
class User < ActiveRecord::Base
belongs_to :address
validates_associated :address
end
class Order < ActiveRecord::Base
belongs_to :address
validates_associated :address
end
class Address < ActiveRecord::Base
has_many :users
has_many :orders
attr_accessible :email, :address
# This isn't a good regex for validating email addresses, it's just an example
validates :email, format: { with: /^[A-z0-9]+@[A-z0-9.]+.[A-z]$/ }
validates :address, presence: true
end
您还可以有conditional validations ,在验证中使用 :if
和 :unless
选项。例如,如果您只想在美国地址
上需要电话号码,则可以使用以下内容:
validates :phone_number, presence: true, if: :us_address?
def us_address?
country == "United States"
end
如果您的地址
可以有许多用户(例如,可能有多个人向一个公司地址订购)并且可以有许多订单(因为客户可以多次订购),则很难在遵守您要求的规则的 Address
模型上编写条件验证。我想到了几个替代方案:
- 将电子邮件存储在
User
模型上。你无法向建筑物发送电子邮件,因此这更有意义。如果您想对用户的电子邮件地址进行快照,以便可以重现发票,则可以在您的订单
中添加一个confirmation_sent_to_email
字段。 - 有两个独立的模型,一个
OrderAddress
和一个UserAddress
。它们可以有不同的验证规则,并且在您的应用程序中您正在处理的类型会变得更加清晰。您仍然可以拥有一个仅保存地址详细信息的Address
模型,并将其与适当的OrderAddress
和UserAddress
模型相关联。
关于ruby-on-rails - rails : validate fields on association,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25591712/