如何使用Rails 4命令嵌套包含记录

时间:2014-04-16 23:25:23

标签: mysql ruby-on-rails ruby activerecord ruby-on-rails-4

正如标题所述:如何使用Rails 4命令嵌套的includes记录?

以下是模型的概述:

产品

  • 标题

ProductSize

  • PRODUCT_ID
  • size_id

尺寸

  • 宽度
  • 高度
  • 顺序

Product有许多SizesProductSizeSizes将通过order模型上的Size进行排序。我在default_scope模型上设置order('order DESC') Sizes

我希望能够获得products的列表,然后遍历每个product并显示可用的sizes列表,由size {订购{1}}。我希望这一切都不会产生低效的查询(n + 1问题),所以我使用的是order

为此,我运行includes生成:

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 查询中获取记录的顺序。您还可以注意到product_sizes的查询确实具有sizes语句,但它不会影响最终结果。

我最初的想法是ORDER BY应该只是size joined查询。很遗憾,我不知道如何使用product_size来完成此操作。

理想情况下,生成的查询看起来更像:

includes

1 个答案:

答案 0 :(得分:0)

我继续将sizes关联直接映射到products。这就是我所拥有的:

product.rb型号:

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

product_size.rb型号:

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

size.rb型号:

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

seeds.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