:option => value
,否则将使用默认设置。这是一个可行的具体示例,但有点难看。如何以更优雅的方式完成同一件事?
def connect_to_oracle opts = {}
host_name = opts[:host_name]
host_name ||= 'a_default_host_name'
db_name = opts[:db_name]
db_name ||= 'a_default_db_name'
userid = opts[:userid]
userid ||= 'a_default_userid'
password = opts[:password]
password ||= 'a_default_password'
url = "jdbc:oracle:thin:#{userid}/#{password}@#{host_name}:1521:#{db_name}"
$db = Sequel.connect(url)
end
#1 楼
您不需要||=
即可使用||
:def connect_to_oracle( opts = {} )
host_name = opts[:host_name] ||'a_default_host_name'
db_name = opts[:db_name] || 'a_default_db_name'
userid = opts[:userid] || 'a_default_userid'
password = opts[:password] ||'a_default_password'
url = "jdbc:oracle:thin:#{userid}/#{password}@#{host_name}:1521:#{db_name}"
$db = Sequel.connect(url)
end
另一种方法是
Hash.merge
:DEFAULT = {
host_name: 'a_default_host_name',
db_name: 'a_default_db_name',
userid: 'a_default_userid',
password: 'a_default_password',
}
def connect_to_oracle( opts = {} )
opts = DEFAULT.merge(opts)
host_name = opts[:host_name]
db_name = opts[:db_name]
userid = opts[:userid]
password = opts[:password]
url = "jdbc:oracle:thin:#{userid}/#{password}@#{host_name}:1521:#{db_name}"
$db = Sequel.connect(url)
end
or:
DEFAULT = {
host_name: 'a_default_host_name',
db_name: 'a_default_db_name',
userid: 'a_default_userid',
password: 'a_default_password',
}
def connect_to_oracle( interface_opts = {} )
opts = DEFAULT.merge(interface_opts )
url = "jdbc:oracle:thin:%s/%s@%s:1521:%s" % [
opts[:userid],
opts[:password],
opts[:host_name],
opts[:db_name],
]
$db = Sequel.connect(url)
end
connect_to_oracle()
connect_to_oracle(:host_name => :xxxxxxxx)
我更喜欢
merge
的版本。因此,我在文档中得到了带有所有默认参数的常量。另一个优点:我可以轻松地添加检查接口中是否包含正确的键。
示例:
DEFAULT = {
host_name: 'a_default_host_name',
db_name: 'a_default_db_name',
userid: 'a_default_userid',
password: 'a_default_password',
}
def connect_to_oracle( myopts = {} )
(myopts.keys - DEFAULT.keys).each{|key|
puts "Undefined key #{key.inspect}"
}
opts = DEFAULT.merge(myopts)
url = "jdbc:oracle:thin:%s/%s@%s:1521:%s" % [
opts[:userid],
opts[:password],
opts[:host_name],
opts[:db_name],
]
#~ $db = Sequel.connect(url)
end
connect_to_oracle(:host_nam => :xxxxxxxx)
我的方法调用包含错误(忘记了'e'),但是调用它时,会收到警告
Undefined key host_nam
。这通常有助于检测错误。 (在实际情况下,我用记录器警告/错误替换了看跌期权)。#2 楼
对于较新的红宝石版本,因为Ruby 2.1关键字参数是最好的选择。def initialize(person:, greeting: "Hello")
end
这里,不需要问候语时必须有人。如果不传递人,则会得到一个
ArgumentError: missing keyword: person
。用关键字参数调用方法的语义与哈希相同。
Greeter.new(greeting: "Hey", person: "Mohamad")
对于旧版本的ruby
对于旧版本的Ruby(2.1版之前),可以使用访存
fetch
。使用
fetch
有两个优点: 它可以设置默认值
如果不指定默认值,则会引发错误
def initialize(options = {})
@greeting = options.fetch(:greeting, "Hello")
@person = options.fetch(:person)
end
如果您尝试在不传递
:person
的情况下实例化对象,则Ruby将引发错误。而:greeting
将默认为hello。#3 楼
在原始Ruby中,可以使用Hash#merge
。由于参数hash中的键将获胜,因此您可以这样编写:opts = {host_name: "a_default_host_name", db_name: "a_default_db_name"}.merge(opts)
如果使用Rails框架,则可以使用非常方便且优雅的
Hash#reverse_merge!
方法可编辑var本身(就像爆炸一样提醒您)opts.reverse_merge!(host_name: "a_default_host_name", db_name: "a_default_db_name")
注意:您可以使用Active Support扩展(非常有用的小软件来改进Ruby),而无需使用所有的Rails框架,只需加载所需的扩展,在这种情况下,它将是:
require 'active_support/core_ext/hash/reverse_merge'
来源:Rails指南
#4 楼
如果您使用的是Ruby 2.0或更高版本,则可以使用关键字参数非常干净地完成此操作。在过去(2.0之前的版本)中,我使用了自定义帮助程序方法来复制此功能。对帮助程序的调用如下所示:保留现有值不变。有关Ruby> = 2.0中关键字参数的文档,请访问rdoc.org-Methods.rdoc
评论
\ $ \ begingroup \ $
.dup.update也可以表示为.merge。
\ $ \ endgroup \ $
–韦恩·康拉德
2014年1月10日20:35
\ $ \ begingroup \ $
@WayneConrad谢谢。我过去曾经使用过它,但似乎又忘记了它。我调整了答案。
\ $ \ endgroup \ $
–坚果
2014年1月10日20:45
\ $ \ begingroup \ $
要非常小心使用key = ops [:key] ||的布尔哈希参数。默认值,如果您尝试传递false,它将始终为默认值。解决它的一种方法是像key = ops [:key] .nil吗? ? true:ops [:key],您可以尝试通过假设如果它们传入该键将是false而不是默认值来缩短此时间,但是您将冒着风险,他们传入与默认值相同的值(假设它是真的),并且您错误地将其假定为假。您还可以反转您的值,因此默认值为false而不是true,但可读性较差。
\ $ \ endgroup \ $
– CTS_AE
18年1月8日在23:42