开发者

Is there an idiomatic way to specify default values for optional parameters in Ruby?

Is there a more concise and idiomatic way to write the following code, which is used to specify default values for optional parameters (in the params/options hash) to a method?

def initialize(params={})
  if params.has_key? :verbose
    @verbose = params[:verbose]
  else
    @verbose = true # this is the  default value
  end
end

I would love to simplify it to something like this:

def initialize(params={})
  @verbose = params[:verbose] or true开发者_如何转开发
end

which almost works, except that you really need to use has_key? :verbose as the condition, instead of just evaluating params[:verbose], in order to cover cases when you want to specify a value of 'false' (i.e. if you want to pass :verbose => false as the argument in this example).

I realize that in this simple example I could easily do:

def initialize(verbose=false)
  @verbose = verbose
end

but, in my real code I actually have a bunch of optional parameters (in addition to a few required ones) and I'd like to put the optional ones in the params hash so that I can easily only specify (by name) the few that I want, rather than having to list them all in order (and potentially having to list ones I don't actually want).


A common pattern is to use

def foo(options = {})
  options = { :default => :value }.merge(options)
end

You’ll end up with options being a hash containing the passed in values, with the options from your defaults hash as any that weren’t provided.


Ruby 2.0.0 has a new feature keyword arguments

Previously you had to write such code:

def foo(options = {})
  options = {bar: 'bar'}.merge(options)
  puts "#{options[:bar]} #{options[:buz]}"
end

foo(buz: 'buz') # => 'bar buz'

Now this is much cleaner:

def foo(bar: 'bar', **options)
  puts "#{bar}, #{options}"
end

foo(buz: 'buz') # => 'bar buz'


I think you're looking for this

params = { :verbose => true }.merge(params)


Another way to write this, more succinctly, would be

def foo(options = {})
    options.reverse_merge! value1: true, value2: 100
end

This set options[:value1] to true (default value) unless options passed in already contains the key :value1. Same for :value2

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