Что такое опционные хэши?

Кто-нибудь объяснит хэши опций? Я прохожу курс ruby ​​с сайта testfirst.org. Упражнение 10 (temperature_object) требует знания хэшей опций.


person colewest    schedule 23.08.2013    source источник


Ответы (5)


Хэш параметров — это хорошая концепция, реализованная с помощью функции парсера ruby. Скажем, у вас есть метод с некоторыми обязательными аргументами. Также вы можете передать некоторые необязательные аргументы. Со временем вы можете добавить больше необязательных аргументов или удалить старые. Чтобы объявление метода было чистым и стабильным, вы можете передать все эти необязательные аргументы в виде хэша. Такой метод будет выглядеть так:

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

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

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

Если у вас есть что-то необязательное, вы называете это так:

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

Этот код настолько идиоматичен для ruby, что его синтаксический анализатор фактически позволяет вам опускать фигурные скобки при передаче хеша в качестве последнего аргумента метода:

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

Например, если вы используете рельсы, вы увидите хэши опций везде. Здесь я открыл просто случайный контроллер в своем приложении:

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

Итак, вкратце: хеш опций — это аргумент метода, который расположен последним и имеет значение по умолчанию {}. И вы обычно передаете ему хэши (отсюда и название).

person Sergio Tulentsev    schedule 23.08.2013
comment
В современной версии Ruby вы действительно должны использовать аргументы ключевого слова вместо хэша параметров. - person Jörg W Mittag; 24.08.2013
comment
@JörgWMittag, можешь объяснить? - person Dennis; 22.09.2014
comment
@Денис: foo(arg1, arg2, truncate: false, redirect_to:). См. этот ответ для всей истории. - person Jörg W Mittag; 22.09.2014
comment
@ JörgWMittag о, оказывается, я знал это - термины сбили меня с толку, поскольку использование более нового синтаксиса технически все равно дало бы вам хеш параметров. В любом случае, всегда хорошо показать пример. - person Dennis; 22.09.2014

Хэши параметров часто используются, когда необходимо передать необязательные аргументы в метод.

Например, если метод имеет один-два необязательных аргумента, вы можете написать

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

Но если у вас есть больше необязательных аргументов, становится некрасиво каждый раз присваивать им значение nil. Здесь идет хеш опций, который позволяет вам писать

def method(arg1, options={})
  @arg1 = arg1
  @arg2 = options[:arg2]
  ....
  @arg15 = options[:arg15]
end
person dimitryeurope    schedule 24.12.2014

Хэш параметров относится к соглашению о передаче параметров методам с использованием хеша ({}), например

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

По соглашению хэш параметров должен быть последним аргументом, чтобы его можно было сделать необязательным. Например.

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

Таким образом, хеш опций не является чем-то особенным. Это просто необязательный последний аргумент, который является хэшем. Хэши опций настолько удобны и распространены, что интерпретатор также позволяет вам не использовать фигурные скобки (это их единственная «особая» часть).

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

В сочетании с сочетанием клавиш Ruby Symbol и необязательными круглыми скобками это может выглядеть очень чистым:

my_func arg1, arg2, opt1: 'foo', opt2: 'bar'
person Max    schedule 23.08.2013

Поскольку все эти ответы верны, в ruby ​​2 улучшена поддержка аргументов ключевых слов.

Вы можете определить свой метод с параметрами хэша по умолчанию как *args и избавиться от options = {}.

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

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

Обязательные аргументы: вам нужно двоеточие после ключа (также вам нужен ruby ​​2.1)

def foo(bar:)
  puts bar
end

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

Необязательные аргументы, вы можете установить по умолчанию 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

Также вы можете использовать стандартные позиционные аргументы с этой новой записью хеш-параметров. Дополнительную информацию можно найти в этом блоге и в официальная документация.

Бонус: рефакторинг прост, потому что вы можете избавиться от хэша опций вашего метода, не изменяя его вызовы. Но... это не совсем так, если у вас есть колл с неожиданной опцией, вы получите ArgumentError: unknown keyword: invalid_arg.

person Alejandro Babio    schedule 30.08.2015

Обратное слияние — лучший способ реализовать хэши опций в 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
person Carlos Cervantes    schedule 20.03.2014