[rubocop] Improve our RuboCop setup
Disable Metrics/BlockLength in specs because the length of a block in the test suite isn't something we want to lint. We want the tests to be as long as they need to be. Set an explicit line length metric instead of continually updating this as we go. Let's pick a max line length that we want to see and stick with it. This metric should only ever decrease: we don't want to see it ever increase again.
This commit is contained in:
parent
0235a18c14
commit
5b5ed2119d
|
@ -12,6 +12,15 @@ inherit_from: .rubocop_todo.yml
|
|||
Layout/IndentHeredoc:
|
||||
Enabled: false
|
||||
|
||||
Metrics/BlockLength:
|
||||
Exclude:
|
||||
- 'spec/**/*.rb'
|
||||
|
||||
Metrics/LineLength:
|
||||
Exclude:
|
||||
- 'Guardfile'
|
||||
Max: 110
|
||||
|
||||
Naming/FileName:
|
||||
Exclude:
|
||||
- 'Dangerfile'
|
||||
|
|
|
@ -1,26 +1,21 @@
|
|||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config`
|
||||
# on 2018-08-14 21:37:22 -0500 using RuboCop version 0.52.1.
|
||||
# on 2018-09-30 14:46:03 -0500 using RuboCop version 0.52.1.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
# versions of RuboCop, may require this file to be generated again.
|
||||
|
||||
# Offense count: 8
|
||||
# Offense count: 7
|
||||
Metrics/AbcSize:
|
||||
Max: 24
|
||||
|
||||
# Offense count: 58
|
||||
# Configuration parameters: CountComments, ExcludedMethods.
|
||||
Metrics/BlockLength:
|
||||
Max: 626
|
||||
Max: 23
|
||||
|
||||
# Offense count: 2
|
||||
# Configuration parameters: CountComments.
|
||||
Metrics/ClassLength:
|
||||
Max: 209
|
||||
|
||||
# Offense count: 8
|
||||
# Offense count: 7
|
||||
Metrics/CyclomaticComplexity:
|
||||
Max: 11
|
||||
|
||||
|
@ -29,27 +24,10 @@ Metrics/CyclomaticComplexity:
|
|||
Metrics/MethodLength:
|
||||
Max: 28
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: CountComments.
|
||||
Metrics/ModuleLength:
|
||||
Max: 102
|
||||
|
||||
# Offense count: 6
|
||||
# Offense count: 5
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 10
|
||||
|
||||
# Offense count: 36
|
||||
# Offense count: 37
|
||||
Style/Documentation:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/IfUnlessModifier:
|
||||
Exclude:
|
||||
- 'lib/hashie/extensions/strict_key_access.rb'
|
||||
|
||||
# Offense count: 263
|
||||
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
||||
# URISchemes: http, https
|
||||
Metrics/LineLength:
|
||||
Max: 170
|
||||
|
|
|
@ -37,6 +37,7 @@ scheme are considered to be bugs.
|
|||
|
||||
### Miscellaneous
|
||||
|
||||
* [#465](https://github.com/intridea/hashie/pull/465): Clean up our RuboCop configuration and fix the outstanding line length violations. This involved some minor refactoring on `Hashie::Extensions::Coercion`, `Hashie::Extensions::Dash::IndifferentAccess`, `Hashie::Extensions::DeepLocate`, `Hashie::Extensions::Mash::SafeAssignment`, and `Hashie::Hash`, but none that were detectable via the test suite - [@michaelherold](https://github.com/michaelherold).
|
||||
* Your contribution here.
|
||||
|
||||
## [3.6.0] - 2018-08-13
|
||||
|
|
|
@ -11,7 +11,8 @@ Gem::Specification.new do |gem|
|
|||
gem.license = 'MIT'
|
||||
|
||||
gem.require_paths = ['lib']
|
||||
gem.files = %w[.yardopts CHANGELOG.md CONTRIBUTING.md LICENSE README.md UPGRADING.md Rakefile hashie.gemspec]
|
||||
gem.files = %w[.yardopts CHANGELOG.md CONTRIBUTING.md LICENSE README.md UPGRADING.md]
|
||||
gem.files += %w[Rakefile hashie.gemspec]
|
||||
gem.files += Dir['lib/**/*.rb']
|
||||
gem.files += Dir['spec/**/*.rb']
|
||||
gem.test_files = Dir['spec/**/*.rb']
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
module Hashie
|
||||
class CoercionError < StandardError; end
|
||||
class CoercionError < StandardError
|
||||
def initialize(key, value, into, message)
|
||||
super("Cannot coerce property #{key.inspect} from #{value.class} to #{into}: #{message}")
|
||||
end
|
||||
end
|
||||
|
||||
module Extensions
|
||||
module Coercion
|
||||
|
@ -12,20 +16,22 @@ module Hashie
|
|||
Symbol => :to_sym
|
||||
}.freeze
|
||||
|
||||
ABSTRACT_CORE_TYPES = if RubyVersion.new(RUBY_VERSION) >= RubyVersion.new('2.4.0')
|
||||
{ Numeric => [Integer, Float, Complex, Rational] }
|
||||
else
|
||||
{
|
||||
Integer => [Fixnum, Bignum], # rubocop:disable Lint/UnifiedInteger
|
||||
Numeric => [Fixnum, Bignum, Float, Complex, Rational] # rubocop:disable Lint/UnifiedInteger
|
||||
}
|
||||
end
|
||||
ABSTRACT_CORE_TYPES =
|
||||
if RubyVersion.new(RUBY_VERSION) >= RubyVersion.new('2.4.0')
|
||||
{ Numeric => [Integer, Float, Complex, Rational] }
|
||||
else
|
||||
{
|
||||
Integer => [Fixnum, Bignum], # rubocop:disable Lint/UnifiedInteger
|
||||
Numeric => [Fixnum, Bignum, Float, Complex, Rational] # rubocop:disable Lint/UnifiedInteger
|
||||
}
|
||||
end
|
||||
|
||||
def self.included(base)
|
||||
base.send :include, InstanceMethods
|
||||
base.extend ClassMethods # NOTE: we wanna make sure we first define set_value_with_coercion before extending
|
||||
|
||||
base.send :alias_method, :set_value_without_coercion, :[]= unless base.method_defined?(:set_value_without_coercion)
|
||||
base.extend ClassMethods
|
||||
unless base.method_defined?(:set_value_without_coercion)
|
||||
base.send :alias_method, :set_value_without_coercion, :[]=
|
||||
end
|
||||
base.send :alias_method, :[]=, :set_value_with_coercion
|
||||
end
|
||||
|
||||
|
@ -37,7 +43,7 @@ module Hashie
|
|||
begin
|
||||
value = self.class.fetch_coercion(into).call(value)
|
||||
rescue NoMethodError, TypeError => e
|
||||
raise CoercionError, "Cannot coerce property #{key.inspect} from #{value.class} to #{into}: #{e.message}"
|
||||
raise CoercionError.new(key, value, into, e.message)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -7,11 +7,23 @@ module Hashie
|
|||
base.send :include, Hashie::Extensions::IndifferentAccess
|
||||
end
|
||||
|
||||
def self.maybe_extend(base)
|
||||
return unless requires_class_methods?(base)
|
||||
|
||||
base.extend(ClassMethods)
|
||||
end
|
||||
|
||||
def self.requires_class_methods?(klass)
|
||||
klass <= Hashie::Dash &&
|
||||
!klass.singleton_class.included_modules.include?(ClassMethods)
|
||||
end
|
||||
private_class_method :requires_class_methods?
|
||||
|
||||
module ClassMethods
|
||||
# Check to see if the specified property has already been
|
||||
# defined.
|
||||
def property?(name)
|
||||
name = translations[name.to_sym] if included_modules.include?(Hashie::Extensions::Dash::PropertyTranslation) && translation_exists?(name)
|
||||
name = translations[name.to_sym] if translation_for?(name)
|
||||
name = name.to_s
|
||||
!!properties.find { |property| property.to_s == name }
|
||||
end
|
||||
|
@ -30,6 +42,13 @@ module Hashie
|
|||
name = name.to_s
|
||||
!!transforms.keys.find { |key| key.to_s == name }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def translation_for?(name)
|
||||
included_modules.include?(Hashie::Extensions::Dash::PropertyTranslation) &&
|
||||
translation_exists?(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -58,7 +58,9 @@ module Hashie
|
|||
end
|
||||
|
||||
def permitted_input_keys
|
||||
@permitted_input_keys ||= properties.map { |property| inverse_translations.fetch property, property }
|
||||
@permitted_input_keys ||=
|
||||
properties
|
||||
.map { |property| inverse_translations.fetch property, property }
|
||||
end
|
||||
|
||||
# Defines a property on the Trash. Options are as follows:
|
||||
|
|
|
@ -62,7 +62,7 @@ module Hashie
|
|||
end
|
||||
|
||||
def self._construct_key_comparator(search_key, object)
|
||||
search_key = search_key.to_s if defined?(::ActiveSupport::HashWithIndifferentAccess) && object.is_a?(::ActiveSupport::HashWithIndifferentAccess)
|
||||
search_key = search_key.to_s if activesupport_indifferent?(object)
|
||||
search_key = search_key.to_s if object.respond_to?(:indifferent_access?) && object.indifferent_access?
|
||||
|
||||
lambda do |non_callable_object|
|
||||
|
@ -93,6 +93,12 @@ module Hashie
|
|||
comparator.call(key, value, object)
|
||||
end
|
||||
private_class_method :_match_comparator?
|
||||
|
||||
def self.activesupport_indifferent?(object)
|
||||
defined?(::ActiveSupport::HashWithIndifferentAccess) &&
|
||||
object.is_a?(::ActiveSupport::HashWithIndifferentAccess)
|
||||
end
|
||||
private_class_method :activesupport_indifferent?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,9 +24,7 @@ module Hashie
|
|||
#
|
||||
module IndifferentAccess
|
||||
def self.included(base)
|
||||
Hashie::Extensions::Dash::IndifferentAccess::ClassMethods.tap do |extension|
|
||||
base.extend(extension) if base <= Hashie::Dash && !base.singleton_class.included_modules.include?(extension)
|
||||
end
|
||||
Hashie::Extensions::Dash::IndifferentAccess.maybe_extend(base)
|
||||
|
||||
base.class_eval do
|
||||
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
|
||||
|
|
|
@ -3,7 +3,9 @@ module Hashie
|
|||
module Mash
|
||||
module SafeAssignment
|
||||
def custom_writer(key, *args) #:nodoc:
|
||||
raise ArgumentError, "The property #{key} clashes with an existing method." if !key?(key) && respond_to?(key, true)
|
||||
if !key?(key) && respond_to?(key, true)
|
||||
raise ArgumentError, "The property #{key} clashes with an existing method."
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
|
|
|
@ -15,12 +15,15 @@ module Hashie
|
|||
# >> hash[:cow]
|
||||
# KeyError: key not found: :cow
|
||||
#
|
||||
# NOTE: For googlers coming from Python to Ruby, this extension makes a Hash behave more like a "Dictionary".
|
||||
# NOTE: For googlers coming from Python to Ruby, this extension makes a Hash
|
||||
# behave more like a "Dictionary".
|
||||
#
|
||||
module StrictKeyAccess
|
||||
class DefaultError < StandardError
|
||||
def initialize(msg = 'Setting or using a default with Hashie::Extensions::StrictKeyAccess does not make sense', *args)
|
||||
super
|
||||
def initialize
|
||||
super(
|
||||
'Setting or using a default with Hashie::Extensions::StrictKeyAccess does not make sense'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -18,20 +18,21 @@ module Hashie
|
|||
def to_hash(options = {})
|
||||
out = {}
|
||||
each_key do |k|
|
||||
assignment_key = if options[:stringify_keys]
|
||||
k.to_s
|
||||
elsif options[:symbolize_keys]
|
||||
k.to_s.to_sym
|
||||
else
|
||||
k
|
||||
end
|
||||
assignment_key =
|
||||
if options[:stringify_keys]
|
||||
k.to_s
|
||||
elsif options[:symbolize_keys]
|
||||
k.to_s.to_sym
|
||||
else
|
||||
k
|
||||
end
|
||||
if self[k].is_a?(Array)
|
||||
out[assignment_key] ||= []
|
||||
self[k].each do |array_object|
|
||||
out[assignment_key] << (array_object.is_a?(Hash) ? flexibly_convert_to_hash(array_object, options) : array_object)
|
||||
out[assignment_key] << maybe_convert_to_hash(array_object, options)
|
||||
end
|
||||
else
|
||||
out[assignment_key] = self[k].is_a?(Hash) || self[k].respond_to?(:to_hash) ? flexibly_convert_to_hash(self[k], options) : self[k]
|
||||
out[assignment_key] = maybe_convert_to_hash(self[k], options)
|
||||
end
|
||||
end
|
||||
out
|
||||
|
@ -44,6 +45,12 @@ module Hashie
|
|||
|
||||
private
|
||||
|
||||
def maybe_convert_to_hash(object, options)
|
||||
return object unless object.is_a?(Hash) || object.respond_to?(:to_hash)
|
||||
|
||||
flexibly_convert_to_hash(object, options)
|
||||
end
|
||||
|
||||
def flexibly_convert_to_hash(object, options = {})
|
||||
if object.method(:to_hash).arity.zero?
|
||||
object.to_hash
|
||||
|
|
|
@ -16,8 +16,10 @@ module Hashie
|
|||
# * No punctuation: Returns the value of the hash for that key, or nil if none exists.
|
||||
# * Assignment (<tt>=</tt>): Sets the attribute of the given method name.
|
||||
# * Existence (<tt>?</tt>): Returns true or false depending on whether that key has been set.
|
||||
# * Bang (<tt>!</tt>): Forces the existence of this key, used for deep Mashes. Think of it as "touch" for mashes.
|
||||
# * Under Bang (<tt>_</tt>): Like Bang, but returns a new Mash rather than creating a key. Used to test existance in deep Mashes.
|
||||
# * Bang (<tt>!</tt>): Forces the existence of this key, used for deep Mashes. Think of it
|
||||
# as "touch" for mashes.
|
||||
# * Under Bang (<tt>_</tt>): Like Bang, but returns a new Mash rather than creating a key.
|
||||
# Used to test existance in deep Mashes.
|
||||
#
|
||||
# == Basic Example
|
||||
#
|
||||
|
@ -64,8 +66,11 @@ module Hashie
|
|||
ALLOWED_SUFFIXES = %w[? ! = _].freeze
|
||||
|
||||
class CannotDisableMashWarnings < StandardError
|
||||
def initialize(message = 'You cannot disable warnings on the base Mash class. Please subclass the Mash and disable it in the subclass.')
|
||||
super(message)
|
||||
def initialize
|
||||
super(
|
||||
'You cannot disable warnings on the base Mash class. ' \
|
||||
'Please subclass the Mash and disable it in the subclass.'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -129,12 +129,14 @@ describe DashTest do
|
|||
context 'writing to properties' do
|
||||
it 'fails writing a required property to nil' do
|
||||
expect { subject.first_name = nil }.to raise_error(*property_required_error('first_name'))
|
||||
expect { required_message.first_name = nil }.to raise_error(*property_required_custom_error('first_name'))
|
||||
expect { required_message.first_name = nil }
|
||||
.to raise_error(*property_required_custom_error('first_name'))
|
||||
end
|
||||
|
||||
it 'fails writing a required property to nil using []=' do
|
||||
expect { subject[:first_name] = nil }.to raise_error(*property_required_error('first_name'))
|
||||
expect { required_message[:first_name] = nil }.to raise_error(*property_required_custom_error('first_name'))
|
||||
expect { required_message[:first_name] = nil }
|
||||
.to raise_error(*property_required_custom_error('first_name'))
|
||||
end
|
||||
|
||||
it 'fails writing to a non-existent property using []=' do
|
||||
|
@ -505,7 +507,8 @@ end
|
|||
|
||||
describe ConditionallyRequiredTest do
|
||||
it 'does not allow a conditionally required property to be set to nil if required' do
|
||||
expect { ConditionallyRequiredTest.new(username: 'bob.smith', password: nil) }.to raise_error(ArgumentError, "The property 'password' must be set, too.")
|
||||
expect { ConditionallyRequiredTest.new(username: 'bob.smith', password: nil) }
|
||||
.to raise_error(ArgumentError, "The property 'password' must be set, too.")
|
||||
end
|
||||
|
||||
it 'allows a conditionally required property to be set to nil if not required' do
|
||||
|
|
|
@ -283,7 +283,8 @@ describe Hashie::Extensions::Coercion do
|
|||
|
||||
it 'raises errors for non-coercable types' do
|
||||
subject.coerce_key :foo, NotInitializable
|
||||
expect { instance[:foo] = 'true' }.to raise_error(Hashie::CoercionError, /NotInitializable is not a coercable type/)
|
||||
expect { instance[:foo] = 'true' }
|
||||
.to raise_error(Hashie::CoercionError, /NotInitializable is not a coercable type/)
|
||||
end
|
||||
|
||||
it 'can coerce false' do
|
||||
|
@ -566,7 +567,8 @@ describe Hashie::Extensions::Coercion do
|
|||
end
|
||||
|
||||
subject.coerce_value type, Symbol
|
||||
expect { instance[:hi] = 1 }.to raise_error(Hashie::CoercionError, /Cannot coerce property :hi from #{type} to Symbol/)
|
||||
expect { instance[:hi] = 1 }
|
||||
.to raise_error(Hashie::CoercionError, /Cannot coerce property :hi from #{type} to Symbol/)
|
||||
end
|
||||
|
||||
it 'coerces Integer to String' do
|
||||
|
|
|
@ -64,7 +64,8 @@ describe Hashie::Extensions::DeepFind do
|
|||
end
|
||||
|
||||
it 'detects all values from a nested hash' do
|
||||
expect(instance.deep_find_all(:title)).to eq([{ type: :string }, 'Call of the Wild', 'Moby Dick', 'Main Library'])
|
||||
expect(instance.deep_find_all(:title))
|
||||
.to eq([{ type: :string }, 'Call of the Wild', 'Moby Dick', 'Main Library'])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,7 +15,9 @@ describe Hashie::Extensions::DeepMerge do
|
|||
context 'without &block' do
|
||||
let(:h1) { subject.new.merge(a: 'a', a1: 42, b: 'b', c: { c1: 'c1', c2: { a: 'b' }, c3: { d1: 'd1' } }) }
|
||||
let(:h2) { { a: 1, a1: 1, c: { c1: 2, c2: 'c2', c3: { d2: 'd2' } }, e: { e1: 1 } } }
|
||||
let(:expected_hash) { { a: 1, a1: 1, b: 'b', c: { c1: 2, c2: 'c2', c3: { d1: 'd1', d2: 'd2' } }, e: { e1: 1 } } }
|
||||
let(:expected_hash) do
|
||||
{ a: 1, a1: 1, b: 'b', c: { c1: 2, c2: 'c2', c3: { d1: 'd1', d2: 'd2' } }, e: { e1: 1 } }
|
||||
end
|
||||
|
||||
it 'deep merges two hashes' do
|
||||
expect(h1.deep_merge(h2)).to eq expected_hash
|
||||
|
|
|
@ -41,7 +41,8 @@ describe Hashie::Extensions::IgnoreUndeclared do
|
|||
property :some_other_key
|
||||
end
|
||||
hash = ForgivingTrashWithMergeAndProperty.new(some_ignored_key: 17, some_key: 12)
|
||||
expect(hash.deep_merge(some_other_key: 55, some_ignored_key: 18)).to eq(some_key: 12, some_other_key: 55)
|
||||
expect(hash.deep_merge(some_other_key: 55, some_ignored_key: 18))
|
||||
.to eq(some_key: 12, some_other_key: 55)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -128,7 +128,14 @@ describe Hashie::Extensions::MethodAccess do
|
|||
it 'includes all of the other method mixins' do
|
||||
klass = Class.new(Hash)
|
||||
klass.send :include, Hashie::Extensions::MethodAccess
|
||||
expect((klass.ancestors & [Hashie::Extensions::MethodReader, Hashie::Extensions::MethodWriter, Hashie::Extensions::MethodQuery]).size).to eq 3
|
||||
|
||||
included_modules = klass.ancestors & [
|
||||
Hashie::Extensions::MethodReader,
|
||||
Hashie::Extensions::MethodWriter,
|
||||
Hashie::Extensions::MethodQuery
|
||||
]
|
||||
|
||||
expect(included_modules.size).to eq 3
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -35,34 +35,33 @@ describe Hashie::Extensions::StrictKeyAccess do
|
|||
context 'lookup' do
|
||||
it('raises an error') do
|
||||
# Formatting of the error message does not vary here because raised by StrictKeyAccess
|
||||
expect { instance.key(invalid_value) }.to raise_error KeyError,
|
||||
%(key not found with value of #{invalid_value.inspect})
|
||||
expect { instance.key(invalid_value) }.to raise_error KeyError
|
||||
end
|
||||
end
|
||||
end
|
||||
shared_examples_for 'StrictKeyAccess raises KeyError instead of allowing defaults' do
|
||||
context '#default' do
|
||||
it 'raises an error' do
|
||||
expect { instance.default(invalid_key) }.to raise_error Hashie::Extensions::StrictKeyAccess::DefaultError,
|
||||
'Setting or using a default with Hashie::Extensions::StrictKeyAccess does not make sense'
|
||||
expect { instance.default(invalid_key) }
|
||||
.to raise_error Hashie::Extensions::StrictKeyAccess::DefaultError
|
||||
end
|
||||
end
|
||||
context '#default=' do
|
||||
it 'raises an error' do
|
||||
expect { instance.default = invalid_key }.to raise_error Hashie::Extensions::StrictKeyAccess::DefaultError,
|
||||
'Setting or using a default with Hashie::Extensions::StrictKeyAccess does not make sense'
|
||||
expect { instance.default = invalid_key }
|
||||
.to raise_error Hashie::Extensions::StrictKeyAccess::DefaultError
|
||||
end
|
||||
end
|
||||
context '#default_proc' do
|
||||
it 'raises an error' do
|
||||
expect { instance.default_proc }.to raise_error Hashie::Extensions::StrictKeyAccess::DefaultError,
|
||||
'Setting or using a default with Hashie::Extensions::StrictKeyAccess does not make sense'
|
||||
expect { instance.default_proc }
|
||||
.to raise_error Hashie::Extensions::StrictKeyAccess::DefaultError
|
||||
end
|
||||
end
|
||||
context '#default_proc=' do
|
||||
it 'raises an error' do
|
||||
expect { instance.default_proc = proc {} }.to raise_error Hashie::Extensions::StrictKeyAccess::DefaultError,
|
||||
'Setting or using a default with Hashie::Extensions::StrictKeyAccess does not make sense'
|
||||
expect { instance.default_proc = proc {} }
|
||||
.to raise_error Hashie::Extensions::StrictKeyAccess::DefaultError
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -88,7 +88,9 @@ describe Hashie::Extensions::SymbolizeKeys do
|
|||
|
||||
context 'singleton methods' do
|
||||
subject { Hash }
|
||||
let(:object) { subject.new.merge('a' => 1, 'b' => { 'c' => 2 }).extend(Hashie::Extensions::SymbolizeKeys) }
|
||||
let(:object) do
|
||||
subject.new.merge('a' => 1, 'b' => { 'c' => 2 }).extend(Hashie::Extensions::SymbolizeKeys)
|
||||
end
|
||||
let(:expected_hash) { { a: 1, b: { c: 2 } } }
|
||||
|
||||
describe '.symbolize_keys' do
|
||||
|
|
|
@ -66,19 +66,43 @@ describe Hash do
|
|||
it '#to_hash returns a hash with same keys' do
|
||||
hash = Hashie::Hash['a' => 'hey', 123 => 'bob', 'array' => [1, 2, 3], subhash: ClassRespondsToHash.new]
|
||||
stringified_hash = hash.to_hash
|
||||
expect(stringified_hash).to eq('a' => 'hey', 123 => 'bob', 'array' => [1, 2, 3], subhash: { 'a' => 'hey', b: 'bar', 123 => 'bob', 'array' => [1, 2, 3] })
|
||||
|
||||
expected = {
|
||||
'a' => 'hey',
|
||||
123 => 'bob',
|
||||
'array' => [1, 2, 3],
|
||||
subhash: { 'a' => 'hey', b: 'bar', 123 => 'bob', 'array' => [1, 2, 3] }
|
||||
}
|
||||
|
||||
expect(stringified_hash).to eq(expected)
|
||||
end
|
||||
|
||||
it '#to_hash with stringify_keys set to true returns a hash with stringified_keys' do
|
||||
hash = Hashie::Hash['a' => 'hey', 123 => 'bob', 'array' => [1, 2, 3], subhash: ClassRespondsToHash.new]
|
||||
symbolized_hash = hash.to_hash(stringify_keys: true)
|
||||
expect(symbolized_hash).to eq('a' => 'hey', '123' => 'bob', 'array' => [1, 2, 3], 'subhash' => { 'a' => 'hey', 'b' => 'bar', '123' => 'bob', 'array' => [1, 2, 3] })
|
||||
|
||||
expected = {
|
||||
'a' => 'hey',
|
||||
'123' => 'bob',
|
||||
'array' => [1, 2, 3],
|
||||
'subhash' => { 'a' => 'hey', 'b' => 'bar', '123' => 'bob', 'array' => [1, 2, 3] }
|
||||
}
|
||||
|
||||
expect(symbolized_hash).to eq(expected)
|
||||
end
|
||||
|
||||
it '#to_hash with symbolize_keys set to true returns a hash with symbolized keys' do
|
||||
hash = Hashie::Hash['a' => 'hey', 123 => 'bob', 'array' => [1, 2, 3], subhash: ClassRespondsToHash.new]
|
||||
symbolized_hash = hash.to_hash(symbolize_keys: true)
|
||||
expect(symbolized_hash).to eq(a: 'hey', :"123" => 'bob', array: [1, 2, 3], subhash: { a: 'hey', b: 'bar', :'123' => 'bob', array: [1, 2, 3] })
|
||||
|
||||
expected = {
|
||||
a: 'hey',
|
||||
:"123" => 'bob',
|
||||
array: [1, 2, 3],
|
||||
subhash: { a: 'hey', b: 'bar', :'123' => 'bob', array: [1, 2, 3] }
|
||||
}
|
||||
|
||||
expect(symbolized_hash).to eq(expected)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -234,7 +234,10 @@ describe Hashie::Mash do
|
|||
end
|
||||
|
||||
it 'copies values for non-duplicate keys when a block is supplied' do
|
||||
duped = subject.merge(details: { address: 'Pasadena CA', state: 'West Thoughtleby' }) { |_, oldv, _| oldv }
|
||||
duped =
|
||||
subject
|
||||
.merge(details: { address: 'Pasadena CA', state: 'West Thoughtleby' }) { |_, oldv, _| oldv }
|
||||
|
||||
expect(duped.details.address).to eq 'Nowhere road'
|
||||
expect(duped.details.state).to eq 'West Thoughtleby'
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue