Creating Nested Resources in Ruby on Rails
🧠 Technical Summary
This guide teaches the concept of nested resources in Ruby on Rails projects. The goal is to establish a logical relationship between the main model (e.g. Shark) and the submodel (e.g. Post) and manage CRUD operations in accordance with this hierarchy.
Steps:
- Creation of the
Postmodel, - Defining the relationship in the
Sharkmodel, - Intertwining the route,
- Editing controller and view files,
- Adding validation and testing the application.
🎯 What You Will Learn in This Guide
- The basics of the Nested resources structure,
- The difference between
belongs_toandhas_manyrelationships, - Managing nested controller structures,
- Correct configuration of forms and routes,
- Making data relationships more organized in Rails.
⚙️ 1. Creating Nested Models and Resources
Switch to the project and create the model Post:
cd sharkapp
rails generate scaffold Post body:text shark:references
This command creates the
Postmodel, establishes its relationship withShark, and creates the necessary files for CRUD operations.
🧩 2. Updating Parent Models and Routes
Add Relationship to Shark Model
# ~/sharkapp/app/models/shark.rb
class Shark < ApplicationRecord
has_many :posts, dependent: :destroy
validates :name, presence: true, uniqueness: true
validates :facts, presence: true
end
dependent: :destroy, when a shark is deleted it also removes all posts belonging to it.
Configure Nested Routes
# ~/sharkapp/config/routes.rb
Rails.application.routes.draw do
resources :sharks do
resources :posts
end
root 'sharks#index'
end
Routes now have the following structure:
/sharks/:shark_id/posts/:id
🧠 3. Adapting the Controller to Nested Structure
Open app/controllers/posts_controller.rb:
class PostsController < ApplicationController
before_action :get_shark
before_action :set_post, only: [:show, :edit, :update, :destroy]
def index
@posts = @shark.posts
end
def new
@post = @shark.posts.build
end
def create
@post = @shark.posts.build(post_params)
if @post.save
redirect_to shark_posts_path(@shark), notice: 'Gönderi başarıyla oluşturuldu.'
else
render :new
end
end
def update
if @post.update(post_params)
redirect_to shark_posts_path(@shark), notice: 'Gönderi güncellendi.'
else
render :edit
end
end
def destroy
@post.destroy
redirect_to shark_posts_path(@shark), notice: 'Gönderi silindi.'
end
private
def get_shark
@shark = Shark.find(params[:shark_id])
end
def set_post
@post = @shark.posts.find(params[:id])
end
def post_params
params.require(:post).permit(:body, :shark_id)
end
end
This controller only acts on posts belonging to the selected shark.
🧱 4. Editing Views
_form.html.erb
<%= form_with(model: [@shark, post], local: true) do |form| %>
<%= form.label :body, 'Gönderi İçeriği' %>
<%= form.text_area :body %>
<%= form.submit 'Kaydet' %>
<% end %>
The form automatically links the post to the relevant shark.
index.html.erb
<h1>Gönderiler</h1>
<table>
<thead>
<tr>
<th>İçerik</th>
<th>Köpek Balığı</th>
<th>İşlemler</th>
</tr>
</thead>
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.body %></td>
<td><%= post.shark.name %></td>
<td>
<%= link_to 'Düzenle', edit_shark_post_path(@shark, post) %> |
<%= link_to 'Sil', [@shark, post], method: :delete, data: { confirm: 'Emin misiniz?' } %>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= link_to 'Yeni Gönderi', new_shark_post_path(@shark) %>
The view lists only posts from the selected shark.
sharks/show.html.erb
<h2><%= @shark.name %> Hakkında Gönderiler</h2>
<ul>
<% @shark.posts.each do |post| %>
<li><%= post.body %></li>
<% end %>
</ul>
<%= link_to 'Yeni Gönderi Ekle', new_shark_post_path(@shark) %> |
<%= link_to 'Geri Dön', sharks_path %>
User can add new post directly from shark detail page.
✅ 5. Model Validation
Update the app/models/post.rb file:
class Post < ApplicationRecord
belongs_to :shark
validates :body, presence: true, uniqueness: true
end
This verification prevents duplicate or empty posts.
🧪 6. Testing the App
Run database migrations:
rails db:migrate
Start the server:
rails s
Test the app from the browser:
http://localhost:3000
You can now view, edit and delete posts specific to each shark.
❓ Frequently Asked Questions (FAQ)
1. Why are nested resources used? To establish a logical relationship where one model (e.g. Post) depends on another model (e.g. Shark).
2. What is the difference between has_many and belongs_to? has_many represents the upper model, belongs_to represents the lower model.
3. Why is dependent: :destroy added? Deleting the parent ensures that all dependent records are also deleted.
4. Can I create a model instead of scaffold? Yes, but scaffold speeds up the process by automatically building the entire CRUD structure.
5. Are three levels of nested structure recommended? No, Rails recommends a maximum of two levels (e.g. shark → post).
🎯 Result
Congratulations! You can now set up the nested resources structure in Ruby on Rails projects and manage relationships between models. 💡 You can try this structure in your own project on GenixNode right now.

