класс Object::HashWithIndifferentAccess
Реализует хэш, где ключи :foo и "foo" считаются одинаковыми.
rgb = ActiveSupport::HashWithIndifferentAccess.new rgb[:black] = '#000000' rgb[:black] # => '#000000' rgb['black'] # => '#000000' rgb['white'] = '#FFFFFF' rgb[:white] # => '#FFFFFF' rgb['white'] # => '#FFFFFF'
Внутренне символы отображаются в строки при использовании в качестве ключей во всём интерфейсе (вызов []=, merge, и т.д.). Это отображение относится к публичному интерфейсу. Например, если:
hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
Вам гарантируется, что ключ будет возвращён как строка:
hash.keys # => ["a"]
Технически принимаются и другие типы ключей:
hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
hash[0] = 0
hash # => {"a"=>1, 0=>0}
но этот класс предназначен для случаев, когда ожидаются ключи в виде строк или символов, и удобно понимать оба как одно и то же. Например, хэш params в Ruby on Rails.
Обратите внимание, что расширения ядра определяют Hash#with_indifferent_access:
rgb = { black: '#000000', white: '#FFFFFF' }.with_indifferent_access
что может быть полезно.
Публичные Классовые Методы
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 83 def self.[](*args) new.merge!(Hash[*args]) end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 58
def initialize(constructor = {})
if constructor.respond_to?(:to_hash)
super()
update(constructor)
else
super(constructor)
end
end # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 75
def self.new_from_hash_copying_default(hash)
hash = hash.to_hash
new(hash).tap do |new_hash|
new_hash.default = hash.default
new_hash.default_proc = hash.default_proc if hash.default_proc
end
end Общедоступные методы экземпляра
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 96 def []=(key, value) regular_writer(convert_key(key), convert_value(value, for: :assignment)) end
Присваивает новое значение хешу:
hash = ActiveSupport::HashWithIndifferentAccess.new hash[:key] = 'value'
Это значение можно позже получить, используя либо :key или +'ключ'+.
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 253 def compact dup.tap(&:compact!) end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 233 def deep_stringify_keys; dup end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 231 def deep_stringify_keys!; self end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 237 def deep_symbolize_keys; to_hash.deep_symbolize_keys! end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 67
def default(key = nil)
if key.is_a?(Symbol) && include?(key = key.to_s)
self[key]
else
super
end
end # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 226 def delete(key) super(convert_key(key)) end
Удаляет указанный ключ из хеша.
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 189
def dup
self.class.new(self).tap do |new_hash|
set_defaults(new_hash)
end
end Возвращает поверхностную копию хеша.
hash = ActiveSupport::HashWithIndifferentAccess.new({ a: { b: 'b' } })
dup = hash.dup
dup[:a][:c] = 'c'
hash[:a][:c] # => nil
dup[:a][:c] # => "c"
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 46 def extractable_options? true end
Возвращает true, чтобы Array#extract_options! находил члены этого класса.
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 167 def fetch(key, *extras) super(convert_key(key), *extras) end
То же, что и Hash#fetch, где переданный в качестве аргумента ключ может быть строкой или символом:
counters = ActiveSupport::HashWithIndifferentAccess.new
counters[:foo] = 1
counters.fetch('foo') # => 1
counters.fetch(:bar, 0) # => 0
counters.fetch(:bar) { |key| 0 } # => 0
counters.fetch(:zoo) # => KeyError: key not found: "zoo"
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 149 def key?(key) super(convert_key(key)) end
Проверяет хеш на наличие ключа, соответствующего переданному аргументу:
hash = ActiveSupport::HashWithIndifferentAccess.new
hash['key'] = 'value'
hash.key?(:key) # => true
hash.key?('key') # => true
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 198 def merge(hash, &block) self.dup.update(hash, &block) end
Этот метод имеет те же семантические значения, что и update, за исключением того, что он не изменяет получателя, а возвращает новый хеш с неопределенным доступом с результатом слияния.
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 54 def nested_under_indifferent_access self end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 244
def reject(*args, &block)
dup.tap { |hash| hash.reject!(*args, &block) }
end # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 221 def replace(other_hash) super(self.class.new_from_hash_copying_default(other_hash)) end
Заменяет содержимое этого хеша на другой_хеш.
h = { "a" => 100, "b" => 200 }
h.replace({ "c" => 300, "d" => 400 }) # => {"c"=>300, "d"=>400}
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 208 def reverse_merge(other_hash) super(self.class.new_from_hash_copying_default(other_hash)) end
Подобно merge, но наоборот: Объединяет получателя в аргумент и возвращает новый хеш с неопределенным доступом в качестве результата:
hash = ActiveSupport::HashWithIndifferentAccess.new
hash['a'] = nil
hash.reverse_merge(a: 0, b: 1) # => {"a"=>nil, "b"=>1}
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 213 def reverse_merge!(other_hash) replace(reverse_merge( other_hash )) end
Такие же семантические значения, как и reverse_merge, но изменяет получателя на месте.
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 240
def select(*args, &block)
dup.tap { |hash| hash.select!(*args, &block) }
end # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 232 def stringify_keys; dup end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 230 def stringify_keys!; self end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 236 def symbolize_keys; to_hash.symbolize_keys! end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 258
def to_hash
_new_hash = Hash.new
set_defaults(_new_hash)
each do |key, value|
_new_hash[key] = convert_value(value, for: :to_hash)
end
_new_hash
end Преобразовать в обычный хеш со строковыми ключами.
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 238 def to_options!; self end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 248
def transform_values(*args, &block)
return to_enum(:transform_values) unless block_given?
dup.tap { |hash| hash.transform_values!(*args, &block) }
end # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 127
def update(other_hash)
if other_hash.is_a? HashWithIndifferentAccess
super(other_hash)
else
other_hash.to_hash.each_pair do |key, value|
if block_given? && key?(key)
value = yield(convert_key(key), self[key], value)
end
regular_writer(convert_key(key), convert_value(value))
end
self
end
end Обновляет получателя на месте, объединяя переданный в качестве аргумента хеш:
hash_1 = ActiveSupport::HashWithIndifferentAccess.new
hash_1[:key] = 'value'
hash_2 = ActiveSupport::HashWithIndifferentAccess.new
hash_2[:key] = 'New Value!'
hash_1.update(hash_2) # => {"key"=>"New Value!"}
Аргумент может быть как ActiveSupport::HashWithIndifferentAccess, так и обычным Hash. В обоих случаях объединение учитывает семантику доступа без различия типов ключей.
Если аргумент — это обычный хеш с ключами :key, и +“ключ”+, то только одно из значений попадет в получатель, но какое именно — не определено.
Если задан блок, значение для дублирующихся ключей будет определяться результатом вызова блока с дублирующимся ключом, значением в получателе и значением в other_hash. Правила для дублирующихся ключей следуют семантике доступа без различия типов ключей:
hash_1[:key] = 10
hash_2['key'] = 12
hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 177
def values_at(*indices)
indices.collect { |key| self[convert_key(key)] }
end Возвращает массив значений по указанным индексам:
hash = ActiveSupport::HashWithIndifferentAccess.new
hash[:a] = 'x'
hash[:b] = 'y'
hash.values_at('a', 'b') # => ["x", "y"]
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 50 def with_indifferent_access dup end
Защищенные методы экземпляра
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 269 def convert_key(key) key.kind_of?(Symbol) ? key.to_s : key end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 273
def convert_value(value, options = {})
if value.is_a? Hash
if options[:for] == :to_hash
value.to_hash
else
value.nested_under_indifferent_access
end
elsif value.is_a?(Array)
if options[:for] != :assignment || value.frozen?
value = value.dup
end
value.map! { |e| convert_value(e, options) }
else
value
end
end # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 290
def set_defaults(target)
if default_proc
target.default_proc = default_proc.dup
else
target.default = default
end
end
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.