更改范围以使用sql

时间:2015-07-31 15:32:48

标签: ruby-on-rails ruby activerecord model

我有两个ruby范围,但它们并没有完全使用activecord。如何将其更改为仅使用activerecord或sql?

article.rb

class Article < Comfy::Cms::Page
  has_many :view_mappings
  has_many :favorite_mappings
  scope :top_by_number_of_favorites, -> { article.sort_by(&:favorite_score).take(10) }

  scope :top_by_number_of_views, -> { article.sort_by(&:view_score).take(10) }

  def favorite_score
    favorite_mappings.since(2.weeks.ago).count * 5
  end

  def view_score
    view_mappings.since(2.weeks.ago).count
  end

schema.rb

  create_table "view_mappings", force: :cascade do |t|
    t.integer  "article_id"
    t.date     "date_viewed"
    t.string   "device_id"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
  end

  create_table "favorite_mappings", force: :cascade do |t|
    t.integer  "article_id"
    t.string   "device_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.date     "date_liked"
  end

2 个答案:

答案 0 :(得分:2)

试试这个:

class Article < Comfy::Cms::Page
  has_many :favorite_mappings
  has_many :view_mappings

  def self.top_by_number_of_favorites(since = 2.weeks.ago, amount = 10)
    with_favorite_score
      .where('date_liked >= ?', since)
      .order('favorite_score DESC')
      .limit(amount)
  end

  def self.top_by_number_of_views(since = 2.weeks.ago, amount = 10)
    with_view_score
      .where('date_viewed >= ?', since)
      .order('view_score DESC')
      .limit(amount)
  end

  def self.with_favorite_score
    joins(:favorite_mappings)
      .select('articles.*, COUNT(favorite_mappings.id) AS favorite_score')
      .group(:id)
  end

  def self.with_view_score
    joins(:view_mappings)
      .select('articles.*, COUNT(view_mappings.id) AS view_score')
      .group(:id)
  end
end

我也做了这个,所以你可以改变回顾日期,所以不是2周,你可以从上个月,一年或任何任意日期获得最热门的文章。现在限制也是可以更改的,因此您可以获得前20个,50个,100个等。您还可以像@articles.top_by_number_of_views.first.view_score一样访问favorite_score / view_score。

答案 1 :(得分:1)

你应该使用一些SQL魔法:

  scope :top_by_number_of_favorites, -> {
    joins(:favorite_mappings).
    where("date_liked >= ?", 2.weeks.ago).
    group(:id).
    select("comfy_cms_pages.*, COUNT(*) AS favorite_score").
    order("favorite_score DESC").
    limit(10)
  }

前两行 - 我们将favorite_mappings加入查询结果,只选择2周或更新的。然后我们按照arcticle ID对结果进行分组,指定我们要选择COUNT个喜欢。然后我们只是从上到下排序,并记录前10条记录。

有关范围的更多信息:

http://guides.rubyonrails.org/active_record_querying.html#scopes

有关聚合函数的更多信息:

https://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html http://www.postgresql.org/docs/9.1/static/functions-aggregate.html

请注意,您将获得分数的文章[&#39; favorite_score&#39;]。此外,您的代码可以使用文章的所有其他字段,因为我们在要选择的字段列表中指定了*