LoadErrorに心が折れそうなときに試したい2つのこと

[gae/jruby] GAE/J+JRuby環境のno such file to loadに心が折れそうなときに試したい2つのこと

今日の課題

このエラーに対処します。

$
$ dev_appserver.rb .
=> Booting DevAppServer
=> Press Ctrl-C to shutdown server
中略
org.jruby.rack.RackInitializationException: no such file to load -- appengine-apis/users
	from ./app.rb:2
	from ./app.rb:19:in `require'
	from config.ru:19
  
	at org.jruby.rack.DefaultRackApplicationFactory$4.init(DefaultRackApplicationFactory.java:172)
	at org.jruby.rack.DefaultRackApplicationFactory.getApplication(DefaultRackApplicationFactory.java:51)
	at org.jruby.rack.SharedRackApplicationFactory.init(SharedRackApplicationFactory.java:27)
中略
$
$

このエラーにも対処します。

$ jruby -S spec spec/なんとかかんとか_spec.rb
#<LoadError: no such file to load -- appengine-apis>
中略
/opt/local/share/java/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require': no such file to load -- appengine-apis (LoadError)
	from /opt/local/share/java/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
中略

誰が使うの?

  • 正しいかどうかはさておき、とにかくコンパイルを通したい人
  • require 'appengine-apis/logger'とかrequire 'appengine-apis/users'が通らなくてイライラしている人

どのように機能するの?

  • appengine-apisへのパスをとにかく通します。

どこで確認したの?

$ uname -v
Darwin Kernel Version 10.3.0: Fri Feb 26 11:58:09 PST 2010; root:xnu-1504.3.12~1/RELEASE_I386
$ 
$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [i686-darwin10]
$ 
$ jruby -v
jruby 1.4.0 (ruby 1.8.7 patchlevel 174) (2010-04-22 6586) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_17) [x86_64-java]
$ 
$ java -version
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04-248-10M3025)
Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01-101, mixed mode)
$ 

いつ確認したの?

  • 2010年5月4日

何が参考になるの?

  • 特にありません。

何か注意点はあるの?

  • このやり方が正しいかよくわかりません。正しくなくてもとにかく動かしたい人向け。

試したいこと。その1

こういうコードで..

$
$ cat app.rb
require 'sinatra'
require 'appengine-apis/users'

get '/' do
  puts "aa"
end
$
$
$ cat Gemfile 
# Critical default settings:
disable_system_gems
disable_rubygems
bundle_path ".gems/bundler_gems"

# List gems to bundle here:
gem "appengine-rack"
gem 'sinatra'
$ 
$

開発サーバを起動時に no such file to load エラーがでるとき。

$
$ dev_appserver.rb .
=> Booting DevAppServer
=> Press Ctrl-C to shutdown server
中略
org.jruby.rack.RackInitializationException: no such file to load -- appengine-apis/users
	from ./app.rb:2
	from ./app.rb:19:in `require'
	from config.ru:19
  
	at org.jruby.rack.DefaultRackApplicationFactory$4.init(DefaultRackApplicationFactory.java:172)
	at org.jruby.rack.DefaultRackApplicationFactory.getApplication(DefaultRackApplicationFactory.java:51)
	at org.jruby.rack.SharedRackApplicationFactory.init(SharedRackApplicationFactory.java:27)
中略
$
$

コード内にrequire 'appengine-apis' を追記して....
Gemfileにgem 'appengine-apis' を追記して....

$
$
$ cat app.rb
require 'sinatra'
require 'appengine-apis'
require 'appengine-apis/users'

get '/' do
  puts "aa"
end
$ 
$
$ cat Gemfile 
# Critical default settings:
disable_system_gems
disable_rubygems
bundle_path ".gems/bundler_gems"

# List gems to bundle here:
gem "appengine-rack"
gem 'appengine-apis'
gem 'sinatra'
$ 
$


実行するとロードエラーが消えた!!
パスに解決にgem 'appengine-apis'が必要だったようです。

$
$
$ dev_appserver.rb .
=> Booting DevAppServer
=> Press Ctrl-C to shutdown server
=> Bundling gems
Calculating dependencies...
Updating source: http://gems.rubyforge.org
Downloading appengine-apis-0.0.14.gem
Installing appengine-apis (0.0.14)
Done.
=> Packaging gems
中略
2010/05/04 4:40:47 com.google.apphosting.utils.jetty.JettyLogger info
???: Started SelectChannelConnector@127.0.0.1:8080
The server is running at http://localhost:8080/

試したいこと。その2

jrubyから単体テストを実行するようなケースでappengine-apisにno such file to loadエラーがでるとき。

$ jruby -S spec spec/なんとかかんとか_spec.rb
#<LoadError: no such file to load -- appengine-apis>
中略
/opt/local/share/java/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require': no such file to load -- appengine-apis (LoadError)
	from /opt/local/share/java/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
中略


コード内に「試したいこと。その1」のようにrequire 'appengine-apis' を追記してもエラーは解消しませんでした。
その時のgemの状態です。いずれもgem install google-appengineではインストールしたものです。

