【问题标题】:Implementing /YYYY/MM/Title-Slug URL structure with Friendly_Id使用 Friendly_Id 实现 /YYYY/MM/Title-Slug URL 结构
【发布时间】:2015-11-28 10:39:56
【问题描述】:

我真的希望有人可以帮助这个 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

<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&A 更新 Rails3 代码,因为这让我在我发现的其他选项中获得了最大的收益。我目前遇到以下控制器异常:

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]

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

  • “Rails 4 博客 /:year/:month/:title with clean routing”(请参阅​​ cmets 以获取链接) - 由于 4.1.2 bug that appears to never having been fixed,这似乎不起作用)
  • “Rails 4.1.2 - to_param 转义斜杠(并破坏应用程序)”(请参阅​​ cmets 以获取链接) - 这可能有效,但我无法为我的目的翻译答案
  • “Friendly_Id 的 id 或日期以斜线分隔”(请参阅​​ cmets 获取链接)

明确一点:我不喜欢这种方法 - 我非常乐意采用完全不同的方式。我希望我的最后一篇博客能够发挥以下作用:

  • http://www.example.com/blog/(用于索引)
  • http://www.example.com/2015/(用于 2015 年帖子的索引)
  • http://www.example.com/2015/09/(获取 2015 年 9 月的帖子索引)
  • http://www.example.com/2015/09/pleeze-help-me(针对个人帖子)

非常感谢!

编辑

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

我发现了两个可能有助于重写方法的选项:折射(有关链接,请参阅 cmets)和 rack-rewrite(有关链接,请参阅 cmets)

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

谢谢!

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

【问题讨论】:

标签: ruby-on-rails ruby-on-rails-4 rails-routing friendly-id


【解决方案1】:

我有一个部分工作的解决方案,可以在我刚刚创建的new question 中查看。索引和单个帖子按需要呈现,但我在创建和编辑帖子时遇到问题,并且我没有年度索引 e.g., http://www.example.com/2015/ 和每月索引 e.g., http://www.example.com/2015/09/ 的解决方案。

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

可以在this subsequent question 接受的答案中找到完整的工作实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-06
    • 2014-03-19
    • 2012-07-06
    • 2014-08-20
    • 1970-01-01
    • 2012-10-02
    相关资源
    最近更新 更多