rails query left joins inner includes active sql ruby-on-rails ruby activerecord

sql - query - rails joins



Cómo impaciente cargar objetos con una unión personalizada en rieles? (4)

Fondo

Los rieles normales de carga ansiosa de colecciones funcionan así:

Person.find(:all, :include=>:companies)

Esto genera algunos sql que hace

LEFT OUTER JOIN companies ON people.company_id = companies.id

Pregunta

Sin embargo, necesito una unión personalizada (esto también podría surgir si estuviera usando find_by_sql ) entonces no puedo usar el vainilla :include => :companies

La combinación personalizada / sql me proporcionará todos los datos que necesito, pero ¿cómo puedo decirle a activerecord que pertenece a los objetos asociados de la Company lugar de ser un montón de filas adicionales?

Actualizar

Necesito poner condiciones adicionales en la unión. Algo como esto:

SELECT blah blah blah LEFT OUTER JOIN companies ON people.company_id = companies.id AND people.magical_flag IS NULL <Several other joins> WHERE blahblahblah


¿No puede agregar las condiciones de unión usando ActiveRecord?

Por ejemplo, tengo una consulta bastante compleja que usa varios registros dependientes y funciona bien al combinar condiciones e incluir directivas

Contractors.find( :all, :include => {:council_areas => :suburbs}, :conditions => ["suburbs.postcode = ?", customer.postcode] )

Asumiendo que:

  1. Contratistas have_many CouncilAreas
  2. CouncilAreas have_many Suburbs

Esta unión devuelve los Contratistas en el suburbio identificado por customer.postcode .

La consulta generada se ve así:

SELECT contractors.*, council_areas.*, suburbs.* FROM `contractors` LEFT OUTER JOIN `contractors_council_areas` ON `contractors_council_areas`.contractor_id = `contractors`.id LEFT OUTER JOIN `council_areas` ON `council_areas`.id = `contractors_council_areas`.council_area_id LEFT OUTER JOIN `council_areas_suburbs` ON `council_areas_suburbs`.council_area_id = `council_areas`.id LEFT OUTER JOIN `suburbs` ON `suburbs`.id = `council_areas_suburbs`.suburb_id WHERE (suburbs.postcode = ''5000'')

(Nota: edité la lista de columnas para abreviar).


¿Puedes elaborar un poco más sobre lo que estás tratando de lograr con esta consulta?

También eche un vistazo a la opción: join para encontrar. Le permite especificar cómo quiere que se unan las tablas. Texto del enlace

Y tenga cuidado al usar: incluir, el comportamiento cambia un poco en Rails 2.1 y puede causar algunos problemas cuando se usa junto con una opción: conditions que hace referencia a una tabla incluida. el texto del enlace y el texto del enlace son dos artículos de Pivotal que mencionan este gotcha.


No estoy seguro de que sea lo que quieres (no estoy 100% seguro de haber entendido tu pregunta y lo que quieres lograr) pero:

¿Qué hay de proporcionar tanto :joins como :includes ?

Person.find( :all, :joins => ''LEFT OUTER JOIN companies ON people.company_id = companies.id AND _pass_custom_conditions_here_'', :includes => :companies )

O AR3 manera:

Person.includes(:companies).joins(''LEFT OUTER JOIN companies ON people.company_id = companies.id AND _pass_custom_conditions_here_'')


Puede usar algo como lo siguiente para obtener la magia sintáctica de combinación externa izquierda apropiada.

Person.reflect_on_association(:companies).options[:conditions] = ''people.magical_flag IS NULL''