request_handler 2.3.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +1 -1
  3. data/.rubocop.yml +13 -14
  4. data/.rubocop_todo.yml +105 -0
  5. data/CHANGELOG.md +7 -0
  6. data/Gemfile +1 -10
  7. data/Guardfile +4 -4
  8. data/Rakefile +7 -6
  9. data/bin/console +3 -3
  10. data/lib/request_handler/base.rb +41 -37
  11. data/lib/request_handler/body_parser.rb +5 -4
  12. data/lib/request_handler/builder/base.rb +1 -1
  13. data/lib/request_handler/builder/body_builder.rb +1 -1
  14. data/lib/request_handler/builder/fieldsets_builder.rb +2 -2
  15. data/lib/request_handler/builder/fieldsets_resource_builder.rb +1 -1
  16. data/lib/request_handler/builder/filter_builder.rb +1 -1
  17. data/lib/request_handler/builder/headers_builder.rb +1 -1
  18. data/lib/request_handler/builder/include_options_builder.rb +1 -1
  19. data/lib/request_handler/builder/multipart_builder.rb +2 -2
  20. data/lib/request_handler/builder/multipart_resource_builder.rb +1 -1
  21. data/lib/request_handler/builder/options_builder.rb +12 -10
  22. data/lib/request_handler/builder/page_builder.rb +2 -2
  23. data/lib/request_handler/builder/page_resource_builder.rb +1 -1
  24. data/lib/request_handler/builder/query_builder.rb +1 -1
  25. data/lib/request_handler/builder/sort_options_builder.rb +1 -1
  26. data/lib/request_handler/concerns/config_helper.rb +2 -2
  27. data/lib/request_handler/config.rb +3 -3
  28. data/lib/request_handler/document_parser.rb +5 -5
  29. data/lib/request_handler/error.rb +17 -1
  30. data/lib/request_handler/fieldsets_parser.rb +28 -24
  31. data/lib/request_handler/filter_parser.rb +15 -13
  32. data/lib/request_handler/header_parser.rb +10 -9
  33. data/lib/request_handler/include_option_parser.rb +18 -17
  34. data/lib/request_handler/json_api_document_parser.rb +31 -15
  35. data/lib/request_handler/json_parser.rb +4 -3
  36. data/lib/request_handler/multipart_parser.rb +20 -15
  37. data/lib/request_handler/option_parser.rb +3 -3
  38. data/lib/request_handler/page_parser.rb +33 -25
  39. data/lib/request_handler/query_parser.rb +6 -6
  40. data/lib/request_handler/schema_parser.rb +20 -17
  41. data/lib/request_handler/sort_option_parser.rb +19 -15
  42. data/lib/request_handler/validation/definition_engine.rb +7 -5
  43. data/lib/request_handler/validation/dry_engine.rb +7 -5
  44. data/lib/request_handler/validation/engine.rb +4 -3
  45. data/lib/request_handler/validation/errors.rb +2 -0
  46. data/lib/request_handler/validation/result.rb +1 -0
  47. data/lib/request_handler/version.rb +1 -1
  48. data/lib/request_handler.rb +8 -8
  49. data/request_handler.gemspec +42 -36
  50. metadata +178 -51
  51. data/lib/request_handler/base_parser.rb +0 -9
@@ -1,23 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'request_handler/error'
4
- require 'request_handler/base_parser'
3
+ require "request_handler/concerns/config_helper"
4
+ require "request_handler/error"
5
5
 
6
6
  module RequestHandler
7
- class PageParser < BaseParser
7
+ class PageParser
8
+ include RequestHandler::Concerns::ConfigHelper
9
+
8
10
  def initialize(params:, page_config:)
9
11
  missing_arguments = []
10
- missing_arguments << { params: 'is missing' } if params.nil?
11
- missing_arguments << { page_config: 'is missing' } if page_config.nil?
12
- raise MissingArgumentError, missing_arguments unless missing_arguments.empty?
13
- @page_options = params.fetch('page') { {} }
14
- raise PageParamsError, page: 'must be a Hash' unless @page_options.is_a?(Hash)
12
+ missing_arguments << { params: "is missing" } if params.nil?
13
+ missing_arguments << { page_config: "is missing" } if page_config.nil?
14
+ raise MissingArgumentError.new(missing_arguments) unless missing_arguments.empty?
15
+
16
+ @page_options = params.fetch("page") { {} }
17
+ raise PageParamsError.new(page: "must be a Hash") unless @page_options.is_a?(Hash)
18
+
15
19
  @config = page_config
