2010-03-20 3 views
1

У меня есть три модели: User, RaceWeek, Race.Rails Association Вопрос

Текущие ассоциации:

class User < ActiveRecord::Base 
    has_many :race_weeks 
end 

class RaceWeek < ActiveRecord::Base 
    belongs_to :user 
    has_many :races 
end 

class Race < ActiveRecord::Base 
    belongs_to :race_week 
end 

user_id Так что является внешним ключом в RaceWeek и race_week_id является внешним ключом в гонке.

fastest_time является признаком модели Race.

ВОПРОС: Каков оптимальный способ получить список пользователей, у которых есть самые быстрые гонки в X?

+0

Пожалуйста, уберите этот вопрос, форматируя его правильно. –

ответ

1

Вы можете сделать это следующим образом:

users = User.all(:limit => X, :joins => {:race_weeks => :races}, :order => "reces.fastest_time DESC").uniq 

Если вы правильно указали has_many :through ассоциации, то вы даже можете сделать это следующим образом:

users = User.all(:limit => X, :joins => :races, :order => "reces.fastest_time DESC").uniq 

В этом решении, вы получите то, что вам хотите с одним запросом, но два соединения. И этот метод uniq не очень хорош, если вы не использовали бы небольшой X.

+0

Как мне изменить это, если бы я хотел включить поля Race в возвращаемый объект User, чтобы я мог получить доступ к самому быстрому? – keruilin

+0

Я думаю, что вам нужно иметь правильные ассоциации в моделях и масштабах с помощью:: order => 'fastest_time DESC''. Но он будет выполнять дополнительные sql-запросы. Затем вы можете получить его так: 'users.each {| a | ставит a.races.fastest.first.fastest_time' – klew

1

Что-то вроде:

races = Race.all(:order => "fastest_time desc", :limit => X, :include => {:race_week => :user}) 
users = races.map{|race| race.race_week.user}.uniq 

Примечание: не проверить это.

+0

Не могли бы вы объяснить, как это: включить работы? Я не совсем уверен, что я получаю то, что: race_week =>: пользователь делает. – keruilin

+0

Кроме того, вы правы, я просто хочу узнать список пользователей с самым быстрым временем гонки X (у Джо может быть 10 самых быстрых раз). Тем не менее, лучшие пользователи X с самым быстрым временем гонки (у Джо есть самое быстрое время, но затем следующие 9 отличных пользователей). – keruilin

+0

include - это в основном просто оптимизация базы данных. Он сообщает ActiveRecord о том, чтобы идти вперед и одновременно получать всех связанных с ним пользователей race_weeks и пользователей. Если вы упустили из: include, он все равно будет работать, просто выполните намного больше запросов. – jrallison

1

Учитывая текущую модель, следует работать.

race_weeks = RaceWeek.find_by_sql(["SELECT user_id FROM race_weeks JOIN races ON races.race_week_id = race_weeks.id ORDER BY races.fastest_time desc LIMIT ?", X) 
users = User.find(race_weeks.collect(&:user_id).uniq) 

Я знаю, что он требует два внешних вид окна, но второй поиск должен быть очень быстро, так как вы только глядя X записи их первичным ключом.

+0

Это вернет лучших пользователей X с самым быстрым временем гонки, не обязательно список пользователей с самым быстрым временем гонки X. – jrallison

+0

Я изменил свой код, чтобы удовлетворить это требование, которое, я думаю, я неправильно понял. –

+0

Ваш лимит по-прежнему ограничивает количество возвращаемых пользователей, не так ли? Это означает, что вы всегда будете возвращать пользователей X. Вопрос о том, как задать вопрос, вы хотите вернуть X быстрее, независимо от того, сколько пользователей получили те самые быстрые времена. И.Е. Пользователь А имеет 10 самых быстрых раз в разы. Если X = 10, вы должны вернуть только одного пользователя. – jrallison