0

Sinatra+Haml+jQueryテンプレートにDataMapper版とMongoid版を追加した

去年作ったSinatra+Haml+jQuery入門のテンプレ、なにげにしょっちゅうアップデートしている。
内容は↑にも書いてあるがおみくじを引くだけの超単純なアプリだ。
新規プロジェクトを開始する時はコレをcloneして使うので、余計な物を付けない様にしている。

githubのリポジトリはここ https://github.com/shokai/sinatra-template


■使っている部品
今はこういう構成になっている

  • Ruby 1.8.7
  • Sinatra 1.3
  • Haml + sinatra-content-for
  • Sass
  • jQuery
  • foreman
  • bundler


master以外のブランチにmongoiddm-mysqlの2つがある。
それぞれDataMapper+MySQLと、Mongoid+MongoDBをバックエンドにしたやつ。


DataMapper+MySQL版はこんなファイル構成にしている。(Mongoidもほぼ同じ)
.
├── Gemfile # 必要なGEMを書いておくファイル。bundle installで一気にインストールされる。
├── Procfile # webサーバーと同時に起動するプロセスを書いておく
├── README.md
├── bin
│   ├── console.rb # DB接続してModel読み込んだ状態でIRBが起動する
│   ├── db_migrate.rb # DBを初期化するツール
│   └── db_upgrate.rb # model更新した時にDBスキーマを更新するツール
├── bootstrap.rb # これを読み込むとconfig.ymlを読んだりmodels/controllers/hellpersを一括読み込みしたりできる
├── config.ru # RackUp用の設定
├── config.yml # 設定ファイル
├── controllers # sinatraのルーティングメソッドを書いたファイルを入れるディレクトリ
│   ├── css.rb
│   └── main.rb
├── helpers # 便利関数を入れるディレクトリ
│   └── helper.rb
├── inits # DB接続とか、一番最初に実行すべき処理を書く
│   └── db.rb
├── models
│   └── omikuji.rb # DBのQueryとかを集約する
├── public
│   └── js
│   ├── jquery.js
│   └── main.js # index.hamlから読まれるJS
├── sample.config.yml # config.ymlにリネームして使う
└── views
├── index.haml # レイアウト抜きのメインコンテンツ部分
├── layout.haml # レイアウト
└── main.scss # cssのテンプレ


■DataMapperとMySQLを使う
MySQL版はこんなの(デモ)

MySQLのセットアップは以前書いた


この下に書いてある事はREADMEにも書いてある。


cloneしてくる
% git clone git://github.com/shokai/sinatra-template.git
% cd sinatra-template
% git branch -a
% git checkout -b dm-mysql remotes/origin/dm-mysql


設定
% cp sample.config.yml config.yml
config.ymlのMySQLのパスワード等を変更する


DB作る。最初のDB作る部分はログインして自分で作らないとならない。
% mysql -u your_name -p
mysql> create database sinatra_template
% ruby bin/db_migrate.rb
DB初期化するけどいいか?と訊かれるのでYesと答えよう。


起動
% gem install foreman bundler
% bundle install
% foreman start
http://localhost:8080 で起動する。


なんかすごい当たり前の話なんだけど、単純なWebアプリではなく、クローラとか色々と組み合わせたアプリを書くことが多い。
クローラとWebアプリが同じModelを読み込んで、同じ設定ファイルを読んで同じDBに接続するようにすると、綺麗に実装できる。

conosle.rbみたいな書き方をすると良い。

#!/usr/bin/env ruby
require 'rubygems'
require 'bundler/setup'
require File.dirname(__FILE__)+'/../bootstrap'
Bootstrap.init :inits, :models
これだけでDB接続してModelを読み込めるので、あとは普通に書けばいい。

設定ファイル(config.yml)の中身も、main.rbでやっているように
@title = Conf['title']
result = Conf['omikuji'].choice
みたいに取り出せる。

0

DataMapperでMySQLを使ってみる

MacにhomebrewでMySQL5.1.58インストールしたの続き。Ruby+DataMapperで使ってみた編。

gem install data_mapper dm-mysql-adapter

できたもの
https://github.com/shokai/datamapper-study

