-
-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add dynamic counts to search filters #5471
base: main
Are you sure you want to change the base?
Conversation
This reverts commit 84872dc.
(There are still some test and linting issues here.) |
Maybe I overreacted. The newly added count queries have a similar speed as the existing count query that already ran for pagination. I have already removed the counts for the submission pages, as it was unbearably slow there (but these pages where already way to slow on naos anyway). The activities page is an edge case. With 7 filters the increase in query time can be up to 300ms, which is about 20% of the total time required to render the page. This makes interactivity on naos feel slightly suboptimal. |
delegate :filter_options, to: :class | ||
self.filter_options = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also seems weird to me. It should be possible to delegate to the controller instance instead of the class, which would be better, IMO.
app/models/activity.rb
Outdated
scope :by_description_languages, lambda { |languages| | ||
by_language = all # allow chaining of scopes | ||
by_language = by_language.where(description_en_present: true) if languages.include? 'en' | ||
by_language = by_language.where(description_nl_present: true) if languages.include? 'nl' | ||
by_language | ||
} | ||
define_singleton_method('description_languages_filter_options') do | ||
scope = unscoped.where(id: select(:id)) | ||
|
||
[{ id: 'nl', name: I18n.t('js.nl'), count: scope.where(description_nl_present: true).count }, | ||
{ id: 'en', name: I18n.t('js.en'), count: scope.where(description_en_present: true).count }] | ||
.filter { |lang| lang[:count].positive? } | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add an extra method to the concern that handles cases like this (and popularity below). It also occurs in submission, IIUC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have now added this extra method:
def filter_options_for(name, &block)
define_singleton_method("#{name}_filter_options", &block)
end
Which does make it a bit more readable. But except for hiding the define_singleton_method
it doesn't do much, as these functions don't have much in common
Co-authored-by: Charlotte Van Petegem <charlotte.vanpetegem@ugent.be>
@coderabbitai review |
1 similar comment
@coderabbitai review |
rebase and request review |
This pull request contains a refactor of search filters. It adds dynamic counts of the expected results to all search filters. When already partially filtered, it also limits the other filters to only show relevant options.
The initial goal was to get rid of some old code that used js functions as part of 'filterCollection' objects to extract the color and paramVal from a filter option. This made most related code quite ugly and there was no longer any need for it.
So with cc610d6 and 810fa47 I made filterCollection a pure map of data objects.
With these changes it became a lot simpler to dynamically update filters.
I tried to write generic concerns that automatically define a dynamic option count when defining a scope. This way the end result should be less specific code.
In the most basic case writing a filter for a given field of a model is as simple as writing
filterable_by :field
in the model and writinghas_filter :field
in the controller. In the controller, the@filters
variable can then be set by callingfilters(elements)
on the unfiltered list of elements.@filters
is then used to update the shown filter options and counts.Common cases, such as enums and foreign keys can be filtered using
filterable_by :field, is_enum: true
andfilterable_by :field, model: Model
respectively.Naturally there are always some more complex cases, in which case a custom name_hash function can be written or even a full custom count function. See
activity.rb
for some examples of this.The most complex case were
course_labels
as these required the course as extra argument. For now these are generalized in their own specific reusable function.