$
$ jgem list | grep -E '(appengine|bundler)'
appengine-jruby-jars (0.0.7.pre)
appengine-rack (0.0.7)
appengine-sdk (1.3.2)
appengine-tools (0.0.11)
bundler08 (0.8.5)
google-appengine (0.0.11)
$ 
$


appengine-apisは含まれていない。これが必要なのかな?
後先考えずにインストール!!

$ sudo jgem install appengine-apis

再実行するとエラーメッセージが変わった!!
SyntaxErrorです。バグでしょうか?
syntax error in testing.rb ...

$
$ jruby -S spec spec/なんとかかんとか_spec.rb
#<SyntaxError: /opt/local/share/java/jruby/lib/ruby/gems/1.8/gems/appengine-apis-0.0.14/lib/appengine-apis/testing.rb:59: , unexpected tRPAREN

          configs = nil if ENV['SKIP_LOCAL_SERVICE_APIS')
                                                        ^
中略

確かにカッコの対応がおかしいのようです。
後先考えずに、gemのコードを直に修正します。(自己責任でどうぞ)

before

          configs = nil if ENV['SKIP_LOCAL_SERVICE_APIS')

after

          configs = nil if ENV['SKIP_LOCAL_SERVICE_APIS']


通った!!

gae+jruby+sinatra+haml+DataMapperでアプリケーション

[gae/jruby] gae+jruby+sinatra+haml+DataMapperでアプリケーションを作ってみる

何がしたいの?

誰が使うの?

  • 動的なスケールアップが可能な環境でサービスを公開したい人
  • 自サーバやレンタルサーバは運用したくないけどサービスを公開したい人
  • rubyアプリケーションをgae上で公開したい人

どのように機能するの?

  • appengine-java-sdkの上でjrubyを動作させます。jrubyの上でrubyアプリケーションが動作します。
  • sinatra,haml,DataMapperとそのappengine用アダプタdm-appengineを使用します。

何を使うの?

gem "google-appengine"
gem "appengine-rack"
gem 'dm-appengine'
gem 'sinatra'
gem 'haml'

どこで確認したの?

いつ確認したの?

  • 2010年4月11日

どんなものができたの?

appspot.com => nnz-弁当店
お弁当を注文すると、24時間以内の注文数を表示するアプリケーションです。
お弁当は3つのメニューから選択可能で、注文した履歴が掲示板形式で表示されます。

何を参考にして作ったの?

gihyo.jp => 第9回 SinatraとSequel・Hamlで掲示板アプリを作るの記事を参考にしてサンプル的なお弁当注文サイトを作ってみました。
もちろん注文してもお弁当は届きませんのでご安心ください。
記事の順序に従ってGAEの掟に合わせた改造を施しながら進めていきます。元記事の筆者の方にはコードの部分転用の承諾をいただきました。
記事の中で「Sequel」を使用している部分は「DataMpper」で書き換えていきます。

リスト1 DataMpperによるモデル定義の例(model/order.rb)

require 'dm-core'

DataMapper.setup(:default, "appengine://auto")

class Orders
  include DataMapper::Resource
  property  :id,          Serial
  property  :name,        Text 
  property  :product,     Text
  property  :date,        Time
  
  def date_jst
    (self.date+9*3600).strftime("%Y/%m/%d(%a) %H:%M:%S")
  end
  
  def count 
    datastore = com.google.appengine.api.datastore.DatastoreServiceFactory.getDatastoreService() 
    query = com.google.appengine.api.datastore.Query.new("Orders") 
    datastore.prepare(query).countEntities() 
  end 
end

上記のメソッドdate_jstは表記上の時刻を日本時間に変換するために9時間加算しています。
お弁当の購入時の現在時刻をデータとして保存すると、UTMの現在時刻が保存されます。それをローカルタイムに変換しようにもjrubyが稼働しているマシンもUTMがローカルタイムですので一筋縄では行きません。
やっつけ仕事的ですが9時間の加算を行い、表示するときだけ日本時間に無理やり変換しています。
またメソッドcountですが、gem "dm-aggregates"を利用すればDataMapperのCountメソッドが使用できるハズなのですが、力及ばずでLowレベルのAPIを使用しました。


