Привіт, друзі! Чи коли-небудь вам було важко управляти відносинами між моделями, одночасно підтримуючи чистоту коду та функціональність вашого додатку? Більше не хвилюйтесь! Сьогодні ми зануримося у захоплюючий світ вкладених ресурсів, і я проведу вас через створення простої, але потужної системи "Користувач-Пост". Давайте зробимо програмування веселим та доступним!
routes.rb
: Визначення маршрутів
root to: "users#index"
resources :users do
resources :posts
end
Відношення з Постами
- Лінія
has_many :posts
встановлює, що у користувача може бути кілька постів. - Додавання
dependent: :destroy
гарантує, що коли користувач буде видалений, усі його пости теж будуть видалені.
Це допомагає тримати вашу базу даних в порядку — жодних сирітських постів, що залишаються без нагляду!
Вкладені атрибути для постів
accepts_nested_attributes_for :posts
дозволяє нам керувати постами безпосередньо через форму користувача.- Додавання
allow_destroy: true
дає змогу користувачам видаляти конкретні пости безпосередньо з форми.
user.rb
: Модель користувача
class User < ApplicationRecord
has_many :posts, dependent: :destroy
accepts_nested_attributes_for :posts, allow_destroy: true
end
post.rb
: Модель поста
class Post < ApplicationRecord
belongs_to :user
end
Тепер давайте почнемо з того, як користувачі взаємодіятимуть з нашим додатком.
Файл _form.html.erb
— ось де відбувається магія. Це серце інтерфейсу користувача нашого додатку, де ми збираємо деталі про користувача та, за бажанням, керуємо його постами в тій самій формі.
Звучить складно, але насправді це надзвичайно інтуїтивно!
_form.html.erb
: Основний файл для створення/редагування користувачів
<%= form_with(model: @user, local: true, html: { id: 'user-form' }) do |user| %>
Ваші дані
\<%= user.label :name %>
\<%= user.text_field :name %>
\<%= user.label :job %>
\<%= user.text_field :job %>
\<%= user.label :dob %>
\<%= user.date_field :dob %>
Додати пости
<div id="posts-section">
Пости
<%= user.fields_for :posts do |post| %>
<%= post.label :title %>
<%= post.text_field :title, disabled: true %>
<%= post.label :body %>
<%= post.text_area :body, disabled: true %>
<% end %>
<%= user.hidden_field :include_posts, value: false %>
<%= user.submit 'Відправити' %>
<% end %>
<script>
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('user-form');
const toggleButton = document.getElementById('toggle-posts');
const postsSection = document.getElementById('posts-section');
const postFields = form.querySelectorAll('.post-fields input, .post-fields textarea');
const includePostsField = form.querySelector('[name*="include_posts"]');
let postsEnabled = false;
toggleButton.addEventListener('click', function() {
postsEnabled = !postsEnabled;
// Перемикаємо видимість і текст кнопки
postsSection.style.display = postsEnabled ? 'block' : 'none';
toggleButton.textContent = postsEnabled ? 'Видалити пости' : 'Додати пости';
// Перемикаємо поля
postFields.forEach(field => {
field.disabled = !postsEnabled;
});
// Оновлюємо приховане поле
includePostsField.value = postsEnabled;
});
// Обробка відправки форми
form.addEventListener('submit', function(e) {
if (!postsEnabled) {
// Очищаємо значення полів постів, коли пости не включені
postFields.forEach(field => {
field.value = '';
});
}
});
});
</script>
Список користувачів (index.html.erb
)
Ця сторінка є своєрідним каталогом користувачів вашої системи.
Вона показує їхні імена, посади та надає кнопки для дій: показати, редагувати або видалити користувачів. Якщо користувачів ще немає, не хвилюйтеся — додаток ввічливо повідомить вас: “Немає постів.”
О, і є блискуча кнопка New User
, щоб додати нового користувача до списку.
Легко, правда?
index.html.erb
: Список користувачів
<%= link_to 'New User', new_user_path %>
<% if @users.empty? %>
Немає постів
<% else %>
<table>
<thead>
<tr>
<th>Повне ім’я</th>
<th>Посада</th>
<th>Дії</th>
</tr>
</thead>
<tbody>
<% @users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.job %></td>
<td>
<%= link_to 'Show', user_path(user) %>
<%= link_to 'Edit', edit_user_path(user) %>
<%= button_to 'Delete', user_path(user), method: :delete %>
</td>
</tr>
<% end %>
</tbody>
</table>
<% end %>
Перегляд деталей користувача (show.html.erb
)
Клікнувши на “Show”, ви відкриваєте сторінку профілю користувача. Тут ви побачите ім’я користувача, його посаду та дату народження. Якщо він написав пости, вони також будуть відображені, показуючи заголовок і текст.
Хочете побачити більше постів? Для цього є кнопка!
Users View
: Динамічна форма для користувачів та постів
show.html.erb
: Перегляд деталей користувача
<div>
Ім’я:
<%= @user.name %>
</div>
<div>
Дата народження:
<%= @user.dob %>
</div>
<div>
Посада:
<%= @user.job %>
</div>
<% if @post.present? %>
<% @posts.each do |post| %>
<div>
Заголовок:
<%= post.title %>
</div>
<div>
Тіло:
<%= post.body %>
</div>
<% end %>
<% end %>
<%= link_to 'Пости', user_posts_path(@user) %>
Перегляд постів
index.html.erb
: Список постів
<%= link_to 'Користувач', new_user_path %>
<% if @posts.empty? %>
Немає постів
<% else %>
<table>
<thead>
<tr>
<th>Повне ім’я</th>
<th>Пост</th>
<th>Дії</th>
</tr>
</thead>
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.user.name %></td>
<td><%= post.title %></td>
<td>
<%= link_to 'Show', user_post_path(post.user, post) %>
<%= link_to 'Edit', edit_user_path(post.user, post) %>
<%= button_to 'Delete', user_post_path(post.user, post), method: :delete %>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= link_to 'Назад до користувачів', users_path %>
<% end %>
show.html.erb
: Перегляд деталей поста
<div>
Ім’я:
<%= @user.name %>
</div>
<div>
Заголовок:
<%= @post.title %>
</div>
<div>
Тіло:
<%= @post.body %>
</div>
<%= link_to 'Назад до постів', user_posts_path(@user) %>
<%= link_to 'Назад до користувачів', users_path %>
Контролери
UsersController
: Керування користувачами
- Виконує CRUD операції для користувачів.
- Включає
posts_attributes
уuser_params
для обробки вкладених даних постів.
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def index
@users = User.all
end
def show
end
def new
@user = User.new
@user.posts.build
end
def create
@user = User.new(user_params)
if @user.save
redirect_to user_path(@user)
else
render :new
end
end
def edit
@user.posts
end
def update
if @user.update(user_params)
redirect_to user_path(@user)
else
render :edit
end
end
def destroy
@user.destroy
redirect_to users_path
end
private
def set_user
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :job, :dob, posts_attributes: [:id, :title, :body, :_destroy])
end
end
PostsController
: Керування постами
- Вкладено до користувачів для забезпечення того, щоб пости були прив’язані до конкретного користувача.
set_user
отримує батьківського користувача перед виконанням будь-якої операції з постом.
class PostsController < ApplicationController
before_action :set_user
before_action :set_post, only: [:show, :edit, :update, :destroy]
def index
@posts = @user.posts
end
def show
end
def new
@post = @user.posts.build
end
def create
@post = @user.posts.build(post_params)
if @post.save
redirect_to user_posts_path(@user)
else
render :new
end
end
def edit
end
def update
if @post.update(post_params)
redirect_to user_posts_path(@user)
else
render :edit
end
end
def destroy
@post.destroy
redirect_to user_posts_path(@user)
end
private
def set_user
@user = User.find(params[:user_id])
end
def set_post
@post = @user.posts.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :body)
end
end
Декілька моментів, які вас точно потішать
1.
Вкладені ресурси, зроблені простими
Кожен пост належить конкретному користувачу, і наші маршрути, контролери та представлення відображають ці відносини. Чисто, логічно і легко зрозуміло!
Розумні представлення
Немає користувачів? Немає постів? Не проблема! Додаток акуратно обробляє порожні стани, надаючи користувачам чітке повідомлення і зберігаючи дружній інтерфейс.
Управління користувачами в одному місці
Завдяки accepts_nested_attributes_for
, ми можемо керувати користувачами та їхніми постами з однієї форми. Менше кліків — більше дій!
Повторно використовуваний код
Методи, такі як set_user
і set_post
, роблять наші контролери чистими і зручними для читання. Тут немає зайвого безладу.
Це лише початок того, що можна зробити з вкладеними ресурсами в Rails.
Незалежно від того, чи ви будуєте блог, маркетплейс або щось абсолютно унікальне, ці концепції вам точно стануть у пригоді.
Є питання чи ідеї? Давайте поспілкуємося в коментарях нижче — я був би радий дізнатися, як ви використовуєте вкладені ресурси у своїх проектах. Не забудьте поставити лайк і підписатися, щоб я продовжував публікувати нові матеріали — це мене мотивує!
Перекладено з: 🎨 Mastering Nested Resources in Rails: A Complete Guide to User-Post Management