如何在Rails 7中为博客文章路由URL添加分类名称
解决方案:为BlogPost添加分类Slug到URL
1. 调整路由配置
替换原有路由,通过嵌套资源实现sitename.com/blog/category-name/blog-post-title的URL结构,同时单独处理新建/创建动作(创建文章时还未关联分类):
Rails.application.routes.draw do # 嵌套路由:处理show/edit/destroy等需要分类的动作 resources :blog_categories, path: 'blog' do resources :blog_posts, path: '', except: [:new, :create] end # 单独处理新建、创建文章的动作(无需在URL中带分类) resources :blog_posts, only: [:new, :create] # 可选:添加从分类页直接新建文章的路由(预选中分类) get 'blog/:blog_category_id/blog_posts/new', to: 'blog_posts#new', as: 'new_blog_category_blog_post' end
2. 改造BlogPosts控制器的查找逻辑
删除原有的find_post和set_post_link方法,替换为同时匹配分类和文章slug的逻辑,并处理URL重定向:
class BlogPostsController < ApplicationController before_action :admin_user, only: [:new, :create, :edit, :update, :destroy] before_action :load_category_and_post, only: [:show, :edit, :update, :destroy] # ... 其他动作代码保持不变 private def post_params params.require(:blog_post).permit(:title, :body, :summary, :thumbnail_link, :blog_category_id) end def load_category_and_post # 通过friendly_id找到分类 @category = BlogCategory.friendly.find(params[:blog_category_id]) # 在分类的文章集合中通过friendly_id找到对应文章 @post = @category.blog_posts.friendly.find(params[:id]) # 重定向到正确URL(处理旧ID、错误分类slug等情况) correct_path = blog_category_blog_post_path(@category, @post) if request.path != correct_path redirect_to correct_path, status: :moved_permanently end end def admin_user redirect_to(root_url) unless current_user.admin? end end
3. 修正视图中的URL辅助方法
将所有生成文章URL的代码,从blog_post_path(@post)替换为blog_category_blog_post_path(@post.blog_category, @post):
- 文章列表链接示例:
<%= link_to post.title, blog_category_blog_post_path(post.blog_category, post) %> - 编辑按钮示例:
<%= link_to '编辑', edit_blog_category_blog_post_path(post.blog_category, post) %> - 删除按钮示例:
<%= link_to '删除', blog_category_blog_post_path(post.blog_category, post), method: :delete, data: { confirm: '确定要删除吗?' } %>
如果使用了new_blog_category_blog_post路由,分类页的新建按钮可以这样写:
<%= link_to '新建文章', new_blog_category_blog_post_path(category) %>
4. (可选)优化BlogPost模型的slug唯一性
如果希望同一分类下的文章slug唯一,可修改BlogPost的friendly_id配置,基于标题和分类slug生成唯一标识:
class BlogPost < ApplicationRecord extend FriendlyId friendly_id :slug_candidates, use: :history belongs_to :blog_category # ... 其他代码保持不变 def slug_candidates [ :title, [:title, blog_category.slug] ] end def should_generate_new_friendly_id? slug.nil? || title_changed? || blog_category_id_changed? end end
此配置会在同名文章时自动拼接分类slug保证唯一性,且文章更换分类时会重新生成slug。
内容的提问来源于stack exchange,提问作者Jake
相关产品推荐
相关产品推荐

