Class: Grape::API

Inherits:
Object
  • Object
show all
Extended by:
Validations::ClassMethods
Defined in:
lib/grape/api.rb,
lib/grape/validations/coerce.rb

Overview

The API class is the primary entry point for creating Grape APIs.Users should subclass this class in order to build an API.

Constant Summary

Boolean =
Virtus::Attribute::Boolean

Class Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from Validations::ClassMethods

document_attribute, params, reset_validations!

Constructor Details

- (API) initialize

A new instance of API



467
468
469
470
471
472
473
474
# File 'lib/grape/api.rb', line 467

def initialize
  @route_set = Rack::Mount::RouteSet.new
  self.class.endpoints.each do |endpoint|
    endpoint.mount_in(@route_set)
  end
  add_head_not_allowed_methods
  @route_set.freeze
end

Class Attribute Details

+ (Object) endpoints (readonly)

Returns the value of attribute endpoints



14
15
16
# File 'lib/grape/api.rb', line 14

def endpoints
  @endpoints
end

+ (Object) instance (readonly)

Returns the value of attribute instance



16
17
18
# File 'lib/grape/api.rb', line 16

def instance
  @instance
end

+ (Object) logger(logger = nil)



18
19
20
21
22
23
24
# File 'lib/grape/api.rb', line 18

def logger(logger = nil)
  if logger
    @logger = logger
  else
    @logger ||= Logger.new($stdout)
  end
end

+ (Object) mountings (readonly)

Returns the value of attribute mountings



15
16
17
# File 'lib/grape/api.rb', line 15

def mountings
  @mountings
end

+ (Object) route_set (readonly)

Returns the value of attribute route_set



9
10
11
# File 'lib/grape/api.rb', line 9

def route_set
  @route_set
end

+ (Object) routes (readonly)

An array of API routes.



416
417
418
# File 'lib/grape/api.rb', line 416

def routes
  @routes
end

+ (Object) settings (readonly)

Returns the value of attribute settings



12
13
14
# File 'lib/grape/api.rb', line 12

def settings
  @settings
end

+ (Object) versions (readonly)

Returns the value of attribute versions



10
11
12
# File 'lib/grape/api.rb', line 10

def versions
  @versions
end

Class Method Details

+ (Object) after(&block)



347
348
349
# File 'lib/grape/api.rb', line 347

def after(&block)
  imbue(:afters, [block])
end

+ (Object) after_validation(&block)



343
344
345
# File 'lib/grape/api.rb', line 343

def after_validation(&block)
  imbue(:after_validations, [block])
end

+ (Object) auth(type = nil, options = {}, &block)

Add an authentication type to the API. Currently only :http_basic, :http_digest and :oauth2 are supported.



275
276
277
278
279
280
281
# File 'lib/grape/api.rb', line 275

def auth(type = nil, options = {}, &block)
  if type
    set(:auth, {:type => type.to_sym, :proc => block}.merge(options))
  else
    settings[:auth]
  end
end

+ (Object) before(&block)



339
340
341
# File 'lib/grape/api.rb', line 339

def before(&block)
  imbue(:befores, [block])
end

+ (Object) call(env)



43
44
45
46
# File 'lib/grape/api.rb', line 43

def call(env)
  compile unless instance
  call!(env)
end

+ (Object) call!(env)



48
49
50
# File 'lib/grape/api.rb', line 48

def call!(env)
  instance.call(env)
end

+ (Object) cascade(value = nil)



424
425
426
427
428
# File 'lib/grape/api.rb', line 424

def cascade(value = nil)
  value.nil? ? 
    (settings.has_key?(:cascade) ? !! settings[:cascade] : true) :
    set(:cascade, value)
end

+ (Object) change!



39
40
41
# File 'lib/grape/api.rb', line 39

def change!
  @instance = nil
end

+ (Object) compile



35
36
37
# File 'lib/grape/api.rb', line 35

def compile
  @instance = self.new
end

+ (Object) content_type(key, val)

Specify additional content-types, e.g.: content_type :xls, 'application/vnd.ms-excel'



167
168
169
# File 'lib/grape/api.rb', line 167

def content_type(key, val)
  settings.imbue(:content_types, key.to_sym => val)
end

+ (Object) content_types

All available content types.



172
173
174
# File 'lib/grape/api.rb', line 172

def content_types
  Grape::ContentTypes.content_types_for(settings[:content_types])
end

+ (Object) default_error_formatter(new_formatter = nil)

Specify a default error formatter.



157
158
159
# File 'lib/grape/api.rb', line 157

def default_error_formatter(new_formatter = nil)
  new_formatter ? set(:default_error_formatter, new_formatter) : settings[:default_error_formatter]
end

+ (Object) default_error_status(new_status = nil)

Specify the default status code for errors.



177
178
179
# File 'lib/grape/api.rb', line 177

def default_error_status(new_status = nil)
  new_status ? set(:default_error_status, new_status) : settings[:default_error_status]
end

+ (Object) default_format(new_format = nil)

Specify the default format for the API's serializers. May be :json or :txt (default).



126
127
128
# File 'lib/grape/api.rb', line 126

def default_format(new_format = nil)
  new_format ? set(:default_format, new_format.to_sym) : settings[:default_format]
end

+ (Object) delete(paths = ['/'], options = {}, &block)



355
# File 'lib/grape/api.rb', line 355

def delete(paths = ['/'], options = {}, &block); route('DELETE', paths, options, &block) end

+ (Object) desc(description, options = {})

Add a description to the next namespace or function.



120
121
122
# File 'lib/grape/api.rb', line 120

def desc(description, options = {})
  @last_description = options.merge(:description => description)
end

+ (Object) do_not_route_head!

Do not route HEAD requests to GET requests automatically



75
76
77
# File 'lib/grape/api.rb', line 75

def do_not_route_head!
  set(:do_not_route_head, true)
end

+ (Object) do_not_route_options!

Do not automatically route OPTIONS



80
81
82
# File 'lib/grape/api.rb', line 80

def do_not_route_options!
  set(:do_not_route_options, true)
end

+ (Object) error_formatter(format, new_formatter)



161
162
163
# File 'lib/grape/api.rb', line 161

def error_formatter(format, new_formatter)
  settings.imbue(:error_formatters, format.to_sym => new_formatter)
end

+ (Object) format(new_format = nil)

Specify the format for the API's serializers. May be :json, :xml, :txt, etc.



132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/grape/api.rb', line 132

def format(new_format = nil)
  if new_format
    set(:format, new_format.to_sym)
    # define the default error formatters
    set(:default_error_formatter, Grape::ErrorFormatter::Base.formatter_for(new_format, {}))
    # define a single mime type
    mime_type = content_types[new_format.to_sym]
    raise Grape::Exceptions::MissingMimeType.new(new_format) unless mime_type
    settings.imbue(:content_types, new_format.to_sym => mime_type)
  else
    settings[:format]
  end
end

+ (Object) formatter(content_type, new_formatter)

Specify a custom formatter for a content-type.



147
148
149
# File 'lib/grape/api.rb', line 147

def formatter(content_type, new_formatter)
  settings.imbue(:formatters, content_type.to_sym => new_formatter)
end

+ (Object) get(paths = ['/'], options = {}, &block)



351
# File 'lib/grape/api.rb', line 351

def get(paths = ['/'], options = {}, &block); route('GET', paths, options, &block) end

+ (Object) head(paths = ['/'], options = {}, &block)



354
# File 'lib/grape/api.rb', line 354

def head(paths = ['/'], options = {}, &block); route('HEAD', paths, options, &block) end

+ (Object) helpers(new_mod = nil, &block)

Add helper methods that will be accessible from any endpoint within this namespace (and child namespaces).

