【问题标题】:Ruby on rails search in serialized array through the checkboxRuby on rails 通过复选框在序列化数组中搜索
【发布时间】:2016-06-30 07:54:02
【问题描述】:

您好,我有一个 Rails 应用程序,我在其中以序列化形式存储标签

product.rb

class Product < ActiveRecord::Base

serialize :product_keywords, Array

scope :with_tag, lambda { |tag|

                  where(["product_keywords LIKE ?", "%"+tag.join("%")+"%"])

                 }

end

在我看来

<% Product.all.active.each do |product| %>

                  <% product.product_keywords.map do |keywords| %>
                          <div class="checkbox">
                            <label>
                              <%= check_box_tag("with_tag[]", keywords, false) %> <%= keywords.capitalize %>
                            </label>
                         </div>                 
                  <% end %>
              <% end %>

在这里,当我从范围 with_tag 的复选框中找到带有标签的产品时,它只会根据最后一个选中的复选框获取记录

您可以通过发生的查询获得清晰的视野

product_keywords LIKE '%tshirt%printed%'

product_keywords 存储在表格的数组中。

如果产品中有多个重复的标签,我如何找到记录

【问题讨论】:

    标签: ruby-on-rails ruby activerecord serialization


    【解决方案1】:

    使用LIKE,您应该为每个标签生成product_keywords LIKE "%#{tag}%"

    最后你应该加入他们SQL'OR'或'AND'取决于情况(任何标签匹配 - 使用OR,所有标签匹配 - 使用AND

    假设您想要使用“AND”,您可以轻松地遍历所有标签以设置范围,如下所示:

    class Product < ActiveRecord::Base
      serialize :product_keywords, Array
      scope :with_tag, lambda { |tag| where(["product_keywords LIKE ?", "%#{tag}%") }
    end
    

    用法

    # we have selected tags in tags
    products = Product.all
    tags.each { |tag| products = products.with_tag(tag) }
    

    这将为每个标签生成 where 条件。许多条件通过 sql 'AND' 在 AR 中加入

    设置为 ['tshirt', 'printed'] 的标签的示例 sql 输出

    ... WHERE product_keywords LIKE "%tshirt%" AND product_keywords LIKE "%printed%"
    

    如果您想对标签条件进行“或”运算(匹配任何条件),您应该构建完整的 SQL where 子句,例如:

    scope :with_any_tag, lambda { |tags|
      # build SQL stmt for all tags, i.e.
      # (product_keywords LIKE ?) OR (product_keywords LIKE ?)
      # replace 'OR' with 'AND' if you need all-matching instead of any-matching
      sql_stmt = tags.collect { |tag| "(product_keywords LIKE ?)" }.join(' OR ')
    
      # prepare sql placeholder values, i.e.
      # %tsrhit%, %printed%
      sql_placeholders = tags.collect {|tag| "%#{tag}%"}
    
      # pass conditions and placeholders to where as a list
      # first param is a stmt, then all placeholders
      where([sql_stmt] + sql_placeholders) 
    }
    

    这是更通用的解决方案,您可以根据情况将OR 更改为AND,反之亦然。

    然后这样使用:

    products = Product.with_any_tag(['tshirt', 'printed'])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-15
      • 2017-08-25
      • 1970-01-01
      • 2010-11-05
      • 1970-01-01
      • 1970-01-01
      • 2012-12-01
      • 1970-01-01
      相关资源
      最近更新 更多