2009-06-10 3 views
7

Powiedzmy chcę metodę, która będzie wywoływana tak:Co znajduje się ładny czysty sposób użycia skrótu opcji z wartości domyślnych jako parametr w Ruby

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

gdzie niektóre opcje mają wartości domyślne:

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

Co to jest miły idiomatyczny ruby ​​sposób realizacji tego domyślnego zachowania w realizacji metody?

Odpowiedz

16

Jeśli używasz poręcze (nie po prostu Ruby), nieco krótsza metoda jest

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

Ma to dodatkową zaletę, że pozwala Ci zrobić wiele linii nieco ciut bardziej czysty:

def foo(options = {}) 
    options.reverse_merge!(
    :some_default => true, 
    :other_default => 5 
) 
end 
+1

Właśnie tego szukałem, dzięki. Odkryłem też, że jeśli nie używasz Railsów, to klejnot Facet również łata małpy Hash z reverse_merge! metoda. –

+1

Pamiętaj, że nie musisz używać wszystkich Railsów, aby uzyskać tę metodę (chociaż może to nie być prawda, gdy ta odpowiedź została pierwotnie opublikowana w 2009 r.). Po prostu musisz używać klejnotu 'activesupport' (który jest dołączany jako część Rails), a następnie upewnij się, że wywołałeś' require "active_support/core_ext/hash/reverse_merge" '. – GMA

19
def foo(options = {}) 
    options = { ... defaults ... }.merge(options) 
end 
4

Zazwyczaj najlepiej jest hermetyzować bezpieczne wartości domyślne w mieszaniu, które jest zadeklarowane jako stała. Na przykład:

require „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 

Ważne jest, aby pamiętać, gdy scalanie obiektów Hash Klucze łańcuchowe i symbolem są różne i nie zostaną połączone, jak można się było spodziewać. W środowisku Railsowym możesz zawsze konwertować je na inne za pomocą Hash # symbolize_keys lub deklarując je jako HashWithIndifferentAccess, które odwzorowują różnicę dla ciebie.

3

Jeśli ktoś widzi to z Google, to pytanie jest stare i nieaktualne. Nowoczesną i znacznie czystszą odpowiedzią (z Ruby> 2.0) jest użycie argumentów słów kluczowych. Mają kilka zalet.

1.) możesz wymagać nazwy klucza w haszdzie. (w Ruby> 2.1)

2.) nie musisz "rozpakowywać" hasha w funkcji. Klucze są po prostu przekazywane jako zmienne. (A więc nie trzeba robić jak speed = opts[:speed])

3.) To czystsze

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

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

zobacz pełne docs rubinowe tutaj: http://www.ruby-doc.org/core-2.1.0/doc/syntax/methods_rdoc.html#label-Array%2FHash+Argument

i dobry mały wpis na blogu tutaj: http://robots.thoughtbot.com/ruby-2-keyword-arguments

Powiązane problemy