hashie 3.6.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/README.md +95 -7
  4. data/UPGRADING.md +78 -2
  5. data/hashie.gemspec +2 -1
  6. data/lib/hashie.rb +20 -19
  7. data/lib/hashie/dash.rb +2 -1
  8. data/lib/hashie/extensions/active_support/core_ext/hash.rb +14 -0
  9. data/lib/hashie/extensions/coercion.rb +23 -16
  10. data/lib/hashie/extensions/dash/indifferent_access.rb +20 -1
  11. data/lib/hashie/extensions/dash/property_translation.rb +5 -2
  12. data/lib/hashie/extensions/deep_fetch.rb +4 -2
  13. data/lib/hashie/extensions/deep_find.rb +12 -3
  14. data/lib/hashie/extensions/deep_locate.rb +22 -7
  15. data/lib/hashie/extensions/indifferent_access.rb +1 -3
  16. data/lib/hashie/extensions/key_conflict_warning.rb +55 -0
  17. data/lib/hashie/extensions/mash/define_accessors.rb +90 -0
  18. data/lib/hashie/extensions/mash/keep_original_keys.rb +2 -1
  19. data/lib/hashie/extensions/mash/safe_assignment.rb +3 -1
  20. data/lib/hashie/extensions/method_access.rb +5 -2
  21. data/lib/hashie/extensions/parsers/yaml_erb_parser.rb +9 -4
  22. data/lib/hashie/extensions/strict_key_access.rb +8 -4
  23. data/lib/hashie/hash.rb +16 -9
  24. data/lib/hashie/mash.rb +99 -43
  25. data/lib/hashie/railtie.rb +7 -0
  26. data/lib/hashie/rash.rb +1 -1
  27. data/lib/hashie/version.rb +1 -1
  28. data/spec/hashie/dash_spec.rb +18 -8
  29. data/spec/hashie/extensions/coercion_spec.rb +17 -8
  30. data/spec/hashie/extensions/deep_find_spec.rb +12 -6
  31. data/spec/hashie/extensions/deep_locate_spec.rb +2 -1
  32. data/spec/hashie/extensions/deep_merge_spec.rb +6 -2
  33. data/spec/hashie/extensions/ignore_undeclared_spec.rb +2 -1
  34. data/spec/hashie/extensions/mash/define_accessors_spec.rb +90 -0
  35. data/spec/hashie/extensions/method_access_spec.rb +8 -1
  36. data/spec/hashie/extensions/strict_key_access_spec.rb +9 -10
  37. data/spec/hashie/extensions/symbolize_keys_spec.rb +3 -1
  38. data/spec/hashie/hash_spec.rb +45 -6
  39. data/spec/hashie/mash_spec.rb +314 -8
  40. data/spec/hashie/trash_spec.rb +9 -3
  41. data/spec/integration/elasticsearch/integration_spec.rb +3 -2
  42. data/spec/integration/rails/app.rb +5 -12
  43. data/spec/integration/rails/integration_spec.rb +22 -1
  44. metadata +8 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8995ca652ff77136955a0d399e6b880e84a9e9c6772c25fdd4cc16599bbb0bce
4
- data.tar.gz: 15b18e37285c1beb76f751aea7907b684bd5faddb0d4a476f305f5da90315f8d
3
+ metadata.gz: 8aa4350423b73820353dc1e15eeff8f6dee0325534e008bec7a2986313673df2
4
+ data.tar.gz: 81467077618908f8e4ce9289072a7cb760f61fe9e40ca5992d39a9e7bba406d1
5
5
  SHA512:
6
- metadata.gz: e17ecdf0d6ce04ed2ad95f0451d53f01842ee32932d1a8f58a5a3b4056a94772d6c61b8ba8493b59de5d85fd304df21f24b506053508bf816b25809d9f6ea20f
7
- data.tar.gz: 54cf50c12052a424a1a4fba3fd3d34e6b65d8ca3f353b96fc96e3c0e9a7dfa76db5856ec1e8b8572128ec34feae59d22ef7df14674a6d05715d372c0bdfce849
6
+ metadata.gz: 680143be9e6ea67deec9ab82c3cac7ab412c177a65519852e88ab8873777df0797cd3cf05f84a8cddea15599d25f0fae8428df9679b539246c7002175ea127f6
7
+ data.tar.gz: c3b7362ef0c83103cf2ab9d876335ca0e9501194d3afca4eabf92db1f0e60b74c0643e880929ed3a7eb2faa40be49f12012d6dc17603ea382171a2a588da5398
@@ -6,6 +6,34 @@ scheme are considered to be bugs.
6
6
 
