scinote-web/app/models/concerns/searchable_model.rb

105 lines
3.2 KiB
Ruby
Raw Normal View History

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' ||
options[:at_search].to_s == 'true'
2017-05-05 22:41:23 +08:00
unless attrs.empty?
like = options[:match_case].to_s == 'true' ? '~' : '~*'
like = 'SIMILAR TO' if options[:at_search].to_s == 'true'
2017-05-05 22:41:23 +08:00
if options[:whole_word].to_s == 'true'
a_query = query.split
.map { |a| Regexp.escape(a) }
.join('|')
a_query = "(#{a_query})"
elsif options[:at_search].to_s == 'true'
a_query = "%#{Regexp.escape(query).downcase}%"
2017-05-05 22:41:23 +08:00
else
a_query = Regexp.escape(query)
end
2017-05-05 22:41:23 +08:00
where_str =
(attrs.map.with_index do |a, i|
if a == 'repository_rows.id'
"CAST(#{a} AS TEXT) #{like} :t#{i} OR "
else
col = options[:at_search].to_s == 'true' ? "lower(#{a})": a
"(trim_html_tags(#{col})) #{like} :t#{i} OR "
end
2017-05-05 22:41:23 +08:00
end
).join[0..-5]
vals = (
attrs.map.with_index do |_, i|
["t#{i}".to_sym, a_query]
2017-05-05 22:41:23 +08:00
end
).to_h
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|
if a == 'repository_rows.id'
"CAST(#{a} AS TEXT) #{like} ANY (array[:t#{i}]) OR "
else
"(trim_html_tags(#{a})) #{like} ANY (array[:t#{i}]) OR "
end
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]
2017-05-05 22:41:23 +08:00
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|
if a == 'repository_rows.id'
"CAST(#{a} AS TEXT) #{like} :t#{i} OR "
else
"(trim_html_tags(#{a})) #{like} :t#{i} OR "
end
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)}%"]
2017-05-05 22:41:23 +08:00
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