16
20
  end
17
21
 
18
22
  def run
19
23
  cfg = deep_to_h(config).keys.reduce(base_page) do |memo, key|
20
24
  next memo if TOP_LEVEL_PAGE_KEYS.include?(key)
25
+
21
26
  memo.merge!("#{key}#{separator}number".to_sym => extract_number(prefix: key),
22
27
  "#{key}#{separator}size".to_sym => extract_size(prefix: key))
23
28
  end
@@ -37,12 +42,13 @@ module RequestHandler
37
42
  def check_for_missing_options(config)
38
43
  missing_arguments = page_options.keys - config.keys.map(&:to_s)
39
44
  return if missing_arguments.empty?
40
- missing_arguments.map! { |e| e.gsub(separator, '.') }
41
- warn 'client sent unknown option ' + missing_arguments.to_s unless missing_arguments.empty?
45
+
46
+ missing_arguments.map! { |e| e.gsub(separator, ".") }
47
+ warn "client sent unknown option #{missing_arguments}" unless missing_arguments.empty?
42
48
  end
43
49
 
44
50
  def extract_number(prefix: nil)
45
- number_string = lookup_nested_params_key('number', prefix) || 1
51
+ number_string = lookup_nested_params_key("number", prefix) || 1
46
52
  check_int(string: number_string, param: "#{prefix}.number")
47
53
  end
48
54
 
@@ -50,41 +56,43 @@ module RequestHandler
50
56
  size = fetch_and_check_size(prefix)
51
57
  default_size = fetch_and_check_default_size(prefix)
52
58
  return default_size if size.nil?
59
+
53
60
  apply_max_size_constraint(size, prefix)
54
61
  end
55
62
 
56
63
  def fetch_and_check_default_size(prefix)
57
- default_size = lookup_nested_config_key('default_size', prefix)
64
+ default_size = lookup_nested_config_key("default_size", prefix)
58
65
  raise_no_default_size(prefix) if default_size.nil?
59
- raise_not_positive(prefix, 'size') unless default_size.is_a?(Integer) && default_size > 0
66
+ raise_not_positive(prefix, "size") unless default_size.is_a?(Integer) && default_size.positive?
60
67
  default_size
61
68
  end
62
69
 
63
70
  def fetch_and_check_size(prefix)
64
- size_string = lookup_nested_params_key('size', prefix)
71
+ size_string = lookup_nested_params_key("size", prefix)
65
72
  return nil if size_string.nil?
73
+
66
74
  check_int(string: size_string, param: "#{prefix}.size") unless size_string.nil?
67
75
  end
68
76
 
69
77
  def check_int(string:, param:)
70
78
  output = Integer(string)
71
- raise_page_param_error!(param) unless output > 0
79
+ raise_page_param_error!(param) unless output.positive?
72
80
  output
73
81
  rescue ArgumentError
74
82
  raise_page_param_error!(param)
75
83
  end
76
84
 
77
85
  def raise_page_param_error!(param)
78
- raise PageParamsError, [{
79
- code: 'INVALID_QUERY_PARAMETER',
80
- status: '400',
81
- detail: 'must be a positive integer',
82
- source: { parameter: "page[#{param}]" }
83
- }]
86
+ raise PageParamsError.new([{
87
+ code: "INVALID_QUERY_PARAMETER",
88
+ status: "400",
89
+ detail: "must be a positive integer",
90
+ source: { parameter: "page[#{param}]" }
91
+ }])
84
92
  end
85
93
 
86
94
  def apply_max_size_constraint(size, prefix)
87
- max_size = lookup_nested_config_key('max_size', prefix)
95
+ max_size = lookup_nested_config_key("max_size", prefix)
88
96
  case max_size
89
97
  when Integer
90
98
  [max_size, size].min