When called without a block, all known helpers within this scope are included.

Examples:

Define some helpers.


class ExampleAPI < Grape::API
  helpers do
    def current_user
      User.find_by_id(params[:token])
    end
  end
end

Parameters:

  • new_mod (Module) (defaults to: nil)

    optional module of methods to include

  • block (Block)

    optional block of methods to include



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/grape/api.rb', line 253

def helpers(new_mod = nil, &block)
  if block_given? || new_mod
    mod = settings.peek[:helpers] || Module.new
    if new_mod
      mod.class_eval do
        include new_mod
      end
    end
    mod.class_eval &block if block_given?
    set(:helpers, mod)
  else
    mod = Module.new
    settings.stack.each do |s|
      mod.send :include, s[:helpers] if s[:helpers]
    end
    change!
    mod
  end
end

+ (Object) http_basic(options = {}, &block)

Add HTTP Basic authorization to the API.

Parameters:

  • options (Hash) (defaults to: {})

    A hash of options.

Options Hash (options):

  • :realm (String)

    "API Authorization" The HTTP Basic realm.



287
288
289
290
# File 'lib/grape/api.rb', line 287

def http_basic(options = {}, &block)
  options[:realm] ||= "API Authorization"
  auth :http_basic, options, &block
end

+ (Object) http_digest(options = {}, &block)



292
293
294
295
296
# File 'lib/grape/api.rb', line 292

def http_digest(options = {}, &block)
  options[:realm] ||= "API Authorization"
  options[:opaque] ||= "secret"
  auth :http_digest, options, &block
end

+ (Object) imbue(key, value)

Add to a configuration value for this namespace.

Parameters:

  • key (Symbol)

    The key of the configuration variable.

  • value (Object)

    The value to which to set the configuration variable.



65
66
67
# File 'lib/grape/api.rb', line 65

def imbue(key, value)
  settings.imbue(key, value)
end

+ (Object) middleware

Retrieve an array of the middleware classes and arguments that are currently applied to the application.



411
412
413
# File 'lib/grape/api.rb', line 411

def middleware
  settings.stack.inject([]){|a,s| a += s[:middleware] if s[:middleware]; a}
end

+ (Object) mount(mounts)



298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/grape/api.rb', line 298

def mount(mounts)
  mounts = { mounts => '/' } unless mounts.respond_to?(:each_pair)
  mounts.each_pair do |app, path|
    if app.respond_to?(:inherit_settings, true)
      app_settings = settings.clone
      mount_path = Rack::Mount::Utils.normalize_path([ settings[:mount_path], path ].compact.join("/"))
      app_settings.set :mount_path, mount_path
      app.inherit_settings(app_settings)
    end
    endpoints << Grape::Endpoint.new(settings.clone, {
      :method => :any,
      :path => path,
      :app => app
    })
  end
end

+ (Object) namespace(space = nil, options = {}, &block) Also known as: group, resource, resources, segment



359
360
361
362
363
364
365
366
367
368
369
370
371
# File 'lib/grape/api.rb', line 359

def namespace(space = nil, options = {},  &block)
  if space || block_given?
    previous_namespace_description = @namespace_description
    @namespace_description = (@namespace_description || {}).deep_merge(@last_description || {})
    @last_description = nil
    nest(block) do
      set(:namespace, Namespace.new(space, options)) if space
    end
    @namespace_description = previous_namespace_description
  else
    Namespace.joined_space_path(settings)
  end
end

+ (Object) options(paths = ['/'], options = {}, &block)



356
# File 'lib/grape/api.rb', line 356

def options(paths = ['/'], options = {}, &block); route('OPTIONS', paths, options, &block) end

+ (Object) parser(content_type, new_parser)

Specify a custom parser for a content-type.



152
153
154
# File 'lib/grape/api.rb', line 152

def parser(content_type, new_parser)
  settings.imbue(:parsers, content_type.to_sym => new_parser)
