aspect 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c759e692a1f7aaf002e2c474f45339003979c186
4
+ data.tar.gz: fad55ab8916d008d522556282a9bbf44539a38da
5
+ SHA512:
6
+ metadata.gz: 83a6b3c76a8963b1301a44dab87dd2176570d27bb939f40e62f0dcc8df411994f511817611e291e0ff6506190dd0c41f8ffa4dcbd9f6cb2ae8f16557aec8b460
7
+ data.tar.gz: 2d5bba3bd952490bfb20ffbdf109a64d23f0c31923fe1a73eee2ebf6394e34650ee4a97309ec264724e02dafdd9fa984012bf6681e00ae490aaa238b00471050
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem "rake"
7
+
8
+ gem "yard"
9
+
10
+ gem "rspec"
11
+ gem "fuubar"
12
+
13
+ gem "redcarpet"
14
+ gem "github-markup"
15
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2016 Ryan Scott Lewis <ryan@rynet.us>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # Aspect
2
+
3
+ A small collection of useful classes, modules, and mixins for plain old Ruby objects.
4
+
5
+ ## Install
6
+
7
+ ### Bundler: `gem "aspect"`
8
+
9
+ ### RubyGems: `gem install aspect`
10
+
11
+ ## Requiring
12
+
13
+ You should cherry pick the classes/modules you want to load like so:
14
+
15
+ ```rb
16
+ require "aspect/has_attributes"
17
+
18
+ class User
19
+ include Aspect::HasAttributes
20
+ end
21
+ ```
22
+
23
+ You can load all classes/modules in a module by requiring just the directory:
24
+
25
+ ```rb
26
+ require "aspect/foo/bar" # Would load aspect/foo/bar/**/*.rb
27
+ require "aspect/foo" # Would load aspect/foo/**/*.rb
28
+ require "aspect" # Would all files
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ ### Aspect::HasAttributes
34
+
35
+ **[Documentation](http://www.rubydoc.info/gems/aspect/Aspect/HasAttributes)**
36
+
37
+ ```rb
38
+ require "aspect/has_attributes"
39
+
40
+ class User
41
+ include Aspect::HasAttributes
42
+
43
+ attribute(:name) { |value| value.to_s.strip }
44
+ attribute(:moderator, query: true)
45
+ attribute(:admin, query: true) { |value| @moderator && value }
46
+
47
+ def initialize(attributes={})
48
+ update_attributes(attributes)
49
+ end
50
+ end
51
+
52
+ user = User.new(name: " Ezio ")
53
+
54
+ p user.name # => "Ezio"
55
+ user.name = :Ezio
56
+ p user.name # => "Ezio"
57
+
58
+ p user.moderator? # => false
59
+ p user.admin? # => false
60
+ user.admin = true
61
+ p user.moderator? # => false
62
+ p user.admin? # => false
63
+ user.moderator = "truthy value"
64
+ user.admin = true
65
+ p user.moderator? # => true
66
+ p user.admin? # => true
67
+ ```
68
+
69
+ ## Copyright
70
+
71
+ Copyright © 2016 Ryan Scott Lewis <ryan@rynet.us>.
72
+
73
+ The MIT License (MIT) - See LICENSE for further details.
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ require "pathname"
2
+ require "rubygems/package_task"
3
+ require "rake/version_task"
4
+ require "yard"
5
+ require "rspec/core/rake_task"
6
+
7
+ gemspec = Pathname.glob(Pathname.new(__FILE__).join("..", "*.gemspec")).first
8
+ spec = Gem::Specification.load(gemspec.to_s)
9
+
10
+ Gem::PackageTask.new(spec) do |task|
11
+ task.need_zip = false
12
+ end
13
+
14
+ Rake::VersionTask.new do |task|
15
+ task.with_git_tag = true
16
+ end
17
+
18
+ YARD::Rake::YardocTask.new
19
+
20
+ RSpec::Core::RakeTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/aspect.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ require "pathname"
2
+
3
+ Gem::Specification.new do |s|
4
+ # Variables
5
+ s.summary = "A small collection of useful classes, modules, and mixins for plain old Ruby objects."
6
+ s.license = "MIT"
7
+
8
+ # Dependencies
9
+ s.add_dependency "version", "~> 1.0.0"
10
+
11
+ # Pragmatically set variables and constants
12
+ s.author = "Ryan Scott Lewis"
13
+ s.email = "ryan@rynet.us"
14
+ s.homepage = "http://github.com/RyanScottLewis/#{s.name}"
15
+ s.version = Pathname.glob("VERSION*").first.read rescue "0.0.0"
16
+ s.description = s.summary
17
+ s.name = Pathname.new(__FILE__).basename(".gemspec").to_s
18
+ s.require_paths = ["lib"]
19
+ s.files = Dir["{Rakefile,Gemfile,README*,VERSION,LICENSE,*.gemspec,{lib,bin,examples,spec,test}/**/*}"]
20
+ s.test_files = Dir["{examples,spec,test}/**/*"]
21
+ end
data/lib/aspect.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "version"
2
+
3
+ # A small collection of useful mixins for plain old Ruby objects.
4
+ module Aspect
5
+ is_versioned
6
+ end
7
+
8
+ require "aspect/has_attributes"
@@ -0,0 +1,239 @@
1
+ module Aspect
2
+ # Easily define attribute getter/setter/accessors on an object with a `.attribute` class method.
3
+ #
4
+ # This also defines the `#update_attributes` instance method to use for mass assignment.
5
+ #
6
+ # **Documentation Notes**
7
+ #
8
+ # Since `.attribute` is a method which dynamically defines methods, you may need to use a special declaration
9
+ # in order to associate the documentation to the method.
10
+ #
11
+ # Here's how I do it with [YARD](http://yardoc.org):
12
+ #
13
+ # ```
14
+ # class User
15
+ # include Aspect::HasAttributes
16
+ #
17
+ # # @method name
18
+ # # Get the name.
19
+ # #
20
+ # # @return [String]
21
+ #
22
+ # # @method name=
23
+ # # Set the name.
24
+ # #
25
+ # # @param [#to_s] value
26
+ # # @return [String]
27
+ # attribute(:name) { |value| value.to_s.strip }
28
+ #
29
+ # # @method admin?
30
+ # # Get whether this user is an admin.
31
+ # #
32
+ # # @return [Boolean]
33
+ #
34
+ # # @method admin=
35
+ # # Set whether this user is an admin.
36
+ # #
37
+ # # @param [Boolean] value
38
+ # # @return [Boolean]
39
+ # attribute(:admin, query: true)
40
+ # end
41
+ # ```
42
+ module HasAttributes
43
+ # The class methods to extend into the object HasAttributes was included in.
44
+ module ClassMethods
45
+ # @method attribute
46
+ # Define an attribute on the object.
47
+ #
48
+ # @example Simple accessor
49
+ # class User
50
+ # include Aspect::HasAttributes
51
+ #
52
+ # attribute(:name)
53
+ # end
54
+ #
55
+ # user = User.new
56
+ # user.name = "Ezio Auditore"
57
+ # user.name # => "Ezio Auditore"
58
+ # @example Simple getter
59
+ # class User
60
+ # include Aspect::HasAttributes
61
+ #
62
+ # attribute(:name, setter: false)
63
+ #
64
+ # def initialize(name)
65
+ # @name = name
66
+ # end
67
+ # end
68
+ #
69
+ # user = User.new("Ezio Auditore")
70
+ # user.name # => "Ezio Auditore"
71
+ # @example Simple setter
72
+ # class User
73
+ # include Aspect::HasAttributes
74
+ #
75
+ # attribute(:name, getter: false)
76
+ #
77
+ # def name
78
+ # @name.strip
79
+ # end
80
+ # end
81
+ #
82
+ # user = User.new
83
+ # user.name = " Ezio Auditore "
84
+ # user.name # => "Ezio Auditore"
85
+ # @example Accessor with block
86
+ # class User
87
+ # include Aspect::HasAttributes
88
+ #
89
+ # attribute(:name) { |value| value.to_s.strip }
90
+ # end
91
+ #
92
+ # user = User.new
93
+ # user.name = " Ezio Auditore "
94
+ # user.name # => "Ezio Auditore"
95
+ # @example Accessor with block, passing options
96
+ # class User
97
+ # include Aspect::HasAttributes
98
+ #
99
+ # conversion_block = Proc.new { |value, options| "#{options[:prefix]}-#{value.to_s.strip}" }
100
+ # attribute(:foo, prefix: "Foo", &conversion_block)
101
+ # attribute(:bar, prefix: "Bar", &conversion_block)
102
+ # end
103
+ #
104
+ # user = User.new
105
+ # user.foo = " Thing "
106
+ # user.foo # => "Foo-Thing"
107
+ # user.bar = " Thingy"
108
+ # user.bar # => "Bar-Thingy"
109
+ # @example Query accessor
110
+ # class User
111
+ # include Aspect::HasAttributes
112
+ #
113
+ # attribute(:admin, query: true)
114
+ # end
115
+ #
116
+ # user = User.new
117
+ # user.admin? # => false
118
+ # user.admin = "yep" # Accepts truthy values
119
+ # user.admin? # => true
120
+ # @example Query accessor with block
121
+ # class User
122
+ # include Aspect::HasAttributes
123
+ #
124
+ # attribute(:moderator, query: true)
125
+ # attribute(:admin, query: true) { |value| @moderator && value }
126
+ # end
127
+ #
128
+ # user = User.new
129
+ #
130
+ # user.moderator? # => false
131
+ # user.admin? # => false
132
+ # user.admin = true
133
+ # user.admin? # => false
134
+ #
135
+ # user.moderator = true
136
+ # user.moderator? # => true
137
+ # user.admin? # => false
138
+ # user.admin = true
139
+ # user.moderator? # => true
140
+ # user.admin? # => true
141
+ # @param [Hash, #to_hash] options The options for defining and passing to the block.
142
+ # @option options [Boolean] :getter (true) Determines whether to define an attribute getter.
143
+ # @option options [Boolean] :setter (true) Determines whether to define an attribute setter.
144
+ # @option options [Boolean] :query (false)
145
+ # Determines whether to define as a query attribute, with the getter having a question mark appended to the
146
+ # method name and the setter converting the value or block into a boolean using bang-bang (`!!`).
147
+ # @yieldparam [Object] value The value given to the setter method.
148
+ # @yieldparam [Hash] options The options given when defining, given to the setter method.
149
+ # @yieldreturn [Object] The value to set the instance variable as.
150
+ # @return [Object]
151
+ def attribute(name, options={}, &block)
152
+ options = options.to_h unless options.is_a?(Hash)
153
+ options = { getter: true, setter: true, query: false }.merge(options)
154
+
155
+ if options[:getter]
156
+ if options[:query]
157
+ define_method("#{name}?") { !!instance_variable_get("@#{name}") }
158
+ else
159
+ attr_reader(name)
160
+ end
161
+ end
162
+
163
+ if options[:setter]
164
+ if options[:query]
165
+ define_method("#{name}=") do |value|
166
+ value = instance_exec(value, options, &block) unless block.nil?
167
+
168
+ instance_variable_set("@#{name}", !!value)
169
+ end
170
+ else
171
+ define_method("#{name}=") do |value|
172
+ value = instance_exec(value, options, &block) unless block.nil?
173
+
174
+ instance_variable_set("@#{name}", value)
175
+ end
176
+ end
177
+ end
178
+
179
+ self
180
+ end
181
+ end
182
+
183
+ class << self
184
+ # On include hook.
185
+ def included(base)
186
+ base.send(:extend, ClassMethods)
187
+ end
188
+ end
189
+
190
+ # @method update_attributes
191
+ # Update attributes on this object.
192
+ #
193
+ # @example
194
+ # class User
195
+ # include Aspect::HasAttributes
196
+ #
197
+ # attribute(:name) { |value| value.to_s.strip }
198
+ # attribute(:moderator, query: true)
199
+ # attribute(:admin, query: true) { |value| @moderator ? value : false }
200
+ # end
201
+ #
202
+ # user = User.new
203
+ #
204
+ # user.name # => nil
205
+ # user.moderator? # => false
206
+ # user.admin? # => false
207
+ #
208
+ # user.update_attributes(name: " Ezio Auditore ", moderator: true)
209
+ #
210
+ # user.name # => "Ezio Auditore"
211
+ # user.moderator? # => true
212
+ # user.admin? # => false
213
+ # @example In `#initialize`
214
+ # class User
215
+ # include Aspect::HasAttributes
216
+ #
217
+ # def initialize(attributes={})
218
+ # update_attributes(attributes)
219
+ # end
220
+ #
221
+ # attribute(:name) { |value| value.to_s.strip }
222
+ # attribute(:moderator, query: true)
223
+ # attribute(:admin, query: true) { |value| @moderator ? value : false }
224
+ # end
225
+ #
226
+ # user = User.new(name: " Ezio Auditore ", moderator: true)
227
+ #
228
+ # user.name # => "Ezio Auditore"
229
+ # user.moderator? # => true
230
+ # user.admin? # => false
231
+ # @param [Hash, #to_h] attributes
232
+ # @return [Object] This object.
233
+ def update_attributes(attributes={})
234
+ attributes = attributes.to_h unless attributes.is_a?(Hash)
235
+
236
+ attributes.each { |name, value| send("#{name}=", value) }
237
+ end
238
+ end
239
+ end
@@ -0,0 +1,265 @@
1
+ require "spec_helper"
2
+
3
+ describe Aspect::HasAttributes do
4
+ describe ".attribute" do
5
+ context "when no options are given" do
6
+ context "and no block is given" do
7
+ let(:instance) do
8
+ instance_class = Class.new do
9
+ include Aspect::HasAttributes
10
+
11
+ attribute(:name)
12
+ end
13
+
14
+ instance_class.new
15
+ end
16
+
17
+ it "should define a getter and a setter which uses the argument given to set the instance variable" do
18
+ expect(instance.name).to eq(nil)
19
+ instance.name = "foo"
20
+ expect(instance.name).to eq("foo")
21
+ end
22
+ end
23
+
24
+ context "and a block is given" do
25
+ let(:instance) do
26
+ instance_class = Class.new do
27
+ include Aspect::HasAttributes
28
+
29
+ attribute(:name) { |value| value.to_s }
30
+ end
31
+
32
+ instance_class.new
33
+ end
34
+
35
+ it "should define a getter and a setter which uses the return value of the block to set the instance variable" do
36
+ expect(instance.name).to eq(nil)
37
+ instance.name = 123
38
+ expect(instance.name).to eq("123")
39
+ end
40
+ end
41
+ end
42
+
43
+ context "when the :getter option is given" do
44
+ context "and it's truthy" do
45
+ let(:instance) do
46
+ instance_class = Class.new do
47
+ include Aspect::HasAttributes
48
+
49
+ attribute(:name, getter: true)
50
+ end
51
+
52
+ instance_class.new
53
+ end
54
+
55
+ it "should define a query getter which uses the argument given to set the instance variable" do
56
+ expect(instance.name).to eq(nil)
57
+ end
58
+ end
59
+
60
+ context "and it's falsey" do
61
+ let(:instance) do
62
+ instance_class = Class.new do
63
+ include Aspect::HasAttributes
64
+
65
+ attribute(:name, getter: false)
66
+ end
67
+
68
+ instance_class.new
69
+ end
70
+
71
+ it "should not define a getter" do
72
+ expect(instance.respond_to?(:name)).to eq(false)
73
+ end
74
+ end
75
+ end
76
+
77
+ context "when the :setter option is given" do
78
+ context "and no block is given" do
79
+ context "and it's truthy" do
80
+ let(:instance) do
81
+ instance_class = Class.new do
82
+ include Aspect::HasAttributes
83
+
84
+ attribute(:name, setter: true)
85
+ end
86
+
87
+ instance_class.new
88
+ end
89
+
90
+ it "should define a query setter which uses the argument given to set the instance variable" do
91
+ expect(instance.name).to eq(nil)
92
+ instance.name = "foobar"
93
+ expect(instance.name).to eq("foobar")
94
+ end
95
+ end
96
+
97
+ context "and it's falsey" do
98
+ let(:instance) do
99
+ instance_class = Class.new do
100
+ include Aspect::HasAttributes
101
+
102
+ attribute(:admin, query: false)
103
+ end
104
+
105
+ instance_class.new
106
+ end
107
+
108
+ it "should define a getter and a setter which uses the return value of the block to set the instance variable" do
109
+ expect(instance.admin).to eq(nil)
110
+ instance.admin = "truthy"
111
+ expect(instance.admin).to eq("truthy")
112
+ end
113
+ end
114
+ end
115
+
116
+ context "and a block is given" do
117
+ context "and it's truthy" do
118
+ let(:instance) do
119
+ instance_class = Class.new do
120
+ include Aspect::HasAttributes
121
+
122
+ attribute(:moderator, query: true)
123
+ attribute(:admin, query: true) { |value| @moderator && value }
124
+ end
125
+
126
+ instance_class.new
127
+ end
128
+
129
+ it "should define a query getter and a query setter which uses the return value of the block to set the instance variable as a truthy value" do
130
+ expect(instance.moderator?).to eq(false)
131
+ expect(instance.admin?).to eq(false)
132
+ instance.admin = "truthy"
133
+ expect(instance.admin?).to eq(false)
134
+ instance.moderator = true
135
+ instance.admin = "truthy"
136
+ expect(instance.moderator?).to eq(true)
137
+ expect(instance.admin?).to eq(true)
138
+ end
139
+ end
140
+
141
+ context "and it's falsey" do
142
+ let(:instance) do
143
+ instance_class = Class.new do
144
+ include Aspect::HasAttributes
145
+
146
+ attribute(:admin, query: false) { "return value" }
147
+ end
148
+
149
+ instance_class.new
150
+ end
151
+
152
+ it "should define a getter and a setter which uses the return value of the block to set the instance variable" do
153
+ expect(instance.admin).to eq(nil)
154
+ instance.admin = "anything"
155
+ expect(instance.admin).to eq("return value")
156
+ end
157
+ end
158
+ end
159
+ end
160
+
161
+ context "when the :query option is given" do
162
+ context "and no block is given" do
163
+ context "and it's truthy" do
164
+ let(:instance) do
165
+ instance_class = Class.new do
166
+ include Aspect::HasAttributes
167
+
168
+ attribute(:admin, query: true)
169
+ end
170
+
171
+ instance_class.new
172
+ end
173
+
174
+ it "should define a query getter and a query setter which uses the argument given to set the instance variable as a truthy value" do
175
+ expect(instance.admin?).to eq(false)
176
+ instance.admin = "truthy"
177
+ expect(instance.admin?).to eq(true)
178
+ end
179
+ end
180
+
181
+ context "and it's falsey" do
182
+ let(:instance) do
183
+ instance_class = Class.new do
184
+ include Aspect::HasAttributes
185
+
186
+ attribute(:admin, query: false)
187
+ end
188
+
189
+ instance_class.new
190
+ end
191
+
192
+ it "should define a getter and a setter which uses the return value of the block to set the instance variable" do
193
+ expect(instance.admin).to eq(nil)
194
+ instance.admin = "truthy"
195
+ expect(instance.admin).to eq("truthy")
196
+ end
197
+ end
198
+ end
199
+
200
+ context "and a block is given" do
201
+ context "and it's truthy" do
202
+ let(:instance) do
203
+ instance_class = Class.new do
204
+ include Aspect::HasAttributes
205
+
206
+ attribute(:moderator, query: true)
207
+ attribute(:admin, query: true) { |value| @moderator && value }
208
+ end
209
+
210
+ instance_class.new
211
+ end
212
+
213
+ it "should define a query getter and a query setter which uses the return value of the block to set the instance variable as a truthy value" do
214
+ expect(instance.moderator?).to eq(false)
215
+ expect(instance.admin?).to eq(false)
216
+ instance.admin = "truthy"
217
+ expect(instance.admin?).to eq(false)
218
+ instance.moderator = true
219
+ instance.admin = "truthy"
220
+ expect(instance.moderator?).to eq(true)
221
+ expect(instance.admin?).to eq(true)
222
+ end
223
+ end
224
+
225
+ context "and it's falsey" do
226
+ let(:instance) do
227
+ instance_class = Class.new do
228
+ include Aspect::HasAttributes
229
+
230
+ attribute(:admin, query: false) { "return value" }
231
+ end
232
+
233
+ instance_class.new
234
+ end
235
+
236
+ it "should define a getter and a setter which uses the return value of the block to set the instance variable" do
237
+ expect(instance.admin).to eq(nil)
238
+ instance.admin = "anything"
239
+ expect(instance.admin).to eq("return value")
240
+ end
241
+ end
242
+ end
243
+ end
244
+ end
245
+
246
+ describe "#update_attributes" do
247
+ let(:instance) do
248
+ class_instance = Class.new do
249
+ include Aspect::HasAttributes
250
+
251
+ attr_accessor :name
252
+ attr_accessor :age
253
+ end
254
+
255
+ class_instance.new
256
+ end
257
+
258
+ it "should update the attributes on the instance" do
259
+ instance.update_attributes(name: "Foo Bar", age: 123)
260
+
261
+ expect(instance.name).to eq("Foo Bar")
262
+ expect(instance.age).to eq(123)
263
+ end
264
+ end
265
+ end
@@ -0,0 +1,11 @@
1
+ require "aspect"
2
+
3
+ RSpec.configure do |config|
4
+ config.expect_with :rspec do |expectations|
5
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
6
+ end
7
+
8
+ config.mock_with :rspec do |mocks|
9
+ mocks.verify_partial_doubles = true
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aspect
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Scott Lewis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: version
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.0
27
+ description: A small collection of useful classes, modules, and mixins for plain old
28
+ Ruby objects.
29
+ email: ryan@rynet.us
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - Gemfile
35
+ - LICENSE
36
+ - README.md
37
+ - Rakefile
38
+ - VERSION
39
+ - aspect.gemspec
40
+ - lib/aspect.rb
41
+ - lib/aspect/has_attributes.rb
42
+ - spec/lib/aspect/has_attributes_spec.rb
43
+ - spec/spec_helper.rb
44
+ homepage: http://github.com/RyanScottLewis/
45
+ licenses:
46
+ - MIT
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 2.4.5
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: A small collection of useful classes, modules, and mixins for plain old Ruby
68
+ objects.
69
+ test_files:
70
+ - spec/spec_helper.rb
71
+ - spec/lib/aspect/has_attributes_spec.rb