diff --git a/app/filters/base_filter.rb b/app/filters/base_filter.rb index 093bc99d..f78ee976 100644 --- a/app/filters/base_filter.rb +++ b/app/filters/base_filter.rb @@ -5,6 +5,10 @@ # BaseFilter is more like an abstract parent class, but it also serves # as a NullObject version of the filter grouping, if you want one class BaseFilter + # This constant should be overriden if you need the ContributionController to + # accept additional parameters for this filter to work + ALLOWED_PARAMS = {} + # This method should be overridden to return a hash with the following keys: # * :name => a short string that the user will see that describes what type of filters these are # * :filters => the output a call to FilterOptionBlueprint.render_as_hash that represent each filter option to check or uncheck diff --git a/app/filters/category_filter.rb b/app/filters/category_filter.rb index 6f745171..40108a47 100644 --- a/app/filters/category_filter.rb +++ b/app/filters/category_filter.rb @@ -1,4 +1,7 @@ class CategoryFilter < BaseFilter + PARAM_NAME = 'Category' + ALLOWED_PARAMS = {PARAM_NAME => {}} + def self.filter_grouping { name: "Categories", @@ -8,9 +11,9 @@ def self.filter_grouping end def filter(scope) - return super unless parameters + return super if parameters[PARAM_NAME].blank? scope.tagged_with( - Category.roots.where(id: parameters.keys).pluck('name'), + Category.roots.where(id: parameters[PARAM_NAME].keys).pluck('name'), any: true ) end diff --git a/app/filters/contact_method_filter.rb b/app/filters/contact_method_filter.rb index c1373a6d..4b33ef05 100644 --- a/app/filters/contact_method_filter.rb +++ b/app/filters/contact_method_filter.rb @@ -1,4 +1,7 @@ class ContactMethodFilter < BaseFilter + PARAM_NAME = 'ContactMethod' + ALLOWED_PARAMS = {PARAM_NAME => {}} + def self.filter_grouping { name: 'Contact Methods', @@ -7,7 +10,7 @@ def self.filter_grouping end def filter(scope) - return super unless parameters - scope.joins(:person).where(people: { preferred_contact_method: parameters.keys }) + return super if parameters[PARAM_NAME].blank? + scope.joins(:person).where(people: { preferred_contact_method: parameters[PARAM_NAME].keys }) end end diff --git a/app/filters/contribution_type_filter.rb b/app/filters/contribution_type_filter.rb index 313699b3..f1e2c7cc 100644 --- a/app/filters/contribution_type_filter.rb +++ b/app/filters/contribution_type_filter.rb @@ -1,8 +1,11 @@ class ContributionTypeFilter + PARAM_NAME = 'ContributionType' + ALLOWED_PARAMS = {PARAM_NAME => {}} + def self.filter_grouping { name: 'Contribution Types', filter_options: [ - { id: 'ContributionType[Ask]', name: 'Ask' }, - { id: 'ContributionType[Offer]', name: 'Offer' } + { id: "#{PARAM_NAME}[Ask]", name: 'Ask' }, + { id: "#{PARAM_NAME}[Offer]", name: 'Offer' } ]} end ALL_ALLOWED_TYPES = ['Ask', 'Offer'].freeze @@ -14,7 +17,7 @@ def initialize(params) end def scopes - classes = parameters.blank? ? ALL_ALLOWED_TYPES : parameters.keys + classes = parameters.blank? || parameters[PARAM_NAME].blank? ? ALL_ALLOWED_TYPES : parameters[PARAM_NAME].keys classes.intersection(ALL_ALLOWED_TYPES).map do |type| type.constantize.matchable end diff --git a/app/filters/service_area_filter.rb b/app/filters/service_area_filter.rb index 4e6271ef..6036b7cb 100644 --- a/app/filters/service_area_filter.rb +++ b/app/filters/service_area_filter.rb @@ -1,4 +1,7 @@ class ServiceAreaFilter < BaseFilter + PARAM_NAME = 'ServiceArea' + ALLOWED_PARAMS = {PARAM_NAME => {}} + def self.filter_grouping { name: 'Service Areas', @@ -7,7 +10,7 @@ def self.filter_grouping end def filter(scope) - return super unless parameters - scope.where(service_area_id: parameters.keys) + return super if parameters[PARAM_NAME].blank? + scope.where(service_area_id: parameters[PARAM_NAME].keys) end end diff --git a/app/filters/urgency_filter.rb b/app/filters/urgency_filter.rb new file mode 100644 index 00000000..c636947d --- /dev/null +++ b/app/filters/urgency_filter.rb @@ -0,0 +1,16 @@ +class UrgencyFilter < BaseFilter + PARAM_NAME = 'UrgencyLevel' + ALLOWED_PARAMS = {PARAM_NAME => {}} + + def self.filter_grouping + { + name: 'Urgency', + filter_options: FilterOptionBlueprint.render_as_hash(UrgencyLevel::TYPES) + } + end + + def filter(scope) + return super if parameters[PARAM_NAME].blank? + scope.where(urgency_level_id: parameters[PARAM_NAME].keys) + end +end \ No newline at end of file diff --git a/app/models/browse_filter.rb b/app/models/browse_filter.rb index eae48e0a..f0cfcdfe 100644 --- a/app/models/browse_filter.rb +++ b/app/models/browse_filter.rb @@ -3,16 +3,15 @@ # BrowseFilter lets the browse page filter contributions by parameters, delegating much of the actual filtering # to the classes listed in BrowseFilter::FILTER_CLASSES class BrowseFilter - FILTERS = { - 'Category' => CategoryFilter, - 'ServiceArea' => ServiceAreaFilter, - 'ContactMethod' => ContactMethodFilter, - 'ContributionType' => ContributionTypeFilter - # 'UrgencyLevel' => UrgencyLevelFilter - }.freeze - FILTER_CLASSES = FILTERS.values.freeze - ALLOWED_PARAMS = FILTERS.keys.each_with_object({}) do |key, hash| - hash[key] = {} + FILTER_CLASSES = [ + CategoryFilter, + ServiceAreaFilter, + ContactMethodFilter, + ContributionTypeFilter, + UrgencyFilter + ].freeze + ALLOWED_PARAMS = FILTER_CLASSES.each_with_object({}) do |filter, hash| + hash.merge! filter::ALLOWED_PARAMS end.freeze attr_reader :parameters @@ -29,16 +28,16 @@ def initialize(parameters) def contributions # ContributionTypeFilter is special and needs to come first because of Single Table Inheretence # Currently, the only other option seemed to be pulling in a gem that supports UNION queries in SQL - starting_relations = ContributionTypeFilter.new(parameters['ContributionType']).scopes + starting_relations = ContributionTypeFilter.new(parameters).scopes # So using whatever relations ContributionTypeFilter gives us (unmatched asks, unmatched offers, etc.) - @contributions ||= FILTERS.reduce(starting_relations) do |resulting_relations, (filter_name, klass)| + @contributions ||= FILTER_CLASSES.reduce(starting_relations) do |resulting_relations, filter_class| # Skip ContributionTypeFilter because we've already used it - next resulting_relations if klass == ContributionTypeFilter + next resulting_relations if filter_class == ContributionTypeFilter # then filter the relations further based on the rules in each class for doing so resulting_relations.map do |scope| - klass.new(parameters[filter_name]).filter(scope) + filter_class.new(parameters).filter(scope) end end.flatten end