Pergunta

Este é o meu primeiro post sobre Pilha, por isso, tenha comigo se eu violar qualquer protocolo.

Eu estou trabalhando em um projeto no Rails (2.1.2), e eu tenho um cenário de relações que se parece com isso:

event [has_many] days

Pessoas (em diferentes categorias) pode se inscrever para os dias do evento, dando os resultados seguinte ligação:

category [has_many] customers [has_many] orders [has_many] days  
[belongs_to] event

Agora, eu gostaria de ter o número total de 'eventos' para um cliente, ou para todos os clientes em uma determinada categoria, e eu estou preso. AFAIK, não há nenhuma maneira de realizar um simples 'encontrar' através de um conjunto de objetos, correto? Então, qual seria a solução; loops aninhados, e um método de coleta para obter os 'eventos' dos 'dias' em ordens?

Por favor, deixe-me saber se eu sou claro.

Obrigado por sua ajuda!

Foi útil?

Solução

Eu pessoalmente fazer isso usando uma instrução MySQL. Eu não sei ao certo, mas acho que é muito mais rápido, em seguida, os outros exemplos (usando os trilhos fornecidos métodos de associação).

Isso significa que, no modelo cliente que você poderia fazer algo como: (Note que eu estou supondo que você está usando as teclas de associação padrão: '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 irá retornar todos os eventos associados com o usuário, e não duplicado (a palavra-chave 'DISTINCT' faz certeza disso). Você irá, como com o exemplo acima, a informação perde sobre o que dias exatamente o usuário se inscreveu. Se você precisar essa informação, por favor, que o diga.

Além disso, eu não incluí um exemplo para o seu modelo Categoria, porque eu achei que você poderia adaptar o meu exemplo si mesmo. Se não, é só me avisar.

EDIT:

Acabei de ler você quer apenas contar os eventos. Isso pode ser feito ainda mais rápido (ou pelo menos, menos memória intensivo) usando a instrução contagem. Para usar isso, basta usar a seguinte função:

def event_count
  Event.count_by_sql(SELECT DISTINCT COUNT(e.*) FROM ... ... ...
end

Outras dicas

Seus modelos provavelmente parecido com este:

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

Com isso, você pode contar eventos para o cliente:

events = customer.days.count(:group => 'event_id')

Ele irá retornar OrderedHash assim:

#<OrderedHash {1=>5, 2=>13, 3=>0}>

Você pode obter eventos contam por:

events[event_id]

events[1] # => 5
events[2] # => 13
etc.

Se você quiser número total de eventos uniq:

events.size # => 3

Em caso de eventos de contagem para todos os clientes na categoria que eu faria algo assim:

events = {}
category.customers.each {|c| events.merge!(c.days.count(:group => 'event_id') ) }
events.size # => 9 - it should be total number of events

Mas neste caso você informações perder quantas vezes cada evento apareceu.

Eu não testei isso, então pode haver alguns erros.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top