Files

Class Index [+]

Quicksearch

Ubiquo::FilteredSearch::ClassMethods

Public Instance Methods

filtered_search(params = {}, options = {}) click to toggle source

Returns a filtered, by named scopes, result set using filter params.

The result is automatically filtered using params[:filter_*] type params where * would be the name of the named_scoped to apply. Multiple named_scopes can be applied simultaniously.

You can also restrict the search to specific scopes. Examples:

 >> Book.paginated_filtered_search(params)
 >> Book.paginated_filtered_search(params, :scopes => [ :text ])
    # File vendor/plugins/ubiquo_core/lib/ubiquo/filtered_search.rb, line 84
84:       def filtered_search(params = {}, options = {})
85:         scopes = select_scopes(params, options[:scopes])
86:         scopes.inject(self) do |results, pair|
87:           pair.last.blank? ? results : results.send(pair.first, pair.last)
88:         end.all(options.except(:scopes))
89:       end
filtered_search_scopes(options = {}) click to toggle source

This macro adds two class methods to facilitate search and filtering within a model: Example:

 >> Book.paginated_filtered_search(params)
 >> Book.filtered_search(params)

filter_* like params are matched against the avaliable named_scopes (removing the filter_ part) and applied.

You can also enable and disable scopes and activate o deactivate default scopes (which are created automatically). Example:

 >> filtered_search_scopes # By default all scopes are enabled
 >> filtered_search_scopes :defaults => false # Disable auto-generated scopes
 >> filtered_search_scopes :enable => [ :text, :published_start ,:publish_end ], :defaults => false

It is also possible to define which fields should be affected by a text search (filter_text param matched against a dinamically generated text named_scope):

 >> filtered_search_scopes :text => [ :title, :description ]
    # File vendor/plugins/ubiquo_core/lib/ubiquo/filtered_search.rb, line 36
36:       def filtered_search_scopes(options = {})
37:         options.reverse_merge!({:defaults => true})
38:         @enabled_scopes = options[:enable] || []
39:         text_scope(options[:text]) if (options[:defaults] || options[:text])
40:         if options[:defaults]
41:           published_at_scopes
42:           @enabled_scopes << :locale
43:         end
44:       end
paginated_filtered_search(params = {}, options = {}) click to toggle source

Returns a paginated and filtered result set. You can use params[:page] to specify which page to retrieve.

It also takes into account order_by and sort_order params. Check filtered_search for more details

    # File vendor/plugins/ubiquo_core/lib/ubiquo/filtered_search.rb, line 51
51:       def paginated_filtered_search(params = {}, options = {})
52:         order_by =  params[:order_by] || options[:order_by] || "#{table_name}.id"
53:         sort_order = params[:sort_order] || options[:sort_order] || 'desc'
54: 
55:         order_by_segments = order_by.split('.')
56: 
57:         # To deal with relation columns. Ex: :'author.name'
58:         # We need to deal with a special case with categories
59:         if order_by_segments.size > 2
60:           table, assoc, column = order_by_segments
61:           assoc_table = (self.reflections[assoc.to_sym] ||
62:                          self.reflections[assoc.pluralize.to_sym]).table_name
63:           options[:include] = assoc_table == 'categories' ? assoc.pluralize : assoc
64:           order_by = "#{assoc_table}.#{column}"
65:         end
66: 
67:         options[:order] = "#{order_by} #{sort_order}"
68: 
69:         ubiquo_paginate(:page => params[:page]) do
70:           filtered_search params, options.except(:order_by, :sort_order)
71:         end
72:       end

Protected Instance Methods

accent_insensitive_regexp(text) click to toggle source

(Not documented)

     # File vendor/plugins/ubiquo_core/lib/ubiquo/filtered_search.rb, line 130
130:       def accent_insensitive_regexp(text)
131:         regexps = ["(a|á|à|â|ã|A|Á|À|Â|Ã)", "(e|é|è|ê|E|É|È|Ê)", "(i|í|ì|I|Í|Ì)", "(o|ó|ò|ô|õ|O|Ó|Ò|Ô|Õ)", "(u|ú|ù|U|Ú|Ù)", "(c|ç|C|Ç)", "(ñ|Ñ)"]
132:         regexps.each { |exp| text.gsub! Regexp.new(exp), exp }
133:         text
134:       end
default_text_fields() click to toggle source

Defines the default columns to search based on existing columns. Currently it uses title, name and description

     # File vendor/plugins/ubiquo_core/lib/ubiquo/filtered_search.rb, line 123
123:       def default_text_fields
124:         ["title", "name", "description"].inject([]) do |result, text_field|
125:           result << text_field if table_exists? && column_names.include?(text_field)
126:           result
127:         end
128:       end
published_at_scopes() click to toggle source

Defines publish_start and publish_end named scopes if the published_at column exists

     # File vendor/plugins/ubiquo_core/lib/ubiquo/filtered_search.rb, line 112
112:       def published_at_scopes
113:         # TODO: End and removal of parse_date, see I18n.parse_date
114:         if table_exists? && column_names.include?("published_at")
115:           @enabled_scopes.concat [ :publish_start, :publish_end ]
116:           named_scope :publish_start , lambda { |value| { :conditions => ["#{table_name}.published_at >= ?", parse_date(value)] } }
117:           named_scope :publish_end   , lambda { |value| { :conditions => ["#{table_name}.published_at <= ?", parse_date(value, :time_offset => 1.day)] } }
118:         end
119:       end
select_scopes(params,restrict_scopes) click to toggle source

Returns an array of valid scopes filtering out invalid ones

     # File vendor/plugins/ubiquo_core/lib/ubiquo/filtered_search.rb, line 137
137:       def select_scopes(params,restrict_scopes)
138:         filters = params.reject {|k,v| !k.to_s.match /^filter_/ }
139:         scopes = filters.inject({}) { |h, (k,v)| h[k.gsub('filter_', '').to_sym] = v; h } # transform filter_bla keys into :bla
140:         valid_scopes = restrict_scopes || @enabled_scopes
141:         rogue_filters = scopes.keys - valid_scopes
142:         unless rogue_filters.blank?
143:           raise Ubiquo::InvalidFilter, "Unexpected filter received in params: #{rogue_filters.inspect}"
144:         end
145:         scopes
146:       end
text_scope(selected_fields) click to toggle source

Defines a named_scope for text search using the received fields or the default ones.

It uses a regexp based and case insensitive and accent insensitive search.

     # File vendor/plugins/ubiquo_core/lib/ubiquo/filtered_search.rb, line 98
 98:       def text_scope(selected_fields)
 99:         fields = selected_fields || default_text_fields
100:         regexp_op = connection.adapter_name == "PostgreSQL" ? "~*" : "REGEXP"
101:         @enabled_scopes.concat [:text]
102:         named_scope :text, lambda { |value|
103:           match = accent_insensitive_regexp(value.downcase)
104:           matches = fields.inject([]) { |r, f| r << match }
105:           conditions = fields.map { |f| "lower(#{table_name}.#{f}) #{regexp_op} ?" }.join(" OR ")
106:           { :conditions => [ conditions, *matches ] }
107:         }
108:       end

Disabled; run with $DEBUG to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.