Railsでリクルートの1dayjobの問題を実装してみる。
あけましておめでとうございます。 久しぶりにブログを書きます。
最近はこたつに入ってだらだらとRuby on Railsの本を読んでみたり、 フロントエンドのモダンな開発環境の勉強をしてホームページを作ってみたり、 競技プログラミングに興味を持ってC++の勉強をしたりしていました。
先月、株式会社リクルートホールディングスのウィンターインターンシップの選考のひとつだった1dayjobを受けて来ました。 そこで課せられた課題は「URL短縮サービスを作れ」という物でした。Twitterなどでよく見る「http://goo.gl/tet7pg」みたいな奴ですね。
これを当時はPythonとFlaskで作って提出したのですが、 周りの参加者の話をきくとRailsで作ったという人が多かったのでRailsの復習もかねて作ってみようと思い立ちました。
要件
詳細な要件は色々ありましたが、忘れてしまったのでざっくりと。
URLを短縮させる
以下のようなリクエストがあったときに
$ curl http://{url短縮サービス}/api/v1/shortenurl -H 'Content-\ Type: application/json' -d '{"LongUrl": "http://www.google.co.jp/"}'
以下のようなレスポンスを返す。
{ "Created": 1418454534, "LongUrl": "http://www.google.co.jp/", "ShortUrl": "http://{url短縮サービス}/4" }
短縮したURLを使って元のURLにアクセスさせる
以下のようなリクエストがあったときに、
$ curl http://{url短縮サービス}/4
以下のようなレスポンスを返す。
<HTML> <HEAD> <TITLE>Moved Permanently</TITLE> </HEAD> <BODY> <H1>Moved Permanently</H1> The document has moved <A HREF="http://www.google.co.jp/">here</A>. </BODY> </HTML>
実装してみる
まずは新規アプリケーションの作成
Railsのインストールとかは省略します。
shorturlという名前でアプリケーションを作成します。
$ rails new shorturl $ cd shorturl
modelの作成
簡単にデータベースに短縮前のURLを保持しておき、 そのインデックスを短縮後のURLにすれば良いでしょう。 今回は省略しますが本番ではURLをもっと短くする為にインデックスを[0-9a-zA-Z]の62種の文字を使い、 10進数から62進数への基数変換を行いました。
ではモデルを作ります。
$ rails generate model url longurl:text invoke active_record create db/migrate/20150103080833_create_urls.rb create app/models/url.rb invoke test_unit create test/models/url_test.rb create test/fixtures/urls.yml $ rake db:migrate == 20150103080833 CreateUrls: migrating ======================================= -- create_table(:urls) -> 0.0016s == 20150103080833 CreateUrls: migrated (0.0017s) ==============================
これでurlsというテーブルが作成されました。
以下のようにrails dbconsole
を使う事でデータベースのコンソールが立ち上がります。
$ rails dbconsole SQLite version 3.7.13 2012-07-17 17:46:21 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> .schema urls CREATE TABLE "urls" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "longurl" text, "created_at" datetime, "updated_at" datetime);
コントローラーの作成
controller一つでやってしまいます。 今回は使いませんが、綺麗な形でTwitterみたいなバージョンのあるAPIを実装したいならGrape[1]というgemを使うと楽な様です。
$ rails generate controller main
app/controllers/main_controller.rb
# coding: utf-8 class MainController < ApplicationController skip_before_filter :verify_authenticity_token ,:only => [:shortenurl] def url2dict(url_obj) return ['Created' => url_obj.created_at.to_i, 'LongUrl' => url_obj.longurl, 'ShortUrl' => 'http://localhost:3000/' + url_obj.id.to_s] end # urlを短縮させる def shortenurl longurl = params[:main][:LongUrl] fetched = Url.find_by(:longurl => longurl) # もし存在すればそのまま返す if fetched render json: url2dict(fetched) return end # 存在しなければ登録し、返す。 url = Url.new(:longurl => longurl) url.save! render json: url2dict(url) return end def index fetched = Url.find_by(:id => params[:id]) @longurl = fetched.longurl render(:layout => false) end end
skip_before_filter :verify_authenticity_token ,:only => [:shortenurl]
としないとpostする際エラーが出ました。
viewの作成
短縮されたアドレスでアクセスされた時にリダイレクトさせる為のhtmlページを作成します。
app/views/main/index.html.erb
<HTML> <HEAD> <TITLE>Moved Permanently</TITLE> </HEAD> <BODY> <H1>Moved Permanently</H1> The document has moved <A HREF="<%= @longurl %>">here</A>. </BODY> </HTML>
routingを行う
Rails.application.routes.draw do post 'api/v1/shortenurl/' => 'main#shortenurl' get '/:id' => 'main#index' end
動作確認を行う
$ rails server => Booting WEBrick => Rails 4.1.8 application starting in development on http://0.0.0.0:3000 => Run `rails server -h` for more startup options => Notice: server is listening on all interfaces (0.0.0.0). Consider using 127.0.0.1 (--binding option) => Ctrl-C to shutdown server [2015-01-04 20:48:56] INFO WEBrick 1.3.1 [2015-01-04 20:48:56] INFO ruby 2.1.2 (2014-05-08) [x86_64-darwin13.0] [2015-01-04 20:48:56] INFO WEBrick::HTTPServer#start: pid=32252 port=3000
これでサーバが立ち上がりました。http://localhost:3000/でアクセスする事が出来ます。
短縮アドレスの登録
$ curl http://127.0.0.1:3000/api/v1/shortenurl -H 'Content-Type: application/json' -d '{"LongUrl": "http://sachaos.net/"}' [{"Created":1420370841,"LongUrl":"http://sachaos.net/","ShortUrl":"http://localhost:3000/1"}]%
短縮アドレスにアクセス
$ curl http://127.0.0.1:3000/1 <HTML> <HEAD> <TITLE>Moved Permanently</TITLE> </HEAD> <BODY> <H1>Moved Permanently</H1> The document has moved <A HREF="http://sachaos.net/">here</A>. </BODY> </HTML>
完成です。