# 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 %>