Skip to content

Ruby on Rails Setup — rails new MVC Architecture and Directory Structure Explained

DodaTech Updated 2026-06-28 8 min read

In this tutorial, you will learn about Ruby on Rails Setup. We cover key concepts, practical examples, and best practices to help you master this topic.

Ruby on Rails setup uses rails new to generate a full MVC application with models, views, controllers, helpers, mailers, and a structured directory following convention over configuration for rapid web development.

What You'll Learn

  • Creating a Rails application with rails new
  • Understanding the MVC architecture
  • Navigating the Rails directory structure
  • Running the Rails server

Why It Matters

Rails revolutionized web development with convention over configuration. Doda Browser uses Rails-inspired patterns for its admin dashboard. Durga Antivirus Pro uses Rails for its cloud management console. Understanding Rails setup is the gateway to building production web applications at startup speed.

Real-World Use

GitHub, Shopify, Airbnb, and Basecamp all run Rails. Any Rails app starts with the same rails new command, generating the same familiar structure. Learning this structure lets you work with any Rails project immediately.

flowchart LR
    A["Rails Setup"] --> B["rails new"]
    B --> C["MVC"]
    C --> D["Models"]
    D --> E["Views"]
    E --> F["Controllers"]
    F --> G["Your App"]
    A:::current --> B
    style A fill:#2563eb,stroke:#2563eb,color:#fff
    style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style E fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style F fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style G fill:#f1f5f9,stroke:#94a3b8,color:#64748b

Prerequisites

# Install Rails
gem install rails

# Verify
rails --version
# Rails 7.2.0

Creating a New Rails Application

rails new blog
cd blog

This single command generates a complete, runnable web application with hundreds of files organized into a predictable structure.

Rails New Options

# Skip test files (use RSpec instead)
rails new blog --skip-test

# API-only application (no views)
rails new api_app --api

# Skip JavaScript
rails new blog --skip-javascript

# Use specific database
rails new blog --database=postgresql

# With all defaults
rails new blog

The Rails Directory Structure

blog/
├── app/
│   ├── controllers/    # Handles requests
│   ├── models/         # Business logic and data
│   ├── views/          # HTML templates
│   ├── helpers/        # View helper methods
│   ├── mailers/        # Email classes
│   ├── jobs/           # Background jobs
│   ├── assets/         # CSS, JS, images
│   └── channels/       # WebSocket channels
├── bin/                # Scripts (rails, rake, setup)
├── config/             # Configuration
│   ├── routes.rb       # URL routing
│   ├── database.yml    # Database config
│   └── environments/   # Per-env settings
├── db/                 # Database schema, migrations
├── lib/                # Custom libraries, tasks
├── log/                # Application logs
├── public/             # Static files
├── storage/            # File uploads
├── test/               # Tests
├── tmp/                # Temporary files
├── vendor/             # Third-party code
├── Gemfile             # Dependencies
├── Gemfile.lock        # Locked versions
├── Rakefile            # Task definitions
├── config.ru           # Rack configuration
└── package.json        # JS dependencies

The app/ Directory (MVC Core)

app/
├── controllers/
│   ├── application_controller.rb  # Base controller
│   └── concerns/                  # Shared controller logic
├── models/
│   ├── application_record.rb      # Base model
│   └── concerns/                  # Shared model logic
├── views/
│   └── layouts/
│       └── application.html.erb   # Main layout
└── helpers/
    └── application_helper.rb      # Shared helpers

Starting the Server

cd blog
bin/rails server
# => Booting Puma
# => Rails 7.2.0 application starting
# => Listening on http://localhost:3000

Visit http://localhost:3000 to see the default Rails welcome page.

MVC Architecture

Model (app/models/)

Models represent data and business logic. They communicate with the database:

# app/models/article.rb
class Article < ApplicationRecord
  belongs_to :author
  has_many :comments

  validates :title, presence: true, length: { minimum: 5 }
  validates :body, presence: true

  scope :published, -> { where(published: true) }

  def summary
    "#{title}#{body.truncate(50)}"
  end
end

View (app/views/)

Views generate HTML responses:

<!-- app/views/articles/index.html.erb -->
<h1>Articles</h1>

<% @articles.each do |article| %>
  <article>
    <h2><%= link_to article.title, article %></h2>
    <p><%= article.summary %></p>
    <small>By <%= article.author.name %></small>
  </article>
<% end %>

<%= link_to "New Article", new_article_path, class: "btn btn-primary" %>

Controller (app/controllers/)

Controllers handle HTTP requests and coordinate models and views:

# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
  before_action :set_article, only: [:show, :edit, :update, :destroy]

  def index
    @articles = Article.published.order(created_at: :desc)
  end

  def show
  end

  def new
    @article = Article.new
  end

  def create
    @article = Article.new(article_params)
    if @article.save
      redirect_to @article, notice: "Article created!"
    else
      render :new, status: :unprocessable_entity
    end
  end

  private

  def set_article
    @article = Article.find(params[:id])
  end

  def article_params
    params.require(:article).permit(:title, :body, :published)
  end
end

Configuration Files

config/routes.rb

Rails.application.routes.draw do
  # RESTful routes for articles
  resources :articles

  # Custom routes
  get "about", to: "pages#about"
  get "contact", to: "pages#contact"

  # Root route
  root "articles#index"
