homeASCIIcasts

185: Formtastic: parte 2  

(view original Railscast)

Other translations: En Tr

Other formats:

Written by Leandro Bertolami

En el episodio anterior introdujimos Formtastic, una excelente gema para producir vistas con muy poco código. Con él creamos una aplicación básica para una clínica veterinaria que tenía formularios para agregar y editar animales y categorías de animales. En este episodio usaremos algunas funciones más avanzadas de Formtastic para extender nuestra aplicación.

La página para editar un animal

Al final del último episodio, teníamos un formulario que podíamos utilizar para crear y actualizar los detalles de un animal. En este episodio modificaremos el formulario para agregarle algunas características más.

Manejando Relaciones Many-to-Many

Un animal puede llegar a la clínica veterinaria con un varios problemas, por lo que la primer modificación que vamos a realizar en nuestra aplicación es agregar un modelo Problem. Este modelo tendrá una relación many-to-many con Animal. En el episodio previo, vimos lo bien que Formtastic maneja las relaciones one-to-many en los formularios cuando lo utilizamos para crear un dropdown de la categoría. No es necesario decir que puede trabajar con relaciones many-to-many de igual forma.

Comenzaremos por crear el scaffolding del modelo Problem. Como en el episodio anterior, utilizaremos nifty generators de Ryan Bates para crear el scaffold de una forma más simple.

script/generate nifty_scaffold problem name:string

Como estamos creando una relación many-to-many necesitaremos un modelo de join. Crearemos uno llamado Symptom que referenciará a ambos, Animal y Problem.

script/generate nifty_scaffold symptom animal_id:integer problem_id:integer --skip-controller

No hay necesidad de manipular los síntomas directamente desde la interfaz web, por lo que utilizamos la opción --skip-controller para evitar crear el controlador.

Para completar este paso, migraremos nuestra base de datos para crear las nuevas tablas.

rake db:migrate

Luego, debemos configurar la asociación entre los modelos Problem, Symptom y Animal. Un Problem tiene muchos Symptoms y Animals:

class Problem < ActiveRecord::Base
  attr_accessible :name
  has_many :symptoms
  has_many :animals, :through => :symptoms
end

Un Symptom pertenece a un Problem y a un Animal:

class Symptom < ActiveRecord::Base
  attr_accessible :animal_id, :problem_id
  belongs_to :animal
  belongs_to :problem
end

Finalmente un Animal tiene muchos Symptoms y Problems:

class Animal < ActiveRecord::Base
  attr_accessible :name, :category_id, :born_on, :female, :problem_ids
  belongs_to :category
  has_many :symptoms
  has_many :problems, :through => :symptoms
end

Hay un cambio más que debemos realizar a nuestro modelo Animal. Como utilizaremos attr_accessible para controlar que campos pueden ser actualizados por asignamiento masivo, necesitamos agregar problem_ids a la lista de campos accesibles de forma de poder asignar múltiples problemas a un animal de forma masiva y permitir actualizaciones a través de la interfaz de usuario.

Ahora que modificamos los modelos podemos actualizar el formulario para que los problemas puedan ser asignado a los animales. Solo necesitamos agregar <%= f.input :problems %> al formulario de animal para mostrar los problemas como un select múltiple.

<% semantic_form_for @animal do |f| %>
  <% f.inputs do %>
    <%= f.input :name %>
    <%= f.input :born_on, :start_year => 1900 %>
    <%= f.input :category, :include_blank => false %>
    <%= f.input :female, :as => :radio, :label => "Gender", :collection => [["Male", false], ["Female", true]] %>
    <%= f.input :problems %>
  <% end %>
  <%= f.buttons %>
<% end %>

Si recargamos la página ahora, veremos la lista de problemas en el formulario. (Agregamos algunos problemas a la base de datos de forma de tener algo que mostrar.) Si seleccionamos un par de problemas y salvamos nuestro animal veremos que están seleccionados al volver a editar el animal.

Los problemas listados con un select múltiple

Nos gustaría mostrar los problemas como una lista de checkboxes en lugar de un select múltiple. La última vez utilizamos la opcion :as de Formtastic para cambiar checkboxes a botones de radio y podemos realizar el mismo cambio aquí para mostrar la lista como checkboxes.

<%= f.input :problems, :as => :checkboxes %>

Otra recarga de la página y los problemas son mostrados como checkboxes, con los ítems previamente seleccionados en el select múltiple chequeados.

Los problemas son ahora mostrados como una lista de checkboxes

Trabajando Con Campos Requeridos

Cada etiqueta de campo tiene un asterisco a su derecha para indicar que es requerido. Formtastic hace que todos los campos sean requeridos por defecto. Podemos sobreescribir este comportamiento para un campo específico utilizando la opción :required.

