dyna_struct 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 14bad87fe3602d8b8b591ed263f4a3c690e50627
4
+ data.tar.gz: 53fa67ed916cb526cde82872c72f4a4a11c9358d
5
+ SHA512:
6
+ metadata.gz: cb99c5957906fad30aa128112a637b10d84dd0d7f0b345f93ca8bfb4735e6fa0251015f67bb6a307e158c154236ac63436a9914df8ed7055c86e6c7ede917acf
7
+ data.tar.gz: 105582c4c8d876a6fbe824e3252ff7f4ab796f32778d506d68c1afb1f9dde0e79965e838b7bba5250c203108453c2fa2208c91527c39e7757cae0acd061bc31d
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.DS_Store
19
+ *.swp
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color --format documentation
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dyna_struct.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'rspec'
8
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 JC Wilcox
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,85 @@
1
+ # DynaStruct
2
+
3
+ DynaStruct offers a number of classes which provide different ways to dynamically assign and interact with instance variables.
4
+ This is accomplished through Ruby's metaprogramming, which allows the dynamic manipulation of data and methods for a specific object.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'dyna_struct'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install dyna_struct
19
+
20
+ ## Usage
21
+
22
+ The DynaStruct module provides four classes, offering different degrees of complexity:
23
+
24
+ * `DynaStruct::Base`
25
+ * `DynaStruct::Reader`
26
+ * `DynaStruct::Accessor`
27
+ * `DynaStruct::Full`
28
+
29
+ `DynaStruct::Base` contains only an initialize method, which takes a Hash and dynamically defines instance variables based on the values provided. So,
30
+
31
+ DynaStruct::Base.new(foo: 'bar')
32
+
33
+ will yield a new object with instance variable `@foo = 'bar'`.
34
+
35
+ `DynaStruct::Reader` offers this same functionality, with the addition of reader methods for instance variables.
36
+
37
+ x = DynaStruct::Reader.new(foo: 'bar)
38
+ x.foo #=> 'bar'
39
+
40
+ Similarly, `DynaStruct::Accessor` adds both getter and setter methods:
41
+
42
+ y = DynaStruct::Accessor.new(foo: 'bar')
43
+ x.foo = 7
44
+ x.foo #=> 7
45
+
46
+ `DynaStruct::Full` offers all of the above features, as well as most of the features offered by Ruby's OpenStruct class.
47
+
48
+ z = DynaStruct::Full.new(foo: 'bar')
49
+ z[:foo] #=> 'bar'
50
+ z['abc'] = 'def'
51
+ z.abc #=> 'def'
52
+ z.to_h #=> { foo: 'bar', abc: 'def' }
53
+
54
+ DynaStruct also offers a `DynaStruct::Modifiable` module, which adds three classes:
55
+
56
+ * `DynaStruct::Modifiable::Base`
57
+ * `DynaStruct::Modifiable::Reader`
58
+ * `DynaStruct::Modifiable::Accessor`
59
+
60
+ These classes correspond to the above classes, but add 3 methods: `.<<`, `.remove`, and `.empty?`,
61
+ which allow the user to make some modifications to the object after instantiation.
62
+
63
+ x = DynaStruct::Modifiable::Reader.new
64
+ x.empty? #=> true
65
+ x << { abc: 'def' }
66
+ x.empty? #=> false
67
+ x.abc #=> 'def'
68
+ x.remove(:abc) #=> 'def'
69
+ x.empty? #=> true
70
+
71
+ * * *
72
+
73
+ The biggest advantage these classes have over Ruby's OpenStruct is inheritance.
74
+
75
+ class Foo < DynaStruct::Reader; end
76
+
77
+ defines a class that can be initialized with an arbitrary Hash and automagically possess instance variables and reader methods corresponding to that Hash.
78
+
79
+ ## Contributing
80
+
81
+ 1. Fork it ( http://github.com/xDAGRONx/dyna_struct/fork )
82
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
83
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
84
+ 4. Push to the branch (`git push origin my-new-feature`)
85
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dyna_struct/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "dyna_struct"
8
+ spec.version = DynaStruct::VERSION
9
+ spec.authors = ["JC Wilcox"]
10
+ spec.email = ["84jwilcox@gmail.com"]
11
+ spec.summary = %q{An alternative to Ruby's Struct, DynaStruct allows dynamic assignment of instance variables.}
12
+ spec.description = %q{DynaStruct offers a number of classes which provide different ways to dynamically assign and interact with instance variables. This is accomplished through Ruby's metaprogramming, which allows the dynamic manipulation of data and methods for a specific object.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ end
@@ -0,0 +1,13 @@
1
+ require "dyna_struct/version"
2
+ require "dyna_struct/base"
3
+ require "dyna_struct/reader"
4
+ require "dyna_struct/accessor"
5
+ require "dyna_struct/modifiable"
6
+ require "dyna_struct/modifiable/base"
7
+ require "dyna_struct/modifiable/reader"
8
+ require "dyna_struct/modifiable/accessor"
9
+ require "dyna_struct/full"
10
+
11
+ module DynaStruct
12
+ # Your code goes here...
13
+ end
@@ -0,0 +1,12 @@
1
+ module DynaStruct
2
+ class Accessor < Base
3
+ private
4
+ def add_attributes(args)
5
+ args.each do |k, v|
6
+ instance_variable_set("@#{k}", v)
7
+ define_singleton_method("#{k}") { instance_variable_get("@#{k}") }
8
+ define_singleton_method("#{k}=") { |value| instance_variable_set("@#{k}", value) }
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ module DynaStruct
2
+ class Base
3
+ def initialize(args=nil)
4
+ add_attributes(args) if args.kind_of?(Hash)
5
+ end
6
+
7
+ private
8
+ def add_attributes(args)
9
+ args.each do |k, v|
10
+ instance_variable_set("@#{k}", v)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,67 @@
1
+ module DynaStruct
2
+ class Full
3
+ def initialize(args=nil)
4
+ args.each_pair do |k, v|
5
+ instance_variable_set("@#{k}", v)
6
+ add_attribute(k)
7
+ end if args.kind_of?(Hash)
8
+ end
9
+
10
+ def [](name)
11
+ instance_variable_get("@#{name}")
12
+ end
13
+
14
+ def []=(name, value)
15
+ instance_variable_set("@#{name}", value)
16
+ add_attribute(name)
17
+ value
18
+ end
19
+
20
+ def to_h
21
+ instance_variables.inject({}) do |result, var|
22
+ result.merge var.to_s[1..-1].to_sym => instance_variable_get(var)
23
+ end
24
+ end
25
+ alias_method :to_hash, :to_h
26
+
27
+ def delete_field(name)
28
+ if respond_to?(name)
29
+ remove_singleton_method(name, "#{name}=")
30
+ remove_instance_variable("@#{name}")
31
+ end
32
+ end
33
+
34
+ def method_missing(method_id, *args)
35
+ method_name = method_id.id2name
36
+ len = args.length
37
+ if method_name.chomp!(?=)
38
+ if len != 1
39
+ raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
40
+ end
41
+ self[method_name] = args.first
42
+ elsif method_name.chomp!(??)
43
+ unless len.zero?
44
+ raise ArgumentError, "wrong number of arguments (#{len} for 0)", caller(1)
45
+ end
46
+ !!self[method_name]
47
+ elsif len == 0
48
+ self[method_name]
49
+ else
50
+ super
51
+ end
52
+ end
53
+
54
+ private
55
+ def add_attribute(name)
56
+ unless respond_to?(name)
57
+ define_singleton_method("#{name}") { instance_variable_get("@#{name}") }
58
+ define_singleton_method("#{name}=") { |value| instance_variable_set("@#{name}", value) }
59
+ end
60
+ name
61
+ end
62
+
63
+ def remove_singleton_method(*method_names)
64
+ singleton_class.send(:remove_method, *method_names)
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,30 @@
1
+ module DynaStruct
2
+ module Modifiable
3
+ def <<(args)
4
+ add_attributes args if args.kind_of?(Hash)
5
+ self
6
+ end
7
+
8
+ def remove(*vars)
9
+ result = vars.map do |var|
10
+ remove_singleton_method(var.to_s) if singleton_method_defined?(var.to_s)
11
+ remove_singleton_method("#{var}=") if singleton_method_defined?("#{var}=")
12
+ remove_instance_variable("@#{var}") if instance_variable_defined?("@#{var}")
13
+ end
14
+ result.length == 1 ? result.first : result
15
+ end
16
+
17
+ def empty?
18
+ instance_variables.empty?
19
+ end
20
+
21
+ private
22
+ def remove_singleton_method(method_name)
23
+ singleton_class.send(:remove_method, method_name)
24
+ end
25
+
26
+ def singleton_method_defined?(method_name)
27
+ singleton_class.send(:method_defined?, method_name)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,7 @@
1
+ module DynaStruct
2
+ module Modifiable
3
+ class Accessor < DynaStruct::Accessor
4
+ include Modifiable
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module DynaStruct
2
+ module Modifiable
3
+ class Base < DynaStruct::Base
4
+ include Modifiable
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module DynaStruct
2
+ module Modifiable
3
+ class Reader < DynaStruct::Reader
4
+ include Modifiable
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ module DynaStruct
2
+ class Reader < Base
3
+ private
4
+ def add_attributes(args)
5
+ args.each do |k, v|
6
+ instance_variable_set("@#{k}", v)
7
+ define_singleton_method("#{k}") { instance_variable_get("@#{k}") }
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module DynaStruct
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe DynaStruct::Accessor do
4
+ describe '.new' do
5
+ include_examples 'DynaStruct::Accessor.new'
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe DynaStruct::Base do
4
+ describe '.new' do
5
+ include_examples 'DynaStruct.new'
6
+ end
7
+ end
@@ -0,0 +1,229 @@
1
+ require 'spec_helper'
2
+
3
+ describe DynaStruct::Full do
4
+ describe '.new' do
5
+ subject { described_class.new(info) }
6
+
7
+ context 'given a hash' do
8
+ context 'with valid info' do
9
+ let(:info) { { a: ?a, b: ?b, ab: 12, a18: nil } }
10
+
11
+ it 'should assign instance variables corresponding to the Hash' do
12
+ info.each do |key, value|
13
+ subject.instance_variable_get("@#{key}")
14
+ .should eq value
15
+ end
16
+ end
17
+
18
+ it 'should create getter and setter methods' do
19
+ info.each do |key, value|
20
+ should respond_to(key)
21
+ subject.send(key).should eq value
22
+ should respond_to("#{key}=")
23
+ end
24
+ end
25
+ end
26
+
27
+ context 'with invalid keys' do
28
+ let(:info) { { 9 => 2, ?@ => 4 } }
29
+
30
+ it 'should raise an exception' do
31
+ expect { subject }.to raise_exception(NameError)
32
+ end
33
+ end
34
+ end
35
+
36
+ context 'given anything besides a hash' do
37
+ it 'should return an empty DynaStruct' do
38
+ [:hi, 0, -1, 5, '', ?a, 'abc', nil, false, true, 1.05, [1,?b,3.0]].each do |arg|
39
+ test = described_class.new(arg)
40
+ test.should be_a(described_class)
41
+ test.instance_variables.should be_empty
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ describe '.[]' do
48
+ let(:info) { { a: ?a, b: ?b } }
49
+
50
+ context 'given a valid attribute' do
51
+ subject { described_class.new(info)[:a] }
52
+
53
+ it 'should return the associated value' do
54
+ should eq ?a
55
+ end
56
+ end
57
+
58
+ context 'given an invalid attribute' do
59
+ subject { described_class.new(info)[:c] }
60
+
61
+ it 'should return nil' do
62
+ should be_nil
63
+ end
64
+ end
65
+
66
+ context 'given an impossible attribute' do
67
+ subject { described_class.new(info)['@99'] }
68
+
69
+ it { expect { subject }.to raise_exception(NameError) }
70
+ end
71
+ end
72
+
73
+ describe '.[]=' do
74
+ subject { described_class.new(b: 3) }
75
+
76
+ it 'should return the value' do
77
+ subject.[]=(:c, 12).should eq 12
78
+ end
79
+
80
+ context 'setting a new attribute' do
81
+ before { subject[:a] = 2 }
82
+
83
+ it 'should set the instance variable' do
84
+ subject.instance_variable_get(:@a).should eq 2
85
+ end
86
+
87
+ it 'should create getter and setter methods' do
88
+ should respond_to(:a)
89
+ subject.a.should eq 2
90
+ should respond_to(:a=)
91
+ end
92
+ end
93
+
94
+ context 'attribute already exists' do
95
+ before { subject[:b] = 5 }
96
+
97
+ it 'should override the value' do
98
+ subject.instance_variable_get(:@b).should eq 5
99
+ end
100
+
101
+ it 'should not break getters or setters' do
102
+ should respond_to(:b)
103
+ subject.b.should eq 5
104
+ should respond_to(:b=)
105
+ end
106
+ end
107
+
108
+ context 'setting an impossible attribute' do
109
+ subject { described_class.new['@99'] = 12 }
110
+
111
+ it { expect { subject }.to raise_exception(NameError) }
112
+ end
113
+ end
114
+
115
+ describe '.to_h' do
116
+ subject { described_class.new(info) }
117
+ let(:info) { { a: ?a, b: ?b, ab: 12, a18: nil } }
118
+
119
+ it 'should return the hash of instance variables and values' do
120
+ subject.to_h.should eq info
121
+ end
122
+
123
+ it 'should use symbols as keys' do
124
+ subject.to_h.keys.each do |key|
125
+ key.should be_a(Symbol)
126
+ end
127
+ end
128
+
129
+ it 'should return the variable names without the @' do
130
+ subject.to_h.keys.each do |key|
131
+ key.to_s[0].should_not eq(?@)
132
+ end
133
+ end
134
+ end
135
+
136
+ describe '.delete_field' do
137
+ subject { described_class.new(info) }
138
+ let(:info) { { a: ?a, b: ?b, ab: 12, a18: nil } }
139
+
140
+ context 'field exists' do
141
+ it 'should remove the getter and setter methods' do
142
+ subject.delete_field(:a)
143
+ should_not respond_to :a
144
+ should_not respond_to :a=
145
+ end
146
+
147
+ it 'should remove the instance variable' do
148
+ subject.delete_field(:a)
149
+ subject.instance_variable_get(:@a).should be_nil
150
+ end
151
+
152
+ it 'should return the value of the deleted variable' do
153
+ subject.delete_field(:a).should eq info[:a]
154
+ end
155
+ end
156
+
157
+ context 'field does not exist' do
158
+ it 'should not raise error' do
159
+ expect { subject.delete_field(:charlie) }.not_to raise_exception
160
+ end
161
+
162
+ it 'should return nil' do
163
+ subject.delete_field(:charlie).should be_nil
164
+ end
165
+ end
166
+ end
167
+
168
+ describe '.method_missing' do
169
+ subject { described_class.new(info) }
170
+ let(:info) { { a: ?a, b: ?b, ab: 12, a18: nil } }
171
+
172
+ context 'given method ending in =' do
173
+ context 'given more than 1 argument' do
174
+ it 'should raise an argument error' do
175
+ expect { subject.send('beta=', 19, 3) }.to raise_exception(ArgumentError)
176
+ end
177
+ end
178
+
179
+ context 'given no arguments' do
180
+ it 'should raise an argument error' do
181
+ expect { subject.send('beta=') }.to raise_exception(ArgumentError)
182
+ end
183
+ end
184
+
185
+ context 'given a single argument' do
186
+ it 'should set the instance variable' do
187
+ subject.beta = 19
188
+ subject.instance_variable_get(:@beta).should eq 19
189
+ end
190
+
191
+ it 'should create getter and setter methods' do
192
+ subject.beta = 19
193
+ should respond_to(:beta)
194
+ subject.beta.should eq 19
195
+ should respond_to(:beta=)
196
+ end
197
+
198
+ it 'should return the value' do
199
+ subject.send('beta=', 19).should eq 19
200
+ end
201
+ end
202
+ end
203
+
204
+ context 'given a method ending in ?' do
205
+ context 'given an argument' do
206
+ it { expect { subject.beta?(12) }.to raise_exception(ArgumentError) }
207
+ end
208
+
209
+ context 'not given an argument' do
210
+ it 'should return the boolean value of the attribute' do
211
+ subject.beta?.should be_false
212
+ subject.a?.should be_true
213
+ end
214
+ end
215
+ end
216
+
217
+ context 'given a method not ending in = or ?' do
218
+ context 'given no arguments' do
219
+ it 'should return nil' do
220
+ subject.hello.should be_nil
221
+ end
222
+ end
223
+
224
+ context 'given an argument' do
225
+ it { expect { subject.alpha(2) }.to raise_exception(NoMethodError) }
226
+ end
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe DynaStruct::Modifiable::Accessor do
4
+ describe '.new' do
5
+ include_examples 'DynaStruct::Accessor.new'
6
+ end
7
+ include_examples 'Modifiable'
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe DynaStruct::Modifiable::Base do
4
+ describe '.new' do
5
+ include_examples 'DynaStruct.new'
6
+ end
7
+ include_examples 'Modifiable'
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe DynaStruct::Modifiable::Reader do
4
+ describe '.new' do
5
+ include_examples 'DynaStruct::Reader.new'
6
+ end
7
+ include_examples 'Modifiable'
8
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe DynaStruct::Reader do
4
+ describe '.new' do
5
+ include_examples 'DynaStruct::Reader.new'
6
+ end
7
+ end
@@ -0,0 +1,62 @@
1
+ shared_examples 'Modifiable' do
2
+ describe '.<<' do
3
+ subject { new_struct << info }
4
+ let(:info) { { hi: 'hello' } }
5
+ let(:new_struct) { described_class.new }
6
+
7
+ it 'should return self' do
8
+ should be_a(described_class)
9
+ should be(new_struct)
10
+ end
11
+
12
+ def adding_method(args)
13
+ described_class.new << args
14
+ end
15
+
16
+ include_examples 'add_attributes'
17
+ end
18
+
19
+ describe '.empty?' do
20
+ subject { described_class.new }
21
+
22
+ it { should respond_to(:empty?) }
23
+
24
+ context 'no attributes assigned' do
25
+ it { should be_empty }
26
+ end
27
+
28
+ context 'attributes assigned' do
29
+ before(:each) { subject << { hi: 'hello' } }
30
+
31
+ it { should_not be_empty }
32
+ end
33
+ end
34
+
35
+ describe '.remove' do
36
+ subject { described_class.new info }
37
+ let(:info) { { a: ?a, b: ?b } }
38
+
39
+ context 'passed valid attributes' do
40
+ it 'should return the array of deleted values' do
41
+ subject.remove(*info.keys).should eq info.values
42
+ end
43
+
44
+ it 'should return just the value if one attribute given' do
45
+ subject.remove(info.keys.first).should eq info.values.first
46
+ end
47
+ end
48
+
49
+ context 'passed invalid attributes' do
50
+ it 'should return nil for those attributes' do
51
+ subject.remove(:a, 'boop').should eq [?a, nil]
52
+ subject.remove('boop').should be_nil
53
+ end
54
+ end
55
+
56
+ context 'passed nothing' do
57
+ it 'should return an empty array' do
58
+ subject.remove.should eq []
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,72 @@
1
+ shared_examples 'DynaStruct.new' do
2
+ def adding_method(args)
3
+ described_class.new args
4
+ end
5
+
6
+ include_examples 'add_attributes'
7
+ end
8
+
9
+ shared_examples 'DynaStruct::Reader.new' do
10
+ include_examples 'DynaStruct.new'
11
+
12
+ subject { described_class.new info }
13
+ let(:info) { { a: ?a, b: ?b, ab: 12, a18: nil } }
14
+
15
+ it 'should create getter methods' do
16
+ info.each do |key, value|
17
+ should respond_to(key)
18
+ subject.send(key).should eq value
19
+ end
20
+ end
21
+ end
22
+
23
+ shared_examples 'DynaStruct::Accessor.new' do
24
+ include_examples 'DynaStruct::Reader.new'
25
+
26
+ subject { described_class.new info}
27
+ let(:info) { { a: ?a, b: ?b, ab: 12, a18: nil } }
28
+
29
+ it 'should create setter methods' do
30
+ info.each do |key, value|
31
+ should respond_to("#{key}=")
32
+ expect { subject.send("#{key}=", -2) }
33
+ .not_to raise_exception
34
+ subject.send(key).should eq -2
35
+ end
36
+ end
37
+ end
38
+
39
+ shared_examples 'add_attributes' do
40
+ context 'given a Hash' do
41
+ subject { adding_method(info) }
42
+
43
+ context 'with valid info' do
44
+ let(:info) { { a: ?a, b: ?b, ab: 12, a18: nil } }
45
+
46
+ it 'should assign instance variables corresponding to the Hash' do
47
+ info.each do |key, value|
48
+ subject.instance_variable_get("@#{key}")
49
+ .should eq value
50
+ end
51
+ end
52
+ end
53
+
54
+ context 'with invalid keys' do
55
+ let(:info) { { 9 => 2, ?@ => 4 } }
56
+
57
+ it 'should raise an exception' do
58
+ expect { subject }.to raise_exception(NameError)
59
+ end
60
+ end
61
+ end
62
+
63
+ context 'given anything that is not a Hash' do
64
+ it 'should not change the DynaStruct' do
65
+ [:hi, 0, -1, 5, '', ?a, 'abc', nil, false, true, 1.05, [1,?b,3.0]].each do |arg|
66
+ subject = adding_method(arg)
67
+ subject.should be_a(described_class)
68
+ subject.instance_variables.should eq []
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,3 @@
1
+ require 'dyna_struct'
2
+ require 'shared_specs'
3
+ require 'modifiable_spec'
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dyna_struct
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - JC Wilcox
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
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: DynaStruct offers a number of classes which provide different ways to
42
+ dynamically assign and interact with instance variables. This is accomplished through
43
+ Ruby's metaprogramming, which allows the dynamic manipulation of data and methods
44
+ for a specific object.
45
+ email:
46
+ - 84jwilcox@gmail.com
47
+ executables: []
48
+ extensions: []
49
+ extra_rdoc_files: []
50
+ files:
51
+ - .gitignore
52
+ - .rspec
53
+ - Gemfile
54
+ - LICENSE.txt
55
+ - README.md
56
+ - Rakefile
57
+ - dyna_struct.gemspec
58
+ - lib/dyna_struct.rb
59
+ - lib/dyna_struct/accessor.rb
60
+ - lib/dyna_struct/base.rb
61
+ - lib/dyna_struct/full.rb
62
+ - lib/dyna_struct/modifiable.rb
63
+ - lib/dyna_struct/modifiable/accessor.rb
64
+ - lib/dyna_struct/modifiable/base.rb
65
+ - lib/dyna_struct/modifiable/reader.rb
66
+ - lib/dyna_struct/reader.rb
67
+ - lib/dyna_struct/version.rb
68
+ - spec/lib/dyna_struct/accessor_spec.rb
69
+ - spec/lib/dyna_struct/base_spec.rb
70
+ - spec/lib/dyna_struct/full_spec.rb
71
+ - spec/lib/dyna_struct/modifiable/accessor_spec.rb
72
+ - spec/lib/dyna_struct/modifiable/base_spec.rb
73
+ - spec/lib/dyna_struct/modifiable/reader_spec.rb
74
+ - spec/lib/dyna_struct/reader_spec.rb
75
+ - spec/modifiable_spec.rb
76
+ - spec/shared_specs.rb
77
+ - spec/spec_helper.rb
78
+ homepage: ''
79
+ licenses:
80
+ - MIT
81
+ metadata: {}
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 2.1.11
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: An alternative to Ruby's Struct, DynaStruct allows dynamic assignment of
102
+ instance variables.
103
+ test_files:
104
+ - spec/lib/dyna_struct/accessor_spec.rb
105
+ - spec/lib/dyna_struct/base_spec.rb
106
+ - spec/lib/dyna_struct/full_spec.rb
107
+ - spec/lib/dyna_struct/modifiable/accessor_spec.rb
108
+ - spec/lib/dyna_struct/modifiable/base_spec.rb
109
+ - spec/lib/dyna_struct/modifiable/reader_spec.rb
110
+ - spec/lib/dyna_struct/reader_spec.rb
111
+ - spec/modifiable_spec.rb
112
+ - spec/shared_specs.rb
113
+ - spec/spec_helper.rb