- Keep most logic out of the views, no one wants to go through a view with a 100 if statements.
- Keep it DRY.
The first thing to do is create a partial that will render the tables. This is not included in the gem because this will differ for each application.
Example:
<header><%table.table_actions.eachdo |table_action| %><%=button_totable_action.label,table_action.path%><%end%></header><tableid="<%=table.name%>"><tr><%table.columns.eachdo |column| %><thclass="<%=column.type%>"><%=column.label%></th><%end%><th>-</th></tr><%table.resources.eachdo |resource| %><trid="resource-<%=resource.id%>"><%table.columns.eachdo |column| %><tdclass="<%=column.type%>"><%=link_tocolumn.path_for(resource)do%><%=column.value_for(resource)%><%end%></td><%end%><td><%table.resource_actions.eachdo |resource_action| %><%=link_toresource_action.label,resource_action.path.call(resource)%><%end%></td></tr><%end%></table>create a table object in for example app/table_objects/
classUserTable < TableObject::Baseself.default_path=->(user){url_helper.user_path(user)}column:email,type: :email,path: ->(user){user.email}column:name,value_method: ->(user){"#{user.first_name}#{user.last_name}"}column:birth_datecolumn:log_in_counttable_action:new,label: 'NEW',path: url_helper.new_user_pathresource_action:edit,label: 'EDIT',path: ->(user){url_helper.edit_user_path(user)}resource_action:destroy,label: 'DESTROY',path: ->(user){url_helper.user_path(user)},method: :destroyend.default_path: if table has a default path this will be used for all columns, unless they have a path assigned..model_class: by default this will try to guess the model class based on the table name by removing the "Table" substring. UserTable => User.default_path: this path will be filled in all columns of the table by default. can be overridden by given your column a path..column: Will create a column object for the table..table_action: Will create action object for the table. This are actions that have to do with the table as a whole. New, Export, ....resource_action: Will create action object for the table. this are actions that have to do with the resource. Edit, Show, Destroy- The type on a column, if not given, is filled in by default based on db info. This uses
model_class. #name: by default this is the table class name in snakecase, but can be set.#resources: This is what you pass in the table. this can be collection of users, books, movies,...
#value_for(resource): If a lambda is given forvalue_method, this will be called. If novalue_methodis present it will public_send the column name on the given resource.#path_for(resrouce): Will return the path for the given resource.- custom options: All options are stored
optionshash. You can also call these as if they where attributes. Example:test_column = TableObject::Column.new(:test_column, 'test?' => true); test_column.test? # => true
- This object is used for table_actions and resource_actions.
- Also has custom options like columns
classUsersController < ApplicationControllerdefindexusers=User.all@user_table=UserTable.new(users)endend<%= render 'shared/table', table: @user_table %>If you access attributes from nested relationships you can create N+1 queries. Prevent these by using include or eager_load.
For more info you can read this
defindexusers=User.includes(:address)@user_table=UserTable.new(users)endAdd this line to your application's Gemfile:
gem'table_object'And then execute:
$ bundleOr install it yourself as:
$ gem install table_objectThe gem is available as open source under the terms of the MIT License.