2010-08-03 9 views
10

que tienen un modelo ActiveRecord como esto:¿Es posible agregar un índice independiente de la base de datos basado en funciones a través de una migración de Rails/ActiveRecord?

create_table "books" do |t| 
    t.string "title" 
end 

class Book < ActiveRecord::Base 
    default_scope :order => 'lower(title) DESC' 
end 

Como se puede ver que quiero para ordenar por la forma minúscula del atributo title, pero esto impone un impacto en el rendimiento a nivel de base de datos. Este golpe puede remediarse de diferentes maneras con diferentes bases de datos. Por ejemplo, en PostgreSQL u Oracle crea un índice basado en las funciones:

CREATE INDEX lowercase_book_title_index ON book (lower(title)); 

SQLite3 no tiene índices basados ​​en funciones por lo que tiene que especificar una colación:

CREATE INDEX lowercase_book_title_index ON book (title COLLATE NOCASE); 

yo no tengo investigó cómo lo hace con MySQL pero estoy seguro de que hay una manera (¿colaciones ?, ¿columnas virtuales?).

En cualquier caso, me gustaría hacer esto de la manera adecuada de Rails con una migración independiente de la base de datos. Por supuesto, puedo crear un índice simple como este:

add_index :books, :title 

Pero el índice que genera distingue entre mayúsculas y minúsculas. Me doy cuenta de que podría escribir una migración dependiente de la base de datos, pero no es muy elegante. Tampoco es práctico. A menudo me encuentro usando SQLite3 en mis estaciones de trabajo de desarrollo y PostgreSQL en producción. Las opciones disponibles para add_index tratan con el nombre del índice, la singularidad y la longitud. ¿Estoy pasando por alto una forma de lograr lo que estoy tratando de hacer aquí?

+0

No está directamente relacionado con su pregunta, pero usar SQLite en desarrollo y PostgreSQL en producción causa mucho dolor. (Muerde mucho a los usuarios de Heroku. A * lot *.) Como PostgreSQL también es gratuito, no tiene sentido desarrollarlo contra SQLite. –

+0

Ha sido sorprendentemente sin dolor para mí, siempre que deje que ActiveRecord escriba el SQL. Este no fue el caso cuando estaba desarrollando MySQL y luego tuve que implementarlo en PostgreSQL. – Sven

Respuesta

0

Nunca tuve ningún problema con ese tipo de clasificación. Básicamente, lo que quiere es que los resultados se clasifican de esta manera:

"A bad title" 
"A better title" 
"a good title" 
"An excellent title" 

Si esto es correcto y va con MySQL, se puede especificar una colación en su database.yml, intente:

production: 
    adapter: mysql2 # or mysql for rails < 3 
    host: ... 
    database: ... 
    username: ... 
    encoding: utf8 # or whatever you are using 
    collation: utf8_general_ci # or whatever fits your language and encoding 

utf8_general_ci significa "cotejar con utf8 de una manera independiente del idioma y ser insensible a mayúsculas y minúsculas".

Esto debería hacer el truco.

+1

Eso es cierto, y gracias por su respuesta, pero estaba buscando una base de datos-_agnostic_ forma de hacerlo. Es decir, solo una migración de Rails puede crear una: columna binaria que se convierte en un blob en MySQL o un bytea en PostgreSQL. Me gustaría poder especificar un índice que no distinga mayúsculas y minúsculas en mi migración de Rails, que se maneja de la manera adecuada. en las bases de datos – Sven

+0

Estoy investigando el mismo problema, ¿encontró una solución? ¿El uso del default_scope con la opción 'inferior' tiene un impacto significativo en el rendimiento? –

1

Respuesta corta: no

Respuesta larga: No, porque no todos los motores de bases de datos que soportan lo Rieles soportes, o de una manera muy diferente. Si está seguro , todos los motores de base de datos lo admiten y luego presentan una solicitud de función para los desarrolladores de ActiveRecord.

Recuerde: en las migraciones de ActiveRecord, solo puede hacer lo que admite todo el motor de base de datos, los elementos específicos de la base de datos necesitan inicializaciones separadas de las migraciones.

Recomiendo configurar esta intercalación a partir de una tarea de rake separada que se ejecuta después de db: migrate. En mis aplicaciones más grandes uso rake setup donde puedo hacer estos pasos específicos.

Cuestiones relacionadas