grape 1.8.0 → 2.1.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 +65 -1
- data/README.md +377 -334
- data/UPGRADING.md +231 -6
- data/grape.gemspec +6 -10
- data/lib/grape/api/instance.rb +13 -10
- data/lib/grape/api.rb +17 -8
- data/lib/grape/content_types.rb +0 -2
- data/lib/grape/cookies.rb +2 -1
- data/lib/grape/dry_types.rb +0 -2
- data/lib/grape/dsl/desc.rb +23 -21
- data/lib/grape/dsl/headers.rb +1 -1
- data/lib/grape/dsl/inside_route.rb +47 -22
- data/lib/grape/dsl/parameters.rb +4 -3
- data/lib/grape/dsl/routing.rb +20 -4
- data/lib/grape/dsl/validations.rb +13 -0
- data/lib/grape/endpoint.rb +15 -10
- data/lib/grape/{util/env.rb → env.rb} +0 -5
- data/lib/grape/error_formatter/txt.rb +11 -10
- data/lib/grape/exceptions/base.rb +3 -3
- data/lib/grape/exceptions/missing_group_type.rb +1 -1
- data/lib/grape/exceptions/unsupported_group_type.rb +1 -1
- data/lib/grape/exceptions/validation.rb +0 -2
- data/lib/grape/exceptions/validation_array_errors.rb +1 -0
- data/lib/grape/exceptions/validation_errors.rb +1 -3
- data/lib/grape/extensions/hash.rb +5 -1
- data/lib/grape/http/headers.rb +18 -24
- data/lib/grape/{util/json.rb → json.rb} +1 -3
- data/lib/grape/locale/en.yml +3 -0
- data/lib/grape/middleware/auth/base.rb +0 -2
- data/lib/grape/middleware/auth/dsl.rb +0 -2
- data/lib/grape/middleware/auth/strategies.rb +1 -2
- data/lib/grape/middleware/base.rb +0 -2
- data/lib/grape/middleware/error.rb +55 -50
- data/lib/grape/middleware/formatter.rb +21 -18
- data/lib/grape/middleware/globals.rb +1 -3
- data/lib/grape/middleware/stack.rb +2 -3
- data/lib/grape/middleware/versioner/accept_version_header.rb +0 -2
- data/lib/grape/middleware/versioner/header.rb +17 -163
- data/lib/grape/middleware/versioner/param.rb +2 -4
- data/lib/grape/middleware/versioner/path.rb +1 -3
- data/lib/grape/namespace.rb +3 -4
- data/lib/grape/path.rb +24 -29
- data/lib/grape/railtie.rb +9 -0
- data/lib/grape/request.rb +3 -5
- data/lib/grape/router/base_route.rb +39 -0
- data/lib/grape/router/greedy_route.rb +20 -0
- data/lib/grape/router/pattern.rb +39 -30
- data/lib/grape/router/route.rb +22 -59
- data/lib/grape/router.rb +30 -36
- data/lib/grape/util/accept/header.rb +19 -0
- data/lib/grape/util/accept_header_handler.rb +105 -0
- data/lib/grape/util/base_inheritable.rb +4 -4
- data/lib/grape/util/cache.rb +0 -3
- data/lib/grape/util/endpoint_configuration.rb +1 -1
- data/lib/grape/util/header.rb +13 -0
- data/lib/grape/util/inheritable_values.rb +0 -2
- data/lib/grape/util/lazy/block.rb +29 -0
- data/lib/grape/util/lazy/object.rb +45 -0
- data/lib/grape/util/lazy/value.rb +38 -0
- data/lib/grape/util/lazy/value_array.rb +21 -0
- data/lib/grape/util/lazy/value_enumerable.rb +34 -0
- data/lib/grape/util/lazy/value_hash.rb +21 -0
- data/lib/grape/util/media_type.rb +70 -0
- data/lib/grape/util/reverse_stackable_values.rb +1 -6
- data/lib/grape/util/stackable_values.rb +1 -6
- data/lib/grape/util/strict_hash_configuration.rb +3 -3
- data/lib/grape/validations/attributes_doc.rb +38 -36
- data/lib/grape/validations/contract_scope.rb +71 -0
- data/lib/grape/validations/params_scope.rb +10 -9
- data/lib/grape/validations/types/array_coercer.rb +0 -2
- data/lib/grape/validations/types/build_coercer.rb +69 -71
- data/lib/grape/validations/types/dry_type_coercer.rb +1 -11
- data/lib/grape/validations/types/json.rb +0 -2
- data/lib/grape/validations/types/primitive_coercer.rb +0 -2
- data/lib/grape/validations/types/set_coercer.rb +0 -3
- data/lib/grape/validations/types.rb +0 -3
- data/lib/grape/validations/validators/base.rb +2 -1
- data/lib/grape/validations/validators/default_validator.rb +5 -1
- data/lib/grape/validations/validators/length_validator.rb +42 -0
- data/lib/grape/validations/validators/values_validator.rb +8 -3
- data/lib/grape/validations.rb +3 -7
- data/lib/grape/version.rb +1 -1
- data/lib/grape/{util/xml.rb → xml.rb} +1 -1
- data/lib/grape.rb +38 -269
- metadata +33 -274
- data/lib/grape/eager_load.rb +0 -20
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +0 -24
- data/lib/grape/router/attribute_translator.rb +0 -63
- data/lib/grape/util/lazy_block.rb +0 -27
- data/lib/grape/util/lazy_object.rb +0 -43
- data/lib/grape/util/lazy_value.rb +0 -91
- data/spec/grape/api/custom_validations_spec.rb +0 -213
- data/spec/grape/api/deeply_included_options_spec.rb +0 -56
- data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -38
- data/spec/grape/api/documentation_spec.rb +0 -59
- data/spec/grape/api/inherited_helpers_spec.rb +0 -114
- data/spec/grape/api/instance_spec.rb +0 -103
- data/spec/grape/api/invalid_format_spec.rb +0 -45
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -38
- data/spec/grape/api/nested_helpers_spec.rb +0 -50
- data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -43
- data/spec/grape/api/parameters_modification_spec.rb +0 -41
- data/spec/grape/api/patch_method_helpers_spec.rb +0 -79
- data/spec/grape/api/recognize_path_spec.rb +0 -21
- data/spec/grape/api/required_parameters_in_route_spec.rb +0 -37
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -26
- data/spec/grape/api/routes_with_requirements_spec.rb +0 -59
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -41
- data/spec/grape/api/shared_helpers_spec.rb +0 -36
- data/spec/grape/api_remount_spec.rb +0 -509
- data/spec/grape/api_spec.rb +0 -4356
- data/spec/grape/dsl/callbacks_spec.rb +0 -45
- data/spec/grape/dsl/desc_spec.rb +0 -98
- data/spec/grape/dsl/headers_spec.rb +0 -62
- data/spec/grape/dsl/helpers_spec.rb +0 -100
- data/spec/grape/dsl/inside_route_spec.rb +0 -531
- data/spec/grape/dsl/logger_spec.rb +0 -24
- data/spec/grape/dsl/middleware_spec.rb +0 -60
- data/spec/grape/dsl/parameters_spec.rb +0 -180
- data/spec/grape/dsl/request_response_spec.rb +0 -225
- data/spec/grape/dsl/routing_spec.rb +0 -275
- data/spec/grape/dsl/settings_spec.rb +0 -261
- data/spec/grape/dsl/validations_spec.rb +0 -55
- data/spec/grape/endpoint/declared_spec.rb +0 -846
- data/spec/grape/endpoint_spec.rb +0 -1085
- data/spec/grape/entity_spec.rb +0 -336
- data/spec/grape/exceptions/base_spec.rb +0 -81
- data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -185
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -358
- data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -15
- data/spec/grape/exceptions/invalid_response_spec.rb +0 -11
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +0 -15
- data/spec/grape/exceptions/missing_group_type_spec.rb +0 -17
- data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -17
- data/spec/grape/exceptions/missing_option_spec.rb +0 -15
- data/spec/grape/exceptions/unknown_options_spec.rb +0 -15
- data/spec/grape/exceptions/unknown_validator_spec.rb +0 -15
- data/spec/grape/exceptions/unsupported_group_type_spec.rb +0 -19
- data/spec/grape/exceptions/validation_errors_spec.rb +0 -92
- data/spec/grape/exceptions/validation_spec.rb +0 -19
- data/spec/grape/extensions/param_builders/hash_spec.rb +0 -83
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -105
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -79
- data/spec/grape/grape_spec.rb +0 -9
- data/spec/grape/integration/global_namespace_function_spec.rb +0 -29
- data/spec/grape/integration/rack_sendfile_spec.rb +0 -48
- data/spec/grape/integration/rack_spec.rb +0 -51
- data/spec/grape/loading_spec.rb +0 -44
- data/spec/grape/middleware/auth/base_spec.rb +0 -31
- data/spec/grape/middleware/auth/dsl_spec.rb +0 -60
- data/spec/grape/middleware/auth/strategies_spec.rb +0 -120
- data/spec/grape/middleware/base_spec.rb +0 -221
- data/spec/grape/middleware/error_spec.rb +0 -85
- data/spec/grape/middleware/exception_spec.rb +0 -294
- data/spec/grape/middleware/formatter_spec.rb +0 -461
- data/spec/grape/middleware/globals_spec.rb +0 -30
- data/spec/grape/middleware/stack_spec.rb +0 -155
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -122
- data/spec/grape/middleware/versioner/header_spec.rb +0 -345
- data/spec/grape/middleware/versioner/param_spec.rb +0 -171
- data/spec/grape/middleware/versioner/path_spec.rb +0 -62
- data/spec/grape/middleware/versioner_spec.rb +0 -21
- data/spec/grape/named_api_spec.rb +0 -19
- data/spec/grape/parser_spec.rb +0 -86
- data/spec/grape/path_spec.rb +0 -252
- data/spec/grape/presenters/presenter_spec.rb +0 -71
- data/spec/grape/request_spec.rb +0 -126
- data/spec/grape/util/inheritable_setting_spec.rb +0 -242
- data/spec/grape/util/inheritable_values_spec.rb +0 -79
- data/spec/grape/util/reverse_stackable_values_spec.rb +0 -134
- data/spec/grape/util/stackable_values_spec.rb +0 -128
- data/spec/grape/util/strict_hash_configuration_spec.rb +0 -38
- data/spec/grape/validations/attributes_doc_spec.rb +0 -153
- data/spec/grape/validations/instance_behaivour_spec.rb +0 -43
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -38
- data/spec/grape/validations/params_scope_spec.rb +0 -1420
- data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -56
- data/spec/grape/validations/types/array_coercer_spec.rb +0 -33
- data/spec/grape/validations/types/primitive_coercer_spec.rb +0 -150
- data/spec/grape/validations/types/set_coercer_spec.rb +0 -32
- data/spec/grape/validations/types_spec.rb +0 -111
- data/spec/grape/validations/validators/all_or_none_spec.rb +0 -162
- data/spec/grape/validations/validators/allow_blank_spec.rb +0 -575
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -205
- data/spec/grape/validations/validators/base_spec.rb +0 -38
- data/spec/grape/validations/validators/coerce_spec.rb +0 -1261
- data/spec/grape/validations/validators/default_spec.rb +0 -463
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -233
- data/spec/grape/validations/validators/except_values_spec.rb +0 -192
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -214
- data/spec/grape/validations/validators/presence_spec.rb +0 -315
- data/spec/grape/validations/validators/regexp_spec.rb +0 -161
- data/spec/grape/validations/validators/same_as_spec.rb +0 -57
- data/spec/grape/validations/validators/values_spec.rb +0 -733
- data/spec/grape/validations/validators/zh-CN.yml +0 -10
- data/spec/grape/validations_spec.rb +0 -2030
- data/spec/integration/eager_load/eager_load_spec.rb +0 -15
- data/spec/integration/multi_json/json_spec.rb +0 -7
- data/spec/integration/multi_xml/xml_spec.rb +0 -7
- data/spec/shared/deprecated_class_examples.rb +0 -16
- data/spec/shared/versioning_examples.rb +0 -215
- data/spec/spec_helper.rb +0 -52
- data/spec/support/basic_auth_encode_helpers.rb +0 -11
- data/spec/support/chunks.rb +0 -14
- data/spec/support/content_type_helpers.rb +0 -15
- data/spec/support/endpoint_faker.rb +0 -25
- data/spec/support/file_streamer.rb +0 -13
- data/spec/support/integer_helpers.rb +0 -13
- data/spec/support/versioned_helpers.rb +0 -55
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Grape
|
|
4
|
-
module Util
|
|
5
|
-
class LazyValue
|
|
6
|
-
attr_reader :access_keys
|
|
7
|
-
|
|
8
|
-
def initialize(value, access_keys = [])
|
|
9
|
-
@value = value
|
|
10
|
-
@access_keys = access_keys
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def evaluate_from(configuration)
|
|
14
|
-
matching_lazy_value = configuration.fetch(@access_keys)
|
|
15
|
-
matching_lazy_value.evaluate
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def evaluate
|
|
19
|
-
@value
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def lazy?
|
|
23
|
-
true
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def reached_by(parent_access_keys, access_key)
|
|
27
|
-
@access_keys = parent_access_keys + [access_key]
|
|
28
|
-
self
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def to_s
|
|
32
|
-
evaluate.to_s
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
class LazyValueEnumerable < LazyValue
|
|
37
|
-
def [](key)
|
|
38
|
-
if @value_hash[key].nil?
|
|
39
|
-
LazyValue.new(nil).reached_by(access_keys, key)
|
|
40
|
-
else
|
|
41
|
-
@value_hash[key].reached_by(access_keys, key)
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def fetch(access_keys)
|
|
46
|
-
fetched_keys = access_keys.dup
|
|
47
|
-
value = self[fetched_keys.shift]
|
|
48
|
-
fetched_keys.any? ? value.fetch(fetched_keys) : value
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def []=(key, value)
|
|
52
|
-
@value_hash[key] = case value
|
|
53
|
-
when Hash
|
|
54
|
-
LazyValueHash.new(value)
|
|
55
|
-
when Array
|
|
56
|
-
LazyValueArray.new(value)
|
|
57
|
-
else
|
|
58
|
-
LazyValue.new(value)
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
class LazyValueArray < LazyValueEnumerable
|
|
64
|
-
def initialize(array)
|
|
65
|
-
super
|
|
66
|
-
@value_hash = []
|
|
67
|
-
array.each_with_index do |value, index|
|
|
68
|
-
self[index] = value
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def evaluate
|
|
73
|
-
@value_hash.map(&:evaluate)
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
class LazyValueHash < LazyValueEnumerable
|
|
78
|
-
def initialize(hash)
|
|
79
|
-
super
|
|
80
|
-
@value_hash = ActiveSupport::HashWithIndifferentAccess.new
|
|
81
|
-
hash.each do |key, value|
|
|
82
|
-
self[key] = value
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def evaluate
|
|
87
|
-
@value_hash.transform_values(&:evaluate)
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'shared/deprecated_class_examples'
|
|
4
|
-
|
|
5
|
-
describe Grape::Validations do
|
|
6
|
-
describe 'Grape::Validations::Base' do
|
|
7
|
-
let(:deprecated_class) do
|
|
8
|
-
Class.new(Grape::Validations::Base)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
it_behaves_like 'deprecated class'
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
describe 'using a custom length validator' do
|
|
15
|
-
subject do
|
|
16
|
-
Class.new(Grape::API) do
|
|
17
|
-
params do
|
|
18
|
-
requires :text, default_length: 140
|
|
19
|
-
end
|
|
20
|
-
get do
|
|
21
|
-
'bacon'
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
let(:default_length_validator) do
|
|
27
|
-
Class.new(Grape::Validations::Validators::Base) do
|
|
28
|
-
def validate_param!(attr_name, params)
|
|
29
|
-
@option = params[:max].to_i if params.key?(:max)
|
|
30
|
-
return if params[attr_name].length <= @option
|
|
31
|
-
|
|
32
|
-
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: "must be at the most #{@option} characters long")
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
let(:app) { Rack::Builder.new(subject) }
|
|
37
|
-
|
|
38
|
-
before do
|
|
39
|
-
described_class.register_validator('default_length', default_length_validator)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
after do
|
|
43
|
-
described_class.deregister_validator('default_length')
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it 'under 140 characters' do
|
|
47
|
-
get '/', text: 'abc'
|
|
48
|
-
expect(last_response.status).to eq 200
|
|
49
|
-
expect(last_response.body).to eq 'bacon'
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it 'over 140 characters' do
|
|
53
|
-
get '/', text: 'a' * 141
|
|
54
|
-
expect(last_response.status).to eq 400
|
|
55
|
-
expect(last_response.body).to eq 'text must be at the most 140 characters long'
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
it 'specified in the query string' do
|
|
59
|
-
get '/', text: 'a' * 141, max: 141
|
|
60
|
-
expect(last_response.status).to eq 200
|
|
61
|
-
expect(last_response.body).to eq 'bacon'
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
describe 'using a custom body-only validator' do
|
|
66
|
-
subject do
|
|
67
|
-
Class.new(Grape::API) do
|
|
68
|
-
params do
|
|
69
|
-
requires :text, in_body: true
|
|
70
|
-
end
|
|
71
|
-
get do
|
|
72
|
-
'bacon'
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
let(:in_body_validator) do
|
|
78
|
-
Class.new(Grape::Validations::Validators::PresenceValidator) do
|
|
79
|
-
def validate(request)
|
|
80
|
-
validate!(request.env['api.request.body'])
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
let(:app) { Rack::Builder.new(subject) }
|
|
85
|
-
|
|
86
|
-
before do
|
|
87
|
-
described_class.register_validator('in_body', in_body_validator)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
after do
|
|
91
|
-
described_class.deregister_validator('in_body')
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
it 'allows field in body' do
|
|
95
|
-
get '/', text: 'abc'
|
|
96
|
-
expect(last_response.status).to eq 200
|
|
97
|
-
expect(last_response.body).to eq 'bacon'
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
it 'ignores field in query' do
|
|
101
|
-
get '/', nil, text: 'abc'
|
|
102
|
-
expect(last_response.status).to eq 400
|
|
103
|
-
expect(last_response.body).to eq 'text is missing'
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
describe 'using a custom validator with message_key' do
|
|
108
|
-
subject do
|
|
109
|
-
Class.new(Grape::API) do
|
|
110
|
-
params do
|
|
111
|
-
requires :text, with_message_key: true
|
|
112
|
-
end
|
|
113
|
-
get do
|
|
114
|
-
'bacon'
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
let(:message_key_validator) do
|
|
120
|
-
Class.new(Grape::Validations::Validators::PresenceValidator) do
|
|
121
|
-
def validate_param!(attr_name, _params)
|
|
122
|
-
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: :presence)
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
let(:app) { Rack::Builder.new(subject) }
|
|
127
|
-
|
|
128
|
-
before do
|
|
129
|
-
described_class.register_validator('with_message_key', message_key_validator)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
after do
|
|
133
|
-
described_class.deregister_validator('with_message_key')
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
it 'fails with message' do
|
|
137
|
-
get '/', text: 'foobar'
|
|
138
|
-
expect(last_response.status).to eq 400
|
|
139
|
-
expect(last_response.body).to eq 'text is missing'
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
describe 'using a custom request/param validator' do
|
|
144
|
-
subject do
|
|
145
|
-
Class.new(Grape::API) do
|
|
146
|
-
params do
|
|
147
|
-
optional :admin_field, type: String, admin: true
|
|
148
|
-
optional :non_admin_field, type: String
|
|
149
|
-
optional :admin_false_field, type: String, admin: false
|
|
150
|
-
end
|
|
151
|
-
get do
|
|
152
|
-
'bacon'
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
let(:admin_validator) do
|
|
158
|
-
Class.new(Grape::Validations::Validators::Base) do
|
|
159
|
-
def validate(request)
|
|
160
|
-
# return if the param we are checking was not in request
|
|
161
|
-
# @attrs is a list containing the attribute we are currently validating
|
|
162
|
-
return unless request.params.key? @attrs.first
|
|
163
|
-
# check if admin flag is set to true
|
|
164
|
-
return unless @option
|
|
165
|
-
# check if user is admin or not
|
|
166
|
-
# as an example get a token from request and check if it's admin or not
|
|
167
|
-
raise Grape::Exceptions::Validation.new(params: @attrs, message: 'Can not set Admin only field.') unless request.headers['X-Access-Token'] == 'admin'
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
let(:app) { Rack::Builder.new(subject) }
|
|
172
|
-
|
|
173
|
-
before do
|
|
174
|
-
described_class.register_validator('admin', admin_validator)
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
after do
|
|
178
|
-
described_class.deregister_validator('admin')
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
it 'fail when non-admin user sets an admin field' do
|
|
182
|
-
get '/', admin_field: 'tester', non_admin_field: 'toaster'
|
|
183
|
-
expect(last_response.status).to eq 400
|
|
184
|
-
expect(last_response.body).to include 'Can not set Admin only field.'
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
it 'does not fail when we send non-admin fields only' do
|
|
188
|
-
get '/', non_admin_field: 'toaster'
|
|
189
|
-
expect(last_response.status).to eq 200
|
|
190
|
-
expect(last_response.body).to eq 'bacon'
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
it 'does not fail when we send non-admin and admin=false fields only' do
|
|
194
|
-
get '/', non_admin_field: 'toaster', admin_false_field: 'test'
|
|
195
|
-
expect(last_response.status).to eq 200
|
|
196
|
-
expect(last_response.body).to eq 'bacon'
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
it 'does not fail when we send admin fields and we are admin' do
|
|
200
|
-
header 'X-Access-Token', 'admin'
|
|
201
|
-
get '/', admin_field: 'tester', non_admin_field: 'toaster', admin_false_field: 'test'
|
|
202
|
-
expect(last_response.status).to eq 200
|
|
203
|
-
expect(last_response.body).to eq 'bacon'
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
it 'fails when we send admin fields and we are not admin' do
|
|
207
|
-
header 'X-Access-Token', 'user'
|
|
208
|
-
get '/', admin_field: 'tester', non_admin_field: 'toaster', admin_false_field: 'test'
|
|
209
|
-
expect(last_response.status).to eq 400
|
|
210
|
-
expect(last_response.body).to include 'Can not set Admin only field.'
|
|
211
|
-
end
|
|
212
|
-
end
|
|
213
|
-
end
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module DeeplyIncludedOptionsSpec
|
|
4
|
-
module Defaults
|
|
5
|
-
extend ActiveSupport::Concern
|
|
6
|
-
included do
|
|
7
|
-
format :json
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
module Admin
|
|
12
|
-
module Defaults
|
|
13
|
-
extend ActiveSupport::Concern
|
|
14
|
-
include DeeplyIncludedOptionsSpec::Defaults
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
class Users < Grape::API
|
|
18
|
-
include DeeplyIncludedOptionsSpec::Admin::Defaults
|
|
19
|
-
|
|
20
|
-
resource :users do
|
|
21
|
-
get do
|
|
22
|
-
status 200
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
class Main < Grape::API
|
|
29
|
-
mount DeeplyIncludedOptionsSpec::Admin::Users
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
describe Grape::API do
|
|
34
|
-
subject { DeeplyIncludedOptionsSpec::Main }
|
|
35
|
-
|
|
36
|
-
def app
|
|
37
|
-
subject
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
it 'works for unspecified format' do
|
|
41
|
-
get '/users'
|
|
42
|
-
expect(last_response.status).to be 200
|
|
43
|
-
expect(last_response.content_type).to eql 'application/json'
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it 'works for specified format' do
|
|
47
|
-
get '/users.json'
|
|
48
|
-
expect(last_response.status).to be 200
|
|
49
|
-
expect(last_response.content_type).to eql 'application/json'
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it "doesn't work for format different than specified" do
|
|
53
|
-
get '/users.txt'
|
|
54
|
-
expect(last_response.status).to be 404
|
|
55
|
-
end
|
|
56
|
-
end
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
describe Grape::API::Instance do
|
|
4
|
-
describe 'boolean constant' do
|
|
5
|
-
module DefinesBooleanInstanceSpec
|
|
6
|
-
class API < Grape::API
|
|
7
|
-
params do
|
|
8
|
-
requires :message, type: Boolean
|
|
9
|
-
end
|
|
10
|
-
post :echo do
|
|
11
|
-
{ class: params[:message].class.name, value: params[:message] }
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def app
|
|
17
|
-
DefinesBooleanInstanceSpec::API
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
let(:expected_body) do
|
|
21
|
-
{ class: 'TrueClass', value: true }.to_s
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
it 'sets Boolean as a type' do
|
|
25
|
-
post '/echo?message=true'
|
|
26
|
-
expect(last_response.status).to eq(201)
|
|
27
|
-
expect(last_response.body).to eq expected_body
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
context 'Params endpoint type' do
|
|
31
|
-
subject { DefinesBooleanInstanceSpec::API.new.router.map['POST'].first.options[:params]['message'][:type] }
|
|
32
|
-
|
|
33
|
-
it 'params type is a boolean' do
|
|
34
|
-
expect(subject).to eq 'Grape::API::Boolean'
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
describe Grape::API do
|
|
6
|
-
subject { Class.new(described_class) }
|
|
7
|
-
|
|
8
|
-
let(:app) { subject }
|
|
9
|
-
|
|
10
|
-
context 'an endpoint with documentation' do
|
|
11
|
-
it 'documents parameters' do
|
|
12
|
-
subject.params do
|
|
13
|
-
requires 'price', type: Float, desc: 'Sales price'
|
|
14
|
-
end
|
|
15
|
-
subject.get '/'
|
|
16
|
-
|
|
17
|
-
expect(subject.routes.first.params['price']).to eq(required: true,
|
|
18
|
-
type: 'Float',
|
|
19
|
-
desc: 'Sales price')
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
it 'allows documentation with a hash' do
|
|
23
|
-
documentation = { example: 'Joe' }
|
|
24
|
-
|
|
25
|
-
subject.params do
|
|
26
|
-
requires 'first_name', documentation: documentation
|
|
27
|
-
end
|
|
28
|
-
subject.get '/'
|
|
29
|
-
|
|
30
|
-
expect(subject.routes.first.params['first_name'][:documentation]).to eq(documentation)
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
context 'an endpoint without documentation' do
|
|
35
|
-
before do
|
|
36
|
-
subject.do_not_document!
|
|
37
|
-
|
|
38
|
-
subject.params do
|
|
39
|
-
requires :city, type: String, desc: 'Should be ignored'
|
|
40
|
-
optional :postal_code, type: Integer
|
|
41
|
-
end
|
|
42
|
-
subject.post '/' do
|
|
43
|
-
declared(params).to_json
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
it 'does not document parameters for the endpoint' do
|
|
48
|
-
expect(subject.routes.first.params).to eq({})
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
it 'still declares params internally' do
|
|
52
|
-
data = { city: 'Berlin', postal_code: 10_115 }
|
|
53
|
-
|
|
54
|
-
post '/', data
|
|
55
|
-
|
|
56
|
-
expect(last_response.body).to eq(data.to_json)
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
describe Grape::API::Helpers do
|
|
4
|
-
let(:user) { 'Miguel Caneo' }
|
|
5
|
-
let(:id) { '42' }
|
|
6
|
-
|
|
7
|
-
module InheritedHelpersSpec
|
|
8
|
-
class SuperClass < Grape::API
|
|
9
|
-
helpers do
|
|
10
|
-
params(:superclass_params) { requires :id, type: String }
|
|
11
|
-
|
|
12
|
-
def current_user
|
|
13
|
-
params[:user]
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
class OverriddenSubClass < SuperClass
|
|
19
|
-
params { use :superclass_params }
|
|
20
|
-
|
|
21
|
-
helpers do
|
|
22
|
-
def current_user
|
|
23
|
-
"#{params[:user]} with id"
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
get 'resource' do
|
|
28
|
-
"#{current_user}: #{params['id']}"
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
class SubClass < SuperClass
|
|
33
|
-
params { use :superclass_params }
|
|
34
|
-
|
|
35
|
-
get 'resource' do
|
|
36
|
-
"#{current_user}: #{params['id']}"
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
class Example < SubClass
|
|
41
|
-
params { use :superclass_params }
|
|
42
|
-
|
|
43
|
-
get 'resource' do
|
|
44
|
-
"#{current_user}: #{params['id']}"
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
context 'non overriding subclass' do
|
|
50
|
-
subject { InheritedHelpersSpec::SubClass }
|
|
51
|
-
|
|
52
|
-
def app
|
|
53
|
-
subject
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
context 'given expected params' do
|
|
57
|
-
it 'inherits helpers from a superclass' do
|
|
58
|
-
get '/resource', id: id, user: user
|
|
59
|
-
expect(last_response.body).to eq("#{user}: #{id}")
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
context 'with lack of expected params' do
|
|
64
|
-
it 'returns missing error' do
|
|
65
|
-
get '/resource'
|
|
66
|
-
expect(last_response.body).to eq('id is missing')
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
context 'overriding subclass' do
|
|
72
|
-
subject { InheritedHelpersSpec::OverriddenSubClass }
|
|
73
|
-
|
|
74
|
-
def app
|
|
75
|
-
subject
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
context 'given expected params' do
|
|
79
|
-
it 'overrides helpers from a superclass' do
|
|
80
|
-
get '/resource', id: id, user: user
|
|
81
|
-
expect(last_response.body).to eq("#{user} with id: #{id}")
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
context 'with lack of expected params' do
|
|
86
|
-
it 'returns missing error' do
|
|
87
|
-
get '/resource'
|
|
88
|
-
expect(last_response.body).to eq('id is missing')
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
context 'example subclass' do
|
|
94
|
-
subject { InheritedHelpersSpec::Example }
|
|
95
|
-
|
|
96
|
-
def app
|
|
97
|
-
subject
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
context 'given expected params' do
|
|
101
|
-
it 'inherits helpers from a superclass' do
|
|
102
|
-
get '/resource', id: id, user: user
|
|
103
|
-
expect(last_response.body).to eq("#{user}: #{id}")
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
context 'with lack of expected params' do
|
|
108
|
-
it 'returns missing error' do
|
|
109
|
-
get '/resource'
|
|
110
|
-
expect(last_response.body).to eq('id is missing')
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'shared/versioning_examples'
|
|
4
|
-
|
|
5
|
-
describe Grape::API::Instance do
|
|
6
|
-
subject(:an_instance) do
|
|
7
|
-
Class.new(Grape::API::Instance) do
|
|
8
|
-
namespace :some_namespace do
|
|
9
|
-
get 'some_endpoint' do
|
|
10
|
-
'success'
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
let(:root_api) do
|
|
17
|
-
to_mount = an_instance
|
|
18
|
-
Class.new(Grape::API) do
|
|
19
|
-
mount to_mount
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def app
|
|
24
|
-
root_api
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
context 'when an instance is mounted on the root' do
|
|
28
|
-
it 'can call the instance endpoint' do
|
|
29
|
-
get '/some_namespace/some_endpoint'
|
|
30
|
-
expect(last_response.body).to eq 'success'
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
context 'when an instance is the root' do
|
|
35
|
-
let(:root_api) do
|
|
36
|
-
to_mount = an_instance
|
|
37
|
-
Class.new(Grape::API::Instance) do
|
|
38
|
-
mount to_mount
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
it 'can call the instance endpoint' do
|
|
43
|
-
get '/some_namespace/some_endpoint'
|
|
44
|
-
expect(last_response.body).to eq 'success'
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
context 'top level setting' do
|
|
49
|
-
it 'does not inherit settings from the superclass (Grape::API::Instance)' do
|
|
50
|
-
expect(an_instance.top_level_setting.parent).to be_nil
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
context 'with multiple moutes' do
|
|
55
|
-
let(:first) do
|
|
56
|
-
Class.new(Grape::API::Instance) do
|
|
57
|
-
namespace(:some_namespace) do
|
|
58
|
-
route :any, '*path' do
|
|
59
|
-
error!('Not found! (1)', 404)
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
let(:second) do
|
|
65
|
-
Class.new(Grape::API::Instance) do
|
|
66
|
-
namespace(:another_namespace) do
|
|
67
|
-
route :any, '*path' do
|
|
68
|
-
error!('Not found! (2)', 404)
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
let(:root_api) do
|
|
74
|
-
first_instance = first
|
|
75
|
-
second_instance = second
|
|
76
|
-
Class.new(Grape::API) do
|
|
77
|
-
mount first_instance
|
|
78
|
-
mount first_instance
|
|
79
|
-
mount second_instance
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
it 'does not raise a FrozenError on first instance' do
|
|
84
|
-
expect { patch '/some_namespace/anything' }.not_to \
|
|
85
|
-
raise_error
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
it 'responds the correct body at the first instance' do
|
|
89
|
-
patch '/some_namespace/anything'
|
|
90
|
-
expect(last_response.body).to eq 'Not found! (1)'
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
it 'does not raise a FrozenError on second instance' do
|
|
94
|
-
expect { get '/another_namespace/other' }.not_to \
|
|
95
|
-
raise_error
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
it 'responds the correct body at the second instance' do
|
|
99
|
-
get '/another_namespace/foobar'
|
|
100
|
-
expect(last_response.body).to eq 'Not found! (2)'
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
end
|