当前位置:  开发笔记 > 后端 > 正文

是否可以使ActiveRecord为使用:join连接选项加载的行创建对象?

如何解决《是否可以使ActiveRecord为使用:join连接选项加载的行创建对象?》经验,为你挑选了1个好方法。

我需要做这样的事情

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?



1> vladr..:

首先,您应该使用: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')

这最终将检索您ActiveRecords在一个单一的,简单的 SQL语句.

推荐阅读
360691894_8a5c48
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有