From be7a98833e07e9e687bcd1aae30f86b34a315fd5 Mon Sep 17 00:00:00 2001 From: Taichi Ishitani Date: Fri, 18 Dec 2020 02:42:10 +0900 Subject: [PATCH] fix warning related to keywoard argument (#45) * add workaround to avoid warnings related to keyword arguments (refs: #44) --- lib/docile/fallback_context_proxy.rb | 26 +++++++++++++++--------- spec/docile_spec.rb | 30 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/lib/docile/fallback_context_proxy.rb b/lib/docile/fallback_context_proxy.rb index db8a608..208dd26 100644 --- a/lib/docile/fallback_context_proxy.rb +++ b/lib/docile/fallback_context_proxy.rb @@ -82,17 +82,25 @@ module Docile # Proxy all methods, excluding {NON_PROXIED_METHODS}, first to `receiver` # and then to `fallback` if not found. - def method_missing(method, *args, &block) - if @__receiver__.respond_to?(method.to_sym) - @__receiver__.__send__(method.to_sym, *args, &block) + args_string = + if RUBY_VERSION >= "2.7.0" + "*args, **kwargs, &block" else - begin - @__fallback__.__send__(method.to_sym, *args, &block) - rescue NoMethodError => e - e.extend(BacktraceFilter) - raise e + "*args, &block" + end + class_eval(<<-METHOD) + def method_missing(method, #{args_string}) + if @__receiver__.respond_to?(method.to_sym) + @__receiver__.__send__(method.to_sym, #{args_string}) + else + begin + @__fallback__.__send__(method.to_sym, #{args_string}) + rescue NoMethodError => e + e.extend(BacktraceFilter) + raise e + end end end - end + METHOD end end diff --git a/spec/docile_spec.rb b/spec/docile_spec.rb index 34b72e5..095c8bb 100644 --- a/spec/docile_spec.rb +++ b/spec/docile_spec.rb @@ -435,6 +435,36 @@ describe Docile do end end end + + if RUBY_VERSION >= "2.0.0" + context "when a DSL method has a keyword argument" do + class DSLMethodWithKeywordArgument + attr_reader :v0, :v1, :v2 + class_eval(<<-METHOD) + def set(v0, v1:, v2:) + @v0 = v0 + @v1 = v1 + @v2 = v2 + end + METHOD + end + + let(:dsl) do + DSLMethodWithKeywordArgument.new + end + + it "calls such DSL methods with no stderr output" do + # This is to check warnings related to keyword argument is not output. + # See: https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/ + expect { Docile.dsl_eval(dsl) { set(0, v2: 2, v1: 1) } }. + not_to output.to_stderr + + expect(dsl.v0).to eq 0 + expect(dsl.v1).to eq 1 + expect(dsl.v2).to eq 2 + end + end + end end describe ".dsl_eval_with_block_return" do