#184 Formtastic Part 1
- Download:
- source codeProject Files in Zip (104 KB)
- mp4Full Size H.264 Video (14.7 MB)
- m4vSmaller H.264 Video (10.3 MB)
- webmFull Size VP8 Video (24.9 MB)
- ogvFull Size Theora Video (19.1 MB)
Si encuentras que escribir el código de las vistas es más que una tarea tediosa, estarás alegre de saber que existe una librería llamada Formtastic que proporciona una manera más concisa para hacerlo. Con ésta, formularios complejos se pueden crear con relativamente poco código como te mostraremos en este episodio.
Creando la aplicación Vet
Antes de comenzar con Formtastic, vale la pena mencionar que existe un paquete de TextMate. El mismo proporciona una serie de útiles fragmentos de código que pueden hacer que la creación de formularios sea aún más fácil.
Para demostrar el funcionamiento de Formtastic, crearemos una nueva aplicación Rails. Esta aplicación llevará el registro de pacientes animales en una clínica veterinaria. Llamaremos a la aplicación vet
y la crearemos de forma normal.
<p>Formtastic es distribuido como una gema. Podemos incluirla en nuestra aplicación agregando las siguiente línea en el archivo <code>/config/environment.rb</code>. (Si estás utilizando TextMate e instalaste el paquete de Formtastic puedes usar <code>ftgem</code> y <code><TAB></code> como un acceso directo).</p> ``` ruby config.gem 'justinfrench-formtastic', :lib => 'formtastic', :source => 'http://gems.github.com'
Para asegurarnos que la gema está instalada, necesitamos ejecutar
``` terminal sudo rake gems:install<p>así estamos listos para comenzar a escribir nuestra aplicación.</p> <p>Nuestra aplicación utilizará la biblioteca <a href="http://github.com/ryanb/nifty-generators">nifty generators</a> de Ryan Bates para facilitar el desarrollo de partes de la misma. Lo primero que usaremos es el generador <code>nifty_layout</code>, el cuál creará un layout y una hoja de estilos</p> ``` terminal script/generate nifty_layout
Luego generaremos nuestro primer modelo, utilizando el generador nifty_scaffold
para crear un controlador y las vistas correspondientes. Pondremos nuestros animales en categorías, así que llamaremos a nuestro modelo Category
y le daremos los atributos name
y description
.
<p>Ahora podemos migrar nuestra base de datos.</p> ``` terminal rake db:migrate
Si corremos nuestra nueva aplicación y navegamos a la página para crear una nueva categoría, veremos el código generado para la vista por el scaffold
El código generado por el scaffolding para el formulario anterior es el siguiente:
``` ruby <% form_for @category do |f| %> <%= f.error_messages %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_area :description, :rows => 5 %>
<%= f.submit "Submit" %>
<% end %><p>Esto es código normal para un formulario Rails, comenzando con <code>form_for</code> y definiendo separadamente cada campo del formulario junto a su etiqueta. Finalmente, hay un botón de enviar con el que podremos agregar una nueva categoría.</p> <p>Formtastic no sobreescribe ninguno de los métodos estándar, por lo que aún podremos utilizarlos en un formulario Formtastic. Si reemplazamos el <code>form_for</code> en el formulario anterior con <code>semantic_form_for</code> de Formtastic, el formulario funcionaría de la misma manera. No tiene mucho sentido hacer eso, sin embargo; la verdadera ventaja aparece cuando utilizamos los métodos de Formtastic. Con ellos, podemos cambiar nuestro formulario para que se vea de la siguiente forma:</p> ``` ruby <% semantic_form_for @category do |f| %> <%= f.inputs %> <%= f.buttons %> <% end %>
El método inputs
es una manera conveniente de generar todos los campos para un modelo, igualmente, el método buttons
genera el botón de enviar. Si ahora recargamos el formulario, se ve un poco diferente.
Este formulario ahora es mostrado utilizando los métodos de Formtastic. La diferencia más notoria es que mientras el formulario generado a través de scaffold utilizaba tags de párrafos, Formtastic utiliza listas ordenadas y fieldsets para separar los campos de entrada de los botones.
El formulario no se ve particularmente lindo como está, pero podemos arreglarlo aplicando un poco de CSS. Formtastic viene con algunas hojas de estilo existentes que podemos generar para no tener que hacer todo el trabajo nosotros mismos. Si corremos
``` terminal script/generate formtastic_stylesheets<p>dos nuevas hojas de estilos serán creadas en el directorio <code>/public/stylesheets</code> de nuestra aplicación y nos permite referenciarlas desde nuestro archivo de layout. En la sección head de nuestro layout ya estamos referenciando una hoja de estilo.</p> ``` ruby <head> <title><%= h(yield(:title) || "Untitled") %></title> <%= stylesheet_link_tag 'application' %> <%= yield(:head) %> </head>
Podemos agregar las dos hojas de estilo de Formtastic aquí para incluirlas en todas las páginas de nuestra aplicación
``` ruby <%= stylesheet_link_tag 'application', 'formtastic', 'formtastic_changes' %><p>El segundo archivo, <code>formtastic_changes</code>, es donde deberíamos realizar cualquier cambio al estilo por defecto provisto por Formtastic. Como ahora tenemos múltiples hojas de estilos, deberíamos utilizar la opción de cache de Rails de forma de combinar todos los archivos en uno solo cuando lo corramos en modo producción (Esto también se aplica a múltiples archivos JavaScript)</p> ``` ruby <%= stylesheet_link_tag 'application', 'formtastic', 'formtastic_changes', :cache => 'base' %>
Utilizando el cacheo de esta forma significa que menos cantidad de archivos serán pedidos al servidor cuando se carga la página, ya que las tres hojas de estilos serán combinadas en una sola llamada base.css
Si recargamos el formulario ahora, se verá un poco mejor, pero todavía no como se debería ver.
Esto es por un par de líneas en la hoja de estilos de Formtastic.
``` terminal html[xmlns] form.formtastic fieldset { display: block; } html[xmlns] form.formtastic fieldset ol li { display: block; }<p>Los dos selectores CSS anteriores esperan que el comienzo de las páginas, el tag <code><html></code>, tenga el atributo <code>xmlns</code>. En el archivo de layout generado por nifty_layout el tag no tiene este atributo, por lo que tendremos que agregarlo para que el formulario se muestre como debería.</p> ``` terminal <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
Recargamos el formulario ahora y veremos como los campos de texto se alinean como hubiéramos esperado. Hora que el formulario se ve como debería podemos agregar un par de categorías, una para perros y otra para gatos. Las utilizaremos pronto cuando creemos el formulario para animales.
Un ejemplo más complejo
Ahora pasaremos al formulario para los animales. Como con las categorías, comenzaremos por generar el scaffold.
``` terminal script/generate nifty_scaffold animal name:string category_id:integer born_on:date female:boolean<p>El modelo <code>Animal</code> tendrá los atributos <code>name</code>, <code>born_on</code> y <code>female</code> junto con un <code>category_id</code> así podremos poner cada animal dentro de una <code>Category</code>. Luego de crear el scaffold ejecutaremos la migración de nuestra base de datos nuevamente de forma que la nueva tabla sea creada.</p> ``` terminal rake db:migrate
El siguiente paso es crear las relaciones entre modelos, así es que un animal pertenece a una categoría…
``` terminal class Animal < ActiveRecord::Base attr_accessible :name, :category_id, :born_on, :female belongs_to :category end<p>…y una categoría tiene muchos animales.</p> ``` ruby class Category < ActiveRecord::Base attr_accessible :name, :description has_many :animals end
El formulario generado por el scaffolding se muestra debajo. Queremos reemplazarlo con un poco de código Formtastic así que lo cambiaremos pronto.
Como en el formulario de categoría, reemplazaremos el código por defecto de form_for
por el código de Formtastic semantic_form_for
.
<p>Esta vez vamos a querer más control sobre los campos de nuestro formulario así que vamos a personalizarlos pronto por lo que hemos pasado un bloque <code>f.inputs</code> y dentro del mismo usamos el método <code>input</code> para definir cada campo. Luego de haber cerrado el bloque, podemos agregar nuestro botón enviar con <code>f.buttons</code> al igual que lo hicimos anteriormente.</p> <p>Si recargamos el formulario ahora, veremos que los campos son mostrados a través de Formtastic.</p> <div class="imageWrapper"> <img src="http://railscasts.com/static/episodes/asciicasts/E184I06.png" width="801" height="477" alt="The New Animal page with the Formtastic controls on it."/> </div> <p>Formtastic ha creado campos de formularios apropiados a los tipos atributos del modelo <code>Animal</code>. Aunque no lo puedes ver aquí, incluso ha inferido que el campo <code>category_id</code> es una asociación y ha cargado el dropdown de categorías con las categorías que agregamos anteriormente.</p> <p>Hay algunos cambios que queremos hacerle a este formulario. Por defecto, la parte del año de la fecha es cargada únicamente con cinco años hacia cada lado del año actual y precisamos mostrar fechas más atrás que eso. También queremos quitar la opción en blanco del dropdown de <code>category</code> y mostrar el campo <code>female</code> como un par de botones de radio en lugar de un checkbox.</p> <p>Podemos personalizar campos usando las mismas opciones que pasamos a los helpers de formularios de Rails. Esto significa que podemos pasarle a <code>born_on</code> <code>:start_year</code> y podemos usar el parámetro <code>:include_blank => false</code> en nuestra categoría para quitar la opción en blanco.</p> ``` ruby <% 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 %> <% end %> <%= f.buttons %> <% end %>
Tenemos que tratar el campo female
un poco diferente ya que estamos cambiando el tipo del elemento en el formulario. Para especificar un tipo de campo diferente al por defecto, Formtastic proporciona el parámetro :as
. Podemos usar :as => :radio
para cambiar el tipo a botones de radio
Si miramos nuevamente el formulario, veremos que los cambios que realizamos efectivamente se reflejan en el mismo, con las fechas comenzando desde 1900, la opción en blanco no está en la categoría y el checkbox de female fue reemplazado por dos botones de radio
Los botones de radio son una mejora con respecto al checkbox, pero en lugar de “yes” y “no” queremos que la etiqueta del campo sea “Gender” y que los botones de radio sean “Male” y “Female”. ¿Permite Formtastic éste nivel de personalización? Así es. Podemos utilizar las opciones :label
y :collection
para asignar los valores de la etiqueta y los botones de radio.
Como su nombre lo indica, la opción :label
asigna el nombre de la etiqueta mientras que la opción :collection
toma un array de arrays especificando el nombre y valor de cada botón de radio.
El formulario ahora se ve como queremos.
Nuestro formulario está ahora completo y podemos utilizarlo para crear cuantos animales queramos.
Llevándolo más lejos
Con Formtastic hemos creado un formulario bastante complejo con relativamente poco código en la vista, utilizando sus opciones de personalización para alterar alguno de los campos a nuestra necesidad. Todavía hay bastante de Formtastic que no hemos cubierto aunque lo haremos en el próximo episodio.