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 collapse

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

#initializeAPI

Returns a new instance of API.



445
446
447
448
449
450
451
452
# File 'lib/grape/api.rb', line 445

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

.endpointsObject (readonly)

Returns the value of attribute endpoints.



21
22
23
# File 'lib/grape/api.rb', line 21

def endpoints
  @endpoints
end

.instanceObject (readonly)

Returns the value of attribute instance.



23
24
25
# File 'lib/grape/api.rb', line 23

def instance
  @instance
end

.logger(logger = nil) ⇒ Object



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

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

.mountingsObject (readonly)

Returns the value of attribute mountings.



22
23
24
# File 'lib/grape/api.rb', line 22

def mountings
  @mountings
end

.route_setObject (readonly)

Returns the value of attribute route_set.



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

def route_set
  @route_set
end

.routesObject (readonly)

An array of API routes.



400
401
402
# File 'lib/grape/api.rb', line 400

def routes
  @routes
end

.settingsObject (readonly)

Returns the value of attribute settings.



19
20
21
# File 'lib/grape/api.rb', line 19

def settings
  @settings
end

.versionsObject (readonly)

Returns the value of attribute versions.



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

def versions
  @versions
end

Class Method Details

.after(&block) ⇒ Object



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

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

.after_validation(&block) ⇒ Object



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

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

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

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



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

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

.before(&block) ⇒ Object



334
335
336
# File 'lib/grape/api.rb', line 334

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

.call(env) ⇒ Object



50
51
52
53
# File 'lib/grape/api.rb', line 50

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

.call!(env) ⇒ Object



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

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

.change!Object



46
47
48
# File 'lib/grape/api.rb', line 46

def change!
  @instance = nil
end

.compileObject



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

def compile
  @instance = self.new
end

.content_type(key, val) ⇒ Object

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



165
166
167
# File 'lib/grape/api.rb', line 165

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

.content_typesObject

All available content types.



170
171
172
# File 'lib/grape/api.rb', line 170

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

.default_error_formatter(new_formatter = nil) ⇒ Object

Specify a default error formatter.



155
156
157
# File 'lib/grape/api.rb', line 155

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

.default_error_status(new_status = nil) ⇒ Object

Specify the default status code for errors.



175
176
177
# File 'lib/grape/api.rb', line 175

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

.default_format(new_format = nil) ⇒ Object

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



124
125
126
# File 'lib/grape/api.rb', line 124

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

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



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

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

.desc(description, options = {}) ⇒ Object

Add a description to the next namespace or function.



118
119
120
# File 'lib/grape/api.rb', line 118

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

.error_formatter(format, new_formatter) ⇒ Object



159
160
161
# File 'lib/grape/api.rb', line 159

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

.format(new_format = nil) ⇒ Object

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



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

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 "missing mime type for #{new_format}" unless mime_type
    settings.imbue(:content_types, new_format.to_sym => mime_type)
  else
    settings[:format]
  end
end

.formatter(content_type, new_formatter) ⇒ Object

Specify a custom formatter for a content-type.



145
146
147
# File 'lib/grape/api.rb', line 145

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

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



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

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

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



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

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

.helpers(new_mod = nil, &block) ⇒ Object

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



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

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

.http_basic(options = {}, &block) ⇒ Object

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.



285
286
287
288
# File 'lib/grape/api.rb', line 285

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

.http_digest(options = {}, &block) ⇒ Object



290
291
292
293
294
# File 'lib/grape/api.rb', line 290

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

.imbue(key, value) ⇒ Object

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.



72
73
74
# File 'lib/grape/api.rb', line 72

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

.middlewareObject

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



395
396
397
# File 'lib/grape/api.rb', line 395

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

.mount(mounts) ⇒ Object



296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/grape/api.rb', line 296

def mount(mounts)
  mounts = {mounts => '/'} unless mounts.respond_to?(:each_pair)
  mounts.each_pair do |app, path|
    if app.respond_to?(:inherit_settings)
      app.inherit_settings(settings.clone)
    end
    endpoints << Grape::Endpoint.new(settings.clone,
      :method => :any,
      :path => path,
      :app => app
    )
  end
end

.namespace(space = nil, &block) ⇒ Object Also known as: group, resource, resources, segment



354
355
356
357
358
359
360
361
362
363
364
365
366
# File 'lib/grape/api.rb', line 354

def namespace(space = nil, &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, space.to_s) if space
    end
    @namespace_description = previous_namespace_description
  else
    Rack::Mount::Utils.normalize_path(settings.stack.map{|s| s[:namespace]}.join('/'))
  end
end

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



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

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

.parser(content_type, new_parser) ⇒ Object

Specify a custom parser for a content-type.



150
151
152
# File 'lib/grape/api.rb', line 150

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

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



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

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

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



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

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

.prefix(prefix = nil) ⇒ Object

Define a root URL prefix for your entire API.



78
79
80
# File 'lib/grape/api.rb', line 78

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

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



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

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

.represent(model_class, options) ⇒ Object

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:

  • (ArgumentError)


227
228
229
230
# File 'lib/grape/api.rb', line 227

def represent(model_class, options)
  raise ArgumentError, "You must specify an entity class in the :with option." unless options[:with] && options[:with].is_a?(Class)
  imbue(:representations, model_class => options[:with])
end

.rescue_from(*exception_classes, options = {}) ⇒ Object

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.



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

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

.reset!Object



33
34
35
36
37
38
39
40
# File 'lib/grape/api.rb', line 33

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

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

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.



322
323
324
325
326
327
328
329
330
331
332
# File 'lib/grape/api.rb', line 322

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

.scope(name = nil, &block) ⇒ Object

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.



376
377
378
# File 'lib/grape/api.rb', line 376

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

.set(key, value) ⇒ Object

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.



63
64
65
# File 'lib/grape/api.rb', line 63

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

.use(middleware_class, *args, &block) ⇒ Object

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.



386
387
388
389
390
# File 'lib/grape/api.rb', line 386

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

.version(*args, &block) ⇒ Object

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


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

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

    raise ArgumentError, "Must specify :vendor option." 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

#call(env) ⇒ Object



454
455
456
# File 'lib/grape/api.rb', line 454

def call(env)
  @route_set.call(env)
end