haveapi 0.20.0 → 0.21.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/Gemfile +1 -1
 - data/Rakefile +6 -6
 - data/haveapi.gemspec +13 -13
 - data/lib/haveapi/action.rb +140 -158
 - data/lib/haveapi/action_state.rb +2 -6
 - data/lib/haveapi/actions/default.rb +8 -10
 - data/lib/haveapi/api.rb +2 -1
 - data/lib/haveapi/authentication/base.rb +5 -8
 - data/lib/haveapi/authentication/basic/provider.rb +4 -5
 - data/lib/haveapi/authentication/chain.rb +19 -17
 - data/lib/haveapi/authentication/oauth2/config.rb +12 -32
 - data/lib/haveapi/authentication/oauth2/provider.rb +20 -30
 - data/lib/haveapi/authentication/oauth2/revoke_endpoint.rb +1 -2
 - data/lib/haveapi/authentication/token/action_config.rb +5 -3
 - data/lib/haveapi/authentication/token/config.rb +5 -5
 - data/lib/haveapi/authentication/token/provider.rb +33 -37
 - data/lib/haveapi/authorization.rb +5 -4
 - data/lib/haveapi/client_example.rb +11 -14
 - data/lib/haveapi/client_examples/curl.rb +37 -37
 - data/lib/haveapi/client_examples/fs_client.rb +29 -31
 - data/lib/haveapi/client_examples/http.rb +35 -36
 - data/lib/haveapi/client_examples/js_client.rb +62 -63
 - data/lib/haveapi/client_examples/php_client.rb +77 -76
 - data/lib/haveapi/client_examples/ruby_cli.rb +30 -30
 - data/lib/haveapi/client_examples/ruby_client.rb +26 -26
 - data/lib/haveapi/common.rb +3 -4
 - data/lib/haveapi/context.rb +11 -10
 - data/lib/haveapi/example.rb +9 -4
 - data/lib/haveapi/example_list.rb +2 -2
 - data/lib/haveapi/exceptions.rb +1 -1
 - data/lib/haveapi/extensions/action_exceptions.rb +2 -2
 - data/lib/haveapi/extensions/base.rb +1 -3
 - data/lib/haveapi/extensions/exception_mailer.rb +260 -257
 - data/lib/haveapi/hooks.rb +40 -39
 - data/lib/haveapi/metadata.rb +1 -1
 - data/lib/haveapi/model_adapter.rb +16 -27
 - data/lib/haveapi/model_adapters/active_record.rb +59 -69
 - data/lib/haveapi/output_formatter.rb +7 -7
 - data/lib/haveapi/output_formatters/base.rb +2 -4
 - data/lib/haveapi/parameters/resource.rb +7 -7
 - data/lib/haveapi/parameters/typed.rb +6 -9
 - data/lib/haveapi/params.rb +38 -45
 - data/lib/haveapi/resource.rb +8 -8
 - data/lib/haveapi/resources/action_state.rb +11 -19
 - data/lib/haveapi/server.rb +102 -107
 - data/lib/haveapi/spec/api_response.rb +1 -1
 - data/lib/haveapi/spec/helpers.rb +1 -1
 - data/lib/haveapi/spec/mock_action.rb +11 -10
 - data/lib/haveapi/spec/spec_methods.rb +9 -8
 - data/lib/haveapi/tasks/yard.rb +2 -2
 - data/lib/haveapi/types.rb +0 -3
 - data/lib/haveapi/validator.rb +6 -3
 - data/lib/haveapi/validator_chain.rb +9 -8
 - data/lib/haveapi/validators/acceptance.rb +6 -6
 - data/lib/haveapi/validators/confirmation.rb +2 -3
 - data/lib/haveapi/validators/exclusion.rb +1 -1
 - data/lib/haveapi/validators/format.rb +1 -1
 - data/lib/haveapi/validators/inclusion.rb +1 -1
 - data/lib/haveapi/validators/length.rb +12 -11
 - data/lib/haveapi/validators/numericality.rb +14 -13
 - data/lib/haveapi/validators/presence.rb +4 -3
 - data/lib/haveapi/version.rb +2 -2
 - data/lib/haveapi.rb +2 -3
 - data/spec/.rubocop.yml +4 -0
 - data/spec/action/dsl_spec.rb +18 -18
 - data/spec/authorization_spec.rb +8 -8
 - data/spec/common_spec.rb +2 -1
 - data/spec/documentation_spec.rb +2 -9
 - data/spec/envelope_spec.rb +2 -2
 - data/spec/hooks_spec.rb +12 -12
 - data/spec/parameters/typed_spec.rb +6 -6
 - data/spec/params_spec.rb +22 -24
 - data/spec/resource_spec.rb +5 -7
 - data/spec/spec_helper.rb +0 -1
 - data/spec/validators/acceptance_spec.rb +1 -1
 - data/spec/validators/confirmation_spec.rb +5 -5
 - data/spec/validators/exclusion_spec.rb +3 -3
 - data/spec/validators/format_spec.rb +2 -2
 - data/spec/validators/inclusion_spec.rb +4 -4
 - data/spec/validators/length_spec.rb +23 -23
 - data/spec/validators/numericality_spec.rb +13 -13
 - data/spec/validators/presence_spec.rb +3 -3
 - metadata +49 -48
 
    
        data/lib/haveapi/server.rb
    CHANGED
    
    | 
         @@ -6,34 +6,34 @@ require 'haveapi/hooks' 
     | 
|
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            module HaveAPI
         
     | 
| 
       8 
8 
     | 
    
         
             
              class Server
         
     | 
| 
       9 
     | 
    
         
            -
                 
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
                attr_accessor :action_state
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_accessor :default_version, :action_state
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_reader :root, :routes, :module_name, :auth_chain, :versions, :extensions
         
     | 
| 
       12 
11 
     | 
    
         | 
| 
       13 
12 
     | 
    
         
             
                include Hookable
         
     | 
| 
       14 
13 
     | 
    
         | 
| 
       15 
14 
     | 
    
         
             
                # Called after the user was authenticated (or not). The block is passed
         
     | 
| 
       16 
15 
     | 
    
         
             
                # current user object or nil as an argument.
         
     | 
| 
       17 
16 
     | 
    
         
             
                has_hook :post_authenticated,
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 17 
     | 
    
         
            +
                         desc: 'Called after the user was authenticated',
         
     | 
| 
      
 18 
     | 
    
         
            +
                         args: {
         
     | 
| 
      
 19 
     | 
    
         
            +
                           current_user: 'object returned by the authentication backend'
         
     | 
| 
      
 20 
     | 
    
         
            +
                         }
         
     | 
| 
       22 
21 
     | 
    
         | 
| 
       23 
22 
     | 
    
         
             
                has_hook :description_exception,
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
      
 23 
     | 
    
         
            +
                         desc: 'Called when an exception occurs when building self-description',
         
     | 
