【问题标题】:Dynamic find conditions in active record活动记录中的动态查找条件
【发布时间】:2009-07-23 03:00:38
【问题描述】:

我在 Rails 中有一个索引操作,可以处理很多参数,例如:

params[:first_name] # can be nil or first_name
params[:age]        # can be nil or age 
params[:country]    # can be nil or country

在查找用户时,我希望 AND 所有不为零的条件。这给了我 8 个查找条件的排列。

我怎样才能使我的代码保持干爽和灵活,而不是以一堆if 语句结束,只是为了构建查找条件。请记住,如果没有指定条件,我只想返回User.all

【问题讨论】:

    标签: ruby-on-rails ruby activerecord


    【解决方案1】:

    比如:

    conditions = params.only(:first_name, :age, :country)
    conditions = conditions.delete_if {|key, value| value.blank?}
    
    if conditions.empty?
      User.all
    else
      User.all(:conditions => conditions)
    end
    

    【讨论】:

    • 奇怪的是,我的 params 哈希似乎没有唯一的方法
    【解决方案2】:

    我通常会为这样的事情使用命名范围:

    class User < ActiveRecord::Base
      named_scope :name_like, lambda {|name| {:conditions => ["first_name LIKE ?", "#{name}%"]}}
      named_scope :age, lambda {|age| {:conditions => {:age => age}}}
      named_scope :in_country, lambda {|country| {:conditions => {:country => country}}}
    end
    
    class UsersController < ActionController
      def index
        root = User
        root = root.name_like(params[:first_name]) unless params[:first_name].blank?
        root = root.age(params[:age]) unless params[:age].blank?
        root = root.country(params[:country]) unless params[:age].blank?
    
        @users = root.paginate(params[:page], :order => "first_name")
      end
    end
    

    这就是我通常所做的。

    【讨论】:

      【解决方案3】:

      这似乎工作得很好:

      conditions = params.slice(:first_name, :age, :country)
      hash = conditions.empty? ? {} : {:conditions => conditions}
      @users = User.all hash 
      

      【讨论】:

        【解决方案4】:

        使用 James Healy 的回答,我修改了要在 Rails 3.2 中使用的代码(以防万一有人需要)。

        conditions = params.slice(:first_name, :age, :country)
        conditions = conditions.delete_if {|key, value| value.blank?}
        
        @users = User.where(conditions)
        

        【讨论】:

          【解决方案5】:

          您可以尝试Ambition,或其他一些 ActiveRecord 扩展。

          【讨论】:

            【解决方案6】:

            这对我也有用

            conditions = params[:search] ? params[:search].keep_if{|key, value| !value.blank?} : {}
            User.all(:conditions => conditions)
            

            【讨论】:

              【解决方案7】:

              如果您碰巧在一个古老的项目 (Rails 2.x) 上并且非常混乱,您可以执行以下操作来向原始查询添加新字段。

              原码:

              User.find(:all,
                 :conditions => ['first_name LIKE ? AND age=? AND country=?',
                      "#{name}%", age, country]
              

              zip_code 字段上添加新的动态条件:

              zip_code  = params[:zip_code]   # Can be blank
              zip_query = "AND zip_code = ?" unless zip_code.blank?
              
              User.find(:all,
                 :conditions => ['first_name LIKE ? AND age=? AND country=? #{zip_query}',
                      "#{name}%", age, country, zip_code].reject(&:blank?)
              

              reject(&amp;:blank?) 添加到conditions 数组将过滤nil 值。

              注意:如果您从零开始编码或重构,其他答案会更好。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2013-06-23
                • 1970-01-01
                • 2015-12-12
                • 2016-06-03
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多