バリケンのRuby日記 RSSフィード

2009-10-23

[][][] Scanty on GAE/J  Scanty on GAE/J - バリケンのRuby日記 を含むブックマーク はてなブックマーク -  Scanty on GAE/J - バリケンのRuby日記  Scanty on GAE/J - バリケンのRuby日記 のブックマークコメント

Rubyの軽量Webアプリケーションフレームワーク「Sinatra」で実装されたブログエンジン「Scanty」を、Google App Engine for Java上でJRubyを使って動かすための、自分用のメモだよ。

ここでの手順は、Debian GNU/Linux 5.0.3 (lenny)で行うことを想定しているよ。

Java SDKのインストール

まだJava SDKをインストールしていない人は、インストールしてね。インストールするには/etc/apt/sources.list

deb http://ftp.jp.debian.org/debian/ lenny main

となっているところにnon-freeを追加して、

deb http://ftp.jp.debian.org/debian/ lenny main non-free

そのあと「apt-get install sun-java6-jdk」と入力すればインストールできるよ。

# apt-get install sun-java6-jdk

Google App Engine for Java SDKのダウンロードと展開

まだGoogle App Engine for Java SDKを入手していない人は、ダウンロードしてね。Linuxの場合、wgetコマンドでダウンロードするのが便利だよ。まだwgetコマンドをインストールしていない場合は、

# apt-get install wget

としてインストールしてね。あと、zipファイルの展開にはunzipコマンドが必要だから、同様に

# apt-get install unzip

としてインストールしてね。wgetコマンドとunzipコマンドが使えるようになったら、次のようにコマンドを入力して展開してね。

$ cd ~
$ wget http://googleappengine.googlecode.com/files/appengine-java-sdk-1.2.6.zip
$ unzip appengine-java-sdk-1.2.6.zip

scantyディレクトリの作成

$ cd ~
$ mkdir scanty
$ cd scanty

Scantyのソースコードの入手

Scantyのソースコードを入手するにはgitコマンドが必要だよ。まだgitコマンドをインストールしていない場合は、

# apt-get install git-core

としてインストールしてね。Google App Engineにデプロイするので、WEB-INFというディレクトリ名でgit cloneするよ。

$ git clone git://github.com/adamwiggins/scanty.git WEB-INF

jruby-complete-1.4.0RC1.jarのダウンロード

$ wget http://dist.codehaus.org/jruby/1.4.0RC1/jruby-complete-1.4.0RC1.jar

Scantyを動作させるのに必要なgemのインストール

JRubygemコマンドを使って、必要となるライブラリを入手するよ。

