在计数中包含嵌套关联属性

时间:2018-01-04 21:40:47

标签: ruby-on-rails activerecord

我的课程看起来像这样:

class Orders < ActiveRecord::Base
  has_many :items
  has_many :types, through: :items
  accepts_nested_attributes_for :items
end

class Item < ActiveRecord::Base
  belongs_to :type
  belongs_to :order
end

class Type < ActiveRecord::Base
  has_many :items
end

订单上有几个项目,这里是概述,项目和类型:

 <Item:0x00007fbcb185c170
   id: 1,
   finish: "Fir",
   size: "38",
   type_id: 8,
   order_id: 1>

 <Type:0x00007fbcace363e8
   id: 8,
   type: "Door",
   name: "Jeldwen Premium Interior">

项目可能具有相同类型但不同的完成和大小属性。我需要从数据库中获取一个订单并以人类可读的格式呈现它们,如下所示:

Order: {
  Types: 
  {
    Name: "Jeldwen Premium Interior",
    Type: "Door",
    Items: 
    {
        finish: "fir",
        size: "36", 
        quanity: "8" # sum of items in the database with same `finish` and `size`
    }, 
    {
        finish: "fir",
        size: "58", 
        quanity: "8" # sum of items in the database with same `finish` and `size`   
    }
}       

我希望能够通过一个db调用获取所有这些信息,并且我在那里得到了一部分,我只是缺少类型名称 -

`Order.where(id: 1).joins(:items).joins(:type).group("items.type_id", "items.size", "items.color").count`

返回type_id,size,finish和quanity:

{[3, "36", "fir"]=>40,
 [3, "48", "fir"]=>36,
 [3, "36", "oak"]=>90,
 [4, "48", "oak"]=>18}

我想将type.nametype.name与计数一起返回,这可能吗?所以一行看起来像:

 ["Jeldwen Premium Interior", "door", 3, "36", "fir"]=>40

1 个答案:

答案 0 :(得分:1)

昨天我遇到了这个问题,最后我使用了find_by_sql

您可以在sql consolefollowing site

中测试sql

您的rails查询

.joins(:items).joins(:type).group("items.type_id", "items.size", "items.color").count

可以用sql完成

SELECT items.type_id, items.size, items.color, types.name, COUNT(types.id) AS NumberOfTypes, COUNT(types.name) AS NumberOfNames FROM items INNER JOIN types on items.id = types.item_id GROUP BY items.type_id, items.size, items.color;

在范围

class Item
    scope :items_count, -> { find_by_sql("SELECT items.type_id, items.size, items.color, types.name, COUNT(types.id) AS NumberOfTypes, COUNT(types.name) AS NumberOfNames FROM items INNER JOIN types on items.id = types.item_id GROUP BY items.type_id, items.size, items.color;") }
end

你可以致电

items = Order.first.items_count

它将返回一个项目数组,不包含count且没有types。类似的东西:

=> [#<Item:0x00564d6bf08c28 id: nil, type: "type1test", size: 133, color: 'blue'>,
#<Item:0x00564d6bef7108 id: nil, type: "type1test", size: 136, color: 'blue'>,
#<Item:0x00564d6bef6e88 id: nil, type: "type1test", size: 137, color: 'blue'>,
#<Item:0x00564d6bef6cf8 id: nil, type: "type1test", size: 132, color: 'blue'>,
#<Item:0x00564d6bef6af0 id: nil, type: "type1test", size: 141, color: 'blue'>,
#<Item:0x00564d6bef68c0 id: nil, type: "type1test", size: 135, color: 'blue'>]

items数组不会包含类型,但会包含一列numberofitems,其结果为COUNT

items[0].numberoftypes 
=> 6
items[0].numberofnames 
=> 4

无论如何这不起作用,因为你不能GROUP BY不同表中的不同字段,并且同时有2 COUNT

您可以尝试使用sql在this console中对其进行测试,看看它是不可能的。

它不会为您的某个列返回正确的计数,但是这种技术现在比您正在使用的那个更好,因为您不需要执行2 JOINS并且它将返回对象。

SQL非常简单,你可以参考https://www.w3schools.com/sql/来更好地理解http://guides.rubyonrails.org/active_record_querying.html中包含的任何sql