8000 Avoid rendering huge associations (#5548) · activeadmin/activeadmin@5a7db30 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5a7db30

Browse files
DanielHeathdeivid-rodriguez
authored andcommitted
Avoid rendering huge associations (#5548)
Render a text filter instead of a select for large associations (opt-in)
1 parent dcff714 commit 5a7db30

File tree

5 files changed

+129
-1
lines changed

5 files changed

+129
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Enhancements
66

77
* Make optimization to not use expensive COUNT queries also work for decorated actions. [#5811] by [@irmela]
8+
* Render a text filter instead of a select for large associations (opt-in) [#5548] by [@DanielHeath]
89

910
## 2.3.1 [](https://github.com/activeadmin/activeadmin/compare/v2.3.0..v2.3.1)
1011

@@ -508,6 +509,7 @@ Please check [0-6-stable] for previous changes.
508509
[#5822]: https://github.com/activeadmin/activeadmin/pull/5822
509510
[#5826]: https://github.com/activeadmin/activeadmin/pull/5826
510511
[#5831]: https://github.com/activeadmin/activeadmin/pull/5831
512+
[#5548]: https://github.com/activeadmin/activeadmin/pull/5548
511513
[#5842]: https://github.com/activeadmin/activeadmin/pull/5842
512514
[#5854]: https://github.com/activeadmin/activeadmin/pull/5854
513515

features/index/filters.feature

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,79 @@ Feature: Index Filtering
265265
When I select "The arrogant president" from "Posts"
266266
And I press "Filter"
267267
And I should see 1 user in the table
268+
269+
Scenario: Too many categories to show
270+
Given a category named "Astrology" exists
271+
And a category named "Astronomy" exists
272+
And a category named "Navigation" exists
273+
And a post with the title "Star Signs" in category "Astrology" exists
274+
And a post with the title "Constellations" in category "Astronomy" exists
275+
And a post with the title "Compass and Sextant" in category "Navigation" exists
276+
And an index configuration of:
277+
"""
278+
ActiveAdmin.register Category
279+
ActiveAdmin.register Post do
280+
config.namespace.maximum_association_filter_arity = 3
281+
end
282+
"""
283+
And I am on the index page for posts
284+
Then I should see "Category" within "#filters_sidebar_section label[for="q_custom_category_id"]"
285+
And I should not see "Category name starts with" within "#filters_sidebar_section"
286+
287+
Given an index configuration of:
288+
"""
289+
ActiveAdmin.register Category
290+
ActiveAdmin.register Post do
291+
config.namespace.maximum_association_filter_arity = 2
292+
end
293+
"""
294+
And I am on the index page for posts
295+
Then I should see "Category name starts with" within "#filters_sidebar_section"
296+
When I fill in "Category name starts with" with "Astro"
297+
And I press "Filter"
298+
Then I should see "Star Signs"
299+
And I should see "Constellations"
300+
And I should not see "Compass and Sextant"
301+
302+
Given an index configuration of:
303+
"""
304+
ActiveAdmin.register Category
305+
ActiveAdmin.register Post do
306+
config.namespace.maximum_association_filter_arity = 2
307+
config.namespace.filter_method_for_large_association = '_contains'
308+
end
309+
"""
310+
And I am on the index page for posts
311+
Then I should see "Category name contains" within "#filters_sidebar_section"
312+
When I fill in "Category name contains" with "Astro"
313+
And I press "Filter"
314+
Then I should see "Star Signs"
315+
And I should see "Constellations"
316+
And I should not see "Compass and Sextant"
317+
318+
Given an index configuration of:
319+
"""
320+
ActiveAdmin.register Category
321+
ActiveAdmin.register Post do
322+
config.namespace.maximum_association_filter_arity = :unlimited
323+
config.namespace.filter_method_for_large_association = '_contains'
324+
end
325+
"""
326+
And I am on the index page for posts
327+
Then I should see "Category" within "#filters_sidebar_section"
328+
When I select "Astronomy" from "Category"
329+
And I press "Filter"
330+
Then I should not see "Star Signs"
331+
And I should see "Constellations"
332+
And I should not see "Compass and Sextant"
333+
334+
Given an index configuration of:
335+
"""
336+
ActiveAdmin.register Category
337+
ActiveAdmin.register Post do
338+
config.namespace.maximum_association_filter_arity = :unlimited
339+
end
340+
"""
341+
And I am on the index page for posts
342+
Then I should see "Category" within "#filters_sidebar_section label[for="q_custom_category_id"]"
343+
And I should not see "Category name starts with" within "#filters_sidebar_section"

lib/active_admin/filters/resource_extension.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,36 @@ def default_association_filters
129129
not_poly.reject! { |r| r.chain.length > 2 }
130130

131131
filters = poly.map(&:foreign_type) + not_poly.map(&:name)
132+
133+
# Check high-arity associations for filterable columns
134+
max = namespace.maximum_association_filter_arity
135+
if max != :unlimited
136+
high_arity, low_arity = not_poly.partition do |r|
137+
r.klass.reorder(nil).limit(max + 1).count > max
138+
end
139+
140+
# Remove high-arity associations with no searchable column
141+
high_arity = high_arity.select(&method(:searchable_column_for))
142+
143+
high_arity = high_arity.map { |r| r.name.to_s + "_" + searchable_column_for(r) + namespace.filter_method_for_large_association }
144+
145+
filters = poly.map(&:foreign_type) + low_arity.map(&:name) + high_arity
146+
end
147+
132148
filters.map &:to_sym
133149
else
134150
[]
135151
end
136152
end
137153

154+
def search_columns
155+
@search_columns ||= namespace.filter_columns_for_large_association.map(&:to_s)
156+
end
157+< D396 /span>
158+
def searchable_column_for(relation)
159+
relation.klass.column_names.find { |name| search_columns.include?(name) }
160+
end
161+
138162
def add_filters_sidebar_section
139163
self.sidebar_sections << filters_sidebar_section
140164
end

lib/active_admin/namespace_settings.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,5 +106,18 @@ class NamespaceSettings < DynamicSettingsNode
106106

107107
# Include association filters by default
108108
register :include_default_association_filters, true
109+
110+
register :maximum_association_filter_arity, :unlimited
111+
112+
register :filter_columns_for_large_association, [
113+
:display_name,
114+
:full_name,
115+
:name,
116+
:username,
117+
:login,
118+
:title,
119+
:email,
120+
]
121+
register :filter_method_for_large_association, '_starts_with'
109122
end
110123
end

lib/generators/active_admin/install/templates/active_admin.rb.erb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,12 +286,25 @@ ActiveAdmin.setup do |config|
286286
# config.filters = true
287287
#
288288
# By default the filters include associations in a select, which means
289-
# that every record will be loaded for each association.
289+
# that every record will be loaded for each association (up
290+
# to the value of config.maximum_association_filter_arity).
290291
# You can enabled or disable the inclusion
291292
# of those filters by default here.
292293
#
293294
# config.include_default_association_filters = true
294295

296+
# config.maximum_association_filter_arity = 256 # default value of :unlimited will change to 256 in a future version
297+
# config.filter_columns_for_large_association, [
298+
# :display_name,
299+
# :full_name,
300+
# :name,
301+
# :username,
302+
# :login,
303+
# :title,
304+
# :email,
305+
# ]
306+
# config.filter_method_for_large_association, '_starts_with'
307+
295308
# == Head
296309
#
297310
# You can add your own content to the site head like analytics. Make sure

0 commit comments

Comments
 (0)
0