TimeCrowdでは招待URLを発行してメンバーを招待することが出来ます。その際に相手に招待URLを連絡するのですが、あまりに長いので文章内に埋め込むとインパクトが強すぎるという要望がありました。
そこで今回は招待URLに対して短縮URLを使用して見やすい形にしたいと思います。
無事に台湾でドラゴンボートの試合を終えて帰国した旅してきたエンジニアの三宅です。
Shortenの導入
今回はShortenというgemを利用して機能を実装することにしました。
Installationを参照しながら進めます。
# Gemfile
gem 'shortener'
bin/rails generate shortener
bin/rake db:migrate
Running via Spring preloader in process 16007
== 20180706014530 CreateShortenedUrlsTable: migrating =========================
-- create_table(:shortened_urls)
-> 0.0302s
-- add_index(:shortened_urls, :unique_key, {:unique=>true})
-> 0.0293s
-- add_index(:shortened_urls, :url, {:length=>2083})
rake aborted!
StandardError: An error has occurred, all later migrations canceled:
Mysql2::Error: Specified key was too long; max key length is 3072 bytes: CREATE INDEX `index_shortened_urls_on_url` ON `shortened_urls` (`url`(2083))
/Users/kotamiyake/code/ruffnote/timecrowd/db/migrate/20180706014530_create_shortened_urls_table.rb:29:in `change'
-e:1:in `'
ActiveRecord::StatementInvalid: Mysql2::Error: Specified key was too long; max key length is 3072 bytes: CREATE INDEX `index_shortened_urls_on_url` ON `shortened_urls` (`url`(2083))
/Users/kotamiyake/code/ruffnote/timecrowd/db/migrate/20180706014530_create_shortened_urls_table.rb:29:in `change'
-e:1:in `'
Mysql2::Error: Specified key was too long; max key length is 3072 bytes
/Users/kotamiyake/code/ruffnote/timecrowd/db/migrate/20180706014530_create_shortened_urls_table.rb:29:in `change'
-e:1:in `'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
マイグレーションでエラーが発生してしまいました。
どうやらカラムインデックスの最大キー長が長すぎるようです。
MySQLでは基本的には単一カラムインデックスの最大キー長は767バイトまで作成できます。特定の条件ではインデックスの最大キー長を3072バイトまで拡張することができます。
TimeCrowdでは最大キー長3072バイトまで拡張しているのですが、それでも足りなかったようです。
マイグレーションファイルを見てみましょう。
class CreateShortenedUrlsTable < ActiveRecord::Migration[4.2]
def change
create_table :shortened_urls do |t|
# we can link this to a user for interesting things
t.integer :owner_id
t.string :owner_type, limit: 20
# the real url that we will redirect to
t.text :url, null: false, length: 2083
# the unique key
t.string :unique_key, limit: 10, null: false
# a category to help categorize shortened urls
t.string :category
# how many times the link has been clicked
t.integer :use_count, null: false, default: 0
# valid until date for expirable urls
t.datetime :expires_at
t.timestamps
end
# we will lookup the links in the db by key, urls and owners.
# also make sure the unique keys are actually unique
add_index :shortened_urls, :unique_key, unique: true
add_index :shortened_urls, :url, length: 2083
add_index :shortened_urls, [:owner_id, :owner_type]
add_index :shortened_urls, :category
end
end
urlのlengthがカラム長、キー長共に2083文字となっています。
TimeCrowdでは文字コードにutf8mb4を採用しているので、カラム長、キー長を768文字にする必要があります。
幸い招待URLの長さは768文字を超えないので768文字に変更して、再度マイグレーションを実行します。
bin/rake db:migrate
Running via Spring preloader in process 37580
== 20180706014530 CreateShortenedUrlsTable: migrating =========================
-- create_table(:shortened_urls)
-> 0.0339s
-- add_index(:shortened_urls, :unique_key, {:unique=>true})
-> 0.0286s
-- add_index(:shortened_urls, :url, {:length=>768})
-> 0.0217s
-- add_index(:shortened_urls, [:owner_id, :owner_type])
-> 0.0275s
-- add_index(:shortened_urls, :category)
-> 0.0278s
== 20180706014530 CreateShortenedUrlsTable: migrated (0.1404s) ================
無事マイグレーションに成功しました。
短縮URLを使ってアクセス
まずは短縮URLからリダイレクトするためのルーティングを設定します。
get '/s/:id' => 'shortener/shortened_urls#show'
例ではルート直下に設定していましたが、短縮URLということでnamespaceとして/s/で区切ることにしました。
それでは次に短縮URLを発行してみたいと思います。
pry(main)> shortened_url = Shortener::ShortenedUrl.generate("https://timecrowd.net")
pry(main)> shortened_url.unique_key
=> "5wr8x"
では開発環境を使って短縮URLにアクセスしてみます。
http://localhost:3000/s/5wr8x
正常にリダイレクトすることが確認できました。
実際の画面で表示すると以下のようになります。
だいぶスッキリしましたね!
これで今までの長々としたURLをチャットやメールに添付する必要はなくなります。
まだこちらの機能はリリースしていませんが、近々リリースできるよう鋭意開発中ですので乞うご期待ください!
参考記事
第32回 InnoDBインデックスの最大キー長について:MySQL道普請便り|gihyo.jp … 技術評論社
http://gihyo.jp/dev/serial/01/mysql-road-construction-news/0032