ruby-on-rails-4 - rails - scaffold ror
Consulta ActiveRecord a travĂ©s de mĂșltiples uniones (4)
Asumiendo managers
es un nombre modelo
managers.find(:all,
:joins=>" JOIN stores ON stores.manager_id = managers.id
JOIN regions ON stores.region_id = regions.id
JOIN readings ON readings.region_number = regions.number"
:conditions=>"manager.name = ''John Smith'' AND regions.number = ''1234567''"
:limit=>100)
Tengo un esquema como este.
managers
has_many :emails
has_many :stores
emails
belongs_to :manager
stores
belongs_to :manager
belongs_to :region
regions
has_many :stores
has_many :readings
readings
belongs_to :regions
Quiero obtener lecturas para un gerente. En SQL haría algo como esto.
SELECT * FROM managers
JOIN stores ON stores.manager_id = managers.id
JOIN regions ON stores.region_id = regions.id
JOIN readings ON readings.region_number = regions.number
WHERE
manager.name = ''John Smith''
AND
regions.number = ''1234567''
LIMIT 100
No puedo averiguar cómo hacer esto en activerecord. He estado tratando de darle sentido a http://guides.rubyonrails.org/active_record_querying.html y http://guides.rubyonrails.org/association_basics.html pero no se está hundiendo. Creo que solo necesito verlo desde Un punto de vista diferente.
Estaba pensando que estaría accediendo a los datos de esta manera pero creo que simplemente no entiendo cómo funciona.
managers.name
managers.stores.name
managers.stores.regions.readings.limit(10)
He estado teniendo que hacer algo como esto que es mucho más feo.
managers.first.stores.first.regions.first.readings.limit(10)
Considere los siguientes modelos (y el uso de has_many a través):
class Reading < ActiveRecord::Base
belongs_to :region,
inverse_of: :readings
end
class Region < ActiveRecord::Base
has_many :readings,
inverse_of: :region
has_many :stores,
inverse_of: :region
end
class Store < ActiveRecord::Base
belongs_to :region,
inverse_of: :stores
belongs_to :manager,
inverse_of: :stores
end
class Manager < ActiveRecord::Base
has_many :stores,
inverse_of: :region
has_many :emails,
inverse_of: :manager
has_many :regions,
through: :stores
has_many :readings,
through: :regions
end
class Email < ActiveRecord::Base
belongs_to :manager,
inverse_of: :emails
end
Ahora su pregunta es un poco ambigua porque dice que desea obtener lecturas para un administrador, pero su SQL no selecciona las lecturas en absoluto y también prescribe una región.
Suponiendo que desea que todas las Lecturas coincidan con un Administrador y una Región dados:
@readings = Reading.joins(region: { stores: :manager }).where(
manager: { name: ''John Smith'' },
region: { id: 1234567 })
Suponiendo que también desea cargar regiones, almacenes y administradores para evitar las consultas 1 + N:
@readings = Reading.includes(region: { stores: :manager }).where(
manager: { name: ''John Smith'' },
region: { id: 1234567 })
Suponiendo que tenga un nombre de administrador y desee tanto sus detalles como sus lecturas:
@manager = Manager.where(name: ''John Smith'').first!
@readings = manager.readings
Todos los ejemplos de consulta anteriores devuelven ActiveRecord::Relation
''s, que puede encadenarse aún más where
condiciones, o las joins
, el limit
, el group
, el having
y el order
etc.
También debe considerar las diferencias de los métodos de eager_load
, eager_load
, preload
, eager_load
y references
. Aquí hay un resumen sobre ellos here también lo alentaría a leer documentos, guías y blogs sobre Arel, ya que también es compatible con las uniones y los alias.
Después de usar ActiveRecord en ira por un tiempo, he llegado a la conclusión de que Sequel / SequelModel es un DB / ORM mucho mejor que ActiveRecord. No hay falta de respeto a los desarrolladores, pero he encontrado que Sequel es una mejor herramienta. Arel tiene poca documentación desde hace años y ActiveRecord / Arel tiene fallas en varias áreas, como condiciones de unión, control de tipos de unión y carga impaciente, uniones, intersecciones, consultas recursivas, árboles / listas de adyacencia y muchas otras características de SQL que Secuela cubre
Como parece que recién está comenzando con AR, tal vez desee comenzar con Sequel en lugar de luchar con las debilidades y las frustraciones de las consultas de ActiveRecord, incluido el uso inconexo de AR y Arel, Relaciones vs Asociaciones y rarezas en la composición de consultas, continúa y en. No hay nada más frustrante que saber el SQL que desea, pero ActiveRecord / Arel conspiran para detenerlo, por lo que se ven obligados a usar la ruta de escape promocionada y ''solo use el fragmento de cadena SQL'' y obtiene un resultado que no se puede encadenar , pero el resto de tu código espera una relación! (por ejemplo, resultados paginados)
Quería comentar sobre el comentario del usuario1757006 del 4 de octubre de 13 a las 14:39 , pero no tengo suficientes puntos. De todos modos, esto aborda escenarios de anidación más profundos. He agregado modelos de planetas y países para mostrar cómo funciona la sintaxis cuando se necesitan encadenar modelos adicionales.
@readings = Reading.includes(planet: [ country: [ region: [ {stores:
:manager}]]]).where(
manager: { name: ''John Smith'' },
region: {id: 1234567 })
prueba algo como esto:
managers.joins(stores: {regions: :readings}).where(''managers.name = ? AND regions.number = ?'', ''John Smith'', ''1234567'').limit(100)