homeASCIIcasts

234: SimpleForm 

(view original Railscast)

Other translations: En Es It

Other formats:

Written by Rafael Carvalho

Há alguns meses, dois episódios falaram sobre a gem Formtastic [assistir, ler]. Ela oferece uma maneira prática de gerar o código para exibir formulários em Rails. Nesse episódio vamos dar uma olhada em uma outra gem chamada SimpleForm. Assim como Formtastic, SimpleForm fornece uma maneira simples de gerar o código dos formulários nas views, se comparado com a maneira padrão do Rails. Se você conhece o Formtastic, então o SimpleForm vai parecer bem familiar, pois eles são realmente muito semelhantes.

A grande pergunta aqui é: dado que as gems são similares, porque você deveria escolher usar SimpleForm em vez de Formtastic? Um motivo é que o SimpleForm é mais leve. Ela é também mais customizável e extensível que o Formtastic. Se você usou o Formtastic e sente que ele se mete no seu caminho, então é bom dar uma olhada no SimpleForm.

Integrando SimpleForm em uma Aplicação

Para demonstrar o SimpleForm, vamos atualizar um formulário escrito usando o código padrão de views do Rails para usar o SimpleForm. A aplicação é um simples comércio eletrônico com um número de produtos, cada qual pertence a uma categora e o formulário que vamos modificar é o formulário de criação de um novo produto. Esse formulário tem diferentes tipos de campos e será um bom exemplo para usar o SimpleForm.

The New Product form.

Para usar o SimpleForm, temos primeiro que adicionar a gem no Gemfile da aplicação.

/Gemfile

gem "simple_form"

E para termos certeza de que está instalada, precisamos executar:

$ bundle install

Agora que a gem está instalada, precisamos executar um generator que adicionará uns poucos arquivos que o SimpleForm precisa dentro da nossa aplicação.

$ rails g simple_form:install
    create  config/initializers/simple_form.rb
    create  config/locales/simple_form.en.yml
    create  lib/templates/erb/scaffold/_form.html.erb

Esses arquivos gerados são usados principalmente para customização e iremos dar uma olhada neles rapidamente. Antes, vamos atualizar o código do nosso formulário de cadastro de produtos que está assim:

/app/view/products/new.html.erb

<%= form_for @product do |f| %>
  <%= f.error_messages %>
  <p>
    <%= f.label :name %>
    <%= f.text_field :name %>
  </p>
  <p>
    <%= f.label :price %>
    <%= f.text_field :price %>
  </p>
  <p>
    <%= f.label :released_on %>
    <%= f.date_select :released_on %>
  </p>
  <p>
    <%= f.label :category_id %>
    <%= f.collection_select :category_id, Category.all, :id, :name %>
  </p>
  <p>
    <%= f.label :rating %>
    <%= f.select :rating, 1..5 %>
  </p>
  <p>
    <%= f.label :discontinued %>
    <%= f.check_box :discontinued %>
  </p>
  <p><%= f.submit %></p>
<% end %>

As duas principais mudanças que precisamos fazer são substituir o form_for pelo simple_form_for e substituir cada par de labels e inputs com um dos métodos do SimpleForm.

/app/view/products/new.html.erb

<%= simple_form_for @product do |f| %>
  <%= f.error_messages %>
  <%= f.input :name %>
  <%= f.input :price %>
  <%= f.input :released_on %>
  <%= f.association :category %>
  <%= f.input :rating %>
  <%= f.input :discontinued %>
  <%= f.button :submit %>
<% end %>

Para a maior parte dos controles no formulário, podemos usar o métodof.input. Um campo onde precisamos usar algo diferente é o category. No formulário original, esse campo usava collection_select para renderizar um menu drop down contendo todas as categorias.

/app/view/products/new.html.erb

<%= f.collection_select :category_id, Category.all, :id, :name %>

Com o SimpleForm, podemos substituir por f.association, que faz a mesma coisa.

Podemos recarregar o formulário e ver como ele está sendo renderizado pelo SimpleForm.

The form rendered with SimpleForm.

O formulário parece um pouco diferente agora pois não tem mais o estilo que tinha anteriormente. Mas é fácil alterar nosso css para adicionar alguns estilos e classes que o SimpleForm usa em seus formulários.

/public/stylesheets/application.css

.simple_form label {
  float: left;
  width: 100px;
  text-align: right;
  margin: 2px 10px;
}

.simple_form div.input {
  margin-bottom: 10px;
}

.simple_form div.boolean, .simple_form input[type='submit'] {
  margin-left: 120px;
}

.simple_form div.boolean label {
  float: none;
  margin: 0;
}

Quando você usar o SimpleForm em sua própria aplicação, vai querer customizar o estilo de acordo com o design da sua aplicação. O CSS acima vai te dar uma ideia de quais os nomes das classes usados nos elementos HTML que o SimpleForm gera. Com o estilo acima aplicado, nosso formulário parece um pouco melhor.

The form now has CSS added.

Personalizando Campos

Para os campos que usamos f.input, o SimpleForm automaticamente detectou cada tipo de coluna, de modo que o campo "Released on" está renderizado como data e "Discontinued" está renderizado com um checkbox, pois ele representa uma coluna boolean. Sendo uma associação, o campo "Category" foi renderizado como um menu drop down com uma opção em branco. Se você quiser customizar esse campo, pode fazer isso adicionando algumas opções. Por exemplo, podemos remover a opção em branco do "Category" adicionando a opção :include_blank.

