Ruby方法和可选参数

Gui*_*ini 33 ruby ruby-on-rails

我正在使用Ruby on Rails,我正在尝试使用可选参数创建一个方法.显然,有很多方法可以做到这一点.我尝试将可选参数命名为哈希值,而不定义它们.输出是不同的.看一看:

# This functions works fine!
def my_info(name, options = {})
    age = options[:age] || 27
    weight = options[:weight] || 160
    city = options[:city] || "New York"
    puts "My name is #{name}, my age is #{age}, my weight is #{weight} and I live in {city}"
end


my_info "Bill"
-> My name is Bill, my age is 27, my weight is 160 and I live in New York
-> OK!

my_info "Bill", age: 28
-> My name is Bill, my age is 28, my weight is 160 and I live in New York
-> OK!

my_info "Bill", weight: 200
-> My name is Bill, my age is 27, my weight is 200 and I live in New York
-> OK!

my_info "Bill", city: "Scottsdale"
-> My name is Bill, my age is 27, my weight is 160 and I live in Scottsdale
-> OK!

my_info "Bill", age: 99, weight: 300, city: "Sao Paulo"
-> My name is Bill, my age is 99, my weight is 300 and I live in Sao Paulo
-> OK!

****************************

# This functions doesn't work when I don't pass all the parameters
def my_info2(name, options = {age: 27, weight: 160, city: "New York"})
    age = options[:age]
    weight = options[:weight]
    city = options[:city]
    puts "My name is #{name}, my age is #{age}, my weight is #{weight} and I live in #{city}"
end

my_info2 "Bill"
-> My name is Bill, my age is 27, my weight is 160 and I live in New York
-> OK!

my_info2 "Bill", age: 28
-> My name is Bill, my age is 28, my weight is  and I live in 
-> NOT OK! Where is my weight and the city??

my_info2 "Bill", weight: 200
-> My name is Bill, my age is , my weight is 200 and I live in 
-> NOT OK! Where is my age and the city??

my_info2 "Bill", city: "Scottsdale"
-> My name is Bill, my age is , my weight is  and I live in Scottsdale
-> NOT OK! Where is my age and my weight?

my_info2 "Bill", age: 99, weight: 300, city: "Sao Paulo"
-> My name is Bill, my age is 99, my weight is 300 and I live in Sao Paulo
-> OK!
Run Code Online (Sandbox Code Playgroud)

可选参数的第二种方法有什么问题?第二种方法只有在我没有传递任何可选参数或者我都传递它们时才有效.

我错过了什么?

Mar*_*rce 55

可选参数在ruby中的工作方式是指定等号,如果没有传递参数,则使用您指定的内容.所以,如果在第二个例子中没有传递第二个参数,那么

{age: 27, weight: 160, city: "New York"}
Run Code Online (Sandbox Code Playgroud)

用来.如果在第一个参数之后使用哈希语法,则传递该精确哈希.

你能做的最好的就是

def my_info2(name, options = {})
  options = {age: 27, weight: 160, city: "New York"}.merge(options)
...
Run Code Online (Sandbox Code Playgroud)

  • 由于`options`将被重新分配,你也可以在原地更新它:`options.reverse_update(年龄:27,体重:160,城市:"纽约") (3认同)

Cha*_*ell 16

问题是默认值optionsHash您发布的第二个版本中的整个.因此,默认值,整个Hash,被覆盖.这就是为什么传递任何东西都无效,因为这会激活默认值,即Hash输入所有这些值也可以,因为它用Hash相同的键覆盖默认值.

我强烈建议使用a Array来捕获方法调用结束时的所有其他对象.

def my_info(name, *args)
  options = args.extract_options!
  age = options[:age] || 27
end
Run Code Online (Sandbox Code Playgroud)

我从阅读Rails的源代码中学到了这个技巧.但请注意,这仅适用于包含ActiveSupport的情况.或者,如果你不希望整个的ActiveSupport宝石的开销,只是用加入到这两种方法Hash,并Array使这成为可能.

rails/activesupport/lib/active_support/core_ext/array/extract_options.rb

因此,当您调用方法时,请调用它,就像使用其他任何其他Rails辅助方法一样.

my_info "Ned Stark", "Winter is coming", :city => "Winterfell"
Run Code Online (Sandbox Code Playgroud)


Win*_*eld 9

如果要默认选项哈希中的值,则需要合并函数中的默认值.如果您将默认值放在默认参数本身中,它将被覆盖:

def my_info(name, options = {})
  options.reverse_merge!(age: 27, weight: 160, city: "New York")

  ...
end
Run Code Online (Sandbox Code Playgroud)


tex*_*uce 5

在第二种方法中,当你说,

my_info2 "Bill", age: 28

它将通过{年龄:28},并且将覆盖整个原始默认哈希{年龄:27,体重:160,城市:"纽约"}.这就是为什么它没有正确显示.