sinatra + heroku + DataMapper + postgreSQL

こんばんは。麺処まつば副店長です。
いやー空が禍々しいですね(雷)

さて、今日は heroku + sinatra で、DB を扱う部分をやってみようと思います。
あとから詳しくかきますけど、今回は postgreSQL と DataMapper 使います。

そんなわけで、今回のメニューはコチラです。

フォームから入力された文字列の最後に
勝手に「。。。多分。」と付加することにより
そこはかとなく胡散臭い文字列に仕立て上げた上でDBに保存する。
かつ保存された、そこはかとなく胡散臭い文字列を表示する。

今回の作り方はこのような流れです。

  • postgreSQL の用意
  • DataMapper の用意
  • bundler
  • migrate
  • モデルの用意
  • app.rb の用意
  • view の用意
  • ローカル動作確認
  • heroku に反映

それでは作っていきましょう。

postgreSQL の用意

heroku で使える DB は、標準で PostgreSQL や、あと MySQL
それから巷で話題の NoSQL なんかも扱えるみたいですが、
今回は、とりあえず、ということで標準の postgreSQL を使ってみようと思います。
(NoSQL は個人的に非常に気になる材料なので、後日やります。(宣言))

まずは、ローカルに PostgreSQL をいれちゃいましょう。
これは、環境によってインストール方法が違うと思うので特に書きません。…が、
副店長の Mac に postgreSQL 入れた時の記録でしたらこちらです
http://d.hatena.ne.jp/noodles_mtb/20110805/1312509838

DataMapper の用意

sinatra はモデルの機能持ってないので、どっかから調達してきます。
ActiveRecord とか、DataMapper とか、Sequelとか色々あるみたいですけど
今回は DataMapper 使ってみようと思います。
まず、DataMapper と、その postgreSQL のアダプター、
それから migrate もお願いしようと思うのでそれも。

$ gem install dm-core
$ gem install dm-postgres-adapter
$ gem install dm-migrations

DataMapper本家→http://datamapper.org/getting-started.html

bundler

DataMapper とか新しく入れたので、bundle する必要があります。
Gemfile

  1 source :rubygems
  2 gem 'sinatra'
  3 gem 'haml'
  4 gem 'dm-core'
  5 gem 'dm-postgres-adapter'
  6 gem 'dm-migrations'

4〜6行目が DataMapper 系の記述です。
これができたら、bundle しましょう

$ bundle update

これで DataMapper を使う準備は整いました。

モデルの用意

それでは、model を書いていきます。
今回は、フォームから入力されたテキストを胡散臭くして
DBに保存するだけなので、大したことは書きません。
word.rb

  1 require 'rubygems'
  2 require 'dm-core'
  3 
  4 class Word
  5 
  6   include DataMapper::Resource
  7   property :id, Serial
  8   property :msg, String
  9 
 10 end

これだけです。

migrate

モデルを作りましたが、肝心の DB がないとダメですね。
まず、postgreSQL に DB つくっといてください。

そしたら、dm-migrations を使って migrate をしましょう。
DataMapper で migrate する場合には、自動と手動の2種類があるようです。
(→http://route477.net/ramaze/?DataMapper
今回は自動の migrate を使ってみます。
(自動の場合、model 内に定義した propery をもとにmigrate するようです)
Rakefile

  1 require 'dm-core'
  2 require 'dm-migrations'
  3 require './word.rb'
  4 
  5 task 'db:migrate' do
  6   DataMapper.setup(:default, ENV['DATABASE_URL'] || 'postgres://user_name:user_password@localhost/db_name')
  7   DataMapper.auto_upgrade!
  8   self
  9 end

1〜2行目で、dm-core と dm-migrateions を使う宣言
3行目は、自作のモデルを呼んでいます(migrate の対象)
5〜9行目で、「db:migrate」の定義をしています。
6行目は、DataMapperを使ってDBに接続にいきます。6行目のコレ↓ですが、

ENV['DATABASE_URL'] || 'postgres://user_name:user_password@localhost/db_name')

これは、前者があれば前者、なければ後者につなぎにいきます。
ここでは、前者は heroku 上で使う DB 、これがなけば後者につなぎにいきます。
ここでは前者がないので後者、つまりローカルの postgreSQL に接続します。
それから、7行目の「auto_upgrade!」
これは、既存テーブルのデータを保持したまま自動 migration を行うものです。
「auto_migrate!」というのもありますが、既存テーブルのデータはなくなってしまいます。
場合に合わせてご利用ください。

※他の方が Rakefile をどういう風に書いてるのか拝見したところ
Rakefile の中で、別の Ruby のプログラムを呼んで
そこから migrate している方が多いようだったのですが
副店長はめんどks……げほげほ…
えー…、今回はお手軽版ということで、このように書いています。

それでは、migrate してみましょう。

$ rake db:migrate

きっと、db_name で指定した DB に新しくテーブルが追加されていると思います。

app.rbの用意

上記までの手順で、モデルを使う準備が整いました。
では、それを使っていきましょう。
app.rb

  1 #coding:utf-8
  2 
  3 require 'rubygems'
  4 require 'sinatra'
  5 require 'haml'
  6 require 'dm-core'
  7 require './word.rb'
  8 
  9 configure :production do
 10 end
 11 
 12 DataMapper.setup(:default, ENV['DATABASE_URL'] || 'postgres://user_name:user_password@localhost/db_name')
 13 
 14 get '/' do
 15   haml :index
 16 end # end [post /]
 17 
 18 post '/' do
 19   str = params[:str] + "。。。多分。"
 20   Word.create(:msg => str)
 21 
 22   @messages = Word.all(:order => [:id.desc])
 23   haml :index
 24 end # end [post /]

大したことはやってません。
6行目で dm-core を require
7行目で 自作の model ( word.rb ) を require
12行目で DB 接続設定。です。

18〜24行目で、post の定義をしています
19行目で 入力された文字列を胡散臭く加工。
20行目で DB に INSERT
22行目で DB に保存された word の一覧を取得しています。
はい、本当に大したことはしていません。

view の用意。

おっと。これでできたと思っていましたが
view のことをすっかり忘れておりました。
views/index.haml

  1 !!! XML
  2 !!!
  3 %html
  4   %head
  5     %meta{ :content=>"text/html", :charset=>"utf-8" }
  6     %title 胡散臭いよー
  7   %body
  8     #main
  9       %h1 胡散臭いよー
 10       %div 胡散臭い文字列なら任せてください。
 11       %form{:action=>"/", :method=>"post"}
 12         %input{:type=>"texfield",:name=>"str"}
 13         %input{:type=>"submit", :value=>"send"}
 14       - if @messages && !@messages.blank?
 15         - for msg in @messages
 16           %div= msg['msg']

本気で大したことしてないので、説明は省略します。

ローカルで動作確認

さて、できたかどうかためしてみましょう

$ rackup

http://localhost:9292/
で入力した任意の文字列が胡散臭くなってかえってきたら成功です。
→あぁぁ…胡散臭い。成功です。

heroku に反映

ローカルで確認できたので、heroku 上にあげてしまいましょう。
まずは、ファイルを上げてしまいます。

$ git commit -a -c "usan kusai"
$ git push heroku master

次に DB です。
rails 以外のプロジェクトの場合、デフォルトでDBが用意されてないそうなので
使う場合はこんなコマンドをたたいた上で migrate します

$ heroku addons:add shared-databasee
$ heroku rake db:migrate

そして、動作確認

$ heroku open

うさんくさくなりましたか?
→すっごい胡散臭いです。成功です。

これで、heroku をなんとなく使える気がしてきました。
どんどん胡散臭いものを作っていきましょう>自分