schemacop 3.0.2 → 3.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90acd1ba976d75dae0019274d843c5d727858655238148a10bd485973e964fba
4
- data.tar.gz: 40e63d805b815c61bcf342fc449fa5f0be506f386b7a315df33c9baada0723cd
3
+ metadata.gz: 85c1da35631e2529c91caa46f76c5784ad51fd83843eb1126912919b36c96809
4
+ data.tar.gz: e1315e5f708c804f329d79fe76c2a22ac9e2179dc3ddf5301ebcbbe280028638
5
5
  SHA512:
6
- metadata.gz: ff575cb152372e2cf0685ae1f5ac123c88245a6bb23acbdc7dd0daa27098d245fc90f9e6f5d381d9490d4476109d22c01a86df5744e84b872c6708e4841b7a06
7
- data.tar.gz: fda34143fc547221dadfe7cdcb24206185e2b1736ad8e4925e70928fb7d22a5f280f54a70503b5cdf7380f30fcdf250f5663eeae26323dec8dbabd4e686928dc
6
+ metadata.gz: f3de1743f921b7c09914d9d8f483ebe05fceb4055671b9d7413302ae0eb442a1b6c5b9c073e82eee43cd94e98c26c055b641677d154b0f515930aabae00a7714
7
+ data.tar.gz: 0c48ce6c72444da2702f1e4a927ffbc4533dea8abbf40f7065fa929be7a4b9ac49d788612550ca587ea6b16be1d24691814f9dec2bc81d7d27aeb48690e32be4
data/CHANGELOG.md CHANGED
@@ -1,14 +1,38 @@
1
1
  # Change log
2
2
 
3
- <!--
4
- ## master (unreleased)
3
+ ## 3.0.7 (2021-02-22)
5
4
 
6
- ### New features
5
+ * Adapt schema definitions handling when using Swagger-standard JSON
7
6
 
8
- ### Bug fixes
7
+ ## 3.0.6 (2021-02-14)
9
8
 
10
- ### Changes
11
- -->
9
+ * Remove option `json_format` from {Schemacop::Schema3.as_json as_json} again.
10
+ If you need to use the swagger format, use
11
+ {Schemacop::V3::Context.with_json_format} instead.
12
+
13
+ * Rename `Schemacop::V3::Context.spawn_with` to
14
+ {Schemacop::V3::Context.with_json_format} and make keyword argument
15
+ `json_format` a positional argument.
16
+
17
+ ## 3.0.5 (2021-02-14)
18
+
19
+ * Allow option `pattern` to be a `Regexp` for `string` (`str`) nodes
20
+
21
+ * Remove `examples_keyword` from context again
22
+
23
+ * Add option `json_format` to {Schemacop::Schema3.as_json as_json}. This allows
24
+ generating a JSON schema that is [specific to
25
+ swagger](https://swagger.io/docs/specification/data-models/keywords/) by
26
+ passing `:swagger` to it.
27
+
28
+ ## 3.0.4 (2021-02-15)
29
+
30
+ * Add `examples_keyword` to context which allows to customize the name of the
31
+ `examples` attribute in JSON output
32
+
33
+ ## 3.0.3 (2021-02-15)
34
+
35
+ * Fix boolean node casting
12
36
 
13
37
  ## 3.0.2 (2021-02-14)
14
38
 
data/README.md CHANGED
@@ -16,7 +16,7 @@ Schemacop is tested with the following ruby versions:
16
16
  * 2.7.1
17
17
  * 3.0.0
18
18
 
19
- For these versions, the automated CI tests are ran on travis. Other ruby versions might work, but stick to these versions for best results.
19
+ Other ruby versions might work but are not covered by our Travis tests.
20
20
 
21
21
  ## Basic example
22
22
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.0.2
1
+ 3.0.7
data/lib/schemacop/v3.rb CHANGED
@@ -3,6 +3,24 @@ module Schemacop
3
3
  def self.register(*args)
4
4
  NodeRegistry.register(*args)
5
5
  end
6
+
7
+ # @private
8
+ def self.sanitize_exp(exp)
9
+ return exp if exp.is_a?(String)
10
+
11
+ _start_slash, caret, exp, dollar, _end_slash, flags = exp.inspect.match(%r{^(/?)(\^)?(.*?)(\$)?(/?)([ixm]*)?$}).captures
12
+ flags = flags.split('')
13
+
14
+ if flags.delete('i')
15
+ exp = "(?i)(#{exp})"
16
+ end
17
+
18
+ if flags.any?
19
+ fail "Flags #{flags.inspect} are not supported by Schemacop."
20
+ end
21
+
22
+ return "#{caret}#{exp}#{dollar}"
23
+ end
6
24
  end
7
25
  end
8
26
 
@@ -11,6 +11,14 @@ module Schemacop
11
11
  FalseClass => :boolean
12
12
  }
