You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby中method_missing+send处理混合参数(含命名参数)报错问题

解决Ruby代理模式中转发含命名参数方法的问题

问题场景

实现代理模式时,调用包含普通参数与命名参数的方法时报错,原代码及错误信息如下:

原代码

class ExecuteProxy
    def initialize(controller_object)
      @controller_object = controller_object
    end

    def method_missing(method, *args)
      args.empty? ? @controller_object.send(method) : @controller_object.send(method, *args)
      return
    end
end

class MyClass
    def no_arghuments
        puts "no_arghuments"
    end
    def one_argument(arg1)
        puts "one_argument #{arg1}"
    end
    def one_argument_and_named(arg1, count:1)
        puts "one_argument #{arg1} and count #{count}"
    end
end

obj = MyClass.new
proxy = ExecuteProxy.new(obj)

proxy.no_arghuments
proxy.one_argument("test")
proxy.one_argument_and_named("test2")
proxy.one_argument_and_named("test2", count:2)

错误输出

no_arghuments
one_argument test
one_argument test2 and count 1
test1.rb:20:in `one_argument_and_named': wrong number of arguments (given 2, expected 1) (ArgumentError)
    from test1.rb:8:in `method_missing'
    from test1.rb:31:in `<main>'

问题原因

原method_missing方法仅捕获了普通参数*args,未处理Ruby的命名参数。调用带命名参数的方法时,命名参数会被当作普通参数传入args,导致目标方法接收到的参数数量不符,触发参数错误。

解决方案

修改method_missing方法,添加**kw参数捕获所有命名参数,调用send时同时传递普通参数和命名参数即可解决问题。

可行代码

class ExecuteProxy
    def initialize(controller_object)
      @controller_object = controller_object
    end

    def method_missing(method, *args, **kw)
      @controller_object.send(method, *args, **kw)
      return
    end
end

class MyClass
    def no_arghuments
        puts "no_arghuments"
    end
    def one_argument(arg1)
        puts "one_argument #{arg1}"
    end
    def one_argument_and_named(arg1, count:1)
        puts "one_argument #{arg1} and count #{count}"
    end
    def only_named(count:, str:"")
        puts "only_named count #{count}, str: #{str}"
    end
    def manyarguments_and_named_args(arg1, arg2, arg3 = "def", count:1, some_other:"d")
        puts "manyarguments_and_named_args #{arg1}, #{arg2}, #{arg3} and count #{count}, some_other #{some_other}"
    end
end

obj = MyClass.new
proxy = ExecuteProxy.new(obj)

proxy.no_arghuments
proxy.one_argument("test")
proxy.one_argument_and_named("test2")
proxy.one_argument_and_named("test2", count:2)
proxy.only_named(count:3)
proxy.only_named(count:3,str:"string")
proxy.manyarguments_and_named_args("a1","a2")
proxy.manyarguments_and_named_args("a1","a2", "s3")
proxy.manyarguments_and_named_args("a1","a2", count:4)
proxy.manyarguments_and_named_args("a1","a2", count:4, some_other:nil)

(注:修正了原可行代码中遗漏的语法闭合符,确保代码可正常运行)

执行输出

no_arghuments
one_argument test
one_argument test2 and count 1
one_argument test2 and count 2
only_named count 3, str: 
only_named count 3, str: string
manyarguments_and_named_args a1, a2, def and count 1, some_other d
manyarguments_and_named_args a1, a2, s3 and count 1, some_other d
manyarguments_and_named_args a1, a2, def and count 4, some_other d
manyarguments_and_named_args a1, a2, def and count 4, some_other 

内容的提问来源于stack exchange,提问作者Roman Gelembjuk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 05:25:59