代码之家  ›  专栏  ›  技术社区  ›  SingleShot

具有绑定变量和可选参数的条件

  •  2
  • SingleShot  · 技术社区  · 15 年前

    name 字符串,例如,“Mi”将找到“Mike”和“Miguel”。我可能会创建这样一个find语句:

    find(:all, :conditions => ['name LIKE ?', "#{name}%"])
    

    假设表单还有两个可选字段, hair_color eye_color 可用于进一步过滤结果。忽略查询的名称部分,可以接受任意数量可选参数的人员的find语句可能如下所示:

    find(:all, :conditions => { params[:person] })

    对于我的两个可选参数,其行为与此等效:

    find(:all, :conditions => { :hair_color => hair_color, :eye_color => eye_color })

    我搞不懂的是如何合并这两种查询,其中必填字段“name”应用于上面的“like”条件,而可选字段 眼睛颜色

    我当然可以构建一个查询字符串来实现这一点,但我觉得必须有一种更优雅的“rails方式”。如何将强制绑定参数与可选参数合并?

    2 回复  |  直到 15 年前
        1
  •  4
  •   lulalala    13 年前

    这是命名范围的完美用法。

    在模型中创建命名范围:

    named_scope :with_name_like, lambda {|name|
      {:conditions => ['name LIKE ?', "#{name}%"]}
    }
    

    此时您可以调用

    Model.with_name_like("Mi").find(:all, :conditions => params[:person])
    

    Rails将为您合并查询。

    如果名称是可选的,则可以使用If条件从方法链中省略命名范围:

    unless name.blank?
       Model.with_name_like("Mi").find(:all, :conditions => params[:person])
    else
       Model.find(:all, :conditions => params[:person])
    end
    

    named_scope :with_name_like, lambda {|name|
      if name.blank?
        {}
      else
        {:conditions => ['name LIKE ?', "#{name}%"]}
      end
    }
    

    更新

    以下是最后一段代码片段的Rails 3版本:

    scope :with_name_like, lambda {|name|
      if not name.blank?
        where('name LIKE ?', "#{name}%")
      end
    }
    
        2
  •  0
  •   Oinak    14 年前

    named_scope :named_like, lambda do |*args| 
      if (name=args.first)
        {:conditions => ["name like ?",name]}
      else
        {}
      end
    end
    
    # or oneliner version:
    
    named_scope :named_like, lambda{|*args| (name=args.first ? {:conditions => ["name like ?",name]} : {}) } }
    

    我希望有帮助