Module: PgSearchScope::ModelHelper
- Defined in:
- lib/pg_search_scope/model_helper.rb
Constant Summary collapse
- SCOPE_METHOD =
defined?(ActiveRecord) && ActiveRecord::VERSION::MAJOR > 3 ? :all : :scoped
- DEFAULT_OPTIONS =
{ :as => nil, :wildcard => true, :operator => :and, :normalization => 0, :select_rank => false, :language => 'simple', :rank_function => :ts_rank }
- 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’ -
:rank_function- Ranking function. Valid values are ‘ts_rank’ and ‘ts_rank_cd’ -
:rank_columns- If you want to sort table by rank only by specific fields - input column names here
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)
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 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/pg_search_scope/model_helper.rb', line 52 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][\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('#{options[:language]}', #{document})" tsquery = "to_tsquery('#{options[:language]}', '#{terms.join(" #{OPERATORS[options[:operator]]} ")}')" rank_tsvector = tsvector if [:rank_columns].present? rank_document = [:rank_columns].map { |n| n = "#{prefix}.#{n}" unless n['.']; "coalesce(#{n}, '')" }.join(" || ' ' || ") rank_tsvector = "to_tsvector('#{options[:language]}', #{rank_document})" end rank = "#{scope_options[:rank_function]}(#{rank_tsvector}, #{tsquery}, #{options[:normalization]})" search_scope = send(SCOPE_METHOD) 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 |