15
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rails初心者が爆速で中級者になるまで駆け抜ける25日カレンダーAdvent Calendar 2018

Day 12

to_paramでURLにユーザーIDを表示する 初心者→中級者へのSTEP12/25

Last updated at Posted at 2018-12-12

#to_paramでURLにユーザーIDを表示する
はじめに
今回解説するのは実際に僕が実装したもので、その時困ったこと、そしてどう対応したのかを紹介します。
このテーマについてはもっと良い方法がありそうなので、ご存知の方はご指摘いただけると幸いです。

##デフォルトのURL
Railsでshowアクションにルートを通すと下記のようになる。
http://localhost/users/1
http://localhost/users/2
http://localhost/users/3
これだと「ん?もしかして会員数3人しかいない?」とか思われたり、何よりセンスがない。

なので、これを下記のようにユーザーIDを表示するようにしたい。
http://localhost/users/@kamo
http://localhost/users/@buta
http://localhost/users/@tanaka

##to_param
実装は簡単で、to_paramというメソッドをオーバーライドするだけ。

User.rb
  def to_param
    user_id
  end

こうすると、モデルからパスを生成する時:idを使ってたのが、:user_idを使うようになってくれます。

to_paramのソースは下記のとおり。

  def to_key
    key = respond_to?(:id) && id
    key ? [key] : nil
  end

  def to_param 
    (persisted? && key = to_key) ? key.join('-') : nil
  end

上のto_keyメソッドから見てみます。最初の1行で、idの有無、またメソッドとして呼び出せるかを確認しています。2行目で3項演算子を用いて、idを配列に格納しています。

そして次のto_paramでは、modelがDBに保存されていることを確認した後、to_keyで得たid の配列を文字列化しています。

このto_paramはパスを生成する段階で呼ばれ、その時にパスにidを返す流れになっています。
それをオーバライドして、user_idが返ってくるようにしたわけです。

##問題が3点
上記のようなto_paramをオーバーライドの仕方だと問題が3点出てきました。

1,user_idにindex,newなど登録されると困る。
2,params[:id]にuser_idが入るのでコントローラーでの修正が必要。
3,omniauthなど、SNSの簡単認証などを使っていて、user_idが最初に登録されない場合、パスを生成できない。

##解決したコードがこちら

User.rb
 def to_param
    user_id ? '@' + user_id : super()
 end

上記のコードではuser_idが存在するなら、@を加えてます。
@が最初に加えられればindexだろうが、newだろうが怖くありません。また、super()はuser_idを持ってないユーザーは元のto_paramの振る舞いをするようにしてます。

User_controller.rb

    def set_user
      if params[:id].chr == '@'
        user_id = params[:id].slice!(0)
        @user = User.find_by!(user_id: user_id)
      else
        @user = User.find(params[:id])
      end
    end

上記では加えた@を外してます。またuser_idを登録してないユーザー用の分岐もかけています。
これでURLにはuser_idが表示され、かつちゃんとユーザーのデータも読み込めます。

##まとめ
この実装してて思ったのは、「Rails wayに反しているのでは...?」となりましたが、他に方法が見当たらないのでこの方法で実装しました。(当時)
今回調べてたら、実はgemでfriendly_idてのがあり、それでも実装できるらしいです。でもまあ、せっかくto_param覚えたし、gemの仕組みを理解するよりこっちの方が仕組みを理解するのが簡単そうだったのでこっちを採用します。

##参考にしたの

【Rails】to_paramでURLをUser.nameにする
https://remonote.jp/rails-to-param-url-user-name

15
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?