collapsium 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 380030070f1838be3f5a7955fcd6e146398653f7
4
- data.tar.gz: 18862980c22abb357b61c26d867a21d397c4faef
3
+ metadata.gz: 39373bf60c53fa0099f0f3066725d0de62448e37
4
+ data.tar.gz: 460a9f149f29cd83210c72e5abd2715046329499
5
5
  SHA512:
6
- metadata.gz: c5be77bf133c4042d193a4f10c4dafbbc2805da3dc4497b29e11802d33a4b34726a2af79642d9f6423f9de14746a46d2a3acc7ff655d1e14d1ba11ca68ba3055
7
- data.tar.gz: 55fa9036b582b1cb8f708c1d384e006b2bf822253ed213eff8204fbeae2e4a159b578ac6a1330ac380ab75b875f637e8cf4385ed8c57760ce0888e3e10d8d29c
6
+ metadata.gz: a1cf946152d25f4eadd5db380fc7907188b0152061b6d0be39e4676442ef272c8fb1efbfce2eba421be5e869466c09fced926dec919592d1cfc3d88228604acf
7
+ data.tar.gz: 39b05aa8b8d64e4608a56f241f7e97ade7a2379eb8867a315cd4480c2360d61cf4c51f90f2b5a67e421be6add9dacef01b96d3ef1c8d8d16c6d2485d4b1e570f
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- collapsium (0.1.0)
4
+ collapsium (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -0,0 +1,70 @@
1
+ # coding: utf-8
2
+ #
3
+ # collapsium
4
+ # https://github.com/jfinkhaeuser/collapsium
5
+ #
6
+ # Copyright (c) 2016 Jens Finkhaeuser and other collapsium contributors.
7
+ # All rights reserved.
8
+ #
9
+
10
+ module Collapsium
11
+ ##
12
+ # Provides prototype matching for Hashes. See #prototype_match
13
+ module PrototypeMatch
14
+ ##
15
+ # Given a prototype Hash, returns true if (recursively):
16
+ # - this hash contains all the prototype's keys, and
17
+ # - this hash contains all the prototype's values
18
+ # Note that this is not the same as equality. If the prototype provides a
19
+ # nil value for any key, then any value in this Hash is considered to be
20
+ # valid.
21
+ # @param prototype (Hash) The prototype to match against.
22
+ # @param strict (Boolean) If true, this Hash may not contain keys that are
23
+ # not present in the prototype.
24
+ # @return (Boolean) True if matching succeeds, false otherwise.
25
+ def prototype_match(prototype, strict = false)
26
+ # Prototype contains keys not in the Hash,so that's a failure.
27
+ if not (prototype.keys - keys).empty?
28
+ return false
29
+ end
30
+
31
+ # In strict evaluation, the Hash may also not contain keys that are not
32
+ # in the prototoype.
33
+ if strict and not (keys - prototype.keys).empty?
34
+ return false
35
+ end
36
+
37
+ # Now we have to examine the prototype's values.
38
+ prototype.each do |key, value|
39
+ # We can skip any nil values in the prototype. They exist only to ensure
40
+ # the key is present.
41
+ if value.nil?
42
+ next
43
+ end
44
+
45
+ # If the prototype value is a Hash, then the Hash value also has to be,
46
+ # and we have to recurse into this Hash.
47
+ if value.is_a?(Hash)
48
+ if not self[key].is_a?(Hash)
49
+ return false
50
+ end
51
+
52
+ self[key].extend(PrototypeMatch)
53
+ if not self[key].prototype_match(value)
54
+ return false
55
+ end
56
+
57
+ next
58
+ end
59
+
60
+ # Otherwise the prototype value must be equal to the Hash's value
61
+ if self[key] != value
62
+ return false
63
+ end
64
+ end
65
+
66
+ # All other cases must be true.
67
+ return true
68
+ end
69
+ end # module PrototypeMatch
70
+ end # module Collapsium
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ #
3
+ # collapsium
4
+ # https://github.com/jfinkhaeuser/collapsium
5
+ #
6
+ # Copyright (c) 2016 Jens Finkhaeuser and other collapsium contributors.
7
+ # All rights reserved.
8
+ #
9
+
10
+ module Collapsium
11
+ ##
12
+ # Provides recursive (deep) dup function for hashes.
13
+ module RecursiveDup
14
+ def recursive_dup
15
+ ret = map do |k, v|
16
+ # Hash values, recurse into them.
17
+ if v.is_a?(Hash)
18
+ n = v.dup # we duplicate v to not extend it.
19
+ n.extend(RecursiveDup)
20
+ next [k, n.recursive_dup]
21
+ end
22
+
23
+ begin
24
+ # Other duplicatable values
25
+ next [k, v.dup]
26
+ rescue TypeError
27
+ # Values such as e.g. Fixnum
28
+ next [k, v]
29
+ end
30
+ end
31
+ return Hash[ret]
32
+ end
33
+
34
+ alias deep_dup recursive_dup
35
+ end # module RecursiveDup
36
+ end # module Collapsium
@@ -9,7 +9,7 @@
9
9
 
10
10
  module Collapsium
11
11
  ##
12
- # Provides recursive merge functions for hashes. Used in PathedHash.
12
+ # Provides recursive merge functions for hashes.
13
13
  module RecursiveMerge
14
14
  ##
15
15
  # Recursively merge `:other` into this Hash.
@@ -0,0 +1,80 @@
1
+ # coding: utf-8
2
+ #
3
+ # collapsium
4
+ # https://github.com/jfinkhaeuser/collapsium
5
+ #
6
+ # Copyright (c) 2016 Jens Finkhaeuser and other collapsium contributors.
7
+ # All rights reserved.
8
+ #
9
+
10
+ module Collapsium
11
+ ##
12
+ # Provides recursive sort functions for hashes.
13
+ module RecursiveSort
14
+ ##
15
+ # Recursively sort a Hash by its keys. Without a block, this function will
16
+ # not be able to compare keys of different size.
17
+ def recursive_sort!(&block)
18
+ return keys.sort(&block).reduce(self) do |seed, key|
19
+ # Delete (and later re-insert) value for ordering
20
+ value = self[key]
21
+ delete(key)
22
+
23
+ # Recurse into Hash values
24
+ if value.is_a?(Hash)
25
+ value.extend(RecursiveSort)
26
+ value.recursive_sort!(&block)
27
+ end
28
+
29
+ # re-insert value
30
+ self[key] = value
31
+
32
+ next seed
33
+ end
34
+ end
35
+
36
+ ##
37
+ # Same as #recursive_sort!, but returns a copy.
38
+ def recursive_sort(&block)
39
+ ret = nil
40
+ if respond_to?(:recursive_dup)
41
+ ret = recursive_dup
42
+ else
43
+ ret = dup
44
+ end
45
+ ret.extend(RecursiveSort)
46
+ return ret.recursive_sort!(&block)
47
+ end
48
+
49
+ # def recursive_merge!(other, overwrite = true)
50
+ # if other.nil?
51
+ # return self
52
+ # end
53
+ #
54
+ # merger = proc do |_, v1, v2|
55
+ # # rubocop:disable Style/GuardClause
56
+ # if v1.is_a? Hash and v2.is_a? Hash
57
+ # next v1.merge(v2, &merger)
58
+ # elsif v1.is_a? Array and v2.is_a? Array
59
+ # next v1 + v2
60
+ # end
61
+ # if overwrite
62
+ # next v2
63
+ # else
64
+ # next v1
65
+ # end
66
+ # # rubocop:enable Style/GuardClause
67
+ # end
68
+ # merge!(other, &merger)
69
+ # end
70
+ #
71
+ # ##
72
+ # # Same as `dup.recursive_merge!`
73
+ # # @param (see #recursive_merge!)
74
+ # def recursive_merge(other, overwrite = true)
75
+ # copy = dup
76
+ # copy.extend(RecursiveMerge)
77
+ # return copy.recursive_merge!(other, overwrite)
78
+ # end
79
+ end # module RecursiveSort
80
+ end # module Collapsium
@@ -8,15 +8,21 @@
8
8
  #
9
9
 
10
10
  require 'collapsium/recursive_merge'
11
+ require 'collapsium/recursive_dup'
12
+ require 'collapsium/recursive_sort'
11
13
  require 'collapsium/indifferent_access'
12
14
  require 'collapsium/pathed_access'
15
+ require 'collapsium/prototype_match'
13
16
 
14
17
  module Collapsium
15
18
 
16
19
  # A Hash that includes all the different Hash extensions in collapsium
17
20
  class UberHash < Hash
18
21
  include RecursiveMerge
22
+ include RecursiveDup
23
+ include RecursiveSort
19
24
  include PathedAccess
25
+ include PrototypeMatch
20
26
 
21
27
  def initialize(*args)
22
28
  super
@@ -8,5 +8,5 @@
8
8
  #
9
9
  module Collapsium
10
10
  # The current release version
11
- VERSION = "0.1.0".freeze
11
+ VERSION = "0.2.0".freeze
12
12
  end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/collapsium/prototype_match'
3
+
4
+ describe ::Collapsium::PrototypeMatch do
5
+ before :each do
6
+ @hash = {
7
+ 'a' => 1,
8
+ :c => {
9
+ 'd' => 4,
10
+ 'f' => 6,
11
+ 42 => 5,
12
+ },
13
+ 'b' => 2,
14
+ }
15
+ @hash.extend(::Collapsium::PrototypeMatch)
16
+ end
17
+
18
+ it "matches a prototype containing any individual key (non-strict)" do
19
+ # Keys exist in hash
20
+ expect(@hash.prototype_match('a' => nil)).to be_truthy
21
+ expect(@hash.prototype_match('b' => nil)).to be_truthy
22
+ expect(@hash.prototype_match(c: nil)).to be_truthy
23
+
24
+ # Key doesn't exist in hash
25
+ expect(@hash.prototype_match(foo: nil)).to be_falsy
26
+ end
27
+
28
+ it "does't match a prototype containing an individual key in strict mode" do
29
+ expect(@hash.prototype_match({ 'a' => nil }, true)).to be_falsy
30
+ end
31
+
32
+ it "matches nested prototypes (non-strict)" do
33
+ proto = {
34
+ c: {
35
+ 'd' => nil,
36
+ }
37
+ }
38
+ expect(@hash.prototype_match(proto)).to be_truthy
39
+ end
40
+
41
+ it "doesn't match nested prototypes (strict)" do
42
+ proto = {
43
+ c: {
44
+ 'd' => nil,
45
+ }
46
+ }
47
+ expect(@hash.prototype_match(proto, true)).to be_falsy
48
+ end
49
+
50
+ it "fails if a value type mismatches a prototype value's type" do
51
+ proto = {
52
+ c: {
53
+ 'd' => {},
54
+ }
55
+ }
56
+ expect(@hash.prototype_match(proto)).to be_falsy
57
+ end
58
+
59
+ it "fails if a value mismatches a prototype value" do
60
+ proto = {
61
+ c: {
62
+ 'd' => 42,
63
+ }
64
+ }
65
+ expect(@hash.prototype_match(proto)).to be_falsy
66
+ end
67
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/collapsium/recursive_dup'
3
+
4
+ describe ::Collapsium::RecursiveDup do
5
+ it "duplicates nested values" do
6
+ h = {
7
+ 'a' => 1,
8
+ :c => {
9
+ 'd' => 4,
10
+ 'f' => 6,
11
+ 42 => 5,
12
+ },
13
+ 'b' => 2,
14
+ }
15
+ h.extend(::Collapsium::RecursiveDup)
16
+
17
+ h2 = h.deep_dup
18
+
19
+ expect(h2.object_id).not_to eql h.object_id
20
+ expect(h2[:c].object_id).not_to eql h[:c].object_id
21
+ end
22
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/collapsium/recursive_sort'
3
+
4
+ describe ::Collapsium::RecursiveSort do
5
+ before :each do
6
+ @tester = {}
7
+ @tester.extend(::Collapsium::RecursiveSort)
8
+ end
9
+
10
+ it "sorts a nested hash with string keys in place" do
11
+ h = {
12
+ 'a' => 1,
13
+ 'c' => {
14
+ 'd' => 4,
15
+ 'f' => 6,
16
+ 'e' => 5,
17
+ },
18
+ 'b' => 2,
19
+ }
20
+ h.extend(::Collapsium::RecursiveSort)
21
+
22
+ h.recursive_sort!
23
+
24
+ expect(h.keys).to eql %w(a b c)
25
+ expect(h['c'].keys).to eql %w(d e f)
26
+ end
27
+
28
+ it "duplicates and sorts an outer hash (not deep)" do
29
+ h = {
30
+ 'a' => 1,
31
+ 'c' => {
32
+ 'd' => 4,
33
+ 'f' => 6,
34
+ 'e' => 5,
35
+ },
36
+ 'b' => 2,
37
+ }
38
+ h.extend(::Collapsium::RecursiveSort)
39
+
40
+ h2 = h.recursive_sort
41
+
42
+ # Only the new outer hash's keys are sorted
43
+ expect(h.keys).to eql %w(a c b)
44
+ expect(h2.keys).to eql %w(a b c)
45
+
46
+ # Both inner hashes are sorted because dup isn't deep
47
+ expect(h['c'].keys).to eql %w(d e f)
48
+ expect(h2['c'].keys).to eql %w(d e f)
49
+
50
+ # Similar with object IDs
51
+ expect(h.object_id).not_to eql h2.object_id
52
+ expect(h['c'].object_id).to eql h2['c'].object_id
53
+ end
54
+
55
+ it "it uses RecursiveDup if present" do
56
+ require_relative '../lib/collapsium/recursive_dup'
57
+ h = {
58
+ 'a' => 1,
59
+ 'c' => {
60
+ 'd' => 4,
61
+ 'f' => 6,
62
+ 'e' => 5,
63
+ },
64
+ 'b' => 2,
65
+ }
66
+ h.extend(::Collapsium::RecursiveSort)
67
+ h.extend(::Collapsium::RecursiveDup)
68
+
69
+ h2 = h.recursive_sort
70
+
71
+ # Only the new outer hash's keys are sorted
72
+ expect(h.keys).to eql %w(a c b)
73
+ expect(h2.keys).to eql %w(a b c)
74
+
75
+ # Only the new inner hash's keys are sorted
76
+ expect(h['c'].keys).to eql %w(d f e)
77
+ expect(h2['c'].keys).to eql %w(d e f)
78
+
79
+ # Similar with object IDs
80
+ expect(h.object_id).not_to eql h2.object_id
81
+ expect(h['c'].object_id).not_to eql h2['c'].object_id
82
+ end
83
+ end
data/spec/spec_helper.rb CHANGED
@@ -6,4 +6,6 @@ end
6
6
 
7
7
  # Always start SimpleCov
8
8
  require 'simplecov'
9
- SimpleCov.start
9
+ SimpleCov.start do
10
+ add_filter 'spec'
11
+ end
@@ -41,4 +41,21 @@ describe Collapsium::UberHash do
41
41
  x = ::Collapsium::UberHash.new
42
42
  expect(x.empty?).to be_truthy
43
43
  end
44
+
45
+ it "has recursive_dup support" do
46
+ x = ::Collapsium::UberHash.new
47
+ expect(x.respond_to?(:recursive_dup)).to be_truthy
48
+ expect(x.respond_to?(:deep_dup)).to be_truthy
49
+ end
50
+
51
+ it "has recursive_sort support" do
52
+ x = ::Collapsium::UberHash.new
53
+ expect(x.respond_to?(:recursive_sort)).to be_truthy
54
+ expect(x.respond_to?(:recursive_sort!)).to be_truthy
55
+ end
56
+
57
+ it "has prototype_match support" do
58
+ x = ::Collapsium::UberHash.new
59
+ expect(x.respond_to?(:prototype_match)).to be_truthy
60
+ end
44
61
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: collapsium
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jens Finkhaeuser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-11 00:00:00.000000000 Z
11
+ date: 2016-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -116,12 +116,18 @@ files:
116
116
  - lib/collapsium.rb
117
117
  - lib/collapsium/indifferent_access.rb
118
118
  - lib/collapsium/pathed_access.rb
119
+ - lib/collapsium/prototype_match.rb
120
+ - lib/collapsium/recursive_dup.rb
119
121
  - lib/collapsium/recursive_merge.rb
122
+ - lib/collapsium/recursive_sort.rb
120
123
  - lib/collapsium/uber_hash.rb
121
124
  - lib/collapsium/version.rb
122
125
  - spec/indifferent_access_spec.rb
123
126
  - spec/pathed_access_spec.rb
127
+ - spec/prototype_match_spec.rb
128
+ - spec/recursive_dup_spec.rb
124
129
  - spec/recursive_merge_spec.rb
130
+ - spec/recursive_sort_spec.rb
125
131
  - spec/spec_helper.rb
126
132
  - spec/uber_hash_spec.rb
127
133
  homepage: https://github.com/jfinkhaeuser/collapsium
@@ -151,7 +157,10 @@ summary: Provides various Hash extensions, and an UberHash class that uses them
151
157
  test_files:
152
158
  - spec/indifferent_access_spec.rb
153
159
  - spec/pathed_access_spec.rb
160
+ - spec/prototype_match_spec.rb
161
+ - spec/recursive_dup_spec.rb
154
162
  - spec/recursive_merge_spec.rb
163
+ - spec/recursive_sort_spec.rb
155
164
  - spec/spec_helper.rb
156
165
  - spec/uber_hash_spec.rb
157
166
  has_rdoc: