Какой хороший чистый способ использовать хэш опций со значениями по умолчанию в качестве параметра в ruby - PullRequest
8 голосов
/ 10 июня 2009

Допустим, я хочу метод, который будет вызываться так:

 tiger = create_tiger( :num_stripes => 12, :max_speed => 43.2 )
 tiger.num_stripes # will be 12

, где некоторые опции имеют значения по умолчанию:

 tiger = create_tiger( :max_speed => 43.2 )
 tiger.num_stripes # will have some default value

каков хороший идиоматический рубиновый способ реализации этого дефолтного поведения в реализации метода?

Ответы [ 4 ]

21 голосов
/ 10 июня 2009
def foo(options = {})
  options = { ... defaults ... }.merge(options)
end
18 голосов
/ 10 июня 2009

Если вы используете Rails (не просто обычный Ruby), то более короткий метод будет

def foo(options = {})
  options.reverse_merge! { ... defaults ... }
end

Это дает дополнительное преимущество, заключающееся в том, что вы можете делать несколько строк более чётко:

def foo(options = {})
  options.reverse_merge!(
    :some_default => true,
    :other_default => 5
  )
end
6 голосов
/ 11 июня 2009

Обычно лучше всего инкапсулировать безопасные значения по умолчанию в хэш, который объявлен как константа. Например:

требуется 'ostruct'

require 'ostruct'

class Tiger < OpenStruct
  DEFAULTS = {
    :num_stripes => 12,
    :max_speed => 43.2
  }.freeze

  def initialize(options = { })
    super(DEFAULTS.merge(options))
  end
end

tiger = Tiger.new(:max_speed => 19.95)

puts tiger.max_speed
puts tiger.num_stripes

Важно отметить, что при объединении объектов Hash ключи String и Symbol отличаются друг от друга и не будут комбинироваться, как вы могли ожидать. В среде Rails вы всегда можете преобразовать одно в другое, используя Hash # symbolize_keys или объявив их как HashWithIndifferentAccess, который отображает разницу для вас.

4 голосов
/ 07 января 2015

Если кто-то увидит это в Google, этот вопрос устарел и устарел. Современный и более понятный ответ (с Ruby> 2.0) - использовать аргументы с ключевыми словами. У них есть несколько преимуществ.

1.) Вам может потребоваться имя ключа в хеше. (в рубине> 2,1)

2.) Вам не нужно «распаковывать» хеш в функции. Ключи просто передаются вам как переменные. (таким образом, вы не должны делать, как speed = opts[:speed])

3.) Это чище

def foo(num_stripes: 12, **rest)
  print num_stripes, rest
end

foo({max_speed: 42}) # would print '12, {max_speed: 42}'

см. Полные документы по ruby ​​здесь: http://www.ruby -doc.org / core-2.1.0 / doc / syntax / method_rdoc.html # label-Array% 2FHash + Аргумент

и хороший небольшой пост в блоге здесь: http://robots.thoughtbot.com/ruby-2-keyword-arguments

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...