@@ -92,7 +100,7 @@ module RequestHandler
92
100
  warn "#{prefix} max_size config not set"
93
101
  size
94
102
  else
95
- raise_not_positive(prefix, 'max_size', ' ')
103
+ raise_not_positive(prefix, "max_size", " ")
96
104
  end
97
105
  end
98
106
 
@@ -111,11 +119,11 @@ module RequestHandler
111
119
  end
112
120
 
113
121
  def raise_no_default_size(prefix, sep = separator)
114
- raise NoConfigAvailableError, :"#{prefix}#{sep}size" => 'has no default_size'
122
+ raise NoConfigAvailableError.new("#{prefix}#{sep}size": "has no default_size")
115
123
  end
116
124
 
117
125
  def raise_not_positive(prefix, key, sep = separator)
118
- raise InternalArgumentError, :"#{prefix}#{sep}#{key}" => 'must be a positive Integer'
126
+ raise InternalArgumentError.new("#{prefix}#{sep}#{key}": "must be a positive Integer")
119
127
  end
120
128
 
121
129
  def separator
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'request_handler/schema_parser'
4
- require 'request_handler/error'
3
+ require "request_handler/schema_parser"
4
+ require "request_handler/error"
5
5
  module RequestHandler
6
6
  class QueryParser < SchemaParser
7
7
  RESERVED_KEYS = %w[fields filter include page sort].freeze
@@ -15,13 +15,13 @@ module RequestHandler
15
15
  def run
16
16
  validate_schema(query)
17
17
  rescue SchemaValidationError => e
