我有一个 Order 对象,它是belongs_to
aBillingAddress
和 a ShippingAddress
。我只想向我的用户显示 ShippingAddress 字段和一个选中的复选框,指示帐单地址与送货地址匹配。如果用户取消选中该框,则会出现 BillingAddress 字段。
我的实现感觉很笨重,而且我的 Order 对象有很多回调。
class Order < ActiveRecord::Base
attr_accessor :bill_to_shipping_address
belongs_to :billing_address, class_name: 'Address'
belongs_to :shipping_address, class_name: 'Address'
accepts_nested_attributes_for :billing_address, :shipping_address
after_initialize :set_billing_to_shipping_address
before_validation :set_billing_address
after_validation :clear_billing_address_errors
# Init the object with option checked
def set_billing_to_shipping_address
self.bill_to_shipping_address ||= '1'
end
# Copy shipping address attrs to billing address
def set_billing_address
self.billing_address = self.shipping_address if bill_to_shipping_address?
end
def bill_to_shipping_address?
bill_to_shipping_address == '1'
end
# If shipping address matches billing, we copy the attrs, and thus duplicate errors too.
# We only need to show the user one set of errors if addresses are the same, so remove them for billing address.
def clear_billing_address_errors
if bill_to_shipping_address?
self.errors.messages.each { |k,v| self.errors.messages.delete(k) if k.to_s.split('.')[0] == 'billing_address' }
end
end
end
我有四个方法和三个注册的回调来满足这个需求。我也在破解错误消息。我在控制器中没有逻辑,形式相对简单。
= form_for @order do |f|
# ...
= f.label :bill_to_shipping_address, class: 'checkbox' do
#{f.check_box :bill_to_shipping_address} Use my shipping address as my billing address.
问题:
- 如何改进我的实施?
- 切换关系会有所帮助吗?-
Order has_one :billing_address
而has_one :shipping_address
不是belongs_to
. 嵌套形式会感觉更自然;在那里,父母创造孩子,而不是相反。
我正在阅读相当多的重构书籍,但我永远无法将它们的示例映射到我自己的对象设计中。我猜我没那么有经验。我正在使用 Rails 4。