Reputation: 6346
So I'm trying to perform queries on a models great granchildren. The relationship is as so...
Tournament > Competitions > Matches > Players
and the Tournament model:
class Tournament < ActiveRecord::Base
has_many :competitions, :dependent => :destroy
has_many :matches, :through => :competitions
has_many :players, :through => :matches
end
Currently what I have for retrieving all the great great grandchildren records is:
@results = @tournament.competitions.collect{|b| b.matches.collect{|c| c.players.with_win_count}}.flatten
And this works, however the problem is that it returns an array. What I'm trying to do is build a dynamic query based on user input, and the player table is essentially a result pool for all matches and the user has the option to filter only what he wants to see. What I have in the end is a fairly potentially complex (depending on user input) query and the additional where clauses cannot be performed on an array. To give you a better idea of how this is meant to work, here is my code...
def results
@tournament = Tournament.find(params[:id])
@results = @tournament.all_great_grandchildren
@results.where(params[:player_condition1]) if params[:player_condition1]
@results.where(params[:player_condition2]) if params[:player_condition2]
@results.where(params[:player_condition3]) if params[:player_condition3]
if params[:match_condition]
#Join to match table so we can query the match fields
@results.join(:match)
@results.where(params[:match_condition])
end
....
@results.order(params[:order]) if params[:order]
end
Is there a way to find all of the great grandchildren (player) records for any given tournament without an array so I can continue to condition the records?
Upvotes: 4
Views: 1546
Reputation: 76
Chamnap has got it. The reason we define “has_many” and “belongs_to” associations in models is to give us easy access to the association models.
So when you have a Tournament object called tournament, you can do
competitions = tournament.competitions
matches = tournament.matches
players = tounaments.players
You can also go in the reverse direction, starting with a player object. Ex: matches = player.matches
With Active Record you shouldn't have to do manual joins or raw SQL model calls when dealing with associations. Have a quick read of the Actice Records Associations guide:
http://guides.rubyonrails.org/association_basics.html
Upvotes: 1
Reputation: 4766
I think you should just call @tournament.players
will work out of the box if you have setup with the above associations.
Upvotes: 8