2013-08-23 6 views
23

Wird jemand bitte Optionen Hashes erklären? Ich arbeite durch den Ruby-Kurs von testfirst.org. Übung 10 (temperature_object) erfordert Kenntnisse über die Optionen-Hashes.Was sind Optionen-Hashes?

Antwort

44

Optionen Hash ist ein nettes Konzept, das durch eine Funktion des Rubin-Parsers ermöglicht wird. Angenommen, Sie haben eine Methode mit einigen erforderlichen Argumenten. Sie können auch einige optionale Argumente übergeben. Im Laufe der Zeit können Sie weitere optionale Argumente hinzufügen oder alte entfernen. Um die Deklaration der Methode sauber und stabil zu halten, können Sie alle diese optionalen Argumente in einem Hash übergeben. Eine solche Methode würde folgendermaßen aussehen:

def foo(arg1, arg2, opts = {}) 
    opts.to_s # just return a string value of opts 
end 

So hat es zwei erforderliche Werte und letzte Argument mit Standardwert von Hash. Wenn Sie keine optionalen Argumente müssen passieren, rufen Sie es wie folgt aus:

foo(1, 2) # => "{}" 

Wenn Sie etwas optional tun haben, können Sie es so nennen:

foo(1, 2, {truncate: true, redirect_to: '/'}) # => "{:truncate=>true, :redirect_to=>\"/\"}" 

Dieser Code ist so idiomatischen ruby, dass seine Parser können Sie tatsächlich geschweiften Klammern weglassen, wenn Hash als letztes Argument an eine Methode übergeben:

foo(1, 2, truncate: true, redirect_to: '/') # => "{:truncate=>true, :redirect_to=>\"/\"}" 

Wenn Sie Schienen verwenden, zum Beispiel, werden Sie Optionen sehen Hashes überall. Hier öffnete ich nur eine Zufallssteuerung in meiner App:

class ProductsController < ApplicationController 
    before_filter :prepare_search_params, only: :index 
            # ^^^^^^^^^^ options hash here 

Also, kurz gesagt: Optionen Hash Argument einer Methode, die zuletzt befindet und Standardwert von {} hat. Und du gibst normalerweise Hashes dazu (daher der Name).

+7

In einer modernen Version von Ruby sollten Sie anstelle eines Options-Hashes unbedingt Schlüsselwortargumente verwenden. –

+0

@ JörgWMittag kannst du das erklären? – Dennis

+1

@Dennis: Google "Ruby Schlüsselwort Argumente" –

5

Ein Options Hash bezieht sich auf die Konvention der Weiterleiten von Optionen an Methoden, um ein Hash-Verwendung ({}) wie so

my_func(arg1, arg2, {:opt1 => 'foo', :opt2 => 'bar'}) 

Die Konvention für die Optionen ist HASH Das letzte Argument sein, so dass es optional vorgenommen werden kann . Z.B.

def my_func(argument1, argument2, options = {}) 
    ... 
end 

So ein Optionen-Hash ist nichts besonderes. Es ist nur ein optionales letztes Argument, das ein Hash ist. Optionen Hashes ist so handlich und ist gemeinsam, dass der Dolmetscher kann Sie auch aus den Klammern lassen (dies ist das ein „besonderer“ Teil von ihnen)

my_func(arg1, arg2, :opt1 => 'foo', :opt2 => 'bar') 

In Kombination mit Rubys Symbol Raute-Taste Verknüpfung und optional Klammern, kann dieses Ende wirklich sauber suchen:

my_func arg1, arg2, opt1: 'foo', opt2: 'bar' 
2

Reverse-Merge ist der beste Weg Optionen zu implementieren Hashes in ruby ​​/ Rails:

def set_state_application(options_hash) 
    options_hash.reverse_merge!(send_email: true, other_default_val: 'a') #will set defaults 
    self.update_column(:status_id, VendorEnums::VendorStatus::APPLICATION) 
    VendorMailer.email_application(self) if options_hash[:send_email] 
    save_state 
end 
9

Optionen Hashes viel verwendet werden, wenn n um optionale Argumente an Methode zu übergeben.

Wenn zum Beispiel Verfahren ein-zwei optionale args hat, können Sie

def method(arg1, arg2 = nil, arg3 = nil) 
    ... 
end 

schreiben Aber wenn Sie mehrere optionale arg haben es wird immer hässlich sie nil jeder Zeit zuzuordnen. Hier kommt die Optionen Hash, die Sie

def method(arg1, options={}) 
    @arg1 = arg1 
    @arg2 = options[:arg2] 
    .... 
    @arg15 = options[:arg15] 
end 
2

Da alle diese Antworten sind richtig schreiben können, Rubin 2 die Unterstützung Schlüsselwörter Argumente verbessert.

Sie können Ihre Methode mit den Standard-Hash-Parametern als *args definieren und die options = {} löschen.

def foo(bar: 'initial') 
    puts bar 
end 

foo # => 'initial' 
foo(bar: 'final') # => 'final' 

Erforderliche Argumente: Sie müssen einen Doppelpunkt nach dem Schlüssel (auch müssen Sie 2.1 Rubin)

def foo(bar:) 
    puts bar 
end 

foo # => ArgumentError: missing keyword: bar 
foo(bar: 'baz') # => 'baz' 

Optionale Argumente, die als Standard nil

def foo(bar: nil, baz: 'aaa') 
    puts "#{bar}:#{baz}" 
end 

foo # => ':aaa' 
foo(baz: 'zab') # => ':zab' 
foo(bar: 'rab', baz: 'zab') # => 'rab:zab' 
foo(bin: 'bin') # => ArgumentError: unknown keyword: bin 

Sie auch festlegen kann die Standard-Positionsargumente mit dieser neuen Hash-Parameter-Notation verwenden. Weitere Informationen finden Sie unter blog und unter der oficial Dokumentation.

Bonus: Der Refactor ist einfach, weil Sie den Optionen Hash Ihrer Methode loswerden können, ohne die Aufrufe davon zu ändern. Aber ... das stimmt nicht ganz, wenn Sie einen Anruf mit einer unerwarteten Option haben, erhalten Sie eine ArgumentError: unknown keyword: invalid_arg.