actionpack/lib/action_controller/api.rb
# frozen_string_literal: true
# :markup: markdown
require "action_view"
require "action_controller"
require "action_controller/log_subscriber"
module ActionController
# # Action Controller API
#
# API Controller is a lightweight version of ActionController::Base, created for
# applications that don't require all functionalities that a complete Rails
# controller provides, allowing you to create controllers with just the features
# that you need for API only applications.
#
# An API Controller is different from a normal controller in the sense that by
# default it doesn't include a number of features that are usually required by
# browser access only: layouts and templates rendering, flash, assets, and so
# on. This makes the entire controller stack thinner, suitable for API
# applications. It doesn't mean you won't have such features if you need them:
# they're all available for you to include in your application, they're just not
# part of the default API controller stack.
#
# Normally, `ApplicationController` is the only controller that inherits from
# `ActionController::API`. All other controllers in turn inherit from
# `ApplicationController`.
#
# A sample controller could look like this:
#
# class PostsController < ApplicationController
# def index
# posts = Post.all
# render json: posts
# end
# end
#
# Request, response, and parameters objects all work the exact same way as
# ActionController::Base.
#
# ## Renders
#
# The default API Controller stack includes all renderers, which means you can
# use `render :json` and siblings freely in your controllers. Keep in mind that
# templates are not going to be rendered, so you need to ensure your controller
# is calling either `render` or `redirect_to` in all actions, otherwise it will
# return `204 No Content`.
#
# def show
# post = Post.find(params[:id])
# render json: post
# end
#
# ## Redirects
#
# Redirects are used to move from one action to another. You can use the
# `redirect_to` method in your controllers in the same way as in
# ActionController::Base. For example:
#
# def create
# redirect_to root_url and return if not_authorized?
# # do stuff here
# end
#
# ## Adding New Behavior
#
# In some scenarios you may want to add back some functionality provided by
# ActionController::Base that is not present by default in
# `ActionController::API`, for instance `MimeResponds`. This module gives you
# the `respond_to` method. Adding it is quite simple, you just need to include
# the module in a specific controller or in `ApplicationController` in case you
# want it available in your entire application:
#
# class ApplicationController < ActionController::API
# include ActionController::MimeResponds
# end
#
# class PostsController < ApplicationController
# def index
# posts = Post.all
#
# respond_to do |format|
# format.json { render json: posts }
# format.xml { render xml: posts }
# end
# end
# end
#
# Make sure to check the modules included in ActionController::Base if you want
# to use any other functionality that is not provided by `ActionController::API`
# out of the box.
class API < Metal
abstract!
# Shortcut helper that returns all the ActionController::API modules except the
# ones passed as arguments:
#
# class MyAPIBaseController < ActionController::Metal
# ActionController::API.without_modules(:UrlFor).each do |left|
# include left
# end
# end
#
# This gives better control over what you want to exclude and makes it easier to
# create an API controller class, instead of listing the modules required
# manually.
def self.without_modules(*modules)
modules = modules.map do |m|
m.is_a?(Symbol) ? ActionController.const_get(m) : m
end
MODULES - modules
end
MODULES = [
AbstractController::Rendering,
UrlFor,
Redirecting,
ApiRendering,
Renderers::All,
ConditionalGet,
BasicImplicitRender,
StrongParameters,
RateLimiting,
DataStreaming,
DefaultHeaders,
Logging,
# Before callbacks should also be executed as early as possible, so also include
# them at the bottom.
AbstractController::Callbacks,
# Append rescue at the bottom to wrap as much as possible.
Rescue,
# Add instrumentations hooks at the bottom, to ensure they instrument all the
# methods properly.
Instrumentation,
# Params wrapper should come before instrumentation so they are properly showed
# in logs
ParamsWrapper
]
MODULES.each do |mod|
include mod
end
ActiveSupport.run_load_hooks(:action_controller_api, self)
ActiveSupport.run_load_hooks(:action_controller, self)
end
end