Ruby On Rails とは?
- Ruby On Rails (以下、Rails)についてはこちらをご確認下さい。
UUID とは何か?
- UUID とは Universally Unique IDentifier のことで普遍的な一意の識別子のことを指す。
なぜ Rails で主キーに UUID を使用するのか?
- 例えば MySQL であれば主キーに AUTO_INCREMENT を使用するケースが多いと思いますが、そうすると該当ページへアクセスする場合、 Rails では URL が
https://example.com/users/1
というようになってしまい、 1 の部分が 2 だったらどうなのか、 10、100 だったらどうなのか・・・というような感じで簡単に推測されてしまいます。 - cancancan や pundit のような権限管理 gem を使用することで URL が推測されてもアクセス不可にさせることもできますが、認証/認可していることが前提となってしまう為、例えばログインはしなくてもいいけれど URL を知っている人だけにアクセスさせたいというようなことができません。
- そこで、今回は URL を知っている人だけにアクセスさせることを実現できるようにしつつ、URL を推測できないようにする為に主キーに UUID を使用します。
該当ページへアクセスする場合の URL がhttps://example.com/users/9332ba51-d7de-4661-acb9-a1b481917dd4
のようになり、推測不可能になります。
ソースコード
-
app/models/concerns/uuid_module.rb を作成して下記のように記述する
- 各々のモデルで使用したい為、モジュール化して concerns/ 配下に配置
- 何らかの理由で id が存在しないテーブルに対して create してもエラーにならないように
has_attribute?(:id)
を行い、 id が存在する場合のみ uuid を生成する - 滅多にないが生成された id が既に存在した場合は再生成する
module UuidModule
extend ActiveSupport::Concern
included do
before_create :generate, if: -> { has_attribute?(:id) }
end
def generate
self.id ||= loop do
uuid = SecureRandom.uuid
break uuid unless self.class.exists?(id: uuid)
end
end
end
- app/models/application_record.rb の上部へ include UuidModule を記述
class ApplicationRecord < ActiveRecord::Base
include UuidModule
# ...
end
留意事項
- マイグレーションの際には主キーは必ず36文字の文字列が保存可能な型にする
class CreateUsers < ActiveRecord::Migration[7.0]
def change
create_table :users, id: :string, limit: 36 do |t|
# ...
end
end
end
まとめ
- 上記のようにすることでデータ新規保存の際には id が推測不可能な文字列になり、該当ページへアクセスする際には冒頭述べたような
https://example.com/users/9332ba51-d7de-4661-acb9-a1b481917dd4
になります。- 該当ページがない場合は
$ rails g scaffold_controller user
などで作成後、レコードを新規作成した上で詳細ページへアクセスしてみて下さい。
- 該当ページがない場合は