You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 11:55:40