18
- raise ExternalArgumentError, (e.errors.map do |schema_error|
18
+ raise ExternalArgumentError.new((e.errors.map do |schema_error|
19
19
  param = schema_error[:source][:pointer]
20
- { status: '400',
21
- code: "#{query[param] ? 'INVALID' : 'MISSING'}_QUERY_PARAMETER",
20
+ { status: "400",
21
+ code: "#{query[param] ? 'INVALID' : 'MISSING'}_QUERY_PARAMETER",
22
22
  detail: schema_error[:detail],
23
23
  source: { parameter: param } }
24
- end)
24
+ end))
25
25
  end
26
26
 
27
27
  private
@@ -1,14 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'request_handler/error'
3
+ require "request_handler/error"
4
4
  module RequestHandler
5
5
  class SchemaParser
6
6
  def initialize(schema:, schema_options: {})
7
7
  missing_arguments = []
8
- missing_arguments << { schema: 'is missing' } if schema.nil?
9
- missing_arguments << { schema_options: 'is missing' } if schema_options.nil?
10
- raise MissingArgumentError, missing_arguments unless missing_arguments.empty?
11
- raise InternalArgumentError, schema: 'must be a Schema' unless validation_engine.valid_schema?(schema)
8
+ missing_arguments << { schema: "is missing" } if schema.nil?
9
+ missing_arguments << { schema_options: "is missing" } if schema_options.nil?
10
+ raise MissingArgumentError.new(missing_arguments) unless missing_arguments.empty?
11
+ raise InternalArgumentError.new(schema: "must be a Schema") unless validation_engine.valid_schema?(schema)
12
+
12
13
  @schema = schema
13
14
  @schema_options = schema_options
14
15
  end
@@ -16,7 +17,8 @@ module RequestHandler
16
17
  private
17
18
 
18
19
  def validate_schema(data, with: schema)
19
- raise MissingArgumentError, data: 'is missing' if data.nil?
20
+ raise MissingArgumentError.new(data: "is missing") if data.nil?
21
+
20
22
  validator = validate(data, schema: with)
21
23
  validation_failure?(validator)
22
24
  validator.output
@@ -32,7 +34,7 @@ module RequestHandler
32
34
  errors = build_errors(validator.errors).map do |error|
33
35
  jsonapi_error(error)
34
36
  end
35
- raise SchemaValidationError, errors
37
+ raise SchemaValidationError.new(errors)
36
38
  end
37
39
 
38
40
  def build_errors(error_hash, path = [])
@@ -46,19 +48,19 @@ module RequestHandler
46
48
  end
47
49
 
48
50
  def error(path, element, failure)
49
- schema_pointer = validation_engine.error_pointer(failure) || (path + [element]).join('/')
51
+ schema_pointer = validation_engine.error_pointer(failure) || (path + [element]).join("/")
50
52
  {
51
- schema_pointer: schema_pointer,
52
- element: element,
53
- message: validation_engine.error_message(failure)
53
+ schema_pointer: schema_pointer,
54
+ element: element,
55
+ message: validation_engine.error_message(failure)
54
56
  }
55
57
  end
56
58
 
57
59
  def jsonapi_error(error)
58
60
  {
59
- status: '422',
60
- code: 'INVALID_RESOURCE_SCHEMA',
61
- title: 'Invalid resource',
61
+ status: "422",
62
+ code: "INVALID_RESOURCE_SCHEMA",
63
+ title: "Invalid resource",
62
64
  detail: error[:message],
63
65
  source: { pointer: build_pointer(error) }
64
66
  }
@@ -69,9 +71,10 @@ module RequestHandler
69
71
  end
70
72
 
71
73
  def add_note(v, k, memo)
72
- memo[k] = if v.is_a? Array
73
- v.join(' ')
74
- elsif v.is_a? Hash
74
+ memo[k] = case v
75
+ when Array
76
+ v.join(" ")
77
+ when Hash
75
78
  v.each { |(val, key)| add_note(val, key, memo) }
76
79
  end
77
80
  memo
@@ -1,35 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'request_handler/option_parser'
4
- require 'request_handler/error'
5
- require 'request_handler/sort_option'
3
+ require "request_handler/option_parser"
4
+ require "request_handler/error"
5
+ require "request_handler/sort_option"
6
6
  module RequestHandler
7
7
  class SortOptionParser < OptionParser
8
8
  def run
9
- return [] unless params.key?('sort')
9
+ return [] unless params.key?("sort")
10
+
10
11
  sort_options = parse_options(fetch_options)
11
- raise SortParamsError, [jsonapi_error('sort options must be unique')] if duplicates?(sort_options)
12
+ raise SortParamsError.new([jsonapi_error("sort options must be unique")]) if duplicates?(sort_options)
13
+
12
14
  sort_options
13
15
  end
14
16
 
15
17
  def fetch_options
16
- raise SortParamsError, [jsonapi_error('must not be empty')] if empty_param?('sort')
17
- params.fetch('sort') { '' }.split(',')
18
+ raise SortParamsError.new([jsonapi_error("must not be empty")]) if empty_param?("sort")
19
+
20
+ params.fetch("sort", "").split(",")
18
21
  end
19
22
 
20
23
  def parse_options(options)
21
24
  options.map do |option|
22
25
  name, order = parse_option(option)
23
- name.gsub!('.', ::RequestHandler.configuration.separator)
26
+ name.gsub!(".", ::RequestHandler.configuration.separator)
24
27
  allowed_option(name)
25
28
  SortOption.new(name, order)
26
29
  end
27
30
  end
28
31
 
29
32
  def parse_option(option)
30
- raise SortParamsError, [jsonapi_error('must not contain spaces')] if option.include? ' '
31
- if option.start_with?('-')
32
- [option[1..-1], :desc]
33
+ raise SortParamsError.new([jsonapi_error("must not contain spaces")]) if option.include? " "
34
+
35
+ if option.start_with?("-")
36
+ [option[1..], :desc]
33
37
  else
34
38
  [option, :asc]
35
39
  end
@@ -38,7 +42,7 @@ module RequestHandler
38
42
  def allowed_option(name)
39
43
  RequestHandler.configuration.validation_engine.validate!(name, allowed_options_type).output
40
44
  rescue Validation::Error
41
- raise OptionNotAllowedError, [jsonapi_error("#{name} is not an allowed sort option")]
45
+ raise OptionNotAllowedError.new([jsonapi_error("#{name} is not an allowed sort option")])
42
46
  end
43
47
 
44
48
  def duplicates?(options)
@@ -49,9 +53,9 @@ module RequestHandler
49
53
 
50
54
  def jsonapi_error(detail)
51
55
  {
52
- code: 'INVALID_QUERY_PARAMETER',
53
- status: '400',
54
- source: { parameter: 'sort' },
56
+ code: "INVALID_QUERY_PARAMETER",
57
+ status: "400",
58
+ source: { parameter: "sort" },
55
59
  detail: detail
56
60
  }
57
61
  end
@@ -1,7 +1,9 @@
1
- require_relative 'errors'
2
- require_relative 'engine'
3
- require_relative 'result'
4
- require 'active_support/core_ext/hash/keys'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "errors"
4
+ require_relative "engine"
5
+ require_relative "result"
6
+ require "active_support/core_ext/hash/keys"
5
7
 
6
8
  module RequestHandler
7
9
  module Validation
@@ -28,7 +30,7 @@ module RequestHandler
28
30
  end
29
31
 
30
32
  def self.error_pointer(validation_error)
31
- validation_error.error_path.join('/')
33
+ validation_error.error_path.join("/")
32
34
  end
33
35
  end
34
36
  end
@@ -1,7 +1,9 @@
1
- require_relative 'errors'
2
- require_relative 'engine'
3
- require_relative 'result'
4
- require 'active_support/core_ext/hash/keys'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "errors"
4
+ require_relative "engine"
5
+ require_relative "result"
6
+ require "active_support/core_ext/hash/keys"
5
7
 
6
8
  module RequestHandler
7
9
  module Validation
@@ -14,7 +16,7 @@ module RequestHandler
14
16
  value = value.deep_symbolize_keys if value.is_a?(Hash)
15
17
  to_result(call_schema(value, schema, options))
16
18
  rescue Dry::Types::ConstraintError => e
17
- Result.new(output: nil, errors: { '' => e })
19
+ Result.new(output: nil, errors: { "" => e })
18
20
  end
19
21
 
20
22
  def self.call_schema(value, schema, options)
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
1
2
 
2
- require_relative 'errors'
3
+ require_relative "errors"
3
4
 
4
5
  module RequestHandler
5
6
  module Validation
@@ -8,11 +9,11 @@ module RequestHandler
8
9
  raise NotImplementedError
9
10
  end
10
11
 
11
- def self.validate(_value, _schema, options: {}) # rubocop:disable Lint/UnusedMethodArgument
12
+ def self.validate(_value, _schema, options: {})
12
13
  raise NotImplementedError
13
14
  end
14
15
 
15
- def self.validate!(_value, _schema, options: {}) # rubocop:disable Lint/UnusedMethodArgument
16
+ def self.validate!(_value, _schema, options: {})
16
17
  raise NotImplementedError
17
18
  end
18
19
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RequestHandler
2
4
  module Validation
3
5
  class Error < StandardError; end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module RequestHandler
3
4
  module Validation
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RequestHandler
4
- VERSION = '2.3.0'.freeze
4
+ VERSION = "3.0.0"
5
5
  end
@@ -1,19 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'request_handler/version'
4
- require 'request_handler/base'
5
- require 'request_handler/validation/dry_engine'
6
- require 'multi_json'
7
- require 'logger'
8
- require 'gem_config'
3
+ require "request_handler/version"
4
+ require "request_handler/base"
5
+ require "request_handler/validation/dry_engine"
6
+ require "multi_json"
7
+ require "logger"
8
+ require "gem_config"
9
9
 
10
10
  module RequestHandler
11
11
  include GemConfig::Base
12
12
 
13
13
  with_configuration do
14
14
  has :validation_engine
15
- has :logger, default: Logger.new(STDOUT)
16
- has :separator, classes: [String], default: '__'
15
+ has :logger, default: Logger.new($stdout)
16
+ has :separator, classes: [String], default: "__"
17
17
  has :raise_jsonapi_errors, default: false
18
18
  end
19
19
  end
@@ -1,48 +1,54 @@
1
- # coding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
- lib = File.expand_path('../lib', __FILE__)
3
+ lib = File.expand_path("lib", __dir__)
5
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
- require 'request_handler/version'
5
+ require "request_handler/version"
7
6
  Gem::Specification.new do |spec|
8
- spec.name = 'request_handler'
7
+ spec.name = "request_handler"
9
8
  spec.version = RequestHandler::VERSION
10
- spec.authors = ['Andreas Eger', 'Dominik Goltermann']
11
- spec.email = ['andreas.eger@runtastic.com', 'dominik.goltermann@runtastic.com']
9
+ spec.authors = ["Andreas Eger", "Dominik Goltermann"]
10
+ spec.email = ["andreas.eger@runtastic.com", "dominik.goltermann@runtastic.com"]
12
11
 
13
- spec.summary = 'shared base for request_handler using dry-* gems'
14
- spec.description = 'shared base for request_handler using dry-* gems'
15
- spec.homepage = 'https://github.com/runtastic/request_handler'
16
- spec.license = 'MIT'
17
- spec.required_ruby_version = '>= 2.6'
12
+ spec.summary = "shared base for request_handler using dry-* gems"
13
+ spec.description = "shared base for request_handler using dry-* gems"
14
+ spec.homepage = "https://github.com/runtastic/request_handler"
15
+ spec.license = "MIT"
16
+ spec.required_ruby_version = ">= 2.6"
18
17
 
19
18
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
20
19
  f.match(%r{^(test|spec|features)/})
21
20
  end
22
- spec.bindir = 'exe'
21
+ spec.bindir = "exe"
23
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
- spec.require_paths = ['lib']
25
-
26
- spec.add_dependency 'docile', '~> 1.3'
27
- spec.add_dependency 'multi_json', '~> 1.12'
28
- spec.add_dependency 'activesupport', '> 4.0'
29
- spec.add_dependency 'gem_config', '~> 0.3 '
30
-
31
- spec.add_development_dependency 'bundler'
32
- spec.add_development_dependency 'rake', '~> 10.0'
33
- spec.add_development_dependency 'rspec', '~> 3.5'
34
- spec.add_development_dependency 'fuubar', '~> 2.2'
35
- spec.add_development_dependency 'simplecov'
36
- spec.add_development_dependency 'codecov'
37
-
38
- spec.add_development_dependency 'rubocop_runner', '~> 2.0'
39
- spec.add_development_dependency 'rubocop', '~> 0.48.1'
40
-
41
- spec.add_development_dependency 'guard'
42
- spec.add_development_dependency 'guard-rspec'
43
- spec.add_development_dependency 'guard-rubocop'
44
-
45
- spec.add_development_dependency 'rack'
46
-
47
- spec.add_development_dependency 'definition', '~> 0.7'
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.add_runtime_dependency "activesupport", "> 4.0"
26
+ spec.add_runtime_dependency "docile", "~> 1.3"
27
+ spec.add_runtime_dependency "gem_config", "~> 0.3 "
28
+ spec.add_runtime_dependency "multi_json", "~> 1.12"
29
+
30
+ spec.add_development_dependency "bundler"
31
+ spec.add_development_dependency "codecov"
32
+ spec.add_development_dependency "danger"
33
+ spec.add_development_dependency "danger-commit_lint"
34
+ spec.add_development_dependency "danger-rubocop"
35
+ spec.add_development_dependency "definition", "~> 0.7"
36
+ spec.add_development_dependency "dry-types", "~> 1.0"
37
+ spec.add_development_dependency "dry-validation", "~> 1.0"
38
+ spec.add_development_dependency "fuubar", "~> 2.2"
39
+ spec.add_development_dependency "guard"
40
+ spec.add_development_dependency "guard-rspec"
41
+ spec.add_development_dependency "guard-rubocop"
42
+ spec.add_development_dependency "rack"
43
+ spec.add_development_dependency "rake", "~> 10.0"
44
+ spec.add_development_dependency "rspec", "~> 3.5"
45
+ spec.add_development_dependency "rspec_junit_formatter"
46
+ spec.add_development_dependency "rt_rubocop_defaults", "~> 2.5"
47
+ spec.add_development_dependency "rubocop", "~> 1.44"
48
+ spec.add_development_dependency "rubocop-rake", "~> 0.6"
49
+ spec.add_development_dependency "rubocop-rspec", "~> 2.18"
50
+ spec.add_development_dependency "rubocop_runner", "~> 2.0"
51
+ spec.add_development_dependency "simplecov"
52
+
53
+ spec.metadata["rubygems_mfa_required"] = "true"
48
54
  end