Ruby on Rails
Motivo decorativo
Ricerca…
Osservazioni
Il pattern Decorator consente di aggiungere o modificare il comportamento degli oggetti in modo situazionale senza influire sull'oggetto di base.
Questo può essere ottenuto attraverso il semplice Ruby usando lo stdlib, o tramite gemme popolari come Draper .
Decorazione di un modello con SimpleDelegator
La maggior parte degli sviluppatori di Rails inizia modificando le informazioni sul modello all'interno del modello stesso:
<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>
Per i modelli con molti dati, questo può diventare rapidamente ingombrante e portare alla logica di copia-incolla da un modello all'altro.
Questo esempio utilizza SimpleDelegator
dallo stdlib.
Tutte le richieste a un oggetto SimpleDelegator
vengono passate all'oggetto padre per impostazione predefinita. È possibile sovrascrivere qualsiasi metodo con la logica di presentazione oppure è possibile aggiungere nuovi metodi specifici per questa vista.
SimpleDelegator
fornisce due metodi: __setobj__
per impostare a quale oggetto viene delegato e __getobj__
per ottenere quell'oggetto.
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
Alcuni decoratori si affidano alla magia per collegare questo comportamento, ma è possibile rendere più ovvio da dove proviene la logica di presentazione inizializzando l'oggetto sulla pagina.
<% user = UserDecorator.new(@user, self) %>
<h1><%= user.full_name %></h1>
<h3>joined: <%= user.created_at %></h3>
Passando un riferimento all'oggetto vista nel decoratore, possiamo ancora accedere a tutti gli altri helper della vista mentre si costruisce la logica di presentazione senza doverlo includere.
Ora il modello di visualizzazione riguarda solo l'inserimento di dati nella pagina ed è molto più chiaro.
Decorare un modello usando Draper
Draper abbina automaticamente i modelli con i loro decoratori per convenzione.
# 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
Data una variabile @user
che contiene un oggetto ActiveRecord, puoi accedere al decoratore chiamando #decorate
su @user
o specificando la classe Draper se vuoi essere specifico.
<% user = @user.decorate %><!-- OR -->
<% user = UserDecorator.decorate(@user) %>
<h1><%= user.full_name %></h1>
<h3>joined: <%= user.created_at %></h3>