Skip to content

Commit

Permalink
Add helper for running class_exec with keywords when needed
Browse files Browse the repository at this point in the history
  • Loading branch information
JonRowe committed Apr 7, 2020
1 parent 63c03e5 commit a82ab9c
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 0 deletions.
31 changes: 31 additions & 0 deletions lib/rspec/support/with_keywords_when_needed.rb
@@ -0,0 +1,31 @@
module RSpec
module Support
module WithKeywordsWhenNeeded
# This module adds keyword sensitive support for core ruby methods
# where we cannot use `ruby2_keywords` directly.

module_function

if RSpec::Support::RubyFeatures.kw_args_supported?
# Remove this in RSpec 4 in favour of explictly passed in kwargs where
# this is used. Works around a warning in Ruby 2.7

def class_exec(klass, *args, &block)
if MethodSignature.new(block).has_kw_args_in?(args)
binding.eval(<<-CODE, __FILE__, __LINE__)
kwargs = args.pop
klass.class_exec(*args, **kwargs, &block)
CODE
else
klass.class_exec(*args, &block)
end
end
ruby2_keywords :class_exec if respond_to?(:ruby2_keywords, true)
else
def class_exec(klass, *args, &block)
klass.class_exec(*args, &block)
end
end
end
end
end
48 changes: 48 additions & 0 deletions spec/rspec/support/with_keywords_when_needed_spec.rb
@@ -0,0 +1,48 @@
require 'rspec/support/with_keywords_when_needed'

module RSpec::Support
RSpec.describe "WithKeywordsWhenNeeded" do

describe ".class_exec" do
extend RubyFeatures

let(:klass) do
Class.new do
def self.check_argument(argument)
raise ArgumentError unless argument == 42
end
end
end

def run(klass, *args, &block)
WithKeywordsWhenNeeded.class_exec(klass, *args, &block)
end

it "will run a block without keyword arguments" do
run(klass, 42) { |arg| check_argument(arg) }
end

it "will run a block with a hash with out keyword arguments" do
run(klass, "value" => 42) { |arg| check_argument(arg["value"]) }
end

it "will run a block with optional keyword arguments when none are provided", :if => kw_args_supported? do
binding.eval(<<-CODE, __FILE__, __LINE__)
run(klass, 42) { |arg, val: nil| check_argument(arg) }
CODE
end

it "will run a block with optional keyword arguments when they are provided", :if => required_kw_args_supported? do
binding.eval(<<-CODE, __FILE__, __LINE__)
run(klass, val: 42) { |val: nil| check_argument(val) }
CODE
end

it "will run a block with required keyword arguments", :if => required_kw_args_supported? do
binding.eval(<<-CODE, __FILE__, __LINE__)
run(klass, val: 42) { |val:| check_argument(val) }
CODE
end
end
end
end

0 comments on commit a82ab9c

Please sign in to comment.