Damian Galarza


AssetPath with ActionController::Metal

At QFive we’re building an API to serve our iOS application and throughout the site for ajax requests. Since our API only serves JSON we could slim down our controllers being used for the API to speed up requests as much as possible. In order to achieve this we’ve built a base controller for our API which inherits from ActionController::Metal instead of ActionController::Base. I was originally introduced to this idea in the book “Crafting Rails Applications” by Jose Valim.

One issue we’ve run into we’ve run into is related to the asset pipeline and serving assets from a custom asset host.

For example:

config/environments/production.rb

Example::Application.configure do
	config.action_controller.asset_host = "//static.example/com"
end

Typically the usage behind this in a rails application is masked, whenever you use image_tag the image will be routed to the asset host on its own behind the scenes. However since we’re inheriting from ActionController::Base there is some work to be done. We’ll need to include a couple of modules and ensure that the load hooks are loaded in our base controller, something that happens behind the scenes when inheriting from ActionController::Base.

class Api::V1::BaseController < ActionController::Metal
	include AbstractController::AssetPaths
	
	include ActionController::Redirecting
	include ActionController::Rendering
	include ActionController::Caching
	include ActionController::Renderers::All
	include ActionController::ConditionalGet
	include ActionController::ParamsWrapper
	include ActionController::MimeResponds
	
	ActiveSupport.run_load_hooks(:action_controller, self)
end

Of course, depending on what your application is using your mileage may vary. Our actual API BaseController looks something more like:

class Api::V1::BaseController < ActionController::Metal
	include AbstractController::AssetPaths
	include ActionController::Helpers

	include ActionController::Redirecting
	include ActionController::Rendering
	include ActionController::Caching
	include ActionController::Renderers::All
	include ActionController::ConditionalGet
	include ActionController::ParamsWrapper

	include ActionController::MimeResponds
	include ActionController::RequestForgeryProtection
	include AbstractController::Callbacks

	include ActionController::Instrumentation
	include ActionController::Rescue

	Rails.application.routes.default_url_options = ActionMailer::Base.default_url_options
	include Rails.application.routes.url_helpers

	append_view_path "#{Rails.root}/app/views"

	protect_from_forgery

	ActiveSupport.run_load_hooks(:action_controller, self)
end

Be sure to check out the rails ActionController::Base to see what else is included by default and tweak as you see fit.