我的情况是User has_one :address
和Address belongs_to :user
。
在这些情况下,我需要能够验证地址对象:
用户注册后,他可以选择部分填写地址表单。在这种状态下,我想验证例如validates :phone_number, :postal_code, numericality: true
,但是如果他愿意,用户可以将该字段留空。
当用户进行购买时,他必须填写地址表单。并且所有字段都必须通过validates presence: true
+之前的验证进行验证。
我理解一种方法是将另一个参数附加到表单(即full_validation
),然后添加一个自定义验证方法,该方法将检查此参数,然后完全验证所有属性。
我只是想知道是否有更高效,更简单的方法来实现这一目标。
到目前为止,我只找到了验证某些属性的方法(请参阅this blog post),但我还没有找到有关如何为某些属性调用部分验证过程的建议。
任何帮助/建议将不胜感激:)
答案 0 :(得分:1)
对于您的第一个用例,您可以使用:allow_blank
上的validates
选项允许该字段为空白,即仅在该字段不为空时才验证该字段?
http://guides.rubyonrails.org/active_record_validations.html#allow-blank
对于这两种用例,您可以使用:if
/ :unless
选项告诉Rails何时触发验证。这称为条件验证:
http://guides.rubyonrails.org/active_record_validations.html#conditional-validation
对于Address
,您可以尝试这样的事情:
class Address
belongs_to :user
validates :phone_number, :postal_code, numericality: true, allow_blank: true, if: new_user?
def new_user?
user && user.new_record?
end
end
这为您的第一个用例提供了一个示例。至于第二种情况,您需要在User
上使用条件验证,以确保在购买时存在地址。如何处理这取决于您的情况:您可以在User
上设置一个标记,或者让该标记检查User
的某些方面,例如存在任何给定用户的购买。
class User
has_one :address
has_many :purchases
validates :address, presence: true, if: has_purchases?
def has_purchases?
purchases.exists?
end
end
答案 1 :(得分:1)
#app/models/user.rb
class User < ActiveRecord::Base
has_one :address, inverse_of: :user
end
#app/models/address.rb
class Address < ActiveRecord::Base
belongs_to :user, inverse_of: :address
validates :phone_number, :postal_code, numericality: true, if: ["phone_number.present?", "postal_code.present?"]
validates :x, :y, :z, presence: true, unless: "user.new_record?"
end
-
用户注册后
使用if
确定phone_number
或postal_code
是否存在。
只有在提交的数据中存在数字才会验证它们的数值。 User
是否是新的并不重要。
-
用户进行购买时
要进行购买,我认为必须创建User
(否则他无法购买)。我使用user.new_record?
方法来确定用户是否是新记录。
最终,我和我的@odaata
的答案提到使用conditional evaluation (if
/ unless
)来确定某些属性/凭据是否值得验证。
docs深入探讨了这个问题;我添加了inverse_of
,因为它可以让您访问关联对象(允许您在user.x
中调用Address
)。
如果您提供有关如何管理purchase
流程的更多背景信息,我将能够为其提供更好的条件逻辑。