end

config/database.yml

development:
  adapter: sqlite3
  database: db/development.sqlite3

test:
  adapter: sqlite3
  database: db/test.sqlite3

production:
  adapter: postgresql
  url: <%= ENV["DATABASE_URL"] %>

Creating Your First Resource

Rails scaffolding generates models, views, controllers, and migrations:

bin/rails generate scaffold Article title:string body:text published:boolean
bin/rails db:migrate
bin/rails server

This creates a fully functional CRUD application at http://localhost:3000/articles.

Common Rails Commands

bin/rails generate        # List all generators
bin/rails generate model Article title:string
bin/rails generate controller Articles
bin/rails generate migration AddCategoryToArticles category:string
bin/rails console         # Interactive console (IRB with Rails)
bin/rails db:migrate      # Run migrations
bin/rails db:rollback     # Undo last migration
bin/rails test            # Run tests
bin/rails routes          # List all routes

Environment-Specific Settings

Rails has three built-in environments:

# config/environments/development.rb
config.consider_all_requests_local = true  # Show detailed errors
config.cache_classes = false               # Reload code on changes

# config/environments/production.rb
config.consider_all_requests_local = false  # Show error pages
config.cache_classes = true                  # Cache for performance
config.force_ssl = true                      # HTTPS only

# config/environments/test.rb
config.cache_classes = true   # Cache for test speed

Common Mistakes

1. Editing Files in vendor/bundle

# Bad — editing gem files
# vendor/bundle/ruby/3.3.0/gems/...

# Good — override in initializers or create wrapper
# config/initializers/my_customization.rb

2. Committing Database Credentials

# Bad — hardcoded in database.yml
production:
  password: "hunter2"

# Good — environment variables
production:
  password: <%= ENV["DATABASE_PASSWORD"] %>

3. Forgetting to Run Migrations

# After adding a model or migration:
bin/rails db:migrate

4. Putting Logic in Views

<!-- Bad — logic in view -->
<% if @user.role == "admin" && @article.published? %>
  <%= @article.title.upcase %>
<% end %>

<!-- Good — use helper -->
<%= display_article_title(@article, @user) %>

5. Not Restarting the Server

When adding gems, routes, or initializers, restart the server with Ctrl+C and bin/rails server.

Practice Questions

1. What does rails new blog generate?

A complete Rails application directory structure with MVC components, configuration files, database setup, asset pipeline, and a default Gemfile — everything needed to start developing a web application.

2. What are the three main MVC components?

Models (data/business logic), Views (HTML presentation), Controllers (request handling). Models interact with the database, controllers Process requests, views render responses.

3. What is the purpose of config/routes.rb?

It maps URLs to controller actions. For example, resources :articles generates all RESTful routes for the Articles controller (index, show, new, create, edit, update, destroy).

4. What are Rails environments and when should you use each?

Development (detailed errors, live reloading), Production (optimized, secure, cached), Test (isolated, fast for automated tests). Each has dedicated config files.

Challenge: Create a new Rails app called "task_manager" with a Task model (title:string, completed:boolean) and demonstrate creating a task through the console.

Solution
rails new task_manager
cd task_manager
bin/rails generate model Task title:string completed:boolean
bin/rails db:migrate
bin/rails console

In Rails console:

# Create a task
task = Task.create(title: "Learn Rails", completed: false)
puts task.id          # 1
puts task.title       # Learn Rails

# Query
incomplete = Task.where(completed: false)
puts incomplete.count  # 1

# Update
task.update(completed: true)
puts task.completed?   # true

FAQ

{{< faq question="What is the difference between Rails and Sinatra?" >}} Rails is a full-stack MVC framework with generators, ORM, and conventions. Sinatra is a lightweight DSL for simple applications and APIs. Rails does more but has a steeper learning curve. {{< /faq >}}

{{< faq question="Do I need to learn Ruby before Rails?" >}} Yes. Understanding Ruby fundamentals (classes, modules, blocks, Enumerable) is essential before Rails. Rails doesn't hide Ruby — it extends it with DSLs and conventions. {{< /faq >}}

{{< faq question="What database does Rails use by default?" >}} SQLite3 in development and test. PostgreSQL is recommended for production. Configure in config/database.yml. {{< /faq >}}

{{< faq question="What is the Rails console?" >}} An interactive Ruby environment loaded with your Rails application. Access models, run queries, test code — all with bin/rails console (or rails c). {{< /faq >}}

{{< faq question="Should I use Rails API or full Rails?" >}} Use rails new --api if you're building an API-only backend (JSON responses, no views). Use full Rails if you need server-rendered HTML, forms, and views. {{< /faq >}}

Try It Yourself

# Create a Rails app
rails new my_blog
cd my_blog

# Generate a Post resource
bin/rails generate scaffold Post title:string body:text
bin/rails db:migrate

# Start server
bin/rails server

# Visit http://localhost:3000/posts
# Create, read, update, and delete posts through the generated interface

What's Next

Now that Rails is set up, learn about Active Record — Rails' ORM for database interaction.

Topic Description Link
Ruby Active Record ORM, queries, relationships {{< ref "26-active-record" >}}
Ruby Migrations Schema changes, data types {{< ref "29-migrations" >}}
Python Django ORM Compare Rails' Active Record with Django Python

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro