Sinatraの使い方を調べつつアプリのテンプレートを作ってみた

Sinatraの使い方を学びつつ、ついでにKomodo IDEで使うSinatraアプリのテンプレートを作成してみます。

Sinatraアプリの原形とセッション&Flashメッセージの組み込み

とりあえずSinatraのインストールから。

$ sudo gem install sinatra
Successfully installed rack-1.0.1
Successfully installed sinatra-0.9.4


SinatraとRackがインストールされました。

アプリのオートリロードするためにShotgunをインストール。

$ sudo gem install shotgun

セッションはRackのセッションを利用し、nakajima/rack-flash @ GitHubでRails風のFlashメッセージを利用します。

$ sudo gem install rack-flash

Sinatraアプリ本体をapp.rbとして作成。
RackのセッションとFlashメッセージを利用できるように設定。
トップページでFlashメッセージをセットして、リンク先/helloでメッセージを表示します。

# -*- encoding: UTF-8 -*-
require 'sinatra'
require 'rack/flash'
 
configure do
  use Rack::Session::Cookie,
    #:key => 'rack.session',
    #:domain => 'example.com',
    #:path => '/',
    :expire_after => 3600,
    :secret => 'IgR~tKW4YxEvzSHqp^uArcmbFeJklf5dNVQDwCUhOosyiMZTGj'
  use Rack::Flash
end
 
get '/' do
  flash[:notice] = "Hello world!"
  "<a href='/hello'>Hello world!</a>"
end
 
get '/hello' do
  flash[:notice]
end

$ shotgun app.rb


でアプリを実行して、http://localhost:9393にアクセスして、動作を確認。

したのは良いんですけど、shotgunを終了したらゾンビになってしまいました。
のでSinatraでshotgunの代わりにRack::Reloaderを使う方法 – Hello, world! – s21gを参考に

configure :development do
  class Sinatra::Reloader < Rack::Reloader
    def safe_load(file, mtime, stderr = $stderr)
      ::Sinatra::Application.reset!
      use_in_file_templates! file
      stderr.puts "#{self.class}: reseting routes"
      super
    end
  end
  use Sinatra::Reloader
end


に変更して、

$ ruby app.rb

として、リロードされるようにしました。

HamlとSassを組み込む

HamlとSassをインストール。

$ sudo gem install haml

viewsディレクトリを作成します。

ページレイアウト用にviews/layout.hamlを作成します。
タイトルを表示してflashメッセージを表示するコード。

!!! XML
!!! Strict
 
%html
  %head
    %title Sinatra Template
    %link{:href => "/styles.css", :rel => "stylesheet", :type => "text/css", :media => "screen"}
  %body
    #branding
      %h1 Sinatra Template
    - if flash[:notice]
      %p.notice= flash['notice']
    - if flash[:error]
      %p.error_notice= flash['error']
 
    #content
      != yield

indexページ用にviews/index.hamlを作成します。

%form{:method => 'POST', :action => '/hello'}
  %input{:type => 'submit', :value => 'Say hello!'}

app.rbにこれらを表示するためのコードを追加&変更。

require 'haml'
get '/' do
  haml :index
end
 
post '/hello' do
  flash[:notice] = "Hello world!"
  redirect '/hello'
end
 
get '/hello' do
  flash[:notice]
end

indexページのSay hello!ボタンをクリックすると/helloにPOSTします。さらにそのPOSTでFlashメッセージをセットして、/helloへリダイレクト。/helloでFlashメッセージが表示されます、という内容。

次にSass。
views/styles.sassを作成。内容はあとでリセット入れたり自分用にカスタマイズするとして、今は動作検証のために簡単なコードに。

body
  :font
    :size 1.5em

app.rbにスタイルシートへアクセスするコードを追加。

get '/*.css' do |path|
  content_type 'text/css', :charset => 'utf-8'
  sass path.to_sym, :sass => {:load_paths => options.views}
end

で、動作確認。期待した通りページが表示されました。

ORM => DataMapperの組み込み

ORMはDataMapperを利用します。

$ sudo gem install datamapper
$ sudo gem install do_sqlite3

app.rbにDataMapperの設定を記述。
データベースにはSQLiteを使用。developmentではmemory、productionではファイルを使用します。

require 'dm-core'
require 'logger'
 