7
7
  [semver]: http://semver.org/spec/v2.0.0.html
8
8
 
9
+ ## [4.0.0] - 2019-10-30
10
+
11
+ [4.0.0]: https://github.com/intridea/hashie/compare/v3.6.0...v4.0.0
12
+
13
+ ### Added
14
+
15
+ * [#323](https://github.com/intridea/hashie/pull/323): Added `Hashie::Extensions::Mash::DefineAccessors` - [@marshall-lee](https://github.com/marshall-lee).
16
+ * [#474](https://github.com/intridea/hashie/pull/474): Expose `YAML#safe_load` options in `Mash#load` - [@riouruma](https://github.com/riouruma), [@dblock](https://github.com/dblock).
17
+ * [#478](https://github.com/intridea/hashie/pull/478): Added optional array parameter to `Hashie::Mash.disable_warnings` - [@bobbymcwho](https://github.com/bobbymcwho).
18
+ * [#481](https://github.com/intridea/hashie/pull/481): Ruby 2.6 - Support `Hash#merge` and `#merge!` called with multiple Hashes/Mashes - [@bobbymcwho](https://github.com/bobbymcwho).
19
+ * [#488](https://github.com/intridea/hashie/pull/488): Added ability to create an anonymous `Hashie::Mash` subclass with key conflict errors silenced using `Hashie::Mash.quiet.new` - [@bobbymcwho](https://github.com/bobbymcwho).
20
+
21
+ ### Changed
22
+
23
+ * [#481](https://github.com/intridea/hashie/pull/481): Implement non-destructive standard Hash methods - [@bobbymcwho](https://github.com/bobbymcwho).
24
+
25
+ ### Fixed
26
+
27
+ * [#459](https://github.com/intridea/hashie/pull/459): Fixed a regression in `Mash.load` that disallowed aliases - [@arekt](https://github.com/arekt) and [@michaelherold](https://github.com/michaelherold).
28
+ * [#465](https://github.com/intridea/hashie/pull/465): Fixed `deep_update` to call any readers when a key exists - [@laertispappas](https://github.com/laertispappas).
29
+ * [#479](https://github.com/intridea/hashie/pull/479): Fixed an issue with `Hash#except` not returning a `Mash` in Rails 6 - [@bobbymcwho](https://github.com/bobbymcwho).
30
+ * [#489](https://github.com/intridea/hashie/pull/489): Updated the documentation to exlain the behavior of `Mash` and keyword arguments - [@Bhacaz](https://github.com/Bhacaz).
31
+
32
+ ### Miscellaneous
33
+
34
+ * [#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).
35
+ * [#482](https://github.com/intridea/hashie/pull/482): Update Travis configs to make jruby builds run on trusty dist. - [@BobbyMcWho](https://github.com/BobbyMcWho).
36
+
9
37
  ## [3.6.0] - 2018-08-13
10
38
 
11
39
  [3.6.0]: https://github.com/intridea/hashie/compare/v3.5.7...v3.6.0
data/README.md CHANGED
@@ -18,7 +18,7 @@ $ gem install hashie
18
18
 
19
19
  ## Upgrading
20
20
 
21
- You're reading the documentation for the stable release of Hashie, 3.6.0. Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
21
+ You're reading the documentation for the stable release of Hashie, 4.0.0. Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
22
22
 
23
23
  ## Hash Extensions
24
24
 
@@ -190,7 +190,7 @@ end
190
190
 
191
191
  ### KeyConversion
192
192
 
193
- The KeyConversion extension gives you the convenience methods of `symbolize_keys` and `stringify_keys` along with their bang counterparts. You can also include just stringify or just symbolize with `Hashie::Extensions::StringifyKeys` or `Hashie::Extensions::SymbolizeKeys`.
193
+ The KeyConversion extension gives you the convenience methods of `symbolize_keys` and `stringify_keys` along with their bang counterparts. You can also include just stringify or just symbolize with `Hashie::Extensions::StringifyKeys` or [`Hashie::Extensions::SymbolizeKeys`](#mash-extension-symbolizekeys).
194
194
 
195
195
  Hashie also has a utility method for converting keys on a Hash without a mixin:
196
196
 
@@ -316,8 +316,8 @@ p.email # => NoMethodError
316
316
 
317
317
  ### DeepMerge
318
318
 
319
- This extension allow you to easily include a recursive merging
320
- system to any Hash descendant:
319
+ This extension allows you to easily include a recursive merging
320
+ system into any Hash descendant:
321
321
 
322
322
  ```ruby
323
323
  class MyHash < Hash
@@ -515,6 +515,55 @@ class Response < Hashie::Mash
515
515
  end
516
516
  ```
517
517
 
518
+ The default is to disable logging for all methods that conflict. If you would like to only disable the logging for specific methods, you can include an array of method keys:
519
+
520
+ ```ruby
521
+ class Response < Hashie::Mash
522
+ disable_warnings :zip, :zap
523
+ end
524
+ ```
525
+
526
+ This behavior is cumulative. The examples above and below behave identically.
527
+
528
+ ```ruby
529
+ class Response < Hashie::Mash
530
+ disable_warnings :zip
531
+ disable_warnings :zap
532
+ end
533
+ ```
534
+
535
+ Disable warnings will honor the last `disable_warnings` call. Calling without parameters will override the ignored methods list, and calling with parameters will create a new ignored methods list. This includes child classes that inherit from a class that disables warnings.
536
+
537
+ ```ruby
538
+ class Message < Hashie::Mash
539
+ disable_warnings :zip, :zap
540
+ disable_warnings
541
+ end
542
+
543
+ # No errors will be logged
544
+ Message.new(merge: 'true', compact: true)
545
+ ```
546
+
547
+ ```ruby
548
+ class Message < Hashie::Mash
549
+ disable_warnings
550
+ end
551
+
552
+ class Response < Message
553
+ disable_warnings :zip, :zap
554
+ end
555
+
556
+ # 2 errors will be logged
557
+ Response.new(merge: 'true', compact: true, zip: '90210', zap: 'electric')
558
+ ```
559
+
560
+ If you would like to create an anonymous subclass of a Hashie::Mash with key conflict warnings disabled:
561
+
562
+ ```ruby
563
+ Hashie::Mash.quiet.new(zip: '90210', compact: true) # no errors logged
564
+ Hashie::Mash.quiet(:zip).new(zip: '90210', compact: true) # error logged for compact
565
+ ```
566
+
518
567
  ### How does the wrapping of Mash sub-Hashes work?
519
568
 
520
569
  Mash duplicates any sub-Hashes that you add to it and wraps them in a Mash. This allows for infinite chaining of nested Hashes within a Mash without modifying the object(s) that are passed into the Mash. When you subclass Mash, the subclass wraps any sub-Hashes in its own class. This preserves any extensions that you mixed into the Mash subclass and allows them to work within the sub-Hashes, in addition to the main containing Mash.
@@ -566,7 +615,7 @@ Twitter.extend mash.to_module # NOTE: if you want another name than settings, ca
566
615
  Twitter.settings.api_key # => 'abcd'
567
616
  ```
568
617
 
569
- You can use another parser (by default: YamlErbParser):
618
+ You can use another parser (by default: [YamlErbParser](lib/hashie/extensions/parsers/yaml_erb_parser.rb)):
570
619
 
571
620
  ```
572
621
  #/etc/data/user.csv
@@ -582,6 +631,14 @@ mash = Mash.load('data/user.csv', parser: MyCustomCsvParser)
582
631
  mash[1] #=> { name: 'John', lastname: 'Doe' }
583
632
  ```
584
633
 
634
+ The `Mash#load` method calls `YAML.safe_load(path, [], [], true)`.
635
+
636
+ Specify `permitted_symbols`, `permitted_classes` and `aliases` options as needed.
637
+
638
+ ```ruby
639
+ Mash.load('data/user.csv', permitted_classes: [Symbol], permitted_symbols: [], aliases: false)
640
+ ```
641
+
585
642
  ### Mash Extension: KeepOriginalKeys
586
643
 
587
644
  This extension can be mixed into a Mash to keep the form of any keys passed directly into the Mash. By default, Mash converts keys to strings to give indifferent access. This extension still allows indifferent access, but keeps the form of the keys to eliminate confusion when you're not expecting the keys to change.
@@ -617,9 +674,9 @@ safe_mash.zip = 'Test' # => ArgumentError
617
674
  safe_mash[:zip] = 'test' # => still ArgumentError
618
675
  ```
619
676
 
620
- ### Mash Extension:: SymbolizeKeys
677
+ ### Mash Extension: SymbolizeKeys
621
678
 
622
- This extension can be mixed into a Mash to change the default behavior of converting keys to strings. After mixing this extension into a Mash, the Mash will convert all keys to symbols.
679
+ This extension can be mixed into a Mash to change the default behavior of converting keys to strings. After mixing this extension into a Mash, the Mash will convert all keys to symbols. It can be useful to use with keywords argument, which required symbol keys.
623
680
 
624
681
  ```ruby
625
682
  class SymbolizedMash < ::Hashie::Mash
@@ -630,6 +687,12 @@ symbol_mash = SymbolizedMash.new
630
687
  symbol_mash['test'] = 'value'
631
688
  symbol_mash.test #=> 'value'
632
689
  symbol_mash.to_h #=> {test: 'value'}
690
+
691
+ def example(test:)
692
+ puts test
693
+ end
694
+
695
+ example(symbol_mash) #=> value
633
696
  ```
634
697
 
635
698
  There is a major benefit and coupled with a major trade-off to this decision (at least on older Rubies). As a benefit, by using symbols as keys, you will be able to use the implicit conversion of a Mash via the `#to_hash` method to destructure (or splat) the contents of a Mash out to a block. This can be handy for doing iterations through the Mash's keys and values, as follows:
@@ -644,6 +707,31 @@ end
644
707
 
645
708
  However, on Rubies less than 2.0, this means that every key you send to the Mash will generate a symbol. Since symbols are not garbage-collected on older versions of Ruby, this can cause a slow memory leak when using a symbolized Mash with data generated from user input.
646
709
 
710
+ ### Mash Extension: DefineAccessors
711
+
712
+ This extension can be mixed into a Mash so it makes it behave like `OpenStruct`. It reduces the overhead of `method_missing?` magic by lazily defining field accessors when they're requested.
713
+
714
+ ```ruby
715
+ class MyHash < ::Hashie::Mash
716
+ include Hashie::Extensions::Mash::DefineAccessors
717
+ end
718
+
719
+ mash = MyHash.new
720
+ MyHash.method_defined?(:foo=) #=> false
721
+ mash.foo = 123
722
+ MyHash.method_defined?(:foo=) #=> true
723
+
724
+ MyHash.method_defined?(:foo) #=> false
725
+ mash.foo #=> 123
726
+ MyHash.method_defined?(:foo) #=> true
727
+ ```
728
+
729
+ You can also extend the existing mash without defining a class:
730
+
731
+ ```ruby
732
+ mash = ::Hashie::Mash.new.with_accessors!
733
+ ```
734
+
647
735
  ## Dash
648
736
 
649
737
  Dash is an extended Hash that has a discrete set of defined properties and only those properties may be set on the hash. Additionally, you can set defaults for each property. You can also flag a property as required. Required properties will raise an exception if unset. Another option is message for required properties, which allow you to add custom messages for required property.
@@ -1,6 +1,84 @@
1
1
  Upgrading Hashie
2
2
  ================
3
3
 
4
+ ### Upgrading to 4.0.0
5
+
6
+ #### Non-destructive Hash methods called on Mash
7
+
8
+ The following non-destructive Hash methods called on Mash will now return an instance of the class it was called on.
9
+
10
+ | method | ruby |
11
+ | ----------------- | ---- |
12
+ | #compact | |
13
+ | #invert | |
14
+ | #reject | |
15
+ | #select | |
16
+ | #slice | 2.5 |
17
+ | #transform_keys | 2.5 |
18
+ | #transform_values | 2.4 |
19
+
20
+ ```ruby
21
+ class Parents < Hashie::Mash; end
22
+
23
+ parents = Parents.new(father: 'Dad', mother: 'Mom')
24
+ cool_parents = parents.transform_values { |v| v + v[-1] + 'io'}
25
+
26
+ p cool_parents
27
+
28
+ # before:
29
+ {"father"=>"Daddio", "mother"=>"Mommio"}
30
+ => {"father"=>"Daddio", "mother"=>"Mommio"}
31
+
32
+ # after:
33
+ #<Parents father="Daddio" mother="Mommio">
34
+ => {"father"=>"Dad", "mother"=>"Mom"}
35
+ ```
36
+
37
+ This may make places where you had to re-make the Mash redundant, and may cause unintended side effects if your application was expecting a plain old ruby Hash.
38
+
39
+ #### Ruby 2.6: Mash#merge and Mash#merge!
40
+
41
+ In Ruby > 2.6.0, Hashie now supports passing multiple hash and Mash objects to Mash#merge and Mash#merge!.
42
+
43
+ #### Hashie::Mash::CannotDisableMashWarnings error class is removed
44
+
45
+ There shouldn't really be a case that anyone was relying on catching this specific error, but if so, they should change it to rescue Hashie::Extensions::KeyConflictWarning::CannotDisableMashWarnings
46
+
47
+ ### Upgrading to 3.7.0
48
+
49
+ #### Mash#load takes options
50
+
51
+ The `Hashie::Mash#load` method now accepts options, changing the interface of `Parser#initialize`. If you have a custom parser, you must update its `initialize` method.
52
+
53
+ For example, `Hashie::Extensions::Parsers::YamlErbParser` now accepts `permitted_classes`, `permitted_symbols` and `aliases` options.
54
+
55
+ Before:
56
+
57
+ ```ruby
58
+ class Hashie::Extensions::Parsers::YamlErbParser
59
+ def initialize(file_path)
60
+ @file_path = file_path
61
+ end
62
+ end
63
+ ```
64
+
65
+ After:
66
+
67
+ ```ruby
68
+ class Hashie::Extensions::Parsers::YamlErbParser
69
+ def initialize(file_path, options = {})
70
+ @file_path = file_path
71
+ @options = options
72
+ end
73
+ end
74
+ ```
75
+
76
+ Options can now be passed into `Mash#load`.
77
+
78
+ ```ruby
79
+ Mash.load(filename, permitted_classes: [])
80
+ ```
81
+
4
82
  ### Upgrading to 3.5.2
5
83
 
6
84
  #### Disable logging in Mash subclasses
@@ -165,5 +243,3 @@ instance.to_hash # => { :first => 'First', "last" => 'Last' }
165
243
  The behavior with `symbolize_keys` and `stringify_keys` is unchanged.
166
244
 
167
245
  See [#152](https://github.com/intridea/hashie/pull/152) for more information.
168
-
169
-
@@ -11,7 +11,8 @@ Gem::Specification.new do |gem|
11
11
  gem.license = 'MIT'
12
12
 
13
13
  gem.require_paths = ['lib']
14
- gem.files = %w[.yardopts CHANGELOG.md CONTRIBUTING.md LICENSE README.md UPGRADING.md Rakefile hashie.gemspec]
14
+ gem.files = %w[.yardopts CHANGELOG.md CONTRIBUTING.md LICENSE README.md UPGRADING.md]
15
+ gem.files += %w[Rakefile hashie.gemspec]
15
16
  gem.files += Dir['lib/**/*.rb']
16
17
  gem.files += Dir['spec/**/*.rb']
17
18
  gem.test_files = Dir['spec/**/*.rb']
@@ -12,26 +12,26 @@ module Hashie
12
12
  autoload :Utils, 'hashie/utils'
13
13
 
14
14
  module Extensions
15
- autoload :Coercion, 'hashie/extensions/coercion'
16
- autoload :DeepMerge, 'hashie/extensions/deep_merge'
17
- autoload :IgnoreUndeclared, 'hashie/extensions/ignore_undeclared'
18
- autoload :IndifferentAccess, 'hashie/extensions/indifferent_access'
19
- autoload :MergeInitializer, 'hashie/extensions/merge_initializer'
20
- autoload :MethodAccess, 'hashie/extensions/method_access'
21
- autoload :MethodQuery, 'hashie/extensions/method_access'
22
- autoload :MethodReader, 'hashie/extensions/method_access'
23
- autoload :MethodWriter, 'hashie/extensions/method_access'
24
- autoload :StringifyKeys, 'hashie/extensions/stringify_keys'
25
- autoload :SymbolizeKeys, 'hashie/extensions/symbolize_keys'
26
- autoload :DeepFetch, 'hashie/extensions/deep_fetch'
27
- autoload :DeepFind, 'hashie/extensions/deep_find'
28
- autoload :DeepLocate, 'hashie/extensions/deep_locate'
29
- autoload :PrettyInspect, 'hashie/extensions/pretty_inspect'
30
- autoload :KeyConversion, 'hashie/extensions/key_conversion'
15
+ autoload :Coercion, 'hashie/extensions/coercion'
16
+ autoload :DeepMerge, 'hashie/extensions/deep_merge'
17
+ autoload :IgnoreUndeclared, 'hashie/extensions/ignore_undeclared'
18
+ autoload :IndifferentAccess, 'hashie/extensions/indifferent_access'
19
+ autoload :MergeInitializer, 'hashie/extensions/merge_initializer'
20
+ autoload :MethodAccess, 'hashie/extensions/method_access'
21
+ autoload :MethodQuery, 'hashie/extensions/method_access'
22
+ autoload :MethodReader, 'hashie/extensions/method_access'
23
+ autoload :MethodWriter, 'hashie/extensions/method_access'
24
+ autoload :StringifyKeys, 'hashie/extensions/stringify_keys'
25
+ autoload :SymbolizeKeys, 'hashie/extensions/symbolize_keys'
26
+ autoload :DeepFetch, 'hashie/extensions/deep_fetch'
27
+ autoload :DeepFind, 'hashie/extensions/deep_find'
28
+ autoload :DeepLocate, 'hashie/extensions/deep_locate'
29
+ autoload :PrettyInspect, 'hashie/extensions/pretty_inspect'
30
+ autoload :KeyConversion, 'hashie/extensions/key_conversion'
31
31
  autoload :MethodAccessWithOverride, 'hashie/extensions/method_access'
32
- autoload :StrictKeyAccess, 'hashie/extensions/strict_key_access'
33
- autoload :RubyVersion, 'hashie/extensions/ruby_version'
34
- autoload :RubyVersionCheck, 'hashie/extensions/ruby_version_check'
32
+ autoload :StrictKeyAccess, 'hashie/extensions/strict_key_access'
33
+ autoload :RubyVersion, 'hashie/extensions/ruby_version'
34
+ autoload :RubyVersionCheck, 'hashie/extensions/ruby_version_check'
35
35
 
36
36
  module Parsers
37
37
  autoload :YamlErbParser, 'hashie/extensions/parsers/yaml_erb_parser'
@@ -47,6 +47,7 @@ module Hashie
47
47
  autoload :KeepOriginalKeys, 'hashie/extensions/mash/keep_original_keys'
48
48
  autoload :SafeAssignment, 'hashie/extensions/mash/safe_assignment'
49
49
  autoload :SymbolizeKeys, 'hashie/extensions/mash/symbolize_keys'
50
+ autoload :DefineAccessors, 'hashie/extensions/mash/define_accessors'
50
51
  end
51
52
 
52
53
  module Array
@@ -219,7 +219,8 @@ module Hashie
219
219
  end
220
220
 
221
221
  def fail_property_required_error!(property)
222
- raise ArgumentError, "The property '#{property}' #{self.class.required_properties[property][:message]}"
222
+ raise ArgumentError,
223
+ "The property '#{property}' #{self.class.required_properties[property][:message]}"
223
224
  end
224
225
 
225
226
  def fail_no_property_error!(property)
@@ -0,0 +1,14 @@
1
+ module Hashie
2
+ module Extensions
3
+ module ActiveSupport
4
+ module CoreExt
5
+ module Hash
6
+ def except(*keys)
7
+ string_keys = keys.map { |key| convert_key(key) }
8
+ super(*string_keys)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,5 +1,9 @@
1
1
  module Hashie
2
- class CoercionError < StandardError; end
2
+ class CoercionError < StandardError
3
+ def initialize(key, value, into, message)
4
+ super("Cannot coerce property #{key.inspect} from #{value.class} to #{into}: #{message}")
5
+ end
6
+ end
3
7
 
4
8
  module Extensions
5
9
  module Coercion
@@ -12,20 +16,22 @@ module Hashie
12
16
  Symbol => :to_sym
13
17
  }.freeze
14
18
 
15
- ABSTRACT_CORE_TYPES = if RubyVersion.new(RUBY_VERSION) >= RubyVersion.new('2.4.0')
16
- { Numeric => [Integer, Float, Complex, Rational] }
17
- else
18
- {
19
- Integer => [Fixnum, Bignum], # rubocop:disable Lint/UnifiedInteger
20
- Numeric => [Fixnum, Bignum, Float, Complex, Rational] # rubocop:disable Lint/UnifiedInteger
21
- }
22
- end
19
+ ABSTRACT_CORE_TYPES =
20
+ if RubyVersion.new(RUBY_VERSION) >= RubyVersion.new('2.4.0')
21
+ { Numeric => [Integer, Float, Complex, Rational] }
22
+ else
23
+ {
24
+ Integer => [Fixnum, Bignum],
25
+ Numeric => [Fixnum, Bignum, Float, Complex, Rational]
26
+ }
27
+ end
23
28
 
24
29
  def self.included(base)
25
30
  base.send :include, InstanceMethods
26
- base.extend ClassMethods # NOTE: we wanna make sure we first define set_value_with_coercion before extending
27
-
28
- base.send :alias_method, :set_value_without_coercion, :[]= unless base.method_defined?(:set_value_without_coercion)
31
+ base.extend ClassMethods
32
+ unless base.method_defined?(:set_value_without_coercion)
33
+ base.send :alias_method, :set_value_without_coercion, :[]=
34
+ end
29
35
  base.send :alias_method, :[]=, :set_value_with_coercion
30
36
  end
31
37
 
@@ -37,7 +43,7 @@ module Hashie
37
43
  begin
38
44
  value = self.class.fetch_coercion(into).call(value)
39
45
  rescue NoMethodError, TypeError => e
40
- raise CoercionError, "Cannot coerce property #{key.inspect} from #{value.class} to #{into}: #{e.message}"
46
+ raise CoercionError.new(key, value, into, e.message)
41
47
  end
42
48
  end
43
49
 
@@ -97,7 +103,8 @@ module Hashie
97
103
  #
98
104
  # @param [Class] from the type you would like coerced.
99
105
  # @param [Class] into the class into which you would like the value coerced.
100
- # @option options [Boolean] :strict (true) whether use exact source class only or include ancestors
106
+ # @option options [Boolean] :strict (true) whether use exact source class
107
+ # only or include ancestors
101
108
  #
102
109
  # @example Coerce all hashes into this special type of hash
103
110
  # class SpecialHash < Hash
@@ -159,10 +166,10 @@ module Hashie
159
166
 
160
167
  def build_coercion(type)
161
168
  if type.is_a? Enumerable
162
- if type.class <= ::Hash
169
+ if type.class == ::Hash
163
170
  type, key_type, value_type = type.class, *type.first
164
171
  build_hash_coercion(type, key_type, value_type)
165
- else # Enumerable but not Hash: Array, Set
172
+ else
166
173
  value_type = type.first
167
174
  type = type.class
168
175
  build_container_coercion(type, value_type)