<%= f.input :problems, :as => :check_boxes, :required => false %>

Controlar esto campo-por-campo puede convertirse rápidamente en una molestia; sería mucho más fácil si podemos utilizar las validaciones del modelo para controlar que campos son requeridos. Formtastic soporta este comportamiento, pero antes debemos instalar un plugin llamado validation_reflection para poder utilizarlo.

Podemos instalar el plugin en nuestra aplicación desde GitHub.

script/plugin install git://github.com/redinger/validation_reflection.git

Una vez que validation_reflection está instalado, necesitamos reiniciar nuestro servidor así nuestro plugin es reconocido. Si recargamos la página veremos que los asteriscos se han ido. Esto es porque ninguno de los campos del modelo Animal tiene validaciones.

Los indicadores de campos requeridos no se muestran más.

Podemos ahora agregar validaciones a los atributos name y born_on para que sear requeridos…

class Animal < ActiveRecord::Base
  attr_accessible :name, :category_id, :born_on, :female, :problem_ids
  belongs_to :category
  has_many :symptoms
  has_many :problems, :through => :symptoms
  validates_presence_of :name, :born_on
end

…y si recargamos el formulario nuevamente, los asteriscos aparecerán nuevamente en las etiquetas de esos campos.

Los dos primeros campos son ahora requeridos por las validaciones del modelo

Como Maneja Formtastic Los Mensajes De Error

Formtastic muestra los mensajes de error de un formulario junto a cada campo. Si quitamos el nombre de nuestro animal y tratamos de actualizar, se mostrará el mensaje de error por defecto.

El texto por defecto en la validación de campo.

Podemos cambiar el comportamiento si lo creemos necesario alterando la configuración de Formtastic

Lo mejor es colocar los detalles de configuración en un archivo en el directorio /config/initializers. Llamaremos al archivo formtastic_config.rb. La página GitHub de Formtastic tiene los detalles de lo que se puede poner dentro del archivo de configuración e incluso hay un archivo de prueba que podemos consultar. Una de las opciones de configuración listadas aquí es inline_errors, que es la que debemos cambiar para indicar donde mostrar los errores del formulario. Para ocultar los errores podemos setear inline_errors a :none en el archivo de configuración.

Formtastic::SemanticFormBuilder.inline_errors = :none

Si tratamos de enviar el formulario inválido nuevamente no nos mostrará errores. Si queremos desplegar los errores como una lista en el tope del formulario podemos utilizar el método error_messages para mostrar los errores en el estilo “clásico” de Rails.

<% semantic_form_for @animal do |f| %>
  <%= f.error_messages %>
  <% f.inputs do %>
  <!-- rest of form -->

Los errores son desplegados ahora en el tope del formulario.

Los errores son desplegados ahora en el tope del formulario.

Hints

Hay una opción de campos de Formtastic que aún no hemos mostrado: :hint. Como su nombre sugiere, :hint muestra un mensaje de hint junto al campo. Para agregar un hint al campo de nombre, solamente necesitamos agregar el mensaje apropiado.

<%= f.input :name, :hint => "Enter the owner&rsquo;s name if none is provided." %>

Cuando recargamos la página el mensaje de hint es mostrado debajo del campo del formulario.

El hint es mostrado debajo del campo.

Si queremos darle estilo al mensaje de hint o a a cualquier otra parte de nuestro formulario, lo podemos hacer modificando el archivo formtastic_changes.css que Formtastic generó en el pasado episodio cuando ejecutamos

script/generate formtastic_stylesheets

El archivo esta pre-cargado con una sección de comentarios, la cuál para nuestra suerte, incluye un ejemplo de como alterar el estilo del texto del hint. Si queremos que el tamaño del texto del hint sea de 11px y en formato itálica, podemos hacerlo utilizando el siguiente CSS:

form.formtastic fieldset ol li p.inline-hints { 
  font-style: italic;
  font-size: 11px;
}

Recargamos el formulario nuevamente y el texto del hint habrá cambiado.

Nuestro hint ahora tiene estilo.

Si queremos realizar más cambios a la apariencia del formulario, lo mejor es mirar el archivo formtastic.css para ver como están definidos los estilos por defecto. Podemos utilizar selectores similares en formtastic_changes.css para sobre-escribir los originales.

Eso es todo por este episodio. Es de esperar que te ha dado suficiente información acerca de Formtastic para persuadirte a que lo pruebes en tus propias aplicaciones. Hay una serie de características que no hemos logrado cubrir en el curso de estos dos episodios. La documentación de Formtastic cubre todas sus características y vale la pena utilizarla para encontrar más información, incluido el soporte de internacionalización