extant 0.3.0

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: 59966f18b3d32352d1ab9700a02a424c1dc812f7
4
+ data.tar.gz: 5b8021c55eef67a6643fd7c50fdf6828953f814c
5
+ SHA512:
6
+ metadata.gz: bc0226bf520414c661d44cfd55a6398553fdc72c1e57144c50317492b4e554eca5bd920a1da12ae5c9a4bf72f327d4f60d4fa12432dd47c289ff05e744368443
7
+ data.tar.gz: 198d0d6440bb0c89aa66957a1d836c4edc0c82901a56c328b0683fab6083933979509da904cdc7dc5c5c587de299a38fa2aa7632f89685f0cbfe60e458a4458f
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 NCC Group Domain Services
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,80 @@
1
+ # Extant
2
+
3
+ _Sponsored by NCC Group Domain Services_
4
+
5
+ Extant provides attribute management for Ruby objects. It is somewhat similar to
6
+ `attr_accessor`, except it does many additional things like, type coercion,
7
+ change tracking (dirty attributes), and most importantly tracking of existence.
8
+
9
+ ## Installation
10
+
11
+ ``` terminal
12
+ $ gem install extant
13
+ ```
14
+
15
+ or in your **Gemfile**
16
+
17
+ ``` ruby
18
+ gem 'extant'
19
+ ```
20
+
21
+ ## Getting Started
22
+
23
+ ```ruby
24
+ class Widget
25
+ include Extant::Attributes
26
+
27
+ attribute :name, String
28
+ attribute :price, Integer
29
+ attribute :production_ready, Extant::Coercers::Boolean, default: false
30
+ end
31
+ ```
32
+
33
+ Basic Usage
34
+ ```ruby
35
+ widget = Widget.new(
36
+ name: 'Doodad',
37
+ price: 100
38
+ )
39
+
40
+ widget.name # => 'Doodad'
41
+ widget.price # => 100
42
+ widget.production_ready # => false
43
+
44
+ widget.attributes # => { name: 'Doodad', price: 100, production_ready: false }
45
+ ```
46
+
47
+ Coercion
48
+ ```ruby
49
+ widget = Widget.new(
50
+ price: 'not a number'
51
+ )
52
+
53
+ widget.extant_attributes[:price].coerced? # => false
54
+ widget.price # => nil
55
+ widget.extant_attributes[:price].pre_coerce_value # => 'not a number'
56
+ ```
57
+
58
+ Existence
59
+ ```ruby
60
+ widget = Widget.new
61
+
62
+ widget.name # => nil
63
+ widget.extant_attributes[:name].set? # => false
64
+
65
+ widget = Widget.new(
66
+ name: nil
67
+ )
68
+
69
+ widget.name # => nil
70
+ widget.extant_attributes[:name].set? # => true
71
+ widget.extant_attributes[:name].coerced? # => true
72
+ ```
73
+
74
+ ## Contributing
75
+
76
+ 1. Fork
77
+ 2. Make changes
78
+ 3. Pull request
79
+ 4. Celebrate
80
+
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
8
+ task :environment do
9
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'extant/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "extant"
8
+ spec.version = Extant::VERSION
9
+ spec.authors = ["NCC Group Domain Services"]
10
+ spec.email = ["brady.love@nccgroup.trust", "emily.dobervich@nccgroup.trust"]
11
+ spec.licenses = ['MIT']
12
+
13
+ spec.summary = %q{Extant, it helps you manage your attributes' existance.}
14
+ spec.description = %q{Define attributes, readers and writers on classes.}
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.9"
20
+ spec.add_development_dependency "rake", "~> 10.0"
21
+ spec.add_development_dependency "rspec", "~> 3.0"
22
+ spec.add_development_dependency "pry-nav"
23
+ spec.add_development_dependency "pry-doc"
24
+ end
@@ -0,0 +1,8 @@
1
+ require 'extant/version'
2
+ require 'extant/unset_value'
3
+ require 'extant/uncoerced_value'
4
+ require 'extant/attributes'
5
+
6
+ module Extant
7
+
8
+ end
@@ -0,0 +1,78 @@
1
+ module Extant
2
+ class Attribute
3
+ attr_reader :name, :coercer_class, :pre_coerce_value, :value
4
+
5
+ def initialize(name, value, definition)
6
+ self.name = name
7
+ self.has_been_coereced = false
8
+ self.definition = definition
9
+
10
+ if UnsetValue == value
11
+ @value = nil
12
+ self.is_unset = true
13
+ else
14
+ set_value(value)
15
+ end
16
+ end
17
+
18
+ def value=(val)
19
+ set_value(val)
20
+ self.value_has_changed = true
21
+ end
22
+
23
+ def coerced?
24
+ !!has_been_coereced
25
+ end
26
+
27
+ def has_changed?
28
+ !!value_has_changed
29
+ end
30
+
31
+ def unset?
32
+ !set?
33
+ end
34
+
35
+ def set?
36
+ !is_unset
37
+ end
38
+
39
+ def coercer_name
40
+ coercer_class.try(:coercer_name)
41
+ end
42
+
43
+ def inspect
44
+ "<Extant::Attribute:#{self.object_id} Name: :#{name} Value: #{value.inspect}>"
45
+ end
46
+
47
+ private
48
+
49
+ def coercer_class
50
+ definition.coercer_class
51
+ end
52
+
53
+ def set_value(val)
54
+ self.pre_coerce_value = val
55
+
56
+ @value = if coercer_class
57
+ coercer = coercer_class.new(val)
58
+ coercer.coerce.tap { self.has_been_coereced = coercer.coerced? }
59
+ else
60
+ self.has_been_coereced = true
61
+ val
62
+ end
63
+
64
+ if UncoercedValue == @value
65
+ @value = nil
66
+
67
+ if definition.allow_nil && pre_coerce_value == nil
68
+ self.has_been_coereced = true
69
+ end
70
+ end
71
+
72
+ self.is_unset = false
73
+ end
74
+
75
+ attr_accessor :value_has_changed, :has_been_coereced, :is_unset, :definition
76
+ attr_writer :name, :coercer_class, :pre_coerce_value
77
+ end
78
+ end
@@ -0,0 +1,28 @@
1
+ module Extant
2
+ class AttributeDefinition
3
+ attr_accessor :name, :type, :coercer_class, :has_default, :default_value,
4
+ :allow_nil
5
+
6
+ def initialize(model, name, opts={})
7
+ self.name = name
8
+ self.type = opts[:type]
9
+ self.has_default = opts.key?(:default)
10
+ self.default_value = opts[:default]
11
+ self.allow_nil = opts.fetch(:allow_nil, true)
12
+
13
+ if type
14
+ self.coercer_class = Extant::Coercers.find(type)
15
+ end
16
+
17
+ model.instance_eval do
18
+ define_method name do
19
+ extant_attributes[name].value
20
+ end
21
+
22
+ define_method "#{name}=" do |val|
23
+ extant_attributes[name].value = val
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,130 @@
1
+ require 'extant/attribute'
2
+ require 'extant/attribute_definition'
3
+
4
+ module Extant
5
+ module Attributes
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ def attribute_definitions
12
+ @attributes ||= {}
13
+ end
14
+
15
+ def attribute(name, type=nil, **opts)
16
+ opts[:type] = type
17
+ attribute_definitions[name] = AttributeDefinition.new(self, name, opts)
18
+ end
19
+ end
20
+
21
+ def initialize(attrs={})
22
+ attrs = Hash[attrs.map{ |k, v| [k.to_sym, v] }]
23
+ attribute_definitions.each do |k, definition|
24
+ value = if attrs.key?(k)
25
+ attrs[k]
26
+ else
27
+ UnsetValue
28
+ end
29
+
30
+ if UnsetValue == value && definition.has_default
31
+ value = definition.default_value.is_a?(Proc) ? definition.default_value.call : definition.default_value
32
+ end
33
+
34
+ extant_attributes[k] =
35
+ Extant::Attribute.new(k, value, definition)
36
+ end
37
+
38
+ self.original_extant_attributes = extant_attributes
39
+ end
40
+
41
+ def attributes
42
+ self.class.attribute_definitions.each_with_object({}) do |(k, _), attrs|
43
+ attrs[k] = send(k)
44
+ end
45
+ end
46
+
47
+ def attribute_definitions
48
+ self.class.attribute_definitions
49
+ end
50
+
51
+ def extant_attributes
52
+ @extant_attributes ||= {}
53
+ end
54
+
55
+ def set_attributes
56
+ self.class.attribute_definitions.each_with_object({}) do |(k, _), attrs|
57
+ if extant_attributes[k].set?
58
+ attrs[k] = send(k)
59
+ end
60
+ end
61
+ end
62
+
63
+ def changed_attributes
64
+ self.class.attribute_definitions.each_with_object({}) do |(k, _), attrs|
65
+ if extant_attributes[k].has_changed?
66
+ attrs[k] = send(k)
67
+ end
68
+ end
69
+ end
70
+
71
+ def each_extant_attribute
72
+ extant_attributes.values.each do |v|
73
+ yield v
74
+ end
75
+ end
76
+
77
+ def update_attributes(attrs={})
78
+ attrs.each do |k, v|
79
+ send("#{k}=".to_sym, v) if respond_to?("#{k}=".to_sym)
80
+ end
81
+
82
+ self
83
+ end
84
+
85
+ def dirty?(attr=nil)
86
+ if attr
87
+ !!changed_extant_attributes[attr]
88
+ else
89
+ changed_extant_attributes.any?
90
+ end
91
+ end
92
+
93
+ def original_extant_attributes
94
+ @original_extant_attributes ||= {}
95
+ end
96
+
97
+ def with(attrs={}, metadata={})
98
+ new_instance = self.class.new(self.attributes)
99
+ new_instance.update_attributes(attrs)
100
+
101
+ new_instance.send(:with_metadata=, metadata)
102
+ new_instance.send(:original_extant_attributes=, original_extant_attributes)
103
+ new_instance
104
+ end
105
+
106
+ def with_metadata
107
+ @with_metadata || {}
108
+ end
109
+
110
+ private
111
+
112
+ attr_writer :with_metadata
113
+
114
+ def changed_extant_attributes
115
+ self.class.attribute_definitions.each_with_object({}) do |(k, _), attrs|
116
+ if extant_attributes[k].has_changed?
117
+ attrs[k] = extant_attributes[k]
118
+ end
119
+ end
120
+ end
121
+
122
+ def original_extant_attributes=(attrs={})
123
+ attrs.each do |k, v|
124
+ original_extant_attributes[k] = v.dup
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+ require 'extant/coercers'
@@ -0,0 +1,47 @@
1
+ module Extant
2
+ module Coercers
3
+ def self.find(type)
4
+ if type.is_a?(::Hash)
5
+ coercer_options = {
6
+ hash_format: type
7
+ }
8
+
9
+ type = HashCoercerBuilder.build(coercer_options)
10
+ end
11
+
12
+ if type.is_a?(::Array)
13
+ coercer_options = {
14
+ array_format: type
15
+ }
16
+
17
+ type = ArrayCoercerBuilder.build(coercer_options)
18
+ end
19
+
20
+ if type.is_a?(Class) && type.ancestors.include?(Extant::Coercers::Base)
21
+ coercer_class = type
22
+ else
23
+ coercer_class = Object.const_get("Extant::Coercers::#{type}")
24
+
25
+ unless coercer_class.method_defined?(:coerce)
26
+ raise "#{type} must respond to #coerce"
27
+ end
28
+ end
29
+
30
+ coercer_class
31
+ end
32
+ end
33
+ end
34
+
35
+ require 'extant/coercers/base'
36
+
37
+ require 'extant/coercers/boolean'
38
+ require 'extant/coercers/date_time'
39
+ require 'extant/coercers/fixnum'
40
+ require 'extant/coercers/float'
41
+ require 'extant/coercers/hash'
42
+ require 'extant/coercers/array'
43
+ require 'extant/coercers/integer'
44
+ require 'extant/coercers/string'
45
+ require 'extant/coercers/symbol'
46
+ require 'extant/coercers/time'
47
+ require 'extant/coercers/uuid'
@@ -0,0 +1,56 @@
1
+ module Extant::Coercers
2
+ class Array < Base
3
+ class << self
4
+ attr_accessor :value_type
5
+ end
6
+
7
+ def coerce
8
+ return ArgumentError unless value.respond_to?(:to_a)
9
+ result = value.to_a
10
+ return ArgumentError unless result.is_a?(::Array)
11
+
12
+ if value_type
13
+ result = result.map do |v|
14
+ coerce_value(v)
15
+ end
16
+ end
17
+
18
+ self.coerced = true
19
+
20
+ result
21
+ rescue ArgumentError
22
+ UncoercedValue
23
+ end
24
+
25
+ private
26
+
27
+ def coerce_value(v)
28
+ coercer = value_type.new(v)
29
+ result = coercer.coerce
30
+ raise ArgumentError unless coercer.coerced?
31
+ result
32
+ end
33
+
34
+ def key_type
35
+ self.class.key_type
36
+ end
37
+
38
+ def value_type
39
+ self.class.value_type
40
+ end
41
+ end
42
+
43
+ class ArrayCoercerBuilder
44
+ def self.build(opts)
45
+ value_type_local = Extant::Coercers.find(opts[:array_format].first)
46
+
47
+ Class.new(Extant::Coercers::Array) do
48
+ self.value_type = value_type_local
49
+
50
+ def self.coercer_name
51
+ 'array'
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,27 @@
1
+ module Extant::Coercers
2
+ class Base
3
+ UncoercedValue = Extant::UncoercedValue
4
+
5
+ def self.coercer_name
6
+ self.name.split("::").last.gsub(/([a-z\d])([A-Z])/,'\1_\2').downcase
7
+ end
8
+
9
+ def initialize(value, options={})
10
+ self.value = value
11
+ self.coerced = false
12
+ self.options = {}
13
+ end
14
+
15
+ def coerce
16
+ rase NotImplementedError.new("#{self.class.name} must implement #{coerce}")
17
+ end
18
+
19
+ def coerced?
20
+ coerced
21
+ end
22
+
23
+ private
24
+
25
+ attr_accessor :value, :coerced, :options
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ module Extant::Coercers
2
+ class Boolean < Base
3
+ def coerce
4
+ if [true, "true", 1].include?(value)
5
+ self.coerced = true
6
+ return true
7
+ elsif [false, "false", 0].include?(value)
8
+ self.coerced = true
9
+ return false
10
+ end
11
+
12
+ Extant::UncoercedValue
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module Extant::Coercers
2
+ class DateTime < Base
3
+ def coerce
4
+ if value.is_a?(::DateTime)
5
+ self.coerced = true
6
+ return value
7
+ end
8
+
9
+ result = ::DateTime.parse(value.to_s)
10
+ self.coerced = true
11
+ result
12
+ rescue ArgumentError
13
+ UncoercedValue
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ module Extant::Coercers
2
+ class Fixnum < Base
3
+ def coerce
4
+ result = Integer(value)
5
+ self.coerced = true
6
+ result
7
+ rescue ArgumentError, TypeError
8
+ UncoercedValue
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Extant::Coercers
2
+ class Float < Base
3
+ def coerce
4
+ result = Float(value)
5
+ self.coerced = true
6
+ result
7
+ rescue ArgumentError, TypeError
8
+ UncoercedValue
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,63 @@
1
+ module Extant::Coercers
2
+ class Hash < Base
3
+ class << self
4
+ attr_accessor :key_type, :value_type
5
+ end
6
+
7
+ def coerce
8
+ result = ::Hash[value]
9
+
10
+ if key_type && value_type
11
+ result = result.each_with_object({}) do |(k, v), h|
12
+ h[coerce_key(k)] = coerce_value(v)
13
+ end
14
+ end
15
+
16
+ self.coerced = true
17
+
18
+ result
19
+ rescue ArgumentError
20
+ UncoercedValue
21
+ end
22
+
23
+ private
24
+
25
+ def coerce_key(v)
26
+ coercer = key_type.new(v)
27
+ result = coercer.coerce
28
+ raise ArgumentError unless coercer.coerced?
29
+ result
30
+ end
31
+
32
+ def coerce_value(v)
33
+ coercer = value_type.new(v)
34
+ result = coercer.coerce
35
+ raise ArgumentError unless coercer.coerced?
36
+ result
37
+ end
38
+
39
+ def key_type
40
+ self.class.key_type
41
+ end
42
+
43
+ def value_type
44
+ self.class.value_type
45
+ end
46
+ end
47
+
48
+ class HashCoercerBuilder
49
+ def self.build(opts)
50
+ key_type_local = Extant::Coercers.find(opts[:hash_format].keys.first)
51
+ value_type_local = Extant::Coercers.find(opts[:hash_format].values.first)
52
+
53
+ Class.new(Extant::Coercers::Hash) do
54
+ self.key_type = key_type_local
55
+ self.value_type = value_type_local
56
+
57
+ def self.coercer_name
58
+ 'hash'
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,11 @@
1
+ module Extant::Coercers
2
+ class Integer < Base
3
+ def coerce
4
+ result = Integer(value)
5
+ self.coerced = true
6
+ result
7
+ rescue ArgumentError, TypeError
8
+ UncoercedValue
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module Extant::Coercers
2
+ class String < Base
3
+ def coerce
4
+ return UncoercedValue if value == nil
5
+
6
+ self.coerced = true
7
+ value.to_s
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,20 @@
1
+ module Extant::Coercers
2
+ class Symbol < Base
3
+ def coerce
4
+ return UncoercedValue if value == nil
5
+
6
+ if value.is_a?(::String)
7
+ result = value.to_sym
8
+ elsif value.is_a?(::Symbol)
9
+ result = value
10
+ else
11
+ raise ArgumentError
12
+ end
13
+
14
+ self.coerced = true
15
+ result
16
+ rescue ArgumentError
17
+ UncoercedValue
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ require 'time'
2
+
3
+ module Extant::Coercers
4
+ class Time < Base
5
+ def coerce
6
+ if value.is_a?(::Time)
7
+ self.coerced = true
8
+ return value
9
+ end
10
+
11
+ result = ::Time.parse(value.to_s)
12
+ self.coerced = true
13
+ result
14
+ rescue ArgumentError
15
+ UncoercedValue
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ module Extant::Coercers
2
+ class Uuid < Base
3
+ UUID_REGEX = /\A[\da-f]{8}-([\da-f]{4}-){3}[\da-f]{12}\z/i
4
+
5
+ def coerce
6
+ if value.to_s =~ UUID_REGEX
7
+ self.coerced = true
8
+ value.to_s
9
+ else
10
+ UncoercedValue
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ require 'singleton'
2
+
3
+ module Extant
4
+ class UncoercedValue
5
+ include Singleton
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'singleton'
2
+
3
+ module Extant
4
+ class UnsetValue
5
+ include Singleton
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Extant
2
+ VERSION = "0.3.0"
3
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: extant
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - NCC Group Domain Services
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-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.9'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry-nav
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-doc
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Define attributes, readers and writers on classes.
84
+ email:
85
+ - brady.love@nccgroup.trust
86
+ - emily.dobervich@nccgroup.trust
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - extant.gemspec
99
+ - lib/extant.rb
100
+ - lib/extant/attribute.rb
101
+ - lib/extant/attribute_definition.rb
102
+ - lib/extant/attributes.rb
103
+ - lib/extant/coercers.rb
104
+ - lib/extant/coercers/array.rb
105
+ - lib/extant/coercers/base.rb
106
+ - lib/extant/coercers/boolean.rb
107
+ - lib/extant/coercers/date_time.rb
108
+ - lib/extant/coercers/fixnum.rb
109
+ - lib/extant/coercers/float.rb
110
+ - lib/extant/coercers/hash.rb
111
+ - lib/extant/coercers/integer.rb
112
+ - lib/extant/coercers/string.rb
113
+ - lib/extant/coercers/symbol.rb
114
+ - lib/extant/coercers/time.rb
115
+ - lib/extant/coercers/uuid.rb
116
+ - lib/extant/uncoerced_value.rb
117
+ - lib/extant/unset_value.rb
118
+ - lib/extant/version.rb
119
+ homepage:
120
+ licenses:
121
+ - MIT
122
+ metadata: {}
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ requirements: []
138
+ rubyforge_project:
139
+ rubygems_version: 2.0.14
140
+ signing_key:
141
+ specification_version: 4
142
+ summary: Extant, it helps you manage your attributes' existance.
143
+ test_files: []
144
+ has_rdoc: