Mat*_*dan 10 ruby variables arguments
在使用方法的命名参数时,我发现自己经常在Ruby中编写我认为不必要的代码.
以下面的代码为例:
def my_method(args)
orange = args[:orange]
lemon = args[:lemon]
grapefruit = args[:grapefruit]
# code that uses
# orange, lemon & grapefruit in this format which is way prettier & concise than
# args[:orange] args[:lemon] args[:grapefruit]
puts "my_method variables: #{orange}, #{lemon}, #{grapefruit}"
end
my_method :orange => "Orange", :grapefruit => "Grapefruit"
Run Code Online (Sandbox Code Playgroud)
我真的不喜欢这段代码的是我必须接受args并将值传递给局部变量,这些变量与DRY原则相反,并且通常占用我的方法中的空间.如果我不使用局部变量并且只使用args [:symbol]语法引用所有变量,那么代码就会变得有些难以理解.
我已经尝试过解决这个问题,但是我不知道如何在方法范围内使用eval或使用任何其他技术来定义局部变量.以下是下面的许多尝试之一,这会导致错误
def my_method_with_eval(args)
method_binding = binding
%w{ orange lemon grapefruit}.each { |variable| eval "#{variable} = args[:#{variable}]", method_binding; }
# code that uses
# orange, lemon & grapefruit in this format which is way prettier & concise than
# args[:orange] args[:lemon] args[:grapefruit]
puts "my_method_with_eval variables: #{orange}, #{lemon}, #{grapefruit}"
end
my_method_with_eval :orange => "Orange", :grapefruit => "Grapefruit"
Run Code Online (Sandbox Code Playgroud)
运行该代码时,我得到了
NameError: undefined local variable or method ‘orange’ for main:Object method my_method_with_eval in named_args_to_local_vars at line at top level in named_args_to_local_vars at line 9
任何人都有任何想法我怎么能以某种方式简化这个,以便我不必用var = args [:var]代码的负载启动我的命名参数方法?
我不相信在Ruby中有任何方法可以做到这一点(如果有人想出一个,请告诉我,我会更新或删除这个答案来反映它!) - 如果没有定义局部变量然而,没有办法用绑定动态定义它.你可以想象orange, lemon, grapefruit = nil
在调用eval之前做一些事情,但是你可能遇到其他问题 - 例如,如果args [:orange]是字符串"Orange",你最终会orange = Orange
用你当前的实现进行评估.
但是,这可以使用标准库中的OpenStruct类(通过"可以工作",我的意思是"这取决于你的风格是否a.orange
比任何更好args[:orange]
"):
require 'ostruct'
def my_method_with_ostruct(args)
a = OpenStruct.new(args)
puts "my_method_with_ostruct variables: #{a.orange}, #{a.lemon}, #{a.grapefruit}"
end
Run Code Online (Sandbox Code Playgroud)
如果您不需要轻松访问此方法的接收器上的任何状态或方法,则可以使用instance_eval,如下所示.
def my_method_with_instance_eval(args)
OpenStruct.new(args).instance_eval do
puts "my_method_with_instance_eval variables: #{orange}, #{lemon}, #{grapefruit}"
end
end
Run Code Online (Sandbox Code Playgroud)
你甚至可以用method_missing做一些棘手的事情(参见这里了解更多)以允许访问"主要"对象,但性能可能不会很好.
总而言之,我认为可能最简单/可读的方式是使用较少干扰您的初始解决方案.
合并Greg和Sand的答案:
require 'ostruct'
def my_method(args = {})
with args do
puts a
puts b
end
end
def with(args = {}, &block)
OpenStruct.new(args).instance_eval(&block)
end
my_method(:a => 1, :b => 2)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1657 次 |
最近记录: |