我有一個訂單對象,belongs_to
a BillingAddress
和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
我可能會改變驗證,所以它只驗證帳單地址,如果地址不相同,我會使用實際布爾值布爾值 - 這應該是透明地發生。在需要進一步清理之前,我會放棄這一點,但是我傾向於在主要清理工作之前停下來,直到他們證明有必要。 – 2013-05-09 13:16:33
@DaveNewton我試圖使用布爾值,但複選框始終提交'0'和'1',這需要我添加一些邏輯來將其轉換爲布爾值。至於你的建議,我試圖做到這一點,但它被證明比我想象的更難。驗證在「地址」中定義,這意味着它們將始終啓動。我可以在我的'Order'模型中驗證這個關聯的存在,我已經在這樣做了。 – Mohamad 2013-05-09 13:19:22
+ Mohamad,我記得在Rails中'1'to_boolean'或'1.to_boolean'是'true','0'.to_boolean'或'0.to_boolean'是'false'。 – DNNX 2013-05-09 14:58:38