Rails has support for powerful application templates that allow you to get up and running with new projects quickly and reliably. One common requirement we face is to setup a project with both API and web pages. Here, we’ll discuss a template that we use to setup such a project.
Gems
We start by setting up the gems for our app. We use Devise for authentication, and devise-token-auth for API tokens. Rolify is used for user roles.
We’ll also setup Bootstrap and jQuery for the web.
Here’s the complete list of our starter gems,
1 2 3 4 5 6 7 8 9 10 11 12
gem_group :development, :test do gem 'factory_bot_rails' gem 'rspec-rails' end
// This file is automatically compiled by Webpack, along with any other files // present in this directory. You're encouraged to place your actual application logic in // a relevant structure within app/javascript and only use these pack files to reference // that code so it'll be compiled.
import JQuery from 'jquery'; window.$ = window.JQuery = JQuery;
import "bootstrap";
// Uncomment to copy all static images under ../images to the output folder and reference // them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>) // or the `imagePath` JavaScript helper below. // // const images = require.context('../images', true) // const imagePath = (name) => images(name, true)
And finally run webpacker:install
1 2 3 4 5
after_bundle do ... rails_command 'webpacker:install' ... end
Base Controllers
Now lets setup the base controllers for Web and API. For the web controller, we’ll use the authenticate_user! provided by devise
1 2 3 4
# app/controllers/web/base_controller.rb class Admin::BaseController < ApplicationController before_action :authenticate_user! end
and for the API controller, we’ll use the SetUserByToken provided by devise_token_auth
1 2 3 4 5
# app/controllers/api/v1/base_controller.rb class Api::V1::BaseController < ActionController::API include DeviseTokenAuth::Concerns::SetUserByToken include Pundit end
Sample Controllers
Now we can setup our sample controllers as below. In both of these, we can now access the currently logged in user as current_user
1 2 3 4 5
# app/controllers/web/dashboard_controller.rb class Web::DashboardController < ApplicationController def index end end
And for the API as
1 2 3 4 5 6
# app/controllers/api/v1/sample_controller.rb class Api::V1::SampleController < Api::V1::BaseController def index render json: { success: true, email: current_user.email }, status: :ok end end
Routes
The last thing to do is to setup the routes. We’ll setup separate namespaces for web and API.
# config/routes.rb Rails.application.routes.draw do authenticated :user do root to: 'web/dashboard#index', as: :authenticated_user_root end
root to: redirect('/users/sign_in')
devise_for :users
namespace :web do get 'dashboard/index' end
# API end points namespace :api do scope module: :v1 do mount_devise_token_auth_for 'User', at: 'auth' get 'sample/index' end end end
And with that, we have setup a project with user roles and authentication, with support for both web and API end points. Here’s a link to the complete template file.