Skip to content

Instantly share code, notes, and snippets.

@sebastianvirlan
Last active April 30, 2018 14:40
Show Gist options
  • Save sebastianvirlan/16f49bfed840c59555f0f2756dda4cc8 to your computer and use it in GitHub Desktop.
Save sebastianvirlan/16f49bfed840c59555f0f2756dda4cc8 to your computer and use it in GitHub Desktop.
Ruby on Rails - Get rid of conditionals on your view
# Imagining a case where you are using loads of conditionals to show different parts of UI.
# There are 2 solutions of what can I see at the moment, either you are creating a different
# view either you fill your view with conditionals.
# index.html.erb - This would be the example where you fill your view with loads of conditionals
<div>
<% if can? :delete, :users %>
<button id="delete_selected">Delete selected</button>
<% end %>
</div>
<table>
<colgroup>
<% if can? :delete, :users %>
<col style="width:10%;">
<% end %>
<col style="width:70%;">
<col style="width:20%;">
</colgroup>
<tr>
<% if can? :delete, User %>
<th>
<a id="select_all_toggle">Select All</a>
</th>
<% end %>
<th>Name</th>
<th>Actions</th>
</tr>
<% @users.each do |user| %>
<tr>
<% if can? :delete, :users %>
<td>
<%= check_box_tag "delete_user_#{user.id}", user.id, false %>
</td>
<% end %>
<td><%= user.name %></td>
<td>
<div class="btn-group">
<%= link_to 'View Details', user_path(user) %>
</div>
</td>
</tr>
<% end %>
</table>
# The provided solution means to extract the conditional dom elements in a separate file:
<% if can? :delete, User %>
<% define_dom_element :delete_selected_btn do %>
<button id="delete_selected">Delete selected</button>
<% end %>
<% define_dom_element :delete_checkbox_col do %>
<col style="width:10%;">
<% end %>
<% define_dom_element :select_all_th do %>
<th><a id="select_all_toggle">Select All</a></th>
<% end %>
<% users_ids.each do |user_id| %>
<% define_dom_element "checkbox_#{user_id}" do %>
<td>
<%= check_box_tag "delete_user_#{user_id}", user_id, false %>
</td>
<% end %>
<% end %>
<% end %>
# And in the main view just retrieve the elements
<% render 'users/delete_multiple_ui_elements', users_ids: @users.pluck(:id) %>
<div><%= retrieve_dom_element(:delete_selected_btn) %></div>
<table>
<colgroup>
<%= retrieve_dom_element(:delete_checkbox_col) %>
<col style="width:70%;">
<col style="width:20%;">
</colgroup>
<tr>
<%= retrieve_dom_element(:select_all_th) %>
<th>Name</th>
<th>Actions</th>
</tr>
<% @users.each do |user| %>
<tr>
<%= retrieve_dom_element("checkbox_#{user.id}") %>
<td><%= user.name %></td>
<td>
<div class="btn-group">
<%= link_to 'View Details', user_path(user) %>
</div>
</td>
</tr>
<% end %>
</table>
# These are the helpers you need to define and register the dom elements
module ApplicationHelper
def define_dom_element(element)
@view_flow.set(element.to_sym, capture(yield) { yield })
end
def retrieve_dom_element(element)
@view_flow.get(element.to_sym)
end
end
# The approach is similar with the content_for method.
# This code is not tested as I just picked elements and pasted here.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment