Modificando registros a base de migraciones

En otras ocasiones hemos hablado de las migraciones de Rails, una característica que nos permite modificar el esquema de la base de datos usando Ruby.

<p>Alguien se puede preguntar cuáles son las ventajas reales de manipular la base de datos usando Ruby en lugar de <span class="caps">SQL</span>.   La primera de ellas es que sólo tendremos que lidiar con las peculiaridades de Ruby, en vez de tener que andar consultando las referencias del dialecto de <span class="caps">SQL</span> que haya tenido a bien implementar el fabricante de nuestro gestor de bases de datos.  La segunda es que, además de modificar el esquema de la base de datos añadiendo tablas, columnas, etc. con las migraciones podemos modificar los datos ya existentes en nuestras tablas.</p>


<p>Supongamos que tenemos la tabla que vendría dada por la siguiente migración:</p>
1
2
3
4
5
6
7
8
9
10
11
class Inicial < ActiveRecord::Migration
  def self.up
    create_table :entradas do |t|
         t.column :voz, :string
         t.column :inicial, :char
         t.column :texto, :text 
    end
  end

  def self.down
  end

Se trata de crear una tabla que nos sirva de diccionario, donde cada voz o palabra tiene un texto asociado pero además una inicial que será el campo que usaremos a la hora de buscar. La inicial, por definición, es la primera letra de la voz.

Pues bien, este esquema para nuestro diccionario tiene un problema: en un diccionario en castellano deberíamos poder buscar por las letras ll y ch. Al haber usado sólo un carácter para la columna inicial no podemos distinguir entre las palabras que empiezan por l y por ll.

Migraciones al rescate: no sólo vamos a cambiar la columna de inicial la base de datos, que pasará a ser una cadena en lugar de un sólo carácter, sino que además rellenaremos esa columan correctamente, comprobando si la voz empieza por ch, por ll o por cualquier otra letra:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class LetrasPorCadenas < ActiveRecord::Migration
  
  def self.dame_inicial str
    pat = /^(ch|ll|[^ ])/
    refs = pat.match str
    refs[0]
  end
  
  def self.up
    remove_column :entradas, :inicial
    add_column :entradas, :inicial, :string
    
    Entrada.reset_column_information
    say_with_time "Genero las iniciales" do
      Entrada.find(:all).each do |e| 
        e.inicial = dame_inicial(e.voz)
        e.save
      end
    end
  end

end

Son a destacar:

  1. El útil metodo say_with_time que nos sirve para rastrear el progreso de nuestra migración
  2. Tras modificar cada registro hay que invocar el método save de ActiveRecord , o de lo contrario la tupla no se modificará—no he visto mención a este detalle en ninguno de los tutoriales de migraciones que he encontrado por ahí.

No intentes casar expresiones regulares usando tu dialecto favorito de SQL. Tu salud mental te lo agradecerá.

blog comments powered by Disqus