PokéDia-1.3の進捗レポート
細かい点ですが、メールアドレスの登録をアドレスブックから行えるようにしました。
絵文字キーボードの利用が出来なくなる可能性があるようなので("Apple issues App Store-wide
細かい点ですが、メールアドレスの登録をアドレスブックから行えるようにしました。
絵文字キーボードの利用が出来なくなる可能性があるようなので("Apple issues App Store-wide
MerbでExpiresやCache-Cont
1 headers['Cache-Control'] = 'public' 2 headers['Expires'] = 3.days.from_now.utc.rfc2822
Merbでリソースに:editのようなカスタムアクションを追加する場合、 以下のように:memberオプションを利用出来ます。
config/rou
1 resources :materials, :member => {:download => :get}
これによって、GET /materials
が、Materials#downloadにmapされます。
Merbでファイルアップロードのspecを書く場合には、
multipart_
1 tmp = Tempfile.new('spec') 2 path = tmp.path + ".txt" 3 begin 4 file = open(path, "w+") 5 file.write "test" 6 multipart_post(resource(:materials), 7 :material => {:id => nil, :label => 'test', :file => file}) 8 tmp.close 9 ensure 10 file.close 11 File.unlink path 12 end
:content_t
Merbのデフォルト構成にはRailsのような HTMLのsanitizeを行うようなヘルパーメソッドは無いのですが、 Gemで提供されている sanitize というライブラリを使うと、簡単にHTMLのsanitizeを行う事が出来ます。
1 Sanitize.clean(html, Sanitize::Config::RELAXED)
タグ毎に有効・無効の細かい設定が出来て、使い勝手が良いです。
Singleton Methodを削除する方法 についてですが、 Objectクラスに用意されているとありがたいですね。
object_ext
1 class Object 2 def remove_singleton_met hod(*args) 3 (class << self; self end).class_eval do 4 args.each{|i| send :remove_met hod, i} 5 end 6 end 7 end
こんな感じ。
方法を探していたのですが、意外と苦戦したのでメモ。
1 object = new Object 2 def object.foo; end 3 object.singleton_ methods #=> [:foo] 4 (class << object; self end).class_eval {send :remove_met hod, :foo} 5 object.singleton_ methods #=> []
これで行けるようです。instance_e
MerbのCacheはなかなか優れた設計なので面白いのですが、
開発中にログにCache Miss/Hitの具合が分かるように出力してほしかったので、
developmen
1 class LoggingMemcachedStor e < Merb::Cach e::Memcach edStore 2 include Extlib::Hook 3 4 before :read do |key, params| 5 if exists?(key, params) 6 Merb.logger.debug "Cache Hit: #{key}" 7 else 8 Merb.logger.debug "Cache Miss: #{key}" 9 end 10 end 11 12 before :write do |key, data, params, conds| 13 Merb.logger.debug "Cache Write: #{key}" 14 end 15 end
こんな感じでログに出ます。
1 merb : worker (port 4000) ~ Cache Hit: Plugins#show 2 merb : worker (port 4000) ~ Cache Write: Plugins#show
EC2のサーバ上でruby-1.8.x
構成
入り口から順に並べるとこんな感じです。
apache2はpassengerを使っているので外せないとして、
ruby-1.9.1
そこで、以前から目を付けていた Swiftiply を試す事にしました。 Swiftiplyはとても面白い設計のウェブサーバで、そのへんは rakutoさんの記事 「[Rails] Swiftiplyのアーキテクチャとベンチマーク」 を読むのがわかりやすいでしょう。
merbはbuilt-inでSwiftiply用のアダプター(Swiftiplie
しかし、例によってswiftiplyが依存しているeventmachi
あとは、swiftiplyの起動スクリプトを用意。
/etc/init.
1 #!/usr/bin/env ruby 2 3 PID = "/var/run/s wiftiply.p id" 4 5 case ARGV[0] 6 when 'start' 7 if File.exist?(PID) 8 puts "swiftiply is already started." 9 exit 1 10 end 11 print "Starting swiftiply: " 12 pid = fork do 13 Process.setsid 14 Process.exec "swiftiply", "-c", "/etc/swift iply.yml" 15 end 16 begin 17 open(PID, "w"){|file| file.write pid} 18 puts "done" 19 rescue Exception => e 20 puts e.message 21 Process.kill 9, pid 22 end 23 when 'stop' 24 print "Stopping swiftiply: " 25 begin 26 pid = open(PID).read.to_i 27 File.unlink PID 28 Process.kill 9, pid 29 puts "done" 30 rescue Exception => e 31 puts e.message 32 end 33 when 'restart' 34 system $0, 'stop' 35 system $0, 'start' 36 else 37 puts "usage: {start|stop|restart}" 38 end
アプリケーションの起動、停止は以下のようにおこないます。
1 cd #{current_path}; #{merb} -K all 2 cd #{current_pa th}; #{merb} -e production -a swift -c 1 -p 30000
これで動きますが、プロセスが死んだりすると不安なので、 monitを使って死活管理をおこなうようにします。
/etc/monit
1 check process swiftiply 2 with pidfile /var/run/swiftiply.p id 3 group root 4 start program = "/etc/init. d/swiftipl y start" 5 stop program = "/etc/init. d/swiftipl y stop" 6 if failed port 4000 then restart 7 if 5 restarts within 5 cycles then timeout 8 9 check process merbist 10 with pidfile /mnt/app/m erbist/cur rent/log/m erb.30000. pid 11 group root 12 start program = "/mnt/app/m erbist/sha red/script /start" 13 as uid app and gid app 14 stop program = "/mnt/app/m erbist/sha red/script /stop" 15 as uid app and gid app 16 if failed port 30000 then restart 17 if 5 restarts within 5 cycles then timeout 18 depends on swiftiply
以上で完了。
現在、http://mer
See Aslo
追記
しばらく運用してみたのですが、プロセスが数時間に一回ぐらいのペースで落ちる問題があったので、Swiftiplyの代わりにPoundを使う構成に変えました。 Swiftiplyは次のバージョン0.7.0から、クラスタリングのサポートが強化されるようなので、それまで待ってみた方が良いかもしれないですね。
Ruby-1.9.1
1 >> puts RubyVM::InstructionSequence.new("puts 'Hello, world!'").disasm #=> nil 2 == disasm: <RubyVM::Instructio nSequence:<compiled>@<compiled>>========== 3 0000 trace 1 ( 1) 4 0002 putnil 5 0003 putstring "Hello, world!" 6 0005 send :puts, 1, nil, 8, <ic> 7 0011 leave
生成したInstractio
1 >> RubyVM::InstructionSequence.new("puts 'Hello, world!'").eval #=> nil 2 Hello, world!
さらに、to_aメソッドで個々のインストラクションに分解する事も出来ます。
1 >> RubyVM::InstructionSequence.new("puts 'Hello, world!'").to_a 2 ["YARVInstru ctionSeque nce/Simple DataFormat ", 1, 1, 1, {:arg_size=>0, :local_size =>1, :stack_max=>2}, "<compiled>", "<compiled>", :top, [], 0, [], [1, [:trace, 1], [:putnil], [:putstring, "Hello, world!"], [:send, :puts, 1, nil, 8, nil], [:leave]]]