configure :development do
  # リロード設定が記述してあります。
  DataMapper.setup(:default, 'sqlite3::memory:')
  DataMapper::Logger.new(STDOUT, :debug)
end
 
configure :production do
  DataMapper.setup(:default, 'sqlite3:production.db')
end

ユーザ認証はどうしましょうか。maxjustus’s sinatra-authentication at master – GitHubとかsubbarao’s sinatra-openid at master – GitHubが便利そうで試してみたんですか、どちらもうまく動かず。DataMapperのプロパティのタイプにBCryptHashがあるので、それを利用して自作するのが簡単かな。とりあえず保留。

テスト環境の導入

テストにはShouldaとCucumber+Webratを利用しようとおもいます。

まずはShoulda。一緒にrack-testも。

$ sudo gem install shoulda
$ sudo gem install rack-test


testディレクトリを作成。

Testing
Sinatra tests can be written using any Rack-based testing library or framework. Rack::Test is recommended:

Sinatra: README

を参考にtest/app_test.rbを作成。

require File.join( File.dirname(__FILE__), '../app.rb')
require 'test/unit'
require 'shoulda'
require 'rack/test'
 
class AppTest < Test::Unit::TestCase
  include Rack::Test::Methods
 
  def app
    Sinatra::Application
  end
 
  context "Access pages" do
    should "show index" do
      get '/'
      assert_match 'Say hello!', last_response.body
    end
 
    should "show hello" do
      post '/hello'
      follow_redirect!
      assert_match 'Hello world!', last_response.body
    end
  end
end

次にCucumber。

$ sudo gem install cucumbe webrat


features, featuers/support, features/step_definitionsディレクトリを作成しました。

cucumber.ymlを「default: –language ja features」という内容で作成しました。

features/support/env.rbを作成しました。

# -*- encoding: UTF-8 -*-
app_file = File.join(File.dirname(__FILE__), '../../app.rb')
require app_file
Sinatra::Application.app_file = app_file
 
require 'test/unit/assertions'
require 'shoulda'
require 'rack/test'
require 'webrat'
 
Encoding.default_external = 'UTF-8'
 
Webrat.configure do |config|
  config.mode = :rack
  config.application_framework = :sinatra
  config.application_port = 4567
end
 
World(Test::Unit::Assertions) do
  def app
    Sinatra::Application
  end
 
  include Rack::Test::Methods
  include Webrat::Methods
  include Webrat::Matchers
end
 
Before do
  DataMapper.auto_migrate!
end

features/step_definitions/webrat_steps.rbは他のシステムで利用しているものをコピー。

問題はfeatures/step_definitions/result_steps.rb。これまではRSpecを利用していたのですが、今回はtest/unitを使うので、xpathの検証とかはどうするかなど。とりあえず動いたコードがこれ。

# -*- encoding: UTF-8 -*-
 
ならば /^"(.*)"と表示される$/ do |text|
  assert_match(/#{text}/m, @response.body)
end
 
ならば /^"(.*)"と表示されない$/ do |text|
  assert_no_match(/#{text}/m, @response.body)
end
 
ならば /^(\w+)メッセージが表示さる$/ do |message_type|
  assert_not_equal 0, Nokogiri::HTML.parse(@response.body).search("//*[@class='#{message_type}']").length
end
 
ならば /^(.*)リクエストが失敗する/ do |_|
  assert_not_equal 200, @response.status
end
 
ならば /ページ読み込みが成功する/ do
  assert_equal 200, @response.status
end


xpathの検査がかっこわるい…。良い方法があったらコメントください。

Rakefileは以下の内容にしました。

require 'cucumber/rake/task'
 
desc 'Run all tests'
task :test do
   require 'rake/testtask'
   Rake::TestTask.new do |t|
      t.test_files = FileList[File.join('test', '**', '*_test.rb')]
   end
end
 
desc "Run all features in features directory"
Cucumber::Rake::Task.new(:features)

あとは

  • Sassを完成させる
  • rack cacheの導入
  • モデル作成したときのためのFixtureの準備
  • configディレクトリを作成して設定ファイルをそこに置くか
  • publicディレクトリの作成
  • ほかいろいろ…

をやったりやらなかったり。

そしてKomodo IDEでプロジェクトテンプレートを作成。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です