Ruby on Rails:为Recipeazy食谱网站添加可编辑删除的评论功能
Great question! Let’s break this down—first, about that tutorial: it’s focused on building a JSON API, so if your Recipeazy app is a traditional server-rendered Rails app (not API-only), some parts (like handling JSON responses instead of views) won’t directly apply. But the core concepts (associations, CRUD actions for comments) are totally transferable. Let’s walk through how to implement this for a standard Rails app:
Step 1: Set Up the Comment Model
First, generate a Comment model that belongs to both a User and a Recipe (since each comment is tied to a user and a recipe):
rails generate model Comment content:text user:references recipe:references rails db:migrate
Then update your models to define the associations:
- In
app/models/user.rb:class User < ApplicationRecord has_many :comments, dependent: :destroy # ... your existing code end - In
app/models/recipe.rb:class Recipe < ApplicationRecord has_many :comments, dependent: :destroy # ... your existing code end - In
app/models/comment.rb:class Comment < ApplicationRecord belongs_to :user belongs_to :recipe validates :content, presence: true end
Step 2: Add Nested Routes
Since comments are a resource under recipes, nest them in your config/routes.rb:
Rails.application.routes.draw do resources :recipes do resources :comments, only: [:create, :edit, :update, :destroy] end # ... your existing routes end
This gives you paths like /recipes/:recipe_id/comments for creating, and /recipes/:recipe_id/comments/:id/edit for editing.
Step 3: Build the Comments Controller
Create app/controllers/comments_controller.rb with actions for creating, editing, updating, and destroying—plus authorization checks to ensure only the comment’s owner can edit/delete:
class CommentsController < ApplicationController before_action :set_recipe before_action :set_comment, only: [:edit, :update, :destroy] before_action :authorize_owner!, only: [:edit, :update, :destroy] def create @comment = @recipe.comments.build(comment_params.merge(user: current_user)) if @comment.save redirect_to @recipe, notice: 'Comment added successfully!' else redirect_to @recipe, alert: 'Failed to add comment.' end end def edit end def update if @comment.update(comment_params) redirect_to @recipe, notice: 'Comment updated successfully!' else render :edit end end def destroy @comment.destroy redirect_to @recipe, notice: 'Comment deleted.' end private def set_recipe @recipe = Recipe.find(params[:recipe_id]) end def set_comment @comment = @recipe.comments.find(params[:id]) end def comment_params params.require(:comment).permit(:content) end def authorize_owner! unless @comment.user == current_user redirect_to @recipe, alert: 'You can only edit or delete your own comments.' end end end
Note: This assumes you have a current_user method set up (from Devise or your own authentication system).
Step 4: Add Comment UI to Recipe Views
Update your recipe show view (app/views/recipes/show.html.erb) to display comments and add a form for new comments:
<!-- Display existing comments --> <h3>Comments</h3> <% @recipe.comments.each do |comment| %> <div class="comment"> <p><strong><%= comment.user.name %></strong></p> <p><%= comment.content %></p> <% if comment.user == current_user %> <%= link_to 'Edit', edit_recipe_comment_path(@recipe, comment) %> <%= link_to 'Delete', recipe_comment_path(@recipe, comment), method: :delete, data: { confirm: 'Are you sure?' } %> <% end %> </div> <% end %> <!-- Form to add a new comment --> <% if current_user %> <%= form_with(model: [@recipe, @recipe.comments.build], local: true) do |form| %> <div class="field"> <%= form.label :content %> <%= form.text_area :content %> </div> <div class="actions"> <%= form.submit 'Add Comment' %> </div> <% end %> <% else %> <p>Please <%= link_to 'log in', new_user_session_path %> to leave a comment.</p> <% end %>
Step 5: Add Edit View for Comments
Create app/views/comments/edit.html.erb for the edit form:
<h3>Edit Comment</h3> <%= form_with(model: [@recipe, @comment], local: true) do |form| %> <div class="field"> <%= form.label :content %> <%= form.text_area :content %> </div> <div class="actions"> <%= form.submit 'Update Comment' %> <%= link_to 'Cancel', @recipe %> </div> <% end %>
Optional: Use a Authorization Gem
For more complex authorization rules (instead of the simple check in the controller), consider using gems like Pundit or CanCanCan—they make managing permissions cleaner as your app grows.
If you run into specific issues (like authentication problems, routing errors, or view rendering bugs), sharing snippets of your existing models/controllers/views would help narrow things down!
内容的提问来源于stack exchange,提问作者iiRosie1

