mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
537b071002
cd31e113c0
switched to passing options as keyword arguments, which always creates a new hash.9e4ff29f74
removed a now-unnecessary call to `dup`, since the options could no longer be accidentally mutated.a55620f3fa
switched back to passing options as a positional argument for Ruby < 2.7, but didn't restore the call to `dup`, which meant that the same options hash was now passed with every method call and mutations leaked from one call to another.
46 lines
1.3 KiB
Ruby
46 lines
1.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "active_support/core_ext/hash/deep_merge"
|
|
require "active_support/core_ext/symbol/starts_ends_with"
|
|
|
|
module ActiveSupport
|
|
class OptionMerger #:nodoc:
|
|
instance_methods.each do |method|
|
|
undef_method(method) unless method.start_with?("__", "instance_eval", "class", "object_id")
|
|
end
|
|
|
|
def initialize(context, options)
|
|
@context, @options = context, options
|
|
end
|
|
|
|
private
|
|
def method_missing(method, *arguments, &block)
|
|
options = nil
|
|
if arguments.first.is_a?(Proc)
|
|
proc = arguments.pop
|
|
arguments << lambda { |*args| @options.deep_merge(proc.call(*args)) }
|
|
elsif arguments.last.respond_to?(:to_hash)
|
|
options = @options.deep_merge(arguments.pop)
|
|
else
|
|
options = @options
|
|
end
|
|
|
|
invoke_method(method, arguments, options, &block)
|
|
end
|
|
|
|
if RUBY_VERSION >= "2.7"
|
|
def invoke_method(method, arguments, options, &block)
|
|
if options
|
|
@context.__send__(method, *arguments, **options, &block)
|
|
else
|
|
@context.__send__(method, *arguments, &block)
|
|
end
|
|
end
|
|
else
|
|
def invoke_method(method, arguments, options, &block)
|
|
arguments << options.dup if options
|
|
@context.__send__(method, *arguments, &block)
|
|
end
|
|
end
|
|
end
|
|
end
|