| 
      
 24 
     | 
    
         
            +
                         args: {
         
     | 
| 
      
 25 
     | 
    
         
            +
                           context: 'HaveAPI::Context',
         
     | 
| 
      
 26 
     | 
    
         
            +
                           exception: 'exception instance'
         
     | 
| 
      
 27 
     | 
    
         
            +
                         },
         
     | 
| 
      
 28 
     | 
    
         
            +
                         ret: {
         
     | 
| 
      
 29 
     | 
    
         
            +
                           http_status: 'HTTP status code to send to client',
         
     | 
| 
      
 30 
     | 
    
         
            +
                           message: 'error message sent to the client'
         
     | 
| 
      
 31 
     | 
    
         
            +
                         }
         
     | 
| 
       33 
32 
     | 
    
         | 
| 
       34 
33 
     | 
    
         
             
                module ServerHelpers
         
     | 
| 
       35 
34 
     | 
    
         
             
                  def setup_formatter
         
     | 
| 
       36 
35 
     | 
    
         
             
                    return if @formatter
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
       37 
37 
     | 
    
         
             
                    @formatter = OutputFormatter.new
         
     | 
| 
       38 
38 
     | 
    
         | 
| 
       39 
39 
     | 
    
         
             
                    unless @formatter.supports?(request.accept)
         
     | 
| 
         @@ -57,15 +57,15 @@ module HaveAPI 
     | 
|
| 
       57 
57 
     | 
    
         
             
                  end
         
     | 
| 
       58 
58 
     | 
    
         | 
| 
       59 
59 
     | 
    
         
             
                  def access_control
         
     | 
| 
       60 
     | 
    
         
            -
                     
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
     | 
    
         
            -
                       
     | 
| 
       68 
     | 
    
         
            -
                     
     | 
| 
      
 60 
     | 
    
         
            +
                    return unless request.env['HTTP_ORIGIN'] && request.env['HTTP_ACCESS_CONTROL_REQUEST_METHOD']
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                    halt 200, {
         
     | 
| 
      
 63 
     | 
    
         
            +
                      'Access-Control-Allow-Origin' => '*',
         
     | 
| 
      
 64 
     | 
    
         
            +
                      'Access-Control-Allow-Methods' => 'GET,POST,OPTIONS,PATCH,PUT,DELETE',
         
     | 
| 
      
 65 
     | 
    
         
            +
                      'Access-Control-Allow-Credentials' => 'false',
         
     | 
| 
      
 66 
     | 
    
         
            +
                      'Access-Control-Allow-Headers' => settings.api_server.allowed_headers,
         
     | 
| 
      
 67 
     | 
    
         
            +
                      'Access-Control-Max-Age' => (60 * 60).to_s
         
     | 
| 
      
 68 
     | 
    
         
            +
                    }, ''
         
     | 
| 
       69 
69 
     | 
    
         
             
                  end
         
     | 
| 
       70 
70 
     | 
    
         | 
| 
       71 
71 
     | 
    
         
             
                  def current_user
         
     | 
| 
         @@ -80,7 +80,7 @@ module HaveAPI 
     | 
|
| 
       80 
80 
     | 
    
         
             
                  def require_auth!
         
     | 
| 
       81 
81 
     | 
    
         
             
                    report_error(
         
     | 
| 
       82 
82 
     | 
    
         
             
                      401,
         
     | 
| 
       83 
     | 
    
         
            -
                      {'WWW-Authenticate' => 'Basic realm="Restricted Area"'},
         
     | 
| 
      
 83 
     | 
    
         
            +
                      { 'WWW-Authenticate' => 'Basic realm="Restricted Area"' },
         
     | 
| 
       84 
84 
     | 
    
         
             
                      'Action requires user to authenticate'
         
     | 
| 
       85 
85 
     | 
    
         
             
                    )
         
     | 
| 
       86 
86 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -106,12 +106,12 @@ module HaveAPI 
     | 
|
| 
       106 
106 
     | 
    
         
             
                  end
         
     | 
| 
       107 
107 
     | 
    
         | 
| 
       108 
108 
     | 
    
         
             
                  def base_url
         
     | 
| 
       109 
     | 
    
         
            -
                    if request.env['HTTP_X_FORWARDED_SSL'] == 'on'
         
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
      
 109 
     | 
    
         
            +
                    scheme = if request.env['HTTP_X_FORWARDED_SSL'] == 'on'
         
     | 
| 
      
 110 
     | 
    
         
            +
                               'https'
         
     | 
| 
       111 
111 
     | 
    
         | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
      
 112 
     | 
    
         
            +
                             else
         
     | 
| 
      
 113 
     | 
    
         
            +
                               request.env['rack.url_scheme']
         
     | 
| 
      
 114 
     | 
    
         
            +
                             end
         
     | 
| 
       115 
115 
     | 
    
         | 
| 
       116 
116 
     | 
    
         
             
                    "#{scheme}://#{request.env['HTTP_HOST']}"
         
     | 
| 
       117 
117 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -140,6 +140,7 @@ module HaveAPI 
     | 
|
| 
       140 
140 
     | 
    
         
             
                module DocHelpers
         
     | 
| 
       141 
141 
     | 
    
         
             
                  def format_param_type(param)
         
     | 
| 
       142 
142 
     | 
    
         
             
                    return param[:type] if param[:type] != 'Resource'
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
       143 
144 
     | 
    
         
             
                    "<a href=\"#root-#{param[:resource].join('-')}-show\">#{param[:type]}</a>"
         
     | 
| 
       144 
145 
     | 
    
         
             
                  end
         
     | 
| 
       145 
146 
     | 
    
         | 
| 
         @@ -188,14 +189,11 @@ module HaveAPI 
     | 
|
| 
       188 
189 
     | 
    
         
             
                end
         
     | 
| 
       189 
190 
     | 
    
         | 
| 
       190 
191 
     | 
    
         
             
                # Set default version of API.
         
     | 
| 
       191 
     | 
    
         
            -
                def default_version=(v)
         
     | 
| 
       192 
     | 
    
         
            -
                  @default_version = v
         
     | 
| 
       193 
     | 
    
         
            -
                end
         
     | 
| 
       194 
192 
     | 
    
         | 
| 
       195 
193 
     | 
    
         
             
                # Load routes for all resource from included API versions.
         
     | 
| 
       196 
194 
     | 
    
         
             
                # All routes are mounted under prefix `path`.
         
     | 
| 
       197 
195 
     | 
    
         
             
                # If no default version is set, the last included version is used.
         
     | 
| 
       198 
     | 
    
         
            -
                def mount(prefix='/')
         
     | 
| 
      
 196 
     | 
    
         
            +
                def mount(prefix = '/')
         
     | 
| 
       199 
197 
     | 
    
         
             
                  @root = prefix
         
     | 
| 
       200 
198 
     | 
    
         | 
| 
       201 
