🎨 Оволодіння вкладеними ресурсами в Rails: Повний посібник з управління користувачами та постами

pic

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

pic

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

Тепер давайте почнемо з того, як користувачі взаємодіятимуть з нашим додатком.

pic

Файл _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

Leave a Reply

Your email address will not be published. Required fields are marked *