Sinatraã¨DataMapperã¨ERBã§ãµã¤ãä½ã£ãã®ã§ã½ã¼ã¹ãå ¬éãã¦ã¿ã
æåã«è¨ã£ã¦ããã¨rubyã¯å ¨ç¶åããã¾ããã
ã¾ãä½ã£ã¦æãã¦ã¿ãã
ãµã¤ãã¯ãhttp://tiwa.hirafoo.net/ããéãããããã¾ãããã§ãã
ã½ã¼ã¹ã¯ãhttp://github.com/hirafoo/tiwaãã«ã
以åã® sinatraとActiveRecordとERBでBBS作ったのでソースを公開してみる - だるろぐ跡地 ã¨ãã¾ãå¤ããã¾ããã
ã¯ã解説ã´ã¼ã
- åºæ¬
railsã®æ§æã模ããMVCã¹ã¿ã¤ã«ã§ä½æãè¦æè¦æã§railsã®ããã¨ã¯ç°ãªãã
人æ°ã®è»½éwafã§ãã
ä»åã¯æåãåå¼·ãã¦ãRackã§ä½ããã¨ãã¦ã¾ãããã以ä¸ã®çç±ã«ããè·¯ç·å¤æ´ããSinatraã使ããã¨ã«ã
layoutãpartialæ©è½ãRackãåãã¦ããªã
railsãsinatraã§ã¯ãlayoutãpartialã¨å¼ã°ããæ©è½ã使ãããããã¯ããã¥ã¼ãå
±éé¨åã¨éå
±éé¨åã«åãã¦æ±ããæ©è½ã¨ãé¨åãã³ãã¬ã¼ããæ¿å
¥ã§ããæ©è½ã ã詳細ã¯çãã
ç§ã¯ãã®æ©è½ã¯ãã¦ã£ããerbãhamlãæ¨æºã§åãã¦ããæ©è½ã ã¨æã£ã¦ããããå®ã¯railsãSinatraãç¬èªå®è£
ãã¦ãããã®ã ã£ããããã¦Rackã¯ãããã®æ©è½ãæã£ã¦ããªãã
ãã®æç¹ã§è©°ãã ãrailsãSinatraã®ã½ã¼ã¹ãããããã®æ©è½ãæã£ã¦ãããã¨èãããããããªäºãããããããªããããããããã®wafã使ãã¹ãã ããã£ã¦Rackã®ä½¿ç¨ã諦ããã
ç§ã¯ãã®äºå®ã«å®ã«é©ãããrubyã®ãã³ãã¬ã¼ãçã¢ã¸ã¥ã¼ã«ã§ããerb|hamlã¯ãåä½ã§ã®å©ç¨ãèãããã¦ããªãã®ã ãããããããã使ã£ã¦ãµã¤ããä½ãã¨ãã¯ãwafã¨ã®ä½µç¨ã絶対æ¡ä»¶ã¨ã§ãããã¦ããã®ã ãããï¼
ãã¦ãããSinatraã¯layoutæ©è½ã¯åãã¦ãããpartialæ©è½ã¯åãã¦ããªããã®ã§ãã¦ãã¦ã©ãã®è¨äºãåèã«ãã¤ã¤ç¬èªå®è£ ã
def partial(template, options = {}) erb "_#{template}".to_sym, options.merge(:layout => false) end
ãã¥ã¼ã®ä¸ã§å¼ã¶ã®ã§ãå½ç¶ãã«ãã¼ã¨ãã¦å®è£
ã
ãªããerbéå®ã®å®è£
ã ããhamlãªã©ã使ãããå ´åã¯è»½ãifæãæãã°ãããããã¨ã
ä½è«1
perlã®æ¨æºçãªãã³ãã¬ã¼ãã¢ã¸ã¥ã¼ã«ã¨ãã¦ä½ç½®ä»ãããã¦ããTemplate::Toolkitã¯ãã¢ã¸ã¥ã¼ã«èªä½ããã®layoutãpartialã«ç¸å½ããæ©è½ãåãã¦ããã
å½ç¶ãwafãªã©ã®ç°å¢ã«å¶éããããã®æ©è½ã使ããã¨ãåºæ¥ãã
ä½è«2
å®ã¯erbåä½ã§ãlayoutæ©è½ãå®ç¾åºæ¥ããããåããã¥ããè¦ãç®ã«ãªãã®ã§ãããã
ãã£ã¹ãããã£ãç¡ã
Rackã®ç¹æ§ä¸å½ç¶ã¨è¨ãã°å½ç¶ã ãããã£ã¹ãããã£ãç¡ãããããrails/Sinatraã¯ç¬èªå®è£
ãã¦ããã
æåã¯ç°¡ç´ ãªãã£ã¹ãããã£ãæ¸ãã¦ããããä¸è¨ã¨åãçç±ã«ããRackã®ä½¿ç¨ã諦ããçªããæãæ¨ã¦ãã
rubyã®ãã£ã¹ãããã£ã¯ç¡ããã¨è»½ãã°ã°ã£ãããè¦å½ãããã
ãã³ãã©ãç¡ã
åä¸ã
ã¨ããããMã¨Cãèªã¿è¾¼ã
(Dir::glob("app/{controller,model}/*.rb")).each do |file| require file end
ã¢ããªã®ã³ã¢ã¨ãªãrbï¼ãã®ã±ã¼ã¹ã§ã¯script/tiwa.rbï¼ã§requireããã°ãä»»æã®M/Cããä»ã®M/Cã®ã¡ã½ãããå¼ã¹ããããã®ã§æ¥½ã
ãããªãããã«ãã¦ãã®ã ãããå½ç¶ã¨è¨ãã°å½ç¶ãªã®ã ãã©ã
ãã¥ã¼ã®ä½ç½®ãå¤æ´ãã
set :views, File.dirname(__FILE__) + '/../app/view'
ç°å¢å¤æ°ã§development/productionãåãã
railsã«å£ããã
@env = ENV["TIWA_ENV"] || "development"
ãã®@envã¯è¦æè¦æã§ä½¿ããä¾ãã°dbã¹ãã¼ãã®èªã¿è¾¼ã¿ã
development: adaptor: hoge production: adaptor: huga
ã¨ã§ããã¦ããã
db = YAML::load_file('config/database.yaml')[@env]
ã§ãç°å¢ã«å¿ããè¨å®ãèªã¿è¾¼ãã
ã½ã¼ã¹ã®èªååèªã¿è¾¼ã¿
Sinatraã¯0.9.2ãããã½ã¼ã¹ã®èªååèªã¿è¾¼ã¿ããããªããªã£ãã
ãããªã¨ãã¯shotgunã使ãã®ã ããï¼http://d.hatena.ne.jp/foosin/20090611/1244735821ï¼ããã¯ããã§ç©´ããã£ããããã
shotgunã§Sinatraã¢ããªãèµ·åãããã¨ã©ããªããã
% shotgun ./script/tiwa.rb -p 1000 - later - % netstat -tln | grep 1000 tcp 0 0 127.0.0.1:1000 0.0.0.0:* LISTEN
ãã®éããæå®ãããã¼ãã¯127.0.0.1ã«ãã¤ã³ãã£ã³ã°ããããã¤ã¾ããSinatraãåããéçºãã·ã³ãA(10.0.12.1)ã¨ããã©ã¦ã¶ããã¢ã¯ã»ã¹ãããã·ã³ãB(10.0.12.2)ã¨ã§ãããã¨ãAã®ãã·ã³ä¸ã§ localhost:1000 ã«ã¢ã¯ã»ã¹ã¯ã§ãã¦ãããã·ã³Bãã 10.0.12.1:1000 ã«ã¯ã¢ã¯ã»ã¹åºæ¥ãªãã
åä¸ã®ãã·ã³ã§éçºã»ç¢ºèªã¾ã§ãã¦ããã®ãªãåé¡ã¯ç¡ãããä»åã¯ããã§ãªãã£ãã®ã§å°ã£ãã
ã¡ãªã¿ã«shotgunã使ããã«èµ·åããã¨
% ./script/tiwa.rb -p 1000 - later - % netstat -tln | grep 1000 tcp 0 0 0.0.0.0:1000 0.0.0.0:* LISTEN
ã¨ãªãã®ã§ããã·ã³Bãã 10.0.12.1:1000 ã§ã¢ã¯ã»ã¹ã§ããã
æåã¯ã
Listen 1001 RewriteEngine On RewriteRule ^/(.*) http://localhost:1000/$1 [P]
ã¨ããapacheã§ä»£ç¨ãã¦ããããpostããç¬éã«æ»ãã ã®ã§ã大人ããpassengerã使ç¨ããalways_restart.txtãé
ç½®ããããpassengerã«ã¤ãã¦ã¯ãhttp://d.hatena.ne.jp/foosin/20090619/1245426335ãã«ã
ã©ããshotgunãã½ã¼ã¹ãåèªã¿è¾¼ã¿ããã®ã¯ãã½ã¼ã¹å¤æ´å¾ã«ãªã¯ã¨ã¹ããåããã¨ããªã®ã§ãshotgunã使ãããpassengerã使ãããå¾
ããããæéã¨ã¤ã©ã¤ã©æã«å¤§å·®ã¯ç¡ãã£ãã
å°ãä¸è¨ã®ãã¼ã説æã§ä½¿ã£ããã¼ãçªå·ã¯æé ã§ããã
ä½è«
ãããªè¨äºãããã
http://blog.s21g.com/articles/1638
åãã£ã¡ãåãããã½ã¼ã¹ãå¤æ´ãã¦ä¿åããç´å¾ã«ã¢ã¯ã»ã¹ãã¦ãåèªã¿è¾¼ã¿ããããå°ãçµã£ã¦ããã ã¨ããããããåãããã
- DataMapper
ååã®BBSä½ææã¨éãã®ã¯ãããããã§ããã
ARã«ä¸æºãããããã§ã¯ãªããåãäºãã£ã¦ãè©°ã¾ããªãã®ã§DataMapperï¼ä»¥ä¸DMï¼ã使ã£ã¦ã¿ãã
setup
å ã»ã©èªã¿è¾¼ãã dbã使ã£ã¦
DataMapper.setup(:default, { :adapter => db["adaptor"], :database => db["database"], :username => db["username"], :password => db["password"], :host => db["host"] })
ãã¼ã¸ã³ã°
DMã«ã¯dm-paginationã¨ãããã¼ã¸ã³ã°ãè¡ãã¢ã¸ã¥ã¼ã«ãåå¨ãããããã©ããorderã«æ¸¡ããå¤ãèªã¾ããªãããã ã£ãã
ï¼ä¸å¿ã½ã¼ã¹ã¯è¿½ã£ã¦ãDM.allãå¼ã¶ã®ã«ä½¿ã£ã¦ããoptionããã³ãããã¨ããã¡ããã¨å¤ã渡ãã¦ããããã ã£ããããåå åãããï¼
ã®ã§ãèªåå®è£
ã
ã¢ãã«ã®ãã¼ã¹ã¯ã©ã¹ãä½ããã¯ã©ã¹ã¡ã½ããã¨ãã¦å®è£
ã
def self.paginate(cond) page = (cond[:page] ? cond[:page] : 1).to_i offset = (page == 1) ? 0 : ((page - 1) * 10) order = cond[:order] cond.delete(:page) cond.delete(:order) @result = self.all(cond) @result = @result.all(:limit => 10, :offset => offset) @result = @result.all(:order => order) if order (@prev, @next) = (page == 1) ? ((@result.size < 10) ? [nil, nil] : [nil, 2]) : (@result.size == 10) ? [page - 1, page + 1] : [page - 1, nil] return @result, @prev, @next
å®ã«ç°¡ç´ ã§ããã
ã¨ããã§DMã使ãæ¹ã®ãµã³ãã«ã¯å°ãªããä¾ãã°å
¬å¼ããã¥ã¢ã«ã¯
http://datamapper.org/docs/
ã ããä¾ãã°ãã¼ã¸ã³ã°ã®éã®offsetã®æå®æ¹æ³ãªã©ã¯è¼ã£ã¦ãªãã
DMã®åºæ¬çãªä½¿ãæ¹ã¯ã°ã°ãã°åºãããã¡ãã£ã¨å¤ãã£ãäºãããããªã£ããé©å½ã«ã½ã¼ã¹ãèªãã ã
ããã¦ãå
¨ã¦ãçµãã£ããã¨ã«ãhttp://www.kuwata-lab.com/book_mdar/index.htmlããè¦ã¤ããããããäºå調æ»ã¯ã¡ããã¨ãããã
å±æ§è¨å®ãããªãã¼ã·ã§ã³
ä¸è¨ããã¥ã¡ã³ãã app/model/ 以ä¸åç
§ã説æã¯ä¸è¦ã¨æãããã
relation
ä¾ãã°ã¯ã©ã¹å ã§
belongs_to :entry
ãªã©ã¨å®£è¨ããã°relationãå¼µã£ã¦ããããããçºè¡ããã¯ã¨ãªã¯joinãããã®ã§ã¯ãªããåã¢ãã«ã«ããããéjoinã®ã¯ã¨ãªãæããã
ãã®å¾ãã¾ãã§joinãããã®ãããªãªãã¸ã§ã¯ããè¿ãã¦ããããããã¯ãããããã
ãã¼ã¿ã½ã¼ã¹ãåä¸ã®ãµã¼ãä¸ã«å
¨ã¦ç´ã¾ã£ã¦ããç°å¢ã§ã¯æãé£å³ã¯ç¡ãã®ã ããã©ã
ãã¤ã°ã¬ã¼ã·ã§ã³
DMã§ã®ãã¤ã°ã¬ã¼ã·ã§ã³ã¯ARã®ããã«rakeã§ã¯ãªããã¯ã©ã¹ã¡ã½ãããå®è¡ããã
DataMapper.auto_migrate!
script/handle_data ã«ç°¡åãªã¹ã¯ãªãããç½®ãã¦ãããã
- etc
ãã®ä»ã
ã¢ãã«ã®ãã¼ã¹ã¯ã©ã¹ãä½æã
module Tiwa module Model class Base def increment(column) self.update(column => (self.__send__(column) + 1)) end # ç¥ end end end
Tiwa::Model::Baseã¯ã©ã¹ï¼å³å¯ã«ã¯ãã®è¡¨ç¾ã¯æ£ãããªãæ°ãããããé¢åãªã®ã§ã¯ã©ã¹ã¨å¼ã¶ãã©ãã大差ç¡ãï¼ããã¼ã¹ã¨ããä»ã®ã¯ã©ã¹ã§ã¯ãã®ã¯ã©ã¹ãç¶æ¿ããã
ãã®incrementã¡ã½ããã¯ãåãåã£ãååã®ã«ã©ã ã®å¤ã1å¢ããã ãã§ãããããã¯Cã§ããããã¨ãæã£ããã
http://twitter.com/hirafoo/status/5762365040
http://twitter.com/kamipo/status/5762395858
http://twitter.com/hirafoo/status/5762459759
http://twitter.com/kamipo/status/5762531208
ã¨ã®ãã¨ã
ã©ã£ã¡ã«ãããCã«ã¯ãã¸ãã¯ã極åè©°ãè¾¼ã¾ãªãããã«ããã®ãæã¾ããã
MVCã®ãªããããã«ã¤ãã¦ã¯ããã§ã¯è§¦ããªãã
ããã¦ãã®ããã«ãrubyã§ã¯ä»»æã®ååã®ã¡ã½ãããåçã«å®è¡ããå ´åã__send__ã¡ã½ãããç¨ããã
perlã§ã¯æ®éã«
$obj->$method_name
ã§å¼ã¹ãã
- console
railsã® script/console ã使ãããã¨æã£ãã/usr/bin/irb ã®ã³ã¼ãã«ãscript/tiwa ãrequireãããã ãã§ä½¿ããã
rubyç´ æ´ãããã
LoadModule env_module modules/mod_env.so SetEnv TIWA_ENV production
æ¯åº¦ã®éãé·ã
ã¨æ¸ãããããã£ãäºã¯ãããªã¨ããã
ããã¦åé ã®éããç§ã¯rubyãå
¨ç¶åãããªããpã¨methodsã«ãä¸è©±ã«ãªã£ã¦ãããriãrefeãã¤ãã¤ãå©ãã«ãªããªãã
ãã®è¨äºãããã¦tiwaã®ã³ã¼ãã«ãåãééããæ®å¿µãªåæãå¤åã«å«ã¾ãã¦ããã¨æãããã