【完全版】railsでのルーティングをgithub風にするためにやったことまとめ

  • 51
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

状況

railsのルーティングがこんな感じになっている。

/hoges/:hoge_id/fugas/:fuga_id/foos/:id/

routes.rbは以下のとおり。

routes.rb
resources :hoges do
    resources :fugas do
      resources :foos
    end
  end

テーブルにはhoge、fuga、fooともに、「(各テーブル名)_name」をつけたカラムが存在している。

やりたいこと

githubみたいな以下のような感じにしたい。

/hoge_name/fuga_name/foo_name/

やったこと

調べる

役に立ったサイトは以下。

routes.rbでresourcesを使ったときのパラメータをid以外にする - PILOG

to_param - リファレンス - Railsドキュメント

Rails routing like github - Stack Overflow

norman/friendly_id

Ruby - Rails 3.2.12 + friendly_id - Qiita

Rails routing like github - Stack Overflow

Nested resource URLs without controller names or numeric IDs in Rails 3 – Jason Codes

調べた結果

何やらfriendly_idっていうのを使うといいらしい。

実装する

  • Gemfileにfriendly_idを追加してインストール
gem 'friendly_id'
$ bundle install
  • friendly_id作成
$ rails g friendly_id
  • migrationファイルの作成
$ rails g migration add_slug_to_hoges slug:string
$ rails g migration add_slug_to_fugas slug:string
$ rails g migration add_slug_to_foos slug:string
  • migrationファイルの編集
add_slug_to_hoges.rb
class AddCachedSlugToHoges < ActiveRecord::Migration
  def up
    add_column :hoges, :slug, :string
    add_index :hoges, :slug, :unique => true
  end

  def down
    remove_column :hoges, :slug
  end
end
add_slug_to_fugas.rb
class AddCachedSlugToFugas < ActiveRecord::Migration
  def up
    add_column :fugas, :slug, :string
    add_index :fugas, [:hoge_id, :slug], :unique => true
  end

  def down
    remove_column :fugas, :slug
  end
end
add_slug_to_foos.rb
class AddCachedSlugToFoos < ActiveRecord::Migration
  def up
    add_column :foos, :slug, :string
    add_index :foos, :slug, :unique => true
  end

  def down
    remove_column :foos, :slug
  end
end

*modelに追記

hoge.rb
class Hoge < ActiveRecord::Base
  has_many :fuga
  has_friendly_id :hoge_name, :use_slug => true
end
fuga.rb
class Fuga < ActiveRecord::Base
  belongs_to :hoge
  has_many :foos, through: :bar, source: :foo
  has_frinedly_id :fuga_name, :use_slug => true, :scope => :hoge_id
end
foo.rb
class Foo < ActiveRecord::Base
  has_many :fugas, through: :bar, source: :fuga
  has_frinedly_id :foo_name, :use_slug => true
end

  • マイグレーションファイルのDBへの反映
$ rake db:migrate
  • routes.rbを編集(rake routesしたときのURI Patternがキモいため)
routes.rb
  resources :hoges, param: :hoge_name, :path => '' do
    resources :fugas, param: :fuga_name, :path => '' do
      resources :foos , param: :foo_name, :path => '' do
      end
    end
  end

結果

github風のルーティングになった

                     Prefix Verb   URI Pattern                                   Controller#Action
    hoge_fuga_foos GET    /:hoge_hoge_name/:fuga_fuga_name/:foo_name/edit(.:format) foos#edit
     hoge_fuga_foo GET    /:hoge_hoge_name/:fuga_fuga_name/:foo_name(.:format)      foos#show
                   PATCH  /:hoge_hoge_name/:fuga_fuga_name/:foo_name(.:format)      foos#update
                   PUT    /:hoge_hoge_name/:fuga_fuga_name/:foo_name(.:format)      foos#update
                   DELETE /:hoge_hoge_name/:fuga_fuga_name/:foo_name(.:format)      foos#destroy

まとめ

github風のルーティングをするのに情報が乏しい、かつ点在しているので苦労しました。
調査〜実装までひととおり書いたつもりなので、これさえあれば実装できると思います。
参考になれば嬉しいです。

謝辞

これを実装するのに、最初に参考サイトを教えてくれたのはkgmyshinでした。ありがとうございました!