我正在尝试使用Rails创建一个通用的产品目录应用程序,并且为了拥有具有不同属性的不同类型的产品,我将产品属性抽象到他们自己的表中,在产品和存储的属性之间有一个链接表。值。
------------- --------------------
|products | |product_properties| ------------
|-----------| |------------------| |properties|
|name |---|value |---|----------|
|description| |product_id | |name |
|etc... | |property_id | ------------
------------- --------------------
例如,产品可以具有width属性(将存储在属性表中以便可以重复使用),而width的值将存储在product_properties表中,并带有将属性链接到产品的记录
这很好但我需要在产品模型中实现facet-able搜索并选择使用ransack。因此,要查找宽度大于30的所有产品,我必须这样做
Product.ransack(product_properties_property_name_eq: 'width', product_properties_value_gt: 30).result
这再次正常,但我更愿意“搜索”'使用属性名称
Product.ransack(width_gt: 30).result
有没有办法动态创建允许我这样做的搜索者(或替代品)?我尝试过使用method_missing,但这让我感到困惑。我正在考虑使用属性表中的所有名称值在模型上创建范围,但我想首先要求一些建议。
更新
我尝试在产品型号上实施一系列自定义搜索工具
class Product < ActiveRecord::Base
Property.pluck(:name, :id).each do |name, id|
ransacker name, formatter: -> (value) { value.to_s.downcase } do
product_properties = Arel::Table.new(:product_properties)
product_properties[:value]
end
end
end
这让我越来越接近我能感受到的答案了。我还在做什么呢?
答案 0 :(得分:2)
这完美地完成了这项工作。这里的问题是Arel::Nodes.build_quoted
。我最初离开了这个,我不会得到任何错误/警告,但我同样得不到任何结果,这让我感到很难过。这显然只在使用Rails 4.2+(Arel 6.0 +)时才有必要。
Property.pluck(:id, :name).each do |id, name|
product_properties = Arel::Table.new(:product_properties)
ransacker name.to_sym, formatter: -> (value) { value.to_s.downcase } do
Arel::Nodes::InfixOperation.new('AND',
Arel::Nodes::InfixOperation.new('=',
product_properties[:property_id], Arel::Nodes.build_quoted(id)
),
product_properties[:value]
)
end
end
要实际使用它,我需要将product_properties表显式连接到查询
Product.joins(:product_properties).ransack(width_gt: 30)
由于搜查文件说明了一些人使用搜索者遇到的困难不是来自Ransack,而是来自不了解Arel。这绝对是这种情况。