13
13
  end
14
+
15
+ def cast(value)
16
+ if value.is_a?(TrueClass) || value.is_a?(FalseClass)
17
+ value
18
+ else
19
+ default
20
+ end
21
+ end
14
22
  end
15
23
  end
16
24
  end
@@ -2,9 +2,13 @@ module Schemacop
2
2
  module V3
3
3
  class Context
4
4
  attr_accessor :schemas
5
+ attr_accessor :json_format
5
6
 
6
- def initialize
7
+ DEFAULT_JSON_FORMAT = :default
8
+
9
+ def initialize(json_format: DEFAULT_JSON_FORMAT)
7
10
  @schemas = {}.with_indifferent_access.freeze
11
+ @json_format = json_format
8
12
  end
9
13
 
10
14
  def schema(name, type = :hash, **options, &block)
@@ -12,6 +16,18 @@ module Schemacop
12
16
  name => Node.create(type, **options, &block)
13
17
  ).freeze
14
18
  end
19
+
20
+ def with_json_format(json_format)
21
+ prev_json_format = @json_format
22
+ @json_format = json_format
23
+ return yield
24
+ ensure
25
+ @json_format = prev_json_format
26
+ end
27
+
28
+ def swagger_json?
29
+ @json_format == :swagger
30
+ end
15
31
  end
16
32
  end
17
33
  end
@@ -21,14 +21,6 @@ module Schemacop
21
21
  super + NodeRegistry.dsl_methods(true) + %i[dsl_dep dsl_add]
22
22
  end
23
23
 
24
- def self.sanitize_exp(exp)
25
- exp = exp.to_s
26
- if exp.start_with?('(?-mix:')
27
- exp = exp.to_s.gsub(/^\(\?-mix:/, '').gsub(/\)$/, '')
28
- end
29
- return exp
30
- end
31
-
32
24
  def add_child(node)
33
25
  unless node.name
34
26
  fail Exceptions::InvalidSchemaError, 'Child nodes must have a name.'
@@ -64,7 +56,7 @@ module Schemacop
64
56
 
65
57
  json = {}
66
58
  json[:properties] = Hash[properties.values.map { |p| [p.name, p.as_json] }] if properties.any?
67
- json[:patternProperties] = Hash[pattern_properties.values.map { |p| [self.class.sanitize_exp(p.name), p.as_json] }] if pattern_properties.any?
59
+ json[:patternProperties] = Hash[pattern_properties.values.map { |p| [V3.sanitize_exp(p.name), p.as_json] }] if pattern_properties.any?
68
60
 
69
61
  # In schemacop, by default, additional properties are not allowed,
70
62
  # the users explicitly need to enable additional properties
@@ -150,6 +150,10 @@ module Schemacop
150
150
 
151
151
  protected
152
152
 
153
+ def context
154
+ Schemacop.context
155
+ end
156
+
153
157
  def item_matches?(item, data)
154
158
  item_result = Result.new(self)
155
159
  item._validate(data, result: item_result)
@@ -157,12 +161,13 @@ module Schemacop
157
161
  end
158
162
 
159
163
  def process_json(attrs, json)
160
- if @schemas.any?
164
+ if !context.swagger_json? && @schemas.any?
161
165
  json[:definitions] = {}
162
166
  @schemas.each do |name, subschema|
163
167
  json[:definitions][name] = subschema.as_json
