diff --git a/activesupport/lib/active_support/core_ext/object/with_options.rb b/activesupport/lib/active_support/core_ext/object/with_options.rb index 11985fa828..3225bab4ca 100644 --- a/activesupport/lib/active_support/core_ext/object/with_options.rb +++ b/activesupport/lib/active_support/core_ext/object/with_options.rb @@ -5,9 +5,9 @@ class Object # An elegant way to factor duplication out of options passed to a series of # method calls. Each method called in the block, with the block variable as - # the receiver, will have its options merged with the default +options+ hash - # provided. Each method called on the block variable must take an options - # hash as its final argument. + # the receiver, will have its options merged with the default +options+ + # Hash or Hash-like object provided. Each method called on + # the block variable must take an options hash as its final argument. # # Without with_options, this code contains duplication: # diff --git a/activesupport/test/option_merger_test.rb b/activesupport/test/option_merger_test.rb index bb66f51bab..54195024a9 100644 --- a/activesupport/test/option_merger_test.rb +++ b/activesupport/test/option_merger_test.rb @@ -114,6 +114,21 @@ def test_option_merger_implicit_receiver assert_equal expected, @options end + def test_with_options_hash_like + hash_like = Class.new do + delegate :to_hash, :deep_merge, to: :@hash + + def initialize(hash) + @hash = hash + end + end + local_options = { "cool" => true } + scope = with_options(hash_like.new(@options)) + + assert_equal local_options, method_with_options(local_options) + assert_equal @options.merge(local_options), scope.method_with_options(local_options) + end + def test_with_options_no_block local_options = { "cool" => true } scope = with_options(@options)