2010-06-02 19 views
9

Estoy sufriendo de una variante de the problem described here:: incluyen y tabla de alias

ActiveRecord assigns table aliases for association joins fairly unpredictably. The first association to a given table keeps the table name. Further joins with associations to that table use aliases including the association names in the path... but it is common for app developers not to know about [other] joins at coding time.

En mi caso estoy de ser mordido por una mezcla tóxica de has_many y: include. Muchas tablas en mi esquema tienen una columna state, y has_many quiere especificar condiciones en esa columna: has_many :foo, :conditions => {:state => 1}. Sin embargo, dado que la columna de estado aparece en muchas tablas, desambiguo especificando explícitamente el nombre de la tabla: has_many :foo, :conditions => "this_table.state = 1".

Esto ha funcionado bien hasta ahora, cuando por eficiencia quiero agregar un :include para precargar un árbol bastante profundo de datos. Esto provoca que la tabla tenga alias de forma incoherente en diferentes rutas de código. Mi lectura de los tickets mencionados anteriormente es que este problema no se soluciona y no se solucionará en Rails 2.x. Sin embargo, no veo ninguna forma de aplicar la solución alternativa sugerida (para especificar el nombre de la tabla con alias explícitamente en la consulta). Me complace especificar el alias de la tabla explícitamente en la declaración has_many, pero no veo ninguna forma de hacerlo. Como tal, la solución no parece aplicable a esta situación (ni, supongo, en muchos escenarios 'named_scope').

¿Existe una solución viable?

Respuesta

0

algo así como

:conditions => { :this_table => { :state => 1 } } 
+2

Se considera buena práctica probar su respuesta al adivinar. La primera entrada en el hash es una columna para la tabla. [2010-06-02 15:16:42] [DEBUG] ThisTable Load (0.000000) Mysql :: Error: # 42S22Una columna desconocida 'this_table.this_table' en 'where clause': SELECT * FROM 'this_table' WHERE (' this_table' .this_table' = '--- -: estado - 1 ') – dondo

0

¿Está utilizando cualquiera de los campos de los :include tablas de la consulta (como: condiciones /: orden, etc.)? Si no, y sólo tiene que cargar registros, puede hacerlo con consulta independiente:

records = Bar.all(:joins => ..., :conditions => ..., ...) 
Bar.send(:preload_associations, records, [:association1, :association2 ... ]) 

preload_associations es método protegido (ver more en esta respuesta), pero utilizando: uniones y: incluir en conjunto por lo general produce gran SQL consulta, que está muy lejos de ser manejable.

+0

Gracias, sugerencia interesante. Sí, las condiciones incluyen campos de: tablas de inclusión. Sin embargo, creo que podría construir la precarga a mano, y tal vez recurriré a eso. Eso obvia mucha de la elegancia de has_many y: incluir, obviamente. – dondo

3

En lugar de utilizar: incluir, con la tecla: unir puede escribir explícitamente la unión y darle su propio alias de tabla. Tienes que especificar a mano la unión, pero hará que tus requisitos sean completamente inequívocos. por ejemplo:

Bar.all(:joins => "INNER JOIN foos AS my_foos ON my_foos.bar_id = bars.id", :conditions => "my_foos.state = 1") 
Cuestiones relacionadas