Railsのルーティングリソースの:idパラメータの名前を変更する


107

動的paramsスロットを変更する方法を探し回ったところ、正確に機能するこの投稿が見つかりました。投稿はhttps://thoughtbot.com/blog/rails-patch-change-the-name-of-the-id-parameter-in

基本的には、ルートが次の場合は何をするかです。

map.resources :clients, :key => :client_name do |client|
  client.resources :sites, :key => :name do |site|
    site.resources :articles, :key => :title
  end
end

これらのルートは次のパスを作成します。

/clients/:client_name
/clients/:client_name/sites/:name
/clients/:client_name/sites/:site_name/articles/:title

1つの解決策はdef to_param、モデル内のメソッドをオーバーライドすることですが、モデル自体には触れずにこれを必要としています。

しかし、それはRails 2.xの場合から、Rails 3で同じようにするにはどうすればよいですか?

更新

このアプリはモンゴイドを使用しています。ARではありません。したがって、gem friendlyはafaikでは使用できません。

回答:


192

Rails 4および5

Rails 4では、:paramオプションが追加されました。これは、まさにあなたが探していることをするようです。Rails 4のコードと比較して、Rails 3のコードを見てください。

細部

これはroutes.rbファイルに簡単に実装できます。

# config/routes.rb

resources :posts, param: :slug

# app/controllers/posts_controller.rb

# ...
@post = Post.find_by(slug: params[:slug])
# ...

Rails 4のリリース以降、この機能はRailsガイドに記載されています

Rails 3

残念ながら、Rails 3ではの:keyオプションresourcesが削除されたため、追加のオプションを渡すだけでは、この方法で作成されたルートの名前を簡単に変更できなくなりました。

細部

この1年で、あなたはすでに何らかの方法でアプリケーションを希望どおりに動作させていると思いますが、Rails 3で説明した効果を得る方法を説明しますroutes.rb。これは、to_paramメソッドよりも少し多くの作業を伴います。あなたはまだカスタム使用して定義されたルートのパラメータを定義することができscope、およびmatch(またはそれのいとこをgetputpost、およびdelete)。マッチャーに必要なパラメーター名を書き込むだけです。

get 'clients/:client_name', :to => 'clients#show', :as => client

scope 'clients/:client_name' do
  get 'sites/:name', :to => 'sites#show', :as => site
end

resources自動的に作成されるすべてのルートを手動で追加する必要がありますが、目的のルートが得られます。また、:controllerオプションwith scopescopeブロックを効果的に使用して、繰り返しの一部を削除することもできます。


編集(2014年5月8日):答えにRails 3と4の両方の情報が含まれていることを明確にします。コードへのリンクを更新して、正確な行番号とコミットに移動し、より長い時間動作するようにします。

編集(2014年11月16日): Rails 4が一番上になり、かなり前からRailsの最新バージョンであるため、関連情報が含まれているはずです。

編集(2016年8月9日):このソリューションがRails 5でも機能することを反映し、古いリンクを更新します。


1
つまり、基本的に、Rails3はルータにリソースオプションを作成してRESTFULLにしましたが、カスタム変数名を指定するためにオーバーライドする必要があります...感じが悪いです!
オーガスティンリーディンガー2013

1
これparamがレール3 のオプションのバックポートです: gist.github.com/sj26/44ef47fe8b98b46ee32d
sj26

これにより、URLヘルパーが壊れます。オブジェクトを渡すと通常のIDベースのルートが生成されたり、スラッグを渡すと[:slug]キーが不足しているという不満が出ます。修正方法はありますか?
RonLugge 2014年

9
参考までに、ネストされたリソースを使用する場合、親リソースのパラメーターはになるためpost_slug、混乱する可能性があります。
ghayes

4
これは本当に良いですが、ネストされたリソースのpost_post_idのような親IDのパラメーター名が必要ない場合はどうすればよいですか?
Asnad Atta

45

Rails 4では、paramオプションを渡して:id paramsを変更します。たとえば、 resources :photos, param: :photo_name/ photos /:photo_nameが生成されます


1

私があなたを正しく理解しているなら、あなたが望むのはあなたのURLのclient_name代わりに持っていることidですよね?

to_paramモデルのメソッドをオーバーライドすることでそれを行うことができます。詳細については、こちらをご覧ください


1
すでに述べたように、私にはモデルを変更しないという制約があります。前述の例は、Rails 3でサポートまたは非推奨になっていませんか?
Autodidact

1

すべてに宝石があるように、そのための宝石があります;)

Rails 3でこの種の動作にFriendlyIdを使用しています。

ただし、次のように、モデルにコードを追加する必要があります。

class Client < ActiveRecord::Base
  has_friendly_id :name
end

...そしてクライアントにURI互換の名前がない場合は、そのためにスラッグを使用することをお勧めしますhas_friendly_id :name, :use_slug => true。これはで実行できます。ただし、スラッグを使用する場合は、それらをデータベースに永続化する必要があることは明らかです。

そしてすでに述べたように、ここで説明されているように、to_paramレール3 でもこのトリックを使用できます。ただし、FriendlyIdはもう少し用途が広いと思います。


私はフレンドリーIDが好きで、多くのプロジェクトで使用しています。実際、私のアプリはMongoidを使用しています。そしてfriendly_idはafaikをサポートしていません。すでに述べたように、私の制約はモデルを変更することではありません。
Autodidact

1
mongoidを使用している場合は、この機能を実現するためのmongoid-slugがあります。実際にはを使用しますto_paramが、バックグラウンドで他のいくつかの巧妙なことも行います。私はここのリンクを発見した:stackoverflow.com/questions/4744446/...
フロスト

私はその宝石が好きでした。同様のスラゴイドがもう1つあります。しかし、私が言っているように、私はモデルを変更しないという制約があります。それto_paramはアプリのフロントエンド部分を壊します。実際、ルーティングアプローチを必死に探しています。APIを変更する必要がありますが、モデルとフロントエンドの部分をアプリから切り離す必要はありません。上記の古いバージョンのレールの例と投稿で述べたように、ルートを変更するだけのアプローチができないのはなぜですか???
Autodidact

カスタムルートキーを使用するようにコントローラーを書き換えようとしましたか?たとえば、@client = Client.find(:name => param[:client_name]ClientsController#show?うまくいくかもしれません。

Client.where(:name => param[:client_name]).first、 あれは。

0

Rails 3では、次のように名前空間とスコープの組み合わせを使用して、IDキーの名前を変更できます(ただし、あまり良くありません)。

namespace :clients do
  scope "/:client_name" do
    namespace :sites do
      scope "/:name" do
         post "/:title" => "articles#create"
         ...
      end
    end
  end
end
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.