astruct 2.11.0 → 3.0.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.
@@ -1,23 +0,0 @@
1
- # encoding: utf-8
2
- require File.expand_path('../lib/astruct/version', __FILE__)
3
-
4
- Gem::Specification.new do |gem|
5
- gem.authors = ["Kurtis Rainbolt-Greene"]
6
- gem.email = ["kurtisrainboltgreene@gmail.com"]
7
- gem.summary = %q{An alternative to OpenStruct}
8
- gem.description = gem.summary
9
- gem.homepage = "http://krainboltgreene.github.com/astruct"
10
-
11
- gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
- gem.files = `git ls-files`.split("\n")
13
- gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
- gem.name = "astruct"
15
- gem.require_paths = ["lib"]
16
- gem.version = AltStruct::VERSION
17
-
18
- gem.add_development_dependency 'rake'
19
- gem.add_development_dependency 'yard'
20
- gem.add_development_dependency 'kramdown'
21
- gem.add_development_dependency 'benchmark-ips'
22
- gem.add_development_dependency 'simplecov'
23
- end
@@ -1,34 +0,0 @@
1
- require 'benchmark/ips'
2
- require 'astruct'
3
- require 'ostruct'
4
-
5
- DATA = (1..10_000).map { |i| { "key#{i}" => "value#{i}" } }.inject :merge!
6
- DATA2 = (10_000..20_000).map { |i| { "key#{i}" => "value#{i}" } }.inject :merge!
7
-
8
- Benchmark.ips do |x|
9
- x.report "OStruct new with data then load with more data" do
10
- class OProfile < OpenStruct; end
11
- op = OProfile.new DATA.dup
12
- op.marshal_load op.marshal_dump.merge DATA2.dup
13
- end
14
-
15
- x.report "AStruct new with data then load with more data" do
16
- class AProfile < AltStruct; end
17
- ap = AProfile.new DATA.dup
18
- ap.load DATA2.dup
19
- end
20
- end
21
- #
22
- # PLATFORM: ruby 1.9.3p286 (2012-10-12 revision 37165) [x86_64-darwin12.2.0]
23
- # TIMESTAMP: 2012-11-06 11:17:33 -0800
24
- # ---
25
- # Calculating -------------------------------------
26
- # OStruct new with data then load with more data
27
- # 1 i/100ms
28
- # AStruct new with data then load with more data
29
- # 1 i/100ms
30
- # -------------------------------------------------
31
- # OStruct new with data then load with more data
32
- # 1.8 (±0.0%) i/s - 9 in 5.186949s
33
- # AStruct new with data then load with more data
34
- # 1.9 (±0.0%) i/s - 10 in 5.353544s
@@ -1,33 +0,0 @@
1
- require 'benchmark/ips'
2
- require 'astruct'
3
- require 'ostruct'
4
-
5
- DATA = (1..10_000).map { |i| { "key#{i}" => "value#{i}" } }.inject :merge!
6
-
7
- Benchmark.ips do |x|
8
- x.report "OStruct new with data then delete" do
9
- class OProfile < OpenStruct; end
10
- op = OProfile.new DATA.dup
11
- op.delete_field :key1
12
- end
13
-
14
- x.report "AStruct new with data then delete" do
15
- class AProfile < AltStruct; end
16
- ap = AProfile.new DATA.dup
17
- ap.delete :key1
18
- end
19
- end
20
- #
21
- # PLATFORM: ruby 1.9.3p286 (2012-10-12 revision 37165) [x86_64-darwin12.2.0]
22
- # TIMESTAMP: 2012-11-06 11:17:50 -0800
23
- # ---
24
- # Calculating -------------------------------------
25
- # OStruct new with data then delete
26
- # 1 i/100ms
27
- # AStruct new with data then delete
28
- # 1 i/100ms
29
- # -------------------------------------------------
30
- # OStruct new with data then delete
31
- # 4.4 (±22.5%) i/s - 22 in 5.028472s
32
- # AStruct new with data then delete
33
- # 5.4 (±18.6%) i/s - 26 in 5.028498s
@@ -1,33 +0,0 @@
1
- require 'benchmark/ips'
2
- require 'astruct'
3
- require 'ostruct'
4
-
5
- DATA = (1..10_000).map { |i| { "key#{i}" => "value#{i}" } }.inject :merge!
6
-
7
- Benchmark.ips do |x|
8
- x.report "OStruct dump with data" do
9
- class OProfile < OpenStruct; end
10
- op = OProfile.new DATA.dup
11
- op.marshal_dump
12
- end
13
-
14
- x.report "AStruct dump with data" do
15
- class AProfile < AltStruct; end
16
- ap = AProfile.new DATA.dup
17
- ap.dump
18
- end
19
- end
20
- #
21
- # PLATFORM: ruby 1.9.3p286 (2012-10-12 revision 37165) [x86_64-darwin12.2.0]
22
- # TIMESTAMP: 2012-11-06 11:18:06 -0800
23
- # ---
24
- # Calculating -------------------------------------
25
- # OStruct dump with data
26
- # 1 i/100ms
27
- # AStruct dump with data
28
- # 1 i/100ms
29
- # -------------------------------------------------
30
- # OStruct dump with data
31
- # 4.6 (±21.6%) i/s - 23 in 5.176739s
32
- # AStruct dump with data
33
- # 5.4 (±37.3%) i/s - 26 in 5.200824s
@@ -1,37 +0,0 @@
1
- require 'benchmark/ips'
2
- require 'astruct'
3
- require 'ostruct'
4
-
5
- DATA = (1..10_000).map { |i| { "key#{i}" => "value#{i}" } }.inject :merge!
6
-
7
- Benchmark.ips do |x|
8
- x.report "OStruct new with data then assign new data" do
9
- class OProfile < OpenStruct; end
10
- op = OProfile.new DATA.dup
11
- op.example1 = "red"
12
- op.example2 = "blue"
13
- op.example3 = "green"
14
- end
15
-
16
- x.report "AStructt new with data then assign new data" do
17
- class AProfile < AltStruct; end
18
- ap = AProfile.new DATA.dup
19
- ap.example1 = "red"
20
- ap.example2 = "blue"
21
- ap.example3 = "green"
22
- end
23
- end
24
- #
25
- # PLATFORM: ruby 1.9.3p286 (2012-10-12 revision 37165) [x86_64-darwin12.2.0]
26
- # TIMESTAMP: 2012-11-06 11:18:22 -0800
27
- # ---
28
- # Calculating -------------------------------------
29
- # OStruct new with data then assign new data
30
- # 1 i/100ms
31
- # AStructt new with data then assign new data
32
- # 1 i/100ms
33
- # -------------------------------------------------
34
- # OStruct new with data then assign new data
35
- # 4.2 (±23.8%) i/s - 21 in 5.200944s
36
- # AStructt new with data then assign new data
37
- # 5.1 (±38.9%) i/s - 24 in 5.001440s
@@ -1,33 +0,0 @@
1
- require 'benchmark/ips'
2
- require 'astruct'
3
- require 'ostruct'
4
-
5
- DATA = (1..10_000).map { |i| { "key#{i}" => "value#{i}" } }.inject :merge!
6
-
7
- Benchmark.ips do |x|
8
- x.report "OStruct inspect with data" do
9
- class OProfile < OpenStruct; end
10
- op = OProfile.new DATA.dup
11
- op.inspect
12
- end
13
-
14
- x.report "AStruct inspect with data" do
15
- class AProfile < AltStruct; end
16
- ap = AProfile.new DATA.dup
17
- ap.inspect
18
- end
19
- end
20
- #
21
- # PLATFORM: ruby 1.9.3p286 (2012-10-12 revision 37165) [x86_64-darwin12.2.0]
22
- # TIMESTAMP: 2012-11-06 11:18:38 -0800
23
- # ---
24
- # Calculating -------------------------------------
25
- # OStruct inspect with data
26
- # 1 i/100ms
27
- # AStruct inspect with data
28
- # 1 i/100ms
29
- # -------------------------------------------------
30
- # OStruct inspect with data
31
- # 4.4 (±22.5%) i/s - 22 in 5.063692s
32
- # AStruct inspect with data
33
- # 4.9 (±20.2%) i/s - 25 in 5.229125s
@@ -1,33 +0,0 @@
1
- require 'benchmark/ips'
2
- require 'astruct'
3
- require 'ostruct'
4
-
5
- DATA = (1..10_000).map { |i| { "key#{i}" => "value#{i}" } }.inject :merge!
6
-
7
- Benchmark.ips do |x|
8
- x.report "OStruct load with data" do
9
- class OProfile < OpenStruct; end
10
- op = OProfile.new
11
- op.marshal_load DATA.dup
12
- end
13
-
14
- x.report "AStruct load with data" do
15
- class AProfile < AltStruct; end
16
- ap = AProfile.new
17
- ap.load DATA.dup
18
- end
19
- end
20
- #
21
- # PLATFORM: ruby 1.9.3p286 (2012-10-12 revision 37165) [x86_64-darwin12.2.0]
22
- # TIMESTAMP: 2012-11-06 11:18:54 -0800
23
- # ---
24
- # Calculating -------------------------------------
25
- # OStruct load with data
26
- # 1 i/100ms
27
- # AStruct load with data
28
- # 1 i/100ms
29
- # -------------------------------------------------
30
- # OStruct load with data
31
- # 5.3 (±37.6%) i/s - 26 in 5.143205s
32
- # AStruct load with data
33
- # 5.3 (±18.8%) i/s - 26 in 5.086193s
@@ -1,37 +0,0 @@
1
- require 'benchmark/ips'
2
- require 'astruct'
3
- require 'ostruct'
4
-
5
- DATA = (1..10_000).map { |i| { "key#{i}" => "value#{i}" } }.inject :merge!
6
-
7
- Benchmark.ips do |x|
8
- x.report "OStruct new with data then 3 deep and inspect" do
9
- class OProfile < OpenStruct; end
10
- op = OProfile.new DATA.dup
11
- op.op2 = OProfile.new DATA.dup
12
- op.op2.op3 = OProfile.new DATA.dup
13
- op.inspect
14
- end
15
-
16
- x.report "AStruct new with data then 3 deep and inspect" do
17
- class AProfile < AltStruct; end
18
- ap = AProfile.new DATA.dup
19
- ap.ap2 = AProfile.new DATA.dup
20
- ap.ap2.ap3 = AProfile.new DATA.dup
21
- ap.inspect
22
- end
23
- end
24
- #
25
- # PLATFORM: ruby 1.9.3p286 (2012-10-12 revision 37165) [x86_64-darwin12.2.0]
26
- # TIMESTAMP: 2012-11-06 11:19:10 -0800
27
- # ---
28
- # Calculating -------------------------------------
29
- # OStruct new with data then 3 deep and inspect
30
- # 1 i/100ms
31
- # AStruct new with data then 3 deep and inspect
32
- # 1 i/100ms
33
- # -------------------------------------------------
34
- # OStruct new with data then 3 deep and inspect
35
- # 1.3 (±0.0%) i/s - 7 in 5.560086s
36
- # AStruct new with data then 3 deep and inspect
37
- # 1.6 (±0.0%) i/s - 9 in 5.569932s
@@ -1,31 +0,0 @@
1
- require 'benchmark/ips'
2
- require 'astruct'
3
- require 'ostruct'
4
-
5
- DATA = (1..10_000).map { |i| { "key#{i}" => "value#{i}" } }.inject :merge!
6
-
7
- Benchmark.ips do |x|
8
- x.report "OStruct new with data" do
9
- class OProfile < OpenStruct; end
10
- OProfile.new DATA.dup
11
- end
12
-
13
- x.report "AStruct new with data" do
14
- class AProfile < AltStruct; end
15
- AProfile.new DATA.dup
16
- end
17
- end
18
- #
19
- # PLATFORM: ruby 1.9.3p286 (2012-10-12 revision 37165) [x86_64-darwin12.2.0]
20
- # TIMESTAMP: 2012-11-06 11:19:28 -0800
21
- # ---
22
- # Calculating -------------------------------------
23
- # OStruct new with data
24
- # 1 i/100ms
25
- # AStruct new with data
26
- # 1 i/100ms
27
- # -------------------------------------------------
28
- # OStruct new with data
29
- # 4.3 (±23.4%) i/s - 21 in 5.130880s
30
- # AStruct new with data
31
- # 5.2 (±38.7%) i/s - 25 in 5.211888s
@@ -1,34 +0,0 @@
1
- require 'benchmark/ips'
2
- require 'astruct'
3
- require 'ostruct'
4
-
5
- DATA = (1..10_000).map { |i| { "key#{i}" => "value#{i}" } }.inject :merge!
6
- UPDATE = DATA.merge (1..5_000).map { |i| { "key#{i}" => "value#{i + rand(1..3)}" } }.inject :merge!
7
-
8
- Benchmark.ips do |x|
9
- x.report "OStruct partial updates with data" do
10
- class OProfile < OpenStruct; end
11
- op = OProfile.new DATA.dup
12
- op.marshal_load op.marshal_dump.merge UPDATE.dup
13
- end
14
-
15
- x.report "AStruct partial updates with data" do
16
- class AProfile < AltStruct; end
17
- ap = AProfile.new DATA.dup
18
- ap.load UPDATE.dup
19
- end
20
- end
21
- #
22
- # PLATFORM: ruby 1.9.3p286 (2012-10-12 revision 37165) [x86_64-darwin12.2.0]
23
- # TIMESTAMP: 2012-11-06 11:19:44 -0800
24
- # ---
25
- # Calculating -------------------------------------
26
- # OStruct partial updates with data
27
- # 1 i/100ms
28
- # AStruct partial updates with data
29
- # 1 i/100ms
30
- # -------------------------------------------------
31
- # OStruct partial updates with data
32
- # 3.4 (±29.5%) i/s - 17 in 5.211254s
33
- # AStruct partial updates with data
34
- # 3.0 (±0.0%) i/s - 15 in 5.116449s
@@ -1,162 +0,0 @@
1
- class AltStruct
2
- module M
3
- ThreadKey = :__inspect_astruct_ids__ # :nodoc:
4
- attr_reader :table
5
- alias_method :__object_id__, :object_id
6
- alias_method :__singleton_class__, :singleton_class
7
-
8
- # Create a new field for each of the key/value pairs passed.
9
- # By default the resulting OpenStruct object will have no
10
- # attributes. If no pairs are passed avoid any work.
11
- #
12
- # require 'ostruct'
13
- # hash = { "country" => "Australia", :population => 20_000_000 }
14
- # data = OpenStruct.new hash
15
- #
16
- # p data # => <OpenStruct country="Australia" population=20000000>
17
- #
18
- # If you happen to be inheriting then you can define your own
19
- # @table ivar before the `super()` call. AltStruct will respect
20
- # your @table.
21
- #
22
- def initialize(pairs = {})
23
- @table ||= {}
24
- for key, value in pairs
25
- key = key.to_sym
26
- __new_field__ key, value
27
- end unless pairs.empty?
28
- end
29
-
30
- # This is the `load()` method, which works like initialize in that it
31
- # will create new fields for each pair passed. Notice that it
32
- # also is a double-underbar method, making it really hard to
33
- # overwrite. It also mimics the behavior of a Hash#merge and
34
- # Hash#merge!
35
- def __load__(pairs)
36
- for key, value in pairs
37
- key = key.to_sym
38
- next if table[key] == value
39
- __new_field__ key, value
40
- end unless pairs.empty?
41
- end
42
- alias_method :marshal_load, :__load__
43
- alias_method :load, :__load__
44
- alias_method :merge, :__load__
45
- alias_method :merge!, :__load__
46
-
47
- # The `dump()` takes the table and out puts in it's natural hash
48
- # format. In addition you can pass along a specific set of keys to
49
- # dump.
50
- def __dump__(*keys)
51
- keys.empty? ? table : __dump_specific__(keys)
52
- end
53
- alias_method :marshal_dump, :__dump__
54
- alias_method :dump, :__dump__
55
- alias_method :to_hash, :__dump__
56
-
57
- def __inspect__
58
- "#<#{self.class}#{__dump_inspect__}>"
59
- end
60
- alias_method :inspect, :__inspect__
61
- alias_method :to_s, :__inspect__
62
-
63
- # The delete_field() method removes a key/value pair on the @table
64
- # and on the singleton class. It also mimics the Hash#delete method.
65
- def __delete_field__(key)
66
- __singleton_class__.send :remove_method, key
67
- __singleton_class__.send :remove_method, :"#{key}="
68
- @table.delete key
69
- end
70
- alias_method :delete_field, :__delete_field__
71
- alias_method :delete, :__delete_field__
72
-
73
- # The `method_missing()` method catches all non-tabled method calls.
74
- # The AltStruct object will return two specific errors depending on
75
- # the call.
76
- def method_missing(method, *args)
77
- name = method.to_s
78
- case
79
- when !name.include?('=')
80
- # This is to catch non-assignment methods
81
- message = "undefined method `#{name}' for #{self}"
82
- raise NoMethodError, message, caller(1)
83
- when args.size != 1
84
- # This is to catch the []= method
85
- message = "wrong number of arguments (#{args.size} for 1)"
86
- raise ArgumentError, message, caller(1)
87
- else
88
- __new_field__ name.chomp!('='), args.first
89
- end
90
- end
91
-
92
- def ==(object)
93
- if object.respond_to? :table
94
- table == object.table
95
- else
96
- false
97
- end
98
- end
99
-
100
- def freeze
101
- super
102
- @table.freeze
103
- end
104
- alias_method :__freeze__, :freeze
105
- alias_method :__frozen?, :frozen?
106
-
107
- private
108
-
109
- def __dump_inspect__
110
- __create_id_list__
111
- unless __id_exists_in_id_list__?
112
- __add_id_to_id_list__
113
- string = __dump__.any? ? " #{__dump_string__.join ', '}" : ""
114
- else
115
- __remove_last_id_from_id_list__
116
- string = __dump__.any? ? " ..." : ""
117
- end
118
- __remove_last_id_from_id_list__
119
- string
120
- end
121
-
122
- def __define_accessor__(key, value)
123
- define_singleton_method(key) { @table[key] }
124
- define_singleton_method(:"#{key}=") { |v| @table[key] = v }
125
- { key => value }.freeze
126
- end
127
-
128
- def __new_field__(key, value)
129
- table.merge! __define_accessor__ key, value
130
- end
131
-
132
- def __dump_specific__(keys)
133
- @table.keep_if { |key| keys.include? key }
134
- end
135
-
136
- def __dump_string__
137
- __dump__.map do |key, value|
138
- "#{key}=#{value.inspect}"
139
- end
140
- end
141
-
142
- def __add_id_to_id_list__
143
- Thread.current[ThreadKey] << object_id
144
- end
145
-
146
- def __create_id_list__
147
- Thread.current[ThreadKey] ||= []
148
- end
149
-
150
- def __id_exists_in_id_list__?
151
- Thread.current[ThreadKey].include?(__object_id__)
152
- end
153
-
154
- def __remove_last_id_from_id_list__
155
- Thread.current[ThreadKey].pop
156
- end
157
-
158
- def __field_exists_and_has_same_value__?(key, value)
159
- table[key] == value
160
- end
161
- end
162
- end