如何在Ruby on Rails上创建“数据透视表”?

时间:2014-01-18 09:36:06

标签: ruby-on-rails

首先,我想提及我对Ruby和Rails的全新,我是在我学习的第一天,所以如果我看起来有点不清楚或太宽,我会道歉我的问题。

我试图做一些简单的事情(我想?),这是为了转动一张桌子。

我有一个看起来像这样的表:

----------------------------------
| Name     | Product ID | Amount |
|----------|----------------------
| Robert   |     P1     |   2    |
| Michael  |     P2     |   1    |
| Leonard  |     P2     |   1    |
| Robert   |     P2     |   4    |
| Robert   |     P3     |   2    |
| Michael  |     P3     |   1    |
----------------------------------

...我想把它变成这样的东西:

---------------------------
| Name     | P1 | P2 | P3 |
---------------------------
| Robert   | 2  | 4  | 2  |
| Michael  | -  | 1  | 1  |
| Leonard  | -  | 1  | -  |
---------------------------

我不太清楚如何实现这一目标。我环顾四周,找不到任何与我问题有关的内容。

我发现了一个名为pivot_table的gem,可以在这里找到:https://github.com/edjames/pivot_table但我不知道如何完全使用它。它有一个小指南,但我不知道在哪里放置代码。

非常感谢任何帮助。

谢谢。

3 个答案:

答案 0 :(得分:6)

看着你的表和你正在寻找的结果,我会这样做(我假设它是一张订单表?)

result = []
Order.all.group_by(&:name).each do |name, orders|
  record = {}
  record["name"] = name
  orders.each do |order|
    record[order.product_id] = order.amount
  end
  result.append(record)
end 

我希望这会给你一个很好的起点!

答案 1 :(得分:5)

首先安装gem

# In your Gemfile
gem 'pivot_table'

然后在您的终端中,运行

bundle install

假设您的第一个表格所代表的模型为Sale

sales = Sale.all
grid = PivotTable::Grid.new do |g|
  g.source_data  = sales
  g.column_name  = :product_id
  g.row_name     = :name
end

然后您可以使用文档中列出的其他方法。例如

g.column_headers # ['P1', 'P2', 'P3']

注意:这只是阅读您链接的GitHub页面。我从未使用过宝石。

编辑:

您可以将代码放在模块中:

# lib/PivotTable
module PivotTable
  def grid(data, options = {})
    grid = PivotTable::Grid.new do |g|
      g.source_data = data
      g.column_name = options[:column_name]
      g.row_name = options[:row_name]
    end
  end
end

然后你会用其他地方用

来调用它
include PivotTable

def my_method
  sales = Sale.all
  grid = grid(sales, { :row_name => :name, :column_name => :product_id })
  # do stuff
end

通过这种方式,您可以重用网格生成代码并使用任意参数调用它。

答案 2 :(得分:0)

这是一个通用的解决方案,我在application_helper.rb

中实现了
def pivot_table row_model, column_model, pivot_model, pivot_attribute
  row_model.all.map do |r|
    column_model.select(:id).sort.map do |c|
      pivot_model.find_by(
        row_model.to_s.downcase => r,
        column_model.to_s.downcase => c
      )&.public_send(pivot_attribute) || 0
    end
  end
end

前三个参数是大写字母ActiveRecord子类名称,而pivot_attribute(是pivot_model的属性)可以用符号或字符串形式给出。假设pivot_model是一个多对多关系,它引用row_modelcolumn_model作为外键。如果没有很多模型,我猜想某些模型可以在参数之间重复,但是我还没有为此进行厨房测试。

返回值是一个数组数组。