safe_values 1.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 +7 -0
- data/.circleci/config.yml +94 -0
- data/.gitignore +10 -0
- data/.rspec +1 -0
- data/.travis.yml +13 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +35 -0
- data/Rakefile +7 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/safe_values.rb +5 -0
- data/lib/safe_values/version.rb +3 -0
- data/lib/value.rb +127 -0
- data/safe_values.gemspec +26 -0
- metadata +99 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ba03abf1ce02d1e319edf07d93dfdd9c95c7985a03085a964b75159672483143
|
4
|
+
data.tar.gz: 1aa9bb295da60cca721fdbb3c8826399845159c4ea5ef7364e3c1cd999494b20
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5848e9df32a06a5a611f8bdc6cc47f1ffec2edcd989c10a834fbaa57588b0a42d73df9f327fd8776fe4c8e2772b8e785f32653ebc713d861ed4d8c84ff044017
|
7
|
+
data.tar.gz: 7b830c4a56c889e7c64cfeb7bfabfcdc3a90b6b53c27fb99d621ef3cf7e4e1accd745ecaf2e26a19031a19d98b171aa4873797f6eada6c384b2a96cfcb76aef2
|
@@ -0,0 +1,94 @@
|
|
1
|
+
version: 2.1
|
2
|
+
|
3
|
+
executors:
|
4
|
+
ruby:
|
5
|
+
parameters:
|
6
|
+
ruby-version:
|
7
|
+
type: string
|
8
|
+
default: "2.6"
|
9
|
+
gemfile:
|
10
|
+
type: string
|
11
|
+
default: "Gemfile"
|
12
|
+
docker:
|
13
|
+
- image: circleci/ruby:<< parameters.ruby-version >>
|
14
|
+
environment:
|
15
|
+
BUNDLE_JOBS: 3
|
16
|
+
BUNDLE_RETRY: 3
|
17
|
+
BUNDLE_PATH: vendor/bundle
|
18
|
+
RAILS_ENV: test
|
19
|
+
BUNDLE_GEMFILE: << parameters.gemfile >>
|
20
|
+
|
21
|
+
jobs:
|
22
|
+
test:
|
23
|
+
parameters:
|
24
|
+
ruby-version:
|
25
|
+
type: string
|
26
|
+
executor:
|
27
|
+
name: ruby
|
28
|
+
ruby-version: << parameters.ruby-version >>
|
29
|
+
parallelism: 1
|
30
|
+
steps:
|
31
|
+
- checkout
|
32
|
+
|
33
|
+
- run:
|
34
|
+
# Remove the non-appraisal gemfile for safety: we never want to use it.
|
35
|
+
name: Prepare bundler
|
36
|
+
command: bundle -v
|
37
|
+
|
38
|
+
- run:
|
39
|
+
name: Compute a gemfile lock
|
40
|
+
command: bundle lock && cp "${BUNDLE_GEMFILE}.lock" /tmp/gem-lock
|
41
|
+
|
42
|
+
- restore_cache:
|
43
|
+
keys:
|
44
|
+
- safe_values-<< parameters.ruby-version >>-{{ checksum "/tmp/gem-lock" }}
|
45
|
+
- safe_values-
|
46
|
+
|
47
|
+
- run:
|
48
|
+
name: Bundle Install
|
49
|
+
command: bundle check || bundle install
|
50
|
+
|
51
|
+
- save_cache:
|
52
|
+
key: safe_values-<< parameters.ruby-version >>-{{ checksum "/tmp/gem-lock" }}
|
53
|
+
paths:
|
54
|
+
- vendor/bundle
|
55
|
+
|
56
|
+
- run:
|
57
|
+
name: Run rspec
|
58
|
+
command: bundle exec rspec --profile 10 --format RspecJunitFormatter --out test_results/rspec.xml --format progress
|
59
|
+
|
60
|
+
- store_test_results:
|
61
|
+
path: test_results
|
62
|
+
|
63
|
+
publish:
|
64
|
+
executor: ruby
|
65
|
+
steps:
|
66
|
+
- checkout
|
67
|
+
- run:
|
68
|
+
name: Setup Rubygems
|
69
|
+
command: |
|
70
|
+
mkdir ~/.gem &&
|
71
|
+
echo -e "---\r\n:rubygems_api_key: $RUBYGEMS_API_KEY" > ~/.gem/credentials &&
|
72
|
+
chmod 0600 ~/.gem/credentials
|
73
|
+
- run:
|
74
|
+
name: Publish to Rubygems
|
75
|
+
command: |
|
76
|
+
gem build safe_values.gemspec
|
77
|
+
gem push safe_values-*.gem
|
78
|
+
|
79
|
+
workflows:
|
80
|
+
version: 2.1
|
81
|
+
build:
|
82
|
+
jobs:
|
83
|
+
- test:
|
84
|
+
name: 'ruby 2.5'
|
85
|
+
ruby-version: "2.5"
|
86
|
+
- test:
|
87
|
+
name: 'ruby 2.6'
|
88
|
+
ruby-version: "2.6"
|
89
|
+
- publish:
|
90
|
+
filters:
|
91
|
+
branches:
|
92
|
+
only: master
|
93
|
+
tags:
|
94
|
+
ignore: /.*/
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/.travis.yml
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
dist: trusty
|
2
|
+
sudo: false
|
3
|
+
language: ruby
|
4
|
+
cache: bundler
|
5
|
+
rvm:
|
6
|
+
- 2.5
|
7
|
+
- 2.6
|
8
|
+
before_install:
|
9
|
+
# Travis' Ruby 2.5.0 ships broken rubygems, won't run rake.
|
10
|
+
# Workaround: update rubygems. See travis-ci issue 8978
|
11
|
+
- gem install bundler
|
12
|
+
notifications:
|
13
|
+
email: false
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2017 DMM.com
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# SafeValues
|
2
|
+
[](https://travis-ci.org/iknow/safe_values)
|
3
|
+
|
4
|
+
`Value` generates `Struct` classes with safer constructors. It is designed to
|
5
|
+
provide a superset of the interface of the `Values` gem, with better
|
6
|
+
performance, by subclassing actual native `Struct`s.
|
7
|
+
|
8
|
+
`Value` constructors require all mandatory arguments to be provided, and supply
|
9
|
+
default values for all optional arguments. Additionally, the resulting instance
|
10
|
+
is frozen. To obtain a mutable `Value`, use `dup`.
|
11
|
+
|
12
|
+
`Value` types are created similarly to `Struct`s, with the addition that
|
13
|
+
optional arguments are may be specified as keyword arguments:
|
14
|
+
|
15
|
+
```ValueType = Value.new(:a, :b, c: default_value)```
|
16
|
+
|
17
|
+
The default values to optional arguments are saved at class creation time and
|
18
|
+
supplied as default constructor arguments to instances. Default values are
|
19
|
+
aliased, so providing mutable defaults is discouraged.
|
20
|
+
|
21
|
+
Two instance constructors are provided, with positional and keyword arguments.
|
22
|
+
|
23
|
+
Value types may be constructed with positional arguments using `new`. Arguments
|
24
|
+
are provided in the same order as specified at class initialization time, with
|
25
|
+
mandatory arguments before optional ones. For example:
|
26
|
+
|
27
|
+
```ValueType.new(1, 2)```
|
28
|
+
or
|
29
|
+
```ValueType.new(1, 2, 3)```
|
30
|
+
|
31
|
+
Value types may be constructed with keyword arguments using `with`. For example:
|
32
|
+
|
33
|
+
```ValueType.with(a: 1, b: 2)```
|
34
|
+
or
|
35
|
+
```ValueType.with(a: 1, b: 2, c: 3)```
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "safe_values"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/safe_values.rb
ADDED
data/lib/value.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# `Value` generates `Struct` classes with safer constructors. It is designed to
|
4
|
+
# provide a superset of the interface of the `Values` gem, with better
|
5
|
+
# performance, by subclassing actual native Structs.
|
6
|
+
#
|
7
|
+
# `Value` constructors require all mandatory arguments to be provided, and
|
8
|
+
# supply default values for all optional arguments. Additionally, the resulting
|
9
|
+
# instance is frozen. To obtain a mutable Value, `dup` the result.
|
10
|
+
#
|
11
|
+
# `Value` structure classes are created similarly to `Struct`s, with the
|
12
|
+
# addition that optional arguments are may be specified as keyword arguments:
|
13
|
+
# `ValueType = Value.new(:a, :b, c: default_value)`. The default values to
|
14
|
+
# optional arguments are saved at class creation time and supplied as default
|
15
|
+
# constructor arguments to instances. Default values are aliased, so providing
|
16
|
+
# mutable defaults is discouraged.
|
17
|
+
#
|
18
|
+
# Two instance constructors are provided, with positional and keyword arguments.
|
19
|
+
#
|
20
|
+
# Value types may be constructed with positional arguments using `new`.
|
21
|
+
# Arguments are provided in the same order as specified at class initialization
|
22
|
+
# time, with mandatory arguments before optional ones.
|
23
|
+
# For example: `ValueType.new(1, 2)`, `ValueType.new(1, 2, 3)`
|
24
|
+
#
|
25
|
+
# Value types may be constructed with keyword arguments using `with`.
|
26
|
+
# For example: `ValueType.with(a: 1, b: 2, c: 3)`
|
27
|
+
class Value < Struct
|
28
|
+
class << self
|
29
|
+
def new(*required_args, **optional_args, &block)
|
30
|
+
arguments = {}
|
31
|
+
required_args.each { |arg| arguments[arg] = true }
|
32
|
+
optional_args.each_key { |arg| arguments[arg] = false }
|
33
|
+
validate_names(*arguments.keys)
|
34
|
+
|
35
|
+
clazz = super(*arguments.keys, &nil)
|
36
|
+
|
37
|
+
# define class and instance methods in modules so that the class can
|
38
|
+
# override them
|
39
|
+
keyword_constructor = generate_keyword_constructor(arguments)
|
40
|
+
class_method_module = Module.new do
|
41
|
+
module_eval(keyword_constructor)
|
42
|
+
define_method(:__constructor_default) do |name|
|
43
|
+
optional_args.fetch(name)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
clazz.extend(class_method_module)
|
47
|
+
|
48
|
+
constructor = generate_constructor(arguments)
|
49
|
+
instance_method_module = Module.new do
|
50
|
+
module_eval(constructor)
|
51
|
+
end
|
52
|
+
clazz.include(instance_method_module)
|
53
|
+
|
54
|
+
# Evaluate the block in the context of the class
|
55
|
+
clazz.class_eval(&block) if block_given?
|
56
|
+
|
57
|
+
clazz
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def validate_names(*params)
|
63
|
+
params.each do |param|
|
64
|
+
unless param.is_a?(Symbol) && param =~ /\A[a-z_][a-zA-Z_0-9]*\z/
|
65
|
+
raise ArgumentError.new("param #{param} is not a valid identifier")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Generates an initialize method with required and optional parameters,
|
71
|
+
# delegating to the Struct constructor. Parameter names must have already
|
72
|
+
# been validated.
|
73
|
+
#
|
74
|
+
# For a Value.new(:a, b: x), will define the method:
|
75
|
+
#
|
76
|
+
# def initialize(a, b = self.class.__constructor_default(:b))
|
77
|
+
# super(a, b)
|
78
|
+
# freeze
|
79
|
+
# end
|
80
|
+
def generate_constructor(arguments)
|
81
|
+
params = arguments.map do |arg_name, required|
|
82
|
+
if required
|
83
|
+
arg_name
|
84
|
+
else
|
85
|
+
"#{arg_name} = self.class.__constructor_default(:#{arg_name})"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
<<-SRC
|
90
|
+
def initialize(#{params.join(", ")})
|
91
|
+
super(#{arguments.keys.join(", ")})
|
92
|
+
freeze
|
93
|
+
end
|
94
|
+
SRC
|
95
|
+
end
|
96
|
+
|
97
|
+
# Generates an alternative construction method accepting keyword arguments
|
98
|
+
# for required and optional parameters, delegating to the generated
|
99
|
+
# constructor. Parameter names must have already been validated.
|
100
|
+
#
|
101
|
+
# For a Value.new(:a, b: x), will define the (class) method:
|
102
|
+
#
|
103
|
+
# def with(a:, b: __constructor_default(:b))
|
104
|
+
# self.new(a, b)
|
105
|
+
# end
|
106
|
+
def generate_keyword_constructor(arguments)
|
107
|
+
params = arguments.map do |arg_name, required|
|
108
|
+
if required
|
109
|
+
"#{arg_name}:"
|
110
|
+
else
|
111
|
+
"#{arg_name}: __constructor_default(:#{arg_name})"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
<<-SRC
|
116
|
+
def with(#{params.join(", ")})
|
117
|
+
self.new(#{arguments.keys.join(", ")})
|
118
|
+
end
|
119
|
+
SRC
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def with(hash = {})
|
124
|
+
return self if hash.empty?
|
125
|
+
self.class.with(to_h.merge(hash))
|
126
|
+
end
|
127
|
+
end
|
data/safe_values.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'safe_values/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'safe_values'
|
8
|
+
spec.version = SafeValues::VERSION
|
9
|
+
spec.authors = ['DMM Eikaiwa']
|
10
|
+
spec.email = ['dev@iknow.jp']
|
11
|
+
|
12
|
+
spec.summary = %q{Struct classes with safer constructors.}
|
13
|
+
spec.homepage = 'http://github.com/iknow/safe_values'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = 'exe'
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ['lib']
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
spec.add_development_dependency 'rspec'
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: safe_values
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- DMM Eikaiwa
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-04-08 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: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
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: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- dev@iknow.jp
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".circleci/config.yml"
|
63
|
+
- ".gitignore"
|
64
|
+
- ".rspec"
|
65
|
+
- ".travis.yml"
|
66
|
+
- Gemfile
|
67
|
+
- LICENSE.txt
|
68
|
+
- README.md
|
69
|
+
- Rakefile
|
70
|
+
- bin/console
|
71
|
+
- bin/setup
|
72
|
+
- lib/safe_values.rb
|
73
|
+
- lib/safe_values/version.rb
|
74
|
+
- lib/value.rb
|
75
|
+
- safe_values.gemspec
|
76
|
+
homepage: http://github.com/iknow/safe_values
|
77
|
+
licenses:
|
78
|
+
- MIT
|
79
|
+
metadata: {}
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubygems_version: 3.0.3
|
96
|
+
signing_key:
|
97
|
+
specification_version: 4
|
98
|
+
summary: Struct classes with safer constructors.
|
99
|
+
test_files: []
|