ruby-on-rails - Ruby:将数组或哈希转换为 activerecord 关系

标签 ruby-on-rails ruby activerecord

我正在尝试将哈希转换为事件记录关系,但无法做到这一点。我打算使用activerecord关系来排序然后过滤Category表。最终目标是创建一个实例方法来过滤前 5 个访问过的类别,然后我可以在 Controller 中使用/调用该类别。这就是我的想法:

类别模型:

def top_5_visited
        Article.joins(:categories).group('categories.name').sum(:impressions_count)
// Add sort
// Limit to top 5 
end

类别 Controller :

@categories = Category.top_5 visited

哈希 {"Simula"=>7, "Haskell"=>5, "JavaScript"=>10, "C#"=>112} 将是通过以下查询创建:

total_count = Article.joins(:categories).group('categories.name').sum(:impressions_count)

我还尝试使用 sort_by 方法将其转换为数组:

total_count_sorted = total_count.sort_by {|_key, value| value}

我用谷歌搜索了“将数组转换为activerecord关系”并引用了this发布,但测试这个:

Category.where(id: total_count_sort.map(&:id))

在 Rails 控制台中,出现此错误:

NoMethodError: undefined method id for ["Simula", 7]:Array

最佳答案

您想要执行的操作从相反的一端(类别)开始,并在 ORDER 子句中使用聚合。

Category.joins(:articles)
        .order('SUM(articles.impressions_count) DESC')
        .group(:id)
        .limit(5)

irb(main):005:0> Category.joins(:articles).order("SUM(articles.impressions_count) DESC").group('categories.id').limit(5)
  Category Load (1.5ms)  SELECT  "categories".* FROM "categories" INNER JOIN "articles" ON "articles"."category_id" = "categories"."id" GROUP BY categories.id ORDER BY SUM(articles.impressions_count) DESC LIMIT $1  [["LIMIT", 5]]
=> #<ActiveRecord::Relation [#<Category id: 4, name: "C#", created_at: "2017-11-15 15:06:32", updated_at: "2017-11-15 15:06:32">, #<Category id: 3, name: "JavaScript", created_at: "2017-11-15 15:06:32", updated_at: "2017-11-15 15:06:32">, #<Category id: 1, name: "Simula", created_at: "2017-11-15 15:03:37", updated_at: "2017-11-15 15:03:37">, #<Category id: 2, name: "Haskell", created_at: "2017-11-15 15:06:32", updated_at: "2017-11-15 15:06:32">]>

您应该创建一个类方法 - 而不是实例方法,因为这基本上只是一个范围,调用实例没有意义。

class Category < ApplicationRecord
  has_many :articles

  def self.order_by_article_impressions
    self.joins(:articles)
        .order('SUM(articles.impressions_count)')
        .group(:id)
  end

  def self.top_5_visited
    order_by_article_impressions.limit(5)
  end

  # Or use `scope` which is just syntactic sugar
  scope(:top_5_visited) -> { order_by_article_impressions.limit(5) }
end

关于ruby-on-rails - Ruby:将数组或哈希转换为 activerecord 关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47310114/

相关文章:

ruby-on-rails - Ruby on Rails 标签与 HTML 标签

html - 设置 bxSlider 幻灯片放映哪里出错了?

ruby-on-rails - 新分配的序列不起作用

ruby-on-rails - 使用未保存的关联

mysql - 将 ruby​​ on rails 应用程序的数据库从 sql server 转换为 mysql

ruby-on-rails - 无法提取 RVM 源

ruby-on-rails - 如何从 Ruby 与 CalDAV 服务器交互?

ruby - 使用 tiny_TDS : [BUG] Segmentation fault 在 rails 中连接到 SQL-Azure

ruby-on-rails - cucumber 显示页面未显示页面(解决方案: it was on the wrong line)

ruby-on-rails - 以其他方式创建记录时,Rails 关联回调未运行