使用Friendly_Id实现/ YYYY / MM / Title-Slug URL结构

我真的希望有人可以用这个问题来帮助这个Rails n00b。 在过去的几天里,我一直在研究,尝试,崩溃(和 – 燃烧)如何为我正在整理的博客实现标准/ YYYY / MM / Title-Slug URL结构。 我已经发现并成功实现了Friendly_Id以处理缓慢(以及历史跟踪),但对于我的生活,我无法解决路由问题的年/月部分。

在我忘记之前:我正在使用Rails 4.2.3和Ruby 2.2.1p85(因为,是的,我利用了RailsTutorial.org中的一些东西):-)

为了最大限度地减少混淆(或附带损害),我已经搭建了一个超级简单的博客应用程序,试图让它全部工作:

$ rails new blog [...] $ cd blog # (Add friendly_id to Gemfile & install) $ rails generate friendly_id $ rails generate scaffold post title content slug:string:uniq [...] $ rake db:migrate 

post.rb进行了以下更改:

 class Post < ActiveRecord::Base extend FriendlyId friendly_id :title, use: :slugged def year created_at.localtime.year end def month created_at.localtime.strftime("%m") end end 

posts_controller.rb

 class PostsController < ApplicationController before_action :set_post, only: [:show, :edit, :update, :destroy] def index @posts = Post.order('created_at DESC').all end def show end def new @post = Post.new end def edit end def create @post = Post.new(post_params) respond_to do |format| if @post.save format.html { redirect_to @post, notice: 'Post was successfully created.' } format.json { render :show, status: :created, location: @post } else format.html { render :new } format.json { render json: @post.errors, status: :unprocessable_entity } end end end def update respond_to do |format| if @post.update(post_params) format.html { redirect_to @post, notice: 'Post was successfully updated.' } format.json { render :show, status: :ok, location: @post } else format.html { render :edit } format.json { render json: @post.errors, status: :unprocessable_entity } end end end def destroy @post.destroy respond_to do |format| format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' } format.json { head :no_content } end end private def set_post @post = Post.friendly.find(params[:id]) end def post_params params.require(:post).permit(:title, :content, :published_at, :slug) end end 

index.html.erb

 

Listing Posts

Title Content Slug

routes.rb

 Rails.application.routes.draw do get '/posts', to: 'posts#index', as: :posts_path get '/posts/:year', to: 'posts#index', as: :posts_year, constraints: { year: /\d{4}/ } get '/posts/:year/:month', to: 'posts#index', as: :posts_month, constraints: { year: /\d{4}/, month: /\d{1,2}/ } get '/posts/:year/:month/:slug', to: 'posts#show', as: :post_date, constraints: { year: /\d{4}/, month: /\d{1,2}/, slug: /[a-z0-9\-]+/ } resources :posts end 

这些更改主要来自更新此Stackoverflow问答中的Rails3代码,因为这让我发现了我发现的其他选项中最远的代码。 我目前正在遇到以下控制器exception:

 Showing […]/app/views/posts/index.html.erb where line #24 raised: No route matches {:action=>"show", :controller=>"posts", :month=>nil, :slug=>nil, :year=>#} missing required keys: [:month, :slug, :year] 

其他解决方案在其他轻微的破坏方式中失败了:

  • “Rails 4 Blog /:year /:month /:title with clean routing”(请参阅​​链接评论) – 这似乎不起作用,因为4.1.2错误似乎从未修复过 )
  • “Rails 4.1.2 – to_param转义斜杠(并打破应用程序)”(请参阅​​链接评论) – 这可能有用,但我无法为我的目的翻译答案
  • “Friendly_Id slugs with id或以斜杠分隔的日期”(请参阅​​链接评论)

要明确的是:我并不喜欢这种方法 – 我很乐意采用完全不同的方式。 我希望我的最终博客能够发挥作用:

  • http://www.example.com/blog/ (索引)
  • http://www.example.com/2015/
  • http://www.example.com/2015/09/ (来自9月15日的post索引)
  • http://www.example.com/2015/09/pleeze-help-me (个别post)

提前谢谢了!

编辑

在寻找一些额外的兔子洞以获得解决方案时,我想知道是否使用URL重写是唯一的? 解决这个问题的方法。 我的直觉说它正在将一个圆形钉子撞到一个方孔中(特别是考虑到博客尚未生效,因此没有机会在野外指向当前的URL结构),但我失败了找到更好的选择。

我找到了两个可能有助于重写方法的选项:折射(参见链接评论)和机架重写(参见链接评论)

有没有人对这种替代方法和/或这些插件有任何意见?

谢谢!

PS – 似乎SO权限的更新现在需要至少10个声誉才能发布超过2个链接,因此我必须删除所有链接才能发布此编辑。 我已将它们移至评论中,因此我可以保存编辑内容。

我有一个部分工作的解决方案,可以在我刚刚创建的一个新问题中查看。 索引和个别post根据需要进行渲染,但我在创建和编辑post时遇到问题,而且我没有年度索引的解决方案, eg, http://www.example.com/2015/和月度索引, eg, http://www.example.com/2015/09/

在新问题上解决这些悬而未决的问题的其他见解将非常感谢!

在随后的问题的接受答案中可以找到完整的,有效的实施。