[Ruby on Rails] Fonction de signet (enregistrement favori, comme): une direction

Cible

Implémentez une fonction de signet (enregistrement favori, comme) pour les articles. bookmark.gif

Environnement de développement

ruby 2.5.7 Rails 5.2.4.3 OS: macOS Catalina

supposition

Créer un modèle

Terminal


$ rails g model Bookmark user:references post:references

Ajoutez null: false pour éviter un stockage vide dans la base de données.

db/migate/xxxxxxxxxxxxxx_create_bookmarks.rb


class CreateBookmarks < ActiveRecord::Migration[5.2]
  def change
    create_table :bookmarks do |t|
      t.references :user, foreign_key: true, null: false
      t.references :post, foreign_key: true, null: false

      t.timestamps
    end
  end
end

Terminal


$ rails db:migrate

Ajouté à chaque modèle.

app/models/bookmark.rb


validates :user_id, uniqueness: { scope: :post_id }

<détails>

Supplément </ summary> En ajoutant les validations ci-dessus, l'enregistrement en double peut être évité. Plus précisément, cela vous empêche d'essayer de vous enregistrer plus d'une fois pendant le chargement. </ détails>

app/models/post.rb


  has_many :bookmarks, dependent: :destroy

  def bookmarked_by?(user)
    bookmarks.where(user_id: user).exists?
  end

app/models/user.rb


has_many :bookmarks, dependent: :destroy

<détails>

Supplément </ summary> En ajoutant bookmarked_by? (Utilisateur) Vérifiez que vous avez déjà ajouté un signet. </ détails>

Créer un contrôleur

Terminal


$ rails g controller bookmarks

app/controllers/bookmarks_controller.rb


class BookmarksController < ApplicationController
  before_action :authenticate_user!

  def create
    @post = Post.find(params[:post_id])
    bookmark = @post.bookmarks.new(user_id: current_user.id)
    if bookmark.save
      redirect_to request.referer
    else
      redirect_to request.referer
    end
  end

  def destroy
    @post = Post.find(params[:post_id])
    bookmark = @post.bookmarks.find_by(user_id: current_user.id)
    if bookmark.present?
    	bookmark.destroy
    	redirect_to request.referer
    else
    	redirect_to request.referer
    end
  end
end

<détails>

Supplément </ summary> Tout d'abord, récupérez le post_id, puis associez le current_user à user_id. La raison de l'insertion de bookmark.present? Est d'éviter l'erreur de double pression. </ détails>

config/routes.rb


  resources :posts, except: [:index] do
    resource :bookmarks, only: [:create, :destroy]
  end

<détails>

Supplément </ summary> Niché dans le post. </ détails>

modification de la vue

erb:app/views/posts/show.html.erb


<tbody>
  <tr>
    <td><%= @post.user.name %></td>
    <td><%= @post.title %></td>
    <td><%= @post.body %></td>
    <td><%= link_to "Éditer", edit_post_path(@post) %></td>
    <% if @post.bookmarked_by?(current_user) %>
      <td><%= link_to "Supprimer le favori", post_bookmarks_path(@post), method: :delete %></td>
    <% else %>
      <td><%= link_to "Signet", post_bookmarks_path(@post), method: :post %></td>
    <% end %>
  </tr>
</tbody>

Pour afficher une liste

Décrivez ce qui suit dans le contrôleur de l'endroit que vous souhaitez afficher. Cette fois, il sera affiché dans app / views / homes / mypage.html.erb.

erb:app/views/homes/mypage.html.erb


<table>
  <caption>Liste de signets</caption>
  <thead>
    <tr>
      <th>Publié par nom</th>
      <th>Titre</th>
      <th>Texte</th>
    </tr>
  </thead>
  <tbody>
    <% @bookmarks.each do |bookmark| %>
      <tr>
        <td><%= bookmark.post.user.name %></td>
        <td>
          <%= link_to post_path(bookmark.post) do %>
            <%= bookmark.post.title %>
          <% end %>
        </td>
        <td><%= bookmark.post.body %></td>
      </tr>
    <% end %>
  </tbody>
</table>

app/controllers/homes_controller.rb


def mypage
  @bookmarks = Bookmark.where(user_id: current_user.id)
end

Recommended Posts