渴望在轨道上的红宝石中加载优化

时间:2015-05-23 12:50:04

标签: ruby-on-rails ruby optimization query-optimization

我有一个has_many Variants的产品。而变体属于产品。我想显示产品的名称(可在产品中找到)以及价格和数量(可在变体中找到)。

Product table:
 -id
 -title
 -description

Variants table:
 - id
 - is_active(boolean)
 - price
 - quantity
 - product_id

这就是表格的样子。这是我的尝试

  def index

    @products =Product.all
    @display = []
    @products.each do |product|
      @children = product.variants.where(is_active: true).order(:price).
                                   select(:id,:price,:quantity).first

      if @children.present?
      @display << {
                   id: product.id,
                    title: product.title,
                    description: product.description,
                    price:  @children.price,
                    quantity:  @children.quantity,
                    variant_id:  @children.id
                  }
      end
    end

    @display = Kaminari.paginate_array(@display).page(params[:page])

  end

我需要最大限度地优化它。这让我想到了第一个问题。如何更好地优化它。
我的第二个问题为什么当我做@products = Product.all.includes(:variants)时,它实际上会增加加载时间而不是降低它,因为我在整个@products数组中得到了该迭代中每个产品的变体(所以它应该算作一个N + 1,我得到每个产品的产品我得到的变种)? 将我的@products数组拆分为4并使4个线程填充显示一个好主意吗?

2 个答案:

答案 0 :(得分:1)

你的代码没有使用急切加载的数据,这就是为什么添加include会减慢速度 - 这只是额外的工作。

通常,如果您调用查询方法(whereorder等),则rails无法使用预先加载的数据。相反,你可以建立一个新的协会:

has_many :active_variants,  -> { where(is_active: true).order(:price) }, class_name: "Variant"

然后急切加载并使用此关联而不是变体关联。

答案 1 :(得分:0)

你应该把它写成;

def index
  @display = Varient.joins(:product).where(is_active: true).order(:price).select('products.id as id, products.title, products.description, price, quantity, variants.id as variant_id')
end