Created
February 10, 2010 17:57
-
-
Save jejacks0n/300614 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module FilterableResource | |
# to test {:filter => {:users => .. } | |
# {:method => 'any', :terms => ['first', 'second'], :fields => 'all'} | |
# {:method => 'any', :terms => 'first second', :fields => 'all'} | |
# {:method => 'any', :terms => 'first', :fields => ['first_name', 'last_name']} | |
# {:method => 'any', :terms => 'first', :fields => 'first_name last_name'} | |
# {:method => 'all', :terms => ['first', 'second'], :fields => 'all'} | |
# {:method => 'all', :terms => 'first second', :fields => 'all'} | |
# {:method => 'all', :terms => 'first', :fields => 'first_name'} | |
# {:method => 'all', :terms => 'first', :fields => ['first_name', 'last_name']} | |
# {:method => 'exact', :terms => ['first', 'second'], :fields => 'all'} | |
# {:method => 'exact', :terms => 'first second', :fields => 'all'} | |
# {:method => 'exact', :terms => 'first second', :fields => 'first_name'} | |
# {:method => 'exact', :terms => 'first second', :fields => ['first_name', 'last_name']} | |
# {:method => 'all_in_order', :terms => ['first', 'second'], :fields => 'all'} | |
# {:method => 'all_in_order', :terms => 'first second', :fields => 'all'} | |
# {:method => 'all_in_order', :terms => 'first second', :fields => 'first_name'} | |
# {:method => 'all_in_order', :terms => 'second first', :fields => 'first_name'} | |
# {:method => 'all_in_order', :terms => 'second first', :fields => ['first_name', 'last_name']} | |
# filter[user][terms]=matching+terms | |
# filter[user][method]=any | |
# filter[user][fields]=all - filter[user][field]=first_name+last_name - filter[user][field]=first_name&filter[user][field]=last_name | |
module ActiveRecordExtensions | |
FILTER_METHODS = [:any, :all, :all_in_order, :exact] | |
# acts_as_filterable :first_name, :last_name, :login, :method => :any | |
def acts_as_filterable(options = {}) | |
cattr_accessor :filterable_fields, :default_filter_method | |
self.filterable_fields = column_names.map { |column_name| column_name.to_sym } | |
self.filterable_fields = if options[:only] | |
options[:only] | |
elsif options[:except] | |
self.filterable_fields - options[:except] | |
else | |
self.filterable_fields | |
end | |
self.filterable_fields.collect!{ |field| field.to_s } | |
self.default_filter_method = options[:method] || :any | |
attach_filterable_scopes | |
end | |
def attach_filterable_scopes | |
# The named scope expects specific things from the hash passed in. It | |
# generates conditions based on the params passed in. | |
# | |
# Example: | |
# {:filter => { | |
# :user => {:method => 'any', :terms => 'first second', :fields => 'all'}} | |
# } | |
# | |
self.named_scope :filtered_from, lambda { |params| | |
return unless params.include?(:filter) and params[:filter][self.table_name.to_sym] | |
options = params[:filter][self.table_name.to_sym] | |
method = filter_method_from_options(options) | |
terms = filter_terms_from_options(options, method) | |
fields = filter_fields_from_options(options) | |
return if fields.blank? or terms.compact.blank? | |
conditions = [] | |
joins = [] | |
terms.each{ |term| | |
value = term.downcase | |
fields.each { |field| | |
if field.include?('.') | |
#join_table, join_field = field.split('.') | |
#:joins => :state_events, :conditions => [ "state_events.name = 'shipped'" ] | |
#joins << '' | |
else | |
field = "#{table_name}.#{field}" | |
end | |
conditions << ["LOWER(#{field}) LIKE ?", "%#{value}%"] | |
} | |
} | |
conditions = conditions.compact.unzip | |
if conditions.length > 1 && conditions[0] = conditions[0].join((method != :all) ? ' OR ' : ' AND ') | |
{:conditions => conditions.empty? ? nil : conditions.flatten} | |
end | |
} | |
end | |
def filter_method_from_options(options) | |
if options[:method].present? && FILTER_METHODS.include?(options[:method].to_sym) | |
options[:method].to_sym | |
else | |
self.default_filter_method | |
end | |
end | |
def filter_terms_from_options(options, method) | |
if options[:terms].is_a?(Array) && method == :exact | |
[options[:terms].join(' ')] | |
elsif method == :exact | |
[options[:terms]] | |
elsif method == :all_in_order | |
[options[:terms].split(' ').join('%')] | |
else | |
options[:terms].split(' ') | |
end | |
end | |
def filter_fields_from_options(options) | |
fields = if options[:fields] == 'all' | |
self.filterable_fields | |
elsif options[:fields].is_a?(Array) | |
options[:fields] | |
else | |
options[:fields].split(' ') | |
end | |
fields.reject!{ |field| !self.filterable_fields.include? field.to_s } | |
end | |
end | |
end | |
ActiveRecord::Base.extend FilterableResource::ActiveRecordExtensions |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment