-
-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
I think this is everything for the refactor
- Loading branch information
Howard M. Miller
committed
Sep 23, 2020
1 parent
c4ca807
commit 9bb4c30
Showing
11 changed files
with
104 additions
and
89 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,17 @@ | ||
# FilterOptionsBlueprint emits a structure that the browse Vue page can turn | ||
# into checkboxes or other form UI elements to filter a list of contributions | ||
# | ||
# We assume that there's a top level type of filter (e.g ContactMethodFilter) | ||
# that then references a series of these FilterOptionBlueprint objects for | ||
# each element (e.g. each available contact method) | ||
class FilterOptionsBlueprint < Blueprinter::Base | ||
# The identifier here needs to be in a format that the BrowseFilter can then | ||
# interpret and use to filter results | ||
identifier :id do |category, _options| | ||
"#{category.class.to_s}[#{category.id}]" | ||
"#{category.class}[#{category.id}]" | ||
end | ||
|
||
# This is currently used as a display name so people can understand | ||
# which each option represents | ||
field :name | ||
end |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# This class has information about how we sort and filter categories | ||
# and is capable of accepting a model scope and adding additional | ||
# `where` clauses to it in order to filter the message | ||
|
||
# BasicFilter is more like an abstract parent class, but it also serves | ||
# as a NullObject version of the filter, if you want one | ||
class BasicFilter | ||
# 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 FilterOptionsBlueprint.render_as_hash that represent each filter option to check or uncheck | ||
def self.options | ||
{} | ||
end | ||
|
||
attr_reader :parameters | ||
|
||
def initialize(parameters) | ||
@parameters = parameters | ||
end | ||
|
||
# By default, return the model scope unfiltered | ||
def filter(scope) | ||
scope | ||
end | ||
end |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,13 @@ | ||
class ContactMethodFilter | ||
class ContactMethodFilter < BasicFilter | ||
def self.options | ||
{ | ||
name: 'Contact Methods', | ||
filters: FilterOptionsBlueprint.render_as_hash(ContactMethod.enabled.distinct(:name)) | ||
} | ||
end | ||
|
||
def self.filter(relation, _parameters) | ||
relation | ||
def filter(scope) | ||
return super unless parameters | ||
scope.joins(:person).where(people: { preferred_contact_method: parameters.keys }) | ||
end | ||
end | ||
end |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,13 @@ | ||
class ServiceAreaFilter | ||
class ServiceAreaFilter < BasicFilter | ||
def self.options | ||
{ | ||
name: 'Service Areas', | ||
filters: FilterOptionsBlueprint.render_as_hash(ServiceArea.i18n) | ||
} | ||
end | ||
|
||
def self.filter(relation, _parameters) | ||
relation | ||
def filter(scope) | ||
return super unless parameters | ||
scope.where(service_area_id: parameters.keys) | ||
end | ||
end | ||
end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,51 @@ | ||
# BrowseFilter code currently makes a lot of assumptions about the model coming in | ||
# I'm going to have to some lifting to make it accept other models | ||
# but at least all these changes will be isolated to this class | ||
# 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 = [ContributionTypeFilter, CategoryFilter, ServiceAreaFilter, ContactMethodFilter] | ||
# FILTERS = { | ||
# 'ServiceArea' => ->(ids, scope) { scope.where(service_area: ids) }, | ||
# 'ContactMethod' => ->(ids, scope) { scope.joins(:person).where(people: {preferred_contact_method: ids})}, | ||
# 'Category' => lambda do |ids, scope| | ||
# scope.tagged_with( | ||
# Category.roots.where(id: ids).pluck('name'), | ||
# any: true | ||
# ) | ||
# end, | ||
# 'UrgencyLevel' => lambda do |ids, scope| | ||
# ids.length == UrgencyLevel::TYPES.length ? scope : scope.where(urgency_level_id: ids) | ||
# end | ||
# }.freeze | ||
|
||
ALLOWED_MODEL_NAMES = ['Ask', 'Offer'].freeze | ||
# ALLOWED_PARAMS = (['ContributionType'] + FILTERS.keys).each_with_object({}) do |key, hash| | ||
# hash[key] = {} | ||
# end.freeze | ||
FILTERS = { | ||
'Category' => CategoryFilter, | ||
'ServiceArea' => ServiceAreaFilter, | ||
'ContactMethod' => ContactMethodFilter, | ||
'ContributionType' => ContributionTypeFilter | ||
# 'UrgencyLevel' => UrgencyLevelFilter | ||
}.freeze | ||
FILTER_CLASSES = FILTERS.values.freeze | ||
ALLOWED_PARAMS_FILTER = FILTERS.keys.each_with_object({}) do |key, hash| | ||
hash[key] = {} | ||
end.freeze | ||
|
||
attr_reader :parameters, :context | ||
|
||
def self.filter_options_json | ||
FILTERS.map(&:options).to_json | ||
FILTER_CLASSES.map(&:options).to_json | ||
end | ||
|
||
def initialize(parameters, context = nil) | ||
@parameters = parameters | ||
@context = context | ||
end | ||
|
||
# Return a filtered array of contributions | ||
def contributions | ||
model_names = parameters['ContributionType']&.keys || ALLOWED_MODEL_NAMES | ||
models = model_names.intersection(ALLOWED_MODEL_NAMES).map(&:constantize) | ||
@contributions ||= models.map { |model| filters(model) }.flatten | ||
# 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 | ||
|
||
# So using whatever relations ContributionTypeFilter gives us (unmatched asks, unmatched offers, etc.) | ||
@contributions ||= FILTERS.reduce(starting_relations) do |resulting_relations, (filter_name, klass)| | ||
# Skip ContributionTypeFilter because we've already used it | ||
next resulting_relations if klass == 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) | ||
end | ||
end.flatten | ||
end | ||
|
||
# These options are for the blueprint so it can add appropriate links to the json for each contribution | ||
def options | ||
return {} unless context | ||
|
||
{ respond_path: ->(id) { context.respond_contribution_path(id)} } | ||
end | ||
|
||
private | ||
|
||
def filter(model) | ||
# parameters.keys.reduce(model.unmatched) do |scope, key| | ||
# filter = FILTERS.fetch(key, ->(_condition, s) {s}) | ||
# filter.call(parameters[key], scope) | ||
# end | ||
|
||
FILTERS.reduce(model.unmatched) do |relation, filter| | ||
filter.filter(relation, parameters) | ||
end | ||
{ respond_path: ->(id) { context.respond_contribution_path(id) } } | ||
end | ||
end |
This file was deleted.
Oops, something went wrong.
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
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