Ruby on Rails应用:用户待办清单与文章书签功能实现问询
Hey there! Let's break down how to build out your Rails app requirements step by step—this should cover everything you need for the bookmark system, single to-do list per user, and viewing others' lists.
First, the Article model needs to be marked as bookmarkable (since the bookmark_system gem requires this for models that can be saved). We'll also link it back to the user who created it, matching your User model's has_many :articles association:
class Article < ActiveRecord::Base acts_as_bookmarkable belongs_to :user, dependent: :destroy end
First, generate the ToDoList model (note Rails uses camel case for class names, even if the filename is snake case):
rails generate model ToDoList user:references rails db:migrate
Next, update the ToDoList model to link to a user:
class ToDoList < ActiveRecord::Base belongs_to :user end
Then, tweak your User model to ensure every user gets exactly one to-do list automatically, and clean up orphaned lists if a user is deleted:
class User < ActiveRecord::Base acts_as_bookmarker has_many :articles, dependent: :destroy has_one :to_do_list, dependent: :destroy # Auto-create a to-do list when a user signs up after_create :create_associated_to_do_list private def create_associated_to_do_list ToDoList.create(user: self) end end
For extra safety, add a database constraint to prevent duplicate to-do lists for a single user. Edit your ToDoList migration file (look for it in db/migrate/) to add a unique index:
class CreateToDoLists < ActiveRecord::Migration[6.1] def change create_table :to_do_lists do |t| t.references :user, null: false, foreign_key: true t.timestamps end # Ensure one to-do list per user at the database level add_index :to_do_lists, :user_id, unique: true end end
If you already ran the migration, run rails db:migrate:redo to apply this change.
The bookmark_system gem adds a bookmarked_articles method to your User model (since Article is bookmarkable). We can wrap this in the ToDoList model to keep things clean:
class ToDoList < ActiveRecord::Base belongs_to :user # Fetch all articles the user has bookmarked def bookmarked_articles user.bookmarked_articles end end
First, generate a controller to handle viewing to-do lists:
rails generate controller ToDoLists show
Update the ToDoListsController to fetch a user's to-do list and their bookmarked articles:
class ToDoListsController < ApplicationController def show @user = User.find(params[:user_id]) @to_do_list = @user.to_do_list @bookmarked_articles = @to_do_list.bookmarked_articles end end
Next, add bookmark/unbookmark actions to your ArticlesController (make sure users are logged in first—we'll use Devise's authenticate_user! as an example):
class ArticlesController < ApplicationController before_action :authenticate_user!, only: [:bookmark, :unbookmark] def bookmark @article = Article.find(params[:id]) current_user.bookmark(@article) redirect_to @article, notice: "Added article to your to-do list!" end def unbookmark @article = Article.find(params[:id]) current_user.unbookmark(@article) redirect_to @article, notice: "Removed article from your to-do list!" end # Keep your existing index/show/new/create actions here end
Update config/routes.rb to add routes for to-do lists and bookmark actions:
Rails.application.routes.draw do # Your existing routes (e.g., devise_for :users, resources :articles) # Route to view a user's to-do list get "/users/:user_id/to_do_list", to: "to_do_lists#show", as: :user_to_do_list # Add bookmark/unbookmark routes to articles resources :articles do member do post :bookmark delete :unbookmark end end end
First, add bookmark/unbookmark buttons to your article show page (app/views/articles/show.html.erb):
<h1><%= @article.title %></h1> <p><%= @article.content %></p> <% if current_user %> <% if current_user.bookmarked?(@article) %> <%= button_to "Remove from To-Do List", unbookmark_article_path(@article), method: :delete, class: "btn btn-danger" %> <% else %> <%= button_to "Add to To-Do List", bookmark_article_path(@article), method: :post, class: "btn btn-primary" %> <% end %> <% end %>
Then, create the to-do list show page (app/views/to_do_lists/show.html.erb) to display bookmarked articles:
<h1><%= @user.username %>'s To-Do List</h1> <% if @bookmarked_articles.empty? %> <p>No articles added to the to-do list yet.</p> <% else %> <ul class="list-group"> <% @bookmarked_articles.each do |article| %> <li class="list-group-item d-flex justify-content-between align-items-center"> <%= link_to article.title, article %> <%# Only let the owner remove articles %> <% if @user == current_user %> <%= button_to "Remove", unbookmark_article_path(article), method: :delete, class: "btn btn-sm btn-danger" %> <% end %> </li> <% end %> </ul> <% end %>
To link to a user's to-do list (e.g., from their profile), use the route helper:
<%= link_to "View #{@user.username}'s To-Do List", user_to_do_list_path(@user) %>
That's it! Now users get a single to-do list automatically, can bookmark articles to add to it, and can view any other user's to-do list.
内容的提问来源于stack exchange,提问作者Joao Quaresma

