Suma z left joinem

3 modele: User, Bet, Bid. Relacje mniej więcej takie:
User has many bets (created).
User has many bids.
User has many bidded_bets (through: “bids”, source: “bet”) (participated).
Bet has many bids.

A potrzebuję uzyskać sumę obstawień we wszystkich zakładach danego usera (ale tylko zakładach spełniających pewne warunki).
Kombinuję tak:

bidded_bets.visible.bids.sum(:amount)

Czyli:

  • weź wszystkie zakłady usera,
  • odfiltruj tylko spełniające warunki (visible to named scope),
  • weź wszystkie obstawienia tych zakładów,
  • oblicz sumę

Niestety zonk: bidded_bets.visible zwróci kolekcję a .bids operuje na pojedynczym obiekcie i się nie dogadają .
Jak więc to zrobić, żeby efektem było takie zapytanie:

SELECT SUM(amount) AS `total` FROM `bids` AS `bid` LEFT JOIN `bets` ON (`bets`.`id` = `bid`.`bet_id`) WHERE `bid`.`user_id` = '1' AND `bets`.`status` IN ('pending','awaiting','created') 

Proponuje nazwe modelu Bid zastapic Stake lub PlacedBet. Bet a bid to raczej dwie rozne rzeczy.

Może zrobić nowego scopa:

scope :visible_with_bids, joins(:bids) & Bet.visible

Heh, a rozwiązanie jest znacznie prostsze jak się okazuje:

bidded_bets.visible.sum(:amount)

:smiley:
Co prawda wynikowe zapytanie jest nieco inne, bo używa inner join, ale wychodzi na to samo:

SELECT SUM(amount) AS sum_id FROM `bets` INNER JOIN `bids` ON `bets`.`id` = `bids`.`bet_id`) WHERE `bids`.`user_id` = '1' AND (bets.published_at IS NOT NULL and bets.banned = 0)