全体的にMongoidに似てる。Mongoidっぽい華麗なメソッドチェーンによるqueryができないっぽいのだけ残念・・
でもコード書いてて書き心地よかったし、SQL素人なのでORマッパーごしじゃないと怖くて使えない。


参考にしたページ
 

chatとかBBSみたいなのを作ろうと思ったがWebアプリにしないでCUIで使うやつにした。
ruby -Ku bin/post_comment.rb てすと
でMySQLに保存して、
ruby -Ku bin/show_comments.rb
で保存してあるのを読む。


ファイルの構造はこうなってる
そのうちsinatra templateに組み込むつもりで書いてみた。
.
├── Gemfile
├── Gemfile.lock
├── README.md
├── bin
│   ├── console.rb
│   ├── migrate.rb
│   ├── post_comment.rb
│   └── show_comments.rb
├── bootstrap.rb
├── config.yml
├── models
│   └── comment.rb
└── sample.config.yml
2 directories, 11 files


DBの設定 config.yml
db :
adapter : mysql
host : localhost
database : study
username : yourname
password : xxxxxxxx


設定に書いたstudyって名前のDBをmysqlに作って、migrateしておく。
mysql -u your_name -p
mysql> create database study;
ruby bin/migrate.rb


model定義 models/comment.rb
Mongoidに似てる。デフォルト値はlambdaで渡すと都度計算してくれる。
class Comment
include DataMapper::Resource
property :id, Serial
property :name, String, :required => true
property :body, String, :required => true
property :created_at, Time, :default => lambda{Time.now}

def to_s
"[#{name}] #{body} - #{created_at}"
end

def self.get_latests(num=10)
self.all(:order => [:id.desc], :limit => num)
end
end
クラスメソッドに「最近数件のコメントを取得」するメソッドを書いた。Query系はmodelに全部抽象的な名前で書いておいて、controllerとかにquery書かないようにすると綺麗になるし、modelだけで単体テストもできるようになる。



設定読み込んでMySQLに接続する
bootstrap.rb
#!/usr/bin/env ruby
require 'rubygems'
require 'bundler/setup'
Bundler.require
require 'yaml'

begin
@@conf = YAML::load open(File.dirname(__FILE__)+'/config.yml').read
rescue => e
STDERR.puts e
STDERR.puts "config.yml load error!!"
exit 1
end

DataMapper.setup(:default, @@conf['db'])

Dir.glob(File.dirname(__FILE__)+'/models/*.rb').each do |rb|
puts "loading #{rb}"
require rb
end

DataMapper::Logger.new($stdout, :debug)
DataMapper.finalize

DataMapperにどのDBを使うか設定してからModelを読み込んで、Loggerを設定したらfinalizeする。finalizeしないとwebアプリとかで使った時に何度もDBに接続しにいったりModelの定義とかを実行してしまうらしい。


postする
bin/post_comment.rb
#!/usr/bin/env ruby
require File.dirname(__FILE__)+'/../bootstrap'

if ARGV.empty?
puts 'error : comment required'
puts "e.g. ruby #{$0} \"hello world\""
exit 1
end

begin
c = Comment.new(:name => `whoami`.strip, :body => ARGV.join(' '))
c.save
rescue => e
STDERR.puts e
exit 1
end

total = Comment.count
Comment.get_latests(5).each do |c|
puts "(#{c.id}/#{total}) #{c}"
end


最近のcommentを見る
bin/show_comments.rb
#!/usr/bin/env ruby
require File.dirname(__FILE__)+'/../bootstrap'

total = Comment.count
Comment.get_latests(20).each do |c|
puts "(#{c.id}/#{total}) #{c}"
end


postしたりshowした実行結果
(12/12) [sho] てすと - Mon Apr 30 13:14:10 +0900 2012
(11/12) [sho] MySQLに保存できるようになった - Mon Apr 30 00:52:25 +0900 2012
(10/12) [sho] できた!! - Mon Apr 30 00:52:06 +0900 2012
(9/12) [sho] できたのでは - Mon Apr 30 00:50:05 +0900 2012
(以下略)


あと、modelを読み込んでDB接続してIRB起動する簡単なスクリプト作っておくと、modelのメソッド試したりQuery発行できたりして便利
bin/console.rb
#!/usr/bin/env ruby
require File.dirname(__FILE__)+'/../bootstrap'
require 'irb'

IRB.start