Skip to content

Instantly share code, notes, and snippets.

@so77id
Created February 22, 2017 04:23
Show Gist options
  • Save so77id/9a861c4783a43ec0d2a700658465aafb to your computer and use it in GitHub Desktop.
Save so77id/9a861c4783a43ec0d2a700658465aafb to your computer and use it in GitHub Desktop.
Searchable Concern
module Searchable
extend ActiveSupport::Concern
included do
self.whitelist = {}
self.joins_whitelist = []
scope :search, -> (search_string){ joins(joins_actable_query).joins(joins_whitelist).where(make_search_query search_string) }
end
module ClassMethods
attr_accessor :whitelist
attr_accessor :joins_whitelist
def search_whitelist *args
act_as_attributes = []
if name.constantize.methods.include? :acting_as_model
act_as_attributes = name.constantize.acting_as_model.columns.map{|column| column.name if column.sql_type == "character varying" and column.name != "actable_type"}.compact
end
args.each do |arg|
case arg.class.name.to_sym
when :Array
if whitelist[arg[0].to_s.camelcase.constantize.name]
whitelist[arg[0].to_s.camelcase.constantize.name] << arg[1].to_s
else
whitelist[arg[0].to_s.camelcase.constantize.name] = [arg[1].to_s]
end
joins_whitelist << arg[0].to_sym if name.constantize.reflect_on_all_associations(:belongs_to).map(&:name).include?(arg[0].to_sym) and !joins_whitelist.include?(arg[0].to_s)
when :Symbol, :String
table_name = if act_as_attributes.include? arg.to_s
name.constantize.acting_as_model.to_s
else
name
end
if whitelist[table_name]
whitelist[table_name] << arg.to_s
else
whitelist[table_name] = [arg.to_s]
end
end
end
end
private
def make_search_query string
query = ""
whitelist.each do |key, value|
sub_query = (key.constantize.columns.map{|column| column.name if column.sql_type == "character varying"}.compact & value)
.inject("") { |query, column|
if query == ""
"#{key.constantize.table_name}.#{column} ILIKE '%#{string}%'"
else
"#{query} OR #{key.constantize.table_name}.#{column} ILIKE '%#{string}%'"
end
}
query = if query == ""
sub_query
else
"#{query} OR #{sub_query}"
end
end
query
end
def joins_actable_query
if name.constantize.methods.include? :acting_as_model
"LEFT JOIN #{name.constantize.acting_as_model.table_name}
ON #{name.constantize.acting_as_model.table_name}.actable_id = #{name.constantize.table_name}.id
AND #{name.constantize.acting_as_model.table_name}.actable_type = '#{name}'"
else
""
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment