2011-02-06 10 views
5

Szukam odpowiedzi, która zwróci tablicę obiektów użytkownika za pośrednictwem (najlepiej) named_scope lub metodą klasy na modelu użytkownika, który wykonuje pewne manipulacje.Zwracanie tablicy obiektów za pośrednictwem named_scope - has_many ... belongs_to association; UNION ALL zapytanie

Więc bez zbędnych ceregieli ...

Mam dwie tabele: użytkowników i walki.

  • Użytkownik ma wiele walk (HAS_MANY: walkach: foreign_key => 'challenger_id lub challengee_id')
  • Walka należący do użytkownika (belongs_to: Challenger: class_name => 'User' ... belongs_to: challengee ,: class_name => 'User')

Walka ma następujące kolumny dotyczą:

  • challenger_id (user_id FK)
  • CHALL engee_id (user_id FK)
  • challenger_won (Boolean)

Jak widać, użytkownik może być challenger lub challengee, ale nie jednocześnie.

  • Jeśli użytkownik jest pretendentem i challenger_won = true, oznacza to wygraną.
  • Jeśli użytkownik jest challenge i challenger_won = false, oznacza to wygraną.
  • Jeśli challenger_won = null, po prostu zignoruj ​​to.

Mam surowego SQL, która zwraca atrybut fighter (user_id) spis większości wygrywa atrybutów:

SELECT a.fighter, COUNT(*) AS wins 
    FROM (SELECT challenger_id AS fighter 
      FROM fights 
     WHERE challenger_won = TRUE 
     UNION ALL 
     SELECT challengee_id AS fighter 
      FROM fights 
     WHERE challenger_won = FALSE 
     ) AS a 
GROUP BY a.fighter; 

Więc biorąc pod uwagę te informacje, w jaki sposób mogę zwrócić tablicę obiektów użytkowników poprzez (korzystnie) named_scope lub metodą klasy w modelu User, która wykonuje pewne manipulacje?

+0

rozważyć zmianę 'challenger_won' kolumna w tabeli' fights', do 'winner_id' (user_id FK), które uczynią stwierdzenie wygrywa wiele czystsze . Mógłbyś wtedy mieć 'has_many: wins,: class_name => 'Fight',: foreign_key => 'winner_id'' który pozwoli ci na zrobienie' user.wins.count' aby znaleźć całkowite wygrane – joshnuss

Odpowiedz

4

Myślę, że można spróbować coś takiego odtworzyć wyniku kwerendy:

class User 
    named_scope :winners, 
     :select => 'users.*, COUNT(fight.id) AS wins', 
     :join => :fights, 
     :conditions => ['(fights.challenger_id = user_id AND fights.challenger_won = TRUE) OR (fights.challengee_id = user_id AND NOT fights.challenger_won = FALSE)'] 
     :group => 'user_id' 
end 

Jednak dla puposes buforowania, warto rozważyć dodanie pola win_count do modelu użytkownika. Jeśli utworzysz metodę ustawiającą dla zwycięzcy walki, możesz zwiększyć wartość win_count dokładnie w tym momencie, kiedy się zmieni.

+0

ahh, zgadza się! nie mogę uwierzyć, że nie myślałem o dodaniu przeciwwskazań do modelu użytkownika ... to zdecydowanie najlepsze podejście ... dzięki – keruilin

0

Albo, bez sprzężenia (mysql specyficzny)

class User 
    named_scope :winners, 
    :select => 'if(challenger_won = FALSE,challenger,challengee) as winner,COUNT(id) AS wins ', 
    :group => 'user_id' 
end 
Powiązane problemy