Sinatra MongoDB Powered by Rabbit 2.1.2 and COZMIXNG
Sinatra と MongoDB 今回は Sinatra で MongoDB の操作を体験してみます 進捗に合わせて ドライバから Ruby で使える便利な ORM の紹介をします
Sinatra と MongoDB まずは初回なので Sinatra の基本からおさらいします
Hello world require 'sinatra' get '/' do "Hello, world!"
Hello world これは最も単純で有名な例ですが HTTP ヘッダを見てみましょう
Hello world ブラウザにはこういったヘッダーの情報を確かめる機能が備わっています その中でも重要なのが Request Method が GET であるという点です
HTTP Method これらのGETはHTTP Methodの一 部で 主にGETやPOSTが使われて います GET POST PUT DELE OPTIO TE N 何か見せる 何か生成する 何か更新する 何か削除する 何か満たす http://www.sinatrarb.com/intro-
POST では 次に post メソッドを試してみましょう require 'sinatra' post '/' do "Hello world!"
POST $ curl -X POST http://localhost:4567 POST コマンドを送信する方法
POST require 'sinatra' post '/' do "Hello world!" get '/' do erb <<EOF <form method='post' action='/'> <input type='submit' /> </form> EOF
POST ただし POST コマンドは通常では値の取得には用いません値を取得するときには GET を使います
MongoDB それでは実際にデータを保存するために MongoDB を利用しましょう
MongoDB インストールは行ってきましたか? $ which mongo $ which mongod
MongoDB まずは基本から $ mongo # クライアントの起動 > db # 現在のテーブル > use foo # foo をこれから使用 ( この時点ではまだ書き込まれていない ) > db # foo
MongoDB 外部接続の場合 $ mongo <hostname>:<port>/<table> -u <user> -p <password>
MongoDB まずは基本から > a = { name: 'Frank' } > db.sinatradb.insert(a) # 挿入 > show collections # sinatradb が書き込まれている > db.sinatradb.find() # 検索
MongoDB $ gem install mongo bson_ext bson_ext は mongo ライブラリに BSON 形式をサポートさせるための Gem です
MongoDB require 'sinatra' require 'mongo' include Mongo # Mongo の省略 configure do conn = MongoClient.new # localhost:27017 set connection: conn set db: conn.db('foo') # use foo get '/collections' do settings.db.collection_names.to_a.to_s # show collections と同じ
MongoDB require 'sinatra' require 'mongo' get '/' do # ドキュメント全体 settings.db['sinatradb'].find.to_a.to_s get '/:collection' do col # name が collection であるものをひとつ返す settings.db['sinatradb'].find_one(name: col).to_s
Haml テンプレートエンジンを使います $ gem install haml
Haml テンプレートエンジンを使います get '/' do haml :index
Haml./views/index.haml %form{action: '/', method: 'post'} %input{name: 'name', placeholder: 'name'} %input{type: 'submit'} 注意 : インデント幅はソフトスペース 2 です
MongoDB Sinatra からデータを登録します post '/' do bson_id = settings.db['sinatradb'].insert(params) bson_id.to_s この ID をコピーしてください
MongoDB BSON_ID からの検索? get '/id/:id' do id settings.db['sinatradb'].find(id).to_s
MongoDB BSON_ID からの検索 get '/id/:id' do id id = BSON::ObjectId.from_string(id) settings.db['sinatradb'].find(id).to_s
ヘルパー helpers do def foo 'baz'
または ヘルパー module Foo def foo 'baz' helpers Foo
ヘルパー # Haml, Slim = foo # ERB <%= foo %>
ヘルパー helpers do def find_by_name(name) settings.db['sinatradb'].find(name: name) def find_all settings.db['sinatradb'].find
ヘルパー = find_by_name.count %ul - find_by_name('frank').each do document %li= document['_id']
データの更新./views/index.haml %ul - find_all.each do document %li %a{href: "/update/#{document['_id']}"}= document['name']
ルーティング データの更新 get '/update/:id' do id @id = id haml :update
データの更新./views/update.haml %h1= find_by_id(@id) %form{action: "/update/#{@id}", method: 'post'} %input{name: 'name', value: find_by_id(@id)} %input{type: 'submit'}
ヘルパー データの更新 helpers do def find_by_id(id) id = BSON::ObjectId.from_string(id) settings.db['sinatradb'].find_one(id)['name']
データの更新 post '/update/:id' do id id = BSON::ObjectId.from_string(id) settings.db['sinatradb'].update({_id: id}, params) redirect '/'
データの削除./views/index.haml %ul - find_all.each do document %li = document['name'] %a{href: "/update/#{document['_id']}"} 更新 %a{href: "/delete/#{document['_id']}"} 削除
ルーティング データの削除 get '/delete/:id' do id id = BSON::ObjectId.from_string(id) settings.db['sinatradb'].remove(_id: id) redirect '/' 本来は POST を使うのですが 今回は操作感を重視して GET を使います
データの追加 はじめに追加した部分も redirect に書き換えましょう post '/' do settings.db['sinatradb'].insert(params) redirect '/'
未完了と完了 ようやく ToDo リストを作り始める基礎をおさえることができました 今度はそれぞれのタスクが完了しているかどうかを判断させます
未完了と完了./views/index.haml %ul - find_all.each do document %li - if document['status'] %s= document['name'] %a{href: "/delete/#{document['_id']}"} 削除 - else = document['name'] %a{href: "/done/#{document['_id']}"} 完了 %a{href: "/update/#{document['_id']}"} 更新 %a{href: "/delete/#{document['_id']}"} 削除
未完了と完了 = document['status'].class.to_s #=> NilClass nil( 空白 ) が返ってくるのでエラーにならないあとから値を変更するのが容易
ルーティング 未完了と完了 get '/done/:id' do id id = BSON::ObjectId.from_string(id) settings.db['sinatradb'].update( {_id: id}, { "$set" => {status: Time.now} } ) redirect '/'
以上 今回はとても単純な ToDo リストを作成してみました次回以降は Ajax を絡めて もっと高機能なアプリケーションを作成しましょう Powered by Rabbit 2.1.2 and COZMIXNG