Suppose I am doing matchmaking of users and games. I have models containing users and games.
class Game < ActiveRecord::Base
has_and_belongs_to_many :users
class User < ActiveRecord::Base
has_and_belongs_to_many :games
Games can have many users, users can be playing many games. Because of HASBM I have a table called games_users too.
I want to search and find games that are waiting for players, which do not also contain the username of the player (i.e. I don't want to add the same player to a game twice...)
I want something like this:
@game = Game.find_by_status(Status::WAITING_USERS, :condition => "game.users.doesnt_contain('username=player')
But I'm not sure how to do it?
Update:
Using jdl's solution, I got the code to run, but get items that I tried to exclude returned in the results. Here's my test code:
logger.debug "Excluding user: #{@user.id}"
games = Game.excluding_user(@user)
if (games != nil && games.count > 0)
@game = Game.find(games[0].id)
games[0].users.each {
|u|
logger.debug "returned game user: #{u.id}"
}
end
(the above code also begs 2 questions.... - how do I get a result of just one game instead of an array, and how to I get a non-readonly version of it; that's why I do the second Game.find...)
And here's the output in the log:
Excluding user: 2
Game Load (0.3ms) SELECT `games`.* FROM `games` left outer join games_users gu on gu.game_id = games.id WHERE (gu.game_id is null or gu.user_id != 2)
Game Columns (1.0ms) SHOW FIELDS FROM `games`
SQL (0.2ms) SELECT count(*) AS count_all FROM `games` left outer join games_users gu on gu.game_id = games.id WHERE (gu.game_id is null or gu.user_id != 2)
Game Load (0.1ms) SELECT * FROM `games` WHERE (`games`.`id` = 3)
games_users Columns (6.8ms) SHOW FIELDS FROM `games_users`
User Load (0.9ms) SELECT * FROM `users` INNER JOIN `games_users` ON `users`.id = `games_users`.user_id WHERE (`games_users`.game_id = 3 )
returned game user: 1
returned game user: 2