frise 0.3.0.pre → 0.3.0
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 +4 -4
- data/CHANGELOG.md +17 -2
- data/README.md +12 -19
- data/frise.gemspec +2 -2
- data/lib/frise/defaults_loader.rb +56 -48
- data/lib/frise/loader.rb +82 -24
- data/lib/frise/parser.rb +8 -3
- data/lib/frise/version.rb +1 -1
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5923c848338d6a2f7dfc35211200ab51a789ad9e9967742e4eb57430346785e9
|
4
|
+
data.tar.gz: e08f1fdf3a14fe288ad67a0baa6a9e557294de9ac5ea814426e9b92792b1be95
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a578f2042b86832986bed1cecbe435330e509e2f6f166ff7302c3eeca37e445bc7acbbcbd4fe16d3cf9c23be68603cd9d4e13f17c508edaeff5e96169b41eaa9
|
7
|
+
data.tar.gz: 1c4378dcec5e8738f25248d6a45fcc96b4392f7144995e08d57407abd3bf1ad5bfe506fe6e1117aa4caef7900dcedfba9dc8b4267b1c4cd6d273c5395313cd2f
|
data/CHANGELOG.md
CHANGED
@@ -1,11 +1,26 @@
|
|
1
|
+
### 0.3.0 (April 16, 2018)
|
2
|
+
|
3
|
+
- Breaking changes
|
4
|
+
- Defaults and schemas are now defined using a directive in the YAML configs instead of
|
5
|
+
implicitly by looking at load paths. See ([#7](https://github.com/velocidi/frise/pull/7)) for
|
6
|
+
more information on migration;
|
7
|
+
- New features
|
8
|
+
- `$include` and `$schema` directives are now available in config files, allowing users to
|
9
|
+
validate and include defaults at any part of the config
|
10
|
+
([#7](https://github.com/velocidi/frise/pull/7));
|
11
|
+
- A new `$content_include` directive allows users to include the content of a file as a YAML
|
12
|
+
string ([#8](https://github.com/velocidi/frise/pull/8));
|
13
|
+
- The `_file_dir` Liquid variable is now available in all included files, containing always the
|
14
|
+
absolute path to the file being loaded ([#7](https://github.com/velocidi/frise/pull/7)).
|
15
|
+
|
1
16
|
### 0.2.0 (August 17, 2017)
|
2
17
|
|
3
18
|
- New features
|
4
19
|
- New schema types `$enum` and `$one_of` for specifying enumerations and values with multiple
|
5
|
-
possible schemas ([#5](https://github.com/
|
20
|
+
possible schemas ([#5](https://github.com/velocidi/frise/pull/5)).
|
6
21
|
- Bug fixes
|
7
22
|
- Deal correctly with non-existing schema files in the load path
|
8
|
-
([#4](https://github.com/
|
23
|
+
([#4](https://github.com/velocidi/frise/pull/4)).
|
9
24
|
|
10
25
|
### 0.1.0 (August 10, 2017)
|
11
26
|
|
data/README.md
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
# Frise
|
2
|
-
[](https://travis-ci.org/velocidi/frise)
|
3
|
+
[](https://coveralls.io/github/velocidi/frise?branch=master)
|
4
4
|
[](https://badge.fury.io/rb/frise)
|
5
5
|
|
6
6
|
Frise is a library for loading configuration files as native Ruby structures. Besides reading and
|
7
7
|
parsing the files themselves, it also:
|
8
8
|
|
9
|
-
-
|
9
|
+
- Allows defining other files to be merged anywhere in the config, which can be used to provide default values specified
|
10
|
+
in another file or set of files;
|
10
11
|
- Interprets [Liquid](https://shopify.github.io/liquid) templates in configs and defaults;
|
11
12
|
- Validates the loaded config according to a schema file or set of files.
|
12
13
|
|
@@ -24,7 +25,6 @@ The simplest example would be to load [a simple configuration](example/config.ym
|
|
24
25
|
|
25
26
|
```ruby
|
26
27
|
require 'frise'
|
27
|
-
require 'pp'
|
28
28
|
|
29
29
|
loader = Frise::Loader.new
|
30
30
|
loader.load('example/config.yml')
|
@@ -44,12 +44,11 @@ Currently Frise only supports YAML files, but it may support JSON and other form
|
|
44
44
|
|
45
45
|
### Default values
|
46
46
|
|
47
|
-
By
|
48
|
-
[example/_defaults](example/_defaults)), Frise can handle its application internally on load time:
|
47
|
+
By using the `$include` directive pointing to the files where default values can be found (in this example,
|
48
|
+
[example/_defaults/config.yml](example/_defaults/config.yml)), Frise can handle its application internally on load time:
|
49
49
|
|
50
50
|
```ruby
|
51
|
-
loader
|
52
|
-
loader.load('example/config.yml')
|
51
|
+
loader.load('example/config_with_defaults.yml')
|
53
52
|
# => {"movies"=>
|
54
53
|
# [{"title"=>"The Shawshank Redemption",
|
55
54
|
# "year"=>1994,
|
@@ -75,15 +74,11 @@ config.
|
|
75
74
|
### Schemas
|
76
75
|
|
77
76
|
Additionally, configuration files can also be validated against a schema. By specifying
|
78
|
-
`
|
79
|
-
[example/_schemas/config.yml](example/_schemas/config.yml)
|
77
|
+
`$schema` in the config, users can provide schema files such as
|
78
|
+
[example/_schemas/config.yml](example/_schemas/config.yml):
|
80
79
|
|
81
80
|
```ruby
|
82
|
-
loader
|
83
|
-
schema_load_paths: ['example/_schemas'],
|
84
|
-
defaults_load_paths: ['example/_defaults'])
|
85
|
-
|
86
|
-
loader.load('example/config.yml')
|
81
|
+
loader.load('example/config_with_defaults_and_schema.yml')
|
87
82
|
# {"movies"=>
|
88
83
|
# [{"title"=>"The Shawshank Redemption",
|
89
84
|
# "year"=>1994,
|
@@ -106,16 +101,14 @@ missing and Frise by default prints a summary of the errors and terminates the p
|
|
106
101
|
|
107
102
|
|
108
103
|
```ruby
|
109
|
-
loader
|
110
|
-
|
111
|
-
loader.load('example/config.yml')
|
104
|
+
loader.load('example/config_with_schema.yml')
|
112
105
|
# 2 config error(s) found:
|
113
106
|
# - At movies.0.director: missing required value
|
114
107
|
# - At ui: missing required value
|
115
108
|
```
|
116
109
|
|
117
110
|
Once more, the structure of the schema mimics the structure of the config itself, making it easy to
|
118
|
-
write schemas and
|
111
|
+
write schemas first and create a config scaffold from its schema later.
|
119
112
|
|
120
113
|
Users can check a whole range of properties in config values besides their type: optional values,
|
121
114
|
hashes with validated keys, hashes with unknown keys and even custom validations are also supported.
|
data/frise.gemspec
CHANGED
@@ -20,12 +20,12 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.require_paths = ['lib']
|
21
21
|
spec.required_ruby_version = '>= 2.3.0'
|
22
22
|
|
23
|
-
spec.add_dependency 'liquid', '~>
|
23
|
+
spec.add_dependency 'liquid', '~> 4.0'
|
24
24
|
|
25
25
|
spec.add_development_dependency 'bundler', '~> 1.14'
|
26
26
|
spec.add_development_dependency 'coveralls', '~> 0.8.21'
|
27
27
|
spec.add_development_dependency 'rake', '~> 12.3'
|
28
28
|
spec.add_development_dependency 'rspec', '~> 3.4'
|
29
|
-
spec.add_development_dependency 'rubocop', '
|
29
|
+
spec.add_development_dependency 'rubocop', '0.55.0'
|
30
30
|
spec.add_development_dependency 'simplecov', '~> 0.14.1'
|
31
31
|
end
|
@@ -7,67 +7,75 @@ module Frise
|
|
7
7
|
#
|
8
8
|
# The merge_defaults and merge_defaults_at entrypoint methods provide ways to read files with
|
9
9
|
# defaults and apply them to configuration objects.
|
10
|
-
|
11
|
-
|
12
|
-
SYMBOLS = %w[$all $optional].freeze
|
10
|
+
class DefaultsLoader
|
11
|
+
SYMBOLS = %w[$all $optional].freeze
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
13
|
+
def initialize(include_sym: '$include', content_include_sym: '$content_include', schema_sym: '$schema')
|
14
|
+
@include_sym = include_sym
|
15
|
+
@content_include_sym = content_include_sym
|
16
|
+
@schema_sym = schema_sym
|
17
|
+
end
|
20
18
|
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
def widened_class(obj)
|
20
|
+
class_name = obj.class.to_s
|
21
|
+
return 'String' if class_name == 'Hash' && !obj[@content_include_sym].nil?
|
22
|
+
return 'Boolean' if %w[TrueClass FalseClass].include? class_name
|
23
|
+
return 'Integer' if %w[Fixnum Bignum].include? class_name
|
24
|
+
class_name
|
25
|
+
end
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
else merge_defaults_obj({}, defaults)
|
29
|
-
end
|
27
|
+
def merge_defaults_obj(config, defaults)
|
28
|
+
config_class = widened_class(config)
|
29
|
+
defaults_class = widened_class(defaults)
|
30
30
|
|
31
|
-
|
32
|
-
|
31
|
+
if defaults.nil?
|
32
|
+
config
|
33
33
|
|
34
|
-
|
35
|
-
|
34
|
+
elsif config.nil?
|
35
|
+
if defaults_class != 'Hash' then defaults
|
36
|
+
elsif defaults['$optional'] then nil
|
37
|
+
else merge_defaults_obj({}, defaults)
|
38
|
+
end
|
36
39
|
|
37
|
-
|
38
|
-
|
39
|
-
(config.keys + defaults.keys).uniq.each do |key|
|
40
|
-
next if SYMBOLS.include?(key)
|
41
|
-
new_config[key] = config[key]
|
42
|
-
new_config[key] = merge_defaults_obj(new_config[key], defaults[key]) if defaults.key?(key)
|
43
|
-
new_config[key] = merge_defaults_obj(new_config[key], defaults['$all']) unless new_config[key].nil?
|
44
|
-
new_config.delete(key) if new_config[key].nil?
|
45
|
-
end
|
46
|
-
new_config
|
40
|
+
elsif defaults_class == 'Array' && config_class == 'Array'
|
41
|
+
defaults + config
|
47
42
|
|
48
|
-
|
49
|
-
|
50
|
-
"with default #{defaults.inspect} (#{widened_class(defaults)})"
|
43
|
+
elsif defaults_class == 'Hash' && defaults['$all'] && config_class == 'Array'
|
44
|
+
config.map { |elem| merge_defaults_obj(elem, defaults['$all']) }
|
51
45
|
|
52
|
-
|
53
|
-
|
46
|
+
elsif defaults_class == 'Hash' && config_class == 'Hash'
|
47
|
+
new_config = {}
|
48
|
+
(config.keys + defaults.keys).uniq.each do |key|
|
49
|
+
next if SYMBOLS.include?(key)
|
50
|
+
new_config[key] = config[key]
|
51
|
+
new_config[key] = merge_defaults_obj(new_config[key], defaults[key]) if defaults.key?(key)
|
52
|
+
new_config[key] = merge_defaults_obj(new_config[key], defaults['$all']) unless new_config[key].nil?
|
53
|
+
new_config.delete(key) if new_config[key].nil?
|
54
54
|
end
|
55
|
-
|
55
|
+
new_config
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
57
|
+
elsif defaults_class != config_class
|
58
|
+
raise "Cannot merge config #{config.inspect} (#{widened_class(config)}) " \
|
59
|
+
"with default #{defaults.inspect} (#{widened_class(defaults)})"
|
61
60
|
|
62
|
-
|
63
|
-
|
64
|
-
merge_defaults_obj(config, defaults)
|
61
|
+
else
|
62
|
+
config
|
65
63
|
end
|
64
|
+
end
|
66
65
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
66
|
+
def merge_defaults_obj_at(config, at_path, defaults)
|
67
|
+
at_path.reverse.each { |key| defaults = { key => defaults } }
|
68
|
+
merge_defaults_obj(config, defaults)
|
69
|
+
end
|
70
|
+
|
71
|
+
def merge_defaults(config, defaults_file, symbol_table = config)
|
72
|
+
defaults = Parser.parse(defaults_file, symbol_table) || {}
|
73
|
+
merge_defaults_obj(config, defaults)
|
74
|
+
end
|
75
|
+
|
76
|
+
def merge_defaults_at(config, at_path, defaults_file, symbol_table = config)
|
77
|
+
defaults = Parser.parse(defaults_file, symbol_table) || {}
|
78
|
+
merge_defaults_obj_at(config, at_path, defaults)
|
71
79
|
end
|
72
80
|
end
|
73
81
|
end
|
data/lib/frise/loader.rb
CHANGED
@@ -10,12 +10,25 @@ module Frise
|
|
10
10
|
#
|
11
11
|
# The load method loads a configuration file, merges the applicable includes and validates its schema.
|
12
12
|
class Loader
|
13
|
-
def initialize(include_sym: '$include',
|
13
|
+
def initialize(include_sym: '$include',
|
14
|
+
content_include_sym: '$content_include',
|
15
|
+
schema_sym: '$schema',
|
16
|
+
pre_loaders: [],
|
17
|
+
validators: nil,
|
18
|
+
exit_on_fail: true)
|
19
|
+
|
14
20
|
@include_sym = include_sym
|
21
|
+
@content_include_sym = content_include_sym
|
15
22
|
@schema_sym = schema_sym
|
16
23
|
@pre_loaders = pre_loaders
|
17
24
|
@validators = validators
|
18
25
|
@exit_on_fail = exit_on_fail
|
26
|
+
|
27
|
+
@defaults_loader = DefaultsLoader.new(
|
28
|
+
include_sym: include_sym,
|
29
|
+
content_include_sym: content_include_sym,
|
30
|
+
schema_sym: schema_sym
|
31
|
+
)
|
19
32
|
end
|
20
33
|
|
21
34
|
def load(config_file, global_vars = {})
|
@@ -36,35 +49,49 @@ module Frise
|
|
36
49
|
def process_includes(config, at_path, root_config, global_vars)
|
37
50
|
return config unless config.class == Hash
|
38
51
|
|
39
|
-
|
40
|
-
|
52
|
+
# process $content_include directives
|
53
|
+
config, content_include_confs = extract_content_include(config, at_path)
|
54
|
+
unless content_include_confs.empty?
|
55
|
+
raise "At #{build_path(at_path)}: a #{@content_include_sym} must not have any sibling key" unless config.empty?
|
56
|
+
|
57
|
+
content = ''
|
58
|
+
content_include_confs.each do |include_conf|
|
59
|
+
symbol_table = build_symbol_table(root_config, at_path, nil, global_vars, include_conf)
|
60
|
+
content += Parser.parse_as_text(include_conf['file'], symbol_table) || ''
|
61
|
+
end
|
62
|
+
return content
|
63
|
+
end
|
64
|
+
|
65
|
+
# process $include directives
|
66
|
+
config, include_confs = extract_include(config, at_path)
|
67
|
+
if include_confs.empty?
|
41
68
|
config.map { |k, v| [k, process_includes(v, at_path + [k], root_config, global_vars)] }.to_h
|
42
69
|
else
|
43
70
|
Lazy.new do
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
symbol_table = merge_at(root_config, at_path, config)
|
48
|
-
.merge(global_vars).merge(extra_vars).merge(extra_consts).merge('_this' => config)
|
71
|
+
include_confs.each do |include_conf|
|
72
|
+
symbol_table = build_symbol_table(root_config, at_path, config, global_vars, include_conf)
|
73
|
+
included_config = Parser.parse(include_conf['file'], symbol_table)
|
49
74
|
|
50
|
-
config =
|
75
|
+
config = @defaults_loader.merge_defaults_obj(config, included_config)
|
76
|
+
config = process_includes(config, at_path, merge_at(root_config, at_path, config), global_vars)
|
51
77
|
end
|
52
|
-
|
78
|
+
updated_root_config = merge_at(root_config, at_path, config)
|
79
|
+
config.map { |k, v| [k, process_includes(v, at_path + [k], updated_root_config, global_vars)] }.to_h
|
53
80
|
end
|
54
81
|
end
|
55
82
|
end
|
56
83
|
|
57
|
-
def process_schema_includes(schema, global_vars)
|
84
|
+
def process_schema_includes(schema, at_path, global_vars)
|
58
85
|
return schema unless schema.class == Hash
|
59
86
|
|
60
|
-
schema, included_schemas = extract_include(schema)
|
87
|
+
schema, included_schemas = extract_include(schema, at_path)
|
61
88
|
if included_schemas.empty?
|
62
|
-
schema.map { |k, v| [k, process_schema_includes(v, global_vars)] }.to_h
|
89
|
+
schema.map { |k, v| [k, process_schema_includes(v, at_path + [k], global_vars)] }.to_h
|
63
90
|
else
|
64
91
|
included_schemas.each do |defaults_conf|
|
65
92
|
schema = Parser.parse(defaults_conf['file'], global_vars).merge(schema)
|
66
93
|
end
|
67
|
-
process_schema_includes(schema, global_vars)
|
94
|
+
process_schema_includes(schema, at_path, global_vars)
|
68
95
|
end
|
69
96
|
end
|
70
97
|
|
@@ -77,10 +104,10 @@ module Frise
|
|
77
104
|
[k, new_v]
|
78
105
|
end.to_h
|
79
106
|
|
80
|
-
config, schema_files = extract_schema(config)
|
107
|
+
config, schema_files = extract_schema(config, at_path)
|
81
108
|
schema_files.each do |schema_file|
|
82
109
|
schema = Parser.parse(schema_file, global_vars)
|
83
|
-
schema = process_schema_includes(schema, global_vars)
|
110
|
+
schema = process_schema_includes(schema, at_path, global_vars)
|
84
111
|
|
85
112
|
errors = Validator.validate_obj(config,
|
86
113
|
schema,
|
@@ -93,37 +120,68 @@ module Frise
|
|
93
120
|
config
|
94
121
|
end
|
95
122
|
|
96
|
-
def extract_schema(config)
|
97
|
-
extract_special(config, @schema_sym) do |value|
|
123
|
+
def extract_schema(config, at_path)
|
124
|
+
extract_special(config, @schema_sym, at_path) do |value|
|
98
125
|
case value
|
99
126
|
when String then value
|
100
|
-
else raise "
|
127
|
+
else raise "At #{build_path(at_path)}: illegal value for a #{@schema_sym} element: #{value.inspect}"
|
101
128
|
end
|
102
129
|
end
|
103
130
|
end
|
104
131
|
|
105
|
-
def extract_include(config)
|
106
|
-
|
132
|
+
def extract_include(config, at_path)
|
133
|
+
extract_include_base(config, @include_sym, at_path)
|
134
|
+
end
|
135
|
+
|
136
|
+
def extract_content_include(config, at_path)
|
137
|
+
extract_include_base(config, @content_include_sym, at_path)
|
138
|
+
end
|
139
|
+
|
140
|
+
def extract_include_base(config, sym, at_path)
|
141
|
+
extract_special(config, sym, at_path) do |value|
|
107
142
|
case value
|
108
143
|
when Hash then value
|
109
144
|
when String then { 'file' => value }
|
110
|
-
else raise "
|
145
|
+
else raise "At #{build_path(at_path)}: illegal value for a #{sym} element: #{value.inspect}"
|
111
146
|
end
|
112
147
|
end
|
113
148
|
end
|
114
149
|
|
115
|
-
def extract_special(config, key)
|
150
|
+
def extract_special(config, key, at_path)
|
116
151
|
case config[key]
|
117
152
|
when nil then [config, []]
|
118
153
|
when Array then [config.reject { |k| k == key }, config[key].map { |e| yield e }]
|
119
|
-
else raise "
|
154
|
+
else raise "At #{build_path(at_path)}: illegal value for #{key}: #{config[key].inspect}"
|
120
155
|
end
|
121
156
|
end
|
122
157
|
|
158
|
+
# merges the `to_merge` value on `config` at path `at_path`
|
123
159
|
def merge_at(config, at_path, to_merge)
|
124
160
|
return config.merge(to_merge) if at_path.empty?
|
125
161
|
head, *tail = at_path
|
126
162
|
config.merge(head => merge_at(config[head], tail, to_merge))
|
127
163
|
end
|
164
|
+
|
165
|
+
# builds the symbol table for the Liquid renderization of a file, based on:
|
166
|
+
# - `root_config`: the root of the whole config
|
167
|
+
# - `at_path`: the current path
|
168
|
+
# - `config`: the config subtree being built
|
169
|
+
# - `global_vars`: the global variables
|
170
|
+
# - `include_conf`: the $include or $content_include configuration
|
171
|
+
def build_symbol_table(root_config, at_path, config, global_vars, include_conf)
|
172
|
+
extra_vars = (include_conf['vars'] || {}).map { |k, v| [k, root_config.dig(*v.split('.'))] }.to_h
|
173
|
+
extra_consts = include_conf['constants'] || {}
|
174
|
+
|
175
|
+
(config ? merge_at(root_config, at_path, config) : root_config)
|
176
|
+
.merge(global_vars)
|
177
|
+
.merge(extra_vars)
|
178
|
+
.merge(extra_consts)
|
179
|
+
.merge('_this' => config)
|
180
|
+
end
|
181
|
+
|
182
|
+
# builds a user-friendly string indicating a path
|
183
|
+
def build_path(at_path)
|
184
|
+
at_path.empty? ? '<root>' : at_path.join('.')
|
185
|
+
end
|
128
186
|
end
|
129
187
|
end
|
data/lib/frise/parser.rb
CHANGED
@@ -10,15 +10,20 @@ module Frise
|
|
10
10
|
class << self
|
11
11
|
def parse(file, symbol_table = nil)
|
12
12
|
return nil unless File.file? file
|
13
|
-
|
13
|
+
YAML.safe_load(parse_as_text(file, symbol_table), [], [], true) || {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse_as_text(file, symbol_table = nil)
|
17
|
+
return nil unless File.file? file
|
18
|
+
content = File.read(file)
|
14
19
|
content = Liquid::Template.parse(content).render with_internal_vars(file, symbol_table) if symbol_table
|
15
|
-
|
20
|
+
content
|
16
21
|
end
|
17
22
|
|
18
23
|
private
|
19
24
|
|
20
25
|
def with_internal_vars(file, symbol_table)
|
21
|
-
symbol_table.merge('_file_dir' => File.dirname(file))
|
26
|
+
symbol_table.merge('_file_dir' => File.expand_path(File.dirname(file)))
|
22
27
|
end
|
23
28
|
end
|
24
29
|
end
|
data/lib/frise/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: frise
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.0
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ShiftForward
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-04-
|
11
|
+
date: 2018-04-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: liquid
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '4.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '4.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,16 +84,16 @@ dependencies:
|
|
84
84
|
name: rubocop
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - '='
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 0.
|
89
|
+
version: 0.55.0
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - '='
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 0.
|
96
|
+
version: 0.55.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: simplecov
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -147,9 +147,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
147
147
|
version: 2.3.0
|
148
148
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
|
-
- - "
|
150
|
+
- - ">="
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
152
|
+
version: '0'
|
153
153
|
requirements: []
|
154
154
|
rubyforge_project:
|
155
155
|
rubygems_version: 2.7.6
|