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@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>


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow