📜 ⬆️ ⬇️

Easy layout in forced places: helpers, decorators, form elements

Many already know that it is not recommended to use logic in views, and in general any data manipulations. To do this, a similar code is carried into decorators , custom form elements , components, and just helpers in the end.

Indeed, with this approach, view files begin to look better. But custom form elements and helpers are simply unbearable.

But there is a simple and elegant way to make them cleaner and easier ...
')


For example, take a custom form element PriceRangeInput .

 class PriceRangeInput < SimpleForm::Inputs::Base def input output = template.content_tag(:div, class: 'j-price-slider') do div = '' div << template.content_tag(:div, class: 'row') do row = "" row << template.content_tag(:span, class: 'span3') do @builder.input(:min_total_price, label: false, input_html: { class: 'input-small j-min-total-price'}) end row << template.content_tag(:span, class: 'span3') do @builder.input(:max_total_price, label: false, input_html: { class: 'input-small j-max-total-price'}) end row.html_safe end div << template.content_tag(:div, class: 'row') do template.content_tag(:span, class: 'span6') do template.content_tag(:div, class: 'j-slider', :data => :slider_data) do end end end div.html_safe end output.html_safe end end 

This element is easy to call from the form:

 = simple_form_for current_search_form, :url => :search, :method => "get" do |f| = f.input :price_range, :label => false, :as => :price_range 

but by simplifying the form itself, the custom element became difficult to understand. Its structure is easily confused.

There is an exit


The solution is to use Arbre - Ruby Object Oriented HTML Views.

It allows you to easily use the layout in the code, as well as create reusable components. Arbre was born in the acive_admin project and is, in fact, its foundation.

Closer to the point


Let's start by adding a helper to the base class of form elements. This is one of the rare examples of the relevant monkey patch.

 class SimpleForm::Inputs::Base private def arbre assigns={}, &block Arbre::Context.new assigns.reverse_merge(:builder=>@builder), template, &block end end 

Now we can fix the form element:

  def input arbre slider_data: slider_data do div class: 'j-price-slider' do div class: 'row' do span class: 'span3' do builder.input :min_total_price, label: false, input_html: { class: 'input-small j-min-total-price'} end span class: 'span3' do builder.input :max_total_price, label: false, input_html: { class: 'input-small j-max-total-price'} end end div class: 'row' do span class: 'span6' do div class: 'j-slider', data: slider_data end end end end end 

Removed all unnecessary, left only what is really needed. The code looks nicer and clearer.

Advantages of Arbre


And so let's summarize a brief summary.

1. Usage
Arbre
allows you to get rid of the buffer for storing the generated tags:

 #  buffer = '' buffer << template.content_tag(:div, class: 'row') do ... buffer << template.content_tag(:div, class: 'row') do buffer.html_safe #  div class: 'row' do ... div class: 'row' do ... 

2. It eliminates the need to use the garbage content_tag in the code and gives us the opportunity to directly indicate the necessary tag:

 #  template.content_tag(:div, class: 'row') #  div class: 'row' 

3. And the most interesting - the components.

Own components


The amazing thing is that Arbre makes it easy to add your own elements and use them in any context.

 class Row < Arbre::Component builder_method :row def build(title, attributes = {}) super(attributes.merge class: 'row') end end 


Immediately after the announcement, the component is ready for use anywhere in the arbre context. Now instead of:

 template.content_tag(:div, class: 'row') do ... 

can write

 row do ... 

and at the output we get the code:

  <div class="row"> ... 

In general, arbre helps to make the inevitable - layout in the code more enjoyable. Recommend.

Source: https://habr.com/ru/post/184528/


All Articles