En mi aplicación, un usuario tiene_muchas entradas. Desafortunadamente, la tabla de tickets no tiene un user_id: tiene un user_login (es una base de datos heredada). Voy a cambiar eso algún día, pero por ahora este cambio tendría demasiadas implicaciones.¿Cómo paso una cadena a un parámetro has_many: finder_sql?
Entonces, ¿cómo puedo crear una asociación de "usuario has_many: tickets" a través de la columna de inicio de sesión?
Intenté lo siguiente finder_sql, pero no funciona.
class User < ActiveRecord::Base
has_many :tickets,
:finder_sql => 'select t.* from tickets t where t.user_login=#{login}'
...
end
me sale un error extraño:
ArgumentError: /var/lib/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:402:in `to_constant_name': Anonymous modules have no name to be referenced by
from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:2355:in `interpolate_sql'
from /var/lib/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:214:in `qualified_name_for'
from /var/lib/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:477:in `const_missing'
from (eval):1:in `interpolate_sql'
from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/association_proxy.rb:95:in `send'
from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/association_proxy.rb:95:in `interpolate_sql'
from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/has_many_association.rb:143:in `construct_sql'
from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/has_many_association.rb:6:in `initialize'
from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations.rb:1032:in `new'
from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations.rb:1032:in `tickets'
from (irb):1
También probé este finder_sql (con comillas dobles alrededor del inicio de sesión):
:finder_sql => 'select t.* from tickets t where t.user_login="#{login}"'
Pero no de la misma manera (y de todos modos , si funciona, sería vulnerable a la inyección sql).
En una base de datos de prueba, he añadido una columna user_id en la tabla de entradas y probamos este finder_sql:
:finder_sql => 'select t.* from tickets t where t.user_login=#{id}'
Ahora bien, esto funciona bien. Entonces, aparentemente, mi problema tiene que ver con el hecho de que la columna de usuarios que trato de usar es una cadena, no una identificación.
He buscado en la red durante bastante tiempo ... pero no pude encontrar una pista.
Me gustaría ser capaz de pasar cualquier parámetro a la finder_sql, y escribir cosas como esta:
has_many :tickets_since_subscription,
:finder_sql => ['select t.* from tickets t where t.user_login=?'+
' and t.created_at>=?', '#{login}', '#{subscription_date}']
Editar: no puedo usar el: parámetro foreign_key de la asociación has_many porque mi tabla de usuarios hace tienen una columna de clave principal de identificación, que se utiliza en otro lugar de la aplicación.
Edición # 2: aparentemente no leí la documentación lo suficiente: la asociación has_many puede tomar un parámetro: primary_key, para especificar qué columna es la clave primaria local (identificación predeterminada). ¡Gracias Daniel por abrir mis ojos! Supongo que responde a mi pregunta original:
has_many tickets, :primary_key="login", :foreign_key="user_login"
Pero aun así, el amor para saber cómo puedo hacer que el has_many: tickets_since_subscription trabajo asociación.
¡Dios mío, no puedo creer que no haya visto esta opción cuando leí los documentos 10 veces! Creo que necesito algunas vacaciones. ¡Muchas gracias! :-) – MiniQuark