Building Frontend & Backend in One Rails App

May be you know it. Frontend and backend/administration. Two completely different looks, but one application. Two different sets of stylesheets and javascripts, but one set of models, validations etc.


Most of my apps have some kind of administration, which is separated from the normal users’ part. When I started with Rails, understanding assets was a challenge I was battling hard. But separating frontend and administration parts was even higher level for me!
The tricky part is in routes and setting up the assets in a right way.

Controllers

I like to keep things clear, so to keep those two parts separated I generate them into subfolders:

> rails g controller frontend/home index
> rails g controller admin/dashboard index

Files generated are as you expect:

/app/controllers/frontend/home_controller.rb
class Frontend::HomeController < ApplicationController
def index
end
end
/app/controllers/admin/dashboard_controller.rb
class Admin::DashboardController < ApplicationController
def index
end
end

But I want each of my controllers having a specific layout, of course. The easiest way to achieve this is to create a parent controllers, set them a layout (I will create those layouts later, don’t worry) and inherit from them (I don’t generate these parent controllers as I don’t want any tests and fixtures to be created, I just create new files manually):

/app/controllers/frontend_controller.rb
class FrontendController < ApplicationController
layout 'frontend/application'
end
/app/controllers/admin_controller.rb
class AdminController < ApplicationController
layout 'admin/application'
end

Now to inherit HomeController and DashboardController from those parents just update them as following:

/app/controllers/frontend/home_controller.rb
class Frontend::HomeController < FrontendController
def index
end
end
/app/controllers/admin/dashboard_controller.rb
class Admin::DashboardController < AdminController
def index
end
end

Routes

Routes seems to be easy, but there is one small hitch. I want my admin part to be running under the localhost:3000/admin folder, but the frontend should be running on the root:

/config/routes.rb
Rails.application.routes.draw do
  namespace :admin do
resource :dashboard, only: :index
root to: 'dashboard#index'
end
  scope module: 'frontend' do
resources :home, only: :index
root to: 'home#index'
end
end

At first I set the namespace for /admin part of the url by namespace :admin do . On the next row I set standard resource for dashboard, but constraint it just to index action. As the last for the admin I set root for the admin part, so /admin is mapped to /admin/dashboard/index .

As I have written above I don’t want the frontend to be mapped to any subfolder, so I’m telling to Rails I’m gonna using controller in a frontend module (remember Frontend::HomeController in the controller above?), but by scope module... I’m not mapping it to any subfolder in url.

The rest is the same as it was for the admin.

Assets

Now the core part — assets. Under the javascript and stylesheets assets folders there should be frontend and admin subfolders already created (they were created when I generated the controllers). If not, create them.
Let’s do same renaming and copying here now:

Move/Copy/app/assets/javascripts/application.js to:
 /app/assets/javascripts/frontend.js
/app/assets/javascripts/admin.js

And the same for stylesheets:
 /app/assets/stylesheets/application.css to:
 /app/assets/stylesheets/frontend.css
/app/assets/stylesheets/admin.css

In these files you import stylesheets and javascripts the same way you are used to, but use each of these files for importing of proper frontend/admin related files.

It should look now like this (among other files and folders, I’m showing here only the important files):

/app/assets/images
- admin
- frontend
/app/assets/javascripts
- admin
- frontent
- admin.js
- frontend.js
/app/assets/stylesheets
- admin
- frontend
- admin.css
- frontend.css

Rails must know about these new asset files to be able to compile them. Add this 4 lines to the end of assets config file:

/config/initializers/assets.rb
Rails.application.config.assets.precompile += %w( admin.css )
Rails.application.config.assets.precompile += %w( admin.js )
Rails.application.config.assets.precompile += %w( frontend.css )
Rails.application.config.assets.precompile += %w( frontend.js )

Layouts

And at the end I’m returning back to the start (as I promised in the controllers part) — I have to setup layouts. In /app/views/layouts I create two folders: frontend and admin . I copy application.html.erb to both of them (you can delete this file from its origin location). Now I must set stylesheets and javascript include tags in each layout to be pointing to the assets in the proper subfolder (remember the frontendand admin subfolders in /app/assets/images , /app/assets/javascripts and /app/assets/stylesheets ?):

/app/views/layouts/frontend/application.html.erb
# change the first parameter from 'application' to 'frontend':
<%= stylesheet_link_tag 'frontend', media: 'all', 'data-turbolinks-track': 'reload' %>
# same for javascripts:
<%= javascript_include_tag 'frontend', 'data-turbolinks-track': 'reload' %>
/app/views/layouts/admin/application.html.erb
# change the first parameter from 'application' to 'admin':
<%= stylesheet_link_tag 'admin', media: 'all', 'data-turbolinks-track': 'reload' %>
# same for javascripts:
<%= javascript_include_tag 'admin', 'data-turbolinks-track': 'reload' %>

Conclusion

And that’s it! Not that hard when you know what to do ;)

Questions?

Into comments, I will answer.


○ I’m still brand new with my CodeRocket. If you like what I’m doing, help me to get to a broader audience by clicking below. I will appreciate it!

And follow me to see what I’m working on! ○