Ruby on Rails
Wzór dekoratora
Szukaj…
Uwagi
Wzorzec Dekoratora pozwala dodawać lub modyfikować zachowanie obiektów w sposób sytuacyjny bez wpływu na obiekt podstawowy.
Można to osiągnąć za pomocą zwykłego Ruby za pomocą stdlib lub za pomocą popularnych klejnotów, takich jak Draper .
Dekorowanie modelu za pomocą SimpleDelegator
Większość programistów Railsów zaczyna od modyfikacji informacji o swoim modelu w samym szablonie:
<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>
W przypadku modeli z dużą ilością danych może to szybko stać się kłopotliwe i prowadzić do logiki kopiowania i wklejania z jednego szablonu do drugiego.
W tym przykładzie użyto SimpleDelegator
z stdlib.
Wszystkie żądania do obiektu SimpleDelegator
są domyślnie przekazywane do obiektu nadrzędnego. Możesz zastąpić dowolną metodę z logiką prezentacji lub możesz dodać nowe metody specyficzne dla tego widoku.
SimpleDelegator
udostępnia dwie metody: __setobj__
aby ustawić, do którego obiektu jest delegowany, i __getobj__
aby uzyskać ten obiekt.
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
Niektórzy dekoratorzy polegają na magii w celu uporządkowania tego zachowania, ale można uczynić bardziej oczywistym, skąd bierze się logika prezentacji, inicjując obiekt na stronie.
<% user = UserDecorator.new(@user, self) %>
<h1><%= user.full_name %></h1>
<h3>joined: <%= user.created_at %></h3>
Przesyłając odwołanie do obiektu widoku do dekoratora, nadal możemy uzyskać dostęp do wszystkich pozostałych pomocników widoku podczas budowania logiki prezentacji bez konieczności jej dołączania.
Teraz szablon widoku dotyczy tylko wstawiania danych na stronę i jest o wiele bardziej przejrzysty.
Dekorowanie modelu za pomocą Drapera
Draper automatycznie dopasowuje modele do dekoratorów zgodnie z konwencją.
# 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
Biorąc pod uwagę zmienną @user
zawierającą obiekt ActiveRecord, możesz uzyskać dostęp do dekoratora, wywołując #decorate
na @user
lub określając klasę Draper, jeśli chcesz być konkretny.
<% user = @user.decorate %><!-- OR -->
<% user = UserDecorator.decorate(@user) %>
<h1><%= user.full_name %></h1>
<h3>joined: <%= user.created_at %></h3>