Support Online
Skip to main content

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 Post model,
  • Defining the relationship in the Shark model,
  • 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_to and has_many relationships,
  • 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 Post model, establishes its relationship with Shark, 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.