The short answer is:
Game.find(:all, :include => :players, :group => 'players.game_id',
:select => "games.*, COUNT(players.id) AS players_count",
:conditions => "players_count < games.num_players"
)
However that's not very DRY. You might find it easier in the long run to set that relationship up with a counter cache. See this railscast for more detailed info on the how and why.
To setting up the counter cache is a simple three step process.
- Add a players_count integer column to Game.
- Update players_count for all your existing game records.
- Add
:counter_cache => true
to the belongs_to :game
declaration.
Then to find all open games:
Game.find(:all, :conditions => "games.players_count < games.num_players")
Bonus points for making that a named scope:
class Game < ActiveRecord::Base
has_many :players
named_scope :open, :conditions => "games.players_count < games.num_players"
named_scope :type, lambda {|type|
{:conditions => {:type => type}}
}
named_scope :baseball, :conditions => {:type => "baseball"}
end
Game.open # => Returns all open games.
Game.baseball.open # => Returns all open baseball games.
Game.open.type("football") # => Returns all open foot ball games.