代码之家  ›  专栏  ›  技术社区  ›  Azi Chen

Ransack-gem-不区分大小写搜索

  •  0
  • Azi Chen  · 技术社区  · 10 年前

    使用Ransack宝石,我想这样做

    https://github.com/activerecord-hackery/ransack/wiki/Basic-Searching#i_cont-work-in-progress-dont-use-yet

     >> User.search(first_name_i_cont: 'Rya').result.to_sql
    => SELECT "users".* FROM "users"  WHERE (UPPER("users"."first_name") LIKE UPPER('%Rya%'))
    

    但这种方法还不起作用。

    所以我试着弄清楚,有没有其他方法可以做到这一点 我得到了一些关于如何做的信息

    //in model
    
      ransacker :ig_case, formatter: proc { |v| v.mb_chars.upcase.to_s } do |parent|
        Arel::Nodes::NamedFunction.new('UPPER',[parent.table[:firstname]])
      end
    
    //in config/ranrack.rb
    
    Ransack.configure do |config|
      config.add_predicate 'ig_case', # Name your predicate
        arel_predicate: 'matches',
        formatter: proc { |v| "%#{v.to_s.gsub(/([\\|\%|.])/, '\\\\\\1').mb_chars.upcase}%"},
        validator: proc { |v| v.present? },
        compounds: true,
        type: :string
    end
    
       // use way
    User.search({ firstname_or_lastname_ig_case: "ABC"}).result.to_sql
    
    => "SELECT `Users`.* FROM `Users` WHERE ((UPPER(`users`.`firstname`) LIKE '%ABC%' OR (`users`.`lastname`) LIKE '%ABC%'))"
    

    几个小时后,我发现当我以模型的方式使用时,我每次只能得到一个大写字段。

    如果我选择了配置方式,我可以升级所有字段,但我不能像这样获取sql 'UPPER(“users”.“first_name”)'

    有什么解决办法吗?我真的非常感谢。

    1 回复  |  直到 10 年前
        1
  •  4
  •   Zoidberg    10 年前

    您需要通过执行以下操作重写适配器中的Arel:

        module Arel
    
          module Nodes
            %w{
              IDoesNotMatch
              IMatches
            }.each do |name|
              const_set name, Class.new(Binary)
            end
          end
    
          module Predications
            def i_matches other
              Nodes::IMatches.new self, other
            end
    
            def i_does_not_match other
              Nodes::IDoesNotMatch.new self, other
            end
          end
    
          module Visitors
    
            class ToSql < Arel::Visitors::Visitor
              def visit_Arel_Nodes_IDoesNotMatch o
                "UPPER(#{visit o.left}) NOT LIKE UPPER(#{visit o.right})"
              end
    
              def visit_Arel_Nodes_IMatches o
                "UPPER(#{visit o.left}) LIKE UPPER(#{visit o.right})"
              end
            end
    
            class Dot < Arel::Visitors::Visitor
              alias :visit_Arel_Nodes_IMatches            :binary
              alias :visit_Arel_Nodes_IDoesNotMatch       :binary
            end
    
            class DepthFirst < Visitor
    
              unless method_defined?(:visit_Arel_Nodes_InfixOperation)
                alias :visit_Arel_Nodes_InfixOperation :binary
                alias :visit_Arel_Nodes_IMatches            :binary
                alias :visit_Arel_Nodes_IDoesNotMatch       :binary
              end
    
            end
    
          end
        end
    

    除此之外,您还需要提供预测的方法。

    这是我解决你问题的方法: https://github.com/Kartstig/ransack

    我有一个公关被关闭了,因为它可能破坏了其他适配器。到目前为止,它在我的应用程序中运行得很好: https://github.com/activerecord-hackery/ransack/pull/405

    还要注意,如果您有任何索引列,它们将被忽略,因为您使用的是UPPER。