Skip to content

Instantly share code, notes, and snippets.

@danielfriis
Last active April 12, 2024 10:14
Show Gist options
  • Save danielfriis/c755794f8b7179bd61843fe2b330f00c to your computer and use it in GitHub Desktop.
Save danielfriis/c755794f8b7179bd61843fe2b330f00c to your computer and use it in GitHub Desktop.
Table helper for Rails
Table Helper for Rails
<%= table_for @documents do |t| %>
<% t.column "File", ->(c) { c.pdf&.filename&.to_s&.truncate(40) || 'No file' } %>
<% t.column "Status", :status %>
<% t.column "Pages", ->(c) { c.pages.count.to_s } %>
<% t.column "Actions" do |c| %>
<%= link_to "Parse", [:parse, c], data: { turbo_method: :post }, class: "text-indigo-600 hover:text-indigo-500" %>
<%= link_to "Show", c, class: "text-indigo-600 hover:text-indigo-500" %>
<%= link_to "Destroy", c, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" }, class: "text-indigo-600 hover:text-indigo-500" %>
<% end %>
<% end %>
module TableHelper
class TableBuilder
include ActionView::Helpers::TagHelper
include ActionView::Helpers::UrlHelper
def initialize(collection, template)
@collection = collection
@template = template
@columns = []
end
def column(title, data_method = nil, options = {}, &block)
@columns << { title: title, data_method: data_method, options: options, block: block }
end
def render
content_tag :table, class: "min-w-full divide-y divide-gray-300" do
safe_join([header, body], "")
end
end
private
def header
content_tag :thead do
content_tag :tr, class: "text-left" do
safe_join(@columns.map { |col|
content_tag :th, class: "px-4 py-3.5 first:pl-0 text-left last:text-right text-sm font-semibold" do
col[:title]
end
}, "")
end
end
end
def body
content_tag :tbody, class: "divide-y divide-gray-200" do
safe_join(@collection.map { |item|
content_tag :tr do
safe_join(@columns.map { |col|
content_tag :td, class: "whitespace-nowrap py-4 px-4 first:pl-0 last:text-right text-sm" do
render_cell_content(col, item)
end
}, "")
end
}, "")
end
end
def render_cell_content(column, item)
if column[:block]
@template.capture(item, &column[:block])
elsif column[:data_method].is_a?(Proc)
column[:data_method].call(item)
else
item.public_send(column[:data_method])
end
end
end
def table_for(collection, &block)
builder = TableBuilder.new(collection, self)
yield(builder)
builder.render
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment