Привіт, друзі! Чи коли-небудь вам було важко управляти відносинами між моделями, одночасно підтримуючи чистоту коду та функціональність вашого додатку? Більше не хвилюйтесь! Сьогодні ми зануримося у захоплюючий світ вкладених ресурсів, і я проведу вас через створення простої, але потужної системи "Користувач-Пост". Давайте зробимо програмування веселим та доступним!
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