为避免刚刚描述的问题,请务必遵循Law of Demeter
,也称为Principle of Least Knowledge
。
要遵循得墨忒耳法则,您可以将上面的代码重写如下:
class Address < ActiveRecord::Base
belongs_to :customer
end
class Customer < ActiveRecord::Base
has_one :address
has_many :invoices
def street
address.street
end
def city
address.city
end
def state
address.state
end
end
class Invoice < ActiveRecord::Base
belongs_to :customer
def customer_name
customer.name
end
def customer_street
customer.street
end
def customer_state
customer.state
end
end
您可以将视图代码更改为以下内容:
<%= @invoice.customer_name %>
<%= @invoice.customer_street %>
<%= @invoice.customer_city %>
<%= @invoice.customer_state %>
在上面的代码中,Invoice上的公共接口已经被可以说与发票接口的其余部分无关的方法污染了。这是得墨忒耳法则的一个普遍缺点,它并不是特别针对 Ruby on Rails。
现在,该方法是类级别的delegate
方法。此方法提供了一种快捷方式,用于指示将在您的对象上创建的一个或多个方法实际上是由相关对象提供的。使用此委托方法,您可以像这样重写您的示例:
class Address < ActiveRecord::Base
belongs_to :customer
end
class Customer < ActiveRecord::Base
has_one :address
has_many :invoices
delegate :street, :city, :state, :to => :address
end
class Invoice < ActiveRecord::Base
belongs_to :customer
delegate :name, :street, :city, :state, :to => :customer, :prefix => true
end
在这种情况下,您不必更改视图代码,方法就像以前一样公开:
<%= @invoice.customer_name %>
<%= @invoice.customer_street %>
<%= @invoice.customer_city %>
<%= @invoice.customer_state %>