使用 SimpleDelegator 装饰模型
大多数 Rails 开发人员首先在模板中修改他们的模型信息:
<h1><%= "#{ @user.first_name } #{ @user.last_name }" %></h1>
<h3>joined: <%= @user.created_at.in_time_zone(current_user.timezone).strftime("%A, %d %b %Y %l:%M %p") %></h3>
对于具有大量数据的模型,这可能很快变得麻烦并导致从一个模板到另一个模板的复制粘贴逻辑。
此示例使用 stdlib 中的 SimpleDelegator
。
默认情况下,对 SimpleDelegator
对象的所有请求都将传递给父对象。你可以使用表示逻辑覆盖任何方法,也可以添加特定于此视图的新方法。
SimpleDelegator
提供了两种方法:__setobj__
用于设置要委托的对象,__getobj__
用于获取该对象。
class UserDecorator < SimpleDelegator
attr_reader :view
def initialize(user, view)
__setobj__ @user
@view = view
end
# new methods can call methods on the parent implicitly
def full_name
"#{ first_name } #{ last_name }"
end
# however, if you're overriding an existing method you need
# to use __getobj__
def created_at
Time.use_zone(view.current_user.timezone) do
__getobj__.created_at.strftime("%A, %d %b %Y %l:%M %p")
end
end
end
一些装饰器依靠魔术来连接这种行为,但是你可以通过初始化页面上的对象使表达逻辑的来源变得更加明显。
<% user = UserDecorator.new(@user, self) %>
<h1><%= user.full_name %></h1>
<h3>joined: <%= user.created_at %></h3>
通过将对视图对象的引用传递给装饰器,我们仍然可以在构建表示逻辑时访问所有其余视图助手,而无需包含它。
现在,视图模板只关注将数据插入页面,而且更加清晰。