Railsで /users/123 の代わりに /userid でユーザーページにアクセス可能にする

Rails のデフォルトでは、ユーザーのプロフィールページのパスは、http://example.com/users/123 のように /users/ 以下にユーザー固有の数字idのパスとなります。ユーザー固有の値としてユーザーが決めた userid 的な値を利用して、かつドメイン直下で http://example.com/userid というパスでもアクセス可能にしたい。

スポンサーリンク

— 環境 —
Rails 4.0.1

ユニークな userid フィールドを追加

まず、サインアップ時に userid を入力してもらうようにします。また userid フィールドは DB および validation で、unique 強制しておきます。サインアップフォームに独自の入力フィールドを追加するのは以下を参考。

Rails4 Devise でサインアップ用のユーザー登録フォームに、独自の入力フィールドを追加する | EasyRamble

canonical_user_path メソッドを ApplicationController に定義

ユーザーが正当な userid を持っている場合は、/userid のパスを返す canonical_user_path というメソッドを作ります。

app/controllers/application_controller.rb

canonical_user_path メソッドは、ユーザーが正当な userid を持っている場合は、ユーザーのプロフィールページのURLとして、http://example.com/shinji のようなドメイン名直下にユーザー名というパスを返します。また、ApplicationController に定義して、helper_method で指定することにより、コントローラーとビューのどこからでも使えるようにしています。

の判定は、通常フォームと OAuth の両方による認証を想定しているためです。詳しくは以下を。

Rails4 で Devise と OmniAuth で、Twitter/Facebook のOAuth認証と通常フォームでの認証を併用して実装 | EasyRamble

これで、コントローラーやビューから canonical_user_path(@user) としてやると、正当な userid を持つ user の場合は “/userid” がユーザーページのパスとして返されます。

http://example.com/userid 用のコントローラーとビュー

UsersController に show_by_userid というメソッドを定義します。

app/controllers/users_controller.rb

show_by_userid メソッドの中身は、show メソッドとほぼ同じです。show_by_userid では、@user の検索に userid を用います。あと、最後にビュー用のテンプレートとして、show アクションと同じものを指定するために、render :template => “users/show” を追加しています。

その他の部分の、show_by_userid と show のロジックは同じですので、適宜 private メソッドに追いやって呼び出すようにすると DRY 違反を防げる。

ルーティング設定

ルーティングに以下を設定します。

config/routes.rb

http://example.com/userid を、users コントローラーの show_by_userid アクションにルーティングさせます。get メソッドを指定。

以上で、例えば id が 123, userid が “shinji” である正当な userid を持つユーザーの場合、/users/123 および /shinji の両方のパスで、ユーザーのプロフィールページにアクセスできます。

canonical_user_path メソッドをテスト

ApplicationController のメソッドをテストする場合、Anonymous Controller を使ってやると良いそうです。以下のテストを書きました。

spec/controllers/application_controller.rb

canonical_user_path が正しいパスを返すかどうかだけをテストしたかったのですけど、書き方がトリッキーな気がします…。何か良い書き方がありそうなので、テストしたいことの意図だけ汲んで下さい。

通常のフォームからサインアップしたユーザーを @normal_user として、Facebook での OAuth により認証したユーザーを @facebook_oauth_user としています。@facebook_oauth_user はモック的なもので、provider に facebook を指定した User オブジェクト。

あとは、各々 canonical_user_path メソッドの実行結果をまとめて、@text に渡してレンダリング。response.body が canonical_user_path の正しい文字列となっているかをチェックしています。

user_path(id) メソッドが /users/userid を返すように変更する方法

以降補足です。

以下のように User モデルで to_param をオーバーライドすると、user_path が user の id ではなくて userid を使うように変更できます。

app/models/user.rb

この場合は、返されるパスは /users/shinji という形になります。私はドメイン直下にユーザー名というURLでアクセス可能にしたかったので、結局採用しませんでした。

スポンサーリンク
パーフェクト Ruby on Rails は、最近読んだ Rails 本の中では一番役に立った本です。Chef や Capistrano など Rails と共によく使用される技術にも触れてあります。Ruby on Rails 4 アプリケーションプログラミングは、入門的な内容で Rails の機能全体を網羅されています。
スポンサーリンク
 
Twitterを使っていますのでフォローお願いたします!ブログの更新情報もつぶやいてます^^
(英語学習用)
  • 2件のコメント
  • ARZ

    新しくルーティングを切って、
    /about
    とかでaboutページを表示したいときはどうすればいいのでしょうか?
    user#show_by_useridに飛ばされてしまうので…

    • taka

      ARZ さん、こんにちは。私が使っている方法ではありますが…
      1. ‘about’ など使われたくないユーザーIDでユーザー登録できないようにする Validator を作成
      2. User モデルでその Validator を使ってバリデーションを行う
      3. config/routes.rb で about の get ルーティングを users#show_by_userid のルーティングより上に(優先させて)設定

      以下の記事が参考になります。
      登録されるとつらいユーザー名を禁止するRails Validator
      http://bitarts.jp/blog/archives/004363.html
      登録されるとつらいユーザー名リスト
      http://qiita.com/phimcall/items/4c559b70f70ea7f1953b

      以上ですがよろしくお願いいたします!

Leave Your Message!