【问题标题】:Is there a better way to do this find in ruby有没有更好的方法来做到这一点在红宝石中找到
【发布时间】:2012-06-19 13:04:23
【问题描述】:

好的,我有这个助手

def playlist_count(user, site_id)
  user.companies.local(site_id).map(&:playlists).flatten.count
end

这将返回所有公司的播放列表计数

class Playlist < ActiveRecord::Base
  belongs_to :company
  scope :active, where('end_date >= ? AND player_id IS NOT NULL', Date.today)

class Company < ActiveRecord::Base
  has_many :playlists, :dependent => :destroy
  scope :local, lambda{ |site_id| where(:site_id => site_id) }

问题是助手变得丑陋,另一个问题是我需要活动播放列表(由我在播放列表模型中的范围定义)

有没有办法清理我的助手或使用范围来获取所有用户公司的活动播放列表计数

【问题讨论】:

  • 您应该将活动范围参数包装在 lambda 中,以便在任何时候调用范围时都会评估 Date.today。 scope :active, lambda { where(...) }

标签: ruby-on-rails ruby ruby-on-rails-3 scope


【解决方案1】:

你可以反过来运行查询:

Playlist.active.where(:company_id => user.companies.local(site_id)).count

【讨论】:

  • 是否 :company_id => user.companies.local(site_id) 产生 SQL in 子句,因为返回的记录不止一条
  • 是的,它会产生类似SELECT COUNT(*) FROM playlist WHERE playlist.company_id IN (SELECT company.id FROM company WHERE …)
  • 啊,这个明显比我的好。
【解决方案2】:

您可以将范围应用于关联。试试这个:

user.companies.local(site_id).map { |company| company.playlists.active.count }.sum

另一个优点是它会执行select count(*) ... SQL 语句,而不是从数据库中获取所有活动的播放列表并在 Ruby 中计算它们。

如果您关心性能,那么在单个 SQL 语句中加入表并计算所有用户公司的活动播放列表会更有效,而不是遍历公司并为每个公司进行计数查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    • 1970-01-01
    • 2016-02-15
    相关资源
    最近更新 更多