/app/view/products/new.html.erb

<%= f.association :category, :include_blank => false %>

O formulário original tem uma lista drop down para o campo rating, mas isso agora foi substituído por um campo texto. Podemos restaurar esse drop down usando a opção :collection passando um range pra ela.

/app/view/products/new.html.erb

<%= f.input :rating, :collection => 1..5 %>

Se queremos a lista renderizada como radio buttons, podemos usar a opção :as.

/app/view/products/new.html.erb

<%= f.input :rating, :collection => 1..5, :as => :radio %>

Quando recarregamos o formulário, vemos que a opção em branco não existe mais no menu drop down e que o campo rating foi renderizado como radio buttons.

The rating field is now rendered as a series of radio buttons.

Outra grande característica do SimpleForm é detectar automaticamente os campos obrigatórios. Podemos demonstrar isso fazendo os campos name e price obrigatórios no modelo Product.

/app/models/product.rb

class Product < ActiveRecord::Base
  attr_accessible :name, :price, :released_on, :category_id, 
  :rating, :discontinued
  belongs_to :category  
  validates_presence_of :name, :price
end

Isso é tudo que precisamos fazer. Quando recarregarmos o formulário, vamos ver esses campos marcados com asteríscos e se tentarmos submeter o formulário sem preencher esses campos, vamos ver uma mensagem de erro.

The form showing the required field errors.

Podemos também adicionar um aviso para cada campo. Vamos supor que queremos informar que o preço deve ser dado em libras esterlinas. Só precisamos adicionar uma opção :hint a esse campo.

/apps/views/products/_form.html.erb

<%= f.input :price, :hint => "prices should be in UKP." %>

Isso adicionará uma mensagem informativa depois do campo no formulário.

The Price field now has a hint.

Há mais informações sobre as opções que podem ser usadas no README do SimpleForm. Vale a pena dar uma olhada no README do Formtastic também, pois muitas opções que ele usa também podem ser usadas pelo SimpleForm.

Personalizando o SimpleForm

Quando executamos o gerador do SimpleForm, ele criou três arquivos.

$ rails g simple_form:install
    create  config/initializers/simple_form.rb
    create  config/locales/simple_form.en.yml
    create  lib/templates/erb/scaffold/_form.html.erb

Se quisermos customizar o SimpleForm em toda a aplicação, podemos modificar esses arquivos. O primeiro contém algumas opções comentadas e muitas configurações podem ser feitas aqui. Por exemplo, podemos alterar a ordem que cada campo é renderizado; podemos alterar a tag html que envolve cada campo e podemos alterar o tamanho padrão de cada campo de texto. Queremos campos de texto mais estreitos na nossa aplicação, então vamos alterar o valor padrão de 50 para 30.

/config/initializers/simple_form.rb

# Use this setup block to configure all options available in SimpleForm.
SimpleForm.setup do |config|

  # Other options removed...

  # Default size for text inputs.
  config.default_input_size = 30
end

Outro arquivo que foi gerado, foi de idiomas e é onde podemos internacionalizar os formulários.

/config/locales/simple_form.en.yml

en:
  simple_form:
    "yes": 'Yes'
    "no": 'No'
    required:
      text: 'required'
      mark: '*'
      # You can uncomment the line below if you need to overwrite the whole required html.
      # When using html, text and mark won't be used.
      # html: '*'
    error_notification:
      default_message: "Some errors were found, please take a look:"
    # Labels and hints examples
    # labels:
    #   password: 'Password'
    #   user:
    #     new:
    #       email: 'E-mail para efetuar o sign in.'
    #     edit:
    #       email: 'E-mail.'
    # hints:
    #   username: 'User name to sign in.'
    #   password: 'No special characters, please.'

Mesmo se a aplicação não precisa mostrar múltiplos idiomas esse arquivo ainda é útil para alterar alguns textos do SimpleForm, como o texto que é apresentado nos campos obrigatórios.

O último arquivo gerado sobrescreve o partial de formulários do gerador do scaffold.

/lib/templates/erb/scaffold/_form.html.erb

<%%= simple_form_for(@<%= singular_name %>) do |f| %>
  <%% if @<%= singular_name %>.errors.any? %>
    <div id="error_explanation">
      <h2><%%= pluralize(@<%= singular_name %>.errors.count, "error") %> prohibited this <%= singular_name %> from being saved:</h2>

      <ul>
      <%% @<%= singular_name %>.errors.full_messages.each do |msg| %>
        <li><%%= msg %></li>
      <%% end %>
      </ul>
    </div>
  <%% end %>

  <div class="inputs">
  <%- attributes.each do |attribute| -%>
    <%%= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> %>
  <%- end -%>
  </div>

  <div class="actions">
    <%%= f.button :submit %>
  </div>
<%% end %>

No Rails 3, podemos sobrescrever qualquer arquivo template de um generator adicionando em nossa aplicação. Então se quisermos customizar o jeito que um generator funciona, para atender a nossa forma de trabalho, podemos simplesmente criar um novo arquivo template.

Por esse episódio é só. O SimpleForm torna fácil criar formulários em suas aplicações Rails e vale muito a pena dar uma olhada nele.