Pierre P.
Pierre P.

Reputation: 1065

Use helpers to clarify code

I have this sign up form which is quite huge so I'm just showing you a "small" part.

<div class="input-element uk-margin-small-bottom uk-flex">
  <% if @user.errors[:first_name].any? %>
    <div class="uk-inline uk-width-1-2" title="<%= @user.errors[:first_name].first %>" uk-tooltip="pos: left">
      <span class="uk-form-icon" uk-icon="icon: user"></span>
      <%= f.text_field :first_name, placeholder: "First name", class: "uk-input uk-form-danger" %>
    </div>
  <% else %>
    <div class="uk-inline uk-width-1-2">
      <span class="uk-form-icon" uk-icon="icon: user"></span>
      <%= f.text_field :first_name, placeholder: "First name", class: "uk-input" %>
    </div>
  <% end %>
</div>

This is the logic for every single input and the schema is the same:

It leads to a huge amount of HTML / Ruby code for the same common mechanism. I know Rails provide some helpers to ease the code in certain scenario.

Can my issue be resolved with helpers? If it can, how do you reckon I should handle that?

Thanks,

Upvotes: 1

Views: 68

Answers (2)

Gerry
Gerry

Reputation: 10497

I think a partial may be cleaner but you could still use a helper, maybe something like this:

Helper

def my_text_field(errors, element)
  div_options = { class: "uk-inline uk-width-1-2" }
  input_class = "uk-input"

  if errors.any?
    div_options.merge(title: errors.first, "uk-tooltip": "pos: left")
    input_class << " uk-form-danger"
  end

  content_tag(:div, div_options) do
    content_tag(:span, class: "uk-form-icon", "uk-icon": "icon: user") do
      element.text_field :first_name, placeholder: "First name", class: input_class
    end
  end
end

View

<div class="input-element uk-margin-small-bottom uk-flex">
  <%= my_text_field(@user.errors[:first_name], f) %>
</div>

Upvotes: 1

joshua.paling
joshua.paling

Reputation: 13952

I'd say you're probably after a partial not a helper.

I'd make a partial called eg: _form_field.html.erb with contents like:

<div class="input-element uk-margin-small-bottom uk-flex">
  <% 
  if model.errors[:field].any?
    title = model.errors[:field].first
    tooltip = 'pos: left'
    input_extra_class = 'uk-form-danger'
  else
    title = '' 
    tooltip = ''
    input_extra_class = ''
  end
  %>
  <div class="uk-inline uk-width-1-2" title="<%= title %>" uk-tooltip="<%= tooltip %>">
    <span class="uk-form-icon" uk-icon="icon: user"></span>
    <%= f.text_field :field, placeholder: label, class: "uk-input <%= input_extra_class %>" %>
  </div>
</div>

And then call it like:

<%= render 'form_field', model: @users, field: :first_name, label: 'First name' %>

Note that in the partial, I've pulled out the bits that do vary into an if-statement, to avoid duplicating the html markup that doesn't vary. That's optional... you can leave it as you had it if you want. But either way, make a partial where you pass in the model, field, and label as local variables.

Here's the rails doco on partials: http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials

Upvotes: 2

Related Questions