hashie 3.3.1 → 3.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -3
- data/README.md +11 -10
- data/hashie.gemspec +7 -6
- data/lib/hashie.rb +1 -0
- data/lib/hashie/dash.rb +12 -6
- data/lib/hashie/extensions/coercion.rb +2 -2
- data/lib/hashie/extensions/indifferent_access.rb +4 -4
- data/lib/hashie/extensions/method_access.rb +1 -1
- data/lib/hashie/extensions/parsers/yaml_erb_parser.rb +4 -1
- data/lib/hashie/extensions/pretty_inspect.rb +1 -1
- data/lib/hashie/mash.rb +3 -3
- data/lib/hashie/version.rb +1 -1
- data/spec/hashie/dash_spec.rb +30 -1
- data/spec/hashie/extensions/autoload_spec.rb +24 -0
- data/spec/hashie/extensions/coercion_spec.rb +1 -1
- data/spec/hashie/extensions/indifferent_access_with_rails_hwia_spec.rb +20 -0
- data/spec/hashie/mash_spec.rb +16 -0
- data/spec/hashie/parsers/yaml_erb_parser_spec.rb +29 -0
- data/spec/hashie/trash_spec.rb +14 -0
- data/spec/spec_helper.rb +7 -5
- metadata +8 -11
- data/.gitignore +0 -9
- data/.rspec +0 -2
- data/.rubocop.yml +0 -34
- data/.travis.yml +0 -16
- data/Gemfile +0 -22
- data/Guardfile +0 -5
- data/RELEASING.md +0 -83
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ac95f1ad6bc1d4b34deb7193b35586f0023e9b9e
|
|
4
|
+
data.tar.gz: 3fde5748adb0c1a40db2409e6bc11b559fa9f739
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2e50bba8ebb421f26da2efdb38d7d64692d2cccfc37e8daa40c118f31e3830f0419577257e85a920f96eec3992a185fcc3da8d072f5b52efe298fa483a0dbe82
|
|
7
|
+
data.tar.gz: 60f9d4137f83832a2d68a791d6d1a73690018c5180406b9b35b118eb84387b7292e517218cc4ddd933238a98db88a55dd6540b36ca7eab5cd692678da1def0fb
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
##
|
|
2
|
-
|
|
3
|
-
*
|
|
1
|
+
## 3.3.2 (11/26/2014)
|
|
2
|
+
|
|
3
|
+
* [#233](https://github.com/intridea/hashie/pull/233): Custom error messages for required properties in Hashie::Dash subclasses - [@joss](https://github.com/joss).
|
|
4
|
+
* [#231](https://github.com/intridea/hashie/pull/231): Added support for coercion on class type that inherit from Hash - [@gregory](https://github.com/gregory).
|
|
5
|
+
* [#228](https://github.com/intridea/hashie/pull/228): Made Hashie::Extensions::Parsers::YamlErbParser pass template filename to ERB - [@jperville](https://github.com/jperville).
|
|
6
|
+
* [#224](https://github.com/intridea/hashie/pull/224): Merging Hashie::Mash now correctly only calls the block on duplicate values - [@amysutedja](https://github.com/amysutedja).
|
|
7
|
+
* [#221](https://github.com/intridea/hashie/pull/221): Reduce amount of allocated objects on calls with suffixes in Hashie::Mash - [@kubum](https://github.com/kubum).
|
|
8
|
+
* [#245](https://github.com/intridea/hashie/pull/245): Added Hashie::Extensions::MethodAccessWithOverride to autoloads - [@Fritzinger](https://github.com/Fritzinger).
|
|
4
9
|
|
|
5
10
|
## 3.3.1 (8/26/2014)
|
|
6
11
|
|
data/README.md
CHANGED
|
@@ -223,11 +223,8 @@ class MyHash < Hash
|
|
|
223
223
|
include Hashie::Extensions::DeepMerge
|
|
224
224
|
end
|
|
225
225
|
|
|
226
|
-
h1 = MyHash
|
|
227
|
-
h2 = MyHash
|
|
228
|
-
|
|
229
|
-
h1 = { x: { y: [4,5,6] }, z: [7,8,9] }
|
|
230
|
-
h2 = { x: { y: [7,8,9] }, z: "xyz" }
|
|
226
|
+
h1 = MyHash[{ x: { y: [4,5,6] }, z: [7,8,9] }]
|
|
227
|
+
h2 = MyHash[{ x: { y: [7,8,9] }, z: "xyz" }]
|
|
231
228
|
|
|
232
229
|
h1.deep_merge(h2) # => { x: { y: [7, 8, 9] }, z: "xyz" }
|
|
233
230
|
h2.deep_merge(h1) # => { x: { y: [4, 5, 6] }, z: [7, 8, 9] }
|
|
@@ -254,7 +251,7 @@ user.deep_fetch :name, :first # => 'Bob'
|
|
|
254
251
|
user.deep_fetch :name, :middle # => 'KeyError: Could not fetch middle'
|
|
255
252
|
|
|
256
253
|
# using a default block
|
|
257
|
-
user.deep_fetch
|
|
254
|
+
user.deep_fetch(:name, :middle) { |key| 'default' } # => 'default'
|
|
258
255
|
|
|
259
256
|
# a nested array
|
|
260
257
|
user.deep_fetch :groups, 1, :name # => 'Open source enthusiasts'
|
|
@@ -385,22 +382,26 @@ safe_mash.zip = 'Test' # => ArgumentError
|
|
|
385
382
|
|
|
386
383
|
## Dash
|
|
387
384
|
|
|
388
|
-
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.
|
|
385
|
+
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.
|
|
389
386
|
|
|
390
387
|
### Example:
|
|
391
388
|
|
|
392
389
|
```ruby
|
|
393
390
|
class Person < Hashie::Dash
|
|
394
391
|
property :name, required: true
|
|
392
|
+
property :age, required: true, message: 'must be set.'
|
|
395
393
|
property :email
|
|
396
394
|
property :occupation, default: 'Rubyist'
|
|
397
395
|
end
|
|
398
396
|
|
|
399
397
|
p = Person.new # => ArgumentError: The property 'name' is required for this Dash.
|
|
398
|
+
p = Person.new(name: 'Bob') # => ArgumentError: The property 'age' must be set.
|
|
400
399
|
|
|
401
|
-
p = Person.new(name: "Bob")
|
|
402
|
-
p.name
|
|
403
|
-
p.name = nil
|
|
400
|
+
p = Person.new(name: "Bob", age: 18)
|
|
401
|
+
p.name # => 'Bob'
|
|
402
|
+
p.name = nil # => ArgumentError: The property 'name' is required for this Dash.
|
|
403
|
+
p.age # => 18
|
|
404
|
+
p.age = nil # => ArgumentError: The property 'age' must be set.
|
|
404
405
|
p.email = 'abc@def.com'
|
|
405
406
|
p.occupation # => 'Rubyist'
|
|
406
407
|
p.email # => 'abc@def.com'
|
data/hashie.gemspec
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
require File.expand_path('../lib/hashie/version', __FILE__)
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |gem|
|
|
4
|
+
gem.name = 'hashie'
|
|
5
|
+
gem.version = Hashie::VERSION
|
|
4
6
|
gem.authors = ['Michael Bleigh', 'Jerry Cheung']
|
|
5
7
|
gem.email = ['michael@intridea.com', 'jollyjerry@gmail.com']
|
|
6
8
|
gem.description = 'Hashie is a collection of classes and mixins that make hashes more powerful.'
|
|
7
9
|
gem.summary = 'Your friendly neighborhood hash library.'
|
|
8
10
|
gem.homepage = 'https://github.com/intridea/hashie'
|
|
11
|
+
gem.license = 'MIT'
|
|
9
12
|
|
|
10
|
-
gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
|
11
|
-
gem.files = `git ls-files`.split("\n")
|
|
12
|
-
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
13
|
-
gem.name = 'hashie'
|
|
14
13
|
gem.require_paths = ['lib']
|
|
15
|
-
gem.
|
|
16
|
-
gem.
|
|
14
|
+
gem.files = %w(.yardopts CHANGELOG.md CONTRIBUTING.md LICENSE README.md UPGRADING.md Rakefile hashie.gemspec)
|
|
15
|
+
gem.files += Dir['lib/**/*.rb']
|
|
16
|
+
gem.files += Dir['spec/**/*.rb']
|
|
17
|
+
gem.test_files = Dir['spec/**/*.rb']
|
|
17
18
|
|
|
18
19
|
gem.add_development_dependency 'rake'
|
|
19
20
|
gem.add_development_dependency 'rspec', '~> 3.0'
|
data/lib/hashie.rb
CHANGED
|
@@ -24,6 +24,7 @@ module Hashie
|
|
|
24
24
|
autoload :DeepFind, 'hashie/extensions/deep_find'
|
|
25
25
|
autoload :PrettyInspect, 'hashie/extensions/pretty_inspect'
|
|
26
26
|
autoload :KeyConversion, 'hashie/extensions/key_conversion'
|
|
27
|
+
autoload :MethodAccessWithOverride, 'hashie/extensions/method_access'
|
|
27
28
|
|
|
28
29
|
module Parsers
|
|
29
30
|
autoload :YamlErbParser, 'hashie/extensions/parsers/yaml_erb_parser'
|
data/lib/hashie/dash.rb
CHANGED
|
@@ -27,6 +27,7 @@ module Hashie
|
|
|
27
27
|
# * <tt>:required</tt> - Specify the value as required for this
|
|
28
28
|
# property, to raise an error if a value is unset in a new or
|
|
29
29
|
# existing Dash.
|
|
30
|
+
# * <tt>:message</tt> - Specify custom error message for required property
|
|
30
31
|
#
|
|
31
32
|
def self.property(property_name, options = {})
|
|
32
33
|
properties << property_name
|
|
@@ -37,7 +38,7 @@ module Hashie
|
|
|
37
38
|
defaults.delete property_name
|
|
38
39
|
end
|
|
39
40
|
|
|
40
|
-
unless instance_methods.map
|
|
41
|
+
unless instance_methods.map(&:to_s).include?("#{property_name}=")
|
|
41
42
|
define_method(property_name) { |&block| self.[](property_name, &block) }
|
|
42
43
|
property_assignment = property_name.to_s.concat('=').to_sym
|
|
43
44
|
define_method(property_assignment) { |value| self.[]=(property_name, value) }
|
|
@@ -46,7 +47,12 @@ module Hashie
|
|
|
46
47
|
if defined? @subclasses
|
|
47
48
|
@subclasses.each { |klass| klass.property(property_name, options) }
|
|
48
49
|
end
|
|
49
|
-
|
|
50
|
+
|
|
51
|
+
if options.delete(:required)
|
|
52
|
+
required_properties[property_name] = options.delete(:message) || "is required for #{name}."
|
|
53
|
+
else
|
|
54
|
+
fail ArgumentError, 'The :message option should be used with :required option.' if options.key?(:message)
|
|
55
|
+
end
|
|
50
56
|
end
|
|
51
57
|
|
|
52
58
|
class << self
|
|
@@ -55,7 +61,7 @@ module Hashie
|
|
|
55
61
|
end
|
|
56
62
|
instance_variable_set('@properties', Set.new)
|
|
57
63
|
instance_variable_set('@defaults', {})
|
|
58
|
-
instance_variable_set('@required_properties',
|
|
64
|
+
instance_variable_set('@required_properties', {})
|
|
59
65
|
|
|
60
66
|
def self.inherited(klass)
|
|
61
67
|
super
|
|
@@ -74,7 +80,7 @@ module Hashie
|
|
|
74
80
|
# Check to see if the specified property is
|
|
75
81
|
# required.
|
|
76
82
|
def self.required?(name)
|
|
77
|
-
required_properties.
|
|
83
|
+
required_properties.key? name
|
|
78
84
|
end
|
|
79
85
|
|
|
80
86
|
# You may initialize a Dash with an attributes hash
|
|
@@ -168,7 +174,7 @@ module Hashie
|
|
|
168
174
|
end
|
|
169
175
|
|
|
170
176
|
def assert_required_attributes_set!
|
|
171
|
-
self.class.required_properties.
|
|
177
|
+
self.class.required_properties.each_key do |required_property|
|
|
172
178
|
assert_property_set!(required_property)
|
|
173
179
|
end
|
|
174
180
|
end
|
|
@@ -182,7 +188,7 @@ module Hashie
|
|
|
182
188
|
end
|
|
183
189
|
|
|
184
190
|
def fail_property_required_error!(property)
|
|
185
|
-
fail ArgumentError, "The property '#{property}'
|
|
191
|
+
fail ArgumentError, "The property '#{property}' #{self.class.required_properties[property]}"
|
|
186
192
|
end
|
|
187
193
|
|
|
188
194
|
def fail_no_property_error!(property)
|
|
@@ -34,10 +34,10 @@ module Hashie
|
|
|
34
34
|
begin
|
|
35
35
|
return set_value_without_coercion(key, coerce_or_init(into).call(value)) unless into.is_a?(Enumerable)
|
|
36
36
|
|
|
37
|
-
if into.class
|
|
37
|
+
if into.class <= ::Hash
|
|
38
38
|
key_coerce = coerce_or_init(into.flatten[0])
|
|
39
39
|
value_coerce = coerce_or_init(into.flatten[-1])
|
|
40
|
-
value =
|
|
40
|
+
value = into.class[value.map { |k, v| [key_coerce.call(k), value_coerce.call(v)] }]
|
|
41
41
|
else # Enumerable but not Hash: Array, Set
|
|
42
42
|
value_coerce = coerce_or_init(into.first)
|
|
43
43
|
value = into.class.new(value.map { |v| value_coerce.call(v) })
|
|
@@ -137,14 +137,14 @@ module Hashie
|
|
|
137
137
|
|
|
138
138
|
def hash_lacking_indifference?(other)
|
|
139
139
|
other.is_a?(::Hash) &&
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
!(other.respond_to?(:indifferent_access?) &&
|
|
141
|
+
other.indifferent_access?)
|
|
142
142
|
end
|
|
143
143
|
|
|
144
144
|
def hash_with_indifference?(other)
|
|
145
145
|
other.is_a?(::Hash) &&
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
other.respond_to?(:indifferent_access?) &&
|
|
147
|
+
other.indifferent_access?
|
|
148
148
|
end
|
|
149
149
|
end
|
|
150
150
|
end
|
|
@@ -6,10 +6,13 @@ module Hashie
|
|
|
6
6
|
class YamlErbParser
|
|
7
7
|
def initialize(file_path)
|
|
8
8
|
@content = File.read(file_path)
|
|
9
|
+
@file_path = file_path
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
def perform
|
|
12
|
-
|
|
13
|
+
template = ERB.new(@content)
|
|
14
|
+
template.filename = @file_path
|
|
15
|
+
YAML.load template.result
|
|
13
16
|
end
|
|
14
17
|
|
|
15
18
|
def self.perform(file_path)
|
data/lib/hashie/mash.rb
CHANGED
|
@@ -58,6 +58,7 @@ module Hashie
|
|
|
58
58
|
include Hashie::Extensions::PrettyInspect
|
|
59
59
|
|
|
60
60
|
ALLOWED_SUFFIXES = %w(? ! = _)
|
|
61
|
+
SUFFIXES_PARSER = /(.*?)([#{ALLOWED_SUFFIXES.join}]?)$/
|
|
61
62
|
|
|
62
63
|
def self.load(path, options = {})
|
|
63
64
|
@_mashes ||= new do |h, file_path|
|
|
@@ -180,7 +181,7 @@ module Hashie
|
|
|
180
181
|
custom_reader(key).deep_update(v, &blk)
|
|
181
182
|
else
|
|
182
183
|
value = convert_value(v, true)
|
|
183
|
-
value = convert_value(blk.call(key, self[k], value), true) if blk
|
|
184
|
+
value = convert_value(blk.call(key, self[k], value), true) if blk && self.key?(k)
|
|
184
185
|
custom_writer(key, value, false)
|
|
185
186
|
end
|
|
186
187
|
end
|
|
@@ -251,8 +252,7 @@ module Hashie
|
|
|
251
252
|
protected
|
|
252
253
|
|
|
253
254
|
def method_suffix(method_name)
|
|
254
|
-
|
|
255
|
-
match = method_name.to_s.match(/(.*?)([#{suffixes_regex}]?)$/)
|
|
255
|
+
match = method_name.to_s.match(SUFFIXES_PARSER)
|
|
256
256
|
[match[1], match[2]]
|
|
257
257
|
end
|
|
258
258
|
|
data/lib/hashie/version.rb
CHANGED
data/spec/hashie/dash_spec.rb
CHANGED
|
@@ -34,6 +34,10 @@ class SubclassedTest < DashTest
|
|
|
34
34
|
property :last_name, required: true
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
class RequiredMessageTest < DashTest
|
|
38
|
+
property :first_name, required: true, message: 'must be set.'
|
|
39
|
+
end
|
|
40
|
+
|
|
37
41
|
class DashDefaultTest < Hashie::Dash
|
|
38
42
|
property :aliases, default: ['Snake']
|
|
39
43
|
end
|
|
@@ -47,11 +51,20 @@ describe DashTest do
|
|
|
47
51
|
[ArgumentError, "The property '#{property}' is required for #{subject.class.name}."]
|
|
48
52
|
end
|
|
49
53
|
|
|
54
|
+
def property_required_custom_error(property)
|
|
55
|
+
[ArgumentError, "The property '#{property}' must be set."]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def property_message_without_required_error
|
|
59
|
+
[ArgumentError, 'The :message option should be used with :required option.']
|
|
60
|
+
end
|
|
61
|
+
|
|
50
62
|
def no_property_error(property)
|
|
51
63
|
[NoMethodError, "The property '#{property}' is not defined for #{subject.class.name}."]
|
|
52
64
|
end
|
|
53
65
|
|
|
54
66
|
subject { DashTest.new(first_name: 'Bob', email: 'bob@example.com') }
|
|
67
|
+
let(:required_message) { RequiredMessageTest.new(first_name: 'Bob') }
|
|
55
68
|
|
|
56
69
|
it('subclasses Hashie::Hash') { should respond_to(:to_mash) }
|
|
57
70
|
|
|
@@ -83,13 +96,29 @@ describe DashTest do
|
|
|
83
96
|
expect { subject.first_name = nil }.to raise_error(*property_required_error('first_name'))
|
|
84
97
|
end
|
|
85
98
|
|
|
99
|
+
it 'errors out when message added to not required property' do
|
|
100
|
+
expect do
|
|
101
|
+
class DashMessageOptionWithoutRequiredTest < Hashie::Dash
|
|
102
|
+
property :first_name, message: 'is required.'
|
|
103
|
+
end
|
|
104
|
+
end.to raise_error(*property_message_without_required_error)
|
|
105
|
+
|
|
106
|
+
expect do
|
|
107
|
+
class DashMessageOptionWithoutRequiredTest < Hashie::Dash
|
|
108
|
+
property :first_name, required: false, message: 'is required.'
|
|
109
|
+
end
|
|
110
|
+
end.to raise_error(*property_message_without_required_error)
|
|
111
|
+
end
|
|
112
|
+
|
|
86
113
|
context 'writing to properties' do
|
|
87
114
|
it 'fails writing a required property to nil' do
|
|
88
115
|
expect { subject.first_name = nil }.to raise_error(*property_required_error('first_name'))
|
|
116
|
+
expect { required_message.first_name = nil }.to raise_error(*property_required_custom_error('first_name'))
|
|
89
117
|
end
|
|
90
118
|
|
|
91
119
|
it 'fails writing a required property to nil using []=' do
|
|
92
120
|
expect { subject[:first_name] = nil }.to raise_error(*property_required_error('first_name'))
|
|
121
|
+
expect { required_message[:first_name] = nil }.to raise_error(*property_required_custom_error('first_name'))
|
|
93
122
|
end
|
|
94
123
|
|
|
95
124
|
it 'fails writing to a non-existent property using []=' do
|
|
@@ -269,7 +298,7 @@ describe DashTest do
|
|
|
269
298
|
end
|
|
270
299
|
|
|
271
300
|
it 'leaves only specified keys and keys with default values' do
|
|
272
|
-
expect(subject.keys.sort_by
|
|
301
|
+
expect(subject.keys.sort_by(&:to_s)).to eq [:count, :first_name]
|
|
273
302
|
expect(subject.email).to be_nil
|
|
274
303
|
expect(subject.count).to eq 0
|
|
275
304
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'hashie'
|
|
3
|
+
|
|
4
|
+
describe Hashie::Extensions do
|
|
5
|
+
describe 'autloads constants' do
|
|
6
|
+
it { is_expected.to be_const_defined(:MethodAccess) }
|
|
7
|
+
it { is_expected.to be_const_defined(:Coercion) }
|
|
8
|
+
it { is_expected.to be_const_defined(:DeepMerge) }
|
|
9
|
+
it { is_expected.to be_const_defined(:IgnoreUndeclared) }
|
|
10
|
+
it { is_expected.to be_const_defined(:IndifferentAccess) }
|
|
11
|
+
it { is_expected.to be_const_defined(:MergeInitializer) }
|
|
12
|
+
it { is_expected.to be_const_defined(:MethodAccess) }
|
|
13
|
+
it { is_expected.to be_const_defined(:MethodQuery) }
|
|
14
|
+
it { is_expected.to be_const_defined(:MethodReader) }
|
|
15
|
+
it { is_expected.to be_const_defined(:MethodWriter) }
|
|
16
|
+
it { is_expected.to be_const_defined(:StringifyKeys) }
|
|
17
|
+
it { is_expected.to be_const_defined(:SymbolizeKeys) }
|
|
18
|
+
it { is_expected.to be_const_defined(:DeepFetch) }
|
|
19
|
+
it { is_expected.to be_const_defined(:DeepFind) }
|
|
20
|
+
it { is_expected.to be_const_defined(:PrettyInspect) }
|
|
21
|
+
it { is_expected.to be_const_defined(:KeyConversion) }
|
|
22
|
+
it { is_expected.to be_const_defined(:MethodAccessWithOverride) }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -160,7 +160,7 @@ describe Hashie::Extensions::Coercion do
|
|
|
160
160
|
|
|
161
161
|
instance[:foo] = %w('bar', 'bar2')
|
|
162
162
|
expect(instance[:foo].map(&:value)).to all(eq 'String')
|
|
163
|
-
expect(instance[:foo]).to be_none
|
|
163
|
+
expect(instance[:foo]).to be_none(&:coerced?)
|
|
164
164
|
expect(instance[:foo]).to be_a(Set)
|
|
165
165
|
end
|
|
166
166
|
|
|
@@ -30,6 +30,11 @@ describe Hashie::Extensions::IndifferentAccess do
|
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
class CoercableHash < Hash
|
|
34
|
+
include Hashie::Extensions::Coercion
|
|
35
|
+
include Hashie::Extensions::MergeInitializer
|
|
36
|
+
end
|
|
37
|
+
|
|
33
38
|
shared_examples_for 'hash with indifferent access' do
|
|
34
39
|
it 'is able to access via string or symbol' do
|
|
35
40
|
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(abc: 123)
|
|
@@ -174,4 +179,19 @@ describe Hashie::Extensions::IndifferentAccess do
|
|
|
174
179
|
subject { IndifferentHashWithTryConvertInitializer }
|
|
175
180
|
it_should_behave_like 'hash with indifferent access'
|
|
176
181
|
end
|
|
182
|
+
|
|
183
|
+
describe 'with coercion' do
|
|
184
|
+
subject { CoercableHash }
|
|
185
|
+
|
|
186
|
+
let(:instance) { subject.new }
|
|
187
|
+
|
|
188
|
+
it 'supports coercion for ActiveSupport::HashWithIndifferentAccess' do
|
|
189
|
+
subject.coerce_key :foo, ActiveSupport::HashWithIndifferentAccess.new(Coercable => Coercable)
|
|
190
|
+
instance[:foo] = { 'bar_key' => 'bar_value', 'bar2_key' => 'bar2_value' }
|
|
191
|
+
expect(instance[:foo].keys).to all(be_coerced)
|
|
192
|
+
expect(instance[:foo].values).to all(be_coerced)
|
|
193
|
+
expect(instance[:foo]).to be_a(ActiveSupport::HashWithIndifferentAccess)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
end
|
|
177
197
|
end
|
data/spec/hashie/mash_spec.rb
CHANGED
|
@@ -71,6 +71,16 @@ describe Hashie::Mash do
|
|
|
71
71
|
expect(subject.abc('foobar')).to eq 123
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
# Added due to downstream gems assuming indifferent access to be true for Mash
|
|
75
|
+
# When this is not, bump major version so that downstream gems can target
|
|
76
|
+
# correct version and fix accordingly.
|
|
77
|
+
# See https://github.com/intridea/hashie/pull/197
|
|
78
|
+
it 'maintains indifferent access when nested' do
|
|
79
|
+
subject[:a] = { b: 'c' }
|
|
80
|
+
expect(subject[:a][:b]).to eq 'c'
|
|
81
|
+
expect(subject[:a]['b']).to eq 'c'
|
|
82
|
+
end
|
|
83
|
+
|
|
74
84
|
it 'returns a Hashie::Mash when passed a bang method to a non-existenct key' do
|
|
75
85
|
expect(subject.abc!.is_a?(Hashie::Mash)).to be_truthy
|
|
76
86
|
end
|
|
@@ -179,6 +189,12 @@ describe Hashie::Mash do
|
|
|
179
189
|
duped = subject.merge(details: { address: 'Pasadena CA' }) { |_, oldv, newv| [oldv, newv].join(', ') }
|
|
180
190
|
expect(duped.details.address).to eq 'Nowhere road, Pasadena CA'
|
|
181
191
|
end
|
|
192
|
+
|
|
193
|
+
it 'copies values for non-duplicate keys when a block is supplied' do
|
|
194
|
+
duped = subject.merge(details: { address: 'Pasadena CA', state: 'West Thoughtleby' }) { |_, oldv, _| oldv }
|
|
195
|
+
expect(duped.details.address).to eq 'Nowhere road'
|
|
196
|
+
expect(duped.details.state).to eq 'West Thoughtleby'
|
|
197
|
+
end
|
|
182
198
|
end
|
|
183
199
|
|
|
184
200
|
describe 'shallow update' do
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Hashie::Extensions::Parsers::YamlErbParser do
|
|
4
|
+
describe '.perform' do
|
|
5
|
+
let(:config) do
|
|
6
|
+
<<-EOF
|
|
7
|
+
---
|
|
8
|
+
foo: verbatim
|
|
9
|
+
bar: <%= "erb" %>
|
|
10
|
+
baz: "<%= __FILE__ %>"
|
|
11
|
+
EOF
|
|
12
|
+
end
|
|
13
|
+
let(:path) { 'template.yml' }
|
|
14
|
+
|
|
15
|
+
subject { described_class.new(path).perform }
|
|
16
|
+
|
|
17
|
+
before do
|
|
18
|
+
expect(File).to receive(:read).with(path).and_return(config)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it { is_expected.to be_a(Hash) }
|
|
22
|
+
|
|
23
|
+
it 'parses YAML after interpolating ERB' do
|
|
24
|
+
expect(subject['foo']).to eq 'verbatim'
|
|
25
|
+
expect(subject['bar']).to eq 'erb'
|
|
26
|
+
expect(subject['baz']).to eq path
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/spec/hashie/trash_spec.rb
CHANGED
|
@@ -252,4 +252,18 @@ describe Hashie::Trash do
|
|
|
252
252
|
end
|
|
253
253
|
end.to raise_error(ArgumentError)
|
|
254
254
|
end
|
|
255
|
+
|
|
256
|
+
context 'when subclassing' do
|
|
257
|
+
class Person < Hashie::Trash
|
|
258
|
+
property :first_name, from: :firstName
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
class Hobbit < Person; end
|
|
262
|
+
|
|
263
|
+
subject { Hobbit.new(firstName: 'Frodo') }
|
|
264
|
+
|
|
265
|
+
it 'keeps translation definitions in subclasses' do
|
|
266
|
+
expect(subject.first_name).to eq('Frodo')
|
|
267
|
+
end
|
|
268
|
+
end
|
|
255
269
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
require 'rubygems'
|
|
2
1
|
require 'pry'
|
|
3
2
|
|
|
4
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
5
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
6
|
-
|
|
7
|
-
require 'hashie'
|
|
8
3
|
require 'rspec'
|
|
4
|
+
require 'hashie'
|
|
5
|
+
|
|
6
|
+
RSpec.configure do |config|
|
|
7
|
+
config.expect_with :rspec do |expect|
|
|
8
|
+
expect.syntax = :expect
|
|
9
|
+
end
|
|
10
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hashie
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.3.
|
|
4
|
+
version: 3.3.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michael Bleigh
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2014-
|
|
12
|
+
date: 2014-11-26 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: rake
|
|
@@ -47,22 +47,14 @@ executables: []
|
|
|
47
47
|
extensions: []
|
|
48
48
|
extra_rdoc_files: []
|
|
49
49
|
files:
|
|
50
|
-
- .gitignore
|
|
51
|
-
- .rspec
|
|
52
|
-
- .rubocop.yml
|
|
53
|
-
- .travis.yml
|
|
54
50
|
- .yardopts
|
|
55
51
|
- CHANGELOG.md
|
|
56
52
|
- CONTRIBUTING.md
|
|
57
|
-
- Gemfile
|
|
58
|
-
- Guardfile
|
|
59
53
|
- LICENSE
|
|
60
54
|
- README.md
|
|
61
|
-
- RELEASING.md
|
|
62
|
-
- Rakefile
|
|
63
55
|
- UPGRADING.md
|
|
56
|
+
- Rakefile
|
|
64
57
|
- hashie.gemspec
|
|
65
|
-
- lib/hashie.rb
|
|
66
58
|
- lib/hashie/clash.rb
|
|
67
59
|
- lib/hashie/dash.rb
|
|
68
60
|
- lib/hashie/extensions/coercion.rb
|
|
@@ -85,8 +77,10 @@ files:
|
|
|
85
77
|
- lib/hashie/rash.rb
|
|
86
78
|
- lib/hashie/trash.rb
|
|
87
79
|
- lib/hashie/version.rb
|
|
80
|
+
- lib/hashie.rb
|
|
88
81
|
- spec/hashie/clash_spec.rb
|
|
89
82
|
- spec/hashie/dash_spec.rb
|
|
83
|
+
- spec/hashie/extensions/autoload_spec.rb
|
|
90
84
|
- spec/hashie/extensions/coercion_spec.rb
|
|
91
85
|
- spec/hashie/extensions/dash/indifferent_access_spec.rb
|
|
92
86
|
- spec/hashie/extensions/deep_fetch_spec.rb
|
|
@@ -101,6 +95,7 @@ files:
|
|
|
101
95
|
- spec/hashie/extensions/method_access_spec.rb
|
|
102
96
|
- spec/hashie/hash_spec.rb
|
|
103
97
|
- spec/hashie/mash_spec.rb
|
|
98
|
+
- spec/hashie/parsers/yaml_erb_parser_spec.rb
|
|
104
99
|
- spec/hashie/rash_spec.rb
|
|
105
100
|
- spec/hashie/trash_spec.rb
|
|
106
101
|
- spec/hashie/version_spec.rb
|
|
@@ -132,6 +127,7 @@ summary: Your friendly neighborhood hash library.
|
|
|
132
127
|
test_files:
|
|
133
128
|
- spec/hashie/clash_spec.rb
|
|
134
129
|
- spec/hashie/dash_spec.rb
|
|
130
|
+
- spec/hashie/extensions/autoload_spec.rb
|
|
135
131
|
- spec/hashie/extensions/coercion_spec.rb
|
|
136
132
|
- spec/hashie/extensions/dash/indifferent_access_spec.rb
|
|
137
133
|
- spec/hashie/extensions/deep_fetch_spec.rb
|
|
@@ -146,6 +142,7 @@ test_files:
|
|
|
146
142
|
- spec/hashie/extensions/method_access_spec.rb
|
|
147
143
|
- spec/hashie/hash_spec.rb
|
|
148
144
|
- spec/hashie/mash_spec.rb
|
|
145
|
+
- spec/hashie/parsers/yaml_erb_parser_spec.rb
|
|
149
146
|
- spec/hashie/rash_spec.rb
|
|
150
147
|
- spec/hashie/trash_spec.rb
|
|
151
148
|
- spec/hashie/version_spec.rb
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/.rubocop.yml
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
AllCops:
|
|
2
|
-
Exclude:
|
|
3
|
-
- .bundle/**
|
|
4
|
-
- bin/**
|
|
5
|
-
- vendor/**
|
|
6
|
-
|
|
7
|
-
Style/CaseEquality:
|
|
8
|
-
Enabled: false
|
|
9
|
-
|
|
10
|
-
Style/Documentation:
|
|
11
|
-
# don't require classes to be documented
|
|
12
|
-
Enabled: false
|
|
13
|
-
|
|
14
|
-
Style/DoubleNegation:
|
|
15
|
-
Enabled: false
|
|
16
|
-
|
|
17
|
-
Style/Encoding:
|
|
18
|
-
# no need to always specify encoding
|
|
19
|
-
Enabled: false
|
|
20
|
-
|
|
21
|
-
Metrics/ClassLength:
|
|
22
|
-
Enabled: false
|
|
23
|
-
|
|
24
|
-
Metrics/CyclomaticComplexity:
|
|
25
|
-
Enabled: false
|
|
26
|
-
|
|
27
|
-
Metrics/LineLength:
|
|
28
|
-
Enabled: false
|
|
29
|
-
|
|
30
|
-
Metrics/MethodLength:
|
|
31
|
-
Enabled: false
|
|
32
|
-
|
|
33
|
-
Metrics/PerceivedComplexity:
|
|
34
|
-
Max: 10
|
data/.travis.yml
DELETED
data/Gemfile
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
source 'http://rubygems.org'
|
|
2
|
-
|
|
3
|
-
platforms :rbx do
|
|
4
|
-
gem 'rubysl'
|
|
5
|
-
gem 'rubinius-developer_tools'
|
|
6
|
-
gem 'racc'
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
group :development do
|
|
10
|
-
gem 'pry'
|
|
11
|
-
gem 'pry-stack_explorer', platforms: [:ruby_19, :ruby_20, :ruby_21]
|
|
12
|
-
gem 'rubocop', '~> 0.25'
|
|
13
|
-
gem 'guard', '~> 2.6.1'
|
|
14
|
-
gem 'guard-rspec', '~> 4.3.1', require: false
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
gemspec
|
|
18
|
-
|
|
19
|
-
group :test do
|
|
20
|
-
# ActiveSupport required to test compatibility with ActiveSupport Core Extensions.
|
|
21
|
-
gem 'activesupport', require: false
|
|
22
|
-
end
|
data/Guardfile
DELETED
data/RELEASING.md
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
# Releasing Hashie
|
|
2
|
-
|
|
3
|
-
There're no particular rules about when to release Hashie. Release bug fixes frequenty, features not so frequently and breaking API changes rarely.
|
|
4
|
-
|
|
5
|
-
### Release
|
|
6
|
-
|
|
7
|
-
Run tests, check that all tests succeed locally.
|
|
8
|
-
|
|
9
|
-
```sh
|
|
10
|
-
bundle install
|
|
11
|
-
bundle exec rake
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
Check that the last build succeeded in [Travis CI](https://travis-ci.org/intridea/hashie) for all supported platforms.
|
|
15
|
-
|
|
16
|
-
Increment the version, modify [lib/hashie/version.rb](lib/hashie/version.rb).
|
|
17
|
-
|
|
18
|
-
* Increment the third number (minor version) if the release has bug fixes and/or very minor features, only (eg. change `0.5.1` to `0.5.2`).
|
|
19
|
-
* Increment the second number (patch version) if the release contains major features or breaking API changes (eg. change `0.5.1` to `0.6.0`).
|
|
20
|
-
|
|
21
|
-
Modify the "Stable Release" section in [README.md](README.md). Change the text to reflect that this is going to be the documentation for a stable release. Remove references to the previous release of Hashie. Keep the file open, you'll have to undo this change after the release.
|
|
22
|
-
|
|
23
|
-
```markdown
|
|
24
|
-
## Stable Release
|
|
25
|
-
|
|
26
|
-
You're reading the documentation for the stable release of Hashie, 3.3.0.
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
Change "Next Release" in [CHANGELOG.md](CHANGELOG.md) to the new version.
|
|
30
|
-
|
|
31
|
-
```markdown
|
|
32
|
-
3.3.0 (8/25/2014)
|
|
33
|
-
=================
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Remove the line with "Your contribution here.", since there will be no more contributions to this release.
|
|
37
|
-
|
|
38
|
-
Commit your changes.
|
|
39
|
-
|
|
40
|
-
```sh
|
|
41
|
-
git add README.md CHANGELOG.md lib/hashie/version.rb
|
|
42
|
-
git commit -m "Preparing for release, 3.3.0."
|
|
43
|
-
git push origin master
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Release.
|
|
47
|
-
|
|
48
|
-
```sh
|
|
49
|
-
$ rake release
|
|
50
|
-
|
|
51
|
-
hashie 3.3.0 built to pkg/hashie-3.3.0.gem.
|
|
52
|
-
Tagged v3.3.0.
|
|
53
|
-
Pushed git commits and tags.
|
|
54
|
-
Pushed hashie 3.3.0 to rubygems.org.
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Prepare for the Next Version
|
|
58
|
-
|
|
59
|
-
Modify the "Stable Release" section in [README.md](README.md). Change the text to reflect that this is going to be the next release.
|
|
60
|
-
|
|
61
|
-
```markdown
|
|
62
|
-
## Stable Release
|
|
63
|
-
|
|
64
|
-
You're reading the documentation for the next release of Hashie, which should be 3.3.1.
|
|
65
|
-
The current stable release is [3.3.0](https://github.com/intridea/hashie/blob/v3.3.0/README.md).
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Add the next release to [CHANGELOG.md](CHANGELOG.md).
|
|
69
|
-
|
|
70
|
-
```markdown
|
|
71
|
-
Next Release
|
|
72
|
-
============
|
|
73
|
-
|
|
74
|
-
* Your contribution here.
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Commit your changes.
|
|
78
|
-
|
|
79
|
-
```sh
|
|
80
|
-
git add CHANGELOG.md README.md
|
|
81
|
-
git commit -m "Preparing for next release."
|
|
82
|
-
git push origin master
|
|
83
|
-
```
|