mongoを使ってurl shortenerつくる
mongoぇ
基本的な使い方はわかったけど、アプリどう組み込むのかの経験をつまぬば。。 簡単そうなアプリケーションとして、url shortenerを作ってみる。
rubyでmongo
とりあえず、rubyで使えるかをためす。 ちゃんと、利用できるgemがあるみたい。。
$ gem i mongo
$ gem i bson_ext
bson_extは
For optimal performance, use of the BSON extension is recommended.
っていわれたので、入れた。 早速使ってみる。
$ pry
> connect = Mongo::Connection.new
> connect.database_names
=> ["local", "mydb", "test"]
データベースの選択
> connect.db("mydb")
コレクションの選択
> coll = db.collection('things')
コレクションの表示
> coll.find.each { |doc| puts doc }
{"_id"=>BSON::ObjectId('514d9d5d41e70994840e6c01'), "name"=>"mongo"}
{"_id"=>BSON::ObjectId('514d9d6541e70994840e6c02'), "x"=>3.0}
{"_id"=>BSON::ObjectId('514d9f6c41e70994840e6c03'), "x"=>1.0, "y"=>1.0}
{"_id"=>BSON::ObjectId('514d9f6c41e70994840e6c04'), "x"=>1.0, "y"=>2.0}
{"_id"=>BSON::ObjectId('514d9f6c41e70994840e6c05'), "x"=>1.0, "y"=>3.0}
{"_id"=>BSON::ObjectId('514d9f6c41e70994840e6c06'), "x"=>1.0, "y"=>4.0}
{"_id"=>BSON::ObjectId('514d9f6c41e70994840e6c07'), "x"=>1.0, "y"=>5.0}
{"_id"=>BSON::ObjectId('514d9f6c41e70994840e6c08'), "x"=>1.0, "y"=>6.0}
{"_id"=>BSON::ObjectId('514d9f6c41e70994840e6c09'), "x"=>1.0, "y"=>7.0}
{"_id"=>BSON::ObjectId('514d9f6c41e70994840e6c0a'), "x"=>1.0, "y"=>8.0}
{"_id"=>BSON::ObjectId('514d9f6c41e70994840e6c0b'), "x"=>1.0, "y"=>9.0}
ドキュメントの挿入
> doc = { x: 1, y: 10 }
> id = coll.insert(doc)
基本はOK。。
url shortener
urlを受け取って、短くしたurlを返すアプリ。 代表的なサービスはbit.ly とかgoo.glとか。
仕様
基本的にコマンドラインからも利用できて、
登録 (POST) :
curl -d url="http://www.google.com/search?q=hello" http://localhost:4567/
> http://localhost:4567/x12d
参照 (GET) :
curl http://localhost:4567/x12d
> http://www.google.com/search?q=hello
見たいなかんじで参照できる。
4桁の数字で短くしてくれるようにする。 小文字アルファベットと数字を使えば、 (26 + 10) = 36文字 364 = 1679616
168万件は許容できる. リリースするようなサービスじゃないので十分。
短縮urlの作成
シンプルに乱数を作る
def strand(n)
char = (("a".."z").to_a + (0..9).to_a)
n.times.collect { |i| char.shuffle[0] }.join
end
アプリを作る
ひな形作成
$ bundle gem shurl
ディレクトリ
$ tree .
.
├── Gemfile
├── README.md
├── Rakefile
├── app.rb
├── config.ru
├── lib
│ ├── shurl
│ │ └── version.rb
│ └── shurl.rb
└── shurl.gemspec
ロジック部分
mongodbにurlデータとそのハッシュ値を入れるだけ。
require 'mongo'
module Shurl
class Model
# mongo db setup
def initialize()
connect = Mongo::Connection.new
db = connect.db("shurl")
@coll = db.collection("urls")
end
def strand(n)
char = (("a".."z").to_a + (0..9).to_a)
n.times.collect { |i| char.shuffle[0].to_s }.join
end
def to_shorturl(request, code)
if request.port == 80
request.scheme.to_s + "://" \
+ request.host.to_s + "/" \
+ code.to_s
else
request.scheme.to_s + "://" \
+ request.host.to_s + ":" + request.port.to_s + "/" \
+ code.to_s
end
end
def to_longurl(code)
doc = @coll.find_one({code: code})
doc["url"] if doc != nil
end
def find_or_create_url(request, longurl)
doc = @coll.find_one({url: longurl})
# create
if doc == nil
code = strand(4)
doc = { "url" => longurl, "code" => code }
@coll.insert(doc)
end
to_shorturl(request, doc["code"])
end
end
end
ルーティング部分
require 'sinatra'
require 'shurl'
#
# routing
#
shurl = Shurl::Model.new
get '/' do
"please post url"
end
# show raw url
get '/s/:code' do
url = shurl.to_longurl(params[:code])
if url == nil
"no url found"
else
url
end
end
# redirect
get '/:code' do
url = shurl.to_longurl(params[:code])
if url == nil
redirect '/'
else
redirect url
end
end
# shorten
post '/' do
if params[:url] == nil
halt 400, "please specify url param"
else
short_url = shurl.find_or_create_url(request, params[:url])
short_url
end
end
実行
$ bundle install --path vendor/install
$ bundle exec rackup
試す
長いURLの記録
$ LONG_URL="https://maps.google.co.jp/maps?q=35.710158,139.812784&num=1&vpsrc=0&hl=ja&brcurrent=3,0x60188ed7f6bdc0a3:0xaa8fcf79ad1e5576,0&ie=UTF8&ll=35.71258,139.812741&spn=0.010088,0.01781&t=m&z=16&iwloc=A"
$ curl --data-urlencode url="$LONG_URL" http://localhost:4006/
http://localhost:4006/tklk
短縮urlのアクセス
$ curl -L http://localhost:4006/tklk
リンク先の中身を見る
$ curl -L http://localhost:4006/s/tklk
https://maps.google.co.jp/maps?q=35.710158,139.812784&num=1&vpsrc=0&hl=ja&brcurrent=3,0x60188ed7f6bdc0a3:0xaa8fcf79ad1e5576,0&ie=UTF8&ll=35.71258,139.812741&spn=0.010088,0.01781&t=m&z=16&iwloc=A
ポストしつつ、飛ぶ。
$ curl -L `curl --data-urlencode url="$LONG_URL" http://localhost:4006/`
さくっとかけていいね!
せっかくなので
githubにあげた。