seleccione muchos a través de muchos ... tipo de
-
21-08-2019 - |
Pregunta
Este es mi primer post en la pila, así que por favor tengan paciencia conmigo si yo viole cualquier protocolo.
Estoy trabajando en un proyecto en Rails (2.1.2), y tengo un escenario de relaciones que tiene este aspecto:
event [has_many] days
La gente (en diferentes categorías) pueden inscribirse para los días del evento, dando los siguientes resultados de unión:
category [has_many] customers [has_many] orders [has_many] days
[belongs_to] event
Ahora, me gustaría tener el número total de 'eventos' para un cliente, o para todos los clientes de una determinada categoría, y estoy atascado. Que yo sepa, no hay manera de llevar a cabo un simple 'encontrar' a través de una matriz de objetos, correcto? Así que, ¿cuál sería la solución; bucles anidados, y un método de cobro para obtener los 'eventos' de los 'días' en los pedidos?
Por favor, hágamelo saber si soy claro.
Gracias por su ayuda!
Solución
Yo personalmente hacer esto utilizando una sentencia MySQL. No sé a ciencia cierta, pero creo que es mucho más rápido que los otros ejemplos (utilizando los carriles previstos métodos de asociación).
Esto significa que en el modelo de atención al cliente que podría hacer algo como: (Tenga en cuenta que estoy asumiendo que usted está utilizando las claves de asociación por defecto: 'model_name_id')
class Customer
def events
Event.find_by_sql("SELECT DISTINCT e.* FROM events e, days d, orders o, customers c WHERE c.id=o.customer_id AND o.id=d.order_id AND e.id=d.event_id")
end
end
que devolverá todos los eventos asociados con el usuario, y no hay duplicados (la palabra clave "DISTINCT se asegura de que). Usted, al igual que con el ejemplo anterior, perderá la información sobre qué días exactamente el usuario se inscribieron para. Si necesita esa información, por favor decirlo.
Además, no he incluido un ejemplo para su modelo Categoría, porque asumí que podría adaptar mi ejemplo usted mismo. Si no es así, házmelo saber.
EDIT:
acabo de leer lo que desea es contar los acontecimientos. Eso se puede hacer aún más rápido (o al menos, menos intensivo de memoria) mediante la instrucción de conteo. Para utilizar eso, sólo tiene que utilizar la siguiente función:
def event_count
Event.count_by_sql(SELECT DISTINCT COUNT(e.*) FROM ... ... ...
end
Otros consejos
Sus modelos, probablemente, este aspecto:
class Category
has_many :customers
class Customer
has_many :orders
has_many :days, :through => :orders # I added this
belongs_to :category
class Order
has_many :days
belongs_to :customer
class Day
belongs_to :event
belongs_to :order
class Event
has_many :days
Con esto se puede contar eventos para el cliente:
events = customer.days.count(:group => 'event_id')
Se volverá OrderedHash como esto:
#<OrderedHash {1=>5, 2=>13, 3=>0}>
Puede obtener eventos cuentan por:
events[event_id]
events[1] # => 5
events[2] # => 13
etc.
Si desea número total de eventos uniq:
events.size # => 3
En caso de contar eventos para todos los clientes en la categoría que me gustaría hacer algo como esto:
events = {}
category.customers.each {|c| events.merge!(c.days.count(:group => 'event_id') ) }
events.size # => 9 - it should be total number of events
Pero en este caso se pierde la información cuántas veces aparecía cada evento.
no he probado esto, así que podría haber algunos errores.