Episodes

Resources

Download Source Code

Summary

# app/helpers/application_helper.rb
module ApplicationHelper
  def easy_table_for(objects, &block)
    table = EasyTable::Base.build(objects) do |table|
      yield table
    end
    table
  end
end

# app/presenters/easy_table/base.rb
module EasyTable
  class Base
    include ActionView::Helpers::TextHelper
    include ActionView::Helpers::TagHelper
    include ActionView::Context

    def self.build(objects, &block)
      raise unless block_given?

      EasyTable::Base.new(objects).build(&block)
    end

    def initialize(objects)
      @objects = objects
    end

    def build(&block)
      content_tag(:table, class: 'table') do
        instance_eval(&block)
      end
    end

    def head(&block)
      concat(content_tag(:thead) do
        concat(content_tag(:tr) do
          instance_eval(&block)
        end)
      end)
    end

    def body(&block)
      concat(content_tag(:tbody) do
        @objects.each do |object|
          @object = object
          concat(content_tag(:tr) do
            instance_eval(&block)
          end)
        end
      end)
    end

    def heading(value)
      concat(content_tag(:th, value))
    end

    def column(field)
      # object - user
      # field - first_name
      # @object.send(field) - user.first_name
      concat(content_tag(:td, @object.send(field)))
    end
    
    def association_column(association, field)
      concat(content_tag(:td) do
        @object.send(association).each do |assocation_record|
          concat(content_tag(:p, assocation_record.send(field)))
        end
      end)
    end

    def presenter_column(presenter, field, through: nil)
      concat(content_tag(:td) do
        case through
        when nil
          concat(content_tag(:p, presenter.new(@object).send(field)))
        else
          @object.send(through).each do |assocation|
            concat(content_tag(:p, presenter.new(assocation).send(field)))
          end
        end
      end)
    end
  end
end

# views/with_dsl/index.html.erb
<%= easy_table_for @users do |t| %>
  <% t.head do %>
    <% t.heading 'First Name' %>
    <% t.heading 'Last Name' %>
    <% t.heading 'Email' %>
    <% t.heading 'Birthday' %>
    <% t.heading 'Addresses' %>
    <% t.heading 'Addresses' %>
  <% end %>
  <% t.body do %>
    <% t.column :first_name %>
    <% t.column :last_name %>
    <% t.column :email %>
    <% t.column :birthday %>
    <% t.association_column :addresses, :street %>
    <% t.presenter_column AddressPresenter, :address, through: :addresses %>
  <% end %>
<% end %>