199 
     | 
    
         
             
                  @sinatra = Sinatra.new do
         
     | 
| 
         @@ -203,8 +201,8 @@ module HaveAPI 
     | 
|
| 
       203 
201 
     | 
    
         
             
                    # for markdown files with extension .md, only .markdown
         
     | 
| 
       204 
202 
     | 
    
         
             
                    Tilt[:md]
         
     | 
| 
       205 
203 
     | 
    
         | 
| 
       206 
     | 
    
         
            -
                    set :views, settings.root 
     | 
| 
       207 
     | 
    
         
            -
                    set :public_folder, settings.root 
     | 
| 
      
 204 
     | 
    
         
            +
                    set :views, "#{settings.root}/views"
         
     | 
| 
      
 205 
     | 
    
         
            +
                    set :public_folder, "#{settings.root}/public"
         
     | 
| 
       208 
206 
     | 
    
         
             
                    set :bind, '0.0.0.0'
         
     | 
| 
       209 
207 
     | 
    
         | 
| 
       210 
208 
     | 
    
         
             
                    if settings.development?
         
     | 
| 
         @@ -246,10 +244,10 @@ module HaveAPI 
     | 
|
| 
       246 
244 
     | 
    
         
             
                    authenticated?(settings.api_server.default_version)
         
     | 
| 
       247 
245 
     | 
    
         | 
| 
       248 
246 
     | 
    
         
             
                    @api = settings.api_server.describe(Context.new(
         
     | 
| 
       249 
     | 
    
         
            -
             
     | 
| 
       250 
     | 
    
         
            -
             
     | 
| 
       251 
     | 
    
         
            -
             
     | 
| 
       252 
     | 
    
         
            -
             
     | 
| 
      
 247 
     | 
    
         
            +
                                                          settings.api_server,
         
     | 
| 
      
 248 
     | 
    
         
            +
                                                          user: current_user,
         
     | 
| 
      
 249 
     | 
    
         
            +
                                                          params:
         
     | 
| 
      
 250 
     | 
    
         
            +
                                                        ))
         
     | 
| 
       253 
251 
     | 
    
         | 
| 
       254 
252 
     | 
    
         
             
                    content_type 'text/html'
         
     | 
| 
       255 
253 
     | 
    
         
             
                    erb :index, layout: :main_layout
         
     | 
| 
         @@ -261,27 +259,27 @@ module HaveAPI 
     | 
|
| 
       261 
259 
     | 
    
         
             
                    authenticated?(settings.api_server.default_version)
         
     | 
| 
       262 
260 
     | 
    
         
             
                    ret = nil
         
     | 
| 
       263 
261 
     | 
    
         | 
| 
       264 
     | 
    
         
            -
                    case params[:describe]
         
     | 
| 
       265 
     | 
    
         
            -
             
     | 
| 
       266 
     | 
    
         
            -
             
     | 
| 
       267 
     | 
    
         
            -
             
     | 
| 
       268 
     | 
    
         
            -
             
     | 
| 
       269 
     | 
    
         
            -
             
     | 
| 
       270 
     | 
    
         
            -
             
     | 
| 
       271 
     | 
    
         
            -
             
     | 
| 
       272 
     | 
    
         
            -
             
     | 
| 
       273 
     | 
    
         
            -
             
     | 
| 
       274 
     | 
    
         
            -
             
     | 
| 
       275 
     | 
    
         
            -
             
     | 
| 
       276 
     | 
    
         
            -
             
     | 
| 
       277 
     | 
    
         
            -
             
     | 
| 
       278 
     | 
    
         
            -
             
     | 
| 
       279 
     | 
    
         
            -
             
     | 
| 
       280 
     | 
    
         
            -
             
     | 
| 
       281 
     | 
    
         
            -
             
     | 
| 
       282 
     | 
    
         
            -
             
     | 
| 
       283 
     | 
    
         
            -
             
     | 
| 
       284 
     | 
    
         
            -
             
     | 
| 
      
 262 
     | 
    
         
            +
                    ret = case params[:describe]
         
     | 
| 
      
 263 
     | 
    
         
            +
                          when 'versions'
         
     | 
| 
      
 264 
     | 
    
         
            +
                            {
         
     | 
| 
      
 265 
     | 
    
         
            +
                              versions: settings.api_server.versions,
         
     | 
| 
      
 266 
     | 
    
         
            +
                              default: settings.api_server.default_version
         
     | 
| 
      
 267 
     | 
    
         
            +
                            }
         
     | 
| 
      
 268 
     | 
    
         
            +
             
     | 
| 
      
 269 
     | 
    
         
            +
                          when 'default'
         
     | 
| 
      
 270 
     | 
    
         
            +
                            settings.api_server.describe_version(Context.new(
         
     | 
| 
      
 271 
     | 
    
         
            +
                                                                   settings.api_server,
         
     | 
| 
      
 272 
     | 
    
         
            +
                                                                   version: settings.api_server.default_version,
         
     | 
| 
      
 273 
     | 
    
         
            +
                                                                   user: current_user, params:
         
     | 
| 
      
 274 
     | 
    
         
            +
                                                                 ))
         
     | 
| 
      
 275 
     | 
    
         
            +
             
     | 
| 
      
 276 
     | 
    
         
            +
                          else
         
     | 
| 
      
 277 
     | 
    
         
            +
                            settings.api_server.describe(Context.new(
         
     | 
| 
      
 278 
     | 
    
         
            +
                                                           settings.api_server,
         
     | 
| 
      
 279 
     | 
    
         
            +
                                                           user: current_user,
         
     | 
| 
      
 280 
     | 
    
         
            +
                                                           params:
         
     | 
| 
      
 281 
     | 
    
         
            +
                                                         ))
         
     | 
| 
      
 282 
     | 
    
         
            +
                          end
         
     | 
| 
       285 
283 
     | 
    
         | 
| 
       286 
284 
     | 
    
         
             
                    @formatter.format(true, ret)
         
     | 
| 
       287 
285 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -298,7 +296,7 @@ module HaveAPI 
     | 
|
| 
       298 
296 
     | 
    
         
             
                    content_type 'text/html'
         
     | 
| 
       299 
297 
     | 
    
         | 
| 
       300 
298 
     | 
    
         
             
                    erb :main_layout do
         
     | 
