grape 0.9.0 → 0.10.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.
Potentially problematic release.
This version of grape might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -66
- data/.rubocop_todo.yml +78 -17
- data/.travis.yml +7 -3
- data/Appraisals +7 -0
- data/CHANGELOG.md +24 -0
- data/CONTRIBUTING.md +7 -0
- data/Gemfile +1 -7
- data/Guardfile +1 -1
- data/README.md +560 -94
- data/RELEASING.md +1 -1
- data/Rakefile +10 -11
- data/UPGRADING.md +211 -3
- data/gemfiles/rails_3.gemfile +14 -0
- data/gemfiles/rails_4.gemfile +14 -0
- data/grape.gemspec +10 -9
- data/lib/backports/active_support/deep_dup.rb +49 -0
- data/lib/backports/active_support/duplicable.rb +88 -0
- data/lib/grape.rb +29 -2
- data/lib/grape/api.rb +59 -65
- data/lib/grape/dsl/api.rb +19 -0
- data/lib/grape/dsl/callbacks.rb +6 -4
- data/lib/grape/dsl/configuration.rb +49 -5
- data/lib/grape/dsl/helpers.rb +7 -8
- data/lib/grape/dsl/inside_route.rb +22 -10
- data/lib/grape/dsl/middleware.rb +5 -5
- data/lib/grape/dsl/parameters.rb +6 -2
- data/lib/grape/dsl/request_response.rb +23 -20
- data/lib/grape/dsl/routing.rb +52 -49
- data/lib/grape/dsl/settings.rb +110 -0
- data/lib/grape/dsl/validations.rb +14 -6
- data/lib/grape/endpoint.rb +104 -88
- data/lib/grape/exceptions/base.rb +2 -2
- data/lib/grape/exceptions/incompatible_option_values.rb +1 -1
- data/lib/grape/exceptions/invalid_formatter.rb +1 -1
- data/lib/grape/exceptions/invalid_versioner_option.rb +1 -1
- data/lib/grape/exceptions/invalid_with_option_for_represent.rb +1 -1
- data/lib/grape/exceptions/missing_mime_type.rb +1 -1
- data/lib/grape/exceptions/missing_option.rb +1 -1
- data/lib/grape/exceptions/missing_vendor_option.rb +1 -1
- data/lib/grape/exceptions/unknown_options.rb +1 -1
- data/lib/grape/exceptions/unknown_validator.rb +1 -1
- data/lib/grape/exceptions/validation.rb +1 -1
- data/lib/grape/exceptions/validation_errors.rb +2 -2
- data/lib/grape/formatter/serializable_hash.rb +1 -1
- data/lib/grape/formatter/xml.rb +1 -1
- data/lib/grape/locale/en.yml +2 -0
- data/lib/grape/middleware/auth/dsl.rb +26 -21
- data/lib/grape/middleware/auth/strategies.rb +1 -1
- data/lib/grape/middleware/auth/strategy_info.rb +0 -2
- data/lib/grape/middleware/base.rb +2 -2
- data/lib/grape/middleware/error.rb +1 -1
- data/lib/grape/middleware/formatter.rb +5 -5
- data/lib/grape/middleware/versioner.rb +1 -1
- data/lib/grape/middleware/versioner/header.rb +3 -3
- data/lib/grape/middleware/versioner/param.rb +2 -2
- data/lib/grape/middleware/versioner/path.rb +1 -1
- data/lib/grape/namespace.rb +1 -1
- data/lib/grape/path.rb +9 -3
- data/lib/grape/util/content_types.rb +16 -8
- data/lib/grape/util/inheritable_setting.rb +74 -0
- data/lib/grape/util/inheritable_values.rb +51 -0
- data/lib/grape/util/stackable_values.rb +52 -0
- data/lib/grape/util/strict_hash_configuration.rb +106 -0
- data/lib/grape/validations.rb +0 -220
- data/lib/grape/validations/attributes_iterator.rb +21 -0
- data/lib/grape/validations/params_scope.rb +176 -0
- data/lib/grape/validations/validators/all_or_none.rb +20 -0
- data/lib/grape/validations/validators/allow_blank.rb +30 -0
- data/lib/grape/validations/validators/at_least_one_of.rb +20 -0
- data/lib/grape/validations/validators/base.rb +37 -0
- data/lib/grape/validations/{coerce.rb → validators/coerce.rb} +3 -3
- data/lib/grape/validations/{default.rb → validators/default.rb} +1 -1
- data/lib/grape/validations/validators/exactly_one_of.rb +20 -0
- data/lib/grape/validations/validators/multiple_params_base.rb +26 -0
- data/lib/grape/validations/validators/mutual_exclusion.rb +25 -0
- data/lib/grape/validations/{presence.rb → validators/presence.rb} +2 -2
- data/lib/grape/validations/validators/regexp.rb +12 -0
- data/lib/grape/validations/validators/values.rb +26 -0
- data/lib/grape/version.rb +1 -1
- data/spec/grape/api_spec.rb +522 -343
- data/spec/grape/dsl/callbacks_spec.rb +4 -4
- data/spec/grape/dsl/configuration_spec.rb +48 -9
- data/spec/grape/dsl/helpers_spec.rb +6 -13
- data/spec/grape/dsl/inside_route_spec.rb +43 -4
- data/spec/grape/dsl/middleware_spec.rb +1 -10
- data/spec/grape/dsl/parameters_spec.rb +8 -1
- data/spec/grape/dsl/request_response_spec.rb +16 -22
- data/spec/grape/dsl/routing_spec.rb +21 -5
- data/spec/grape/dsl/settings_spec.rb +219 -0
- data/spec/grape/dsl/validations_spec.rb +8 -11
- data/spec/grape/endpoint_spec.rb +115 -86
- data/spec/grape/entity_spec.rb +33 -33
- data/spec/grape/exceptions/invalid_formatter_spec.rb +3 -5
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +4 -6
- data/spec/grape/exceptions/missing_mime_type_spec.rb +5 -6
- data/spec/grape/exceptions/missing_option_spec.rb +3 -5
- data/spec/grape/exceptions/unknown_options_spec.rb +3 -5
- data/spec/grape/exceptions/unknown_validator_spec.rb +3 -5
- data/spec/grape/exceptions/validation_errors_spec.rb +5 -5
- data/spec/grape/loading_spec.rb +44 -0
- data/spec/grape/middleware/auth/base_spec.rb +0 -4
- data/spec/grape/middleware/auth/dsl_spec.rb +2 -4
- data/spec/grape/middleware/auth/strategies_spec.rb +5 -6
- data/spec/grape/middleware/exception_spec.rb +8 -10
- data/spec/grape/middleware/formatter_spec.rb +13 -15
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +10 -10
- data/spec/grape/middleware/versioner/header_spec.rb +25 -25
- data/spec/grape/middleware/versioner/param_spec.rb +15 -17
- data/spec/grape/middleware/versioner/path_spec.rb +1 -2
- data/spec/grape/middleware/versioner_spec.rb +0 -1
- data/spec/grape/path_spec.rb +66 -45
- data/spec/grape/util/inheritable_setting_spec.rb +217 -0
- data/spec/grape/util/inheritable_values_spec.rb +63 -0
- data/spec/grape/util/stackable_values_spec.rb +115 -0
- data/spec/grape/util/strict_hash_configuration_spec.rb +38 -0
- data/spec/grape/validations/attributes_iterator_spec.rb +4 -0
- data/spec/grape/validations/params_scope_spec.rb +57 -0
- data/spec/grape/validations/validators/all_or_none_spec.rb +60 -0
- data/spec/grape/validations/validators/allow_blank_spec.rb +170 -0
- data/spec/grape/validations/{at_least_one_of_spec.rb → validators/at_least_one_of_spec.rb} +7 -3
- data/spec/grape/validations/{coerce_spec.rb → validators/coerce_spec.rb} +8 -11
- data/spec/grape/validations/{default_spec.rb → validators/default_spec.rb} +7 -9
- data/spec/grape/validations/{exactly_one_of_spec.rb → validators/exactly_one_of_spec.rb} +15 -11
- data/spec/grape/validations/{mutual_exclusion_spec.rb → validators/mutual_exclusion_spec.rb} +11 -9
- data/spec/grape/validations/{presence_spec.rb → validators/presence_spec.rb} +30 -30
- data/spec/grape/validations/{regexp_spec.rb → validators/regexp_spec.rb} +2 -4
- data/spec/grape/validations/{values_spec.rb → validators/values_spec.rb} +95 -23
- data/spec/grape/validations/{zh-CN.yml → validators/zh-CN.yml} +0 -0
- data/spec/grape/validations_spec.rb +335 -70
- data/spec/shared/versioning_examples.rb +7 -8
- data/spec/spec_helper.rb +2 -0
- data/spec/support/basic_auth_encode_helpers.rb +1 -1
- data/spec/support/content_type_helpers.rb +1 -1
- data/spec/support/versioned_helpers.rb +3 -3
- metadata +80 -33
- data/lib/grape/util/deep_merge.rb +0 -23
- data/lib/grape/util/hash_stack.rb +0 -120
- data/lib/grape/validations/at_least_one_of.rb +0 -25
- data/lib/grape/validations/exactly_one_of.rb +0 -26
- data/lib/grape/validations/mutual_exclusion.rb +0 -25
- data/lib/grape/validations/regexp.rb +0 -12
- data/lib/grape/validations/values.rb +0 -23
- data/spec/grape/util/hash_stack_spec.rb +0 -132
| @@ -27,7 +27,7 @@ describe Grape::Middleware::Versioner::Path do | |
| 27 27 | 
             
                end
         | 
