Skip to content

Commit

Permalink
Support Object#with_options without a block
Browse files Browse the repository at this point in the history
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>
```
  • Loading branch information
seanpdoyle committed Nov 15, 2021
1 parent 15f6113 commit 8dc27b5
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 1 deletion.
5 changes: 5 additions & 0 deletions activesupport/CHANGELOG.md
@@ -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
Expand Down
21 changes: 20 additions & 1 deletion activesupport/lib/active_support/core_ext/object/with_options.rb
Expand Up @@ -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
4 changes: 4 additions & 0 deletions activesupport/lib/active_support/option_merger.rb
Expand Up @@ -30,5 +30,9 @@ def method_missing(method, *arguments, &block)
@context.__send__(method, *arguments, &block)
end
end

def respond_to_missing?(*arguments)
@context.respond_to?(*arguments)
end
end
end
8 changes: 8 additions & 0 deletions activesupport/test/option_merger_test.rb
Expand Up @@ -105,6 +105,14 @@ def test_option_merger_implicit_receiver
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
Expand Down

0 comments on commit 8dc27b5

Please sign in to comment.