end

+ (Object) patch(paths = ['/'], options = {}, &block)



357
# File 'lib/grape/api.rb', line 357

def patch(paths = ['/'], options = {}, &block); route('PATCH', paths, options, &block) end

+ (Object) post(paths = ['/'], options = {}, &block)



352
# File 'lib/grape/api.rb', line 352

def post(paths = ['/'], options = {}, &block); route('POST', paths, options, &block) end

+ (Object) prefix(prefix = nil)

Define a root URL prefix for your entire API.



70
71
72
# File 'lib/grape/api.rb', line 70

def prefix(prefix = nil)
  prefix ? set(:root_prefix, prefix) : settings[:root_prefix]
end

+ (Object) put(paths = ['/'], options = {}, &block)



353
# File 'lib/grape/api.rb', line 353

def put(paths = ['/'], options = {}, &block); route('PUT', paths, options, &block) end

+ (Object) represent(model_class, options)

Allows you to specify a default representation entity for a class. This allows you to map your models to their respective entities once and then simply call present with the model.

Note that Grape will automatically go up the class ancestry to try to find a representing entity, so if you, for example, define an entity to represent Object then all presented objects will bubble up and utilize the entity provided on that represent call.

Examples:

class ExampleAPI < Grape::API
  represent User, :with => Entity::User

  get '/me' do
    present current_user # :with => Entity::User is assumed
  end
end

Parameters:

  • model_class (Class)

    The model class that will be represented.

  • options (Hash)

    a customizable set of options

Options Hash (options):

  • :with (Class)

    The entity class that will represent the model.

Raises:



229
230
231
232
# File 'lib/grape/api.rb', line 229

def represent(model_class, options)
  raise Grape::Exceptions::InvalidWithOptionForRepresent.new unless options[:with] && options[:with].is_a?(Class)
  imbue(:representations, model_class => options[:with])
end

+ (Object) rescue_from(*exception_classes, options = {})

Allows you to rescue certain exceptions that occur to return a grape error rather than raising all the way to the server level.

Examples:

Rescue from custom exceptions

class ExampleAPI < Grape::API
  class CustomError < StandardError; end

  rescue_from CustomError
end

Parameters:

  • exception_classes (Array)

    A list of classes that you want to rescue, or the symbol :all to rescue from all exceptions.

  • block (Block)

    Execution block to handle the given exception.

  • options (Hash) (defaults to: {})

    Options for the rescue usage.

Options Hash (options):

  • :backtrace (Boolean)

    Include a backtrace in the rescue response.



198
199
200
201
202
203
204
205
206
207
# File 'lib/grape/api.rb', line 198

def rescue_from(*args, &block)
  if block_given?
    args.each do |arg|
      imbue(:rescue_handlers, { arg => block })
    end
  end
  imbue(:rescue_options, args.pop) if args.last.is_a?(Hash)
  set(:rescue_all, true) and return if args.include?(:all)
  imbue(:rescued_errors, args)
end

+ (Object) reset!



26
27
28
29
30
31
32
33
# File 'lib/grape/api.rb', line 26

def reset!
  @settings  = Grape::Util::HashStack.new
  @route_set = Rack::Mount::RouteSet.new
  @endpoints = []
  @mountings = []
  @routes = nil
  reset_validations!
end

+ (Object) route(methods, paths = ['/'], route_options = {}, &block)

Defines a route that will be recognized by the Grape API.

Examples:

Defining a basic route.

class MyAPI < Grape::API
  route(:any, '/hello') do
    {:hello => 'world'}
  end
end

Parameters:

  • methods (HTTP Verb)

    One or more HTTP verbs that are accepted by this route. Set to :any if you want any verb to be accepted.

  • paths (String) (defaults to: ['/'])

    One or more strings representing the URL segment(s) for this route.