| 
       301 
     | 
    
         
            -
                      GitHub::Markdown.render(File.new(settings.views 
     | 
| 
      
 299 
     | 
    
         
            +
                      GitHub::Markdown.render(File.new("#{settings.views}/../../../README.md").read)
         
     | 
| 
       302 
300 
     | 
    
         
             
                    end
         
     | 
| 
       303 
301 
     | 
    
         
             
                  end
         
     | 
| 
       304 
302 
     | 
    
         | 
| 
         @@ -315,7 +313,6 @@ module HaveAPI 
     | 
|
| 
       315 
313 
     | 
    
         
             
                    erb :doc_layout, layout: :main_layout do
         
     | 
| 
       316 
314 
     | 
    
         
             
                      begin
         
     | 
| 
       317 
315 
     | 
    
         
             
                        @content = doc(f)
         
     | 
| 
       318 
     | 
    
         
            -
             
     | 
| 
       319 
316 
     | 
    
         
             
                      rescue Errno::ENOENT
         
     | 
| 
       320 
317 
     | 
    
         
             
                        halt 404
         
     | 
| 
       321 
318 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -359,11 +356,11 @@ module HaveAPI 
     | 
|
| 
       359 
356 
     | 
    
         | 
| 
       360 
357 
     | 
    
         
             
                    @v = v
         
     | 
| 
       361 
358 
     | 
    
         
             
                    @help = settings.api_server.describe_version(Context.new(
         
     | 
| 
       362 
     | 
    
         
            -
             
     | 
| 
       363 
     | 
    
         
            -
             
     | 
| 
       364 
     | 
    
         
            -
             
     | 
| 
       365 
     | 
    
         
            -
             
     | 
| 
       366 
     | 
    
         
            -
             
     | 
| 
      
 359 
     | 
    
         
            +
                                                                   settings.api_server,
         
     | 
| 
      
 360 
     | 
    
         
            +
                                                                   version: v,
         
     | 
| 
      
 361 
     | 
    
         
            +
                                                                   user: current_user,
         
     | 
| 
      
 362 
     | 
    
         
            +
                                                                   params:
         
     | 
| 
      
 363 
     | 
    
         
            +
                                                                 ))
         
     | 
| 
       367 
364 
     | 
    
         | 
| 
       368 
365 
     | 
    
         
             
                    content_type 'text/html'
         
     | 
| 
       369 
366 
     | 
    
         
             
                    erb :doc_layout, layout: :main_layout do
         
     | 
| 
         @@ -378,11 +375,11 @@ module HaveAPI 
     | 
|
| 
       378 
375 
     | 
    
         
             
                    authenticated?(v)
         
     | 
| 
       379 
376 
     | 
    
         | 
| 
       380 
377 
     | 
    
         
             
                    @formatter.format(true, settings.api_server.describe_version(Context.new(
         
     | 
| 
       381 
     | 
    
         
            -
             
     | 
| 
       382 
     | 
    
         
            -
             
     | 
| 
       383 
     | 
    
         
            -
             
     | 
| 
       384 
     | 
    
         
            -
             
     | 
| 
       385 
     | 
    
         
            -
             
     | 
| 
      
 378 
     | 
    
         
            +
                                                                                   settings.api_server,
         
     | 
| 
      
 379 
     | 
    
         
            +
                                                                                   version: v,
         
     | 
| 
      
 380 
     | 
    
         
            +
                                                                                   user: current_user,
         
     | 
| 
      
 381 
     | 
    
         
            +
                                                                                   params:
         
     | 
| 
      
 382 
     | 
    
         
            +
                                                                                 )))
         
     | 
| 
       386 
383 
     | 
    
         
             
                  end
         
     | 
| 
       387 
384 
     | 
    
         | 
| 
       388 
385 
     | 
    
         
             
                  # Register blocking resource
         
     | 
| 
         @@ -404,16 +401,14 @@ module HaveAPI 
     | 
|
| 
       404 
401 
     | 
    
         | 
| 
       405 
402 
     | 
    
         
             
                def validate_resources(resources)
         
     | 
| 
       406 
403 
     | 
    
         
             
                  resources.each_value do |r|
         
     | 
| 
       407 
     | 
    
         
            -
                    r[:actions].each_key 
     | 
| 
       408 
     | 
    
         
            -
                      a.validate_build
         
     | 
| 
       409 
     | 
    
         
            -
                    end
         
     | 
| 
      
 404 
     | 
    
         
            +
                    r[:actions].each_key(&:validate_build)
         
     | 
| 
       410 
405 
     | 
    
         | 
| 
       411 
406 
     | 
    
         
             
                    validate_resources(r[:resources])
         
     | 
| 
       412 
407 
     | 
    
         
             
                  end
         
     | 
| 
       413 
408 
     | 
    
         
             
                end
         
     | 
| 
       414 
409 
     | 
    
         | 
| 
       415 
410 
     | 
    
         
             
                def mount_resource(prefix, v, resource, hash)
         
     | 
| 
       416 
     | 
    
         
            -
                  hash[resource] = {resources: {}, actions: {}}
         
     | 
| 
      
 411 
     | 
    
         
            +
                  hash[resource] = { resources: {}, actions: {} }
         
     | 
| 
       417 
412 
     | 
    
         | 
| 
       418 
413 
     | 
    
         
             
                  resource.routes(prefix).each do |route|
         
     | 
| 
       419 
414 
     | 
    
         
             
                    if route.is_a?(Hash)
         
     | 
| 
         @@ -430,7 +425,7 @@ module HaveAPI 
     | 
|
| 
       430 
425 
     | 
    
         
             
                end
         
     | 
| 
       431 
426 
     | 
    
         | 
| 
       432 
427 
     | 
    
         
             
                def mount_nested_resource(v, routes)
         
     | 
| 
       433 
     | 
    
         
            -
                  ret = {resources: {}, actions: {}}
         
     | 
| 
      
 428 
     | 
    
         
            +
                  ret = { resources: {}, actions: {} }
         
     | 
| 
       434 
429 
     | 
    
         | 
| 
       435 
430 
     | 
    
         
             
                  routes.each do |route|
         
     | 
| 
       436 
431 
     | 
    
         
             
                    if route.is_a?(Hash)
         
     | 
| 
         @@ -460,27 +455,26 @@ module HaveAPI 
     | 
|
| 
       460 
455 
     | 
    
         
             
                    begin
         
     | 
| 
       461 
456 
     | 
    
         
             
                      body = request.body.read
         
     | 
| 
       462 
457 
     | 
    
         | 
| 
       463 
     | 
    
         
            -
                      if body.empty?
         
     | 
| 
       464 
     | 
    
         
            -
             
     | 
| 
       465 
     | 
    
         
            -
             
     | 
| 
       466 
     | 
    
         
            -
             
     | 
| 
       467 
     | 
    
         
            -
             
     | 
| 
       468 
     | 
    
         
            -
             
     | 
| 
       469 
     | 
    
         
            -
                    rescue => e
         
     | 
| 
      
 458 
     | 
    
         
            +
                      body = if body.empty?
         
     | 
| 
      
 459 
     | 
    
         
            +
                               nil
         
     | 
| 
      
 460 
     | 
    
         
            +
                             else
         
     | 
| 
      
 461 
     | 
    
         
            +
                               JSON.parse(body, symbolize_names: true)
         
     | 
| 
      
 462 
     | 
    
         
            +
                             end
         
     | 
| 
      
 463 
     | 
    
         
            +
                    rescue StandardError => e
         
     | 
| 
       470 
464 
     | 
    
         
             
                      report_error(400, {}, 'Bad JSON syntax')
         
     | 
| 
       471 
465 
     | 
    
         
             
                    end
         
     | 
| 
       472 
466 
     | 
    
         | 
| 
       473 
467 
     | 
    
         
             
                    action = route.action.new(request, v, params, body, Context.new(
         
     | 
| 
       474 
     | 
    
         
            -
             
     | 
| 
       475 
     | 
    
         
            -
             
     | 
| 
       476 
     | 
    
         
            -
             
     | 
| 
       477 
     | 
    
         
            -
             
     | 
| 
       478 
     | 
    
         
            -
             
     | 
| 
       479 
     | 
    
         
            -
             
     | 
| 
       480 
     | 
    
         
            -
             
     | 
| 
       481 
     | 
    
         
            -
             
     | 
| 
       482 
     | 
    
         
            -
             
     | 
| 
       483 
     | 
    
         
            -
             
     | 
| 
      
 468 
     | 
    
         
            +
                                                                          settings.api_server,
         
     | 
| 
      
 469 
     | 
    
         
            +
                                                                          version: v,
         
     | 
| 
      
 470 
     | 
    
         
            +
                                                                          request: self,
         
     | 
| 
      
 471 
     | 
    
         
            +
                                                                          action: route.action,
         
     | 
| 
      
 472 
     | 
    
         
            +
                                                                          path: route.path,
         
     | 
| 
      
 473 
     | 
    
         
            +
                                                                          params:,
         
     | 
| 
      
 474 
     | 
    
         
            +
                                                                          user: current_user,
         
     | 
| 
      
 475 
     | 
    
         
            +
                                                                          endpoint: true,
         
     | 
| 
      
 476 
     | 
    
         
            +
                                                                          resource_path: route.resource_path
         
     | 
| 
      
 477 
     | 
    
         
            +
                                                                        ))
         
     | 
| 
       484 
478 
     | 
    
         | 
| 
       485 
479 
     | 
    
         
             
                    unless action.authorized?(current_user)
         
     | 
| 
       486 
480 
     | 
    
         
             
                      report_error(403, {}, 'Access denied. Insufficient permissions.')
         
     | 
| 
         @@ -493,11 +487,11 @@ module HaveAPI 
     | 
|
| 
       493 
487 
     | 
    
         
             
                      http_status || 200,
         
     | 
| 
       494 
488 
     | 
    
         
             
                      @formatter.format(
         
     | 
| 
       495 
489 
     | 
    
         
             
                        status,
         
     | 
| 
       496 
     | 
    
         
            -
                        status 
     | 
| 
       497 
     | 
    
         
            -
                         
     | 
| 
      
 490 
     | 
    
         
            +
                        status ? reply : nil,
         
     | 
| 
      
 491 
     | 
    
         
            +
                        status ? nil : reply,
         
     | 
| 
       498 
492 
     | 
    
         
             
                        errors,
         
     | 
| 
       499 
493 
     | 
    
         
             
                        version: false
         
     | 
| 
       500 
     | 
    
         
            -
                      ) 
     | 
| 
      
 494 
     | 
    
         
            +
                      )
         
     | 
| 
       501 
495 
     | 
    
         
             
                    ]
         
     | 
