2016-02-12 23:52:43 +08:00
|
|
|
module SearchableModel
|
|
|
|
extend ActiveSupport::Concern
|
|
|
|
|
|
|
|
included do
|
|
|
|
# Helper function for relations that
|
|
|
|
# adds OR ILIKE where clause for all specified attributes
|
|
|
|
# for the given search query
|
2017-05-05 22:41:23 +08:00
|
|
|
scope :where_attributes_like, lambda { |attributes, query, options = {}|
|
|
|
|
return unless query
|
2016-02-12 23:52:43 +08:00
|
|
|
attrs = []
|
2017-05-05 22:41:23 +08:00
|
|
|
if attributes.blank?
|
2016-02-12 23:52:43 +08:00
|
|
|
# Do nothing in this case
|
|
|
|
elsif attributes.is_a? Symbol
|
|
|
|
attrs = [attributes.to_s]
|
|
|
|
elsif attributes.is_a? String
|
|
|
|
attrs = [attributes]
|
|
|
|
elsif attributes.is_a? Array
|
2017-05-05 22:41:23 +08:00
|
|
|
attrs = attributes.collect(&:to_s)
|
2016-02-12 23:52:43 +08:00
|
|
|
else
|
2017-05-05 22:41:23 +08:00
|
|
|
raise ArgumentError, ':attributes must be an array, symbol or string'
|
2016-02-12 23:52:43 +08:00
|
|
|
end
|
|
|
|
|
2017-05-05 22:41:23 +08:00
|
|
|
if options[:whole_word].to_s == 'true' ||
|
|
|
|
options[:whole_phrase].to_s == 'true'
|
|
|
|
unless attrs.empty?
|
|
|
|
like = options[:match_case].to_s == 'true' ? '~' : '~*'
|
|
|
|
|
|
|
|
if options[:whole_word].to_s == 'true'
|
|
|
|
a_query = query.split
|
|
|
|
.map { |a| Regexp.escape(a) }
|
|
|
|
.join('|')
|
|
|
|
else
|
|
|
|
a_query = Regexp.escape(query)
|
|
|
|
end
|
|
|
|
a_query = '\\y(' + a_query + ')\\y'
|
|
|
|
where_str =
|
|
|
|
(attrs.map.with_index do |a, i|
|
|
|
|
"(trim_html_tags(#{a})) #{like} :t#{i} OR "
|
|
|
|
end
|
|
|
|
).join[0..-5]
|
|
|
|
vals = (
|
|
|
|
attrs.map.with_index do |_, i|
|
|
|
|
["t#{i}".to_sym, a_query]
|
|
|
|
end
|
|
|
|
).to_h
|
2016-11-14 19:32:41 +08:00
|
|
|
|
2017-05-05 22:41:23 +08:00
|
|
|
return where(where_str, vals)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
like = options[:match_case].to_s == 'true' ? 'LIKE' : 'ILIKE'
|
|
|
|
|
|
|
|
if query.count(' ') > 0
|
2017-04-11 20:55:44 +08:00
|
|
|
unless attrs.empty?
|
2017-05-05 22:41:23 +08:00
|
|
|
a_query = query.split.map { |a| "%#{sanitize_sql_like(a)}%" }
|
2016-07-21 19:11:15 +08:00
|
|
|
where_str =
|
2016-11-11 18:41:23 +08:00
|
|
|
(attrs.map.with_index do |a, i|
|
2017-05-05 22:41:23 +08:00
|
|
|
"(trim_html_tags(#{a})) #{like} ANY (array[:t#{i}]) OR "
|
2016-11-11 18:41:23 +08:00
|
|
|
end
|
|
|
|
).join[0..-5]
|
2017-05-05 22:41:23 +08:00
|
|
|
vals = (
|
|
|
|
attrs.map.with_index do |_, i|
|
|
|
|
["t#{i}".to_sym, a_query]
|
|
|
|
end
|
|
|
|
).to_h
|
2016-02-12 23:52:43 +08:00
|
|
|
|
2016-07-21 19:11:15 +08:00
|
|
|
return where(where_str, vals)
|
|
|
|
end
|
|
|
|
else
|
2017-04-11 20:55:44 +08:00
|
|
|
unless attrs.empty?
|
2016-07-21 19:11:15 +08:00
|
|
|
where_str =
|
2016-11-11 18:41:23 +08:00
|
|
|
(attrs.map.with_index do |a, i|
|
2017-05-05 22:41:23 +08:00
|
|
|
"(trim_html_tags(#{a})) #{like} :t#{i} OR "
|
2016-11-11 18:41:23 +08:00
|
|
|
end
|
|
|
|
).join[0..-5]
|
2017-05-05 22:41:23 +08:00
|
|
|
vals = (
|
|
|
|
attrs.map.with_index do |_, i|
|
|
|
|
["t#{i}".to_sym, "%#{sanitize_sql_like(query.to_s)}%"]
|
|
|
|
end
|
|
|
|
).to_h
|
2016-07-21 19:11:15 +08:00
|
|
|
|
|
|
|
return where(where_str, vals)
|
|
|
|
end
|
2016-02-12 23:52:43 +08:00
|
|
|
end
|
2017-05-05 22:41:23 +08:00
|
|
|
}
|
2016-02-12 23:52:43 +08:00
|
|
|
end
|
2016-11-11 18:41:23 +08:00
|
|
|
end
|