Implementando a estrutura de URL / AAAA / MM / Title-Slug com Friendly_Id

Estou realmente esperando que alguém possa ajudar este Rails n00b com esse problema. Eu estive pesquisando, tentando, travando (e queimando) nos últimos dias sobre como implementar a estrutura de URL padrão / AAAA / MM / Slug de título para um blog que estou montando. Descobri e implementei o Friendly_Id com êxito para lidar com a lentidão (junto com o rastreamento do histórico), mas durante toda a minha vida não consigo resolver a parte do ano / mês do problema de roteamento.

Antes que eu esqueça: estou usando o Rails 4.2.3 e o Ruby 2.2.1p85 (porque, sim, eu aproveitei um monte de coisas do RailsTutorial.org) :-)

Para minimizar a confusão (ou danos colaterais), criei um aplicativo de blog super simples para tentar fazer tudo funcionar:

$ 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

Efetuou as seguintes alterações empost.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

Essas mudanças são principalmente da atualização do código Rails3 destePerguntas e respostas sobre Stackoverflow pois isso me tirou o máximo de outras opções que descobri. Atualmente, estou executando a seguinte exceção de controlador:

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]

Outras soluções que falharam de outras maneiras um pouco esmagadoras de alma:

"Blog do Rails 4 /: ano /: mês /: título com roteamento limpo" (veja os comentários no link) - isso parece não funcionar devido a uma4.1.2 bug que parece nunca ter sido corrigido)"Rails 4.1.2 - to_param escapa barras (e interrompe o aplicativo)" (veja os comentários no link) - isso pode funcionar, mas não consegui traduzir a resposta para meus propósitos"Lesmas Friendly_Id com ids ou datas separadas por barras" (ver comentários no link)

Para ser claro: não estou apegado a essa abordagem - estou mais do que feliz em seguir um caminho totalmente diferente. Gostaria apenas que meu blog final funcionasse como:

http://www.example.com/blog/ (para o índice)http://www.example.com/2015/ (para um índice de 2015 postagens)http://www.example.com/2015/09/ (para um índice de postagens de 15 de setembro)http://www.example.com/2015/09/pleeze-help-me (para uma postagem individual)

Muito obrigado antecipadamente!

EDITAR

Ao descer alguns buracos de coelho adicionais para obter uma solução para isso, estou me perguntando se o uso da reescrita de URL seria o único? abordagem para esta questão. Meu intestino diz que está colocando um pino redondo em um buraco quadrado (especialmente porque o blog ainda não está no ar, por isso não há chance de que haja links ocultos apontando para a estrutura atual da URL), mas estou falhando para encontrar uma alternativa melhor.

Encontrei duas opções que podem ajudar na abordagem de reescrita: refração (consulte os comentários no link) e reescrita em rack (consulte os comentários no link)

Alguém tem alguma opinião sobre essa abordagem alternativa e / ou esses plugins?

Obrigado!

PS - Parece haver uma atualização nas permissões de SO que agora exigem pelo menos 10 reputação para postar mais de 2 links, então tive que remover todos os links para publicar esta edição. Mudei-os para os comentários para que eu possa salvar a edição.

questionAnswers(1)

yourAnswerToTheQuestion