value_semantics 2.1.0 → 3.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 17ee24bc8ffd744493e9957a4cb7ee0071f0c33aa8560b3ed36689575b9c0ab1
4
- data.tar.gz: 05da8d260966f9257578f0ebf3891ba447b51032709bb75b39bdacba3e081961
3
+ metadata.gz: f122fa566277c213c7eb2a31b38af94d4287b1688d91da91bd5eea8044a041ba
4
+ data.tar.gz: 371bc15f0cc7449042b19d5064e4a28f76ec1d6c0aae2c64622adf3252621045
5
5
  SHA512:
6
- metadata.gz: 4a4da5150969146f5fd8cb06a17f8e43b1c897cd40f228cdddd7b2a8367fdbbceeacc66843668bf74a48575d72f752d3f24fd101c2ac7e946335688a1eec95a3
7
- data.tar.gz: c0e71a37be6df7bcafa4833f7b7cea4304468818a4391e020770c6f85e16edaf68a56c84c572f3bd26399aa85b2dc149abb48660d82750a656d746d87da5a16a
6
+ metadata.gz: a7ebe03be2de318e43027cc4d27ed737111654a5d74c0646f62691076e0f51938eb55966a3f04105f4a4c86d242a0134ca3f5fafa27089aedd4c51f2fb45abd9
7
+ data.tar.gz: ac4e7a9f938e0bd9193d4260a8c211db6a05554463b6312a6409499a8d22c7a34b281093cf2c487676fefd58915b21027a47c99a75619fb2b80c457672ced57e
@@ -1,13 +1,25 @@
1
1
  language: ruby
2
+ script: bin/test
3
+
4
+ # test old Ruby versions WITHOUT mutation testing
2
5
  rvm:
3
- - 2.3.7
4
- - 2.4.4
5
- - 2.5.1
6
- script: bin/mutation_test.sh
6
+ - 2.3.8
7
+ - 2.4.10
8
+ - 2.5.8
9
+ - 2.6.6
10
+ env: MUTATION_TEST=false
11
+
12
+ # test the latest Ruby version WITH mutation testing
13
+ matrix:
14
+ include:
15
+ - rvm: 2.7.1
16
+ env: MUTATION_TEST=true
17
+
18
+ # deploy gem on tagged commits, on the latest Ruby version only
7
19
  deploy:
8
20
  provider: rubygems
9
21
  on:
10
22
  tags: true
11
- rvm: 2.5.1
23
+ env: MUTATION_TEST=true
12
24
  api_key:
13
25
  secure: nL74QuUczEpA0qbhSBN2zjGdviWgKB3wR6vFvwervv1MZNWmwOQUYe99Oq9kPeyc8/x2MR/H6PQm5qbrk/WAfRede01WxlZ/EBUW+9CYGrxcBsGONx9IULO8A0I8/yN/YJHW2vjo3dfR66EwVsXTVWq8U63PRRcwJIyTqnIiUm2sxauMQoPRBbXG+pD9v/EJSn3ugpdtxp0lVYDn8LDKk5Ho4/wbpY4ML11XUJa9mz9CyR/GsAzdy5FTXaDMOwuWOVEx9cab7m4qPOBhmlJY4TrmooFpxTxRwChcvByjq1IboEd2M3RT5on7Q/xDTlHSOuT0OS8mnS2AocGT4a1gC+W/xOlghgEcN+xs2V5mfucR6+iUYlCy32uz1w3ey7T2X5xN4ubut09r1xLi7eu1NisAoAc+GOJ4TIxQNqkeRhY4X/fs8j7SMfOEMDr6pPxSLKZxgSvExt+IbdcZD/uQ7rTBQkadYCbc9MX5dHazBievmar3ZsFffbIf+n13FVDXsaPgRt7DlFM5dqGrEwVwt1jFRhdFuDCjkj4QWOLn7E1uY3XqgrqGvgUBlF8Znwc6qicW8zxV4SIWhqIzCOH6L9WIZGLHNq0remoCd9sq9Ter9av3jL+6UmZRRAr+JceeZfZmsYIXKomECzleM9FXMx7FXlpjJKOlf3JnrfeCTwI=
