Rails MVC & Routing
Rails MVC & Routing Rails implements a strict MVC pattern. The router maps URLs to controller actions. Controllers coordinate between models and views. Masterin…
Rails MVC & Routing
Rails implements a strict MVC pattern. The router maps URLs to controller actions. Controllers coordinate between models and views. Mastering routes.rb and controller conventions covers the vast majority of web request handling in Rails.
routes.rb
# config/routes.rb
Rails.application.routes.draw do
# resources generates 7 RESTful routes (index/show/new/create/edit/update/destroy)
resources :articles
# Nested resources
resources :posts do
resources :comments, only: [:index, :create, :destroy]
end
# Singular resource (no :id in URL — e.g. user profile)
resource :profile, only: [:show, :edit, :update]
# Namespace — groups routes and controllers under a prefix
namespace :admin do
resources :users
resources :analytics, only: [:index]
end
# => /admin/users, controllers in app/controllers/admin/users_controller.rb
# Scope — URL prefix without affecting controller namespace
scope :api do
resources :products
end
# => /api/products, controllers still in app/controllers/products_controller.rb
# API versioning with module and scope
scope :api do
namespace :v1 do
resources :users
end
end
# => /api/v1/users, controller: Api::V1::UsersController
# Member routes (operate on a specific resource)
resources :articles do
member do
post :publish
delete :archive
end
collection do
get :featured # /articles/featured
end
end
# Concerns — shared route fragments
concern :commentable do
resources :comments
end
resources :posts, concerns: :commentable
resources :photos, concerns: :commentable
# Named routes
get "/about", to: "pages#about", as: :about
# => about_path, about_url helpers generated
root "dashboard#index"
end# Inspect routes
rails routes # All routes
rails routes -g article # Filter by pattern
rails routes --expanded # Show full details
# Route helpers generated by resources :articles:
# articles_path → /articles (index, create)
# new_article_path → /articles/new (new)
# article_path(article) → /articles/:id (show, update, destroy)
# edit_article_path(art) → /articles/:id/edit (edit)Controllers
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
before_action :authenticate_user! # Runs before every action
before_action :set_article, only: [:show, :edit, :update, :destroy]
before_action :authorize_author!, only: [:edit, :update, :destroy]
def index
@articles = Article.published.order(created_at: :desc).page(params[:page])
# render :index is implicit — renders app/views/articles/index.html.erb
end
def show
# @article already set by before_action
respond_to do |format|
format.html # renders show.html.erb
format.json { render json: @article }
end
end
def new
@article = Article.new
end
def create
@article = current_user.articles.build(article_params)
if @article.save
redirect_to @article, notice: "Article created successfully."
else
render :new, status: :unprocessable_entity
end
end
def update
if @article.update(article_params)
redirect_to @article, notice: "Article updated."
else
render :edit, status: :unprocessable_entity
end
end
def destroy
@article.destroy!
redirect_to articles_path, status: :see_other, notice: "Article deleted."
end
private
def set_article
@article = Article.find(params[:id])
end
# Strong parameters — whitelist what can be mass assigned
def article_params
params.require(:article).permit(:title, :body, :published, tag_ids: [])
end
def authorize_author!
redirect_to root_path, alert: "Not authorized." unless @article.author == current_user
end
end