高级搜索Rails中的多个关联

时间:2011-12-22 13:41:29

标签: sql ruby-on-rails activerecord associations

我正在尝试为我的候选模型构建高级搜索查找器。 让我们想象它有几个字段+多个关联,如has_many: languages& has_many: skills。现在我正在建立这样的查询:

query = Candidate.select("*")
if position_name
  query = query.where('position_name LIKE ? OR position_name IS NULL',"%#{position_name}%")
end 

if salary
  query = query.where('salary <= ? OR salary IS NULL',salary)
end

依旧......

现在我想添加更多高级条件,例如找到只有PHPJava这类技能的用户(所以只返回那些兼具两种技能的用户)

这只有在我插入OR

时才有效
  query = query.joins(:skills)
  query = query.where('`skills`.`name` = ? OR `skills`.`name` = ?',"Java","PHP")

另外,我对语言也一样(加上语言有language.name&amp; language.level

有人能指出我在哪个方向看?还有如何建立这样的条件,我可以使用多种技能或多种语言?

1 个答案:

答案 0 :(得分:3)

查看各种搜索宝石,如Ransack,Metawhere或Searchlogic

http://rubygems.org/gems/ransack

https://github.com/railsdog/searchlogic

Ransack和Searchlogic都允许搜索相关模型,您可以使用范围来限制搜索参数。

Searchlogic的搜索参数示例。

[search][admitted_gte]  

[search][admitted_lte]  

[search][aetiology_like_any][]  VIRUS

[search][at_risk_gte]   

[search][at_risk_lte]   

[search][died_gte]  

[search][died_lte]  

[search][gezi_reference_like]   

[search][id]    

[search][incidents_location_encrypted_postcode_like]    

[search][lab_confirmed_gte] 

[search][lab_confirmed_lte] 

[search][onset_first_after] 

[search][onset_first_before]    

[search][onset_last_after]  

[search][onset_last_before] 

[search][outbreak_type_equals_any][]    FOODBORNE

[search][point_source_date_after]   

[search][point_source_date_before]  

[search][total_affected_gte]    

[search][total_affected_lte]    

[search][user_reference_like]   

[search][year_equals_any][] 2010

search[order]   descend_by_id

Outbreak_Controller.rb索引操作返回搜索查询的结果。从17个搜索参数中,只需要一个搜索逻辑调用@ search = Outbreak.search(params[:search])。这些参数被列入允许搜索参数列表的白名单 - 代码未显示。

def index

          #set the default index order to be descending Outbreak id
          if !params[:search][:order]
              params[:search][:order] = "descend_by_id"  
          end
          if params[:search][:bacterial_agents_bacterium_name_like_any] != nil && !params[:search][:bacterial_agents_bacterium_name_like_any].empty?
              params[:search][:bacterial_agents_category_like] = "CAUSATIVE"
          end
          if params[:search][:viral_agents_virus_name_like_any] != nil && !params[:search][:viral_agents_virus_name_like_any].empty?
              params[:search][:viral_agents_category_like] = "CAUSATIVE"
          end
          if params[:search][:protozoal_agents_protozoa_name_like_any] != nil && !params[:search][:protozoal_agents_protozoa_name_like_any].empty?
              params[:search][:protozoal_agents_category_like] = "CAUSATIVE"
          end
          if params[:search][:toxic_agents_toxin_name_like_any] != nil && !params[:search][:toxic_agents_toxin_name_like_any].empty?
              params[:search][:toxic_agents_category_like] = "CAUSATIVE"
          end
  #Outbreak.search takes all of the given params and runs it against the Outbreak model and it's associated models
  @search = Outbreak.search(params[:search])
end