mirror of
https://github.com/thoughtbot/factory_bot.git
synced 2022-11-09 11:43:51 -05:00
Fix ruby 2.7 kwargs warning
Ruby 2.7 deprecated passing kwargs when the method expects a hash or passing a hash when the method expects kwargs. In factory_bot, this creates the warning: ``` /Users/hparker/code/factory_bot/lib/factory_bot/decorator/new_constructor.rb:9: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call /Users/hparker/code/factory_bot/spec/acceptance/initialize_with_spec.rb:220: warning: The called method `initialize' is defined here ``` We can fix this warning by updating the syntax. We need to include `**kwargs` in the `method_missing` calls when we are on ruby 2.7 or later. In decorator.rb, adding `**kwargs` alone doesn't work since adding `**kwargs` can change what arguments remain in the `args`. In this case we have to class eval the method if we are running ruby 2.7. This way the syntax is valid in previous versions and we can use the `...` operator which allows us to avoid changing the arguments passed on in method missing. Co-authored-by: Lee Quarella <leequarella@gmail.com>
This commit is contained in:
parent
468536ff65
commit
5c071d42fd
4 changed files with 45 additions and 16 deletions
|
@ -6,17 +6,29 @@ module FactoryBot
|
||||||
@component = component
|
@component = component
|
||||||
end
|
end
|
||||||
|
|
||||||
def method_missing(name, *args, &block) # rubocop:disable Style/MethodMissingSuper
|
if ::Gem::Version.new(::RUBY_VERSION) >= ::Gem::Version.new("2.7")
|
||||||
@component.send(name, *args, &block)
|
class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
||||||
|
def method_missing(...) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
|
||||||
|
@component.send(...)
|
||||||
end
|
end
|
||||||
|
|
||||||
def respond_to_missing?(name, include_private = false)
|
def send(...)
|
||||||
@component.respond_to?(name, true) || super
|
__send__(...)
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
else
|
||||||
|
def method_missing(name, *args, &block) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
|
||||||
|
@component.send(name, *args, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
def send(symbol, *args, &block)
|
def send(symbol, *args, &block)
|
||||||
__send__(symbol, *args, &block)
|
__send__(symbol, *args, &block)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def respond_to_missing?(name, include_private = false)
|
||||||
|
@component.respond_to?(name, true) || super
|
||||||
|
end
|
||||||
|
|
||||||
def self.const_missing(name)
|
def self.const_missing(name)
|
||||||
::Object.const_get(name)
|
::Object.const_get(name)
|
||||||
|
|
|
@ -6,10 +6,17 @@ module FactoryBot
|
||||||
@invoked_methods = []
|
@invoked_methods = []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if ::Gem::Version.new(::RUBY_VERSION) >= ::Gem::Version.new("2.7")
|
||||||
|
def method_missing(name, *args, **kwargs, &block) # rubocop:disable Style/MissingRespondToMissing
|
||||||
|
@invoked_methods << name
|
||||||
|
super
|
||||||
|
end
|
||||||
|
else
|
||||||
def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing
|
def method_missing(name, *args, &block) # rubocop:disable Style/MissingRespondToMissing
|
||||||
@invoked_methods << name
|
@invoked_methods << name
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def __invoked_methods__
|
def __invoked_methods__
|
||||||
@invoked_methods.uniq
|
@invoked_methods.uniq
|
||||||
|
|
|
@ -35,13 +35,23 @@ module FactoryBot
|
||||||
|
|
||||||
attr_writer :instance
|
attr_writer :instance
|
||||||
|
|
||||||
def method_missing(method_name, *args, &block) # rubocop:disable Style/MethodMissingSuper
|
if ::Gem::Version.new(::RUBY_VERSION) >= ::Gem::Version.new("2.7")
|
||||||
|
def method_missing(method_name, *args, **kwargs, &block) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
|
||||||
|
if @instance.respond_to?(method_name)
|
||||||
|
@instance.send(method_name, *args, **kwargs, &block)
|
||||||
|
else
|
||||||
|
SyntaxRunner.new.send(method_name, *args, **kwargs, &block)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
def method_missing(method_name, *args, &block) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
|
||||||
if @instance.respond_to?(method_name)
|
if @instance.respond_to?(method_name)
|
||||||
@instance.send(method_name, *args, &block)
|
@instance.send(method_name, *args, &block)
|
||||||
else
|
else
|
||||||
SyntaxRunner.new.send(method_name, *args, &block)
|
SyntaxRunner.new.send(method_name, *args, &block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def respond_to_missing?(method_name, _include_private = false)
|
def respond_to_missing?(method_name, _include_private = false)
|
||||||
@instance.respond_to?(method_name) || SyntaxRunner.new.respond_to?(method_name)
|
@instance.respond_to?(method_name) || SyntaxRunner.new.respond_to?(method_name)
|
||||||
|
|
|
@ -201,7 +201,7 @@ describe "initialize_with has access to all attributes for construction" do
|
||||||
|
|
||||||
name { email.gsub(/@.+/, "") }
|
name { email.gsub(/@.+/, "") }
|
||||||
|
|
||||||
initialize_with { new(attributes) }
|
initialize_with { new(**attributes) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ describe "initialize_with with an 'attributes' attribute" do
|
||||||
FactoryBot.define do
|
FactoryBot.define do
|
||||||
factory :user do
|
factory :user do
|
||||||
attributes { {name: "Daniel"} }
|
attributes { {name: "Daniel"} }
|
||||||
initialize_with { new(attributes) }
|
initialize_with { new(**attributes) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue