2012年5月17日木曜日

sinatra (7) - データベース -

(6)の続き。
データベースは、MySQLSQLiteなど選択に困るほど存在しますが、ここでは ドキュメント指向データベースのMongoDBを使用します。
インストールは公式ページにしたがっておこないます。
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10

/etc/apt/sources.list

deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen
$ sudo update
$ sudo apt-get install mongodb-10gen
次にsinatraで扱えるようにします。
.
├── config
│     ├── mongoid.yml  # 追加
│     └── unicorn.rb
├── config.ru
├── Gemfile
├── Gemfile.lock
├── Guardfile
├── lib
│     ├── app.rb
│     └── models.rb  # 追加
├── public
├── spec
│     ├── app_spec.rb
│     └── spec_helper.rb
└── views
       ├── index.slim
       ├── layout.slim
       └── style.scss
source :rubygems

gem 'sinatra', require: 'sinatra/base'
gem 'slim'
gem 'sass'
gem 'unicorn'
gem 'mongoid'
gem 'bson_ext'

group :development do
  gem 'sinatra-reloader', require: 'sinatra/reloader'
end

group :test do
  gem 'rspec'
  gem 'rack-test', require: 'rack/test'
  gem 'guard-rspec'
end
$ bundle install

config/mongoid.yml

development:
  host: localhost
  database: mydb
動かすだけであれば、設定はこの程度でも動作します。
公式により詳細な設定が書かれています。

lib/models.rb

class Game
  include Mongoid::Document
  field :title, type: String
  field :platform, type: String
end

lib/app.rb

require 'models'

class MyApp < Sinatra::Base

  configure :development do
    Bundler.require :development
    register Sinatra::Reloader
    Slim::Engine.set_default_options pretty: true
    Mongoid.logger = Logger.new(STDOUT)
    Mongoid.logger.level = Logger::INFO
  end

  configure do
    set :root, File.expand_path('../../', __FILE__)
    Mongoid.load! File.join(settings.root, 'config', 'mongoid.yml')
  end

  get '/' do
    slim :index
  end

  get '/games/:field' do
    content_type :text
    game = Game.first
    game ? "#{game.__send__ params[:field]}" : "nil"
  end

  get '/css/:file.css' do
    scss params[:file].to_sym
  end
end
Mongoid.load! File.join(settings.root, 'config', 'mongoid.yml')
で設定を読み込みます。
このまま使用するとRSpecを使用した時もクエリの内容等、デバッグログが出力されてしまうので抑制します。
Mongoid.logger = Logger.new(STDOUT)
Mongoid.logger.level = Logger::INFO
用途に合わせて出力先や出力レベルを調整するとよいでしょう。
注意しなければならないのはMongoid.load!よりも前に定義しなくてはいけないことです。Mongo Ruby Driverが公開APIを提供していないため、masterの設定より先に記述しなくてはいけないようです。ソースを除くとrailsでは別途railsで指定したloggerを参照しているようです。
models.rbでサンプルとなるモデルを定義しています。このあたりsinatraは自由なのでapp.rbに定義してもよいし、モデルごとにファイルを分割しても問題ありません。使える型についても公式に記述があります。
ルートも増えたところで対応するテストケースも追加しておきましょう。

spec/spec_helper.rb

require 'bundler/setup'
Bundler.require :default, :test

require 'app'
require 'models'

RSpec.configure do |config|
  config.include Rack::Test::Methods
end

spec/app_spec.rb

require 'spec_helper'

describe MyApp do

  def app
    @app ||= MyApp
  end

  context "when get '/'" do
    before do
      get '/'
    end
    subject { last_response }
    its(:status) { should == 200 }
    its(:body) { should include("Hello World!") }
  end

  describe "MongoDB access" do
    before do
      Game.destroy_all if Game.exists?
      Game.create(title: "GOD EATER BURST", platform: "PSP")
    end
    context "when get '/games/title'" do
      before { get 'games/title' }
      subject { last_response }
      its(:body) { should == "GOD EATER BURST" }
    end
    context "when get '/games/platform'" do
      before { get 'games/platform' }
      subject { last_response }
      its(:body) { should == "PSP" }
    end
  end
end

0 件のコメント:

コメントを投稿