Rails中使用define_method定义赋值方法无效问题排查
问题分析与解决方案
你遇到的问题根源很明确:错误地把参数名包含进了动态定义的方法名称里,导致实际生成的方法和你预期的不一致。
你的错误点
看你写的这段代码:
TYPES.each do |type| define_method "#{type}s=(objects)" do
这里你把方法名写成了"#{type}s=(objects)",相当于定义了一个名为cars=(objects)(而不是cars=)的方法。这就是为什么:
- 调用
myobject.cars=objects时提示方法不存在——因为这个方法根本没被定义 - 执行
puts myobject.methods能看到cars=(objects)——这才是你实际定义的方法名
正确的写法
动态定义赋值方法时,define_method的第一个参数只需要方法的名称(也就是带=的部分),方法的参数要放在代码块的参数列表里:
TYPES = %w(car truck) TYPES.each do |type| define_method "#{type}s=" do |objects| # 这里添加你的方法逻辑,比如把值存到实例变量里 instance_variable_set("@#{type}s", objects) end end
验证修正效果
现在再调用myobject.cars=some_objects就会正常工作了:
- Ruby的赋值语法
obj.attr=value会自动匹配名为attr=的方法 - 你可以用
myobject.methods.include?(:cars=)来确认方法是否正确定义
额外说明
如果你非要调用之前错误定义的cars=(objects)方法,只能通过send来调用:
myobject.send("cars=(objects)", some_objects)
但这显然不是你想要的写法,所以修正方法名的定义才是根本解决办法。
内容的提问来源于stack exchange,提问作者Petran
相关产品推荐
相关产品推荐

