AwesomeController was built to understand and simplify the concepts of ActionController and the functionality it provides. It started by taking a simple example Ruby on Rails app and removing the inheritance of ActionController from the app's controllers. From there, everything was built by following the trail of failures and referencing the real code of Action Controller to understand what it is doing.
In order to run the code in this repo, clone the repository and run bin/setup
. After a successful setup, you can use the tests to play with the code by dropping a binding.pry in the code you want to peruse and running the tests.
If you have any issues getting the code running, please open an issue with an example of your error.
The code for AwesomeController lives in /app/controllers/awesome_controller
, and the controllers inheriting from it live in /app/controllers/awesome
.
For each controller inheriting from AwesomeController, there is a corresponding controller for it inheriting from Action Controller, living in the top level directory of /app/controllers
or /app/controllers/api
.
app/controllers
├── awesome_controller # Where the AwesomeController code lives
│ ├── api.rb
│ ├── base.rb
│ ├── callbacks.rb
│ ├── flash.rb
│ ├── implicit_rendering.rb
│ ├── json_renderer.rb
│ ├── params.rb
│ ├── redirecting.rb
│ ├── rendering.rb
│ ├── super_base.rb
│ └── url_for.rb
├── awesome # Where the controllers inheriting from AwesomeController live
│ ├── api
│ │ └── posts_controller.rb
│ ├── application_controller.rb
│ └── posts_controller.rb
├── api
│ └── posts_controller.rb
├── application_controller.rb
└── posts_controller.rb
SuperBase - Source Code
Inspired By ActionController::Metal
SuperBase provides the very basic functionality of a controller like dispatching. Both AwesomeController::Base and AwesomeController::Api inherit from SuperBase and build upon its functionality to become more complex controller classes.
This is similar to the relationship ActionController::API and ActionController::Base to ActionController::Metal.
Api - Source Code
Inspired By ActionController::API
The AwesomeController::Api class provides a minimal implementation of ActionController::API. It's a controller that provides the ability to render JSON.
Base - Source Code
Inspired By ActionController::Base
The AwesomeController::Base class provides a minimal implementation of ActionController::Base. It's a controller that provides the ability to render HTML implicitly. In order to do so, it requires several more modules including Redirecting, UrlFor, and Flash.
Callbacks - Source Code
Inspired By AbstractController::Callbacks
Callbacks provide the functionality for methods like :before_action
, :around_action
, and :after_action
. It does so by taking advantage of the callback ActiveSupport::Callbacks API, as do the real AbstractController::Callbacks and the callbacks provided by Active Record through ActiveModel::Callbacks.
Params - Source Code
Inspired By ActionController::Parameters
Params provides a nice way of receiving parameters from the request, requiring params (and throwing an error when they don't exist), and permitting params (and filtering out the ones that aren't permitted).
Note: The implementation of Params in AwesomeController slightly differs from the code presented in the talk. This was for presentation's sake, and the differences are documented in the module.
ImplicitRendering - Source Code
Inspired By ActionController::BasicImplicitRender
ImplicitRendering provides a way to render without explicitly calling render
in your controller methods. It does so by checking to see if the controller has rendered, and if it has not, then it calls a default render
method, here provided by the Rendering module.
UrlFor - Source Code
Inspired By ActionController::UrlFor
UrlFor is a very simple module that extends the functionality of Rails Routing's UrlFor.
Redirecting - Source Code
Inspired By ActionController::Redirecting
Redirecting a request requires 3 things:
- A redirection status code (
3xx
) - A
Location
header set to the place we're redirecting to. - (This is Rails specific) We need to set the body. I'm not sure on the exact reason, but failing tests led me to think it's so we don't perform an implicit render; set the body so that it looks like it's rendered. Rails does this by setting the body to "You are being redirected."
Flash - Source Code
Inspired By ActionController::Flash
Flash provides a way to set flash messages on the request for redirect_to
and provides a notice
method for views to pull the flash information from the request. Very little code was needed here since the Flash implementation mostly lives on the request, provided by the Flash middleware.
Rendering - Source Code
Inspired By AbstractController::Rendering
Rendering provides a render
method that connects with the Rails Action View module to render html views. It does so by including the ActionView::Layouts module and defining methods that the Layouts module expects from the controller, providing details that Action View needs to render HTML, like where the views live for AwesomeController (/app/views
).
JsonRenderer - Source Code
Inspired By ActionController::Renderers
JsonRenderer is where the rendering specific to JSON was stored. In the talk, I wrote the JSON rendering functionality directly in render for the Api class, but in the code, I created an abstract method of rendering, allowing both the Api and Base classes to use the same render method.
The JsonRenderer module defines render_to_body
, one of the methods used in render
, to provide the JSON rendering functionality.