| 28 28 | 
             
              end
         | 
| 29 29 |  | 
| 30 | 
            -
              [ | 
| 30 | 
            +
              [%w(v1 v2), [:v1, :v2], [:v1, 'v2'], ['v1', :v2]].each do |versions|
         | 
| 31 31 | 
             
                context 'with specified versions as #{versions}' do
         | 
| 32 32 | 
             
                  before { @options = { versions: versions } }
         | 
| 33 33 |  | 
| @@ -40,5 +40,4 @@ describe Grape::Middleware::Versioner::Path do | |
| 40 40 | 
             
                  end
         | 
| 41 41 | 
             
                end
         | 
| 42 42 | 
             
              end
         | 
| 43 | 
            -
             | 
| 44 43 | 
             
            end
         | 
    
        data/spec/grape/path_spec.rb
    CHANGED
    
    | @@ -2,65 +2,64 @@ require 'spec_helper' | |
| 2 2 |  | 
| 3 3 | 
             
            module Grape
         | 
| 4 4 | 
             
              describe Path do
         | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
                  it "remembers the path" do
         | 
| 5 | 
            +
                describe '#initialize' do
         | 
| 6 | 
            +
                  it 'remembers the path' do
         | 
| 8 7 | 
             
                    path = Path.new('/:id', anything, anything)
         | 
| 9 8 | 
             
                    expect(path.raw_path).to eql('/:id')
         | 
| 10 9 | 
             
                  end
         | 
| 11 10 |  | 
| 12 | 
            -
                  it  | 
| 11 | 
            +
                  it 'remembers the namespace' do
         | 
| 13 12 | 
             
                    path = Path.new(anything, '/users', anything)
         | 
| 14 13 | 
             
                    expect(path.namespace).to eql('/users')
         | 
| 15 14 | 
             
                  end
         | 
| 16 15 |  | 
| 17 | 
            -
                  it  | 
| 16 | 
            +
                  it 'remebers the settings' do
         | 
| 18 17 | 
             
                    path = Path.new(anything, anything, foo: 'bar')
         | 
| 19 18 | 
             
                    expect(path.settings).to eql(foo: 'bar')
         | 
| 20 19 | 
             
                  end
         | 
| 21 20 | 
             
                end
         | 
| 22 21 |  | 
| 23 | 
            -
                describe  | 
| 24 | 
            -
                  it  | 
| 22 | 
            +
                describe '#mount_path' do
         | 
| 23 | 
            +
                  it 'is nil when no mount path setting exists' do
         | 
| 25 24 | 
             
                    path = Path.new(anything, anything, {})
         | 
| 26 25 | 
             
                    expect(path.mount_path).to be_nil
         | 
| 27 26 | 
             
                  end
         | 
| 28 27 |  | 
| 29 | 
            -
                  it  | 
| 28 | 
            +
                  it 'is nil when the mount path is nil' do
         | 
| 30 29 | 
             
                    path = Path.new(anything, anything, mount_path: nil)
         | 
| 31 30 | 
             
                    expect(path.mount_path).to be_nil
         | 
| 32 31 | 
             
                  end
         | 
| 33 32 |  | 
| 34 | 
            -
                  it  | 
| 35 | 
            -
                    path = Path.new(anything, anything, mount_path:  | 
| 36 | 
            -
                    expect(path.mount_path).to eql( | 
| 33 | 
            +
                  it 'splits the mount path' do
         | 
| 34 | 
            +
                    path = Path.new(anything, anything, mount_path: %w(foo bar))
         | 
| 35 | 
            +
                    expect(path.mount_path).to eql(%w(foo bar))
         | 
| 37 36 | 
             
                  end
         | 
| 38 37 | 
             
                end
         | 
| 39 38 |  | 
| 40 | 
            -
                describe  | 
| 41 | 
            -
                  it  | 
| 39 | 
            +
                describe '#root_prefix' do
         | 
| 40 | 
            +
                  it 'is nil when no root prefix setting exists' do
         | 
| 42 41 | 
             
                    path = Path.new(anything, anything, {})
         | 
| 43 42 | 
             
                    expect(path.root_prefix).to be_nil
         | 
| 44 43 | 
             
                  end
         | 
| 45 44 |  | 
| 46 | 
            -
                  it  | 
| 45 | 
            +
                  it 'is nil when the mount path is nil' do
         | 
| 47 46 | 
             
                    path = Path.new(anything, anything, root_prefix: nil)
         | 
| 48 47 | 
             
                    expect(path.root_prefix).to be_nil
         | 
| 49 48 | 
             
                  end
         | 
| 50 49 |  | 
| 51 | 
            -
                  it  | 
| 50 | 
            +
                  it 'splits the mount path' do
         | 
| 52 51 | 
             
                    path = Path.new(anything, anything, root_prefix: 'hello/world')
         | 
| 53 | 
            -
                    expect(path.root_prefix).to eql( | 
| 52 | 
            +
                    expect(path.root_prefix).to eql(%w(hello world))
         | 
| 54 53 | 
             
                  end
         | 
| 55 54 | 
             
                end
         | 
| 56 55 |  | 
| 57 | 
            -
                describe  | 
| 58 | 
            -
                  it  | 
| 56 | 
            +
                describe '#uses_path_versioning?' do
         | 
| 57 | 
            +
                  it 'is false when the version setting is nil' do
         | 
| 59 58 | 
             
                    path = Path.new(anything, anything, version: nil)
         | 
| 60 59 | 
             
                    expect(path.uses_path_versioning?).to be false
         | 
| 61 60 | 
             
                  end
         | 
| 62 61 |  | 
| 63 | 
            -
                  it  | 
| 62 | 
            +
                  it 'is false when the version option is header' do
         | 
| 64 63 | 
             
                    path = Path.new(
         | 
| 65 64 | 
             
                      anything,
         | 
| 66 65 | 
             
                      anything,
         | 
| @@ -71,7 +70,7 @@ module Grape | |
| 71 70 | 
             
                    expect(path.uses_path_versioning?).to be false
         | 
| 72 71 | 
             
                  end
         | 
| 73 72 |  | 
| 74 | 
            -
                  it  | 
| 73 | 
            +
                  it 'is true when the version option is path' do
         | 
| 75 74 | 
             
                    path = Path.new(
         | 
| 76 75 | 
             
                      anything,
         | 
| 77 76 | 
             
                      anything,
         | 
| @@ -83,70 +82,70 @@ module Grape | |
| 83 82 | 
             
                  end
         | 
| 84 83 | 
             
                end
         | 
| 85 84 |  | 
| 86 | 
            -
                describe  | 
| 87 | 
            -
                  it  | 
| 85 | 
            +
                describe '#has_namespace?' do
         | 
| 86 | 
            +
                  it 'is false when the namespace is nil' do
         | 
| 88 87 | 
             
                    path = Path.new(anything, nil, anything)
         | 
| 89 88 | 
             
                    expect(path).not_to have_namespace
         | 
| 90 89 | 
             
                  end
         | 
| 91 90 |  | 
| 92 | 
            -
                  it  | 
| 91 | 
            +
                  it 'is false when the namespace starts with whitespace' do
         | 
| 93 92 | 
             
                    path = Path.new(anything, ' /foo', anything)
         | 
| 94 93 | 
             
                    expect(path).not_to have_namespace
         | 
| 95 94 | 
             
                  end
         | 
| 96 95 |  | 
| 97 | 
            -
                  it  | 
| 96 | 
            +
                  it 'is false when the namespace is the root path' do
         | 
| 98 97 | 
             
                    path = Path.new(anything, '/', anything)
         | 
| 99 98 | 
             
                    expect(path).not_to have_namespace
         | 
| 100 99 | 
             
                  end
         | 
| 101 100 |  | 
| 102 | 
            -
                  it  | 
| 101 | 
            +
                  it 'is true otherwise' do
         | 
| 103 102 | 
             
                    path = Path.new(anything, '/world', anything)
         | 
| 104 103 | 
             
                    expect(path).to have_namespace
         | 
| 105 104 | 
             
                  end
         | 
| 106 105 | 
             
                end
         | 
| 107 106 |  | 
| 108 | 
            -
                describe  | 
| 109 | 
            -
                  it  | 
| 107 | 
            +
                describe '#has_path?' do
         | 
| 108 | 
            +
                  it 'is false when the path is nil' do
         | 
| 110 109 | 
             
                    path = Path.new(nil, anything, anything)
         | 
| 111 110 | 
             
                    expect(path).not_to have_path
         | 
| 112 111 | 
             
                  end
         | 
| 113 112 |  | 
| 114 | 
            -
                  it  | 
| 113 | 
            +
                  it 'is false when the path starts with whitespace' do
         | 
| 115 114 | 
             
                    path = Path.new(' /foo', anything, anything)
         | 
| 116 115 | 
             
                    expect(path).not_to have_path
         | 
| 117 116 | 
             
                  end
         | 
| 118 117 |  | 
| 119 | 
            -
                  it  | 
| 118 | 
            +
                  it 'is false when the path is the root path' do
         | 
| 120 119 | 
             
                    path = Path.new('/', anything, anything)
         | 
| 121 120 | 
             
                    expect(path).not_to have_path
         | 
| 122 121 | 
             
                  end
         | 
| 123 122 |  | 
| 124 | 
            -
                  it  | 
| 123 | 
            +
                  it 'is true otherwise' do
         | 
| 125 124 | 
             
                    path = Path.new('/hello', anything, anything)
         | 
| 126 125 | 
             
                    expect(path).to have_path
         | 
| 127 126 | 
             
                  end
         | 
| 128 127 | 
             
                end
         | 
| 129 128 |  | 
| 130 | 
            -
                describe  | 
| 131 | 
            -
                  context  | 
| 132 | 
            -
                    it  | 
| 129 | 
            +
                describe '#path' do
         | 
| 130 | 
            +
                  context 'mount_path' do
         | 
| 131 | 
            +
                    it 'is not included when it is nil' do
         | 
| 133 132 | 
             
                      path = Path.new(nil, nil, mount_path: '/foo/bar')
         | 
| 134 133 | 
             
                      expect(path.path).to eql '/foo/bar'
         | 
| 135 134 | 
             
                    end
         | 
| 136 135 |  | 
| 137 | 
            -
                    it  | 
| 136 | 
            +
                    it 'is included when it is not nil' do
         | 
| 138 137 | 
             
                      path = Path.new(nil, nil, {})
         | 
| 139 138 | 
             
                      expect(path.path).to eql('/')
         | 
| 140 139 | 
             
                    end
         | 
| 141 140 | 
             
                  end
         | 
| 142 141 |  | 
| 143 | 
            -
                  context  | 
| 144 | 
            -
                    it  | 
| 142 | 
            +
                  context 'root_prefix' do
         | 
| 143 | 
            +
                    it 'is not included when it is nil' do
         | 
| 145 144 | 
             
                      path = Path.new(nil, nil, {})
         | 
| 146 145 | 
             
                      expect(path.path).to eql('/')
         | 
| 147 146 | 
             
                    end
         | 
| 148 147 |  | 
| 149 | 
            -
                    it  | 
| 148 | 
            +
                    it 'is included after the mount path' do
         | 
| 150 149 | 
             
                      path = Path.new(
         | 
| 151 150 | 
             
                        nil,
         | 
| 152 151 | 
             
                        nil,
         | 
| @@ -158,7 +157,7 @@ module Grape | |
| 158 157 | 
             
                    end
         | 
| 159 158 | 
             
                  end
         | 
| 160 159 |  | 
| 161 | 
            -
                  it  | 
| 160 | 
            +
                  it 'uses the namespace after the mount path and root prefix' do
         | 
| 162 161 | 
             
                    path = Path.new(
         | 
| 163 162 | 
             
                      nil,
         | 
| 164 163 | 
             
                      'namespace',
         | 
| @@ -169,7 +168,7 @@ module Grape | |
| 169 168 | 
             
                    expect(path.path).to eql('/foo/hello/namespace')
         | 
| 170 169 | 
             
                  end
         | 
| 171 170 |  | 
| 172 | 
            -
                  it  | 
| 171 | 
            +
                  it 'uses the raw path after the namespace' do
         | 
| 173 172 | 
             
                    path = Path.new(
         | 
| 174 173 | 
             
                      'raw_path',
         | 
| 175 174 | 
             
                      'namespace',
         | 
| @@ -181,19 +180,30 @@ module Grape | |
| 181 180 | 
             
                  end
         | 
| 182 181 | 
             
                end
         | 
| 183 182 |  | 
| 184 | 
            -
                describe  | 
| 185 | 
            -
                  context  | 
| 183 | 
            +
                describe '#suffix' do
         | 
| 184 | 
            +
                  context 'when using a specific format' do
         | 
| 185 | 
            +
                    it 'is empty' do
         | 
| 186 | 
            +
                      path = Path.new(nil, nil, {})
         | 
| 187 | 
            +
                      allow(path).to receive(:uses_specific_format?) { true }
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                      expect(path.suffix).to eql('')
         | 
| 190 | 
            +
                    end
         | 
| 191 | 
            +
                  end
         | 
| 192 | 
            +
             | 
| 193 | 
            +
                  context 'when path versioning is used' do
         | 
| 186 194 | 
             
                    it "includes a '/'" do
         | 
| 187 195 | 
             
                      path = Path.new(nil, nil, {})
         | 
| 196 | 
            +
                      allow(path).to receive(:uses_specific_format?) { false }
         | 
| 188 197 | 
             
                      allow(path).to receive(:uses_path_versioning?) { true }
         | 
| 189 198 |  | 
| 190 199 | 
             
                      expect(path.suffix).to eql('(/.:format)')
         | 
| 191 200 | 
             
                    end
         | 
| 192 201 | 
             
                  end
         | 
| 193 202 |  | 
| 194 | 
            -
                  context  | 
| 203 | 
            +
                  context 'when path versioning is not used' do
         | 
| 195 204 | 
             
                    it "does not include a '/' when the path has a namespace" do
         | 
| 196 205 | 
             
                      path = Path.new(nil, 'namespace', {})
         | 
| 206 | 
            +
                      allow(path).to receive(:uses_specific_format?) { false }
         | 
| 197 207 | 
             
                      allow(path).to receive(:uses_path_versioning?) { true }
         | 
| 198 208 |  | 
| 199 209 | 
             
                      expect(path.suffix).to eql('(.:format)')
         | 
| @@ -201,6 +211,7 @@ module Grape | |
| 201 211 |  | 
| 202 212 | 
             
                    it "does not include a '/' when the path has a path" do
         | 
| 203 213 | 
             
                      path = Path.new('/path', nil, {})
         | 
| 214 | 
            +
                      allow(path).to receive(:uses_specific_format?) { false }
         | 
| 204 215 | 
             
                      allow(path).to receive(:uses_path_versioning?) { true }
         | 
| 205 216 |  | 
| 206 217 | 
             
                      expect(path.suffix).to eql('(.:format)')
         | 
| @@ -208,6 +219,7 @@ module Grape | |
| 208 219 |  | 
| 209 220 | 
             
                    it "includes a '/' otherwise" do
         | 
| 210 221 | 
             
                      path = Path.new(nil, nil, {})
         | 
| 222 | 
            +
                      allow(path).to receive(:uses_specific_format?) { false }
         | 
| 211 223 | 
             
                      allow(path).to receive(:uses_path_versioning?) { true }
         | 
| 212 224 |  | 
| 213 225 | 
             
                      expect(path.suffix).to eql('(/.:format)')
         | 
| @@ -215,15 +227,24 @@ module Grape | |
| 215 227 | 
             
                  end
         | 
| 216 228 | 
             
                end
         | 
| 217 229 |  | 
| 218 | 
            -
                describe  | 
| 219 | 
            -
                  it  | 
| 230 | 
            +
                describe '#path_with_suffix' do
         | 
| 231 | 
            +
                  it 'combines the path and suffix' do
         | 
| 220 232 | 
             
                    path = Path.new(nil, nil, {})
         | 
| 221 233 | 
             
                    allow(path).to receive(:path) { '/the/path' }
         | 
| 222 234 | 
             
                    allow(path).to receive(:suffix) { 'suffix' }
         | 
| 223 235 |  | 
| 224 236 | 
             
                    expect(path.path_with_suffix).to eql('/the/pathsuffix')
         | 
| 225 237 | 
             
                  end
         | 
| 226 | 
            -
                end
         | 
| 227 238 |  | 
| 239 | 
            +
                  context 'when using a specific format' do
         | 
| 240 | 
            +
                    it 'does not have a suffix' do
         | 
| 241 | 
            +
                      path = Path.new(nil, nil, {})
         | 
| 242 | 
            +
                      allow(path).to receive(:path) { '/the/path' }
         | 
| 243 | 
            +
                      allow(path).to receive(:uses_specific_format?) { true }
         | 
| 244 | 
            +
             | 
| 245 | 
            +
                      expect(path.path_with_suffix).to eql('/the/path')
         | 
| 246 | 
            +
                    end
         | 
| 247 | 
            +
                  end
         | 
| 248 | 
            +
                end
         | 
| 228 249 | 
             
              end
         | 
| 229 250 | 
             
            end
         | 
| @@ -0,0 +1,217 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            module Grape
         | 
| 3 | 
            +
              module Util
         | 
| 4 | 
            +
                describe InheritableSetting do
         | 
| 5 | 
            +
                  before :each do
         | 
| 6 | 
            +
                    InheritableSetting.reset_global!
         | 
| 7 | 
            +
                  end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  let(:parent) do
         | 
| 10 | 
            +
                    Grape::Util::InheritableSetting.new.tap do |settings|
         | 
| 11 | 
            +
                      settings.global[:global_thing] = :global_foo_bar
         | 
| 12 | 
            +
                      settings.namespace[:namespace_thing] = :namespace_foo_bar
         | 
| 13 | 
            +
                      settings.namespace_inheritable[:namespace_inheritable_thing] = :namespace_inheritable_foo_bar
         | 
| 14 | 
            +
                      settings.namespace_stackable[:namespace_stackable_thing] = :namespace_stackable_foo_bar
         | 
| 15 | 
            +
                      settings.route[:route_thing] = :route_foo_bar
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  let(:other_parent) do
         | 
| 20 | 
            +
                    Grape::Util::InheritableSetting.new.tap do |settings|
         | 
| 21 | 
            +
                      settings.namespace[:namespace_thing] = :namespace_foo_bar_other
         | 
| 22 | 
            +
                      settings.namespace_inheritable[:namespace_inheritable_thing] = :namespace_inheritable_foo_bar_other
         | 
| 23 | 
            +
                      settings.namespace_stackable[:namespace_stackable_thing] = :namespace_stackable_foo_bar_other
         | 
| 24 | 
            +
                      settings.route[:route_thing] = :route_foo_bar_other
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  before :each do
         | 
| 29 | 
            +
                    subject.inherit_from parent
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  describe '#global' do
         | 
| 33 | 
            +
                    it 'sets a global value' do
         | 
| 34 | 
            +
                      subject.global[:some_thing] = :foo_bar
         | 
| 35 | 
            +
                      expect(subject.global[:some_thing]).to eq :foo_bar
         | 
| 36 | 
            +
                      subject.global[:some_thing] = :foo_bar_next
         | 
| 37 | 
            +
                      expect(subject.global[:some_thing]).to eq :foo_bar_next
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    it 'sets the global inherited values' do
         | 
| 41 | 
            +
                      expect(subject.global[:global_thing]).to eq :global_foo_bar
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    it 'overrides global values' do
         | 
| 45 | 
            +
                      subject.global[:global_thing] = :global_new_foo_bar
         | 
| 46 | 
            +
                      expect(parent.global[:global_thing]).to eq :global_new_foo_bar
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    it 'should handle different parents' do
         | 
| 50 | 
            +
                      subject.global[:global_thing] = :global_new_foo_bar
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                      subject.inherit_from other_parent
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                      expect(parent.global[:global_thing]).to eq :global_new_foo_bar
         | 
| 55 | 
            +
                      expect(other_parent.global[:global_thing]).to eq :global_new_foo_bar
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  describe '#api_class' do
         | 
| 60 | 
            +
                    it 'is specific to the class' do
         | 
| 61 | 
            +
                      subject.api_class[:some_thing] = :foo_bar
         | 
| 62 | 
            +
                      parent.api_class[:some_thing] = :some_thing
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                      expect(subject.api_class[:some_thing]).to eq :foo_bar
         | 
| 65 | 
            +
                      expect(parent.api_class[:some_thing]).to eq :some_thing
         | 
| 66 | 
            +
                    end
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                  describe '#namespace' do
         | 
| 70 | 
            +
                    it 'sets a value until the end of a namespace' do
         | 
| 71 | 
            +
                      subject.namespace[:some_thing] = :foo_bar
         | 
| 72 | 
            +
                      expect(subject.namespace[:some_thing]).to eq :foo_bar
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                    it 'uses new values when a new namespace starts' do
         | 
| 76 | 
            +
                      subject.namespace[:namespace_thing] = :new_namespace_foo_bar
         | 
| 77 | 
            +
                      expect(subject.namespace[:namespace_thing]).to eq :new_namespace_foo_bar
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                      expect(parent.namespace[:namespace_thing]).to eq :namespace_foo_bar
         | 
| 80 | 
            +
                    end
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  describe '#namespace_inheritable' do
         | 
| 84 | 
            +
                    it 'works with inheritable values' do
         | 
| 85 | 
            +
                      expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
         | 
| 86 | 
            +
                    end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                    it 'should handle different parents' do
         | 
| 89 | 
            +
                      expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                      subject.inherit_from other_parent
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                      expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar_other
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                      subject.inherit_from parent
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                      expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                      subject.inherit_from other_parent
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                      subject.namespace_inheritable[:namespace_inheritable_thing] = :my_thing
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                      expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :my_thing
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                      subject.inherit_from parent
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                      expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :my_thing
         | 
| 108 | 
            +
                    end
         | 
| 109 | 
            +
                  end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                  describe '#namespace_stackable' do
         | 
| 112 | 
            +
                    it 'works with stackable values' do
         | 
| 113 | 
            +
                      expect(subject.namespace_stackable[:namespace_stackable_thing]).to eq [:namespace_stackable_foo_bar]
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                      subject.inherit_from other_parent
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                      expect(subject.namespace_stackable[:namespace_stackable_thing]).to eq [:namespace_stackable_foo_bar_other]
         | 
| 118 | 
            +
                    end
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                  describe '#route' do
         | 
| 122 | 
            +
                    it 'sets a value until the next route' do
         | 
| 123 | 
            +
                      subject.route[:some_thing] = :foo_bar
         | 
| 124 | 
            +
                      expect(subject.route[:some_thing]).to eq :foo_bar
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                      subject.route_end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                      expect(subject.route[:some_thing]).to be_nil
         | 
| 129 | 
            +
                    end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                    it 'works with route values' do
         | 
| 132 | 
            +
                      expect(subject.route[:route_thing]).to eq :route_foo_bar
         | 
| 133 | 
            +
                    end
         | 
| 134 | 
            +
                  end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                  describe '#api_class' do
         | 
| 137 | 
            +
                    it 'is specific to the class' do
         | 
| 138 | 
            +
                      subject.api_class[:some_thing] = :foo_bar
         | 
| 139 | 
            +
                      expect(subject.api_class[:some_thing]).to eq :foo_bar
         | 
| 140 | 
            +
                    end
         | 
| 141 | 
            +
                  end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                  describe '#inherit_from' do
         | 
| 144 | 
            +
                    it 'notifies clones' do
         | 
| 145 | 
            +
                      new_settings = subject.point_in_time_copy
         | 
| 146 | 
            +
                      expect(new_settings).to receive(:inherit_from).with(other_parent)
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                      subject.inherit_from other_parent
         | 
| 149 | 
            +
                    end
         | 
| 150 | 
            +
                  end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                  describe '#point_in_time_copy' do
         | 
| 153 | 
            +
                    let!(:cloned_obj) { subject.point_in_time_copy }
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                    it 'resets point_in_time_copies' do
         | 
| 156 | 
            +
                      expect(cloned_obj.point_in_time_copies).to be_empty
         | 
| 157 | 
            +
                    end
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                    it 'decouples namespace values' do
         | 
| 160 | 
            +
                      subject.namespace[:namespace_thing] = :namespace_foo_bar
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                      cloned_obj.namespace[:namespace_thing] = :new_namespace_foo_bar
         | 
| 163 | 
            +
                      expect(subject.namespace[:namespace_thing]).to eq :namespace_foo_bar
         | 
| 164 | 
            +
                    end
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                    it 'decouples namespace inheritable values' do
         | 
| 167 | 
            +
                      expect(cloned_obj.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                      subject.namespace_inheritable[:namespace_inheritable_thing] = :my_thing
         | 
| 170 | 
            +
                      expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :my_thing
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                      expect(cloned_obj.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                      cloned_obj.namespace_inheritable[:namespace_inheritable_thing] = :my_cloned_thing
         | 
| 175 | 
            +
                      expect(cloned_obj.namespace_inheritable[:namespace_inheritable_thing]).to eq :my_cloned_thing
         | 
| 176 | 
            +
                      expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :my_thing
         | 
| 177 | 
            +
                    end
         | 
| 178 | 
            +
             | 
| 179 | 
            +
                    it 'decouples namespace stackable values' do
         | 
| 180 | 
            +
                      expect(cloned_obj.namespace_stackable[:namespace_stackable_thing]).to eq [:namespace_stackable_foo_bar]
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                      subject.namespace_stackable[:namespace_stackable_thing] = :other_thing
         | 
| 183 | 
            +
                      expect(subject.namespace_stackable[:namespace_stackable_thing]).to eq [:namespace_stackable_foo_bar, :other_thing]
         | 
| 184 | 
            +
                      expect(cloned_obj.namespace_stackable[:namespace_stackable_thing]).to eq [:namespace_stackable_foo_bar]
         | 
| 185 | 
            +
                    end
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                    it 'decouples route values' do
         | 
| 188 | 
            +
                      expect(cloned_obj.route[:route_thing]).to eq :route_foo_bar
         | 
| 189 | 
            +
             | 
| 190 | 
            +
                      subject.route[:route_thing] = :new_route_foo_bar
         | 
| 191 | 
            +
                      expect(cloned_obj.route[:route_thing]).to eq :route_foo_bar
         | 
| 192 | 
            +
                    end
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                    it 'adds itself to original as clone' do
         | 
| 195 | 
            +
                      expect(subject.point_in_time_copies).to include(cloned_obj)
         | 
| 196 | 
            +
                    end
         | 
| 197 | 
            +
                  end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                  describe '#to_hash' do
         | 
| 200 | 
            +
                    it 'return all settings as a hash' do
         | 
| 201 | 
            +
                      subject.global[:global_thing] = :global_foo_bar
         | 
| 202 | 
            +
                      subject.namespace[:namespace_thing] = :namespace_foo_bar
         | 
| 203 | 
            +
                      subject.namespace_inheritable[:namespace_inheritable_thing] = :namespace_inheritable_foo_bar
         | 
| 204 | 
            +
                      subject.namespace_stackable[:namespace_stackable_thing] = [:namespace_stackable_foo_bar]
         | 
| 205 | 
            +
                      subject.route[:route_thing] = :route_foo_bar
         | 
| 206 | 
            +
             | 
| 207 | 
            +
                      expect(subject.to_hash).to include(global: { global_thing: :global_foo_bar })
         | 
| 208 | 
            +
                      expect(subject.to_hash).to include(namespace: { namespace_thing: :namespace_foo_bar })
         | 
| 209 | 
            +
                      expect(subject.to_hash).to include(namespace_inheritable: {
         | 
| 210 | 
            +
                                                           namespace_inheritable_thing: :namespace_inheritable_foo_bar })
         | 
| 211 | 
            +
                      expect(subject.to_hash).to include(namespace_stackable: { namespace_stackable_thing: [:namespace_stackable_foo_bar, [:namespace_stackable_foo_bar]] })
         | 
| 212 | 
            +
                      expect(subject.to_hash).to include(route: { route_thing: :route_foo_bar })
         | 
| 213 | 
            +
                    end
         | 
| 214 | 
            +
                  end
         | 
| 215 | 
            +
                end
         | 
| 216 | 
            +
              end
         | 
| 217 | 
            +
            end
         |