sinatra

2012年08月18日

sinatraを一から勉強し直している。
Ruby on Railといったフレームワークをちゃんと使ったことがないから、理解していないことが多すぎる。 ということで、sinatraの基本的な使い方として、以下をまず始めに学ぶことにした。

  1. deply環境の切り替え方法
  2. auto reloadを使えるようにする方法

auto reloadは、ソースコードを変更したとき、アプリケーションサーバを起動し直さなくても、自動的に再読み込みをしてくれるので、try&errorをするときの作業効率が全く違う。是非早めにマスターしておきたい。
deploy環境の指定ができるようになると、プログラム中で環境に応じた処理を分岐させることができる。
開発環境では、reloaderを有効にするが、本番環境では無効にするとか、開発環境の場合にdebug用の出力を出す、とかを簡単に切り替えられて楽になる。

で、いきなりつまずいた。

sinatraでのdeploy環境は、以下の3つから選択することとなる。

  • 開発環境:development
  • テスト環境:test
  • 本番環境:production

環境を指定するには、コードの最初の方で以下のように宣言しておく。

set :environment, :production

環境の指定は、rubyを実行する時の-eオプションで指定することもできる。

ruby app.rb -e production

使い方は、それ以降でdevelop?もしくはproduction?メドッドで判別し、trueかfalseが返るので、それで条件分岐させる。

@debug="checkpoint通過" if development?

このdevelopment?やproduction?やtest?というメッソッドは、sinatra/base.rbの中で以下のように定義されている。

def development?; environment == :development end
def production?;  environment == :production  end
def test?;        environment == :test        end

さて、このenvironment変数に入っている環境指定のシンボルをどうやって参照するかも試した。
マニュアルによれば、settings.environmentで取れるはずだ。

しかし、settings.environmentで得た結果と、production?で得た結果が異なるのである。
例えば、以下のようなコードでは。

# encoding: utf-8
require 'rubygems'
require 'sinatra'

set :environment, :production

class App < Sinatra::Base

  configure :development do
    require 'sinatra/reloader'
    register Sinatra::Reloader
  end

  get '/' do
    @messages="hello world with sinatra/reloader"
    @mode="environment is " + settings.environment.to_s
    @debug1="debug: production?="  + production?.to_s  if production?
    @debug1="debug: development?=" + development?.to_s if development?
    erb :envtest
  end
end

App.run!

出力はこうなる。

environment is development
debug: production?=true

一方、以下のようにclass定義内にset文を入れると、

# encoding: utf-8
require 'rubygems'
require 'sinatra'

class App < Sinatra::Base
  set :environment, :production

  configure :development do
    require 'sinatra/reloader'
    register Sinatra::Reloader
  end

  get '/' do
    @messages="hello world with sinatra/reloader"
    @mode="environment is " + settings.environment.to_s
    @debug1="debug: production?="  + production?.to_s  if production?
    @debug1="debug: development?=" + development?.to_s if development?
    erb :envtest
  end
end

App.run!

このようになる。

environment is production
debug: development?=true

この違いがわからないまま、今に至る訳である。
class定義の外でsetしたものはクラス変数に入り、内側でsetしたものはインスタンス変数に入るのだろうか。 そして、settingsはインスタンス変数を見ているが、?メソッドはクラス変数を見ていると考えれば、合点はいくが、なぜそんなふうになっているのかは謎。
実用上は、production?メドッドで分岐させることが多いはずなので、classの外側で定義しておけば問題ない。

また、ruby起動時の-eオプションで指定した場合も、前者(classの外側で定義)と同じ動きをする。
ややこしいことに、configure 〜 do は、内側で定義した:environmentで判断されるようだ。

では、外側で定義した:environmentの値を、内側の:environmentに代入するような仕組みにすればいいかと思ったが、どうもそれもうまく動かない。
結局、rubyの思想に反するが、両方で定義しておくのが安定しそうだ。
 

ちなみに、reloaderの読み込みは、上記コード内のconfigureブロックの中で書いてあるとおり。
参考は以下。



sylphide_ffr31mr at 20:12コメント(0)トラックバック(0) 

2010年08月18日

GAE上でsinatraとoauthとtwitter

GAE上のjrubyプログラムでクライアントからの値を取れるようになったので、次はいよいよ他のサービスとの通信だ。 しかし、他のサービスとの通信をするには、認証という大きな壁がある。
一番簡単そうなtwitterで遊んでみることにする。
twitterは、今月(2010-08)にbasic認証を終了するとアナウンスしているので、oauthを使う。 oauthのお勉強はこちらなど。

まずは、環境の確認の意味で、こちらのプログラムを動かしてみる。

しかし、なかなか素直に動かない。
試行錯誤すること3日。
あちこちを参考にするが、つまづきまくる。

結果としては、原因が2つあったようだ。

一つは、appengine gemでjrubyへライブラリを組み込むとき、appcfg.rb bundleをするが、gemの依存関係の処理がうまくいっていないようだ。 依存gemをGemfilesに書いてあげることで、gemのloadはクリアできた。

二つ目の原因は、twitter gemとoauth gemの2つをrequireしていたのだが、twitter gemにoauthのクラスが組み込まれており、oauth gemと競合していた。require twitterのみにして解決した。

あと、GAEの特徴として、Net::HTTPが素のままでは使えないという問題もあるが、これもgoogle-appengineが解決してくれているので、今や意識しなくてよいようだ。

動作環境は以下。

$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux]
$ gem list

*** LOCAL GEMS ***

appengine-apis (0.0.18)
appengine-rack (0.0.11)
appengine-sdk (1.3.5)
appengine-tools (0.0.15)
bundler08 (0.8.5)
crack (0.1.6)
google-appengine (0.0.15)
hashie (0.2.2)
httparty (0.5.2)
jruby-jars (1.5.1)
jruby-rack (1.0.2, 1.0.1)
oauth (0.4.1)
rack (1.2.1)
ruby-hmac (0.4.0)
rubyzip (0.9.4)
twitter (0.9.8)
yajl-ruby (0.7.7)

Gemfilesとrequireリストは、以下になる。

$ more Gemfile 
# Critical default settings:
disable_system_gems
disable_rubygems
bundle_path ".gems/bundler_gems"

# List gems to bundle here:
gem 'appengine-rack', '0.0.11.pre'
gem 'appengine-apis'
gem 'sinatra'
gem 'httparty'
gem 'yajl-ruby'
gem 'jruby-openssl'
gem 'twitter'

$ cat sample.tw.rb
require 'rubygems'
require 'openssl'
require 'twitter'
(以下略)
まちゅダイアリー Sinatra と OAuth を使って Twitter のタイムラインを取得してみたのソースが続く


sylphide_ffr31mr at 20:10コメント(0)トラックバック(0) 
記事検索
最新コメント
livedoor プロフィール
月別アーカイブ
  • ライブドアブログ