Ruby on Rails
Декоратор
Поиск…
замечания
Шаблон Decorator позволяет добавлять или изменять поведение объектов ситуационным способом, не затрагивая базовый объект.
Это может быть достигнуто, хотя простой Ruby с использованием stdlib, или через популярные драгоценные камни, такие как Draper .
Оформление модели с помощью 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>
Для моделей с большим количеством данных это может быстро стать громоздким и привести к логике копирования вставки из одного шаблона в другой.
В этом примере используется SimpleDelegator
из stdlib.
Все запросы к объекту 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>
Передавая ссылку на объект вида в декоратор, мы все равно можем получить доступ ко всем остальным помощникам вида при построении логики представления без необходимости включать его.
Теперь шаблон просмотра касается только вставки данных на страницу, и это гораздо более понятно.
Украшение модели с помощью Draper
Дрейпер автоматически согласовывает модели с их декораторами.
# app/decorators/user_decorator.rb
class UserDecorator < Draper::Decorator
def full_name
"#{object.first_name} #{object.last_name}"
end
def created_at
Time.use_zone(h.current_user.timezone) do
object.created_at.strftime("%A, %d %b %Y %l:%M %p")
end
end
end
Учитывая переменную @user
содержащую объект ActiveRecord, вы можете получить доступ к своему декоратору, вызвав #decorate
в @user
, или указав класс Draper, если хотите быть конкретным.
<% user = @user.decorate %><!-- OR -->
<% user = UserDecorator.decorate(@user) %>
<h1><%= user.full_name %></h1>
<h3>joined: <%= user.created_at %></h3>