aspect 0.0.1

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: 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