| 
       502 
496 
     | 
    
         
             
                  end
         
     | 
| 
       503 
497 
     | 
    
         | 
| 
         @@ -520,11 +514,11 @@ module HaveAPI 
     | 
|
| 
       520 
514 
     | 
    
         
             
                      request: self,
         
     | 
| 
       521 
515 
     | 
    
         
             
                      action: route.action,
         
     | 
| 
       522 
516 
     | 
    
         
             
                      path: route.path,
         
     | 
| 
       523 
     | 
    
         
            -
                      args 
     | 
| 
       524 
     | 
    
         
            -
                      params 
     | 
| 
      
 517 
     | 
    
         
            +
                      args:,
         
     | 
| 
      
 518 
     | 
    
         
            +
                      params:,
         
     | 
| 
       525 
519 
     | 
    
         
             
                      user: current_user,
         
     | 
| 
       526 
520 
     | 
    
         
             
                      endpoint: true,
         
     | 
| 
       527 
     | 
    
         
            -
                      resource_path: route.resource_path 
     | 
| 
      
 521 
     | 
    
         
            +
                      resource_path: route.resource_path
         
     | 
| 
       528 
522 
     | 
    
         
             
                    )
         
     | 
| 
       529 
523 
     | 
    
         | 
| 
       530 
524 
     | 
    
         
             
                    begin
         
     | 
| 
         @@ -533,8 +527,7 @@ module HaveAPI 
     | 
|
| 
       533 
527 
     | 
    
         
             
                      unless desc
         
     | 
| 
       534 
528 
     | 
    
         
             
                        report_error(403, {}, 'Access denied. Insufficient permissions.')
         
     | 
| 
       535 
529 
     | 
    
         
             
                      end
         
     | 
| 
       536 
     | 
    
         
            -
             
     | 
| 
       537 
     | 
    
         
            -
                    rescue => e
         
     | 
| 
      
 530 
     | 
    
         
            +
                    rescue StandardError => e
         
     | 
| 
       538 
531 
     | 
    
         
             
                      tmp = settings.api_server.call_hooks_for(:description_exception, args: [ctx, e])
         
     | 
| 
       539 
532 
     | 
    
         
             
                      report_error(
         
     | 
| 
       540 
533 
     | 
    
         
             
                        tmp[:http_status] || 500,
         
     | 
| 
         @@ -552,7 +545,7 @@ module HaveAPI 
     | 
|
| 
       552 
545 
     | 
    
         | 
| 
       553 
546 
     | 
    
         
             
                  ret = {
         
     | 
| 
       554 
547 
     | 
    
         
             
                    default_version: @default_version,
         
     | 
| 
       555 
     | 
    
         
            -
                    versions: {default: describe_version(context)} 
     | 
| 
      
 548 
     | 
    
         
            +
                    versions: { default: describe_version(context) }
         
     | 
| 
       556 
549 
     | 
    
         
             
                  }
         
     | 
| 
       557 
550 
     | 
    
         | 
| 
       558 
551 
     | 
    
         
             
                  @versions.each do |v|
         
     | 
| 
         @@ -571,7 +564,7 @@ module HaveAPI 
     | 
|
| 
       571 
564 
     | 
    
         
             
                    help: version_prefix(context.version)
         
     | 
| 
       572 
565 
     | 
    
         
             
                  }
         
     | 
| 
       573 
566 
     | 
    
         | 
| 
       574 
     | 
    
         
            -
                  #puts JSON.pretty_generate(@routes)
         
     | 
| 
      
 567 
     | 
    
         
            +
                  # puts JSON.pretty_generate(@routes)
         
     | 