164
168
  end
165
169
  end
170
+
166
171
  attrs.each do |attr|
167
172
  if options.include?(attr)
168
173
  json[attr.to_s.camelize(:lower).to_sym] = options[attr]
@@ -170,7 +175,7 @@ module Schemacop
170
175
  end
171
176
 
172
177
  json[:title] = @title if @title
173
- json[:examples] = @examples if @examples
178
+ json[context.swagger_json? ? :example : :examples] = @examples if @examples
174
179
  json[:description] = @description if @description
175
180
  json[:default] = @default if @default
176
181
  json[:enum] = @enum.to_a if @enum
@@ -4,16 +4,34 @@ module Schemacop
4
4
  class NumericNode < Node
5
5
  ATTRIBUTES = %i[
6
6
  minimum
7
- exclusive_minimum
8
7
  maximum
9
- exclusive_maximum
10
8
  multiple_of
9
+ exclusive_minimum
10
+ exclusive_maximum
11
11
  ].freeze
12
12
 
13
13
  def self.allowed_options
14
14
  super + ATTRIBUTES
15
15
  end
16
16
 
17
+ def process_json(attrs, json)
18
+ if context.swagger_json?
19
+ if options[:exclusive_minimum]
20
+ json[:minimum] = options[:exclusive_minimum]
21
+ json[:exclusiveMinimum] = true
22
+ end
23
+
24
+ if options[:exclusive_maximum]
25
+ json[:maximum] = options[:exclusive_maximum]
26
+ json[:exclusiveMaximum] = true
27
+ end
28
+
29
+ attrs -= %i[exclusive_minimum exclusive_maximum]
30
+ end
31
+
32
+ super attrs, json
33
+ end
34
+
17
35
  def _validate(data, result:)
18
36
  super_data = super
19
37
  return if super_data.nil?
@@ -11,7 +11,11 @@ module Schemacop
11
11
  end
12
12
 
13
13
  def as_json
14
- process_json([], '$ref': "#/definitions/#{@path}")
14
+ if context.swagger_json?
15
+ process_json([], '$ref': "#/components/schemas/#{@path}")
16
+ else
17
+ process_json([], '$ref': "#/definitions/#{@path}")
18
+ end
15
19
  end
16
20
 
17
21
  def _validate(data, result:)
@@ -4,7 +4,6 @@ module Schemacop
4
4
  ATTRIBUTES = %i[
5
5
  min_length
6
6
  max_length
7
- pattern
8
7
  format
9
8
  ].freeze
10
9
 
@@ -23,7 +22,7 @@ module Schemacop
23
22
  # rubocop:enable Layout/LineLength
24
23
 
25
24
  def self.allowed_options
26
- super + ATTRIBUTES - %i[cast_str] + %i[format_options]
25
+ super + ATTRIBUTES - %i[cast_str] + %i[format_options pattern]
27
26
  end
28
27
 
29
28
  def allowed_types
@@ -31,7 +30,11 @@ module Schemacop
31
30
  end
32
31
 
33
32
  def as_json
34
- process_json(ATTRIBUTES, type: :string)
33
+ json = { type: :string }
34
+ if options[:pattern]
35
+ json[:pattern] = V3.sanitize_exp(Regexp.compile(options[:pattern]))
36
+ end
37
+ process_json(ATTRIBUTES, json)
35
38
  end
36
39
 
37
40
  def _validate(data, result:)
@@ -50,8 +53,14 @@ module Schemacop
50
53
  end
51
54
 
52
55
  # Validate pattern #
53
- if options[:pattern] && !super_data.match?(Regexp.compile(options[:pattern]))
54
- result.error "String does not match pattern #{options[:pattern].inspect}."
56
+ if (pattern = options[:pattern])
57
+ unless options[:pattern].is_a?(Regexp)
58
+ pattern = Regexp.compile(pattern)
59
+ end
60
+
61
+ unless super_data.match?(pattern)
62
+ result.error "String does not match pattern #{V3.sanitize_exp(pattern).inspect}."
63
+ end
55
64
  end
56
65
 
57
66
  # Validate format #