@@ -0,0 +1,24 @@
1
+ # Changelog
2
+
3
+ Notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+
9
+ ## [3.2.1] - 2020-07-11
10
+ ### Fixed
11
+ - Fix warnings new to Ruby 2.7 about keyword arguments
12
+
13
+ ## [3.2.0] - 2019-09-30
14
+ ### Added
15
+ - `ValueSemantics::Struct`, a convenience for creating a new class and mixing
16
+ in ValueSemantics in a single step.
17
+
18
+ ## [3.1.0] - 2019-06-30
19
+ ### Added
20
+ - Built-in PP support for value classes
21
+
22
+ ## [3.0.0] - 2019-01-27
23
+
24
+ First public release
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ source 'https://oss:fLUos7k6c7Ak7zjhwbYphPJbwBk1Uuew@gem.mutant.dev' do
4
+ gem 'mutant-license'
5
+ end
4
6
 
5
7
  # Specify your gem's dependencies in the gemspec
6
8
  gemspec
data/README.md CHANGED
@@ -5,15 +5,20 @@
5
5
  ValueSemantics
6
6
  ==============
7
7
 
8
- Create value classes quickly, with all the [conventions of a good value object](https://github.com/zverok/good-value-object).
8
+ A gem for making value classes.
9
9
 
10
- Generates modules that provide value semantics for a given set of attributes.
11
- Provides the behaviour of an immutable struct-like value class,
12
- with light-weight validation and coercion.
10
+ Generates modules that provide [conventional value semantics](https://github.com/zverok/good-value-object) for a given set of attributes.
11
+ The behaviour is similar to an immutable `Struct` class,
12
+ plus extensible, lightweight validation and coercion.
13
13
 
14
14
  These are intended for internal use, as opposed to validating user input like ActiveRecord.
15
- Invalid or missing attributes cause an exception intended for developers,
16
- not an error message intended for the user.
15
+ Invalid or missing attributes cause an exception for developers,
16
+ not an error message intended for application users.
17
+
18
+ See the [announcement blog post][] for some of the rationale behind the gem, and some [discussion on Reddit].
19
+
20
+ [announcement blog post]: https://www.rubypigeon.com/posts/value-semantics-gem-for-making-value-classes/
21
+ [discussion on Reddit]: https://www.reddit.com/r/ruby/comments/akz4fs/valuesemanticsa_gem_for_making_value_classes/
17
22
 
18
23
 
19
24
  Defining and Creating Value Objects
@@ -103,7 +108,7 @@ Defaults
103
108
  --------
104
109
 
105
110
  Defaults can be specified in one of two ways:
106
- the `:default` option, or the `default_generator` option.
111
+ the `:default` option, or the `:default_generator` option.
107
112
 
108
113
  ```ruby
109
114
  class Cat
@@ -164,8 +169,8 @@ for common situations:
164
169
  class LightSwitch
165
170
  include ValueSemantics.for_attributes {
166
171
 
167
- # Boolean: only allows `true` or `false`
168
- on? Boolean()
172
+ # Bool: only allows `true` or `false`
173
+ on? Bool()
169
174
 
170
175
  # ArrayOf: validates elements in an array
171
176
  light_ids ArrayOf(Integer)
@@ -174,7 +179,7 @@ class LightSwitch
174
179
  color Either(Integer, String, nil)
175
180
 
176
181
  # these validators are composable
177
- wierd_attr Either(Boolean(), ArrayOf(Boolean()))
182
+ wierd_attr Either(Bool(), ArrayOf(Bool()))
178
183
  }
179
184
  end
180
185
 
@@ -299,6 +304,21 @@ For example, the default value could be a string,
299
304
  which would then be coerced into an `IPAddr` object.
300
305
 
301
306
 
307
+ ## ValueSemantics::Struct
308
+
309
+ This is a convenience for making a new class and including ValueSemantics in
310
+ one step, similar to how `Struct` works from the Ruby standard library. For
311
+ example:
312
+
313
+ ```ruby
314
+ Cat = ValueSemantics::Struct.new do
315
+ name String, default: "Mittens"
316
+ end
317
+
318
+ Cat.new.name #=> "Mittens"
319
+ ```
320
+
321
+
302
322
  ## Installation
303
323
 
304
324
  Add this line to your application's Gemfile:
@@ -321,6 +341,7 @@ Or install it yourself as:
321
341
  Bug reports and pull requests are welcome on GitHub at:
322
342
  https://github.com/tomdalling/value_semantics
323
343
 
344
+ Keep in mind that this gem aims to be as close to 100% backwards compatible as possible.
324
345
 
325
346
  ## License
326
347
 
@@ -0,0 +1,15 @@
1
+ #!/bin/bash
2
+ set -ue
3
+
4
+ MUTANT_PATTERN=${1:-ValueSemantics*}
5
+
6
+ # if $MUTATION_TEST is false, just run RSpec
7
+ if [[ "${MUTATION_TEST:-true}" == "false" ]] ; then
8
+ bundle exec rspec
9
+ else
10
+ bundle exec mutant \
11
+ --include lib \
12
+ --require value_semantics \
13
+ --use rspec "$MUTANT_PATTERN" \
14
+ --ignore-subject "ValueSemantics::Struct.new" # causes unfixable failure I don't want to deal with
15
+ fi
@@ -1,39 +1,80 @@
1
1
  module ValueSemantics
2
+ class Error < StandardError; end
3
+ class UnrecognizedAttributes < Error; end
4
+ class NoDefaultValue < Error; end
5
+ class MissingAttributes < Error; end
6
+
2
7
  NOT_SPECIFIED = Object.new.freeze
3
8
 
9
+ #
10
+ # Creates a module via the DSL
11
+ #
12
+ # @yield The block containing the DSL
13
+ # @return [Module]
14
+ #
15
+ # @see DSL
16
+ # @see InstanceMethods
17
+ #
4
18
  def self.for_attributes(&block)
5
- attributes = DSL.run(&block)
6
- generate_module(attributes.freeze)
19
+ recipe = DSL.run(&block)
20
+ bake_module(recipe)
7
21
  end
8
22
 
9
- def self.generate_module(attributes)
23
+ #
24
+ # Creates a module from a {Recipe}
25
+ #
26
+ # @param recipe [Recipe]
27
+ # @return [Module]
28
+ #
29
+ def self.bake_module(recipe)
10
30
  Module.new do
11
- # include all the instance methods
12
- include(Semantics)
31
+ const_set(:VALUE_SEMANTICS_RECIPE__, recipe)
32
+ include(InstanceMethods)
13
33
 
14
34
  # define the attr readers
15
- attributes.each do |attr|
35
+ recipe.attributes.each do |attr|
16
36
  module_eval("def #{attr.name}; #{attr.instance_variable}; end")
17
37
  end
18
38
 
19
- # define BaseClass.attributes class method
20
- const_set(:ATTRIBUTES__, attributes)
21
39
  def self.included(base)
22
- base.const_set(:ValueSemantics_Generated, self)
23
- class << base
24
- def attributes
25
- self::ATTRIBUTES__
26
- end
27
- end
40
+ base.const_set(:ValueSemantics_Attributes, self)
41
+ base.extend(ClassMethods)
28
42
  end
29
43
  end
30
44
  end
31
45
 
32
- module Semantics
46
+ #
47
+ # All the class methods available on ValueSemantics classes
48
+ #
49
+ # When a ValueSemantics module is included into a class,
50
+ # the class is extended by this module.
51
+ #
52
+ module ClassMethods
53
+ #
54
+ # @return [Recipe] the recipe used to build the ValueSemantics module that
55
+ # was included into this class.
56
+ #
57
+ def value_semantics
58
+ self::VALUE_SEMANTICS_RECIPE__
59
+ end
60
+ end
61
+
62
+ #
63
+ # All the instance methods available on ValueSemantics objects
64
+ #
65
+ module InstanceMethods
66
+ #
67
+ # Creates a value object based on a Hash of attributes
68
+ #
69
+ # @param given_attrs [Hash] a hash of attributes, with symbols for keys
70
+ # @raise [UnrecognizedAttributes] if given_attrs contains keys that are not attributes
71
+ # @raise [MissingAttributes] if given_attrs is missing any attributes that do not have defaults
72
+ # @raise [ArgumentError] if any attribute values do no pass their validators
73
+ #
33
74
  def initialize(given_attrs = {})
34
75
  remaining_attrs = given_attrs.dup
35
76
 
36
- self.class.attributes.each do |attr|
77
+ self.class.value_semantics.attributes.each do |attr|
37
78
  key, value = attr.determine_from!(remaining_attrs, self.class)
38
79
  instance_variable_set(attr.instance_variable, value)
39
80
  remaining_attrs.delete(key)
@@ -41,30 +82,54 @@ module ValueSemantics
41
82
 
42
83
  unless remaining_attrs.empty?
43
84
  unrecognised = remaining_attrs.keys.map(&:inspect).join(', ')
44
- raise ArgumentError, "Unrecognised attributes: #{unrecognised}"
85
+ raise UnrecognizedAttributes, "Unrecognized attributes: #{unrecognised}"
45
86
  end
46
87
  end
47
88
 
89
+ #
90
+ # Creates a copy of this object, with the given attributes changed (non-destructive update)
91
+ #
92
+ # @param new_attrs [Hash] the attributes to change
93
+ # @return A new object, with the attribute changes applied
94
+ #
48
95
  def with(new_attrs)
49
96
  self.class.new(to_h.merge(new_attrs))
50
97
  end
51
98
 
99
+ #
100
+ # @return [Hash] all of the attributes
101
+ #
52
102
  def to_h
53
- self.class.attributes
103
+ self.class.value_semantics.attributes
54
104
  .map { |attr| [attr.name, public_send(attr.name)] }
55
105
  .to_h
56
106
  end
57
107
 
108
+ #
109
+ # Loose equality
110
+ #
111
+ # @return [Boolean] whether all attributes are equal, and the object
112
+ # classes are ancestors of eachother in any way
113
+ #
58
114
  def ==(other)
59
115
  (other.is_a?(self.class) || is_a?(other.class)) && other.to_h.eql?(to_h)
60
116
  end
61
117
 
118
+ #
119
+ # Strict equality
120
+ #
121
+ # @return [Boolean] whether all attribuets are equal, and both objects
122
+ # has the exact same class
123
+ #
62
124
  def eql?(other)
63
125
  other.class.equal?(self.class) && other.to_h.eql?(to_h)
64
126
  end
65
127
 
128
+ #
129
+ # Unique-ish integer, based on attributes and class of the object
130
+ #
66
131
  def hash
67
- @__hash ||= (to_h.hash ^ self.class.hash)
132
+ to_h.hash ^ self.class.hash
68
133
  end
69
134
 
70
135
  def inspect
@@ -74,14 +139,32 @@ module ValueSemantics
74
139
 
75
140
  "#<#{self.class} #{attrs}>"
76
141
  end
142
+
143
+ def pretty_print(pp)
144
+ pp.object_group(self) do
145
+ to_h.each do |attr, value|
146
+ pp.breakable
147
+ pp.text("#{attr}=")
148
+ pp.pp(value)
149
+ end
150
+ end
151
+ end
77
152
  end
78
153
 
154
+ #
155
+ # Represents a single attribute of a value class
156
+ #
79
157
  class Attribute
80
- NO_DEFAULT_GENERATOR = ->{ raise "Attribute does not have a default value" }
158
+ NO_DEFAULT_GENERATOR = lambda do
159
+ raise NoDefaultValue, "Attribute does not have a default value"
160
+ end
81
161
 
82
162
  attr_reader :name, :validator, :coercer, :default_generator
83
163
 
84
- def initialize(name:, default_generator:, validator:, coercer:)
164
+ def initialize(name:,
165
+ default_generator: NO_DEFAULT_GENERATOR,
166
+ validator: Anything,
167
+ coercer: nil)
85
168
  @name = name.to_sym
86
169
  @default_generator = default_generator
87
170
  @validator = validator
@@ -89,10 +172,35 @@ module ValueSemantics
89
172
  freeze
90
173
  end
91
174
 
175
+ def self.define(name,
176
+ validator=Anything,
177
+ default: NOT_SPECIFIED,
178
+ default_generator: nil,
179
+ coerce: nil)
180
+ generator = begin
181
+ if default_generator && !default.equal?(NOT_SPECIFIED)
182
+ raise ArgumentError, "Attribute '#{name}' can not have both a :default and a :default_generator"
183
+ elsif default_generator
184
+ default_generator
185
+ elsif !default.equal?(NOT_SPECIFIED)
186
+ ->{ default }
187
+ else
188
+ NO_DEFAULT_GENERATOR
189
+ end
190
+ end
191
+
192
+ new(
193
+ name: name,
194
+ validator: validator,
195
+ default_generator: generator,
196
+ coercer: coerce,
197
+ )
198
+ end
199
+
92
200
  def determine_from!(attr_hash, klass)
93
201
  raw_value = attr_hash.fetch(name) do
94
202
  if default_generator.equal?(NO_DEFAULT_GENERATOR)
95
- raise ArgumentError, "Value missing for attribute '#{name}'"
203
+ raise MissingAttributes, "Value missing for attribute '#{name}'"
96
204
  else
97
205
  default_generator.call
98
206
  end
@@ -130,11 +238,38 @@ module ValueSemantics
130
238
  end
131
239
  end
132
240
 
241
+ #
242
+ # Contains all the configuration necessary to bake a ValueSemantics module
243
+ #
244
+ # @see ValueSemantics.bake_module
245
+ #
246
+ class Recipe
247
+ attr_reader :attributes
248
+
249
+ def initialize(attributes:)
250
+ @attributes = attributes
251
+ freeze
252
+ end
253
+ end
254
+
255
+ #
256
+ # Builds a {Recipe} via DSL methods
257
+ #
258
+ # DSL blocks are <code>instance_eval</code>d against an object of this class.
259
+ #
260
+ # @see Recipe
261
+ # @see ValueSemantics.for_attributes
262
+ #
133
263
  class DSL
264
+ #
265
+ # Builds a {Recipe} from a DSL block
266
+ #
267
+ # @yield to the block containing the DSL
268
+ # @return [Recipe]
134
269
  def self.run(&block)
135
270
  dsl = new
136
271
  dsl.instance_eval(&block)
137
- dsl.__attributes
272
+ Recipe.new(attributes: dsl.__attributes.freeze)
138
273
  end
139
274
 
140
275
  attr_reader :__attributes
@@ -143,8 +278,8 @@ module ValueSemantics
143
278
  @__attributes = []
144
279
  end
145
280
 
146
- def Boolean
147
- Boolean
281
+ def Bool
282
+ Bool
148
283
  end
149
284
 
150
285
  def Either(*subvalidators)
@@ -159,60 +294,47 @@ module ValueSemantics
159
294
  ArrayOf.new(element_validator)
160
295
  end
161
296
 
162
- def def_attr(attr_name,
163
- validator=Anything,
164
- default: NOT_SPECIFIED,
165
- default_generator: nil,
166
- coerce: nil
167
- )
168
- generator = begin
169
- if default_generator && !default.equal?(NOT_SPECIFIED)
170
- raise ArgumentError, "Attribute '#{attr_name}' can not have both a default, and a default_generator"
171
- elsif default_generator
172
- default_generator
173
- elsif !default.equal?(NOT_SPECIFIED)
174
- ->{ default }
175
- else
176
- Attribute::NO_DEFAULT_GENERATOR
177
- end
178
- end
179
-
180
- __attributes << Attribute.new(
181
- name: attr_name,
182
- validator: validator,
183
- default_generator: generator,
184
- coercer: coerce
185
- )
297
+ def def_attr(*args, **kwargs)
298
+ __attributes << Attribute.define(*args, **kwargs)
186
299
  end
187
300
 
188
- def method_missing(name, *args)
301
+ def method_missing(name, *args, **kwargs)
189
302
  if respond_to_missing?(name)
190
- def_attr(name, *args)
303
+ def_attr(name, *args, **kwargs)
191
304
  else
192
305
  super
193
306
  end
194
307
  end
195
308
 
196
309
  def respond_to_missing?(method_name, _include_private=nil)
197
- first_letter = method_name[0]
310
+ first_letter = method_name.to_s.each_char.first
198
311
  first_letter.eql?(first_letter.downcase)
199
312
  end
200
313
  end
201
314
 
202
- module Boolean
203
- extend self
204
-
205
- def ===(value)
315
+ #
316
+ # Validator that only matches `true` and `false`
317
+ #
318
+ module Bool
319
+ # @return [Boolean]
320
+ def self.===(value)
206
321
  true.equal?(value) || false.equal?(value)
207
322
  end
208
323
  end
209
324
 
325
+ #
326
+ # Validator that matches any and all values
327
+ #
210
328
  module Anything
329
+ # @return [true]
211
330
  def self.===(_)
212
331
  true
213
332
  end
214
333
  end
215
334
 
335
+ #
336
+ # Validator that matches if any of the given subvalidators matches
337
+ #
216
338
  class Either
217
339
  attr_reader :subvalidators
218
340
 
@@ -221,11 +343,15 @@ module ValueSemantics
221
343
  freeze
222
344
  end
223
345
 
346
+ # @return [Boolean]
224
347
  def ===(value)
225
348
  subvalidators.any? { |sv| sv === value }
226
349
  end
227
350
  end
228
351
 
352
+ #
353
+ # Validator that matches arrays if each element matches a given subvalidator
354
+ #
229
355
  class ArrayOf
230
356
  attr_reader :element_validator
231
357
 
@@ -234,9 +360,28 @@ module ValueSemantics
234
360
  freeze
235
361
  end
236
362
 
363
+ # @return [Boolean]
237
364
  def ===(value)
238
365
  Array === value && value.all? { |element| element_validator === element }
239
366
  end
240
367
  end
241
368
 
369
+ #
370
+ # ValueSemantics equivalent of the Struct class from the Ruby standard
371
+ # library
372
+ #
373
+ class Struct
374
+ #
375
+ # Creates a new Class with ValueSemantics mixed in
376
+ #
377
+ # @yield a block containing ValueSemantics DSL
378
+ # @return [Class] the newly created class
379
+ #
380
+ def self.new(&block)
381
+ klass = Class.new
382
+ klass.include(ValueSemantics.for_attributes(&block))
383
+ klass
384
+ end
385
+ end
386
+
242
387
  end
@@ -1,3 +1,3 @@
1
1
  module ValueSemantics
2
- VERSION = "2.1.0"
2
+ VERSION = "3.2.1"
3
3
  end
@@ -9,13 +9,11 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Tom Dalling"]
10
10
  spec.email = [["tom", "@", "tomdalling.com"].join]
11
11
 
12
- spec.summary = %q{Create value classes quickly, with all the proper conventions.}
12
+ spec.summary = %q{Makes value classes, with lightweight validation and coercion.}
13
13
  spec.description = %q{
14
- Create value classes quickly, with all the proper conventions.
15
-
16
- Generates modules that provide value semantics for a given set of attributes.
17
- Provides the behaviour of an immutable struct-like value class,
18
- with light-weight validation and coercion.
14
+ Generates modules that provide conventional value semantics for a given set of attributes.
15
+ The behaviour is similar to an immutable `Struct` class,
16
+ plus extensible, lightweight validation and coercion.
19
17
  }
20
18
  spec.homepage = "https://github.com/tomdalling/value_semantics"
21
19
  spec.license = "MIT"
@@ -27,9 +25,10 @@ Gem::Specification.new do |spec|
27
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
26
  spec.require_paths = ["lib"]
29
27
 
30
- spec.add_development_dependency "bundler", "~> 1.15"
31
- spec.add_development_dependency "rspec", "~> 3.7.0"
28
+ spec.add_development_dependency "bundler", ">= 1.15"
29
+ spec.add_development_dependency "rspec", "~> 3.7"
32
30
  spec.add_development_dependency "mutant-rspec"
31
+ spec.add_development_dependency "yard"
33
32
  spec.add_development_dependency "byebug"
34
33
  spec.add_development_dependency "gem-release"
35
34
  end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: value_semantics
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 3.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Dalling
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-21 00:00:00.000000000 Z
11
+ date: 2020-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.15'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.15'
27
27
  - !ruby/object:Gem::Dependency
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 3.7.0
33
+ version: '3.7'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 3.7.0
40
+ version: '3.7'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: mutant-rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
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'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: byebug
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -80,10 +94,9 @@ dependencies:
80
94
  - - ">="
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0'
83
- description: "\n Create value classes quickly, with all the proper conventions.\n\n
84
- \ Generates modules that provide value semantics for a given set of attributes.\n
85
- \ Provides the behaviour of an immutable struct-like value class,\n with light-weight
86
- validation and coercion.\n "
97
+ description: "\n Generates modules that provide conventional value semantics for
98
+ a given set of attributes.\n The behaviour is similar to an immutable `Struct`
99
+ class,\n plus extensible, lightweight validation and coercion.\n "
87
100
  email:
88
101
  - tom@tomdalling.com
89
102
  executables: []
@@ -93,12 +106,13 @@ files:
93
106
  - ".gitignore"
94
107
  - ".rspec"
95
108
  - ".travis.yml"
109
+ - CHANGELOG.md
96
110
  - Gemfile
97
111
  - LICENSE.txt
98
112
  - README.md
99
113
  - bin/console
100
- - bin/mutation_test.sh
101
114
  - bin/setup
115
+ - bin/test
102
116
  - lib/value_semantics.rb
103
117
  - lib/value_semantics/version.rb
104
118
  - value_semantics.gemspec
@@ -121,8 +135,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
135
  - !ruby/object:Gem::Version
122
136
  version: '0'
123
137
  requirements: []
124
- rubygems_version: 3.0.0
138
+ rubyforge_project:
139
+ rubygems_version: 2.7.7
125
140
  signing_key:
126
141
  specification_version: 4
127
- summary: Create value classes quickly, with all the proper conventions.
142
+ summary: Makes value classes, with lightweight validation and coercion.
128
143
  test_files: []
@@ -1,6 +0,0 @@
1
- #!/bin/sh
2
- set -ue
3
-
4
- PATTERN=${1:-ValueSemantics*}
5
-
6
- bundle exec mutant --include lib --require value_semantics --use rspec "$PATTERN"