Formtastic
O formtastic é uma gem mantida pelo Justin French que pode ser considerado com um conjuto de helper que utilizam semântica HTML e facilita a criação de formulários em projetos Rails.
A instalação é bem simples, basta adicionar a linha abaixo no arquivo environment.rb.
config.gem 'formtastic'então instalar as dependências com o rake do rails.
rake gems:install
script/generate formtasticPra montar um scaffold completo do seu modelo você pode usar os helpers em suas views:
<% semantic_form_for @user do |f| %> <%= f.inputs %> <%= f.buttons %> <% end %>
No brwoser vai mostrar um html igual a este.
<form action="/admin/users" class="formtastic user" id="new_user" method="post"> <div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="P0Wk/UO8rwgkhuhkEkz7sF1raZ9Xi/fvAx+Bhc/N3ko=" /></div> <fieldset class="inputs"> <ol> <li class="string required" id="user_name_input"> <label for="user_name">Nome<abbr title="required">*</abbr></label> <input id="user_name" maxlength="255" name="user[name]" size="50" type="text" /> </li> <li class="string required" id="user_email_input"> <label for="user_email">Email<abbr title="required">*</abbr></label> <input id="user_email" maxlength="255" name="user[email]" size="50" type="text" /> </li> <li class="password required" id="user_password_input"> <label for="user_password">Senha<abbr title="required">*</abbr></label> <input id="user_password" name="user[password]" size="50" type="password" /> </li> </ol> </fieldset> <fieldset class="buttons"> <ol> <li class="commit"> <input class="create" id="user_submit" name="commit" type="submit" value="Create Usuário" /> </li> </ol> </fieldset> </form>
Algumas vezes queremos montar um formulário somente de alguns determinados campos do objeto então você pode especificar este da seguinte forma.
<% semantic_form_for @user do |f| %> <%= f.inputs :email, :password %> <%= f.buttons :commit %> <% end %>
<form action="/admin/users" class="formtastic user" id="new_user" method="post"> <div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="P0Wk/UO8rwgkhuhkEkz7sF1raZ9Xi/fvAx+Bhc/N3ko=" /></div> <fieldset class="inputs"> <ol> <li class="string required" id="user_email_input"> <label for="user_email">Email<abbr title="required">*</abbr></label> <input id="user_email" maxlength="255" name="user[email]" size="50" type="text" /> </li> <li class="password required" id="user_password_input"> <label for="user_password">Senha<abbr title="required">*</abbr></label> <input id="user_password" name="user[password]" size="50" type="password" /> </li> </ol> </fieldset> <fieldset class="buttons"> <ol> <li class="commit"> <input class="create" id="user_submit" name="commit" type="submit" value="Create Usuário" /> </li> </ol> </fieldset> </form>
Caso você queira ainda especificar algo pra cada um dos atributos você pode escrever um input pra cada atributo.
<% semantic_form_for @post do |f| %> <% f.inputs do %> <%= f.input :email %> <%= f.input :password %> <% end %> <% f.buttons :commit %> <% end %>
<form action="/admin/users" class="formtastic user" id="new_user" method="post"> <div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="P0Wk/UO8rwgkhuhkEkz7sF1raZ9Xi/fvAx+Bhc/N3ko=" /></div> <fieldset class="inputs"> <ol> <li class="string required" id="user_name_input"> <label for="user_name">Nome<abbr title="required">*</abbr></label> <input id="user_name" maxlength="255" name="user[name]" size="50" type="text" /> </li> <li class="string required" id="user_email_input"> <label for="user_email">Email<abbr title="required">*</abbr></label> <input id="user_email" maxlength="255" name="user[email]" size="50" type="text" /> </li> </ol> </fieldset> <fieldset class="buttons"> <ol> <li class="commit"> <input class="create" id="user_submit" name="commit" type="submit" value="Create Usuário" /> </li> </ol> </fieldset> </form>
Existem muitos outras opções pra utilizar :as, :collection, :input_html, :button_html, :wrapper_html, :label, :hint, :for e :required
A opção :as serve pra trocar o valor padrão de um determinado campo, abaixo a lista de valores possíveis.
:select # um campo select. Padrão pra relacionamentos: belongs_to, has_many e has_and_belongs_to_many. :check_boxes # um gropo de campos check_box. Alternativa para o :select que pode ser usado nos relacionamentos: has_many e has_and_belongs_to_many. :radio # um grupo de campos radio. Alternativa para o :select que pode ser usado no relacionamento: belongs_to. :time_zone # um campo select. Padrão pra colunas tipo: :string que tenha "time_zone" no nome. :password # um campo password . Padrão pra colunas tipo: :string que tenham "password" no nome. :text # um textarea. Padrão pra colunas tipo: :text. :date # um select de datas. Padrão pra colunas tipo: :date. :datetime # um select de data e hora. Padrão pra colunas tipo: :datetime e :timestamp. :time # um select de hora. Padrão pra colunas tipo: :time. :boolean # um checkbox. Padrão pra colunas tipo: :boolean. :string # um campo de texto. Padrã pra colunas tipo: :string. :numeric # um campo de texto (igual ao :string). Padrão para os camppos tipo: :integer, :float e :decimal. :file # um campo file. Padrão pra atributos: paperclip or attachment_fu. :country # um select com os nomes dos países. Padrão pra colunas com o tipo: :string com o nome "country" - precisa ter o plugin country_select instalado. :hidden # um campo hidden. Padrão pra colunas tipo: :integer com nome :id.
<% semantic_form_for @post do |f| %> <%= f.inputs do %> <%= f.input :email %> <%= f.input :roles, :as => :check_boxes %> <% end %> <% f.buttons :commit %> <% end %>
HTML
<form action="/admin/users" class="formtastic user" id="new_user" method="post"> <div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="P0Wk/UO8rwgkhuhkEkz7sF1raZ9Xi/fvAx+Bhc/N3ko=" /></div> <fieldset class="inputs"> <ol> <li class="string required" id="user_email_input"> <label for="user_email">Email<abbr title="required">*</abbr></label> <input id="user_email" maxlength="255" name="user[email]" size="50" type="text" /> </li> <li class="check_boxes optional" id="user_roles_input"> <fieldset> <legend class="label"><label for="user_role_ids_1">Roles</label></legend> <ol> <li> <label for="user_role_ids_1"> <input name="user[role_ids][]" type="hidden" value="" /> <input id="user_role_ids_1" name="user[role_ids][]" type="checkbox" value="1" /> Admin </label> </li> </ol> </fieldset> </li> </ol> </fieldset> <fieldset class="buttons"> <ol> <li class="commit"> <input class="create" id="user_submit" name="commit" type="submit" value="Create Usuário" /> </li> </ol> </fieldset> </form>
A opção :collection é usada pra alterar as opções de um campo select ou checkbox.
f.input :authors, :as => :check_boxes, :collection => User.find(:all, :order => "last_name ASC") f.input :authors, :as => :check_boxes, :collection => current_user.company.users.active f.input :authors, :as => :check_boxes, :collection => [@justin, @kate] f.input :authors, :as => :check_boxes, :collection => ["Justin", "Kate", "Amelia", "Gus", "Meg"] f.input :author, :as => :select, :collection => Author.find(:all) f.input :author, :as => :select, :collection => { @justin.name => @justin.id, @kate.name => @kate.id } f.input :author, :as => :select, :collection => ["Justin", "Kate", "Amelia", "Gus", "Meg"] f.input :author, :as => :radio, :collection => User.find(:all) f.input :author, :as => :radio, :collection => [@justin, @kate] f.input :author, :as => :radio, :collection => { @justin.name => @justin.id, @kate.name => @kate.id } f.input :author, :as => :radio, :collection => ["Justin", "Kate", "Amelia", "Gus", "Meg"] f.input :admin, :as => :radio, :collection => ["Yes!", "No"]
A opção :input_html é usada pra passar atributos HTML para o campo.
<% semantic_form_for @user do |f| %> <% f.inputs do %> <%= f.input :name, :input_html => { :size => 100 } %> <%= f.input :email, :input_html => { :disabled => true } %> <%= f.input :senha, :input_html => { :class => 'senha' } %> <% end %> <%= f.buttons %> <% end %>
<form action="/admin/users" class="formtastic user" id="new_user" method="post"> <div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="P0Wk/UO8rwgkhuhkEkz7sF1raZ9Xi/fvAx+Bhc/N3ko=" /></div> <fieldset class="inputs"> <ol> <li class="string required" id="user_name_input"> <label for="user_name">Nome<abbr title="required">*</abbr></label> <input id="user_name" maxlength="255" name="user[name]" size="100" type="text" /> </li> <li class="string required" id="user_email_input"> <label for="user_email">Email<abbr title="required">*</abbr></label> <input id="user_email" maxlength="255" name="user[email]" size="50" type="text" disabled="disabled" /> </li> <li class="password required" id="user_password_input"> <label for="user_password">Senha<abbr title="required">*</abbr></label> <input class="senha" id="user_password" name="user[password]" size="50" type="password" /> </li> </ol> </fieldset> <fieldset class="buttons"> <ol> <li class="commit"> <input class="create" id="user_submit" name="commit" type="submit" value="Create Usuário" /> </li> </ol> </fieldset> </form>
A opção :button_html é usada pra passaratributos HTML paraos botões.
<% semantic_form_for @user do |f| %> <%= f.inputs %> <% f.buttons do %> <%= f.commit_button :button_html => { :class => "primary" } %> <% end %> <% end %>
<form action="/admin/users" class="formtastic user" id="new_user" method="post"> <div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="P0Wk/UO8rwgkhuhkEkz7sF1raZ9Xi/fvAx+Bhc/N3ko=" /></div> <fieldset class="inputs"> <ol> <li class="string required" id="user_name_input"> <label for="user_name">Nome<abbr title="required">*</abbr></label> <input id="user_name" maxlength="255" name="user[name]" size="50" type="text" /> </li> <li class="string required" id="user_email_input"> <label for="user_email">Email<abbr title="required">*</abbr></label> <input id="user_email" maxlength="255" name="user[email]" size="50" type="text" /> </li> <li class="password required" id="user_password_input"> <label for="user_password">Senha<abbr title="required">*</abbr></label> <input id="user_password" name="user[password]" size="50" type="password" /> </li> </ol> </fieldset> <fieldset class="buttons"> <ol> <li class="commit"> <input class="primary create" id="user_submit" name="commit" type="submit" value="Create Usuário" /> </li> </ol> </fieldset> </form>
A opção :wrapper_html é usada pra passar atributos HTML para o elemento HTML que envolve os campos, por padrão uma tag <li>.
<% semantic_form_for @user do |f| %> <% f.inputs do %> <%= f.input :email, :wrapper_html => { :class => "email" } %> <%= f.input :password, :wrapper_html => { :style => "margin:2px;" } %> <% end %> <%= f.buttons %> <% end %>
<form action="/admin/users" class="formtastic user" id="new_user" method="post"> <div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="P0Wk/UO8rwgkhuhkEkz7sF1raZ9Xi/fvAx+Bhc/N3ko=" /></div> <fieldset class="inputs"> <ol> <li class="string required email" id="user_email_input"> <label for="user_email">Email<abbr title="required">*</abbr></label> <input id="user_email" maxlength="255" name="user[email]" size="50" type="text" /> </li> <li class="password required" id="user_password_input" style="margin:2px;"> <label for="user_password">Senha<abbr title="required">*</abbr></label> <input id="user_password" name="user[password]" size="50" type="password" /> </li> </ol> </fieldset> <fieldset class="buttons"> <ol> <li class="commit"> <input class="create" id="user_submit" name="commit" type="submit" value="Create Usuário" /> </li> </ol> </fieldset> </form>
A opção :label é usada pra setar um label específico.
<% semantic_form_for @user do |f| %> <% f.inputs do %> <%= f.input :email, :label => 'Seu email:' %> <%= f.input :password, :label => 'Sua senha:' %> <% end %> <% end %>
<form action="/admin/users" class="formtastic user" id="new_user" method="post"> <div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="P0Wk/UO8rwgkhuhkEkz7sF1raZ9Xi/fvAx+Bhc/N3ko=" /></div> <fieldset class="inputs"> <ol> <li class="string required" id="user_email_input"> <label for="user_email">Seu email:<abbr title="required">*</abbr></label> <input id="user_email" maxlength="255" name="user[email]" size="50" type="text" /> </li> <li class="password required" id="user_password_input"> <label for="user_password">Sua senha:<abbr title="required">*</abbr></label> <input id="user_password" name="user[password]" size="50" type="password" /> </li> </ol> </fieldset> </form>
A opção :hint é usada pra passar texto de informação dentro do bloco.
<% semantic_form_for @user do |f| %> <% f.inputs do %> <%= f.input :email, :hint => 'Deve ser um email válido.' %> <%= f.input :password, :hint => 'Deve conter pelo menos 2 caracteres especiais.' %> <% end %> <% end %>
<form action="/admin/users" class="formtastic user" id="new_user" method="post"> <div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="P0Wk/UO8rwgkhuhkEkz7sF1raZ9Xi/fvAx+Bhc/N3ko=" /></div> <fieldset class="inputs"> <ol> <li class="string required" id="user_email_input"> <label for="user_email">Email<abbr title="required">*</abbr></label> <input id="user_email" maxlength="255" name="user[email]" size="50" type="text" /> <p class="inline-hints">Deve ser um email válido.</p> </li> <li class="password required" id="user_password_input"> <label for="user_password">Senha<abbr title="required">*</abbr></label> <input id="user_password" name="user[password]" size="50" type="password" /> <p class="inline-hints">Deve conter pelo menos 2 caracteres especiais.</p> </li> </ol> </fieldset> <fieldset class="buttons"> <ol> <li class="commit"> <input class="create" id="user_submit" name="commit" type="submit" value="Create Usuário" /> </li> </ol> </fieldset> </form>
A opção :for é usada pra formulários com nested_attributes.
<% semantic_form_for @user do |f| %> <%= f.inputs :name, :email %> <%= f.inputs :idade, :for => :perfil %> <% end %>
uma alternativa é usar como bloco passando então a usar o helper semantic_fields_for.
<% semantic_form_for @user do |f| %> <% f.inputs do %> <%= f.input :name %> <%= f.input :email %> <% end %> <% f.semantic_fields_for :perfil do |p| %> <%= p.input :idade %> <% end %> <% end %>
<form action="/admin/users" class="formtastic user" id="new_user" method="post"> <div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="P0Wk/UO8rwgkhuhkEkz7sF1raZ9Xi/fvAx+Bhc/N3ko=" /></div> <fieldset class="inputs"> <ol> <li class="string required" id="user_name_input"> <label for="user_name">Nome<abbr title="required">*</abbr></label> <input id="user_name" maxlength="255" name="user[name]" size="50" type="text" /> </li> <li class="string required" id="user_email_input"> <label for="user_email">Email<abbr title="required">*</abbr></label> <input id="user_email" maxlength="255" name="user[email]" size="50" type="text" /> </li> <li class="string required" id="user_perfil_age_input"> <label for="user_perfil_age">Idade<abbr title="required">*</abbr></label> <input id="user_perfil_age" name="user[perfil][age]" size="50" type="text" /> </li> </ol> </fieldset> <fieldset class="buttons"> <ol> <li class="commit"> <input class="create" id="user_submit" name="commit" type="submit" value="Create Usuário" /> </li> </ol> </fieldset> </form>
A opção :required é usada para informar se o campo é obrigatório ou opcional.
<% semantic_form_for @user do |f| %> <% f.inputs do %> <%= f.input :name, :required => false %> <%= f.input :email, :required => true %> <%= f.input :password, :required => true %> <% end %> <% end %>
<form action="/admin/users" class="formtastic user" id="new_user" method="post"> <div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="P0Wk/UO8rwgkhuhkEkz7sF1raZ9Xi/fvAx+Bhc/N3ko=" /></div> <fieldset class="inputs"> <ol> <li class="string optional" id="user_name_input"> <label for="user_name">Nome</label> <input id="user_name" maxlength="255" name="user[name]" size="50" type="text" /> </li> <li class="string required" id="user_email_input"> <label for="user_email">Email<abbr title="required">*</abbr></label> <input id="user_email" maxlength="255" name="user[email]" size="50" type="text" /> </li> <li class="password required" id="user_password_input"> <label for="user_password">Senha<abbr title="required">*</abbr></label> <input id="user_password" name="user[password]" size="50" type="password" /> </li> </ol> </fieldset> <fieldset class="buttons"> <ol> <li class="commit"> <input class="create" id="user_submit" name="commit" type="submit" value="Create Usuário" /> </li> </ol> </fieldset> </form>
O formtastic continua crescendo a cada dia e existem mais coisas já implementas e que estão em implementação, então se você precisar de algo mais específico basta dar uma conferida no projeto que é bem provável você encontrar o que precisa.