@@ -121,7 +130,9 @@ module Schemacop
121
130
  end
122
131
 
123
132
  if options[:pattern]
124
- fail 'Option "pattern" must be a string.' unless options[:pattern].is_a?(String)
133
+ unless options[:pattern].is_a?(String) || options[:pattern].is_a?(Regexp)
134
+ fail 'Option "pattern" must be a string or Regexp.'
135
+ end
125
136
 
126
137
  begin
127
138
  Regexp.compile(options[:pattern])
data/schemacop.gemspec CHANGED
@@ -1,14 +1,14 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: schemacop 3.0.2 ruby lib
2
+ # stub: schemacop 3.0.7 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "schemacop".freeze
6
- s.version = "3.0.2"
6
+ s.version = "3.0.7"
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
10
10
  s.authors = ["Sitrox".freeze]
11
- s.date = "2021-02-14"
11
+ s.date = "2021-02-22"
12
12
  s.files = [".gitignore".freeze, ".releaser_config".freeze, ".rubocop.yml".freeze, ".travis.yml".freeze, ".yardopts".freeze, "CHANGELOG.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "README_V2.md".freeze, "README_V3.md".freeze, "RUBY_VERSION".freeze, "Rakefile".freeze, "VERSION".freeze, "lib/schemacop.rb".freeze, "lib/schemacop/base_schema.rb".freeze, "lib/schemacop/exceptions.rb".freeze, "lib/schemacop/railtie.rb".freeze, "lib/schemacop/schema.rb".freeze, "lib/schemacop/schema2.rb".freeze, "lib/schemacop/schema3.rb".freeze, "lib/schemacop/scoped_env.rb".freeze, "lib/schemacop/v2.rb".freeze, "lib/schemacop/v2/caster.rb".freeze, "lib/schemacop/v2/collector.rb".freeze, "lib/schemacop/v2/dupper.rb".freeze, "lib/schemacop/v2/field_node.rb".freeze, "lib/schemacop/v2/node.rb".freeze, "lib/schemacop/v2/node_resolver.rb".freeze, "lib/schemacop/v2/node_supporting_field.rb".freeze, "lib/schemacop/v2/node_supporting_type.rb".freeze, "lib/schemacop/v2/node_with_block.rb".freeze, "lib/schemacop/v2/validator/array_validator.rb".freeze, "lib/schemacop/v2/validator/boolean_validator.rb".freeze, "lib/schemacop/v2/validator/float_validator.rb".freeze, "lib/schemacop/v2/validator/hash_validator.rb".freeze, "lib/schemacop/v2/validator/integer_validator.rb".freeze, "lib/schemacop/v2/validator/nil_validator.rb".freeze, "lib/schemacop/v2/validator/number_validator.rb".freeze, "lib/schemacop/v2/validator/object_validator.rb".freeze, "lib/schemacop/v2/validator/string_validator.rb".freeze, "lib/schemacop/v2/validator/symbol_validator.rb".freeze, "lib/schemacop/v3.rb".freeze, "lib/schemacop/v3/all_of_node.rb".freeze, "lib/schemacop/v3/any_of_node.rb".freeze, "lib/schemacop/v3/array_node.rb".freeze, "lib/schemacop/v3/boolean_node.rb".freeze, "lib/schemacop/v3/combination_node.rb".freeze, "lib/schemacop/v3/context.rb".freeze, "lib/schemacop/v3/dsl_scope.rb".freeze, "lib/schemacop/v3/global_context.rb".freeze, "lib/schemacop/v3/hash_node.rb".freeze, "lib/schemacop/v3/integer_node.rb".freeze, "lib/schemacop/v3/is_not_node.rb".freeze, "lib/schemacop/v3/node.rb".freeze, "lib/schemacop/v3/node_registry.rb".freeze, "lib/schemacop/v3/number_node.rb".freeze, "lib/schemacop/v3/numeric_node.rb".freeze, "lib/schemacop/v3/object_node.rb".freeze, "lib/schemacop/v3/one_of_node.rb".freeze, "lib/schemacop/v3/reference_node.rb".freeze, "lib/schemacop/v3/result.rb".freeze, "lib/schemacop/v3/string_node.rb".freeze, "lib/schemacop/v3/symbol_node.rb".freeze, "schemacop.gemspec".freeze, "test/lib/test_helper.rb".freeze, "test/schemas/nested/group.rb".freeze, "test/schemas/user.rb".freeze, "test/unit/schemacop/v2/casting_test.rb".freeze, "test/unit/schemacop/v2/collector_test.rb".freeze, "test/unit/schemacop/v2/custom_check_test.rb".freeze, "test/unit/schemacop/v2/custom_if_test.rb".freeze, "test/unit/schemacop/v2/defaults_test.rb".freeze, "test/unit/schemacop/v2/empty_test.rb".freeze, "test/unit/schemacop/v2/nil_dis_allow_test.rb".freeze, "test/unit/schemacop/v2/node_resolver_test.rb".freeze, "test/unit/schemacop/v2/short_forms_test.rb".freeze, "test/unit/schemacop/v2/types_test.rb".freeze, "test/unit/schemacop/v2/validator_array_test.rb".freeze, "test/unit/schemacop/v2/validator_boolean_test.rb".freeze, "test/unit/schemacop/v2/validator_float_test.rb".freeze, "test/unit/schemacop/v2/validator_hash_test.rb".freeze, "test/unit/schemacop/v2/validator_integer_test.rb".freeze, "test/unit/schemacop/v2/validator_nil_test.rb".freeze, "test/unit/schemacop/v2/validator_number_test.rb".freeze, "test/unit/schemacop/v2/validator_object_test.rb".freeze, "test/unit/schemacop/v2/validator_string_test.rb".freeze, "test/unit/schemacop/v2/validator_symbol_test.rb".freeze, "test/unit/schemacop/v3/all_of_node_test.rb".freeze, "test/unit/schemacop/v3/any_of_node_test.rb".freeze, "test/unit/schemacop/v3/array_node_test.rb".freeze, "test/unit/schemacop/v3/boolean_node_test.rb".freeze, "test/unit/schemacop/v3/global_context_test.rb".freeze, "test/unit/schemacop/v3/hash_node_test.rb".freeze, "test/unit/schemacop/v3/integer_node_test.rb".freeze, "test/unit/schemacop/v3/is_not_node_test.rb".freeze, "test/unit/schemacop/v3/node_test.rb".freeze, "test/unit/schemacop/v3/number_node_test.rb".freeze, "test/unit/schemacop/v3/object_node_test.rb".freeze, "test/unit/schemacop/v3/one_of_node_test.rb".freeze, "test/unit/schemacop/v3/reference_node_test.rb".freeze, "test/unit/schemacop/v3/string_node_test.rb".freeze, "test/unit/schemacop/v3/symbol_node_test.rb".freeze]
13
13
  s.homepage = "https://github.com/sitrox/schemacop".freeze
14
14
  s.licenses = ["MIT".freeze]
@@ -142,6 +142,13 @@ class V3Test < SchemacopTest
142
142
  assert_equal expected_json.as_json, @schema.as_json.as_json
143
143
  end
144
144
 
145
+ def assert_swagger_json(expected_json)
146
+ # TODO: Double "as_json" should not be necessary
147
+ Schemacop.context.with_json_format(:swagger) do
148
+ assert_equal expected_json.as_json, @schema.as_json.as_json
149
+ end
150
+ end
151
+
145
152
  def assert_match_any(array, exp)
146
153
  assert array.any? { |element| element.match?(exp) },
147
154
  "Expected any of #{array.inspect} to match #{exp}."
@@ -120,6 +120,22 @@ module Schemacop
120
120
  ]
