1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/actionpack/lib/action_controller/api.rb

150 lines
4.9 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
require "action_view"
require "action_controller"
require "action_controller/log_subscriber"
2015-04-15 14:30:27 -04:00
module ActionController
# API Controller is a lightweight version of <tt>ActionController::Base</tt>,
2015-06-15 07:27:38 -04:00
# 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.
2015-04-15 14:30:27 -04:00
#
# 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, cookies, sessions,
# 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
2015-04-15 14:30:27 -04:00
# 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.
2015-04-15 14:30:27 -04:00
#
# Normally, +ApplicationController+ is the only controller that inherits from
# <tt>ActionController::API</tt>. All other controllers in turn inherit from
# +ApplicationController+.
2015-04-15 14:30:27 -04:00
#
# A sample controller could look like this:
#
# class PostsController < ApplicationController
# def index
# posts = Post.all
# render json: posts
2015-04-15 14:30:27 -04:00
# end
# end
#
# Request, response, and parameters objects all work the exact same way as
2015-04-15 14:30:27 -04:00
# <tt>ActionController::Base</tt>.
#
# == Renders
#
# The default API Controller stack includes all renderers, which means you
# can use <tt>render :json</tt> and brothers 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 <tt>render</tt> or <tt>redirect_to</tt> in
# all actions, otherwise it will return 204 No Content.
2015-04-15 14:30:27 -04:00
#
# def show
# post = Post.find(params[:id])
# render json: post
2015-04-15 14:30:27 -04:00
# end
#
# == Redirects
#
# Redirects are used to move from one action to another. You can use the
# <tt>redirect_to</tt> method in your controllers in the same way as in
2015-04-15 14:30:27 -04:00
# <tt>ActionController::Base</tt>. For example:
#
# def create
# redirect_to root_url and return if not_authorized?
# # do stuff here
# end
#
# == Adding New Behavior
2015-04-15 14:30:27 -04:00
#
# In some scenarios you may want to add back some functionality provided by
# <tt>ActionController::Base</tt> that is not present by default in
# <tt>ActionController::API</tt>, for instance <tt>MimeResponds</tt>. This
2015-06-15 07:27:38 -04:00
# module gives you the <tt>respond_to</tt> 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:
2015-04-15 14:30:27 -04:00
#
# 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
2015-04-15 14:30:27 -04:00
# end
# end
#
# Make sure to check the modules included in <tt>ActionController::Base</tt>
# if you want to use any other functionality that is not provided
# by <tt>ActionController::API</tt> out of the box.
2015-04-15 14:30:27 -04:00
class API < Metal
abstract!
2015-06-15 07:27:38 -04:00
# Shortcut helper that returns all the ActionController::API modules except
# the ones passed as arguments:
2015-04-15 14:30:27 -04:00
#
# class MyAPIBaseController < ActionController::Metal
2015-06-15 07:27:38 -04:00
# ActionController::API.without_modules(:ForceSSL, :UrlFor).each do |left|
2015-04-15 14:30:27 -04:00
# include left
# end
# end
#
# This gives better control over what you want to exclude and makes it easier
2015-06-15 07:27:38 -04:00
# to create an API controller class, instead of listing the modules required
# manually.
2015-04-15 14:30:27 -04:00
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,
2015-04-15 14:30:27 -04:00
Renderers::All,
ConditionalGet,
BasicImplicitRender,
2015-04-15 14:30:27 -04:00
StrongParameters,
ForceSSL,
DataStreaming,
2015-06-15 07:27:38 -04:00
# Before callbacks should also be executed as early as possible, so
2015-04-15 14:30:27 -04:00
# 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
2015-04-15 14:30:27 -04:00
]
MODULES.each do |mod|
include mod
end
ActiveSupport.run_load_hooks(:action_controller_api, self)
2015-04-15 14:30:27 -04:00
ActiveSupport.run_load_hooks(:action_controller, self)
end
end