value_class 0.1.0.pre.prerelease2

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
+ SHA256:
3
+ metadata.gz: e3ea3aec695d36750ca2629b6348ae5ea195f7d0225b415051b2bf6df665faf5
4
+ data.tar.gz: d90ca345053f89ff2f3db5ea88ee5ea887aa4ca1633743cb09eff1e6c40391cb
5
+ SHA512:
6
+ metadata.gz: 56047ca389a9e46e4d78498e1b65906363efb0ff20942389157504a7044ae9e508d7b9e74adcc57c533b15c524103502fb4b2e804d86301c7bcc794af97c0379
7
+ data.tar.gz: 3549fe478d4177a84cd2f97c5863f60e17b192a074acdc95c0f5c37f4acde03ffc320e4d7a8c3e385ac2e1811ab5bbe521c7618e5b2bb066324acd971e8f9b69
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /.idea/
10
+ spec/reports/*
11
+ .rubocop-http*
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/groovy
2
+ @Library('jenkins-pipeline@v0.4.5')
3
+ import com.invoca.docker.*;
4
+
5
+ pipeline {
6
+ agent {
7
+ kubernetes {
8
+ defaultContainer "ruby"
9
+ yamlFile ".jenkins/ruby_build_pod.yml"
10
+ }
11
+ }
12
+
13
+ environment {
14
+ GITHUB_TOKEN = credentials('github_token')
15
+ GITHUB_KEY = credentials('github_key')
16
+ BUNDLE_GEM__FURY__IO = credentials('gemfury_deploy_token')
17
+ }
18
+
19
+ stages {
20
+ stage('Setup') {
21
+ steps {
22
+ script {
23
+ sh '''
24
+ # get SSH setup inside the container
25
+ eval `ssh-agent -s`
26
+ echo "$GITHUB_KEY" | ssh-add -
27
+ mkdir -p /root/.ssh
28
+ ssh-keyscan -t rsa github.com > /root/.ssh/known_hosts
29
+ bundle install
30
+ '''
31
+ }
32
+ }
33
+ }
34
+
35
+ stage('Unit Test') {
36
+ steps {
37
+ script {
38
+ sh 'bundle exec rspec --format RspecJunitFormatter --out spec/reports/rspec.xml'
39
+ }
40
+ }
41
+
42
+ post {
43
+ always { junit 'spec/reports/rspec.xml' }
44
+ success { updateGitHubStatus('clean-build', 'success', 'Unit tests.') }
45
+ failure { updateGitHubStatus('clean-build', 'failure', 'Unit tests.') }
46
+ }
47
+ }
48
+ }
49
+ }
50
+
51
+ void updateGitHubStatus(String context, String status, String description) {
52
+ gitHubStatus([
53
+ repoSlug: 'Invoca/value_class',
54
+ sha: env.GIT_COMMIT,
55
+ description: description,
56
+ context: context,
57
+ targetURL: env.BUILD_URL,
58
+ token: env.GITHUB_TOKEN,
59
+ status: status
60
+ ])
61
+ }
@@ -0,0 +1,19 @@
1
+ ---
2
+ apiVersion: v1
3
+ kind: Pod
4
+ metadata:
5
+ labels:
6
+ jenkins/active-table-set: 'true'
7
+ namespace: jenkins
8
+ name: active-table-set
9
+ spec:
10
+ containers:
11
+ - name: ruby
12
+ image: ruby:2.6.1
13
+ tty: true
14
+ resources:
15
+ requests:
16
+ memory: "100Mi"
17
+ command:
18
+ - cat
19
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,5 @@
1
+ # This rubocop config file inherits from our centralized style-guide repository.
2
+ # If you are looking to update the ruby style guide, be sure to both update the rubocop config
3
+ # as well as the README.md
4
+ # https://github.com/Invoca/style-guide/tree/master/ruby
5
+ inherit_from: https://raw.githubusercontent.com/Invoca/style-guide/master/ruby/.rubocop.yml
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.6.1
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # CHANGELOG for `value_class`
2
+
3
+ Inspired by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
4
+
5
+ Note: this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [0.1.0]
8
+
9
+ ### Changed
10
+
11
+ - Cloned from Active Table Set
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source 'https://rubygems.org'
2
+ source 'https://gem.fury.io/invoca'
3
+
4
+ # Specify your gem's dependencies in value_class.gemspec
5
+ gemspec
6
+
7
+ group :development do
8
+ gem 'bundler', '~> 1.8'
9
+ gem 'pry'
10
+ gem 'pry-byebug'
11
+ gem 'rake', '~> 13.0'
12
+ gem 'rspec', '~> 3.7'
13
+ gem 'rspec-mocks', '~> 3.7'
14
+ gem 'rspec_junit_formatter'
15
+ gem 'rubocop', '0.74.0'
16
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,69 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ value_class (0.1.0.pre.prerelease2)
5
+ attr_comparable
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ remote: https://gem.fury.io/invoca/
10
+ specs:
11
+ ast (2.4.0)
12
+ attr_comparable (0.2.0)
13
+ byebug (10.0.2)
14
+ coderay (1.1.2)
15
+ diff-lcs (1.3)
16
+ jaro_winkler (1.5.4)
17
+ method_source (0.9.0)
18
+ parallel (1.19.1)
19
+ parser (2.7.1.1)
20
+ ast (~> 2.4.0)
21
+ pry (0.11.3)
22
+ coderay (~> 1.1.0)
23
+ method_source (~> 0.9.0)
24
+ pry-byebug (3.6.0)
25
+ byebug (~> 10.0)
26
+ pry (~> 0.10)
27
+ rainbow (3.0.0)
28
+ rake (13.0.1)
29
+ rspec (3.7.0)
30
+ rspec-core (~> 3.7.0)
31
+ rspec-expectations (~> 3.7.0)
32
+ rspec-mocks (~> 3.7.0)
33
+ rspec-core (3.7.1)
34
+ rspec-support (~> 3.7.0)
35
+ rspec-expectations (3.7.0)
36
+ diff-lcs (>= 1.2.0, < 2.0)
37
+ rspec-support (~> 3.7.0)
38
+ rspec-mocks (3.7.0)
39
+ diff-lcs (>= 1.2.0, < 2.0)
40
+ rspec-support (~> 3.7.0)
41
+ rspec-support (3.7.1)
42
+ rspec_junit_formatter (0.4.1)
43
+ rspec-core (>= 2, < 4, != 2.12.0)
44
+ rubocop (0.74.0)
45
+ jaro_winkler (~> 1.5.1)
46
+ parallel (~> 1.10)
47
+ parser (>= 2.6)
48
+ rainbow (>= 2.2.2, < 4.0)
49
+ ruby-progressbar (~> 1.7)
50
+ unicode-display_width (>= 1.4.0, < 1.7)
51
+ ruby-progressbar (1.10.1)
52
+ unicode-display_width (1.6.1)
53
+
54
+ PLATFORMS
55
+ ruby
56
+
57
+ DEPENDENCIES
58
+ bundler (~> 1.8)
59
+ pry
60
+ pry-byebug
61
+ rake (~> 13.0)
62
+ rspec (~> 3.7)
63
+ rspec-mocks (~> 3.7)
64
+ rspec_junit_formatter
65
+ rubocop (= 0.74.0)
66
+ value_class!
67
+
68
+ BUNDLED WITH
69
+ 1.17.2
data/README.md ADDED
@@ -0,0 +1,100 @@
1
+ # ValueClass
2
+
3
+ Provides a simple mechanism for declaring a class with complex attributes. Instances of the class can be progressively
4
+ constructed in a using a block. The class is immutable outside of the block. This is useful for building simple
5
+ configuration DSLs.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'value_class'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install value_class
22
+
23
+ ## Usage
24
+
25
+ The following class declaration allow a bicycle to be declared:
26
+
27
+ ```ruby
28
+ class BikeTire
29
+ include ValueClass::Constructable
30
+
31
+ value_attr :diameter, description: "The diameter in inches"
32
+ value_attr :tred, description: "The tred on the tire"
33
+ end
34
+
35
+ class BikeSeat
36
+ include ValueClass::Constructable
37
+
38
+ value_attr :size, description: "The size of the bike seat in inches"
39
+ value_attr :color
40
+ end
41
+
42
+ class Bicycle
43
+ include ValueClass::Constructable
44
+
45
+ value_description "For riding around town"
46
+ value_attr :speeds
47
+ value_attr :color, default: :orange
48
+ value_attr :seat, class_name: 'BikeSeat'
49
+
50
+ value_list_attr :riders, insert_method: :add_rider
51
+ value_list_attr :tires, insert_method: :tire, class_name: 'BikeTire'
52
+ end
53
+ ```
54
+
55
+ Given the above declarations, you can then configure a bicycle with the following code.
56
+
57
+ ```ruby
58
+ bike = Bicycle.config do |bicycle|
59
+ bicycle.speeds 10
60
+ bicycle.color :blue
61
+ bicycle.seat do |seat|
62
+ seat.color :green
63
+ seat.size :large
64
+ end
65
+ end
66
+ ```
67
+
68
+ You can also directly declare the class:
69
+
70
+ ```ruby
71
+ bike = Bicycle.new(speeds: 10, color: :gold, tires: [{ diameter: 40, tred: :mountain }, { diameter: 50, tred: :slicks }])
72
+ ```
73
+
74
+ If you have a simple class, ValueClass provides a replacement for ruby struct that allows for a quick class declaration.
75
+
76
+ ```ruby
77
+
78
+ Gears = ValueClass.struct(:first_gear, :second_gear, :third_gear, default: 200)
79
+ gear = Gears.new(first_gear: 20)
80
+ ```
81
+
82
+ Once an instance of a class is returned. It is immutable: it is frozen and all if its attributes are frozen.
83
+
84
+ ### Running Tests
85
+
86
+ Tests in this gem are written in Rspec and can be executed through the main rake task for the repo
87
+ ```bash
88
+ bundle exec rake
89
+ ```
90
+
91
+ If there is a subset of tests you would like to run, you can add the `focus: true` tag to the test or context to only run the subset of tests.
92
+
93
+ ## Contributing
94
+
95
+ 1. Fork it ( https://github.com/invoca/value_class/fork )
96
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
97
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
98
+ 4. Push to the branch (`git push origin my-new-feature`)
99
+ 4. Make sure the tests pass: `rspec spec`
100
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env rake
2
+ # frozen_string_literal: true
3
+
4
+ require 'rspec/core/rake_task'
5
+
6
+ Bundler::GemHelper.install_tasks
7
+
8
+ RSpec::Core::RakeTask.new(:spec)
9
+
10
+ task :rubocop do
11
+ puts "rubocop"
12
+ rubocop_output = `rubocop -a app lib test`
13
+ print rubocop_output
14
+ unless rubocop_output.match(/files inspected, no offenses detected/)
15
+ exit 1
16
+ end
17
+ end
18
+
19
+ task default: [:spec, :rubocop]
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ValueClass
4
+ class Attribute
5
+ attr_reader :name, :options, :limit
6
+
7
+ OPTIONS = {
8
+ description: "A description of the attribute.",
9
+ default: "The default value for this parameter.",
10
+ class_name: "The name of the value class for this attribute. Allows for construction from a nested hash.",
11
+ list_of_class: "Used to declare an attribute that is a list of a class.",
12
+ required: "If true, the parameter is required",
13
+ limit: "The set of valid values",
14
+ insert_method: "The name of the method to create to allow inserting into a list during progressive construction"
15
+ }.freeze
16
+
17
+ def initialize(name, options)
18
+ if (invalid_options = options.keys - OPTIONS.keys).any?
19
+ raise ArgumentError, "Unknown option(s): #{invalid_options.join(',')}"
20
+ end
21
+
22
+ @name = name.to_sym.freeze
23
+ @options = options.freeze
24
+ @limit = options[:limit]
25
+ end
26
+
27
+ def description(prefix = "")
28
+ if options[:description]
29
+ "#{prefix}#{name}: #{options[:description]}"
30
+ else
31
+ "#{prefix}#{name}"
32
+ end
33
+ end
34
+
35
+ def get_value(config)
36
+ raw_value = raw_value(config)
37
+
38
+ cast_value = cast_value(raw_value)
39
+
40
+ if cast_value.nil? && options[:required]
41
+ raise ArgumentError, "must provide a value for #{name}"
42
+ end
43
+
44
+ if !cast_value.nil? && limit && !limit.include?(cast_value)
45
+ raise ArgumentError, "invalid value #{cast_value.inspect} for #{name}. allowed values #{limit.inspect}"
46
+ end
47
+
48
+ if cast_value.nil?
49
+ default
50
+ else
51
+ cast_value
52
+ end
53
+ end
54
+
55
+ def hash_value(raw_value)
56
+ if options[:list_of_class] && raw_value.is_a?(Array)
57
+ raw_value.map(&:to_hash)
58
+ elsif options[:class_name] && raw_value
59
+ raw_value.to_hash
60
+ else
61
+ raw_value
62
+ end
63
+ end
64
+
65
+ def default
66
+ value = options[:default]
67
+ begin
68
+ value.dup
69
+ rescue TypeError
70
+ value
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ def cast_value(raw_value)
77
+ if options[:list_of_class] && raw_value.is_a?(Array)
78
+ inner_class = options[:list_of_class]
79
+ raw_value.map { |v| Object.const_get(inner_class).new(v).freeze }
80
+ elsif options[:class_name] && raw_value
81
+ Object.const_get(options[:class_name]).new(raw_value).freeze
82
+ else
83
+ raw_value
84
+ end
85
+ end
86
+
87
+ def raw_value(config)
88
+ if config.is_a?(Hash)
89
+ config[name]
90
+ else
91
+ config.send(name)
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ValueClass
4
+ module Constructable
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ base.include(ValueClass)
8
+ end
9
+
10
+ def clone_config
11
+ config = self.class.config_class.new
12
+ self.class.value_attributes.each do |attr|
13
+ current_value = send(attr.name)
14
+ dup_value =
15
+ begin
16
+ current_value.dup
17
+ rescue TypeError
18
+ current_value
19
+ end
20
+ config.send("#{attr.name}=", dup_value)
21
+ end
22
+ yield config
23
+ self.class.new(config)
24
+ end
25
+
26
+ module ClassMethods
27
+ # Constructs an instance using the configuration created in the passed in block.
28
+ def config
29
+ config = config_class.new
30
+ value_attributes.each do |attr|
31
+ if attr.default
32
+ config.send("#{attr.name}=", attr.default)
33
+ end
34
+ end
35
+ yield config
36
+ new(config)
37
+ end
38
+
39
+ def config_class
40
+ unless @config_class
41
+ @config_class = Class.new
42
+
43
+ value_attributes.each do |attribute|
44
+ # Define assignment operator
45
+ @config_class.send(:attr_writer, attribute.name)
46
+
47
+ define_accessor(attribute)
48
+ if (insert_method = attribute.options[:insert_method])
49
+ define_insert(attribute, insert_method)
50
+ end
51
+ end
52
+ end
53
+ @config_class
54
+ end
55
+
56
+ private
57
+
58
+ def define_insert(attribute, insert_method)
59
+ if (class_name = attribute.options[:list_of_class])
60
+ config_class.class_eval <<-EORUBY, __FILE__, __LINE__ + 1
61
+ def #{insert_method}(value=nil, &blk)
62
+ if blk
63
+ @#{attribute.name} << #{class_name}.config { |config| yield config }
64
+ else
65
+ @#{attribute.name} << #{class_name}.new(value)
66
+ end
67
+ @#{attribute.name}
68
+ end
69
+ EORUBY
70
+ else
71
+ config_class.class_eval <<-EORUBY, __FILE__, __LINE__ + 1
72
+ def #{insert_method}(value)
73
+ @#{attribute.name} << value
74
+ @#{attribute.name}
75
+ end
76
+ EORUBY
77
+ end
78
+ end
79
+
80
+ def define_accessor(attribute)
81
+ if (class_name = attribute.options[:class_name])
82
+ config_class.class_eval <<-EORUBY, __FILE__, __LINE__ + 1
83
+ def #{attribute.name}(&blk)
84
+ if blk
85
+ @#{attribute.name} = #{class_name}.config { |config| yield config }
86
+ end
87
+ @#{attribute.name}
88
+ end
89
+ EORUBY
90
+ else
91
+ config_class.class_eval <<-EORUBY, __FILE__, __LINE__ + 1
92
+ def #{attribute.name}(value = nil)
93
+ unless value.nil?
94
+ @#{attribute.name} = value
95
+ end
96
+ @#{attribute.name}
97
+ end
98
+ EORUBY
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ValueClass
4
+ VERSION = "0.1.0-prerelease2"
5
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'attr_comparable'
4
+ require 'value_class/attribute'
5
+
6
+ module ValueClass
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ # Default constructor
12
+ def initialize(config = {})
13
+ check_constructor_params(config)
14
+ self.class.declare_comparison_operators
15
+ self.class.value_attributes.each do |attribute|
16
+ instance_variable_set("@#{attribute.name}", attribute.get_value(config).freeze)
17
+ end
18
+ end
19
+
20
+ # TODO: These need to be added to attr_comparible
21
+ def eql?(other)
22
+ self == other
23
+ end
24
+
25
+ def hash
26
+ self.class.value_attributes.map do |attribute|
27
+ instance_variable_get("@#{attribute.name}")
28
+ end.hash
29
+ end
30
+
31
+ def to_hash
32
+ self.class.value_attributes.each_with_object({}) do |attribute, hash|
33
+ # Attributes are frozen, but hash with indifferent access mutates values (!!!), so we have to dup
34
+ # in order to get a value we can use
35
+ unsafe_version = attribute.hash_value(instance_variable_get("@#{attribute.name}"))
36
+ safe_version =
37
+ begin
38
+ unsafe_version.dup
39
+ rescue TypeError
40
+ unsafe_version
41
+ end
42
+
43
+ hash[attribute.name.to_sym] = safe_version
44
+ end
45
+ end
46
+
47
+ def self.struct(*args)
48
+ Class.new do
49
+ include ValueClass::Constructable
50
+ value_attrs(*args)
51
+ end
52
+ end
53
+
54
+ protected
55
+
56
+ def check_constructor_params(config)
57
+ if config.is_a?(Hash)
58
+ extra_keys = config.keys - self.class.value_attributes.map(&:name)
59
+ extra_keys.empty? or raise ArgumentError, "unknown attribute #{extra_keys.join(', ')}"
60
+ end
61
+ end
62
+
63
+ module ClassMethods
64
+ def value_description(value = nil)
65
+ if value
66
+ @value_description = value
67
+ end
68
+ @value_description
69
+ end
70
+
71
+ def value_list_attr(attribute_name, options = {})
72
+ value_attr(attribute_name, options.merge(default: [], class_name: nil, list_of_class: options[:class_name]))
73
+ end
74
+
75
+ def value_attr(attribute_name, options = {})
76
+ attribute = Attribute.new(attribute_name, options)
77
+ value_attributes << attribute
78
+
79
+ attr_reader(attribute.name)
80
+ end
81
+
82
+ def value_attrs(*args)
83
+ options = args.last.is_a?(::Hash) ? args.pop : {}
84
+ args.each { |arg| value_attr(arg, options) }
85
+ end
86
+
87
+ def config_help(prefix = "")
88
+ [
89
+ "#{name}: #{value_description}",
90
+ " attributes:",
91
+ value_attributes.map { |ca| ca.description(prefix + " ") }
92
+ ].flatten.join("\n") + "\n"
93
+ end
94
+
95
+ def value_attributes
96
+ @value_attributes ||= []
97
+ end
98
+
99
+ def declare_comparison_operators
100
+ unless @comparison_operators_declared
101
+ @comparison_operators_declared = true
102
+
103
+ include AttrComparable
104
+ attr_compare(value_attributes.map(&:name))
105
+ end
106
+ end
107
+
108
+ def inherited(new_child_class)
109
+ value_attributes.each { |attr| new_child_class.value_attributes << attr }
110
+ end
111
+ end
112
+ end
113
+
114
+ # These build off of the above, so they are required last
115
+ require 'value_class/constructable'
@@ -0,0 +1,21 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'value_class/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "value_class"
7
+ spec.version = ValueClass::VERSION
8
+ spec.authors = ["Bob Smith"]
9
+ spec.email = ["bob@invoca.com"]
10
+
11
+ spec.summary = %q{ValueClass a lightweight way to define configuration DSLs.}
12
+ spec.description = %q{ValueClass provides an interface to declare simple classes that can be progressively constructed but that are imutable afterwards.}
13
+ spec.homepage = "https://github.com/invoca/value_class"
14
+ spec.license = ""
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency 'attr_comparable'
21
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: value_class
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.pre.prerelease2
5
+ platform: ruby
6
+ authors:
7
+ - Bob Smith
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-04-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: attr_comparable
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: ValueClass provides an interface to declare simple classes that can be
28
+ progressively constructed but that are imutable afterwards.
29
+ email:
30
+ - bob@invoca.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".gitignore"
36
+ - ".jenkins/Jenkinsfile"
37
+ - ".jenkins/ruby_build_pod.yml"
38
+ - ".rspec"
39
+ - ".rubocop.yml"
40
+ - ".ruby-version"
41
+ - ".travis.yml"
42
+ - CHANGELOG.md
43
+ - Gemfile
44
+ - Gemfile.lock
45
+ - README.md
46
+ - Rakefile
47
+ - lib/value_class.rb
48
+ - lib/value_class/attribute.rb
49
+ - lib/value_class/constructable.rb
50
+ - lib/value_class/version.rb
51
+ - value_class.gemspec
52
+ homepage: https://github.com/invoca/value_class
53
+ licenses:
54
+ - ''
55
+ metadata: {}
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">"
68
+ - !ruby/object:Gem::Version
69
+ version: 1.3.1
70
+ requirements: []
71
+ rubygems_version: 3.0.1
72
+ signing_key:
73
+ specification_version: 4
74
+ summary: ValueClass a lightweight way to define configuration DSLs.
75
+ test_files: []