121
121
  })
122
122
  end
123
+
124
+ def test_cast
125
+ schema :boolean
126
+
127
+ assert_cast(true, true)
128
+ assert_cast(false, false)
129
+ assert_cast(nil, nil)
130
+ end
131
+
132
+ def test_cast_default
133
+ schema :boolean, default: true
134
+
135
+ assert_cast(true, true)
136
+ assert_cast(false, false)
137
+ assert_cast(nil, true)
138
+ end
123
139
  end
124
140
  end
125
141
  end
@@ -125,6 +125,12 @@ module Schemacop
125
125
  exclusiveMinimum: 0
126
126
  )
127
127
 
128
+ assert_swagger_json(
129
+ type: :integer,
130
+ minimum: 0,
131
+ exclusiveMinimum: true
132
+ )
133
+
128
134
  assert_validation 5
129
135
  assert_validation 1
130
136
  assert_validation(0) do
@@ -158,6 +164,12 @@ module Schemacop
158
164
  exclusiveMaximum: 5
159
165
  )
160
166
 
167
+ assert_swagger_json(
168
+ type: :integer,
169
+ maximum: 5,
170
+ exclusiveMaximum: true
171
+ )
172
+
161
173
  assert_validation 4
162
174
  assert_validation 1
163
175
  assert_validation(5) do
