Support `Object#with_options` without a block

When the block argument is omitted, the decorated Object instance is returned:

```ruby
 # app/helpers/my_styled_helpers.rb
 module MyStyledHelpers
   def styled
     with_options style: "color: red;"
   end
 end

 # styled.link_to "I'm red", "/"
 # #=> <a href="/" style="color: red;">I'm red</a>

 # styled.button_tag "I'm red too!"
 # #=> <button style="color: red;">I'm red too!</button>
```
This commit is contained in:
Sean Doyle 2021-07-02 11:42:27 -04:00
parent 15f6113622
commit 8dc27b59c5
4 changed files with 37 additions and 1 deletions

View File

@ -1,3 +1,8 @@
* Invoking `Object#with_options` without a `&block` argument returns the
`ActiveSupport::OptionMerger` instance.
*Sean Doyle*
* `Rails.application.executor` hooks are now called around every tests.
This helps to better simulate request or job local state being reset around tests and prevent state

View File

@ -75,8 +75,27 @@ class Object
# end
# end
#
# When the block argument is omitted, the decorated Object instance is returned:
#
# module MyStyledHelpers
# def styled
# with_options style: "color: red;"
# end
# end
#
# # styled.link_to "I'm red", "/"
# # #=> <a href="/" style="color: red;">I'm red</a>
#
# # styled.button_tag "I'm red too!"
# # #=> <button style="color: red;">I'm red too!</button>
#
def with_options(options, &block)
option_merger = ActiveSupport::OptionMerger.new(self, options)
block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
if block.nil?
option_merger
else
block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
end
end
end

View File

@ -30,5 +30,9 @@ module ActiveSupport
@context.__send__(method, *arguments, &block)
end
end
def respond_to_missing?(*arguments)
@context.respond_to?(*arguments)
end
end
end

View File

@ -105,6 +105,14 @@ class OptionMergerTest < ActiveSupport::TestCase
assert_equal expected, @options
end
def test_with_options_no_block
local_options = { "cool" => true }
scope = with_options(@options)
assert_equal local_options, method_with_options(local_options)
assert_equal @options.merge(local_options), scope.method_with_options(local_options)
end
private
def method_with_options(options = {})
options