java-topology/defects/rails/patch/rails-0013-collection-helpers-selected-set.patch

50 lines
2.1 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Fixes rails-0013: CollectionHelpers#default_html_options_for_collection — Array(current_value).map(&:to_s).include? inside render_collection loop O(C×V×4) per collection render.
--- a/actionview/lib/action_view/helpers/tags/collection_helpers.rb
+++ b/actionview/lib/action_view/helpers/tags/collection_helpers.rb
@@ DEFECT rails-0013: lines 47-69 and 75-84
def default_html_options_for_collection(item, value)
html_options = @html_options.dup
[:checked, :selected, :disabled, :readonly].each do |option|
current_value = @options[option]
next if current_value.nil?
accept = if current_value.respond_to?(:call)
current_value.call(item)
else
- Array(current_value).map(&:to_s).include?(value.to_s) # O(V) Array rebuild + scan per item
+ # moved to render_collection: @_option_sets[option] is a pre-built Set
+ @_option_sets[option].include?(value.to_s) # FIX: O(1) per item
end
...
end
end
+ def build_option_sets
+ @_option_sets = {}
+ [:checked, :selected, :disabled, :readonly].each do |opt|
+ val = @options[opt]
+ next if val.nil? || val.respond_to?(:call)
+ @_option_sets[opt] = Array(val).map(&:to_s).to_set # FIX: build once O(V)
+ end
+ end
def render_collection
+ build_option_sets
@collection.map do |item|
value = value_for_collection(item, @value_method)
...
end
end
# BEFORE: Array(current_value).map(&:to_s).include?(value.to_s) — rebuilds the array
# AND scans it for every item × every option type
# C items × 4 option types × V values = O(C×4×V) per render
# AFTER: Sets built once before the loop; O(1) lookup per item × option type
# O(C×4) per render
# Severity: HIGH — every collection_check_boxes / collection_radio_buttons hits this path
# Speedup: ~V× where V = number of option values (typical: 2-50)
# At C=200 items, V=20 checked values: 16,000 → 800 ops per render