Ruby on rails 如何在where子句中使用实例方法

Ruby on rails 如何在where子句中使用实例方法,ruby-on-rails,Ruby On Rails,在我的类别模型中,我有一个实例方法,可以将类别内所有产品的所有平均价格相加: def price_average(store_id) products.pluck(:price_average).map { |h| h[store_id] }.sum end 在我的类别控制器中,我试图使用过滤器仅显示平均价格高于特定金额的类别。我该怎么做 我这里的主要挑战是,price\u average不是一个列名,所以做一些类似于@categories的事情。其中(“price\u average('

在我的
类别
模型中,我有一个实例方法,可以将类别内所有产品的所有平均价格相加:

def price_average(store_id)
  products.pluck(:price_average).map { |h| h[store_id] }.sum
end
在我的
类别
控制器中,我试图使用过滤器仅显示
平均价格高于特定金额的类别。我该怎么做

我这里的主要挑战是,
price\u average
不是一个列名,所以做一些类似于
@categories的事情。其中(“price\u average('1')>1000”)
就是失败了

模型的结构如下所示:

class Category < ApplicationRecord
    # t.string "name"
    # t.datetime "created_at", precision: 6, null: false
    # t.datetime "updated_at", precision: 6, null: false

    has_and_belongs_to_many :products
    has_many :prices, through: :products

    def price_average(store_id)
      products.pluck(:price_average).map { |h| h[store_id] }.sum
    end
end


class Product < ApplicationRecord
    # t.string "name"
    # t.datetime "created_at", precision: 6, null: false
    # t.datetime "updated_at", precision: 6, null: false
    # t.jsonb "price_average", default: {}

    has_and_belongs_to_many :categories
    has_many :prices

end
类别

price\u average
列中,我存储的是json,其中store\u id是用于检索值的索引。

您可以在类别表中添加一个名为price\u average的列,并在每次添加类别中的产品或从类别中删除产品时更新它,然后您就可以依赖此字段


请注意,当您需要在运行时显示的平均值大于您计算的值时,这将节省处理时间

,正如问题所理解的,使用SQL查询提出解决方案,以优化解决方案,而不更改模式

第1步:

获取store\u id为
store\u id的所有产品的平均价格

# GET price_average of products, grouped on product and category. 
# This query would be a sub query to the next step.
# SQL code
SELECT 
    id, category_id, 
    (json_array_elements(products.price_average)->>'STORE_ID')::numeric as price_average 
    FROM products 
    GROUP BY id, category_id
第二步:

查找价格平均值之和,并过滤总和大于最小价格平均值变量的产品和类别

# SQL code
SELECT products.id, products.category_id, sum(products.price_average) as price_average 
        FROM (
            # Query from step 1
            SELECT id, category_id, (json_array_elements(products.price_average)->>'STORE_ID')::numeric as price_average 
            FROM products 
            GROUP BY id, category_id
            ) AS products 
        GROUP BY products.id, products.category_id
        HAVING sum(products.price_average) > MIN_PRICE_AVERAGE_VARIABLE 
第三步:

从步骤2中获取类别的ID,使用相同的ID查找所有类别。使用exec_query执行在上一步中获得的查询

# ruby code
@connection = ActiveRecord::Base.connection
result = @connection.exec_query("SELECT product_category.category_id FROM (
    SELECT products.id, products.category_id AS category_id, sum(products.price_average) as price_average  
    FROM (
    SELECT id, category_id, (json_array_elements(products.price_average)->>#{STORE_ID})::numeric as price_average 
            FROM products 
            GROUP BY id, category_id
    ) AS products 
    GROUP BY products.id, products.category_id
    HAVING sum(products.price_average)>#{MIN_PRICE_AVERAGE_VARIABLE} 
    ) AS product_category")
category_ids = result.rows.flatten.uniq
Category.where(id: category_ids)
话虽如此,这里有一个模式更改建议:

  • 最好创建一个带有(产品标识、类别标识、商店标识、平均价格、其他公共列)的表
  • 这将有助于找到一个总和(平均价格),根据产品标识、类别标识、商店标识的任意组合进行过滤或分组

让我知道这是否有帮助。谢谢

能否添加类别、产品和门店之间的关联详细信息。平均价格是一个杂烩吗?门店标识的角色?price_average的列类型还是price_average又是一种实例方法?刚刚编辑了原始帖子。