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.

blog comments powered by Disqus