Slide 1

Slide 1 text

Apéro Ruby Lille - Avril 2017 1 / 41

Slide 2

Slide 2 text

https://bobmaerten.eu 2 / 41

Slide 3

Slide 3 text

https://levups.com/fr/blog 3 / 41

Slide 4

Slide 4 text

4 / 41

Slide 5

Slide 5 text

5 / 41

Slide 6

Slide 6 text

6 / 41

Slide 7

Slide 7 text

7 / 41

Slide 8

Slide 8 text

8 / 41

Slide 9

Slide 9 text

9 / 41

Slide 10

Slide 10 text

10 / 41

Slide 11

Slide 11 text

11 / 41

Slide 12

Slide 12 text

12 / 41

Slide 13

Slide 13 text

13 / 41

Slide 14

Slide 14 text

14 / 41

Slide 15

Slide 15 text

15 / 41

Slide 16

Slide 16 text

16 / 41

Slide 17

Slide 17 text

17 / 41

Slide 18

Slide 18 text

18 / 41

Slide 19

Slide 19 text

19 / 41

Slide 20

Slide 20 text

20 / 41

Slide 21

Slide 21 text

21 / 41

Slide 22

Slide 22 text

22 / 41

Slide 23

Slide 23 text

Et puis c'est gentil tes images mais on veut voir du code ! 23 / 41

Slide 24

Slide 24 text

# model class Article < ApplicationRecord end # decorator class ArticleDecorator < Draper::Decorator delegate_all def published_date object.published_at.strftime("%A, %B %e") end end # controller @article = Article.find(params[:id]).decorate # view = @article.published_date 24 / 41

Slide 25

Slide 25 text

# model class Person attr_reader :first_name, :last_name def initialize(first_name, last_name) @first_name, @last_name = first_name, last_name end end # decorator class PersonDecorator < SimpleDelegator def full_name "#{first_name} #{last_name}" end end # code person = Person.new('Gérard', 'Menvussa') person.first_name #=> 'Gérard' person.last_name #=> 'Menvussa' decorated_person = PersonDecorator.new(person) decorated_person.full_name #=> 'Gérard Menvussa' 25 / 41

Slide 26

Slide 26 text

# app/decorators/application_decorator.rb class ApplicationDecorator < SimpleDelegator attr_reader :view_context alias_method :h, :view_context DEFAULT_VIEW_CONTEXT = ApplicationController.new.view_context def self.each(collection, &block) collection.each { |e| block.call new(e) } end def self.wrap(collection) collection.map { |e| new(e) } end def initialize(model, view_context = nil) super(model) @view_context = view_context || DEFAULT_VIEW_CONTEXT end end 26 / 41

Slide 27

Slide 27 text

attr_reader :view_context view_context est un objet ActionController / ActionMailer contient les informations de la requête (host, controller, action, etc.) permet d'accéder aux helpers (rails helpers, routes helpers, custom helpers, etc.) alias_method :h, :view_context alias pour réduire la largueur du code source La plupart des implémentations de decorators utilisent h en raccourci 27 / 41

Slide 28

Slide 28 text

def self.each(collection, &block) collection.each { |e| block.call new(e) } end def self.wrap(collection) collection.map { |e| new(e) } end
    <% PersonDecorator.each(Person.registered) do |decorated_person| %>
  • <%= decorated_person.full_name %>
  • <% end %>
# controller @decorated_people = PersonDecorator.wrap(Person.registered) # view <%= safe_join @decorated_people.map(&:full_name), tag(:br) %> 28 / 41

Slide 29

Slide 29 text

class PersonDecorator < ApplicationDecorator def register_link h.content_tag(:p) do h.link_to h.register_person_path(person_id: id) do h.fa_icon('chevron‑down', text: 'Enregistrer cette personne') end end end end 29 / 41

Slide 30

Slide 30 text

require "test_helper" class PersonDecoratorTest < ActionView::TestCase setup do view.extend FontAwesome::Rails::IconHelper @person = people(:person_1) @decorated_person = PersonDecorator.new(@decorated_person, view) end test "register_link" do assert_includes @decorated_person.register_link, @person.id assert_includes @decorated_person.register_link, 'Enregister' end end 30 / 41

Slide 31

Slide 31 text

DEFAULT_VIEW_CONTEXT = ApplicationController.new.view_context def initialize(model, view_context = nil) super(model) @view_context = view_context || DEFAULT_VIEW_CONTEXT end Fallback sur un view_context par défaut pour accéder à nos helpers view_context n'était pas défini sur certains tests mailers/controllers class UserDecoratorTest < ActionView::TestCase setup do @person = Person.new('Gérard', 'Menvussa') @decorated_person = PersonDecorator.new @person, view end test "fullname" do assert_includes @decorated_person.fullname, @person.first_name assert_includes @decorated_person.fullname, @person.last_name end end 31 / 41

Slide 32

Slide 32 text

32 / 41

Slide 33

Slide 33 text

33 / 41

Slide 34

Slide 34 text

34 / 41

Slide 35

Slide 35 text

35 / 41

Slide 36

Slide 36 text

36 / 41

Slide 37

Slide 37 text

37 / 41

Slide 38

Slide 38 text

https://bibwild.wordpress.com/2012/12/19/the-simplest-rails-decorator- implementation-that-just-might-work https://hashrocket.com/blog/posts/using-simpledelegator-for-your- decorators https://robots.thoughtbot.com/decorating-activerecord 38 / 41

Slide 39

Slide 39 text

Générique de la série MadMen (AMC) MemeSuper.com GitHub.com 39 / 41

Slide 40

Slide 40 text

40 / 41

Slide 41

Slide 41 text

https://github.com/amatsuda/active_decorator 41 / 41