🆔

Rails初学者がUUIDを導入して学んだこと

に公開

Rails初学者がUUIDを導入して学んだこと

はじめに

現在、未経験からWebエンジニアを目指してRuby on Railsを学習しています。

ポートフォリオとして開発しているコーデ記録アプリ「Stylog」で、投稿URLにUUIDを導入しました。

最初は、

「なぜUUIDを使うの?」

という状態でしたが、実際に導入してみると、

  • 公開URLの安全性
  • Railsのルーティング
  • to_param

など、多くの学びがありました。

この記事では、自分がUUIDを導入して理解したことをまとめます。


UUIDとは?

UUID(Universally Unique Identifier)は、世界中で重複しないことを目的とした識別子です。

例えば、通常のIDだと

/posts/1
/posts/2
/posts/3

ですが、UUIDだと

/posts/550e8400-e29b-41d4-a716-446655440000

のようになります。


なぜUUIDを導入したのか

最初は普通にidを使っていました。

/posts/1
/posts/2
/posts/3

しかしこれだと、

  • 件数を推測できる
  • 存在するURLを予測できる

という問題があります。

そこで、公開用IDとしてUUIDを利用することにしました。


実装方法

まずpostsテーブルにuuidカラムを追加しました。

add_column :posts, :uuid, :string
add_index :posts, :uuid, unique: true

モデルでは、

before_create :set_uuid

def to_param
  uuid
end

private

def set_uuid
  self.uuid ||= SecureRandom.uuid
end

を設定しました。


to_paramとは?

最初はこれがよく分かりませんでした。

Railsは通常、

post_path(post)

を書くと、

/posts/1

を生成します。

しかし、

def to_param
  uuid
end

を書くと、

/posts/550e8400-e29b-41d4-a716-446655440000

になります。

つまり、URLで利用する値を変更できる仕組みです。


ハマったこと①

URLはUUIDになったのに詳細画面が開かない

UUID導入後、URLは変わったのに投稿詳細ページが表示できなくなりました。

原因はコントローラでした。

変更前

@post = Post.find(params[:id])

変更後

@post = Post.find_by!(uuid: params[:uuid])

URLはUUIDなのに、DB検索はidで探していたためエラーになっていました。

UUIDを使う場合は、取得処理もUUIDに合わせて変更する必要があります。


ハマったこと②

Renderでuuidがnilのレコードが存在していた

途中でRender上でエラーが発生しました。

調べてみると、

uuid: nil

の投稿が存在していました。

原因はUUID導入前に作成されたレコードでした。

既存レコードにはUUIDが設定されていなかったため、

No route matches

のようなエラーが発生していました。

既存レコードにもUUIDを付与することで解決しました。


UUIDを導入して良かったこと

導入前は、

「なぜわざわざUUIDを使うのだろう?」

と思っていました。

しかし実装してみると、

  • URLから件数を推測されにくい
  • 公開用IDと内部IDを分離できる
  • 実務でも使われる設計を学べた

というメリットがありました。


学んだこと

UUID導入を通じて、単にURLを変更するだけではなく、

  • Railsのルーティング
  • to_param
  • findfind_by!
  • データ移行

など多くのことを学べました。

特に、

def to_param
  uuid
end

の仕組みを理解できたのは大きな収穫でした。


まとめ

最初は「なんとなくセキュリティのために使うもの」という認識でしたが、実際に導入してみるとRailsの仕組みそのものを理解する良い学習になりました。

もしRailsでポートフォリオを作っている方がいたら、UUIDの導入に挑戦してみるのもおすすめです。

実装だけでなく、

  • URL生成
  • レコード取得
  • データ移行

まで考えるきっかけになると思います。

最後まで読んでいただきありがとうございました。

Discussion