Asociando imágenes a nuestros registros
Una de las funcionalidades que quería añadirle al Diccionario Malacitano es la de poder adornar ciertas entradas (no todas) con imágenes. Lo que me ha sorprendido (y a estas alturas ya tendría que estar acostumbrado) es lo tremendamente sencillo que es si usamos el plugin file_column. Basta con instalarlo, hacer una pequeña migración en la base de datos y con un par de ajustes podremos subir nuestras imágenes a la aplicación y mostrarlas en nuestras vistas cuando lo consideremos necesario.
<!--more-->
<h2>Instalación de <code>file_column</code></h2>
<p>Este <em>plugin</em> es permite asociar ficheros a las entidades de nuestro modelo. La idea consiste en crear una nueva columna para cada registro donde insertaremos el <em>path</em> del fichero que deseemos asociar. En nuestro caso se tratará de una imagen, pero podría ser cualquier otra cosa (siempre que luego sepamos devolverla con el <code>content-type</code> adecuado)</p>
<p>Podemos descargar este plugin de <a href="http://www.kanthak.net/opensource/file_column/">la web del autor</a> He tenido problemas usando <code>svn</code> para importar en mi proyecto el código del <em>plugin</em>, así que he tenido que recurrir a instalarlo directamente en <code>vendor/plugins/file-column</code> descargando el <a href="http://www.kanthak.net/opensource/file_column/file-column-0.3.1.tar.gz">último paquete</a></p>
<h2>Preparando la base de datos</h2>
<p>No hay mucho que hacer: añadimos a nuestra tabla de entradas del diccionario una columna llamada <code>imagen</code> que contendrá una cadena. El <em>plugin</em> se encargará de gestionar este campo de forma que contenga el <em>path</em> completo del fichero correspondiente.</p>
1 2 3 4 5 6 7 8 9 |
class AddFileColumn < ActiveRecord::Migration def self.up add_column :entradas, :imagen, :string end def self.down remove_column :entradas, :imagen end end |
Para evitar que el nuevo campo imagen sea tratado como una cadena cualquiera, tendremos que declarar en nuestra clase del modelo que el campo imagen es de tipo file_column (con lo que pasará a estar controlado por el código del plugin que hemos instalado)
1 2 3 |
class Entrada < ActiveRecord::Base file_column :imagen end |
Modificando el formulario generado por el andamiaje
Queremos que al editar una entrada podamos escoger un archivo en el formulario correspondiente y que el archivo se suba al servidor (junto con el resto de datos del registro que hemos editado) Esto quiere decir que el formulario de edición de nuestras entradas pasa a ser un formulario multiparte (un parte para los datos de la entrada y otra parte para la imagen que queramos subir). Lo tendremos que especificar así en edit.rhtml
1 2 3 4 |
<%= form_tag ({:action => 'update', :id => @entrada}, :multipart => true) %>
<%= render :partial => 'form' %>
<%= submit_tag 'Edit' %>
<%= end_form_tag %> |
Por supuesto, habrá que añadir el nuevo campo en el parcial _form.rhtml_, usando el helper file_column_field que nos proporciona el plugin:
1 2 |
<p><label for="entrada_imagen">Imagen</label><br/> <%= file_column_field 'entrada', 'imagen' %> |
Mostrando la imagen
Para mostrar la imagen en aquellas entradas que dispongan de ella, tendremos que modificar nuestro parcial _entrada.rhtml (de su uso como respuesta a la llamada Ajax que se hace al hacer clic sobre una letra de índice hablamos en una historia anterior)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<% @entradas.each do |entrada| %> <div class="entrada"> <% if entrada.imagen %> <% @entrada = entrada -%> <%= image_tag( url_for_file_column("entrada", "imagen"), { :class => 'entrada-imagen'}) -%> <% end %> <dl> <dt><em><strong><%= entrada.voz -%></strong></em> <dd><%= textilize_without_paragraph(entrada.texto) -%> </dl> </div> <% end %> |
Para generar el path correspondiente a la columna imagen de la entrada correspondiente, hay que usar el helper url_for_file_column Observad cómo el primer parámetro es el nombre de una variable de instancia (de ahí la línea anterior asignando el iterador entrada a una variable de instancia)
Y no tenemos nada más que hacer. Por defecto, el plugin las guardará en public/entrada/imagen, en un subdirectorio correspondiente al id de los registros que tengan valor en este campo. Podeis ver cómo queda en la aplicación final viendo la entrada cenachero del Diccionario Malacitano.
