我有下面的方法有很多参数。我已经将这个方法从参数列表转换为哈希,以避免与默认参数混淆。
def foo_bar(options = {})
Rails.logger.info("Got params #{options.inspect}")
good_name = options[:foo1]
another_param = options[:foo2]
yet_another = options[:foo3] || "yes"
still_one = options[:foo3]
valid_name = options[:foo4]
easy_name = options[:foo5]
mode = options[:foo6]
..
字符串
调用这个方法现在很容易,只使用上下文中必需的参数,这很好
foo_bar(foo1: my_foo1, foo3: my_foo3, foo6: my_mode)
型
但我的问题是,由于Rails通常是非常直观的语言,在那里你有很多快捷方式和方法来做事情,如何使这个方法的参数签名更清楚,
- 我不需要从hash中提取参数,它们会自动分配给correcting local var,而没有那些“额外”的行,现在分配是从选项hash中进行的。
- 没有一长串带有默认值的参数
我想避免这种情况,因为当调用这个方法时,我不能自由地选择我想赋值给哪个参数。而且调用也不清楚哪个参数是哪个参数,因为它们不是通过名称引用的,而是通过值和顺序引用的。
def foo_bar(good_name, another_param = nil, yet_another = "yes", still_one = "xx", valid_name = nil, easy_name = nil, foo6 = "std")
型
方法重载在这里不起作用,也试过了。这不像在C#或Java中实现。
我试过:方法重载参数作为散列参数“正常的方式”
1条答案
按热度按时间hujrc8aj1#
首先,声明方法的现代方法是使用关键字参数而不是哈希作为位置参数。
字符串
位置参数方法的一个问题是,你实际上可以传递不是散列的输入,它会在方法内部爆炸,而不是得到一个参数错误,它会立即告诉你什么是错的。
**
是一个双splat,意味着我们正在吸收传递给该方法的任何关键字参数。处理默认值的方法有很多种。如果你不想在方法定义中显式列出它们(
def foo(bar: :Baz, ...)
),你可以使用一个私有方法来生成默认选项:型
这使得子类可以覆盖方法,并且在Rails代码库中随处可见。
reverse_merge
来自ActiveSupport,你可以在普通Ruby中对merge
做同样的事情,但顺序相反。我不需要从hash中提取参数,它们会自动分配给correcting local var。
这种模式通常称为质量分配:
型
对于传递给方法的每个关键字参数,我们尝试调用一个与键同名的setter方法。虽然您可以直接调用
instance_variable_set
并设置Ivars,但这不允许您控制可以分配什么以及如何分配。在Rails中,你可以从ActiveModel::AttributeAssignment的模型中免费获得它,如果需要,它可以混合到任何类中。