Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save tinogomes/3690cee1092187afbd86e7552100d910 to your computer and use it in GitHub Desktop.
Save tinogomes/3690cee1092187afbd86e7552100d910 to your computer and use it in GitHub Desktop.
Helpers, Decorators e Presenters

Helpers, Decorators e Presenters

O que são os Helpers no Rails?

O Helper no Rails fica localizado em app/helpers e é nada mais que um módulo auto-injetado no contexto da view, ou seja, os métodos implementados neste módulo Helper estarão disponíveis no contexto da view. Até a versão 3 do Rails, os Helpers eram aplicados considerando o controller que está em uso. O que isso significa, o helper app/helpers/carts_helper.rb seria aplicado apenas nas views referentes ao controller app/controllers/carts_controller.rb. Para criar um Helper que fosse comum entre controllers, o mesmo era criado como ApplicationHelper (app/helpers/application_helper.rb). A partir do Rails 4, todos os Helpers são aplicados para todos os controllers.

Exemplo:

#!Ruby
# app/helpers/resource_helper.rb
module ApplicationHelper
  def say_hello(user)
    name = content_tag :span, user&.name || "Guest"

    "Hello #{name}"
  end
end

# app/views/layouts/application.html.erb
...
<% @current_user = OpenStruct.new(name: "Tino") %>
<%= say_hello @current_user %>

Results:
Hello <span>Tino</span>

<%= say_hello nil %>

Results:
Hello <span>Guest</span>

Por conta que o Helper é injetado no contexto da view, seus métodos podem acessar as variáveis/métodos que também estão disponíveis na view, como no exemplo acima, que está acessando o helper content_tag. Porém, esse tipo de acesso deve ser evitado ao máximo, por conta de tornar o método dependente do contexto externo. Uma boa prática é, sempre que possível, fazer a passagem dos parametros necessário para execução do método. No exemplo acima, @current_user poderia ser acessado diretamente no método say_hello.

O que são Decorators?

Decorator é um pattern que aumenta um objeto com novas propriedades, que nem sempre fazem sentido existir diretamente na classe desse objeto.

Exemplo:

#!Ruby
require 'active_model'

class Product
  include ActiveModel::Model
  attr_accessor :name, :price

  def free_shipping?
    price.to_f > 1000.0
  end
end

class Tax < SimpleDelegator
  def initialize(product)
    @product = product
    __setobj__ product
  end

  def price
    @product.price * (1 + rate)
  end

  def rate
    raise "should be implemented"
  end
end

class IPI < Tax
  def rate
    0.05
  end
end

class ICMS < Tax
  def rate
    0.12
  end
end

@product = Product.new name: "Carrinho de mão", price: 2100.40

puts @product.name # => "Carrinho de mão"
puts @product.price # => 2100.40

@product = ICMS.new(IPI.new(@product))

puts @product.name # => "Carrinho de mão"
puts @product.price # => 2423.02

O que são Presenters?

Um presenter é essencialmente um Decorator. O conceito foi introduzido pelo Jay Fields e é mais voltado à exibição das informações (embora, no exemplo original ele usa como um modo de simplificar os objetos de um formulário).

A idéia principal do Presenter é aplicar lógicas e formatações, facilitando o uso da visualização do objeto "decorado" na camada de apresentação (view)

Exemplo (considerando já a existência da classe Product acima)

#!Ruby
class ProductPresenter < SimpleDelegator
  def initialize(product)
    @product = product
    __setobj__ product
  end

  def price
    helpers.number_to_currency(product.price)
  end

  def shipping_method_partial
    product.free_shipping? ? "free_shipping" : "shipping_method_selector"
  end

  private

  attr_reader :product

  def helpers
    ApplicationController.helpers
  end
end

@product = ProductPresenter.new(product)

puts @product.name  # => "Carrinho de mão"
puts @product.price # => "$2,423.02"
#!ERB
<%# Então na view, podemos usar apenas: %>
<%= @product.price %>

<%# Em vez de poluir a view com algo como: %>
<%= number_to_currency @product.price %>

<%= render partial: @product.shipping_method_partial, product: @product %>

Quando usar Helper ou Presenter?

A primeira coisa que você precisa detectar é que tipo de lógica é possível extrair de sua view. Algumas coisas mais genéricas fazem mais sentido serem extraídas como helpers (como exemplo os FormHelpers do Rails). Outras, como ifs para determinar qual partial deve ser renderizada provavelmente devem ser movidas para seu presenter.

Fontes:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment