具有绑定变量和可选参数的条件
-
10-07-2019 - |
题
假设我有一个表单,用户可以搜索名称以特定name
字符串开头的人,例如<!>“Mi <!>”;会找到<!>“迈克<!>”;和<!>“Miguel <!>”;我可能会像这样创建一个find语句:
find(:all, :conditions => ['name LIKE ?', "#{name}%"])
假设表单还有两个可选字段hair_color
和eye_color
,可用于进一步过滤结果。忽略查询的名称部分,可以接受任意数量的可选参数的人的查找语句可能如下所示:
find(:all, :conditions => { params[:person] })
对于我的两个可选参数,其行为与此相同:
find(:all, :conditions => { :hair_color => hair_color, :eye_color => eye_color })
我无法弄清楚如何合并这两种查询所需的字段,<!> quot; name <!> quot;应用于<!> quot; like <!> quot;上面的条件,可以添加可选的<=>和<=>参数(可能还有其他参数)来进一步过滤结果。
我当然可以建立一个查询字符串来执行此操作,但我觉得必须有一个<!> quot; rails way <!> quot;那更优雅。如何将强制绑定参数与可选参数合并?
解决方案
这是对命名范围的完美使用。
在模型中创建命名范围:
named_scope :with_name_like, lambda {|name|
{:conditions => ['name LIKE ?', "#{name}%"]}
}
此时你可以打电话
Model.with_name_like("Mi").find(:all, :conditions => params[:person])
Rails会为你合并查询。
编辑:Waseem的代码:
如果名称是可选的,您可以使用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
}
其他提示
还要遵守Waseem请求,但允许nil为空白? (如果您想使用<!>引用@things = Thing.named_like(params [:name])<!>直接),这是有害的。
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]} : {}) } }
我希望它有所帮助