$ mkdir WEB-INF/gems
$ java -jar jruby-complete-1.4.0RC1.jar -S gem install -i WEB-INF/gems sinatra --no-ri --no-rdoc
$ java -jar jruby-complete-1.4.0RC1.jar -S gem install -i WEB-INF/gems dm-core --version 0.9.11 --no-ri --no-rdoc
$ java -jar jruby-complete-1.4.0RC1.jar -S gem install -i WEB-INF/gems dm-aggregates --version 0.9.11 --no-ri --no-rdoc
$ java -jar jruby-complete-1.4.0RC1.jar -S gem install -i WEB-INF/gems dm-types --version 0.9.11 --no-ri --no-rdoc
$ java -jar jruby-complete-1.4.0RC1.jar -S gem install -i WEB-INF/gems dm-datastore-adapter --no-ri --no-rdoc
$ java -jar jruby-complete-1.4.0RC1.jar -S gem install -i WEB-INF/gems builder --no-ri --no-rdoc
$ rm WEB-INF/gems/cache/*

jruby-core.jarruby-stdlib.jarlibフォルダに作成

次のようにコマンドを入力して、「jruby-complete-1.4.0RC1.jar」から「jruby-core.jar」と「ruby-stdlib.jar」を作成するよ。ここでは元となる「jruby-complete-1.4.0RC1.jar」は削除しているけど、削除したくない人は他のディレクトリにコピーしておいてね。

$ mkdir tmp_unpack
$ cd tmp_unpack
$ jar xf ../jruby-complete-1.4.0RC1.jar
$ cd ..
$ mkdir jruby-core
$ mv tmp_unpack/org jruby-core
$ mv tmp_unpack/com jruby-core
$ mv tmp_unpack/jline jruby-core
$ mv tmp_unpack/jay jruby-core
$ mv tmp_unpack/jruby jruby-core
$ cd jruby-core
$ jar cf ../jruby-core.jar .
$ cd ../tmp_unpack
$ jar cf ../ruby-stdlib.jar .
$ cd ..
$ rm -rf jruby-core
$ rm -rf tmp_unpack
$ mv jruby-core.jar WEB-INF/lib
$ mv ruby-stdlib.jar WEB-INF/lib
$ rm jruby-complete-1.4.0RC1.jar

appengine-api-1.0-sdk-1.2.6.jarのコピー

次のコマンドを入力して、「appengine-api-1.0-sdk-1.2.6.jar」ファイルをコピーするよ。

$ cp ../appengine-java-sdk-1.2.6/lib/user/appengine-api-1.0-sdk-1.2.6.jar WEB-INF/lib

jruby-rack-0.9.5.jarのダウンロード

$ wget http://kenai.com/projects/jruby-rack/downloads/download/jruby-rack-0.9.5.jar
$ mv jruby-rack-0.9.5.jar WEB-INF/lib

ソースコードにパッチを適用

テキストエディタで次の内容のファイルをscanty_gae_patch.diffという名前で保存してね。

diff -cr scanty_orig/lib/post.rb scanty_gae/lib/post.rb
*** scanty_orig/lib/post.rb	2009-10-23 15:16:31.000000000 +0900
--- scanty_gae/lib/post.rb	2009-10-23 15:08:46.000000000 +0900
***************
*** 1,20 ****
  require File.dirname(__FILE__) + '/../vendor/maruku/maruku'
  
  $LOAD_PATH.unshift File.dirname(__FILE__) + '/../vendor/syntax'
  require 'syntax/convertors/html'
  
! class Post < Sequel::Model
! 	unless table_exists?
! 		set_schema do
! 			primary_key :id
! 			text :title
! 			text :body
! 			text :slug
! 			text :tags
! 			timestamp :created_at
! 		end
! 		create_table
! 	end
  
  	def url
  		d = created_at
--- 1,28 ----
+ gem "dm-core", "0.9.11"
+ 
+ require 'dm-core'
+ require 'dm-aggregates'
+ require 'dm-types'
+ require 'dm-datastore-adapter/datastore-adapter'
+ 
+ DataMapper.setup(:datastore,
+                  :adapter => :datastore,
+                  :database => 'posts')
+ 
  require File.dirname(__FILE__) + '/../vendor/maruku/maruku'
  
  $LOAD_PATH.unshift File.dirname(__FILE__) + '/../vendor/syntax'
  require 'syntax/convertors/html'
  
! class Post
!   include DataMapper::Resource
!   def self.default_repository_name; :datastore end
!   property :id,         Serial
!   property :title,      Text,     :lazy => false
!   property :body,       Text,     :lazy => false
!   property :slug,       Text,     :lazy => false
!   property :tags,       Text,     :lazy => false
!   property :created_at, DateTime
  
  	def url
  		d = created_at
diff -cr scanty_orig/main.rb scanty_gae/main.rb
*** scanty_orig/main.rb	2009-10-23 15:16:31.000000000 +0900
--- scanty_gae/main.rb	2009-10-23 15:08:48.000000000 +0900
***************
*** 1,11 ****
  require 'rubygems'
  require 'sinatra'
  
! $LOAD_PATH.unshift File.dirname(__FILE__) + '/vendor/sequel'
! require 'sequel'
  
  configure do
! 	Sequel.connect(ENV['DATABASE_URL'] || 'sqlite://blog.db')
  
  	require 'ostruct'
  	Blog = OpenStruct.new(
--- 1,11 ----
  require 'rubygems'
  require 'sinatra'
  
! #$LOAD_PATH.unshift File.dirname(__FILE__) + '/vendor/sequel'
! #require 'sequel'
  
  configure do
! 	#Sequel.connect(ENV['DATABASE_URL'] || 'sqlite://blog.db')
  
  	require 'ostruct'
  	Blog = OpenStruct.new(
***************
*** 44,55 ****
  ### Public
  
  get '/' do
! 	posts = Post.reverse_order(:created_at).limit(10)
  	erb :index, :locals => { :posts => posts }, :layout => false
  end
  
  get '/past/:year/:month/:day/:slug/' do
! 	post = Post.filter(:slug => params[:slug]).first
  	stop [ 404, "Page not found" ] unless post
  	@title = post.title
  	erb :post, :locals => { :post => post }
--- 44,56 ----
  ### Public
  
  get '/' do
! 	posts = Post.all(:limit => 10, :order => [:created_at.asc])
! #	posts = Post.all(:order => [:created_at.asc])
  	erb :index, :locals => { :posts => posts }, :layout => false
  end
  
  get '/past/:year/:month/:day/:slug/' do
! 	post = Post.first(:slug => params[:slug])
  	stop [ 404, "Page not found" ] unless post
  	@title = post.title
  	erb :post, :locals => { :post => post }
***************
*** 60,79 ****
  end
  
  get '/past' do
! 	posts = Post.reverse_order(:created_at)
  	@title = "Archive"
  	erb :archive, :locals => { :posts => posts }
  end
  
  get '/past/tags/:tag' do
  	tag = params[:tag]
! 	posts = Post.filter(:tags.like("%#{tag}%")).reverse_order(:created_at).limit(30)
  	@title = "Posts tagged #{tag}"
  	erb :tagged, :locals => { :posts => posts, :tag => tag }
  end
  
  get '/feed' do
! 	@posts = Post.reverse_order(:created_at).limit(20)
  	content_type 'application/atom+xml', :charset => 'utf-8'
  	builder :feed
  end
--- 61,80 ----
  end
  
  get '/past' do
! 	posts = Post.all(:order => [:created_at.asc])
  	@title = "Archive"
  	erb :archive, :locals => { :posts => posts }
  end
  
  get '/past/tags/:tag' do
  	tag = params[:tag]
! 	posts = Post.all(:tags => tag, :limit => 30, :order => [:created_at.asc])
  	@title = "Posts tagged #{tag}"
  	erb :tagged, :locals => { :posts => posts, :tag => tag }
  end
  
  get '/feed' do
! 	@posts = Post.all(:limit => 20, :order => [:created_at.asc])
  	content_type 'application/atom+xml', :charset => 'utf-8'
  	builder :feed
  end
***************
*** 107,120 ****
  
  get '/past/:year/:month/:day/:slug/edit' do
  	auth
! 	post = Post.filter(:slug => params[:slug]).first
  	stop [ 404, "Page not found" ] unless post
  	erb :edit, :locals => { :post => post, :url => post.url }
  end
  
  post '/past/:year/:month/:day/:slug/' do
  	auth
! 	post = Post.filter(:slug => params[:slug]).first
  	stop [ 404, "Page not found" ] unless post
  	post.title = params[:title]
  	post.tags = params[:tags]
--- 108,121 ----
  
  get '/past/:year/:month/:day/:slug/edit' do
  	auth
! 	post = Post.first(:slug => params[:slug])
  	stop [ 404, "Page not found" ] unless post
  	erb :edit, :locals => { :post => post, :url => post.url }
  end
  
  post '/past/:year/:month/:day/:slug/' do
  	auth
! 	post = Post.first(:slug => params[:slug])
  	stop [ 404, "Page not found" ] unless post
  	post.title = params[:title]
  	post.tags = params[:tags]
diff -cr scanty_orig/views/feed.builder scanty_gae/views/feed.builder
*** scanty_orig/views/feed.builder	2009-10-23 15:16:31.000000000 +0900
--- scanty_gae/views/feed.builder	2009-10-23 15:08:46.000000000 +0900
***************
*** 2,17 ****
  xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
  	xml.title Blog.title
  	xml.id Blog.url_base
! 	xml.updated @posts.first[:created_at].iso8601 if @posts.any?
  	xml.author { xml.name Blog.author }
  
  	@posts.each do |post|
  		xml.entry do
! 			xml.title post[:title]
  			xml.link "rel" => "alternate", "href" => post.full_url
  			xml.id post.full_url
! 			xml.published post[:created_at].iso8601
! 			xml.updated post[:created_at].iso8601
  			xml.author { xml.name Blog.author }
  			xml.summary post.summary_html, "type" => "html"
  			xml.content post.body_html, "type" => "html"
--- 2,17 ----
  xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
  	xml.title Blog.title
  	xml.id Blog.url_base
! 	xml.updated @posts.first.created_at if @posts.any?
  	xml.author { xml.name Blog.author }
  
  	@posts.each do |post|
  		xml.entry do
! 			xml.title post.title
  			xml.link "rel" => "alternate", "href" => post.full_url
  			xml.id post.full_url
! 			xml.published post.created_at
! 			xml.updated post.created_at
  			xml.author { xml.name Blog.author }
  			xml.summary post.summary_html, "type" => "html"
  			xml.content post.body_html, "type" => "html"
diff -cr scanty_orig/views/index.erb scanty_gae/views/index.erb
*** scanty_orig/views/index.erb	2009-10-23 15:16:31.000000000 +0900
--- scanty_gae/views/index.erb	2009-10-23 15:08:46.000000000 +0900
***************
*** 16,23 ****
  <div id="content">
  	<% posts.each do |post| %>
  	<div class="post">
! 		<p class="date"><%= post[:created_at].strftime("%b") %><b><%= post[:created_at].strftime("%d") %></b></p>
! 		<h2 class="title"><a href="<%= post.url %>"><%= post[:title] %></a></h2>
  		<p class="meta"><small>
  			<%= post.linked_tags %>
  			<% if Blog.disqus_shortname %>
--- 16,23 ----
  <div id="content">
  	<% posts.each do |post| %>
  	<div class="post">
! 		<p class="date"><%= post.created_at.strftime("%b") %><b><%= post.created_at.strftime("%d") %></b></p>
! 		<h2 class="title"><a href="<%= post.url %>"><%= post.title %></a></h2>
  		<p class="meta"><small>
  			<%= post.linked_tags %>
  			<% if Blog.disqus_shortname %>
diff -cr scanty_orig/views/tagged.erb scanty_gae/views/tagged.erb
*** scanty_orig/views/tagged.erb	2009-10-23 15:16:31.000000000 +0900
--- scanty_gae/views/tagged.erb	2009-10-23 15:08:46.000000000 +0900
***************
*** 1,8 ****
  <h1>Posts tagged <%= tag %></h1>
  <% posts.each do |post| %>
  <div class="post">
! 	<p class="date"><%= post[:created_at].strftime("%b") %><b><%= post[:created_at].strftime("%d") %></b></p>
! 	<h2 class="title"><a href="<%= post.url %>"><%= post[:title] %></a></h2>
  	<p class="meta"><small><%= post.linked_tags %> | <a href="<%= post.url %>#disqus_thread">comments</a></small></p>
  	<div class="entry">
  		<%= post.summary_html %>
--- 1,8 ----
  <h1>Posts tagged <%= tag %></h1>
  <% posts.each do |post| %>
  <div class="post">
! 	<p class="date"><%= post.created_at.strftime("%b") %><b><%= post.created_at.strftime("%d") %></b></p>
! 	<h2 class="title"><a href="<%= post.url %>"><%= post.title %></a></h2>
  	<p class="meta"><small><%= post.linked_tags %> | <a href="<%= post.url %>#disqus_thread">comments</a></small></p>
  	<div class="entry">
  		<%= post.summary_html %>

次のコマンドでパッチを適用してね。

$ patch -p1 -d WEB-INF < scanty_gae_patch.diff

WEB-INF/appengine-web.xmlの作成

テキストエディタで次の内容を入力して、WEB-INFディレクトリの中にappengine-web.xmlという名前で保存してね。

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    <application>scanty</application>
    <version>1</version>
    <static-files>
      <include path="/public/**.*" />
    </static-files>
    <resource-files />
    <sessions-enabled>false</sessions-enabled>
    <system-properties>
      <property name="jruby.management.enabled" value="false" />
      <property name="os.arch" value="" />
      <property name="jruby.compile.mode" value="JIT"/> <!-- JIT|FORCE|OFF -->
      <property name="jruby.compile.fastest" value="true"/>
      <property name="jruby.compile.frameless" value="true"/>
      <property name="jruby.compile.positionless" value="true"/>
      <property name="jruby.compile.threadless" value="false"/>
      <property name="jruby.compile.fastops" value="false"/>
      <property name="jruby.compile.fastcase" value="false"/>
      <property name="jruby.compile.chainsize" value="500"/>
      <property name="jruby.compile.lazyHandles" value="false"/>
      <property name="jruby.compile.peephole" value="true"/>
   </system-properties>
</appengine-web-app>

WEB-INF/web.xmlの作成

テキストエディタで次の内容を入力して、WEB-INFディレクトリの中にweb.xmlという名前で保存してね。

<!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

  <context-param>
    <param-name>public.root</param-name>
    <param-value>/</param-value>
  </context-param>

  <context-param>
    <param-name>rackup</param-name>
    <param-value>require 'rubygems'
require 'sinatra'

root_dir = File.dirname(__FILE__)

#set :environment, :production
set :environment, :development
set :root,        root_dir
set :app_file,    File.join(root_dir, 'main.rb')
disable :run

require 'main'

run Sinatra::Application

</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.min.runtimes</param-name>
    <param-value>1</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.max.runtimes</param-name>
    <param-value>1</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.init.serial</param-name>
    <param-value>true</param-value>
  </context-param>

  <filter>
    <filter-name>RackFilter</filter-name>
    <filter-class>org.jruby.rack.RackFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>RackFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <listener>
    <listener-class>org.jruby.rack.RackServletContextListener</listener-class>
  </listener>

</web-app>

開発用サーバの起動

次のコマンドを入力して、開発用サーバを起動してね。

$ ../appengine-java-sdk-1.2.6/bin/dev_appserver.sh .

Webブラウザで開発用サーバにアクセス

http://localhost:8080/にアクセスして、動作確認してね。デフォルトではログインパスワードは「changeme」だよ。

Google App Engineにデプロイ

「appengine-web.xml」の「application」と「version」を適切に設定して、次のコマンドを実行してね。

$ ../appengine-java-sdk-1.2.6/bin/appcfg.sh update .
トラックバック - http://rubyist.g.hatena.ne.jp/muscovyduck/20091023

2009-08-23

[][][] 「Ramazeを使って120行で作る単語帳アプリ」 on GAE/J  「Ramazeを使って120行で作る単語帳アプリ」 on GAE/J - バリケンのRuby日記 を含むブックマーク はてなブックマーク -  「Ramazeを使って120行で作る単語帳アプリ」 on GAE/J - バリケンのRuby日記  「Ramazeを使って120行で作る単語帳アプリ」 on GAE/J - バリケンのRuby日記 のブックマークコメント

Ruby Freaks Lounge:第12回 Ramazeを使って120行で作る単語帳アプリ|gihyo.jp … 技術評論社」という記事にある単語帳アプリを、Google App Engine for Java上でJRubyを使って動かすための、自分用のメモだよ。

ここでの手順は、Windowsで行うことを想定しているよ。

あと、残念ながらバリデーションがうまく動かなかったから、ここでの例では同じ単語を複数登録することができてしまうよ。

Java SDKのダウンロードとインストール

まだJava SDKをインストールしていない人は、ダウンロードしてインストールしてね。

Java SDKをインストールするには、Java SDKのダウンロードサイトにアクセスして、下のほうにある「JDK 6 Update 16」の右側の「Download」をクリックしてね。Platformは「Windows」を選択してね。

ダウンロードしたインストーラ「jdk-6u16-windows-i586.exe」をダブルクリックすると、インストールが始まるよ。

Google App Engine for Java SDKのダウンロードと展開

まだGoogle App Engine for Java SDKを入手していない人は、ダウンロードしてね。

Google App Engine for Java SDKを入手するには、Google App Engineのダウンロードサイトにアクセスして、「appengine-java-sdk-1.2.2.zip」をクリックしてダウンロードしてね。ダウンロードした「appengine-java-sdk-1.2.2.zip」ファイルは圧縮されているから、Cドライブ直下に展開してね。

ramazewordsディレクトリの作成

コマンドプロンプトを起動して、次のようにコマンドを入力してね

空白を含むパス上だとうまく動かないみたいなので、ここではCドライブ直下に作成しているよ

> cd \
> mkdir ramazewords
> cd \ramazewords

jruby-complete-1.3.1.jarのダウンロードと設置

まだ「jruby-complete-1.3.1.jar」を入手していない人は、ダウンロードしてね。入手先はJRubyのサイトだよ。

jruby-complete-1.3.1.jar」をクリックしてダウンロードしたら、先ほど作ったC:\ramazewordsフォルダに配置してね。

WEB-INFフォルダの作成

先ほど作った「ramazewords」ディレクトリの中に、次のように3つのディレクトリを作成するよ。

> mkdir WEB-INF
> mkdir WEB-INF\gems
> mkdir WEB-INF\lib

Ramaze、DataMapperのインストール

JRubygemコマンドを使って、必要となるライブラリを入手するよ。

> set JAVA_HOME=C:\PROGRA~1\Java\jdk1.6.0_16
> set PATH=%JAVA_HOME%\bin;C:\appengine-java-sdk-1.2.2\bin;%PATH%
> java -jar jruby-complete-1.3.1.jar -S gem install -i WEB-INF\gems ramaze --no-ri --no-rdoc
> java -jar jruby-complete-1.3.1.jar -S gem install -i WEB-INF\gems addressable --no-ri --no-rdoc
> java -jar jruby-complete-1.3.1.jar -S gem install -i WEB-INF\gems dm-datastore-adapter --no-ri --no-rdoc
> java -jar jruby-complete-1.3.1.jar -S gem install -i WEB-INF\gems dm-validations --no-ri --no-rdoc
> rmdir /s /q WEB-INF\gems\bin
> del /q WEB-INF\gems\cache\*

jruby-core.jarruby-stdlib.jarlibフォルダに作成

次のようにコマンドを入力して、「jruby-complete-1.3.1.jar」から「jruby-core.jar」と「ruby-stdlib.jar」を作成するよ。ここでは元となる「jruby-complete-1.3.1.jar」は削除しているけど、削除したくない人は他のフォルダにコピーしておいてね。

> mkdir tmp_unpack
> cd tmp_unpack
> jar xf ../jruby-complete-1.3.1.jar
> cd ..
> mkdir jruby-core
> move tmp_unpack\org jruby-core
> move tmp_unpack\com jruby-core
> move tmp_unpack\jline jruby-core
> move tmp_unpack\jay jruby-core
> move tmp_unpack\jruby jruby-core
> cd jruby-core
> jar cf ../jruby-core.jar .
> cd ..\tmp_unpack
> jar cf ../ruby-stdlib.jar .
> cd ..
> rmdir /s /q jruby-core
> rmdir /s /q tmp_unpack
> move jruby-core.jar WEB-INF\lib
> move ruby-stdlib.jar WEB-INF\lib
> del jruby-complete-1.3.1.jar

appengine-api-1.0-sdk-1.2.2.jarのコピー

次のコマンドを入力して、「appengine-api-1.0-sdk-1.2.2.jar」ファイルをコピーするよ。

> copy C:\appengine-java-sdk-1.2.2\lib\user\appengine-api-1.0-sdk-1.2.2.jar WEB-INF\lib

jruby-rack-0.9.5-SNAPSHOT.jarのダウンロードと配置

こちらのサイトから「jruby-rack-0.9.5-SNAPSHOT.jar」をダウンロードして、C:\ramazewords\WEB-INF\libに配置してね。ダウンロードは右下のほうの「raw」というリンクをクリックしてね。

WEB-INF/app.rbの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にapp.rbという名前で保存してね。

require 'rubygems'
require 'ramaze'

require 'dm-core'
require 'dm-aggregates'
require 'dm-types'
require 'dm-datastore-adapter/datastore-adapter'
#require 'dm-validations'

# Model
DataMapper.setup(:datastore,
                 :adapter => :datastore,
                 :database => 'words')

class Word
  include DataMapper::Resource
  def self.default_repository_name; :datastore end
  property :id, Serial
  property :name, String
  property :description, Text,     :lazy => false

#  validates_is_unique :name
end
#DataMapper.auto_upgrade!

# Controller
class WordController < Ramaze::Controller
  map '/'
  engine :ERB
  layout 'default'

  def index
    @words = Word.all
  end

  def new
  end

  def create
    word = Word.create(
      :name => request[:name],
      :description => request[:description]
    )
    if word
      redirect r(:show, word.id)
    else
      redirect_referer
    end
  end

  def show(id)
    @word = Word.get(id)
  end

  def delete(id)
    redirect_referer unless request.post?
    word = Word.get(id)
    if word
      word.destroy
      redirect r(:index)
    else
      redirect_referer
    end
  end

  def random
    at = rand(Word.count)
    @word = Word.first(:offset => at)
    render_view :show
  end
end

WEB-INF/layout/default.html.erbの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にlayoutフォルダを作成して、そこにdefault.html.erbという名前で保存してね。あ、このファイルは日本語を含んでいるから、ファイルを保存するときは文字コードを「UTF-8」に設定してね。

<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>単語帳</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <link href="/screen.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" src="/jquery-1.3.2.min.js" />
  </head>
  <body>
    <h1>単語帳</h1>

    <%= @content %>
  </body>
</html>

WEB-INF/view/index.html.erbの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にviewフォルダを作成して、そこにindex.html.erbという名前で保存してね。このファイルも日本語を含んでいるから、ファイルを保存するときは文字コードを「UTF-8」に設定してね。

<h2>単語一覧</h2>
<div class="box"><ul>
  <% @words.each do |word| %>
    <li><%= a(word.name, :show, word.id) %></li>
  <% end %>
</ul>
</div>

<ul>
  <li><%= a("(新規作成)", :new) %></li>
  <li><%= a("(ランダム表示)", :random) %></li>
</ul>

WEB-INF/view/new.html.erbの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中のviewフォルダの中にnew.html.erbという名前で保存してね。このファイルも日本語を含んでいるから、ファイルを保存するときは文字コードを「UTF-8」に設定してね。

<h2>単語の追加</h2>
<form method="POST" action="create">
  <ul>
    <li>単語:<input type="text" name="name"></li>
    <li>解説:<textarea name="description" cols="80" rows="10"></textarea></li>
    <br/><input type="submit" value="登録">
  </ul>
</form>
<%= a('キャンセル', :index) %>

WEB-INF/view/show.html.erbの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中のviewフォルダの中にshow.html.erbという名前で保存してね。このファイルも日本語を含んでいるから、ファイルを保存するときは文字コードを「UTF-8」に設定してね。

<div class="box">
  <h3><%=h @word.name %></h3>
  <pre><%=h @word.description %></pre>
  <a href="#" id="asdf">(削除)</a>
</div>

<%= a("一覧に戻る", :index) %>

<script type="text/javascript">
$(document).ready(function(){
  $("#asdf").click(function(){
    if(confirm('本当に?')){
      $.post("<%= r(:delete, @word.id) %>", function(){
        location.href = "<%= r(:index) %>";
      });
    }
  });
});
</script>

WEB-INF/public/screen.cssの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にpublicフォルダを作成して、そこにscreen.cssという名前で保存してね。

body {
  width: 60%;
  padding-left: 20%;
}
h1, h2, form, .box {
  border: 2px dashed black;
  margin: 10px;
  padding: 8px;
}

jquery-1.3.2.min.jsのダウンロードと配置

こちらのサイトから「jquery-1.3.2.min.js」ファイルをダウンロードして、C:\ramazewords\WEB-INF\publicに配置してね。

WEB-INF/appengine-web.xmlの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にappengine-web.xmlという名前で保存してね。

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    <application>ramaze_on_gae</application>
    <version>1</version>
    <static-files>
      <include path="/public/**.*" />
    </static-files>
    <resource-files />
    <sessions-enabled>false</sessions-enabled>
    <system-properties>
      <property name="jruby.management.enabled" value="false" />
      <property name="os.arch" value="" />
      <property name="jruby.compile.mode" value="JIT"/> <!-- JIT|FORCE|OFF -->
      <property name="jruby.compile.fastest" value="true"/>
      <property name="jruby.compile.frameless" value="true"/>
      <property name="jruby.compile.positionless" value="true"/>
      <property name="jruby.compile.threadless" value="false"/>
      <property name="jruby.compile.fastops" value="false"/>
      <property name="jruby.compile.fastcase" value="false"/>
      <property name="jruby.compile.chainsize" value="500"/>
      <property name="jruby.compile.lazyHandles" value="false"/>
      <property name="jruby.compile.peephole" value="true"/>
   </system-properties>
</appengine-web-app>

WEB-INF/web.xmlの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にweb.xmlという名前で保存してね。

<!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
 
  <context-param>
    <param-name>public.root</param-name>
    <param-value>/</param-value>
  </context-param>
 
  <context-param>
    <param-name>rackup</param-name>
    <param-value>require 'rubygems'

class Thread
  def Thread.exclusive
    _old = Thread.critical
    begin
      Thread.critical = true
      return yield
    ensure
      Thread.critical = _old
    end
  end
end

require 'ramaze'

require 'app'

Ramaze.start(:root => __DIR__, :started => true)
run Ramaze
</param-value>
  </context-param>
 
  <context-param>
    <param-name>jruby.min.runtimes</param-name>
    <param-value>1</param-value>
  </context-param>
 
  <context-param>
    <param-name>jruby.max.runtimes</param-name>
    <param-value>1</param-value>
  </context-param>
 
  <context-param>
    <param-name>jruby.init.serial</param-name>
    <param-value>true</param-value>
  </context-param>
 
  <filter>
    <filter-name>RackFilter</filter-name>
    <filter-class>org.jruby.rack.RackFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>RackFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
 
  <listener>
    <listener-class>org.jruby.rack.RackServletContextListener</listener-class>
  </listener>
 
</web-app>

data_objects_adapterにモンキーパッチを適用

C:\ramazewords\WEB-INF\gems\gems\dm-aggregates-0.9.11\lib\dm-aggregates\adaptersフォルダの中にあるdata_objects_adapter.rbの46行目以下の

      module SQL
        private

        alias original_property_to_column_name property_to_column_name
...

となっているところに、property_to_column_nameの定義を次のように追加するよ。

      module SQL
        private

        def property_to_column_name(repository, property, qualify)
          table_name = property.model.storage_name(repository.name) if property && property.respond_to?(:model)

          if table_name && qualify
            "#{quote_table_name(table_name)}.#{quote_column_name(property.field(repository.name))}"
          else
            quote_column_name(property.field(repository.name))
          end
        end

        alias original_property_to_column_name property_to_column_name
...

開発用サーバの起動

次のコマンドを入力して、開発用サーバを起動してね。

> dev_appserver.cmd .

Webブラウザで開発用サーバにアクセス

http://localhost:8080/にアクセスして、動作確認してね。

Google App Engineにデプロイ

「appengine-web.xml」の「application」と「version」を適切に設定して、次のコマンドを実行してね。

> appcfg.cmd update .
トラックバック - http://rubyist.g.hatena.ne.jp/muscovyduck/20090823

2009-08-22

[][] Ramaze on GAE/J  Ramaze on GAE/J - バリケンのRuby日記 を含むブックマーク はてなブックマーク -  Ramaze on GAE/J - バリケンのRuby日記  Ramaze on GAE/J - バリケンのRuby日記 のブックマークコメント

Rubyで書かれた軽量Webアプリケーション開発フレームワーク「Ramaze」をGoogle App Engine for Java上でJRubyを使って動かすための、自分用のメモだよ。ここでの手順はWindowsで行うことを想定しているよ。

Java SDKのダウンロードとインストール

まだJava SDKをインストールしていない人は、ダウンロードしてインストールしてね。

Java SDKをインストールするには、Java SDKのダウンロードサイトにアクセスして、下のほうにある「JDK 6 Update 16」の右側の「Download」をクリックしてね。Platformは「Windows」を選択してね。

ダウンロードしたインストーラ「jdk-6u16-windows-i586.exe」をダブルクリックすると、インストールが始まるよ。

Google App Engine for Java SDKのダウンロードと展開

まだGoogle App Engine for Java SDKを入手していない人は、ダウンロードしてね。

Google App Engine for Java SDKを入手するには、Google App Engineのダウンロードサイトにアクセスして、「appengine-java-sdk-1.2.2.zip」をクリックしてダウンロードしてね。ダウンロードした「appengine-java-sdk-1.2.2.zip」ファイルは圧縮されているから、Cドライブ直下に展開してね。

ramaze_on_gaeディレクトリの作成

コマンドプロンプトを起動して、次のようにコマンドを入力してね

空白を含むパス上だとうまく動かないみたいなので、ここではCドライブ直下に作成しているよ

> cd \
> mkdir ramaze_on_gae
> cd \ramaze_on_gae

jruby-complete-1.3.1.jarのダウンロードと設置

まだ「jruby-complete-1.3.1.jar」を入手していない人は、ダウンロードしてね。入手先はJRubyのダウンロードサイトだよ。

jruby-complete-1.3.1.jar」をクリックしてダウンロードしたら、先ほど作ったC:\ramaze_on_gaeフォルダに配置してね。

WEB-INFフォルダの作成

先ほど作った「\ramaze_on_gae」ディレクトリの中に、次のように3つのディレクトリを作成するよ。

> mkdir WEB-INF
> mkdir WEB-INF\gems
> mkdir WEB-INF\lib

Ramazeのインストール

JRubygemコマンドを使って、必要となるライブラリを入手するよ。

> set JAVA_HOME=C:\PROGRA~1\Java\jdk1.6.0_16
> set PATH=%JAVA_HOME%\bin;C:\appengine-java-sdk-1.2.2\bin;%PATH%
> java -jar jruby-complete-1.3.1.jar -S gem install -i WEB-INF\gems ramaze --no-ri --no-rdoc
> del /q WEB-INF\gems\cache\*

jruby-core.jarruby-stdlib.jarlibフォルダに作成

次のようにコマンドを入力して、「jruby-complete-1.3.1.jar」から「jruby-core.jar」と「ruby-stdlib.jar」を作成するよ。ここでは元となる「jruby-complete-1.3.1.jar」は削除しているけど、削除したくない人は他のフォルダにコピーしておいてね。

> mkdir tmp_unpack
> cd tmp_unpack
> jar xf ../jruby-complete-1.3.1.jar
> cd ..
> mkdir jruby-core
> move tmp_unpack\org jruby-core
> move tmp_unpack\com jruby-core
> move tmp_unpack\jline jruby-core
> move tmp_unpack\jay jruby-core
> move tmp_unpack\jruby jruby-core
> cd jruby-core
> jar cf ../jruby-core.jar .
> cd ..\tmp_unpack
> jar cf ../ruby-stdlib.jar .
> cd ..
> rmdir /s /q jruby-core
> rmdir /s /q tmp_unpack
> move jruby-core.jar WEB-INF\lib
> move ruby-stdlib.jar WEB-INF\lib
> del jruby-complete-1.3.1.jar

appengine-api-1.0-sdk-1.2.2.jarのコピー

次のコマンドを入力して、「appengine-api-1.0-sdk-1.2.2.jar」ファイルをコピーするよ。

> copy C:\appengine-java-sdk-1.2.2\lib\user\appengine-api-1.0-sdk-1.2.2.jar WEB-INF\lib

jruby-rack-0.9.5-SNAPSHOT.jarのダウンロードと配置

こちらのサイトから「jruby-rack-0.9.5-SNAPSHOT.jar」をダウンロードして、C:\ramaze_on_gae\WEB-INF\libに配置してね。ダウンロードは右下のほうの「raw」というリンクをクリックしてね。

WEB-INF/hello.rbの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にhello.rbという名前で保存してね。単に「Hello, World!!」と表示させるだけのアプリケーションだよ。

require 'rubygems'
require 'ramaze'

class MainController < Ramaze::Controller
  def index
    "Hello, World!"
  end
end

WEB-INF/appengine-web.xmlの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にappengine-web.xmlという名前で保存してね。

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    <application>ramaze_on_gae</application>
    <version>1</version>
    <static-files />
    <resource-files />
    <sessions-enabled>false</sessions-enabled>
    <system-properties>
      <property name="jruby.management.enabled" value="false" />
      <property name="os.arch" value="" />
      <property name="jruby.compile.mode" value="JIT"/> <!-- JIT|FORCE|OFF -->
      <property name="jruby.compile.fastest" value="true"/>
      <property name="jruby.compile.frameless" value="true"/>
      <property name="jruby.compile.positionless" value="true"/>
      <property name="jruby.compile.threadless" value="false"/>
      <property name="jruby.compile.fastops" value="false"/>
      <property name="jruby.compile.fastcase" value="false"/>
      <property name="jruby.compile.chainsize" value="500"/>
      <property name="jruby.compile.lazyHandles" value="false"/>
      <property name="jruby.compile.peephole" value="true"/>
   </system-properties>
</appengine-web-app>

WEB-INF/web.xmlの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にweb.xmlという名前で保存してね。

<!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
 
  <context-param>
    <param-name>public.root</param-name>
    <param-value>/</param-value>
  </context-param>
 
  <context-param>
    <param-name>rackup</param-name>
    <param-value>require 'rubygems'

class Thread
  def Thread.exclusive
    _old = Thread.critical
    begin
      Thread.critical = true
      return yield
    ensure
      Thread.critical = _old
    end
  end
end

require 'ramaze'

require 'hello'

Ramaze.start(:root => __DIR__, :started => true)
run Ramaze
</param-value>
  </context-param>
 
  <context-param>
    <param-name>jruby.min.runtimes</param-name>
    <param-value>1</param-value>
  </context-param>
 
  <context-param>
    <param-name>jruby.max.runtimes</param-name>
    <param-value>1</param-value>
  </context-param>
 
  <context-param>
    <param-name>jruby.init.serial</param-name>
    <param-value>true</param-value>
  </context-param>
 
  <filter>
    <filter-name>RackFilter</filter-name>
    <filter-class>org.jruby.rack.RackFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>RackFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
 
  <listener>
    <listener-class>org.jruby.rack.RackServletContextListener</listener-class>
  </listener>
 
</web-app>

開発用サーバの起動

次のコマンドを入力して、開発用サーバを起動してね。

> dev_appserver.cmd .

Webブラウザで開発用サーバにアクセス

http://localhost:8080/にアクセスして、動作確認してね。

Google App Engineにデプロイ

「appengine-web.xml」の「application」と「version」を適切に設定して、次のコマンドを実行してね。

> appcfg.cmd update .
トラックバック - http://rubyist.g.hatena.ne.jp/muscovyduck/20090822

2009-08-15

[][][] SinatBBS on GAE/J  SinatBBS on GAE/J - バリケンのRuby日記 を含むブックマーク はてなブックマーク -  SinatBBS on GAE/J - バリケンのRuby日記  SinatBBS on GAE/J - バリケンのRuby日記 のブックマークコメント

Ruby Freaks Lounge:第9回 SinatraとSequel・Hamlで掲示板アプリを作る|gihyo.jp … 技術評論社」という記事にある「SinatBBS」という掲示板アプリを、Google App Engine for Java上でJRubyを使って動かすための、自分用のメモだよ。

ここでの手順は、Windowsで行うことを想定しているよ。

Java SDKのダウンロードとインストール

まだJava SDKをインストールしていない人は、ダウンロードしてインストールしてね。

Java SDKをインストールするには、Java SDKのダウンロードサイトにアクセスして、下のほうにある「JDK 6 Update 16」の右側の「Download」をクリックしてね。Platformは「Windows」を選択してね。

ダウンロードしたインストーラ「jdk-6u16-windows-i586.exe」をダブルクリックすると、インストールが始まるよ。

Google App Engine for Java SDKのダウンロードと展開

まだGoogle App Engine for Java SDKを入手していない人は、ダウンロードしてね。

Google App Engine for Java SDKを入手するには、Google App Engineのダウンロードサイトにアクセスして、「appengine-java-sdk-1.2.2.zip」をクリックしてダウンロードしてね。ダウンロードした「appengine-java-sdk-1.2.2.zip」ファイルは圧縮されているから、Cドライブ直下に展開してね。

sinatbbsディレクトリの作成

コマンドプロンプトを起動して、次のようにコマンドを入力してね

空白を含むパス上だとうまく動かないみたいなので、ここではCドライブ直下に作成しているよ

> cd \
> mkdir sinatbbs
> cd \sinatbbs

jruby-complete-1.3.1.jarのダウンロードと設置

まだ「jruby-complete-1.3.1.jar」を入手していない人は、ダウンロードしてね。入手先はJRubyのサイトだよ。

jruby-complete-1.3.1.jar」をクリックしてダウンロードしたら、先ほど作ったC:\sinatbbsフォルダに配置してね。

WEB-INFフォルダの作成

先ほど作った「sinatbbs」ディレクトリの中に、次のように3つのディレクトリを作成するよ。

> mkdir WEB-INF
> mkdir WEB-INF\gems
> mkdir WEB-INF\lib

Sinatra、DataMapper、Hamlのインストール

JRubygemコマンドを使って、必要となるライブラリを入手するよ。

> set JAVA_HOME=C:\PROGRA~1\Java\jdk1.6.0_16
> set PATH=%JAVA_HOME%\bin;C:\appengine-java-sdk-1.2.2\bin;%PATH%
> java -jar jruby-complete-1.3.1.jar -S gem install -i WEB-INF\gems sinatra --no-ri --no-rdoc
> java -jar jruby-complete-1.3.1.jar -S gem install -i WEB-INF\gems addressable --no-ri --no-rdoc
> java -jar jruby-complete-1.3.1.jar -S gem install -i WEB-INF\gems dm-datastore-adapter --no-ri --no-rdoc
> java -jar jruby-complete-1.3.1.jar -S gem install -i WEB-INF\gems haml --no-ri --no-rdoc
> rmdir /s /q WEB-INF\gems\bin
> del /q WEB-INF\gems\cache\*

jruby-core.jarruby-stdlib.jarlibフォルダに作成

次のようにコマンドを入力して、「jruby-complete-1.3.1.jar」から「jruby-core.jar」と「ruby-stdlib.jar」を作成するよ。ここでは元となる「jruby-complete-1.3.1.jar」は削除しているけど、削除したくない人は他のフォルダにコピーしておいてね。

> mkdir tmp_unpack
> cd tmp_unpack
> jar xf ../jruby-complete-1.3.1.jar
> cd ..
> mkdir jruby-core
> move tmp_unpack\org jruby-core
> move tmp_unpack\com jruby-core
> move tmp_unpack\jline jruby-core
> move tmp_unpack\jay jruby-core
> move tmp_unpack\jruby jruby-core
> cd jruby-core
> jar cf ../jruby-core.jar .
> cd ..\tmp_unpack
> jar cf ../ruby-stdlib.jar .
> cd ..
> rmdir /s /q jruby-core
> rmdir /s /q tmp_unpack
> move jruby-core.jar WEB-INF\lib
> move ruby-stdlib.jar WEB-INF\lib
> del jruby-complete-1.3.1.jar

appengine-api-1.0-sdk-1.2.2.jarのコピー

次のコマンドを入力して、「appengine-api-1.0-sdk-1.2.2.jar」ファイルをコピーするよ。

> copy C:\appengine-java-sdk-1.2.2\lib\user\appengine-api-1.0-sdk-1.2.2.jar WEB-INF\lib

jruby-rack-0.9.4.jarのダウンロードと配置

JRuby-Rackのサイトから「jruby-rack-0.9.4.jar」をダウンロードして、C:\sinatra_on_gae\WEB-INF\libに配置してね。

WEB-INF/start.rbの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にstart.rbという名前で保存してね。

require 'rubygems'
require 'sinatra'
require 'model/comment.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
  @comments = Comments.all(:order => [:posted_date.desc])
  haml :index
end

put '/comment' do
  Comments.create(
    :name => request[:name],
    :title => request[:title],
    :message => request[:message],
    :posted_date => Time.now
  )
  redirect '/'
end

WEB-INF/model/comment.rbの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にmodelフォルダを作成して、そこにcomment.rbという名前で保存してね。

require 'dm-core'
require 'dm-aggregates'
require 'dm-types'
require 'dm-datastore-adapter/datastore-adapter'

DataMapper.setup(:datastore,
                 :adapter => :datastore,
                 :database => 'comments')

class Comments
  include DataMapper::Resource
  def self.default_repository_name; :datastore end
  property :id,         Serial
  property :name,       String
  property :title,       String
  property :message,       Text,     :lazy => false
  property :posted_date, DateTime

  def date
    (self.posted_date.new_offset(Rational(3, 8))).strftime("%Y-%m-%d %H:%M:%S")
  end
 
  def formatted_message
    Rack::Utils.escape_html(self.message).gsub(/\n/, "<br>")
  end
end

WEB-INF/views/index.hamlの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にviewsフォルダを作成して、そこにindex.hamlという名前で保存してね。あ、このファイルは日本語を含んでいるから、ファイルを保存するときは文字コードを「UTF-8」に設定してね。

%form{:method => "POST", :action => '/comment'}
  %input{:type => "hidden", :name => "_method", :value => "PUT"}
  %table
    %tr
      %td 名前
      %td 
        %input{:type => "text", :name => "name"}
    %tr
      %td タイトル
      %td
        %input{:type => "text", :name => "title"}
    %tr
      %td 内容
      %td
        %textarea{:name => "message", :cols => 60, :rows => 8}
    %tr
      %td
      %td
        %input{:type => "submit"}

- @comments.each do |comment|
  .comment
    %h2= h comment.title
    .info
      %span.name== by #{h comment.name}
      %span.date== (#{h comment.date})

    .message
      = comment.formatted_message

WEB-INF/views/layout.hamlの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中のviewsフォルダの中にlayout.hamlという名前で保存してね。

!!! XML
!!! Strict
 
%html
  %head
    %title SinatBBS
    %meta{:"http-equiv"=>"Content-Type", :content=>"text/html", :charset=>"utf-8"}
    %link{:rel=>"stylesheet", :type=>"text/css", :href=>"/style.css"}
  %body
    %h1 SinatBBS
    != yield

WEB-INF/views/style.sassの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にviewsフォルダの中にstyle.sassという名前で保存してね。

body
  margin: 0px 20%
  padding: 0px

h1
  margin: 1em

form
  border: 1px solid black
  margin: 1em
  padding: 0.5em

.comment
  border: 1px solid black
  margin: 1em
  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

WEB-INF/appengine-web.xmlの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にappengine-web.xmlという名前で保存してね。

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    <application>sinatra_on_gae</application>
    <version>1</version>
    <static-files />
    <resource-files />
    <sessions-enabled>false</sessions-enabled>
    <system-properties>
      <property name="jruby.management.enabled" value="false" />
      <property name="os.arch" value="" />
      <property name="jruby.compile.mode" value="JIT"/> <!-- JIT|FORCE|OFF -->
      <property name="jruby.compile.fastest" value="true"/>
      <property name="jruby.compile.frameless" value="true"/>
      <property name="jruby.compile.positionless" value="true"/>
      <property name="jruby.compile.threadless" value="false"/>
      <property name="jruby.compile.fastops" value="false"/>
      <property name="jruby.compile.fastcase" value="false"/>
      <property name="jruby.compile.chainsize" value="500"/>
      <property name="jruby.compile.lazyHandles" value="false"/>
      <property name="jruby.compile.peephole" value="true"/>
   </system-properties>
</appengine-web-app>

WEB-INF/web.xmlの作成

テキストエディタで次の内容を入力して、WEB-INFフォルダの中にweb.xmlという名前で保存してね。

<!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

  <context-param>
    <param-name>public.root</param-name>
    <param-value>/</param-value>
  </context-param>

  <context-param>
    <param-name>rackup</param-name>
    <param-value>require 'rubygems'
require 'sinatra'

root_dir = File.dirname(__FILE__)

#set :environment, :production
set :environment, :development
set :root,        root_dir
set :app_file,    File.join(root_dir, 'start.rb')
disable :run

require 'start'

run Sinatra::Application
</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.min.runtimes</param-name>
    <param-value>1</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.max.runtimes</param-name>
    <param-value>1</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.init.serial</param-name>
    <param-value>true</param-value>
  </context-param>

  <filter>
    <filter-name>RackFilter</filter-name>
    <filter-class>org.jruby.rack.RackFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>RackFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <listener>
    <listener-class>org.jruby.rack.RackServletContextListener</listener-class>
  </listener>

</web-app>

開発用サーバの起動

次のコマンドを入力して、開発用サーバを起動してね。

> dev_appserver.cmd .

Webブラウザで開発用サーバにアクセス

http://localhost:8080/にアクセスして、動作確認してね。

Google App Engineにデプロイ

「appengine-web.xml」の「application」と「version」を適切に設定して、次のコマンドを実行してね。

> appcfg.cmd update .
トラックバック - http://rubyist.g.hatena.ne.jp/muscovyduck/20090815

2009-08-12

[][] jruby-complete-1.3.1.jarからjruby-core.jarとruby-stdlib.jarを作る  jruby-complete-1.3.1.jarからjruby-core.jarとruby-stdlib.jarを作る - バリケンのRuby日記 を含むブックマーク はてなブックマーク -  jruby-complete-1.3.1.jarからjruby-core.jarとruby-stdlib.jarを作る - バリケンのRuby日記  jruby-complete-1.3.1.jarからjruby-core.jarとruby-stdlib.jarを作る - バリケンのRuby日記 のブックマークコメント

Windowsでjruby-complete-1.3.1.jarからjruby-core.jarとruby-stdlib.jarを作るための、自分用のメモだよ。基本的にはd:id:technohippyさんのこちらのエントリの通りだよ。

ちなみに、jruby-core.jarとruby-stdlib.jarは、Google App Engine上でJRubyを使うために必要となるファイルだよ。詳しい使い方は、また今度。

  • Java SDKのダウンロードとインストール
    • まだJava SDKをインストールしていない人は、ダウンロードしてインストールしてね
    • http://java.sun.com/javase/downloads/
    • 「JDK 6 Update 16」の右側の「Download」をクリックしてね。Platformは「Windows」だよ
    • ダウンロードしたインストーラ「jdk-6u16-windows-i586.exe」をダブルクリックしてインストールしてね。
  • コマンドプロンプトの起動
    • コマンドプロンプトを起動して、次のようにコマンドを入力してね
> set JAVA_HOME=C:\PROGRA~1\Java\jdk1.6.0_16
> set PATH=%JAVA_HOME%\bin;%PATH%
> cd [jruby-complete-1.3.1.jarをダウンロードしたディレクトリ]
> mkdir tmp_unpack
> cd tmp_unpack
> jar xf ../jruby-complete-1.3.1.jar
> cd ..
> mkdir jruby-core
> move tmp_unpack\org jruby-core
> move tmp_unpack\com jruby-core
> move tmp_unpack\jline jruby-core
> move tmp_unpack\jay jruby-core
> move tmp_unpack\jruby jruby-core
> cd jruby-core
> jar cf ../jruby-core.jar .
> cd ..\tmp_unpack
> jar cf ../ruby-stdlib.jar .
> cd ..
> rmdir /s /q jruby-core
> rmdir /s /q tmp_unpack

これで、「jruby-complete-1.3.1.jar」と同じフォルダに「jruby-core.jar」と「ruby-stdlib.jar」ができているはずだよ。

[][] 「jruby-complete-1.3.1.jar」はJRuby一式  「jruby-complete-1.3.1.jar」はJRuby一式 - バリケンのRuby日記 を含むブックマーク はてなブックマーク -  「jruby-complete-1.3.1.jar」はJRuby一式 - バリケンのRuby日記  「jruby-complete-1.3.1.jar」はJRuby一式 - バリケンのRuby日記 のブックマークコメント

説明を省略しちゃったけど、「jruby-complete-1.3.1.jar」はJRubyを動かすために必要なライブラリを全部含んだものだよ。だから、Javaの実行環境と「jruby-complete-1.3.1.jar」さえあれば、JRubyをインストールしていなくても次のような感じでJRubyを起動することができるよ。

> java -jar jruby-complete-1.3.1.jar -v
jruby 1.3.1 (ruby 1.8.6p287) (2009-06-15 6586) (Java HotSpot(TM) Client VM 1.6.0_16) [x86-java]

> java -jar jruby-complete-1.3.1.jar -S jirb
irb(main):001:0> 2 + 3
5

irb(main):002:0> exit

>

気軽にRubyを試してみたい、という人にもいいかも!

[][] Sinatra on GAE/J  Sinatra on GAE/J - バリケンのRuby日記 を含むブックマーク はてなブックマーク -  Sinatra on GAE/J - バリケンのRuby日記  Sinatra on GAE/J - バリケンのRuby日記 のブックマークコメント

Rubyで書かれた軽量Webアプリケーション開発フレームワーク「Sinatra」をGoogle App Engine for Java上でJRubyを使って動かすための、自分用のメモだよ。基本的にはjugyoさんのこちらのエントリの通りだよ。ここでの手順はWindowsで行うことを想定しているよ。

  • sinatra_on_gaeディレクトリの作成
    • コマンドプロンプトを起動して、次のようにコマンドを入力してね
    • 空白を含むパス上だとうまく動かないみたいなので、ここではCドライブ直下に作成しているよ
> cd \
> mkdir sinatra_on_gae
  • アプリケーションのフォルダの作成
> cd \sinatra_on_gae
> mkdir WEB-INF
> mkdir WEB-INF\gems
> mkdir WEB-INF\lib
  • Sinatraのインストール
> set JAVA_HOME=C:\PROGRA~1\Java\jdk1.6.0_16
> set PATH=%JAVA_HOME%\bin;C:\appengine-java-sdk-1.2.2\bin;%PATH%
> java -jar jruby-complete-1.3.1.jar -S gem install -i WEB-INF\gems sinatra --no-ri --no-rdoc
> rmdir /s /q WEB-INF\gems\bin
> del /q WEB-INF\gems\cache\*
  • jruby-core.jarとruby-stdlib.jarをlibフォルダに作成
> mkdir tmp_unpack
> cd tmp_unpack
> jar xf ../jruby-complete-1.3.1.jar
> cd ..
> mkdir jruby-core
> move tmp_unpack\org jruby-core
> move tmp_unpack\com jruby-core
> move tmp_unpack\jline jruby-core
> move tmp_unpack\jay jruby-core
> move tmp_unpack\jruby jruby-core
> cd jruby-core
> jar cf ../jruby-core.jar .
> cd ..\tmp_unpack
> jar cf ../ruby-stdlib.jar .
> cd ..
> rmdir /s /q jruby-core
> rmdir /s /q tmp_unpack
> move jruby-core.jar WEB-INF\lib
> move ruby-stdlib.jar WEB-INF\lib
> del jruby-complete-1.3.1.jar
  • appengine-api-1.0-sdk-1.2.2.jarのコピー
> copy C:\appengine-java-sdk-1.2.2\lib\user\appengine-api-1.0-sdk-1.2.2.jar WEB-INF\lib
  • WEB-INF/app.rbの作成
    • 単に「Hello World!!」と表示させるだけのアプリケーションだよ。
require 'rubygems'
require 'sinatra'

get '/' do
  'Hello World!!'
end
  • WEB-INF/appengine-web.xmlの作成
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    <application>sinatra_on_gae</application>
    <version>1</version>
    <static-files />
    <resource-files />
    <sessions-enabled>false</sessions-enabled>
    <system-properties>
      <property name="jruby.management.enabled" value="false" />
      <property name="os.arch" value="" />
      <property name="jruby.compile.mode" value="JIT"/> <!-- JIT|FORCE|OFF -->
      <property name="jruby.compile.fastest" value="true"/>
      <property name="jruby.compile.frameless" value="true"/>
      <property name="jruby.compile.positionless" value="true"/>
      <property name="jruby.compile.threadless" value="false"/>
      <property name="jruby.compile.fastops" value="false"/>
      <property name="jruby.compile.fastcase" value="false"/>
      <property name="jruby.compile.chainsize" value="500"/>
      <property name="jruby.compile.lazyHandles" value="false"/>
      <property name="jruby.compile.peephole" value="true"/>
   </system-properties>
</appengine-web-app>
  • WEB-INF/web.xmlの作成
<!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

  <context-param>
    <param-name>public.root</param-name>
    <param-value>/</param-value>
  </context-param>

  <context-param>
    <param-name>rackup</param-name>
    <param-value>require 'rubygems'
require 'sinatra'

root_dir = File.dirname(__FILE__)

#set :environment, :production
set :environment, :development
set :root,        root_dir
set :app_file,    File.join(root_dir, 'app.rb')
disable :run

require 'app'

run Sinatra::Application
</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.min.runtimes</param-name>
    <param-value>1</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.max.runtimes</param-name>
    <param-value>1</param-value>
  </context-param>

  <context-param>
    <param-name>jruby.init.serial</param-name>
    <param-value>true</param-value>
  </context-param>

  <filter>
    <filter-name>RackFilter</filter-name>
    <filter-class>org.jruby.rack.RackFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>RackFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <listener>
    <listener-class>org.jruby.rack.RackServletContextListener</listener-class>
  </listener>

</web-app>
  • 開発用サーバの起動
> dev_appserver.cmd .
  • Google App Engineにデプロイ
    • 「appengine-web.xml」の「application」と「version」を適切に設定して、次のコマンドを実行してね
> appcfg.cmd update .

追記:SinatBBSをGAE/Jで動かしてみました!

lively1233lively12332014/10/23 15:20  天然なバンブーに活用してグッチサングラス偽物を通販

  衣装の他、バッグ?財布?靴?香水?時計?ジュエリーなど幅広く手がけるイタリアのファッションブランド。グッチサングラス「BAMBOO AND METAL AVIATOR 」もこちらあちら在庫なし、グッチサングラス偽物に興味があったのはぜひブランドコピーにご注目してくれて、ブランドの元祖と呼ばれ、世界で初めて品質保証のためにデザイナーの名前を商品に入れたことでも知られる。オープンから数年のうちに、グッチオ?グッチの皮革製品は、乗馬からインスピレーションを得たハンドバッグ、トランク、グローブ、シューズ、ベルトのコレクションを求めて世界各地から顧客が訪れるようになる。

  くつわとあぶみをモチーフにしたホースビットの革新的なデザインはこの頃に誕生し、後にグッチデザインの普遍的なシンボルとなる。グッチ2014/FW 新作のサングラス「BAMBOO AND METAL AVIATOR 」を紹介。「BAMBOO AND METAL AVIATOR 」グッチサングラスブランドはフィレンツェのクラシックなデザインの解釈を再演する。豊かな歴史的遺産と優れた職人技巧妙な融合、モダンでラグジュアリーを表す。www.btcxm.com「BAMBOO AND METAL AVIATOR 」グッチメガネは2013年発売してから、後数四半期のシリーズを数多く提供して、材質には天然なバンブーに用いられ、GGロゴをレーザーして、グッチサングラスにもっとユニークさを与える。わがしゃではスーパーコピー 代引き対応に採用。

  最も細心のアプローチは、メガネフレームの完璧に現れるために曲げ加工にバンブーあたり内の水を抜くと確認して、バンブーに柔らか色合いを加え、また悪い天気を避けるため、竹ワックスにする。そして、各竹の寿命を長く守る。そんな細部まで注意して製造アプローチのおがげて、よくフィレンツェの家の最高の解釈、、常に卓越性の伝統に付着していると体験できる。グッチ商品を体験したいなら、GUCCI 激安 コピーを購入しましょう。

トラックバック - http://rubyist.g.hatena.ne.jp/muscovyduck/20090812