0

Short of extracting shipping and billing addresses into an Address model, how can I remove this validation duplication?

I only want to validate the billing address if it's not the same as the shipping address. How would I go about extracting it into a module? An example would be really helpful as I never know what to include in modules, or self refers to.

  validates :shipping_name, :shipping_address1, :shipping_street_number, :shipping_city, presence: true
  validates :shipping_state, inclusion: { in: Address.states.values }
  validates :shipping_post_code, length: { is: 5 }, numericality: { only_integer: true }

  validates :billing_name, :billing_address1, :billing_street_number, :billing_city, presence: true, unless: -> { self.bill_to_shipping_address? }
  validates :billing_state, inclusion: { in: Address.states.values }, unless: -> { self.bill_to_shipping_address? }
  validates :billing_post_code, length: { is: 5 }, numericality: { only_integer: true }, unless: -> { self.bill_to_shipping_address? }
4

1 回答 1

1

您可以创建一个方法,然后传入两种地址之间不同的位。在这种情况下,区别在于字段的前缀词和传递额外选项的能力。

module AddressValidator
  def validates_address(type, options = {})
    validates :"#{type}_name", :"#{type}_address1", :"#{type}_street_number", :"#{type}_city", {presence: true}.merge(options)
    validates :"#{type}_state", {inclusion: { in: Address.states.values }}.merge(options)
    validates :"#{type}_post_code", {length: { is: 5 }, numericality: { only_integer: true }}.merge(options)
  end
end

class MyModel < ActiveRecord::Base
  extend AddressValidator
  validates_address(:shipping)
  validates_address(:billing, unless: -> { self.bill_to_shipping_address? })
end
于 2013-05-15T14:08:33.797 回答