リスト2 HamlによるHTML表現の例(views/layout.haml

!!! XML
!!! Strict

%html
  %head
    %title nnz-弁当店
    %meta{:"http-equiv"=>"Content-Type", :content=>"text/html", :charset=>"utf-8"}
    %link{:rel=>"stylesheet", :type=>"text/css", :href=>"/style.css"}
  %body
    %table{:width => "100%"}
      .banner
        %h1 nnz-弁当店ご注文β
        
    != yield

    .footer
      #column-a
        .column
          %ul
            %h3 nnz
            %li 
              %a{:href => "/"} home
            %li 
              %a{:href => "/"} products
            %li 
              %a{:href => "/"} orders
            %li 
              %a{:href => "/"} contact us
             

リンク先はダミーですが、なんちゃってフッターもつけてみました。


リスト3 HamlによるHTML表現の例(views/index.haml

%form{:method => "POST", :action => '/order'}
  %input{:type => "hidden", :name => "_method", :value => "PUT"}
  %table
    %tr
      %fieldset
        %h3 お弁当何にする?
        .radio_group.toggle
          %p
            %input.radio{:type=>"radio", :name=>"product", :id=>"product_1", :value=>"のり弁", :checked=>true}/
            %label.radio{:for=>"product_1"} のり弁
          %p
            %input.radio{:type=>"radio", :name=>"product", :id=>"product_2", :value=>"唐揚げ弁当", }/
            %label.radio{:for=>"product_2"} 唐揚げ弁当
          %p
            %input.radio{:type=>"radio", :name=>"product", :id=>"product_3", :value=>"特盛りカレー", }/
            %label.radio{:for=>"product_3"} 特盛りカレー
      %td 名前
      %td 
        %input{:type => "text", :name => "name"}
      %td
        %input{:type => "submit"}

.today_order
  %h3 本日(24時間以内)のご注文は #{h @orders.count} 件です。
        

- @orders.each do |order|
  .comment
    %h2= h order.product
    .info
      %span.name== by #{h order.name}
      %span.date== (#{h order.date_jst})

掲示板を一般公開すると情報セキュリティ的にいろいろと心配ですので、ラジオボタンと名前欄だけのアプリケーションにしました。
自由入力が可能な名前欄はescape_html(hで別名定義済)でエスケープを行うこともセキュリティ上必要です。



リスト4 SassによるCSS表現の例(views/style.sass)

.banner
  margin: 0px 0%
  padding: 1em
  text-align: center
  color: #FFF
  background-color: #5998CF
  background: -webkit-gradient(linear, left top, left bottom, from(#70AEE5), to(#4080B6))
  background: -moz-linear-gradient(top, #70AEE5, #4080B6)  
   

body
  margin: 0px 0%
  padding: 0px
  focus: autoline none

h1
  margin: 1em

form
  margin: 0px 20%
  padding: 0.5em

.today_order
  margin: 10px 20%
  padding: 0.5em
  
.comment
  border: 1px solid black
  margin: 10px 20%
  padding: 0.5em
    
  h2
    margin: 0px
    font-size: medium
    float: left

  .info
    span.name
      padding-left: 0.5em
      font-size: small
    span.date
      font-size: small

  .message
    margin-top: 1em

.footer 
  background: #EEE
  width: 100%
  font-size: 15px
  margin: 0px
  padding-bottom: 20px
  text-align: left !important
  
  .column
    width: 120px
    padding: 10px 0 5px 20px

  h3
    font-size: 12px
    color: #444
    font-weight: bold
    
  li 
    font-size: 11px
    margin: 0
    padding: 0 0 0 10px

    a 
      color: #444
      text-decoration: none
      padding: 0 10px
      margin-left: -10px
      
ul
  margin-bottom: 20px
  list-style: none outside

CSSの代わりにSASSでスタイル指定を行います。
SASSを使えばタグ地獄から開放されるかな?思いきやイヤイヤこれも大変です。
メンテが楽になるのはおそらく間違いないと思いますが、新規作成には結構ひと苦労です。



リスト5 Sinatraによるコントローラ部分(start.rb)

require 'sinatra'
require 'model/order.rb'

helpers do
  include Rack::Utils
  alias_method :h, :escape_html
end

get '/style.css' do
  content_type 'text/css', :charset => 'utf-8'
  sass :style
end

get '/' do
  #24時間以内の注文
  @orders = Orders.all(:date.gt => Time.now-24*3600, :order => [:date.desc], :limit => 100)
  haml :index
end

put '/order' do
  Orders.create({
    :name     => request[:name],
    :product  => request[:product],
    :date     => Time.now,
  })
  
  redirect '/'
end

Orders.allの部分で発注時刻が24時間以内の最大100レコードを時刻降順で取り出しています。
発注時刻は"Time.now"部分で画面が呼ばれた時刻が記録されていますが、これはGAEが動作している環境に依存する時刻です。もちろん日本時間ではありません。



リスト6 (Gemfile)

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

# List gems to bundle here:
gem "appengine-rack"
gem 'dm-appengine'
gem 'sinatra'
gem 'haml'

'dm-appengine'部分がDataMapperを含んでいます。使用するgem名をGemfileへ記述しておくと、ダウンロードからjarファイルへの取り込みまで全部面倒を見てくれます。

gae上でjrubyを動かしたい。までの道のり3

何がしたいの?

誰が使うの?

  • rubyアプリケーションをgae上で公開したい人
  • 自サーバやレンタルサーバは運用したくないけどサービスを公開したい人
  • 動的なスケールアップが可能な環境でサービスを公開したい人

どのように機能するの?

  • appengine-java-sdkの上でjrubyを動作させます。jrubyの上でrubyを動作させます。
  • さらにそのrubyの上でrubyのライブラリやアプリケーションを動作させます。

何を使うの?

gem「google-appengine」

どこで確認したの?

いつ確認したの?

  • 2010年3月27日

何か注意点はあるの?

  • 特にありません

どんな手順でやるの?

まずは環境確認です。
今回からはCrubyの実行環境はruby1.8です。

$ 
$ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0]
$ 
$ gem list google-appengine

*** LOCAL GEMS ***

google-appengine (0.0.10.1)
$ 


ディレクトリ/opt/app/devにアプリケーションnnz-testを作成します....作成できました。

$ cd /opt/app/dev
$ 
$ ls
$ 
$ appcfg.rb generate_app nnz-test
=> Generating gemfile
=> Bundling gems
Calculating dependencies...
Updating source: http://gems.rubyforge.org
/Library/Ruby/Gems/1.8/gems/bundler08-0.8.5/lib/bundler08/resolver.rb:115:Warning: Gem::Dependency#version_requirements is deprecated and will be removed on or after August 2010.  Use #requirement
Caching: appengine-rack-0.0.6.gem
Caching: rack-1.1.0.gem
Installing rack (1.1.0)
Installing appengine-rack (0.0.6)
Done.
=> Packaging gems
=> Installing JRuby
=> Installing JRuby-Rack
=> Installing appengine-sdk
=> Generating rackup
=> Generating configuration files
$ 
$ ls
nnz-test
$ 

ローカルで起動します...起動しました。

$ cd nnz-test/
$ pwd
/opt/app/dev/nnz-test
$ dev_appserver.rb .
=> Booting DevAppServer
=> Press Ctrl-C to shutdown server
中略
The server is running at http://localhost:8080/
$ 


ブラウザで確認します。


GAEにアップロードします....アップロードが完了しました。

$ pwd
/opt/app/dev/nnz-test
$ 
$ cat config.ru 
require 'appengine-rack'
AppEngine::Rack.configure_app(          
    :application => "nnz-test",           
    :precompilation_enabled => true,
    :version => "1")
run lambda { Rack::Response.new("Hello").finish }
$ 
$ appcfg.rb update .
=> Running AppCfg
Reading application configuration data...
Beginning server interaction for nnz-test...
0% Creating staging directory
5% Scanning for jsp files.
20% Scanning files on local disk.
25% Initiating update.
Email: メールアドレスを入力する
Password for メールアドレス  に対応するパスワードを入力する 
28% Cloning 2 static files.
31% Cloning 11 application files.
40% Uploading 3 files.
52% Uploaded 1 files.
61% Uploaded 2 files.
68% Uploaded 3 files.
73% Initializing precompilation...
90% Deploying new version.
95% Will check again in 1 seconds
98% Will check again in 2 seconds
99% Will check again in 4 seconds
99% Will check again in 8 seconds
99% Will check again in 16 seconds
99% Closing update: new version is ready to start serving.
99% Uploading index definitions.

Update completed successfully.
Success.
Cleaning up temporary files...
$ 


ダッシュボードを確認します。.... version 1 のアプリケーションが稼働していることが確認できました。

ブラウザでappspot.comにアクセスします。.....appspot.com上でレスポンスを確認できました。

次はsinatraアプリです。
myapp.rbを作成し、myapp.rbを呼び出すように変更して、開発サーバで実行してみます....豪快にコケました。
requireがオカシイと言ってます。

$
$ cat myapp.rb 
require 'rubygems'
require 'sinatra'

get '/'        do 'top page'  end
get '/ja'      do 'ようこそ!!' end
get '/en'      do 'welcame!!' end
get '/ja/info' do '<h2>これはなに?</h2>'   end
get '/en/info' do '<h2>what is this?</h2>' end
$ 
$ cat config.ru 
require 'appengine-rack'
require 'myapp'
AppEngine::Rack.configure_app(          
    :application => "nnz-test",           
    :precompilation_enabled => true,
    :version => "2")
run  Sinatra::Application
$
$ 
$ dev_appserver.rb .
=> Booting DevAppServer
=> Press Ctrl-C to shutdown server
2010-03-28 01:02:04.981 java[94720:1607] [Java CocoaComponent compatibility mode]: Enabled
2010-03-28 01:02:04.983 java[94720:1607] [Java CocoaComponent compatibility mode]: Setting timeout for SWT to 0.100000
2010/03/27 16:02:05 com.google.appengine.tools.development.agent.impl.BlackList initBlackList
?v???I: Unable to read a jre library while constructing the blacklist. Security restrictions may not be entirely emulated. /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/lib/plugin.jar
2010/03/27 16:02:10 com.google.appengine.tools.development.ApiProxyLocalImpl log
?v???I: [1269705730220000] javax.servlet.ServletContext log: unable to create shared application instance
org.jruby.rack.RackInitializationException: no such file to load -- sinatra
	from ./myapp.rb:2
	from ./myapp.rb:3:in `require'
	from config.ru:3

	at org.jruby.rack.DefaultRackApplicationFactory$4.init(DefaultRackApplicationFactory.java:169)
	at org.jruby.rack.DefaultRackApplicationFactory.getApplication(DefaultRackApplicationFactory.java:51)
	at org.jruby.rack.SharedRackApplicationFactory.init(SharedRackApplicationFactory.java:27)
	at org.jruby.rack.RackServletContextListener.contextInitialized(RackServletContextListener.java:40)
	at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:530)
	at org.mortbay.jetty.servlet.Context.startContext(Context.java:135)
	at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1218)
以下、省略

Gemfileに gem "sinatra" を付け加えて再実行します...今度はうまく行きました。
アプリケーション本体でrequireするgemはGemfileにも書かなければならないようです。

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

# List gems to bundle here:
gem "appengine-rack"
gem "sinatra"
$ 
$ dev_appserver.rb .
=> Booting DevAppServer
=> Press Ctrl-C to shutdown server
=> Bundling gems
Calculating dependencies...
Updating source: http://gems.rubyforge.org
/Library/Ruby/Gems/1.8/gems/bundler08-0.8.5/lib/bundler08/resolver.rb:115:Warning: Gem::Dependency#version_requirements is deprecated and will be removed on or after August 2010.  Use #requirement
Installing sinatra (1.0)
Done.
=> Packaging gems
2010-03-28 01:07:06.227 java[94733:1607] [Java CocoaComponent compatibility mode]: Enabled
2010-03-28 01:07:06.230 java[94733:1607] [Java CocoaComponent compatibility mode]: Setting timeout for SWT to 0.100000
2010/03/27 16:07:06 com.google.appengine.tools.development.agent.impl.BlackList initBlackList
?v???I: Unable to read a jre library while constructing the blacklist. Security restrictions may not be entirely emulated. /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/lib/plugin.jar
The server is running at http://localhost:8080/


エンコードの指定をしていないので、手動で文字コードを変更する必要があるかもしれませんが、そこはご愛嬌。
開発サーバで想定通りの表示を得ることができました。


アップロードします...成功しました。

$ 
$ appcfg.rb update .
=> Running AppCfg
Reading application configuration data...
Beginning server interaction for nnz-test...
0% Creating staging directory
5% Scanning for jsp files.
20% Scanning files on local disk.
25% Initiating update.
28% Cloning 2 static files.
31% Cloning 12 application files.
40% Uploading 4 files.
52% Uploaded 1 files.
61% Uploaded 2 files.
68% Uploaded 3 files.
73% Uploaded 4 files.
77% Initializing precompilation...
90% Deploying new version.
95% Will check again in 1 seconds
98% Will check again in 2 seconds
99% Will check again in 4 seconds
99% Will check again in 8 seconds
99% Will check again in 16 seconds
99% Closing update: new version is ready to start serving.
99% Uploading index definitions.

Update completed successfully.
Success.
Cleaning up temporary files...
$ 


バージョン2をアップロードしましたが、
google app engine -[Administration]-[Versions]で見てみるとアップロードしただけは、defaultバージョンは更新されず[1]のままです。
[2]→[Make Default]を選択することで新しいバージョンがデフォルトになります。



sinatraアプリケーションの動作確認が完了しました。
テストサイトは適宜バージョン更新します。この時のバージョンはこれです。



アプリケーションは上書きされるわではなく世代保存されています。
バージョンを明示的に指定して以前のバージョンのアプリケーションに接続することができます。
http://1.latest.nnz-test.appspot.com/
http://2.latest.nnz-test.appspot.com/

続きはこちらです。
gae+jruby+sinatra+haml+DataMapperでアプリケーションを作ってみる

gae上でjrubyを動かしたい。までの道のり1

何がしたいの?

誰が使うの?

  • rubyアプリケーションをgae上で公開したい人
  • 自サーバやレンタルサーバは運用したくないけどサービスを公開したい人
  • 動的なスケールアップが可能な環境でサービスを公開したい人

どのように機能するの?

  • appengine-java-sdkの上でjrubyを動作させます。jrubyの上でrubyを動作させます。
  • さらにそのrubyの上でrubyのライブラリやアプリケーションを動作させます。

何を使うの?

-appengine-java-sdk
-jruby
gem「google-appengine」に含まれており、別途用意する必要は無い。

どこで確認したの?

いつ確認したの?

  • 2010年3月23日

何か注意点はあるの?

手元の環境ではruby1.9ではアプリケーションの構築に失敗しました。ruby1.8でHelloWorldに成功しました。原因は分かりましたが対策が分かりませんした。

どんな手順でやるの?

実行パスが通っていることろにコマンドを配置します。
appengine-java-sdkを配置後、PATHを通します。

<del>$ ls /usr/local/lib/
appengine-java-sdk-1.3.1         
$ export PATH=$PATH:/usr/local/lib/appengine-java-sdk-1.3.1/bin/</del>

appengine-java-sdkはgem「google-appengine」に含まれており、別途用意する必要は無い。

google-appengineをインストール。と思いきやエラーです。
gemのバージョンが古いと言っています。

$ 
$ ruby -v
ruby 1.9.1p376 (2009-12-07 revision 26041) [i386-darwin10]
$ 
$ sudo gem install google-appengine
ERROR:  Error installing google-appengine:
	bundler08 requires RubyGems version >= 1.3.5
$ 
$ gem -v
1.3.1

gem自身の更新どうやるんだっけ?と思い検索しているとなんだか怖いことを書いてあるのを見つけました。
gemのアップデートには気をつけて
手元の環境ではMacPortでインストールしたrubyを使用しているわけですが、
gemsはruby1.9の添付のgemsなので本来はport経由で更新するべきです。
しかし、port上には更新されたrubyはエントリされていません。

$ port outdated
No installed ports are outdated.
$ port list ruby19
ruby19                         @1.9.1-p376     lang/ruby19
$ 
$ ruby -v
ruby 1.9.1p376 (2009-12-07 revision 26041) [i386-darwin10]
$ 

ちょっと怖いですがrubygems-updateとやらでgemsを更新してみます。

$ gem -v
1.3.1
$ 
$ gem search -r rubygems-update

*** REMOTE GEMS ***

rubygems-update (1.3.6)
$ 
$ sudo gem install rubygems-update
Successfully installed rubygems-update-1.3.6
1 gem installed
$
$ sudo update_rubygems
RubyGems 1.3.6 installed
$
$ gem -v
1.3.6
$ 

気を取り直してリトライします。今回はうまくいきました。
jrubyではなくCRubyのgemを使用します。

$ sudo gem install google-appengine
Successfully installed bundler08-0.8.5
Successfully installed rubyzip-0.9.4
Successfully installed appengine-tools-0.0.10.1
Successfully installed google-appengine-0.0.10.1
4 gems installed

appcfg.rbでアプリケーションmyhelloを作成します。
ディレクトリなどを作ってくれています...がLoadErrorでコケました。ファイルが無いとか言っています。

$ 
$ appcfg.rb generate_app myhello
=> Generating gemfile
/opt/local/lib/ruby/gems/1.9.1/gems/appengine-tools-0.0.10.1/lib/appengine-tools/gem_bundler.rb:63: warning: already initialized constant RUBY_ENGINE
=> Bundling gems
Calculating dependencies...
Updating source: http://gems.rubyforge.org
/opt/local/lib/ruby/gems/1.9.1/gems/bundler08-0.8.5/lib/bundler08/resolver.rb:115:Warning: Gem::Dependency#version_requirements is deprecated and will be removed on or after August 2010.  Use #requirement
Caching: appengine-rack-0.0.6.gem
Caching: rack-1.1.0.gem
Installing rack (1.1.0)
Installing appengine-rack (0.0.6)
Done.
/opt/local/lib/ruby/gems/1.9.1/gems/appengine-tools-0.0.10.1/lib/appengine-tools/gem_bundler.rb:73: warning: already initialized constant RUBY_ENGINE
=> Packaging gems
=> Installing JRuby
=> Installing JRuby-Rack
=> Installing appengine-sdk
=> Generating rackup
=> Generating configuration files
file:/opt/local/lib/ruby/gems/1.9.1/gems/appengine-jruby-jars-0.0.6/lib/appengine-jruby-rubygems-0.0.6.jar!/rubygems/custom_require.rb:31:in `require': no such file to load -- .gems/bundler_gems/jruby/1.8/environment (LoadError)
	from file:/opt/local/lib/ruby/gems/1.9.1/gems/appengine-jruby-jars-0.0.6/lib/appengine-jruby-rubygems-0.0.6.jar!/rubygems/custom_require.rb:31:in `require'
	from /opt/local/lib/ruby/gems/1.9.1/gems/appengine-tools-0.0.10.1/lib/appengine-tools/bundler.rb:263:in `generate_xml'
中略
Error executing jruby
$ 


gemのロードに問題が起きているようです。
自分で1.9.1のディレクトリを作成しているのにjruby/1.8を探したいようです。
ruby1.9には対応してないってことなのかな?

$ ls hello/.gems/bundler_gems/jruby/
1.9.1
$ 
.gems/bundler_gems/jruby/1.8/environment (LoadError)

次回 に続きます。

gae上でjrubyを動かしたい。までの道のり2

何がしたいの?

誰が使うの?

  • rubyアプリケーションをgae上で公開したい人
  • 自サーバやレンタルサーバは運用したくないけどサービスを公開したい人
  • 動的なスケールアップが可能な環境でサービスを公開したい人

どのように機能するの?

  • appengine-java-sdkの上でjrubyを動作させます。jrubyの上でrubyを動作させます。
  • さらにそのrubyの上でrubyのライブラリやアプリケーションを動作させます。

何を使うの?

-appengine-java-sdk
-jruby
gem「google-appengine」に含まれており、別途用意する必要は無い。

どこで確認したの?

いつ確認したの?

  • 2010年3月23日

何か注意点はあるの?

  • 手元の環境ではruby1.9ではアプリケーションの構築に失敗しました。ruby1.8でHelloWorldに成功しました。原因は分かりましたが対策が分かりませんした。



前回 からの続きです。

調べてみたもののどのように対策して良いものかわかりません。
切り分けのために大胆にも一旦ruby1.9環境を捨ててmacosの標準の1.8に戻ってみます。
その前にruby1.9でインストールした/opt/local/bin/appcfg.rbと
この後ruby1.8でインストールする/usr/bin/appcfg.rbの名前衝突を避けるために一旦1.9側のgemからappengine-toolsを削除します。

$ sudo gem uninstall appengine-tools
Password:
Remove executables:
	appcfg.rb, dev_appserver.rb

in addition to the gem? [Yn]  Y
Removing appcfg.rb
Removing dev_appserver.rb

You have requested to uninstall the gem:
	appengine-tools-0.0.10.1
google-appengine-0.0.10.1 depends on [appengine-tools (= 0.0.10.1)]
If you remove this gems, one or more dependencies will not be met.
Continue with Uninstall? [Yn]  Y
Successfully uninstalled appengine-tools-0.0.10.1
$ 
$ which ruby
/opt/local/bin/ruby
$ 
$ sudo port uninstall ruby19
Password:
--->  Deactivating ruby19 @1.9.1-p376_0+nosuffix
--->  Uninstalling ruby19 @1.9.1-p376_0+nosuffix
$ 
$ which ruby
/usr/bin/ruby
$ 
$ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0]
$ 
$ 


gemのバージョンアップは先ほどと同じ手順で...と思いきやupdate_rubygemsが動作しません。
macportのgemはパスが通っている/opt/loca/binにupdate_rubygemsを配置してくれましたが、こっちはその気は無いようです。

$ gem -v
1.3.1
$ 
$ 
$ gem search -r rubygems-update

*** REMOTE GEMS ***

rubygems-update (1.3.6)
$ 
$ which gem
/usr/bin/gem
$ 
$ sudo gem install rubygems-update
Successfully installed rubygems-update-1.3.6
1 gem installed
Installing ri documentation for rubygems-update-1.3.6...
Installing RDoc documentation for rubygems-update-1.3.6...
Could not find main page README
Could not find main page README
Could not find main page README
Could not find main page README
$ 
$ sudo update_rubygems
sudo: unable to execute /opt/local/bin/update_rubygems: No such file or directory
$ 


半分やけっぱちで直パスで叩いてみます。でもダメ。

$ 
$ sudo /Library/Ruby/Gems/1.8/gems/rubygems-update-1.3.6/bin/update_rubygems 
Error: Cannot find RubyGems Update Path!

RubyGems has already been updated.
The rubygems-update gem may now be uninstalled.
E.g.    gem uninstall rubygems-update
$ 
$ gem -v
1.3.1
$ 
$


結局 -update --sysytemでアップデートしました。

$ 
$ sudo gem update --system
Updating RubyGems
Updating rubygems-update
Successfully installed rubygems-update-1.3.6
:0:Warning: Gem::SourceIndex#search support for String patterns is deprecated
Updating RubyGems to 1.3.6
Installing RubyGems 1.3.6
RubyGems 1.3.6 installed

=== 1.3.6 / 2010-02-17
中略
$
$ gem -v
1.3.6
$ 


何度目だろうかリトライ...成功。

$ 
$ sudo gem install google-appengine
Password:
Successfully installed rack-1.1.0
Successfully installed appengine-rack-0.0.6
Successfully installed appengine-sdk-1.3.1
Successfully installed appengine-jruby-jars-0.0.6
Successfully installed bundler08-0.8.5
Successfully installed rubyzip-0.9.4
Successfully installed appengine-tools-0.0.10.1
Successfully installed google-appengine-0.0.10.1
8 gems installed

とうとう成功。そしてサヨウナラruby1.9。早すぎたんだ(ry....

$ 
$ appcfg.rb generate_app myhello18
=> Generating gemfile
=> Bundling gems
Calculating dependencies...
Updating source: http://gems.rubyforge.org
/Library/Ruby/Gems/1.8/gems/bundler08-0.8.5/lib/bundler08/resolver.rb:115:Warning: Gem::Dependency#version_requirements is deprecated and will be removed on or after August 2010.  Use #requirement
Caching: appengine-rack-0.0.6.gem
Caching: rack-1.1.0.gem
Installing rack (1.1.0)
Installing appengine-rack (0.0.6)
Done.
=> Packaging gems
=> Installing JRuby
=> Installing JRuby-Rack
=> Installing appengine-sdk
=> Generating rackup
=> Generating configuration files
$ 
$ 


そして開発サーバ起動...ちょっとエラーでているけど成功。

$ dev_appserver.rb myhello18
=> Booting DevAppServer
=> Press Ctrl-C to shutdown server
2010-03-23 23:17:53.344 java[67777:1707] [Java CocoaComponent compatibility mode]: Enabled
2010-03-23 23:17:53.347 java[67777:1707] [Java CocoaComponent compatibility mode]: Setting timeout for SWT to 0.100000
2010/03/23 14:17:55 com.google.appengine.tools.development.agent.impl.BlackList initBlackList
?v???I: Unable to read a jre library while constructing the blacklist. Security restrictions may not be entirely emulated. /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/lib/plugin.jar
The server is running at http://localhost:8080/
^C$ 
$ 
$ 

Xcodeでソースコードのバージョン管理をしたい


何がしたいの?

  • 変更のスナップショットを適宜取りながら安全にコード変更がしたい
  • XcodeでSCM機能を使ってソースコードのバージョン管理をしたい
  • Xcodeのオーガナイザをエディタ替わりに使っているだけだけどバージョン管理したい
  • 開発者ひとりしかないけどバージョン管理したい

誰が使うの?

  • コードをちょっと変更したら動作しなくなって慌ててバックアップを探すことがある人

どのように機能するの?

何を使うの?

どこで確認したの?

いつ確認したの?

  • 2010年3月16日

何か注意点はあるの?

  • 特にありません。

どんな手順でやるの?

  • まずはmacport経由でインストール
$ sudo port install subversion
$ pwd
/opt/svn
$ 
$ svnadmin create /opt/svn/svntest --fs-type fsfs
$ ls -r svntest/
locks      hooks      format     db         conf       README.txt
$ 
  • 参考ブログによるとtrunk,branches,tagというディレクトリ名が王道らしいので巻かれてみます。
$ mkdir -p /tmp/svntest/trunk
$ mkdir -p /tmp/svntest/branches
$ mkdir -p /tmp/svntest/tags
$ ls /tmp/svntest
branches tags     trunk
$ 
$ svn import /tmp/svntest/ file:////opt/svn/svntest -m "Initial import"
追加しています              /tmp/svntest/trunk
追加しています              /tmp/svntest/branches
追加しています              /tmp/svntest/tags

リビジョン 1 をコミットしました。
$ 
  • XcodeでSCM追加
    • メニュー[SCM]-[SCMリポジトリを構成]を選択してボタン[+]を選択して新しいリポジトリを追加します。
    • URL→file:///opt/svn/svntestを入力して暫く待つと、名前やスキーム、パスが自動的に補完されて一番下に[認証されました]の表示が現れます。


  • XcodeのSCMメニューに[リポジトリ]が追加されているのでので選択します。
    • 見慣れない画面が開きました。ボタン[読み込む]で管理対象のディレクトリを読み込みます。


  • メニュー[表示]-[ツールバーをカスタマイズ]を選択して、[復元]と[スナップショットを]をツールバーに追加します。
    • [復元]ボタンでウィンドウ[スナップショット]が開きます。
    • [スナップショット]ウィンドウのボタン[作成]でスナップショットを作成します。
    • 過去のスナップショットと現在のコードの差分を確認できます。
    • スナップショットを2つ選択すると2つのスナップショット間の差分も確認できます。
    • オーガナイザの[スナップショットボタン]はツリー[PROJECT&SOURCES]でディレクトリを選択しているときのみ有効なようです。



  • 管理対象のディレクトリ内であれば、チェックアウトしてなくてもファイルもスナップショット間の差分が取れます。
    • 管理対象のディレクトリへのファイル追加や削除も自動検出します。
    • ファイルの出入が激しい実験的なプロジェクトにはとても助かる機能です。

    • もちろんsubversionをチェックイン、チェックアウトによる長期的なソースコード管理にも使用するわけですが、
    • コンパイルが通る度、テストが通る度に気軽にスナップショットをパシャパシャ取ることでコード変更が気軽にできるようになるかもしれません。

Xcodeの中からrubyスクリプトを実行したい


何がしたいの?

  • Xcodeの中からRubyプログラムを一撃で実行したい

誰が使うの?

  • Xcodeとターミナルの行ったり来たりが面倒な人

どのように機能するの?

何を使うの?

  • Xcode オーガナイザ

どこで確認したの?

いつ確認したの?

  • 2010年3月13日

何か注意点はあるの?

  • 特にありません

どんな手順でやるの?

  • Xcodeを起動します
  • メニュー[ウィンドウ]-[オーガナイザ]
  • 対象のスクリプトファイルまたはディレクトリを左ペイン[PROJECT&SOURCES]ツリーにドラッグます。


  • ツールバー[アクション]を長押し後[アクションを編集]を選択します。

・左下の[+]を選択してドロップダウンメニューより[新規シェルスクリプト]を選択します。
・コマンド入力画面に下記のコマンドを入力します。
rubyのパスは環境に合わせて調整してください。

#!/bin/sh

INPUT=`cat -`
/opt/local/bin/ruby $INPUT

・ドロップダウン[入力]はどれでも結果には関係ありませんが、とりあえず[選択部分]を選択します。
・ドロップダウン[ディレクトリ]は[定義しているオーガナイザ項目]を選択します。
・ドロップダウン[出力]は[警告に表示]を選択します。
・ドロップダウン[エラー]は[選択部分]はどれでも似たような結果が得られますが、とりあえず[スクリプト出力と結合]を選択します。
・スクロールバーの左脇あたりをクリックするとショートカットキーの入力画面になりますので、空いているキーを割り当てます。
・[OK]を選択します。
・割り当てたショートカットキーを選択すると実行結果が警告ダイアログボックに表示されます。