Rails等でURLにランダムな文字列を使いたい時のアレ

  • 115
    いいね
  • 3
    コメント
この記事は最終更新日から1年以上が経過しています。

http://example.com/samples/lk23Affa

みたいなURLにランダムな文字列を使いたい時ありますよね。
上記がRailsのActiveResourceのRESTfulっぽいルーティングだとしたら、
samplesというresourceのid=lk23Affaにアクセスしてることになりますね。

ActiveRecordだと普通にテーブルを作成していったら、
主キーのidは、auto_incrementのただの数字連番になってしまいます。
また、文字列の主キーを設定するのが結構面倒なので *1、
access_tokenというようなカラムで別に値を保持しておくのがよさそうです。

db/migrate/xxx_create_samples.rb
class CreateSamples < ActiveRecord::Migration
  def change
    create_table :samples do |t|
      t.string :access_token, :null => false, :limit => 6
      t.timestamps
    end
    add_index :samples, :access_token, :unique => true
  end
end
app/model/sample.rb
class Sample < ActiveRecord::Base
  validates_uniqueness_of :access_token
  validates_presence_of :access_token
  after_initialize :set_access_token

  private
  def set_access_token
    self.access_token = self.access_token.blank? ? generate_access_token : self.access_token
  end                                                                                                                                                                                          

  def generate_access_token
    tmp_token = SecureRandom.urlsafe_base64(6)
    self.class.where(:access_token => tmp_token).blank? ? tmp_token : generate_access_token
  end
end
config/routes.rb
  get '/samples/:access_token' => 'samples#show'
app/controller/samples_controller.rb
class SamplesController < ActionController::Base
  def  show
    @sample = Sample.where(:access_token => params[:access_token]).first
  end
end

こんな感じに書いたらユニークな文字列をURLに含めて、
リソースを表示させることが出来るかと思います!
とりあえず、access_tokenって名づけましたが、もっと一般的に使われてる良い名前があったら教えて欲しいです。

追記:2012.01.02
@tkawa さんの作った https://github.com/tkawa/resources_id_replace
を使うと、綺麗にRoutingが出来るようになるようです。
詳しくは↓のコメント欄をどうぞ。

*1: MySQLでは、migrationファイル中にexecuteメソッドを使ってSQLを直に書き、alter tableでprimary keyを追加できるけど、sqlite3では、alter tableこそ使えるものの、primary keyを追加できないという問題あり。

参考ページ:
- URL短縮サービスで使われるような、ランダムでユニークなアクセストークンを発行するプラグイン - 篳篥日記
- ActiveRecord で id 以外のカラムをプライマリキーにして、しかも型が int じゃないときの話 - 何かの記録
- SQLite Query Language: ALTER TABLE