класс ActiveSupport::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
что может быть полезно.
Для доступа к этому классу за пределами Rails, необходимо подключить расширение ядра с помощью:
require "active_support/core_ext/hash/indifferent_access"
что, в свою очередь, потребует этот файл.
Публичные методы класса
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 85 def self.[](*args) new.merge!(Hash[*args]) end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 70
def initialize(constructor = nil)
if constructor.respond_to?(:to_hash)
super()
update(constructor)
hash = constructor.is_a?(Hash) ? constructor : constructor.to_hash
self.default = hash.default if hash.default
self.default_proc = hash.default_proc if hash.default_proc
elsif constructor.nil?
super()
else
super(constructor)
end
end Публичные методы экземпляра
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 168 def [](key) super(convert_key(key)) end
То же самое, что и Hash#[], где ключ, переданный в качестве аргумента, может быть строкой или символом:
counters = ActiveSupport::HashWithIndifferentAccess.new counters[:foo] = 1 counters['foo'] # => 1 counters[:foo] # => 1 counters[:zoo] # => nil
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 98 def []=(key, value) regular_writer(convert_key(key), convert_value(value, conversion: :assignment)) end
Присваивает новое значение хешу:
hash = ActiveSupport::HashWithIndifferentAccess.new hash[:key] = 'value'
Это значение может быть позже получено с помощью :key или 'key'.
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 181 def assoc(key) super(convert_key(key)) end
То же самое, что и Hash#assoc, где ключ, переданный в качестве аргумента, может быть строкой или символом:
counters = ActiveSupport::HashWithIndifferentAccess.new
counters[:foo] = 1
counters.assoc('foo') # => ["foo", 1]
counters.assoc(:foo) # => ["foo", 1]
counters.assoc(:zoo) # => nil
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 375 def compact dup.tap(&:compact!) end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 319 def deep_stringify_keys; dup end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 317 def deep_stringify_keys!; self end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 324 def deep_symbolize_keys; to_hash.deep_symbolize_keys! end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 223
def default(key = (no_key = true))
if no_key
super()
else
super(convert_key(key))
end
end То же самое, что и Hash#default, где ключ, переданный в качестве аргумента, может быть строкой или символом:
hash = ActiveSupport::HashWithIndifferentAccess.new(1)
hash.default # => 1
hash = ActiveSupport::HashWithIndifferentAccess.new { |hash, key| key }
hash.default # => nil
hash.default('foo') # => 'foo'
hash.default(:foo) # => 'foo'
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 303 def delete(key) super(convert_key(key)) end
Удаляет указанный ключ из хеша.
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 208 def dig(*args) args[0] = convert_key(args[0]) if args.size > 0 super(*args) end
То же самое, что и Hash#dig, где ключ, переданный в качестве аргумента, может быть строкой или символом:
counters = ActiveSupport::HashWithIndifferentAccess.new
counters[:foo] = { bar: 1 }
counters.dig('foo', 'bar') # => 1
counters.dig(:foo, :bar) # => 1
counters.dig(:zoo) # => nil
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 264
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] # => "c"
dup[:a][:c] # => "c"
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 311 def except(*keys) dup.except!(*keys) end
Возвращает хеш с индифферентным доступом, который включает всё, кроме заданных ключей.
hash = { a: "x", b: "y", c: 10 }.with_indifferent_access
hash.except(:a, "b") # => {c: 10}.with_indifferent_access
hash # => { a: "x", b: "y", c: 10 }.with_indifferent_access
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 58 def extractable_options? true end
Возвращает true, так что Array#extract_options! находит члены этого класса.
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 195 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 251
def fetch_values(*indices, &block)
indices.map! { |key| convert_key(key) }
super
end Возвращает массив значений по указанным индексам, но также вызывает исключение, когда один из ключей не может быть найден.
hash = ActiveSupport::HashWithIndifferentAccess.new
hash[:a] = 'x'
hash[:b] = 'y'
hash.fetch_values('a', 'b') # => ["x", "y"]
hash.fetch_values('a', 'c') { |key| 'z' } # => ["x", "z"]
hash.fetch_values('a', 'c') # => KeyError: key not found: "c"
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 151 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 273 def merge(*hashes, &block) dup.update(*hashes, &block) end
Этот метод имеет ту же семантику, что и update, за исключением того, что он не изменяет получатель, а возвращает новый хеш с индифферентным доступом с результатом слияния.
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 66 def nested_under_indifferent_access self end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 332
def reject(*args, &block)
return to_enum(:reject) unless block_given?
dup.tap { |hash| hash.reject!(*args, &block) }
end # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 298 def replace(other_hash) super(self.class.new(other_hash)) end
Заменяет содержимое этого хэша на other_hash.
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 283 def reverse_merge(other_hash) super(self.class.new(other_hash)) end
Подобно merge, но наоборот: Объединяет получатель в аргумент и возвращает новый хэш с независимым доступом в результате:
hash = ActiveSupport::HashWithIndifferentAccess.new
hash['a'] = nil
hash.reverse_merge(a: 0, b: 1) # => {"a"=>nil, "b"=>1}
Hash#reverse_merge # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 289 def reverse_merge!(other_hash) super(self.class.new(other_hash)) end
Такая же семантика, как у reverse_merge, но изменяет получатель на месте.
Hash#reverse_merge! # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 327
def select(*args, &block)
return to_enum(:select) unless block_given?
dup.tap { |hash| hash.select!(*args, &block) }
end # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 365
def slice(*keys)
keys.map! { |key| convert_key(key) }
self.class.new(super)
end # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 370
def slice!(*keys)
keys.map! { |key| convert_key(key) }
super
end Hash#slice! # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 318 def stringify_keys; dup end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 316 def stringify_keys!; self end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 322 def symbolize_keys; to_hash.symbolize_keys! end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 380
def to_hash
_new_hash = Hash.new
set_defaults(_new_hash)
each do |key, value|
_new_hash[key] = convert_value(value, conversion: :to_hash)
end
_new_hash
end Преобразовать в обычный хэш со строковыми ключами.
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 325 def to_options!; self end
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 344
def transform_keys(hash = NOT_GIVEN, &block)
return to_enum(:transform_keys) if NOT_GIVEN.equal?(hash) && !block_given?
dup.tap { |h| h.transform_keys!(hash, &block) }
end # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 349
def transform_keys!(hash = NOT_GIVEN, &block)
return to_enum(:transform_keys!) if NOT_GIVEN.equal?(hash) && !block_given?
if hash.nil?
super
elsif NOT_GIVEN.equal?(hash)
keys.each { |key| self[yield(key)] = delete(key) }
elsif block_given?
keys.each { |key| self[hash[key] || yield(key)] = delete(key) }
else
keys.each { |key| self[hash[key] || key] = delete(key) }
end
self
end # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 337
def transform_values(&block)
return to_enum(:transform_values) unless block_given?
dup.tap { |hash| hash.transform_values!(&block) }
end # File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 132
def update(*other_hashes, &block)
if other_hashes.size == 1
update_with_single_argument(other_hashes.first, block)
else
other_hashes.each do |other_hash|
update_with_single_argument(other_hash, block)
end
end
self
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!"}
hash = ActiveSupport::HashWithIndifferentAccess.new
hash.update({ "a" => 1 }, { "b" => 2 }) # => { "a" => 1, "b" => 2 }
Аргументы могут быть либо ActiveSupport::HashWithIndifferentAccess, либо обычным Hash. В любом случае объединение учитывает семантику независимого доступа.
Если аргумент — обычный хэш с ключами :key и "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 237
def values_at(*keys)
keys.map! { |key| convert_key(key) }
super
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 62 def with_indifferent_access dup end
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.