| 
       575 
568 
     | 
    
         | 
| 
       576 
569 
     | 
    
         
             
                  @routes[context.version][:resources].each do |resource, children|
         
     | 
| 
       577 
570 
     | 
    
         
             
                    r_name = resource.resource_name.underscore
         
     | 
| 
         @@ -601,7 +594,7 @@ module HaveAPI 
     | 
|
| 
       601 
594 
     | 
    
         
             
                end
         
     | 
| 
       602 
595 
     | 
    
         | 
| 
       603 
596 
     | 
    
         
             
                def add_auth_module(v, name, mod, prefix: '')
         
     | 
| 
       604 
     | 
    
         
            -
                  @routes[v] ||= {authentication: {name => {resources: {}}}}
         
     | 
| 
      
 597 
     | 
    
         
            +
                  @routes[v] ||= { authentication: { name => { resources: {} } } }
         
     | 
| 
       605 
598 
     | 
    
         | 
| 
       606 
599 
     | 
    
         
             
                  HaveAPI.get_version_resources(mod, v).each do |r|
         
     | 
| 
       607 
600 
     | 
    
         
             
                    mount_resource("#{@root}_auth/#{prefix}/", v, r, @routes[v][:authentication][name][:resources])
         
     | 
| 
         @@ -615,6 +608,7 @@ module HaveAPI 
     | 
|
| 
       615 
608 
     | 
    
         | 
| 
       616 
609 
     | 
    
         
             
                def allowed_headers
         
     | 
| 
       617 
610 
     | 
    
         
             
                  return @allowed_headers_str if @allowed_headers_str
         
     | 
| 
      
 611 
     | 
    
         
            +
             
     | 
| 
       618 
612 
     | 
    
         
             
                  @allowed_headers_str = @allowed_headers.join(',')
         
     | 
| 
       619 
613 
     | 
    
         
             
                end
         
     | 
| 
       620 
614 
     | 
    
         | 
| 
         @@ -627,6 +621,7 @@ module HaveAPI 
     | 
|
| 
       627 
621 
     | 
    
         
             
                end
         
     | 
| 
       628 
622 
     | 
    
         | 
| 
       629 
623 
     | 
    
         
             
                private
         
     | 
| 
      
 624 
     | 
    
         
            +
             
     | 
| 
       630 
625 
     | 
    
         
             
                def do_authenticate(v, request)
         
     | 
| 
       631 
626 
     | 
    
         
             
                  @auth_chain.authenticate(v, request)
         
     | 
| 
       632 
627 
     | 
    
         
             
                end
         
     | 
    
        data/lib/haveapi/spec/helpers.rb
    CHANGED
    
    
| 
         @@ -10,21 +10,22 @@ module HaveAPI::Spec 
     | 
|
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
                def call(input, user: nil, &block)
         
     | 
| 
       12 
12 
     | 
    
         
             
                  action = @action.new(nil, @v, input, nil, HaveAPI::Context.new(
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
      
 13 
     | 
    
         
            +
                                                              @server,
         
     | 
| 
      
 14 
     | 
    
         
            +
                                                              version: @v,
         
     | 
| 
      
 15 
     | 
    
         
            +
                                                              action: @action,
         
     | 
| 
      
 16 
     | 
    
         
            +
                                                              path: @path,
         
     | 
| 
      
 17 
     | 
    
         
            +
                                                              params: input,
         
     | 
| 
      
 18 
     | 
    
         
            +
                                                              user:,
         
     | 
| 
      
 19 
     | 
    
         
            +
                                                              endpoint: true
         
     | 
| 
      
 20 
     | 
    
         
            +
                                                            ))
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
                  unless action.authorized?(user)
         
     | 
| 
       23 
     | 
    
         
            -
                     
     | 
| 
      
 23 
     | 
    
         
            +
                    raise 'Access denied. Insufficient permissions.'
         
     | 
| 
       24 
24 
     | 
    
         
             
                  end
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
                  status, data, errors = action.safe_exec
         
     | 
| 
       27 
     | 
    
         
            -
                   
     | 
| 
      
 27 
     | 
    
         
            +
                  raise(data || 'action failed') unless status
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
       28 
29 
     | 
    
         
             
                  action.instance_exec(@test, &block)
         
     | 
| 
       29 
30 
     | 
    
         
             
                  data
         
     | 
| 
       30 
31 
     | 
    
         
             
                end
         
     | 
| 
         @@ -28,7 +28,7 @@ module HaveAPI::Spec 
     | 
|
| 
       28 
28 
     | 
    
         
             
                # Two modes:
         
     | 
| 
       29 
29 
     | 
    
         
             
                #   http_method, path, params = {}
         
     | 
| 
       30 
30 
     | 
    
         
             
                #   [resource], action, params, &block
         
     | 
