使用动态搜索者进行方面搜索

时间:2015-10-28 16:38:17

标签: ruby-on-rails ransack

我正在尝试使用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

这让我越来越接近我能感受到的答案了。我还在做什么呢?

1 个答案:

答案 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。这绝对是这种情况。