Ruby on Rails
Dekoratormönster
Sök…
Anmärkningar
Decorator-mönstret gör att du kan lägga till eller ändra beteende hos objekt på ett situationellt sätt utan att påverka basobjektet.
Detta kan uppnås genom vanlig Ruby med stdlib eller via populära ädelstenar som Draper .
Dekorera en modell med SimpleDelegator
De flesta Rails-utvecklare börjar med att ändra sin modellinformation i själva mallen:
<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>
För modeller med mycket data kan detta snabbt bli besvärligt och leda till kopieringspapper-logik från en mall till en annan.
Detta exempel använder SimpleDelegator
från stdlib.
Alla förfrågningar till ett SimpleDelegator
objekt skickas som standard till överordnade objekt. Du kan åsidosätta alla metoder med presentationslogik, eller du kan lägga till nya metoder som är specifika för den här vyn.
SimpleDelegator
tillhandahåller två metoder: __setobj__
att ställa in vilket objekt som delegeras till, och __getobj__
att få det objektet.
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
Vissa dekoratörer förlitar sig på magi för att leda upp detta beteende, men du kan göra det mer uppenbart var presentationslogiken kommer från genom att initialisera objektet på sidan.
<% user = UserDecorator.new(@user, self) %>
<h1><%= user.full_name %></h1>
<h3>joined: <%= user.created_at %></h3>
Genom att skicka en referens till visningsobjektet till dekoratören kan vi fortfarande få åtkomst till alla resten av visningshjälparna medan vi bygger presentationslogiken utan att behöva inkludera den.
Nu handlar visningsmallen bara om att infoga data på sidan, och det är mycket tydligare.
Dekorera en modell med Draper
Draper matchar automatiskt modeller med sina dekoratörer enligt konvention.
# 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
Med en @user
variabel som innehåller ett ActiveRecord-objekt kan du komma åt din dekoratör genom att ringa #decorate
på @user
eller genom att ange Draper-klassen om du vill vara specifik.
<% user = @user.decorate %><!-- OR -->
<% user = UserDecorator.decorate(@user) %>
<h1><%= user.full_name %></h1>
<h3>joined: <%= user.created_at %></h3>