简体   繁体   English

如何使用Rails 4订购嵌套的include记录

[英]How can I order nested includes records with Rails 4

As the title states: how can I order nested includes records with Rails 4? 如标题所述:如何使用Rails 4订购嵌套的includes记录?

Here is an overview of the models: 以下是模型的概述:

Product 产品

  • title 标题
  • price 价钱
  • etc 等等

ProductSize 产品尺寸

  • product_id product_id
  • size_id size_id

Size 尺寸

  • width 宽度
  • height 高度
  • order 订购

A Product has many Sizes through ProductSize . 通过ProductSize Product具有多种Sizes Sizes are to be ordered through order on the Size model. Sizes是通过订购orderSize模型。 I have a default_scope of order('order DESC') set on the Sizes model 我在Sizes模型上设置了default_scope of order('order DESC')

I want to be able to get a list of products , and then loop through each product and show a list of available sizes , ordered by the size order . 我希望能够获得products列表,然后遍历每个product并显示可用sizes的列表,按size order I want this all without making inefficient queries (n+1 problem), so I am using includes . 我希望所有这些都不会造成效率低下的查询(n + 1问题),因此我正在使用includes

To do this, I run Product.includes(:product_sizes => [:size]).all which generates: 为此,我运行Product.includes(:product_sizes => [:size]).all会生成:

SELECT "products".* FROM "products"

SELECT "product_sizes".* FROM "product_sizes" 
WHERE "product_sizes"."product_id" IN (X, X, X, X)

SELECT "sizes".* FROM "sizes" 
WHERE "sizes"."id" IN (X, X, X, X, X, X, X, X) ORDER BY `order` ASC

As you can see my my ordering will be off since it will use the order in which I got the records from the product_sizes query. 如您所见,我的排序将关闭,因为它将使用从product_sizes查询中获取记录的顺序。 You can also notice that the query for sizes does indeed have the ORDER BY statement, but it does not affect the end result. 您还可以注意到, sizes查询的确具有ORDER BY语句,但不会影响最终结果。

My initial thought would be that the size should just be joined onto the product_size query. 我最初的想法是将sizejoinedproduct_size查询中。 Unfortunately I have no idea on how to do this using includes . 不幸的是,我不知道如何使用includes做到这一点。

Ideally the generated queries would look more like: 理想情况下,生成的查询应类似于:

SELECT "products".* FROM "products"

SELECT "product_sizes".* FROM "product_sizes" 
WHERE "product_sizes"."product_id" IN (X, X, X, X)
JOIN "size" ON product_sizes.size_id = sizes.id
ORDER BY `size`.`order`

SELECT "sizes".* FROM "sizes" 
WHERE "sizes"."id" IN (X, X, X, X, X, X, X, X) ORDER BY `order` ASC

I went ahead and mapped the sizes association directly onto products . 我继续将sizes关联直接映射到products Here is what I have: 这是我所拥有的:

product.rb model: product.rb模型:

class Product < ActiveRecord::Base
  has_many :product_sizes
  has_many :sizes, through: :product_sizes, source: :size
end

product_size.rb model: product_size.rb模型:

class ProductSize < ActiveRecord::Base
  belongs_to :product
  belongs_to :size
end

size.rb model: size.rb模型:

class Size < ActiveRecord::Base
  default_scope -> { order(order: :desc)}
end

seeds.rb file: (you can run rake db:seed to see how it works) seed.rb文件:(您可以运行rake db:seed来查看其工作原理)

# Size.delete_all
# Product.delete_all
# ProductSize.delete_all

size1 = Size.create!(width: 20, height: 5, order: 3)
size2 = Size.create!(width: 30, height: 15, order: 2)
size3 = Size.create!(width: 10, height: 123, order: 1)
size4 = Size.create!(width: 14, height: 12, order: 4)
size5 = Size.create!(width: 24, height: 32, order: 5)
size6 = Size.create!(width: 45, height: 13, order: 7)
size7 = Size.create!(width: 54, height: 31, order: 6)
size8 = Size.create!(width: 35, height: 14, order: 8)
size9 = Size.create!(width: 42, height: 41, order: 9)
size10 = Size.create!(width: 13, height: 54, order: 10)

product1 = Product.create!(title: "Chair", price: 21.00)
product2 = Product.create!(title: "Table", price: 120.00)
product3 = Product.create!(title: "Microwave", price: 34.00)

ProductSize.create!(size: size1, product: product1)
ProductSize.create!(size: size3, product: product1)
ProductSize.create!(size: size5, product: product1)

ProductSize.create!(size: size1, product: product2)
ProductSize.create!(size: size3, product: product2)
ProductSize.create!(size: size4, product: product2)

ProductSize.create!(size: size1, product: product3)
ProductSize.create!(size: size2, product: product3)
ProductSize.create!(size: size3, product: product3)
ProductSize.create!(size: size8, product: product3)
ProductSize.create!(size: size9, product: product3)
ProductSize.create!(size: size10, product: product3)
ProductSize.create!(size: size4, product: product3)
ProductSize.create!(size: size5, product: product3)
ProductSize.create!(size: size6, product: product3)
ProductSize.create!(size: size7, product: product3)

products = Product.includes(:sizes).references(:sizes).order('"sizes"."order" DESC').to_a
products.each do |product|
  puts product.title
  product.sizes.each { |size| print "#{size.order} " }
  puts    
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM