Module: PgSearchScope::ModelHelper
- Defined in:
- lib/pg_search_scope/model_helper.rb
Constant Summary collapse
- DEFAULT_OPTIONS =
{ :as => nil, :wildcard => true, :operator => :and, :normalization => 0, :select_rank => false, :language => 'simple' }
- OPERATORS =
{ :and => '&', :or => '|' }
Instance Method Summary collapse
-
#search_scope_for(*column_names) ⇒ Object
Creates fulltext search scope.
Instance Method Details
#search_scope_for(*column_names) ⇒ Object
Creates fulltext search scope
Options
-
:as
- Scope name -
:normalization
- Controls rank behaviour, see www.postgresql.org/docs/9.0/static/textsearch-controls.html#TEXTSEARCH-RANKING -
:wildcard
- Controls search words modification:true - add :* to ends of each search word false - do not modify search words :last - add :* to end of last word
-
:operator
- Boolean operator (:and or :or) which combines search query -
:select_rank
- Include rank in select statement, as scope_name_rank -
:language
- Search language, e.g. ‘simple’ (without magic), ‘english’
Usage
search_scope_for :name
-->
search_by_name("Ivan")
search_scope_for :name, :address,
:wildcard => :last
-->
search_by_name_and_address("Ivan, Aurora st.", :select_rank => true)
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/pg_search_scope/model_helper.rb', line 46 def search_scope_for *column_names = DEFAULT_OPTIONS.merge column_names. scope_name = [:as] || "search_by_#{column_names.join('_and_')}" scope scope_name, Proc.new { |search_string, | = .merge( || {}) search_string ||= '' terms = search_string.scan(/'*([\p{Lu}\p{Ll}\d\.']+)/u).map {|s,_| s.gsub /'/, "''"} if terms.present? prefix = arel_table.table_alias || arel_table.name document = column_names.map { |n| n = "#{prefix}.#{n}" unless n['.']; "coalesce(#{n}, '')" }.join(" || ' ' || ") case [:wildcard] when true then terms.map! { |s| "#{s}:*" } when :last then terms[-1] = "#{terms[-1]}:*" end tsvector = "to_tsvector('#{[:language]}', #{document})" tsquery = "to_tsquery('#{[:language]}', '#{terms.join(" #{OPERATORS[[:operator]]} ")}')" rank = "ts_rank(#{tsvector}, #{tsquery}, #{[:normalization]})" search_scope = scoped if [:select_rank] search_scope = search_scope.select("#{rank} #{scope_name}_rank") end search_scope.where("#{tsvector} @@ #{tsquery}").order("#{rank} DESC") else if [:select_rank] scoped.select("0 #{scope_name}_rank") end end } end |