JRuby on Rails on Google App Engineåæ訳
Google App Engineã®Javaçãåºã¾ãããã¾ãJavaã¯æ¯è¼çã©ãã§ããããã§ãããå¬ãããã¨ã«ãã®ä¸ã§ã¯JRubyãåãããã§ããæµ·å¤ã®å é§è ãããã°ã£ã¦ããã°ãæ¸ãã¦ãããã®ã§ããã¤ãã®ããã«åæ訳ãã¦ã¿ã¾ãã
http://olabini.com/blog/2009/04/jruby-on-rails-on-google-app-engine/
ããã¯æè¿ã¢ãã¦ã³ã¹ãããGoogle App EngineãJavaããµãã¼ãããã¨ãããã¥ã¼ã¹ã«é¢ããè¨äºã®3ã¤ç®ã ãä»åã®è¨äºã§ã¯JRuby on Railsã¢ããªã±ã¼ã·ã§ã³ãGAE/Jã§åããã®ã«å¿ è¦ãªæé ãããã£ã¦ã¿ã¦ãã¢ããªã±ã¼ã·ã§ã³ã®ç¹æ§ãã©ã®ããã«ãªãã¨äºæ³ãã¹ããã«ä»ãã¦æ¸ãããã
ã¾ãJRubyã¯ææ°çãå¿ è¦ã ãJRuby1.2ãªãªã¼ã¹ä»¥éã«JRubyã®trunkã«å ããããå¤æ´ã®ã»ã¨ãã©ãå¿ è¦ã«ãªãã®ã§ãcheck outãã¦ãã«ããã¦ããããææ°çã®Railsãã¡ããã¨åãã
æåã«åºæ¬ã¨ãªãRailsã¢ããªãã»ããã¢ãããããããã®å¾ãããã¨ãããã¤ããããã¾ãWarblerãpluginizeã§ã¤ã³ã¹ãã¼ã«ãã¦ãWarble configurationãã¡ã¤ã«ãçæãããããã«ã¯æ¬¡ã®ããã«ããã¨ããã"jruby -S gem install warbler", "jruby -S warble pluginize", æå¾ã« "jruby -S warble config"ãå¾åã®äºã¤ã¯Railsã¢ããªã±ã¼ã·ã§ã³ã®ã«ã¼ãã§è¡ããã¨ã
ã¾ãRails gemã®ããªã¼ãºãå¿ è¦ã ã以ä¸ã®ãã¨ãçµãã£ããå ¨ã¦ã®ãã¡ã¤ã«ã確èªãã¦ä¸è¦ãªãã¡ã¤ã«ã¯å ¨ã¦åé¤ãã¦ããããå ¬éããã¦ããã¨ããGAE/Jã¯1000ãã¡ã¤ã«ã¾ã§ããæ±ããªãããã«å¶éããã¦ããããã©ãæ¨æºçãªRailsã¢ããªã¯æçµçã«ãã以ä¸ã®ãµã¤ãºã«ãªã£ã¦ãããActiveRecordã¯å ¨ã¦åé¤ãã¦æ§ããªãããtestãã£ã¬ã¯ããªããããªãã ãããä»ã«ãããããã¨æ¶ãããã¡ã¤ã«ãããã¯ãã ã
GAE/Jã使ãå ´åActiveRecordã¯å¿ è¦ãªãã¯ããªã®ã§ãconfig/environment.rbã§ããããã¼ãããªãããã«æ°ãã¤ãããã次ã®ã¹ãããã§warble.rbãã¡ã¤ã«ãå¤æ´ãã¦ããã以ä¸ãåã®ããã¹ããã¨ã ï¼
ã¾ãã次ã®ããã«ãã¦å¿ è¦ãªGAE/Jãã¡ã¤ã«ã確å®ã«å«ã¾ããããã«ãããï¼
config.includes = FileList["appengine-web.xml", "datastore-indexes.xml"]
ã¾ããã©ã³ã¿ã¤ã ãããã¤èµ·åããããã©ã¡ã¼ã¿ãè¨å®ããå¿ è¦ãããã
config.webxml.jruby.min.runtimes = 1 config.webxml.jruby.max.runtimes = 1 config.webxml.jruby.init.serial = true
æå¾ã®ãªãã·ã§ã³ã¯JRuby-rackã®trunkãã¼ã¸ã§ã³ã§å©ç¨å¯è½ã ãããmin=1, max=1ã«è¨å®ããªãã®ã§ããã°ããã®ãªãã·ã§ã³ãå¿ è¦ã«ãªãããããã¦ãããªãã¨JRuby-rackã¯ã©ã³ã¿ã¤ã ãåæåã¹ã¬ãããè¤æ°ç«ã¡ä¸ãããã¨ãã¦ãã¾ãã
æå¾ã«ããæ°ãããã¼ã¸ã§ã³ã®ã©ã¤ãã©ãªã使ç¨å¯è½ã«ãããããã©ã®Javaã©ã¤ãã©ãªã使ç¨ãããã¨ããæå®ã空ã®é åã«ãã¦ããï¼
config.java_libs = []
å¾ã§å ¨ã¦ã®jarãã¡ã¤ã«ããã®libãã£ã¬ã¯ããªã«è¿½å ãã¦ããã
ç§ã追å ããæå¾ã®è¨å®ãªãã·ã§ã³ã¯Railsã«DataStoreãã»ãã·ã§ã³ã¹ãã¢ã¨ãã¦ä½¿ç¨ãããããã®ãã®ã ãYARBLãè¦ãã°ã©ããã£ããåããã ããã
ã¾ãappengine-web.xmlãã¡ã¤ã«ã«ãããã¤ãã®ãªãã·ã§ã³ãè¨å®ãããæãéè¦ãªã®ã¯JMXããªãã«ãã¦os.archã空ã«ãããã¨ã ã
<property name="jruby.management.enabled" value="false" /> <property name="os.arch" value="" />
ããã¯è¦ãã°å¤§ä½åããã ããã
ã¾ã ç§ããã¾ãè¡ã£ã¦ããªããã¨ãä¸ã¤ãã£ã¦ã"protect_from_forgery"ãã§ããªãã®ã§app/controller/application.rbã§ãã®è¡ãã³ã¡ã³ãã¢ã¦ããã¦ããã¦ã»ããã
jarãã¡ã¤ã«ãããã¤ãlibãã£ã¬ã¯ããªã«ç½®ãå¿ è¦ããããã©ããã®ã¾ã¾ã§ã¯GAE/Jã«ã¯å¤§ããããã®ã§jruby-complete jarã¯åå²ããå¿ è¦ããããlibã«ç½®ãæåã®ãã¡ã¤ã«ã¯appengine-api.jarã ãã¾ãjruby-rackã®ææ°ãã«ããå¿ è¦ãæå¾ã«jruby-complete.jarãåå²ããªãããç§ã¯æ¬¡ã®ãããªã¹ã¯ãªããã使ã£ã¦ããã¤ãã®jarãã¡ã¤ã«ãåãåºããã
#!/bin/sh rm -rf jruby-core.jar rm -rf ruby-stdlib.jar rm -rf tmp_unpack mkdir tmp_unpack cd tmp_unpack jar xf ../jruby-complete.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 rm -rf jruby-complete.jar
ãã®ã¹ã¯ãªããã¯æ¬¡ã®äºã¤ã®jarãçæãããjruby-core.jar, ruby-stdlib.jar
åãèªåã®ã¢ããªã±ã¼ã·ã§ã³ãApp Engineã«ãããã¤ããããã«å¿ è¦ãªã®ã¯ãã ããããã®è¾ºãå ¨é¨ã ã
YARBL
ãã®ã¤ã³ãã©ã試ãããã«ãYARBLã¨ããå°ããã¢ããªã±ã¼ã·ã§ã³ãä½æããããã®ã¢ããªã§ã¯ããã°ãä½æãã¦è¨äºãæ稿ã§ãããã³ã¡ã³ãããã®ä»ã®ã¹ãããªæ©è½ã¯ãªãã«ãç¨æããã¦ããªããããã§ãããã¯å®éã«åä½ãã¦ãããYARBLã§ã¯BeeUã¨Bumbleã使ç¨ãããBeeUã使ã£ã¦ç®¡çè ã¨ãã¦ãã°ã¤ã³ããã¦ã¼ã¶ã¼ã ããå®éã«è¨äºæ稿ãããããã°ãå¤æ´ã§ããããã«ãã¦ããããããã®æ©è½ã®ãµãã¼ãã¯Google UserServiceã使ãã°é常ã«ç°¡åã ã£ãã
å®éã«åãã¦ãããã®ã¯ï¼ãã¾ãããã°ï¼ãã¡ãã§è¦ãããï¼ http://yarubyblog.appspot.com ãã¾ãã½ã¼ã¹ã³ã¼ãã¯ç§ã®GitHubãªãã¸ããªã«ããï¼ http://github.com/olabini/yarbl ã
Bumble
Bumbleã¯ã¨ã¦ãã·ã³ãã«ãªDataStoreã®ã©ããã¼ã§ãGoogleã®DataStoreã使ããã¼ã¿ã¢ãã«ãä½æã§ãããããã¯YARBLã®ããã¯ã¨ã³ãã¨ãã¦éçºãããã®ã§ãå®éã«ã¯YARBLã§å¿ è¦ãªæ©è½ã ãããµãã¼ãããã¦ããã
以ä¸ãYARBLã®ãã¼ã¿ã¢ãã«ãã©ã®ããã«ãªã£ã¦ãããã ããããè¦ãã°Bumbleã§ã©ã®ããã«ã¢ãã«ãå®ç¾©ããããªãã¨ãªããããã ãããä¸ç¹æ³¨æãã¹ãã¯ãDataStoreã®ã¨ã³ãã£ãã£ã¯ã©ããªããããã£/å±æ§ãåãå ¥ããã®ã§(訳ãããããã)ãRubyã®ãããªè¨èªã«ã¨ã¦ãããåã£ã¦ããã
class Person include Bumble ds :given_name, :sur_name, :email has_many :blogs, Blog, :owner_id end class Blog include Bumble ds :name, :owner_id, :created_at belongs_to :owner, Person has_many :posts, :Post, :blog_id, :iorder => :created_at end class Post include Bumble ds :title, :content, :created_at, :blog_id belongs_to :blog, Blog end
å®éã«ã¢ãã«ã使ãã«ã¯æ¬¡ã®ããã«ããï¼
Blog.all Post.all({}, :limit => 15, :iorder => :created_at) blog = Blog.get(params[:id]) posts = blog.posts Blog.create :name => name, :owner => @person, :created_at => Time.now Post.all.each do |p| p.delete! end
ããããµãã¼ãããã¦ããã¡ã½ããã®ã»ã¼å
¨ã¦ã ãå®è£
ã¯ã¨ã¦ãå°ããã®ã§è¿·ããã¨ã¯ãªãã ããããã¡ãããããã¯å
¨ããã¥ã¼ã³ããã¦ããªãã®ã§ãã¾ãã«ãããããã§ããããã®ã¯ããã¦ã»ããããããã¯å¤§æè¿ï¼ã³ã¼ãã¯æ¬¡ã®å ´æã«ããï¼ http://github.com/olabini/bumble
BeeU
Googleã®ã¦ã¼ã¶ã¼ãµã¼ãã¹ã使ããªããBeeUãå©ç¨ã§ãããããã¯ã¨ã¦ãå°ããªãã¬ã¼ã ã¯ã¼ã¯ã§ããã¤ãã®ãã¨ãæå©ããè¦ããã«æ°ç¨®é¡ã®ãã«ãã¼ã¡ã½ããã使ããããã«ãªãããã£ã«ã¿ã¼ã¡ã½ããã¨ãã¦ã¯assign_user, assign_admin_status, verify_admin_userã®3ã¤ãå©ç¨ã§ããããã«ãªããæåã®äºã¤ã¯ãããã@userã¨@adminã¨ããã¤ã³ã¹ã¿ã³ã¹å¤æ°ãçæããã@userå¤æ°ã¯UserServiceã®Userãªãã¸ã§ã¯ããä¿æãã@adminã¯ãã¦ã¼ã¶ã¼ããã°ã¤ã³ãã¦ãã¦ããã«ãã®ã¦ã¼ã¶ã¼ã管çè ã§ããã¨ãã«çã«ãªãçå½å¤ã ãæå¾ã®ä¸ã¤ã¯ç¾å¨ã®ã¦ã¼ã¶ã¼ã管çè ãã©ããããã§ãã¯ããããã°ã¤ã³ãã¦ããªãå ´åã¯ãã°ã¤ã³ãã¼ã¸ã«ãªãã¤ã¬ã¯ãããããã°ã¤ã³ãã¦ããã管çè ã§ã¯ãªãã£ãã¨ãã«ã¯Not Authorizedãè¿ãããããããã®3ã¤ã®ã¡ã½ããã¯å ¨ã¦before filterã¨ãã¦ä½¿ç¨ãã¦ã»ããã
require_adminã¨ãããã¤ã¬ãã«ã®ã¡ã½ããããã£ã¦ãããã¯ç®¡çè 権éã§å®ãã¹ãã¡ã½ãããæå®ããããã«å©ç¨ã§ãããThis is really all you need.
æå¾ã«ãã°ã¤ã³URLã¨ãã°ã¢ã¦ãURLãçæããã¡ã½ããã2ã¤ããããããã¯ä¸¡æ¹ã¨ãURLãçæããããã¼ã¸ã«ãªãã¤ã¬ã¯ãã§æ»ã£ã¦ããããã«ãªã£ã¦ããã
BeeUã¯ç§ã®GitHubãªãã¸ããªã«ããï¼ http://github.com/olabini/beeu
ã¾ã¨ã
ã¾ã¨ãã¨ãã¦ãããã¤ãã®å°ããªåé¡ãé¤ãã°ãJRuby on Railsã¯App Engineä¸ã§ã¨ã¦ããã¾ãåä½ããã主ãªåé¡ã¯èµ·åæã®ã³ã¹ãã¨ãã¹ãã ãèµ·åã«ã©ã®ããããããããGAE/Jã使ã£ã¦äºåã«ç¥ããã¨ã¯ã§ããªãããã®ä»£ããã«åã¯å®éã«ä¸åº¦ç®ã®ãªãªã¼ã¹ããã¦è©¦ãã¦ã¿ãå¿ è¦ããããã¾ãç¾å¨ã®GAE/Jã¯ãã¤ãã³ã¼ãã®äºåæ¤è¨¼ãªã©ãããã®ã§ãé常ã®JDKã¨æ¯ã¹ã¦èµ·åã«å°ãæéãããããããã©ã³ã¿ã¤ã ã¯èµ·åã«ããã20ç§éã¾ããããã®ã§ãåãã¦ã®ã¢ã¯ã»ã¹ã«ã¯å°ãæéãããã£ããè¯ããã¥ã¼ã¹ã¨ãã¦ã¯ãããã¯ä»¥åã¯ãã£ã¨ã¾ããã£ãã¨ãããã¨ã ãããæ°é±éã§ã¤ã³ãã©ã¯ç¸å½é«éã«ãªã£ã¦ãããä»å¾ãæ¹åãè¦è¾¼ããã ããã¨ç§å人ã¯ç¢ºä¿¡ãã¦ããããã æªã ã«åé¡ãªã®ã¯ãã©ã³ã¿ã¤ã ãäºåã«ä½æã§ããªãã®ã§ããã¤ãã®ãªã¯ã¨ã¹ãã§æ³å以ä¸ã«æéãããããã¨ããããã¨ã ã
ä¸åº¦å®è¡ããã°ããã®ãã¨ã¯ããã©ã¼ãã³ã¹ããã£ã¨æ¹åããç¹ã¯æ³¨ç®ã«å¤ããããã¼ã¸å ã§ä½åº¦DataStoreã¸ã®ã¢ã¯ã»ã¹ãçºçãããã«ãããã©ãä¸ãªã¯ã¨ã¹ãã«120msã500msæããã®ãè¦ããã¨ããããããã¯ã¤ã³ãã©ãå¿ è¦ãªä½æ¥ãèããã¨ãããã»ã©æªãå¤ã§ããªãããã¼ã¿ã¢ã¯ã»ã¹ãããªãå¶ç´ãããããã ãã©ãmemcachingãçµ±åããæéããã¨ããã°ãæ¹åã¯ååå¯è½ã ã¨æãã
æå¾ã¾ã§ç§ãæ©ã¾ãã¦ããã®ã¯ãã¹ãã«ä»ãã¦ã ãã©ãããã°ããã®ãæ確ãªçãã¯ãªããå ã®ãã¹ãã§è¿°ã¹ãããã«æ¹æ³ã¯ããã¤ããããã©ãRailsã¢ããªã±ã¼ã·ã§ã³ã«çµè¾¼ã¾ãã¦ããæ¹æ³ã»ã©ãã£ããããç©ã¯ãªããå®éããã¹ãèªååã®ã³ã¹ãã大ããããªã®ã§ãç§ã¯ä»åã®ã¢ããªã±ã¼ã·ã§ã³ã§ã¯ã»ã¨ãã©ããã¥ã¢ã«ã§ã®ãã¹ããããã¦ããªãã
æå¾ã«ãGoogle App Engineã¨JRuby on Railsã¨ãããã¯ããã¸ã®çµã¿åããã¯ã¨ã¦ãé åçã ãããããçµã¿åãããæåã®ToughtWorksããã¸ã§ã¯ãã®ç»å ´ã楽ãã¿ã«ãã¦ããã
ä¸è¨æé ãå®éã«è©¦ãã¦ã¿ãã®ã§ããã£ãããã£ã¡ãã©ããã
http://d.hatena.ne.jp/technohippy/20090409#1239217083