使用 Friendly_Id 实现/YYYY/MM/Title-Slug URL 结构 [英] Implementing /YYYY/MM/Title-Slug URL structure with Friendly_Id

查看:73
本文介绍了使用 Friendly_Id 实现/YYYY/MM/Title-Slug URL 结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm really hoping someone can help this Rails n00b with this issue. I've been researching, trying, crashing(-and-burning) over the past few days on how to implement the standard /YYYY/MM/Title-Slug URL structure for a blog I'm putting together. I've discovered and successfully implemented Friendly_Id to handle the sluggification (along with history tracking), but for the life of me I can't get the Year/Month part of the routing problem resolved.

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

Before I forget: I'm using Rails 4.2.3 and Ruby 2.2.1p85 (because, yes, I leveraged a bunch of stuff from RailsTutorial.org) :-)

为了尽量减少混淆(或附带损害),我搭建了一个超级简单的博客应用程序来尝试让它一切正常:

To minimize confusion (or collateral damage), I've scaffolded a super-simple blog app to try to get it all working:

$ 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 进行了以下更改:

Made the following changes to 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

<p id="notice"><%= notice %></p>

<h1>Listing Posts</h1>

<table>
  <thead>
    <tr>
      <th>Title</th>
      <th>Content</th>
      <th>Slug</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @posts.each do |post| %>
      <tr>
        <td><%= post.title %></td>
        <td><%= post.content %></td>
        <td><%= post.slug %></td>
        <td><%= link_to 'Show', post_date_path(post) %></td>
        <td><%= link_to 'Edit', edit_post_path(post) %></td>
        <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New Post', new_post_path %>

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 Q& 中的 Rails3 代码;A 因为这让我在我发现的其他选项中走得最远.我目前遇到以下控制器异常:

These changes are mostly from updating the Rails3 code from this Stackoverflow Q&A as that has gotten me the furthest out of other options I've discovered. I'm currently running into the following Controller Exception:

Showing […]/app/views/posts/index.html.erb where line #24 raised:

No route matches {:action=>"show", :controller=>"posts", :month=>nil, :slug=>nil, :year=>#<Post id: 23, title: "test", content: "", slug: "test-4", created_at: "2015-09-01 21:05:48", updated_at: "2015-09-01 21:05:48">} missing required keys: [:month, :slug, :year]

以其他稍微令人崩溃的方式失败的其他解决方案:

Other solutions that have failed in other slightly soul-crushing ways:

  • Rails 4 博客/:year/:month/:title with clean routing"(请参阅​​链接的评论)- 由于 4.1.2 似乎从未修复过的错误)
  • Rails 4.1.2 - to_param 转义斜杠(并破坏应用程序)"(请参阅​​链接的评论)- 这可能有效,但我无法为我的目的翻译答案
  • Friendly_Id slug,用斜杠分隔 ID 或日期"(见链接评论)

需要明确的是:我不喜欢这种方法 - 我非常乐意采用完全不同的方式.我希望我的最终博客能够作为:

To be clear: I'm not wedded to this approach - I'm more than happy to go an entirely different way. I would just like my final blog to function as:

  • http://www.example.com/blog/(用于索引)
  • http://www.example.com/2015/(用于 2015 年帖子的索引)
  • http://www.example.com/2015/09/(用于 15 年 9 月的帖子索引)
  • http://www.example.com/2015/09/pleeze-help-me(针对个人帖子)
  • http://www.example.com/blog/ (for the index)
  • http://www.example.com/2015/ (for an index of 2015 posts)
  • http://www.example.com/2015/09/ (for an index of posts from Sept'15)
  • http://www.example.com/2015/09/pleeze-help-me (for an individual post)

非常感谢!

编辑

在深入一些额外的兔子洞以获得解决方案时,我想知道使用 URL 重写是否是唯一的方法?这个问题的方法.我的直觉说它正在将一个圆钉敲入一个方孔(特别是考虑到该博客尚未上线,因此不可能有指向当前 URL 结构的链接),但我失败了寻找更好的选择.

In going down some additional rabbit holes to get a solution to this, I'm wondering if using URL rewriting would be the only? approach for this issue. My gut says that it's pounding a round peg into a square hole (especially given that the blog isn't live yet, so there's no chance that there are links out in the wild pointing to the current URL structure), but I'm failing to find a better alternative.

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

I've found two options that might help with the rewrite approach: refraction (see comments for link) and rack-rewrite (see comments for link)

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

Does anyone have any input on this alternative approach and/or these plugins?

谢谢!

PS - 似乎对 SO 权限进行了更新,现在需要至少 10 个声望才能发布 2 个以上的链接,因此我必须删除所有链接才能发布此编辑.我已将它们移至评论处,以便我可以保存编辑.

PS - There appears to be an update to SO permissions that now require at least 10 reputation to post more than 2 links, so I had to remove all the links in order to post this edit. I've moved them to the comments so I can get the edit saved.

推荐答案

我有一个部分有效的解决方案,可以在 新问题我刚刚创建.索引和个别帖子按需要呈现,但我在创建 & 时遇到了问题.编辑帖子,我没有针对年度索引例如http://www.example.com/2015/和每月索引例如http://www.example的解决方案.com/2015/09/.

I've got a partially-working solution that can be viewed in a new question I've just created. The index and individual posts render as desired, but I'm running into issues when creating & editing posts and I don't have a solution for yearly indexes e.g., http://www.example.com/2015/ and monthly indexes e.g., http://www.example.com/2015/09/.

在新问题中解决这些悬而未决的问题的其他见解将不胜感激!

Additional insight on resolving these outstanding issues at the new question would be really appreciated!

可以在 这个后续问题.

这篇关于使用 Friendly_Id 实现/YYYY/MM/Title-Slug URL 结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