astruct 2.11.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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