327
328
329
330
331
332
333
334
335
336
337
# File 'lib/grape/api.rb', line 327

def route(methods, paths = ['/'], route_options = {}, &block)
  endpoint_options = {
    :method => methods,
    :path => paths,
    :route_options => (@namespace_description || {}).deep_merge(@last_description || {}).deep_merge(route_options || {})
  }
  endpoints << Grape::Endpoint.new(settings.clone, endpoint_options, &block)

  @last_description = nil
  reset_validations!
end

+ (Object) route_param(param, options = {}, &block)

Thie method allows you to quickly define a parameter route segment in your API.

Parameters:

  • param (Symbol)

    The name of the parameter you wish to declare.

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • You (Regexp)

    may supply a regular expression that the declared parameter must meet.



378
379
380
381
382
# File 'lib/grape/api.rb', line 378

def route_param(param, options = {}, &block)
  options = options.dup
  options[:requirements] = { param.to_sym => options[:requirements] } if options[:requirements].is_a?(Regexp)
  namespace(":#{param}", options, &block)
end

+ (Object) scope(name = nil, &block)

Create a scope without affecting the URL.

Parameters:

  • name (Symbol) (defaults to: nil)

    Purely placebo, just allows to to name the scope to make the code more readable.



392
393
394
# File 'lib/grape/api.rb', line 392

def scope(name = nil, &block)
  nest(block)
end

+ (Object) set(key, value)

Set a configuration value for this namespace.

Parameters:

  • key (Symbol)

    The key of the configuration variable.

  • value (Object)

    The value to which to set the configuration variable.



56
57
58
# File 'lib/grape/api.rb', line 56

def set(key, value)
  settings[key.to_sym] = value
end

+ (Object) use(middleware_class, *args, &block)

Apply a custom middleware to the API. Applies to the current namespace and any children, but not parents.

Parameters:

  • middleware_class (Class)

    The class of the middleware you'd like to inject.



402
403
404
405
406
# File 'lib/grape/api.rb', line 402

def use(middleware_class, *args, &block)
  arr = [middleware_class, *args]
  arr << block if block_given?
  imbue(:middleware, [arr])
end

+ (Object) version(*args, &block)

Specify an API version.

Examples:

API with legacy support.

class MyAPI < Grape::API
  version 'v2'

  get '/main' do
    {:some => 'data'}
  end

  version 'v1' do
    get '/main' do
      {:legacy => 'data'}
    end
  end
end


101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/grape/api.rb', line 101

def version(*args, &block)
  if args.any?
    options = args.pop if args.last.is_a? Hash
    options ||= {}
    options = {:using => :path}.merge!(options)

    raise Grape::Exceptions::MissingVendorOption.new if options[:using] == :header && !options.has_key?(:vendor)

    @versions = versions | args
    nest(block) do
      set(:version, args)
      set(:version_options, options)
    end
  end

  @versions.last unless @versions.nil?
end

Instance Method Details

- (Object) call(env)



476
477
478
479
480
# File 'lib/grape/api.rb', line 476

def call(env)
  status, headers, body = @route_set.call(env)
  headers.delete('X-Cascade') unless cascade?
  [ status, headers, body ]
end

- (Boolean) cascade?

Some requests may return a HTTP 404 error if grape cannot find a matching route. In this case, Rack::Mount adds a X-Cascade header to the response and sets it to 'pass', indicating to grape's parents they should keep looking for a matching route on other resources.

In some applications (e.g. mounting grape on rails), one might need to trap errors from reaching upstream. This is effectivelly done by unsetting X-Cascade. Default :cascade is true.

Returns:



490
491
492
493
494
# File 'lib/grape/api.rb', line 490

def cascade?
  return !! self.class.settings[:cascade] if self.class.settings.has_key?(:cascade)
  return !! self.class.settings[:version_options][:cascade] if self.class.settings[:version_options] && self.class.settings[:version_options].has_key?(:cascade)
  true
end