@@ -63,6 +63,20 @@ module Schemacop
63
63
  })
64
64
  end
65
65
 
66
+ def test_swagger_example
67
+ schema :string, examples: ['Foo', 'Foo bar']
68
+
69
+ assert_json(
70
+ type: :string,
71
+ examples: ['Foo', 'Foo bar']
72
+ )
73
+
74
+ assert_swagger_json(
75
+ type: :string,
76
+ example: ['Foo', 'Foo bar']
77
+ )
78
+ end
79
+
66
80
  def test_cast_in_root
67
81
  schema :integer, cast_str: true, required: true
68
82
 
@@ -101,6 +101,12 @@ module Schemacop
101
101
  exclusiveMinimum: 0
102
102
  )
103
103
 
104
+ assert_swagger_json(
105
+ type: :number,
106
+ minimum: 0,
107
+ exclusiveMinimum: true
108
+ )
109
+
104
110
  assert_validation 5
105
111
  assert_validation 1
106
112
  assert_validation(0) do
@@ -134,6 +140,12 @@ module Schemacop
134
140
  exclusiveMaximum: 5
135
141
  )
136
142
 
143
+ assert_swagger_json(
144
+ type: :number,
145
+ maximum: 5,
146
+ exclusiveMaximum: true
147
+ )
148
+
137
149
  assert_validation 4
138
150
  assert_validation 1
139
151
  assert_validation(5) do
@@ -80,7 +80,7 @@ module Schemacop
80
80
  end
81
81
  end
82
82
 
83
- def test_pattern
83
+ def test_pattern_as_string
84
84
  schema :string, pattern: '^a_.*_z$'
85
85
 
86
86
  assert_json(type: :string, pattern: '^a_.*_z$')
@@ -95,6 +95,22 @@ module Schemacop
95
95
  end
96
96
  end
97
97
 
98
+ def test_pattern_as_regexp
99
+ schema :string, pattern: /^a_.*_z$/i
100
+
101
+ assert_json(type: :string, pattern: '^(?i)(a_.*_z)$')
102
+
103
+ assert_validation 'a__z'
104
+ assert_validation 'a__Z'
105
+ assert_validation 'a_ foo bar _Z'
106
+ assert_validation '' do
107
+ error '/', 'String does not match pattern "^(?i)(a_.*_z)$".'
108
+ end
109
+ assert_validation 'a_ _zfoo' do
110
+ error '/', 'String does not match pattern "^(?i)(a_.*_z)$".'
111
+ end
112
+ end
113
+
98
114
  def test_format_date
99
115
  schema :string, format: :date
100
116
 
@@ -314,8 +330,8 @@ module Schemacop
314
330
  end
315
331
 
316
332
  assert_raises_with_message Exceptions::InvalidSchemaError,
317
- 'Option "pattern" must be a string.' do
318
- schema :string, pattern: //
333
+ 'Option "pattern" must be a string or Regexp.' do
334
+ schema :string, pattern: 42
319
335
  end
320
336
 
321
337
  assert_raises_with_message Exceptions::InvalidSchemaError,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: schemacop
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.2
4
+ version: 3.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sitrox
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-14 00:00:00.000000000 Z
11
+ date: 2021-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport