我需要做这样的事情
class User < ActiveRecord::Base
has_many :abuse_reports
end
class AbuseReport < ActiveRecord::Base
belongs_to :abuser, :class_name => 'User', :foreign_key => 'abuser_id'
belongs_to :game
end
class Game < ActiveRecord::Base
has_many :abuse_reports
end
@top_abusers = User.page(params[:page],
:joins => [
'JOIN abuse_reports ON users.id = abuse_reports.abuser_id',
'JOIN games ON games.id = abuse_reports.game_id'
],
:group => 'users.id',
:select => 'users.*, count(distinct games.id) AS game_count, count(abuse_reports.id) as abuse_report_count',
:order => 'game_count DESC, abuse_report_count DESC'
)
这可行,但不会为AbuseReports或Games创建对象 - 它只返回一堆行。当我从视图中引用这些对象时,它会再次加载它们。有没有办法来解决这个问题?或者某种方式来获得这种行为而不使用:join?
答案 0 :(得分:11)
首先,您应该使用:include而不是:join
User.find(:all, :include => { :abuse_reports => [ :game ] }, :order => )
或者,在您的情况下,请尝试
User.page(params[:page], :include => { :abuse_reports => [ :game ] })
这将为您执行连接和一次性检索记录。
现在,这可能会多次为您检索给定的游戏记录(如果同一游戏通过多个报告与用户绑定。)如果您的游戏记录很大,您可以减少应用和应用之间交换的数据量。 RDBMS如下:
class User < ActiveRecord::Base
has_many :abuse_reports
has_many :abused_games, :through => :abuse_reports
end
...
User.find(:all, :include => [ :abuse_reports, :abused_games ])
最后,您还需要检索计数并进行相应的排序。查看http://railscasts.com/episodes/23了解如何将计数器缓存添加到实际活动记录中(计数器缓存简化了SQL并使RDBMS的生活更轻松,查询运行更快)。设置计数器缓存后,您最终可以更改以上内容:
User.find(:all, :include => [ :abuse_reports, :abused_games ], :order => 'users.abused_games_count DESC, users.abuse_reports_count DESC')
这将最终在一个单,简单 SQL语句中检索您的ActiveRecords。
答案 1 :(得分:3)
您遇到的问题是您使用的ActiveRecord并非“假设”使用。我的意思是你正在编写自己的sql,这使得AR放弃了对你的全部控制。
如果您希望AR处理所有内容,您应该尝试使用少量自己的SQL。看起来您想知道哪个用户具有最高数量的AbuseReports。尝试这样的事情:
some_user.abuse_reports.count
获取abuse_reports的计数