Class: Decidim::ResourceSearch
- Inherits:
- 
      Searchlight::Search
      
        - Object
- Searchlight::Search
- Decidim::ResourceSearch
 
- Defined in:
- app/services/decidim/resource_search.rb
Overview
This is the base class to be used by other search services. Searchlight documentation: github.com/nathanl/searchlight
Instance Attribute Summary collapse
- 
  
    
      #component  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Returns the value of attribute component. 
- 
  
    
      #organization  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Returns the value of attribute organization. 
- 
  
    
      #user  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Returns the value of attribute user. 
Class Method Summary collapse
- 
  
    
      .text_search_fields(*fields)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Public: Companion method to ‘search_search_text` which defines the attributes where we should search for text values in a model. 
Instance Method Summary collapse
- 
  
    
      #base_query  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Creates the SearchLight base query. 
- 
  
    
      #initialize(scope, options = {})  ⇒ ResourceSearch 
    
    
  
  
  
    constructor
  
  
  
  
  
  
  
    Initialize the Searchlight::Search base class with the options provided. 
- 
  
    
      #results  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    We overwrite the ‘results` method to ensure we only return unique results. 
- 
  
    
      #search_category_id  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Handle the category_id filter. 
- 
  
    
      #search_origin  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Handle the origin filter. 
- 
  
    
      #search_scope_id  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Handles the scope_ids filter. 
- 
  
    
      #search_search_text  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Handle the search_text filter. 
Constructor Details
#initialize(scope, options = {}) ⇒ ResourceSearch
Initialize the Searchlight::Search base class with the options provided.
scope - The scope used to create the base query options - A hash of options to modify the search. These options will be
converted to methods by SearchLight so they can be used on filter
methods. (Default {})
| 15 16 17 18 19 20 21 | # File 'app/services/decidim/resource_search.rb', line 15 def initialize(scope, = {}) super() @scope = scope @user = [:current_user] || [:user] @component = [:component] @organization = [:organization] || component&.organization end | 
Instance Attribute Details
#component ⇒ Object (readonly)
Returns the value of attribute component.
| 7 8 9 | # File 'app/services/decidim/resource_search.rb', line 7 def component @component end | 
#organization ⇒ Object (readonly)
Returns the value of attribute organization.
| 7 8 9 | # File 'app/services/decidim/resource_search.rb', line 7 def organization @organization end | 
#user ⇒ Object (readonly)
Returns the value of attribute user.
| 7 8 9 | # File 'app/services/decidim/resource_search.rb', line 7 def user @user end | 
Class Method Details
.text_search_fields(*fields) ⇒ Object
Public: Companion method to ‘search_search_text` which defines the attributes where we should search for text values in a model.
| 25 26 27 28 | # File 'app/services/decidim/resource_search.rb', line 25 def self.text_search_fields(*fields) @text_search_fields = fields if fields.any? @text_search_fields end | 
Instance Method Details
#base_query ⇒ Object
Creates the SearchLight base query. Check if the option component was provided.
| 47 48 49 50 51 | # File 'app/services/decidim/resource_search.rb', line 47 def base_query raise "Missing component" unless component @scope.where(component: component) end | 
#results ⇒ Object
We overwrite the ‘results` method to ensure we only return unique results. We can’t use ‘#uniq` because it returns an Array and we’re adding scopes in the controller, and ‘#distinct` doesn’t work here because in the later scopes we’re ordering by ‘RANDOM()` in a DB level, and `SELECT DISTINCT` doesn’t work with ‘RANDOM()` sorting, so we need to perform two queries.
The correct behaviour is backed by tests.
| 97 98 99 | # File 'app/services/decidim/resource_search.rb', line 97 def results base_query.model.where(id: super.pluck(:id)) end | 
#search_category_id ⇒ Object
Handle the category_id filter
| 54 55 56 57 58 59 60 | # File 'app/services/decidim/resource_search.rb', line 54 def search_category_id return query if category_ids.include?("all") query .includes(:categorization) .where(decidim_categorizations: { decidim_category_id: all_category_ids }) end | 
#search_origin ⇒ Object
Handle the origin filter.
| 82 83 84 85 86 87 | # File 'app/services/decidim/resource_search.rb', line 82 def search_origin renamed_origin = Array(origin).map do |search_value| "#{search_value}_origin" end apply_scopes(%w(official_origin citizens_origin user_group_origin meeting_origin), renamed_origin) end | 
#search_scope_id ⇒ Object
Handles the scope_ids filter. When we want to show only those that do not have a scope_ids set, we cannot pass an empty String or nil because Searchlight will automatically filter out these params, so the method will not be used. Instead, we need to pass a fake ID and then convert it inside. In this case, in order to select those elements that do not have a scope_ids set we use ‘“global”` as parameter, and in the method we do the needed changes to search properly.
| 69 70 71 72 73 74 75 76 77 78 79 | # File 'app/services/decidim/resource_search.rb', line 69 def search_scope_id return query if scope_ids.include?("all") clean_scope_ids = scope_ids conditions = [] conditions << "#{query.model_name.plural}.decidim_scope_id IS NULL" if clean_scope_ids.delete("global") conditions.concat(["? = ANY(decidim_scopes.part_of)"] * clean_scope_ids.count) if clean_scope_ids.any? query.includes(:scope).references(:decidim_scopes).where(conditions.join(" OR "), *clean_scope_ids.map(&:to_i)) end | 
#search_search_text ⇒ Object
Handle the search_text filter. We have to cast the JSONB columns into a ‘text` type so that we can search.
| 32 33 34 35 36 37 38 39 40 41 42 43 | # File 'app/services/decidim/resource_search.rb', line 32 def search_search_text return query unless self.class.text_search_fields.any? fields = self.class.text_search_fields.dup text_query = query.where(localized_search_text_in("#{query.model_name.plural}.#{fields.shift}"), text: "%#{search_text}%") fields.each do |field| text_query = text_query.or(query.where(localized_search_text_in("#{query.model_name.plural}.#{field}"), text: "%#{search_text}%")) end text_query end |