How to Architect Rails Project - Part 1
Tags: rails, tutorial, ruby, architecture
Published: 2019-12-04 16:31:57

When I started to build web applications with ruby on rails, I had a lot of questions that I figured out through the years of using the framework. Now in this article, I’m going to share the base structure to start building a web application.

Depending on the requirements our structure could slightly change, in this scenario, I’m going to build a simple **portfolio app** with a blog of articles.


Before start building our project, let’s imagine two layers one to administrate the site and the other for public access (front pages). Here is how it should look.

![Modules](https://miro.medium.com/max/1060/1*rW0W8dEaRtJzuXRz3RCszA.jpeg)

**Admin (Dashboard):**
Only admin users have access and permissions to post articles, add portfolio jobs, see reports, etc.
There are many ways to build modules, for example using ActiveAdmin gem we can crate the admin module, another way is creating engines, but we are going to set up our dashboard module from scratch.

**Surface (front pages):**
In this module, we’ll put all the public pages like home, about, portfolio, blog, and contact.
Once we have clear this concept, let’s kick-off creating or project…

```bash
rails new portfolio -d postgresql -T
```

> *-T = skip testing modules. We’ll focus on test and design in other article*

Move under the Portfolio directory and run the following commands to create the database and migrations…

```bash
rails db:create
rails db:migrate
```

Until here, we have a clean project with no custom pages or modules. So, let’s start creating our project architecture.
First, under controllers create 2 folders called (admins, surface). Our tree would look like this.

```
app/controllers
  ├── admins
  └── surface
  └── application_controller.rb
```

Create these controllers under admins and surface folders `base_controller.rb`, `blogs_controller.rb`, `works_controller.rb` and `pages_controller.rb`

```
app/controllers
  ├── admins # Portfolio blog and work management
  │   └── base_controller.rb
  |   └── blogs_controller.rb
  |   └── works_controller.rb
  └── surface # Public pages
  │   └── pages_controller.rb
  └── application.rb
```

Let’s add some code to our admin controllers…

```ruby
# admins/base_controller.rb
class Admins::BaseController < ApplicationController
  # Define what users can access to this module
  # Define what view layout to use 
end
```

```
#admins/works_controller.rb
# here we are extending from our Admins::BaseControler
class Admins::WorksController < Admins::BaseController
end
```

```ruby
# admins/blogs_controllers
# Inherits from Admins::BaseController
class Admins::BlogsController < Admins::BaseController
end
```

Let’s add some code to our surface controller…

```ruby
# surface/pages_controller.rb
class Surface::PagesController < ApplicationController
  #define our pages
  def home
  end
  
  def about
  end
  def work
  end
  
  def blog
  end
  
  def contact
  end
end
```

Next, we are going to add some routes to our app un `config/routes.rb`.

```ruby
Rails.application.draw do
  # Define our root page
  root to: 'surface/pages#home'
  
  # Frontend pages
  
  # scope module 'surface' to get this format url `domain.com/about, domain.com/work...` 
  # and not `domain.com/surface/about...`
  scope module: 'surface' do
    get '/about', to: 'pages#about', as: 'surface_about'
    get '/work', to: 'pages#work', as: 'surface_work'
    get '/blog', to: 'pages#blog', as: 'surface_blog'
    get '/contact', to: 'pages#contact', as: 'surface_contact'
  end
end
```

> *These routes also can be isolated in files, we’ll isolate these routes in the next article.*

Now, we should create our views according to our modules, let’s focus first in our Surface module, so let’s create the following folders and views.

```
app/views
  ├── surface/pages # Write in each file <h1>Page Name</h1> 
  │   └── home.html.erb     # I.e <h1>Home</h1>
  │   └── about.html.erb    # I.e <h1>About</h1>
  |   └── work.html.erb     # I.e <h1>Work</h1>
  |   └── blog.html.erb     # I.e <h1>Blog</h1>
  |   └── contact.html.erb  # I.e <h1>Contact</h1>
  └── partials   
  │   └── _header.html.erb
  |   └── _footer.html.erb
  └── layouts 
  |   └── application.html.erb
```

Now let’s edit `application.html.erb` under the layout folder and add the header and footer partials.

> *Partials are the components that will be used across the site.*

Let’s add some Html links to our `_header.html.erb` under the partials folder...

```erb
<header>
  <h1>Logo</h1>
  <nav>
    <ul>
      <li><%= link_to 'Home', root_path %></li>
      <li><%= link_to 'About', surface_about_path %></li>
      <li><%= link_to 'Work', surface_work_path %></li>
      <li><%= link_to 'Blog', surface_blog_path %></li>
      <li><%= link_to 'Contact', surface_contact_path %></li>
    </ul>
  </nav>
</header>
```

Next, add the header partial to our layout `applicaton.html.erb`

```erb
<!DOCTYPE html>
<html>
  <head>
    <title>Portfolio</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>
  <body>
    <%= render "partials/header" %>
    <%= yield %>
  </body>
</html>
```

Alright! we have our surface module working perfectly 💯 if you go tho `http://localhost:3000` you will be able to navigate between the pages.

![demo](https://miro.medium.com/max/600/1*XtKeK23_ESvngy7PnCmX4g.gif)


If you got any error through this setup, feel free to drop me a line dev.renzo.diaz@gmail.com I’ll try to answer all your doubts asap.

In the next [Part 2](https://dev.to/renzodiaz/how-to-architect-rails-project-part-2-3be8), will cover the admin module, authentication users, dashboard layout, CRUDS, and some of the front-end stuff.

[<img src="https://cdn.buymeacoffee.com/buttons/bmc-new-btn-logo.svg" alt="Buy me a coffee" style="display: inline !important;">](https://www.buymeacoffee.com/renzodiaz)