black_hole_struct 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 73a1e2099462587da0f479f244188535c3a237bd
4
+ data.tar.gz: e664723785a1fee9b05b29593a1ee481743d2298
5
+ SHA512:
6
+ metadata.gz: 54e70fa218aacd903f040a52112eaad60eb22e1561c6ffd502e6dc5ed53100967bc20e955d9fd93e3b53d3839751fe8fce3b0f2b8c0bda785ce5327a663d6eb7
7
+ data.tar.gz: 017822bce9972ef9cb83d7b6ed052eea09678ce9cd69bb33e7a5e6551be5262613d78384758d72d29a682b4decb5e1602655c304262890b9e35651070e8e246b
data/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # BlackHoleStruct
2
+
3
+ **BlackHoleStruct** is a data structure similar to an `OpenStruct`, that allows
4
+ infinite chaining of attributes or [autovivification](https://en.wikipedia.org/wiki/Autovivification).
5
+
6
+ ## Installation
7
+
8
+ Add it to your Gemfile:
9
+
10
+ ```ruby
11
+ gem "black-hole-struct"
12
+ ```
13
+
14
+ Or install the gem manually:
15
+
16
+ ```sh
17
+ $ gem install black-hole-struct
18
+ ```
19
+
20
+ ## Basic Usage
21
+
22
+ ```ruby
23
+ require "black_hole_struct"
24
+
25
+ config = BlackHoleStruct.new
26
+ config.dashboard.theme = "white"
27
+ config.dashboard.time.from = "now-1h"
28
+ config.dashboard.time.to = "now"
29
+
30
+ puts config.dashboard.theme # "white"
31
+ puts config.dashboard.time # #<BlackHoleStruct :from="now-1h" :to="now">
32
+ puts config.dashboard.time.from # "now-1h"
33
+ ```
34
+
35
+ ### Advanced usage
36
+
37
+ Check the [documentation](http://www.rubydoc.info/github/mickey/black-hole-struct/master/BlackHoleStruct).
@@ -0,0 +1,103 @@
1
+ # *BlackHoleStruct* is a data structure similar to an OpenStruct, that allows
2
+ # infinite chaining of attributes or [autovivification](https://en.wikipedia.org/wiki/Autovivification).
3
+ class BlackHoleStruct
4
+ # Current version
5
+ VERSION = "0.1.0"
6
+
7
+ # BlackHoleStruct can be optionally initialized with a Hash
8
+ # @param [Hash] hash Initialize with a hash
9
+ # @return [BlackHoleStruct]
10
+ def initialize(hash = {})
11
+ raise ArgumentError, "Argument should be a Hash" unless hash.is_a?(Hash)
12
+
13
+ @table = {}
14
+ hash.each do |key, value|
15
+ value = self.class.new(value) if value.is_a?(Hash)
16
+ @table[key.to_sym] = value
17
+ end
18
+ end
19
+
20
+ # Retrieves the value object corresponding to the key symbol.
21
+ # @param [Symbol] key
22
+ # @return the value object or a BlackHoleStruct if nothing was found
23
+ def [](key)
24
+ method_missing(key)
25
+ end
26
+
27
+ # Associates the value given by value with the key given by key.
28
+ # @param [Symbol] key
29
+ # @param value
30
+ # @return the value
31
+ def []=(key, value)
32
+ method_missing("#{key}=", value)
33
+ end
34
+
35
+ # Two BlackHoleStruct are equal if they each contain the same number of keys
36
+ # and if each key-value pair is equal to the corresponding elements in
37
+ # the other BlackHoleStruct.
38
+ # @param [BlackHoleStruct]
39
+ # @return [Boolean]
40
+ def ==(other)
41
+ other.is_a?(self.class) && self.to_h == other.to_h
42
+ end
43
+ alias :eql? :==
44
+
45
+ # Deletes the key-value pair and returns the value from hsh whose key is equal to key.
46
+ # If the key is not found, returns an instance of BlackHoleStruct.
47
+ # @param [Symbol] key
48
+ def delete_field(key)
49
+ @table[key.to_sym] = self.class.new
50
+ end
51
+
52
+ # Calls block once for each key in hsh, passing the key-value pair as parameters.
53
+ # if no block is given, an Enumerator is returned instead.
54
+ # @yield [key, value]
55
+ def each_pair
56
+ @table.each_pair
57
+ end
58
+
59
+ # Adds the contents of other_hash to hsh.
60
+ # If no block is specified, entries with duplicate keys are overwritten with the values from other_hash,
61
+ # otherwise the value of each duplicate key is determined by calling the block with the key,
62
+ # its value in hsh and its value in other_hash.
63
+ # @param [Hash] other_hash
64
+ # @return the final hash
65
+ def merge!(other_hash)
66
+ # no deep merge
67
+ @table = self.to_h.merge!(other_hash)
68
+ end
69
+ alias :update :merge!
70
+
71
+ # Converts self to the hash
72
+ # @return [Hash]
73
+ def to_h
74
+ hash = {}
75
+ @table.each do |key, value|
76
+ hash[key] = value.is_a?(self.class) ? value.to_h : value
77
+ end
78
+ hash
79
+ end
80
+
81
+ # Return the contents of this instance as a string.
82
+ # @return [String]
83
+ def inspect
84
+ "#<#{self.class}"
85
+ .concat(@table.map { |k, v| " :#{k}=#{v.inspect}" }.join(" "))
86
+ .concat(">")
87
+ end
88
+ alias :to_s :inspect
89
+
90
+ private
91
+
92
+ def method_missing(name, *args)
93
+ if @table[name.to_sym]
94
+ @table[name.to_sym]
95
+ else
96
+ if name[-1] == "="
97
+ @table[name[0..-2].to_sym] = args.first
98
+ else
99
+ @table[name.to_sym] = self.class.new
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,106 @@
1
+ require File.expand_path('../../lib/black_hole_struct', __FILE__)
2
+ require 'minitest/autorun'
3
+
4
+ class BlackHoleStructTest < Minitest::Test
5
+ def setup
6
+ @subject = BlackHoleStruct.new
7
+ end
8
+
9
+ def test_instanciate_without_arguments
10
+ assert_instance_of BlackHoleStruct, @subject
11
+ end
12
+
13
+ def test_accessor
14
+ @subject.theme = "white"
15
+ assert_equal @subject.theme, "white"
16
+ assert_equal @subject[:theme], "white"
17
+
18
+ @subject[:theme] = "black"
19
+ assert_equal @subject.theme, "black"
20
+ assert_equal @subject[:theme], "black"
21
+ end
22
+
23
+ def test_missing_values
24
+ assert_instance_of BlackHoleStruct, @subject.missing
25
+ end
26
+
27
+ def test_nested_accessor
28
+ @subject.dashboard.theme = "white"
29
+ assert_equal @subject.dashboard.theme, "white"
30
+ assert_equal @subject[:dashboard][:theme], "white"
31
+
32
+ @subject[:dashboards][:theme] = "black"
33
+ assert_equal @subject.dashboards.theme, "black"
34
+ assert_equal @subject[:dashboards][:theme], "black"
35
+ end
36
+
37
+ def test_equality
38
+ @subject.dashboard.theme = "white"
39
+ other = BlackHoleStruct.new
40
+ other.dashboard.theme = "white"
41
+ assert_equal @subject, other
42
+ assert_equal @subject.eql?(other), true
43
+ end
44
+
45
+ def test_instanciate_with_arguments
46
+ assert_raises ArgumentError do
47
+ BlackHoleStruct.new(Array.new)
48
+ end
49
+
50
+ subject = BlackHoleStruct.new(theme: "white")
51
+ assert_equal subject.theme, "white"
52
+
53
+ subject = BlackHoleStruct.new(dashboard: {theme: "white"})
54
+ assert_equal subject.dashboard.theme, "white"
55
+ end
56
+
57
+ def test_delete_field
58
+ @subject.theme = "white"
59
+ @subject.delete_field(:theme)
60
+ assert_equal @subject.theme, BlackHoleStruct.new
61
+
62
+ @subject.dashboard.theme = "white"
63
+ @subject.delete_field(:dashboard)
64
+ assert_equal @subject.dashboard, BlackHoleStruct.new
65
+ assert_equal @subject.dashboard.theme, BlackHoleStruct.new
66
+
67
+ assert_equal @subject.delete_field(:missing), BlackHoleStruct.new
68
+ end
69
+
70
+ def test_each_pair
71
+ assert_kind_of Enumerator, @subject.each_pair
72
+
73
+ @subject.theme = "white"
74
+ assert_equal @subject.each_pair.to_a, [[:theme, "white"]]
75
+
76
+ @subject.each_pair do |key, value|
77
+ assert_equal key, :theme
78
+ assert_equal value, "white"
79
+ end
80
+ end
81
+
82
+ def test_to_h
83
+ @subject.dashboard.theme = "white"
84
+ @subject.host = "127.0.0.1"
85
+
86
+ assert_equal @subject.to_h, {
87
+ dashboard: {theme: "white"},
88
+ host: "127.0.0.1"
89
+ }
90
+ end
91
+
92
+ def test_merge
93
+ @subject.theme = "white"
94
+ @subject.merge!(size: 5)
95
+
96
+ assert_equal @subject.to_h, {
97
+ theme: "white", size: 5
98
+ }
99
+ end
100
+
101
+ def test_inspect
102
+ assert_equal @subject.inspect, '#<BlackHoleStruct>'
103
+ @subject.theme = "white"
104
+ assert_equal @subject.inspect, '#<BlackHoleStruct :theme="white">'
105
+ end
106
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: black_hole_struct
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael Bensoussan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: yard
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: BlackHoleStruct is a data structure similar to an OpenStruct allowing
42
+ autovivification.
43
+ email:
44
+ - mbensoussan.is@gmail.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - README.md
50
+ - lib/black_hole_struct.rb
51
+ - test/black_hole_struct_test.rb
52
+ homepage: https://github.com/mickey/black_hole_struct
53
+ licenses:
54
+ - MIT
55
+ metadata: {}
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 2.5.1
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: BlackHoleStruct is a data structure
76
+ test_files:
77
+ - test/black_hole_struct_test.rb