| 
       31 
     | 
    
         
            -
                def call_api(*args, & 
     | 
| 
      
 31 
     | 
    
         
            +
                def call_api(*args, &)
         
     | 
| 
       32 
32 
     | 
    
         
             
                  if args[0].is_a?(::Array) || args[1].is_a?(::Symbol)
         
     | 
| 
       33 
33 
     | 
    
         
             
                    r_name, a_name, params = args
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
         @@ -42,7 +42,7 @@ module HaveAPI::Spec 
     | 
|
| 
       42 
42 
     | 
    
         
             
                    method(action.http_method).call(
         
     | 
| 
       43 
43 
     | 
    
         
             
                      path,
         
     | 
| 
       44 
44 
     | 
    
         
             
                      params && params.to_json,
         
     | 
| 
       45 
     | 
    
         
            -
                      {'Content-Type' => 'application/json'}
         
     | 
| 
      
 45 
     | 
    
         
            +
                      { 'Content-Type' => 'application/json' }
         
     | 
| 
       46 
46 
     | 
    
         
             
                    )
         
     | 
| 
       47 
47 
     | 
    
         | 
| 
       48 
48 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -51,7 +51,7 @@ module HaveAPI::Spec 
     | 
|
| 
       51 
51 
     | 
    
         
             
                    method(http_method).call(
         
     | 
| 
       52 
52 
     | 
    
         
             
                      path,
         
     | 
| 
       53 
53 
     | 
    
         
             
                      params && params.to_json,
         
     | 
| 
       54 
     | 
    
         
            -
                      {'Content-Type' => 'application/json'}
         
     | 
| 
      
 54 
     | 
    
         
            +
                      { 'Content-Type' => 'application/json' }
         
     | 
| 
       55 
55 
     | 
    
         
             
                    )
         
     | 
| 
       56 
56 
     | 
    
         
             
                  end
         
     | 
| 
       57 
57 
     | 
    
         
             
                end
         
     | 
| 
         @@ -79,22 +79,23 @@ module HaveAPI::Spec 
     | 
|
| 
       79 
79 
     | 
    
         
             
                  v = version || @api.default_version
         
     | 
| 
       80 
80 
     | 
    
         
             
                  action, path = find_action(v, r_name, a_name)
         
     | 
| 
       81 
81 
     | 
    
         
             
                  m = MockAction.new(self, @api, action, path, v)
         
     | 
| 
       82 
     | 
    
         
            -
                  m.call(params, user 
     | 
| 
      
 82 
     | 
    
         
            +
                  m.call(params, user:, &block)
         
     | 
| 
       83 
83 
     | 
    
         
             
                end
         
     | 
| 
       84 
84 
     | 
    
         | 
| 
       85 
85 
     | 
    
         
             
                # Return parsed API response.
         
     | 
| 
       86 
86 
     | 
    
         
             
                # @return [HaveAPI::Spec::ApiResponse]
         
     | 
| 
       87 
87 
     | 
    
         
             
                def api_response
         
     | 
| 
       88 
     | 
    
         
            -
                  if last_response  
     | 
| 
      
 88 
     | 
    
         
            +
                  if last_response == @last_response
         
     | 
| 
      
 89 
     | 
    
         
            +
                    @api_response ||= ApiResponse.new(last_response.body)
         
     | 
| 
      
 90 
     | 
    
         
            +
                  else
         
     | 
| 
       89 
91 
     | 
    
         
             
                    @last_response = last_response
         
     | 
| 
       90 
92 
     | 
    
         
             
                    @api_response = ApiResponse.new(last_response.body)
         
     | 
| 
       91 
93 
     | 
    
         | 
| 
       92 
     | 
    
         
            -
                  else
         
     | 
| 
       93 
     | 
    
         
            -
                    @api_response ||= ApiResponse.new(last_response.body)
         
     | 
| 
       94 
94 
     | 
    
         
             
                  end
         
     | 
| 
       95 
95 
     | 
    
         
             
                end
         
     | 
| 
       96 
96 
     | 
    
         | 
| 
       97 
97 
     | 
    
         
             
                protected
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
       98 
99 
     | 
    
         
             
                def get_opt(name)
         
     | 
| 
       99 
100 
     | 
    
         
             
                  self.class.opts && self.class.opts[name]
         
     | 
| 
       100 
101 
     | 
    
         
             
                end
         
     | 
| 
         @@ -113,7 +114,7 @@ module HaveAPI::Spec 
     | 
|
| 
       113 
114 
     | 
    
         
             
                    end.second
         
     | 
| 
       114 
115 
     | 
    
         
             
                  end
         
     | 
| 
       115 
116 
     | 
    
         | 
| 
       116 
     | 
    
         
            -
                  top[:actions].detect do |k,  
     | 
| 
      
 117 
     | 
    
         
            +
                  top[:actions].detect do |k, _v|
         
     | 
| 
       117 
118 
     | 
    
         
             
                    k.to_s.demodulize.underscore.to_sym == a_name
         
     | 
| 
       118 
119 
     | 
    
         
             
                  end
         
     | 
| 
       119 
120 
     | 
    
         
             
                end
         
     | 
    
        data/lib/haveapi/tasks/yard.rb
    CHANGED
    
    | 
         @@ -3,10 +3,10 @@ require 'haveapi/tasks/hooks' 
     | 
|
| 
       3 
3 
     | 
    
         
             
            def render_doc_file(src, dst)
         
     | 
| 
       4 
4 
     | 
    
         
             
              src = File.join(File.dirname(__FILE__), '..', '..', '..', src)
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
               
     | 
| 
      
 6 
     | 
    
         
            +
              proc do
         
     | 
| 
       7 
7 
     | 
    
         
             
                File.write(
         
     | 
| 
       8 
8 
     | 
    
         
             
                  dst,
         
     | 
| 
       9 
     | 
    
         
            -
                  ERB.new(File.read(src) 
     | 
| 
      
 9 
     | 
    
         
            +
                  ERB.new(File.read(src)).result(binding)
         
     | 
| 
       10 
10 
     | 
    
         
             
                )
         
     | 
| 
       11 
11 
     | 
    
         
             
              end
         
     | 
| 
       12 
12 
     | 
    
         
             
            end
         
     | 
    
        data/lib/haveapi/types.rb
    CHANGED
    
    
    
        data/lib/haveapi/validator.rb
    CHANGED
    
    | 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module HaveAPI
         
     | 
| 
       2 
2 
     | 
    
         
             
              # Validators are stored in this module.
         
     | 
| 
       3 
     | 
    
         
            -
              module Validators 
     | 
| 
      
 3 
     | 
    
         
            +
              module Validators; end
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
              # Base class for all validators.
         
     | 
| 
       6 
6 
     | 
    
         
             
              #
         
     | 
| 
         @@ -37,7 +37,7 @@ module HaveAPI 
     | 
|
| 
       37 
37 
     | 
    
         | 
| 
       38 
38 
     | 
    
         
             
                  # True if this validator uses any of options in hash `opts`.
         
     | 
| 
       39 
39 
     | 
    
         
             
                  def use?(opts)
         
     | 
| 
       40 
     | 
    
         
            -
                     
     | 
| 
      
 40 
     | 
    
         
            +
                    opts.keys.intersect?(@takes)
         
     | 
| 
       41 
41 
     | 
    
         
             
                  end
         
     | 
| 
       42 
42 
     | 
    
         | 
| 
       43 
43 
     | 
    
         
             
                  # Use the validator on given set of options in hash `opts`. Used
         
     | 
| 
         @@ -45,7 +45,8 @@ module HaveAPI 
     | 
|
| 
       45 
45 
     | 
    
         
             
                  def use(opts)
         
     | 
| 
       46 
46 
     | 
    
         
             
                    keys = opts.keys & @takes
         
     | 
| 
       47 
47 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
                     
     | 
| 
      
 48 
     | 
    
         
            +
                    raise 'too many keys' if keys.size > 1
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
       49 
50 
     | 
    
         
             
                    new(keys.first, opts.delete(keys.first))
         
     | 
| 
       50 
51 
     | 
    
         
             
                  end
         
     | 
| 
       51 
52 
     | 
    
         
             
                end
         
     | 
| 
         @@ -94,6 +95,7 @@ module HaveAPI 
     | 
|
| 
       94 
95 
     | 
    
         
             
                end
         
     | 
| 
       95 
96 
     | 
    
         | 
| 
       96 
97 
     | 
    
         
             
                protected
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
       97 
99 
     | 
    
         
             
                # This method has three modes of function.
         
     | 
| 
       98 
100 
     | 
    
         
             
                #
         
     | 
| 
       99 
101 
     | 
    
         
             
                # 1. If `v` is nil, it returns `@opts`. It is used if `@opts` is not a hash
         
     | 
| 
         @@ -109,6 +111,7 @@ module HaveAPI 
     | 
|
| 
       109 
111 
     | 
    
         
             
                  else
         
     | 
| 
       110 
112 
     | 
    
         
             
                    return default unless @opts.is_a?(::Hash)
         
     | 
| 
       111 
113 
     | 
    
         
             
                    return @opts[v] unless @opts[v].nil?
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
       112 
115 
     | 
    
         
             
                    default
         
     | 
| 
       113 
116 
     | 
    
         
             
                  end
         
     | 
| 
       114 
117 
     | 
    
         
             
                end
         
     | 
| 
         @@ -8,6 +8,7 @@ module HaveAPI 
     | 
|
| 
       8 
8 
     | 
    
         
             
                  find_validators(args) do |validator|
         
     | 
| 
       9 
9 
     | 
    
         
             
                    obj = validator.use(args)
         
     | 
| 
       10 
10 
     | 
    
         
             
                    next unless obj.useful?
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
       11 
12 
     | 
    
         
             
                    @required = true if obj.is_a?(Validators::Presence)
         
     | 
| 
       12 
13 
     | 
    
         
             
                    @validators << obj
         
     | 
| 
       13 
14 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -21,8 +22,8 @@ module HaveAPI 
     | 
|
| 
       21 
22 
     | 
    
         
             
                def add_or_replace(name, opt)
         
     | 
| 
       22 
23 
     | 
    
         
             
                  args = { name => opt }
         
     | 
| 
       23 
24 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
                  unless v_class = find_validator(args)
         
     | 
| 
       25 
     | 
    
         
            -
                     
     | 
| 
      
 25 
     | 
    
         
            +
                  unless (v_class = find_validator(args))
         
     | 
| 
      
 26 
     | 
    
         
            +
                    raise "validator for '#{name}' not found"
         
     | 
| 
       26 
27 
     | 
    
         
             
                  end
         
     | 
| 
       27 
28 
     | 
    
         | 
| 
       28 
29 
     | 
    
         
             
                  exists = @validators.detect { |v| v.is_a?(v_class) }
         
     | 
| 
         @@ -42,9 +43,9 @@ module HaveAPI 
     | 
|
| 
       42 
43 
     | 
    
         
             
                    @validators << obj if obj.useful?
         
     | 
| 
       43 
44 
     | 
    
         
             
                  end
         
     | 
| 
       44 
45 
     | 
    
         | 
| 
       45 
     | 
    
         
            -
                   
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
                   
     | 
| 
      
 46 
     | 
    
         
            +
                  return unless v_class == Validators::Presence
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  @required = !opt.nil? && obj.useful?
         
     | 
| 
       48 
49 
     | 
    
         
             
                end
         
     | 
| 
       49 
50 
     | 
    
         | 
| 
       50 
51 
     | 
    
         
             
                # Returns true if validator Validators::Presence is used.
         
     | 
| 
         @@ -69,15 +70,15 @@ module HaveAPI 
     | 
|
| 
       69 
70 
     | 
    
         | 
| 
       70 
71 
     | 
    
         
             
                  @validators.each do |validator|
         
     | 
| 
       71 
72 
     | 
    
         
             
                    next if validator.validate(value, params)
         
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
                    }
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                    ret << (format(validator.message, value:))
         
     | 
| 
       75 
75 
     | 
    
         
             
                  end
         
     | 
| 
       76 
76 
     | 
    
         | 
| 
       77 
77 
     | 
    
         
             
                  ret.empty? ? true : ret
         
     | 
| 
       78 
78 
     | 
    
         
             
                end
         
     | 
| 
       79 
79 
     | 
    
         | 
| 
       80 
80 
     | 
    
         
             
                protected
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
       81 
82 
     | 
    
         
             
                def find_validator(args)
         
     | 
| 
       82 
83 
     | 
    
         
             
                  HaveAPI::Validators.constants.select do |v|
         
     | 
| 
       83 
84 
     | 
    
         
             
                    validator = HaveAPI::Validators.const_get(v)
         
     | 
| 
         @@ -16,12 +16,12 @@ module HaveAPI 
     | 
|
| 
       16 
16 
     | 
    
         
             
                takes :accept
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
                def setup
         
     | 
| 
       19 
     | 
    
         
            -
                  if simple?
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
      
 19 
     | 
    
         
            +
                  @value = if simple?
         
     | 
| 
      
 20 
     | 
    
         
            +
                             take
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
      
 22 
     | 
    
         
            +
                           else
         
     | 
| 
      
 23 
     | 
    
         
            +
                             take(:value)
         
     | 
| 
      
 24 
     | 
    
         
            +
                           end
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
                  @message = take(:message, "has to be #{@value}")
         
     | 
| 
       27 
27 
     | 
    
         
             
                end
         
     | 
| 
         @@ -29,7 +29,7 @@ module HaveAPI 
     | 
|
| 
       29 
29 
     | 
    
         
             
                def describe
         
     | 
| 
       30 
30 
     | 
    
         
             
                  {
         
     | 
| 
       31 
31 
     | 
    
         
             
                    value: @value,
         
     | 
| 
       32 
     | 
    
         
            -
                    message: @message 
     | 
| 
      
 32 
     | 
    
         
            +
                    message: @message
         
     | 
| 
       33 
33 
     | 
    
         
             
                  }
         
     | 
| 
       34 
34 
     | 
    
         
             
                end
         
     | 
| 
       35 
35 
     | 
    
         | 
| 
         @@ -23,8 +23,7 @@ module HaveAPI 
     | 
|
| 
       23 
23 
     | 
    
         
             
                  @equal = take(:equal, true)
         
     | 
| 
       24 
24 
     | 
    
         
             
                  @message = take(
         
     | 
| 
       25 
25 
     | 
    
         
             
                    :message,
         
     | 
| 
       26 
     | 
    
         
            -
                    @equal ? "must be the same as #{@param}"
         
     | 
| 
       27 
     | 
    
         
            -
                           : "must be different from #{@param}"
         
     | 
| 
      
 26 
     | 
    
         
            +
                    @equal ? "must be the same as #{@param}" : "must be different from #{@param}"
         
     | 
| 
       28 
27 
     | 
    
         
             
                  )
         
     | 
| 
       29 
28 
     | 
    
         
             
                end
         
     | 
| 
       30 
29 
     | 
    
         | 
| 
         @@ -32,7 +31,7 @@ module HaveAPI 
     | 
|
| 
       32 
31 
     | 
    
         
             
                  {
         
     | 
| 
       33 
32 
     | 
    
         
             
                    equal: @equal ? true : false,
         
     | 
| 
       34 
33 
     | 
    
         
             
                    parameter: @param,
         
     | 
| 
       35 
     | 
    
         
            -
                    message: @message 
     | 
| 
      
 34 
     | 
    
         
            +
                    message: @message
         
     | 
| 
       36 
35 
     | 
    
         
             
                  }
         
     | 
| 
       37 
36 
     | 
    
         
             
                end
         
     | 
| 
       38 
37 
     | 
    
         |