Apacheモジュールのmod-spdyを入れてみました。
SPDYは、HTTPを拡張して単一のセッションで複数リクエストを送受信することができるプロトコルです。
利用にはHTTPS通信可能な環境が必要です。

インストールはRPMが配布されているため、それを使うと楽です。

mod_spdy - Google Developers
https://developers.google.com/speed/spdy/mod_spdy/

yum install at
wget https://dl-ssl.google.com/dl/linux/direct/mod-spdy-beta_current_x86_64.rpm
rpm -U mod-spdy-beta_current_x86_64.rpm


インストールすると、Apacheのconf.dディレクトリに設定ファイルができるので、確認するといいでしょう。

ハマったところは、ApacheのSSLRequireSSLディレクティブを利用していると403が出てしまうことでしょうか。

mod_spdy doesn't work with SSLRequireSSL
http://code.google.com/p/mod-spdy/issues/detail?id=31

ひとまず、SSLRequireSSLディレクティブを外して動作させてみました。

ChromeでSPDY通信が有効になっているか確認する場合は、「chrome://net-internals/#spdy」にアクセスするか、以下のエクステンションを使うのが楽です。

Chrome ウェブストア - SPDY indicator
https://chrome.google.com/webstore/detail/spdy-indicator/mpbpobfflnpcgagjijhmgnchggcjblin
(SPDYの時は、URLのわきに緑色の稲妻のようなマークが出ます。)

パフォーマンスの差は体感できませんでした。実運用しているサービスのテスト環境に入れたため、画像などのリソースが別ドメインにあるとかSPDYがあまり効かない条件がそろっていました。

今のところ実運用する必要性は感じていませんが、注目のプロトコルですので、引き続き、チェックはしたいと思います。

Posted by あかさた
facebook Commentsプラグインの幅をレイアウトに合わせて可変にしたかったので
やり方を調べていたところ、Stack Overflowにやり方があったので、やってみました。

javascript - How to make facebook comment box width 100%? - Stack Overflow
http://stackoverflow.com/questions/10862256/how-to-make-facebook-comment-box-width-100

.fb-comments, .fb-comments span, .fb-comments iframe {
    width: 100% !important; 
}


このブログは、レスポンシブにしてあるので、このまま動作するか不安でしたが
ぱっと見、問題なく動いていそうだったので、これで良しとすることにしました。

Posted by あかさた
以下の脆弱性がアナウンスされていたため、本ブログのRailsのアップグレードを実施しました。

JVNVU#94771138 Ruby on Rails に複数の脆弱性
http://jvn.jp/cert/JVNVU94771138/

(1) GemfileのRailsバージョンを変更
(2) route.rb, environments下のファイルを退避(上書きされるため)
(3) 以下のコマンドを実施

bundle update
rake rails:update


特にハマるところもなく終了。

Posted by あかさた
以下の記事を読むと、DCIはRubyでは遅いという指摘があったので、移譲で
実装すればいいと思ったので、下記記事のサンプルコードをもとに、
send/method_missing, forwardable, delegateを使ったサンプルを書いて
みました。

※ 上記記事では移譲を使ったアプローチにも言及しているし、改善するには
頑張らないといけないという程度の話と認識しました。

■ ベンチマークの結果(ruby 1.9.3p194)

         without dci  3024223.4 (±1.7%) i/s -   15139474 in   5.007655s
            with dci   768491.0 (±6.6%) i/s -    3833440 in   5.011732s
      with dci(send)  1586461.1 (±2.1%) i/s -    7977320 in   5.030680s
with dci(forwardable)
                      1712079.6 (±1.8%) i/s -    8580546 in   5.013597s
  with dci(delegate)  1134862.9 (±1.3%) i/s -    5701904 in   5.025205s


見にくくて済みません。コードは下の方にあります。

■ 思ったこと

元記事のベンチマークは、オブジェクトの生成コストくらいしかないような
処理にextendを突っ込んでいるため、そりゃ比較にならないだろうという
問題があります。

そもそも、処理が無いならDCIを入れる意味なんてほとんどないことを考えれば、
ここのコストは無視してもいいものなのですが、無視してもいいコストをいかに
削るかという、無駄に挑戦することも一興かなと思い、記事にしました。

fooメソッドの処理内容によっては(※)、extendを使った元記事のアプローチの
方が優秀な場合もあると思います。柔軟性などを考えれば、移譲の方が使い勝手が
いいだろうとも思いますが。

※ 単純な移譲にならずに、Double Dispatchになるとオーバーヘッドで遅くなる
可能性もあると思います。

さて、ベンチマーク結果に移ると、forwardableが意外と速い。先に書いた通り、
オブジェクト生成コストしかないような処理に対して、半分程度の速度低下で
DCIが実現できるということです。これは、RubyにおけるDCIの実用性を示す
ものではないでしょうか。

■ 余談

これ、DCIじゃなくてRoleObjectじゃんって突っ込みが入りそうですが、
DCIで設計したらRoleObjectで実装するのが定番かなと思ってます。あとは、
Decoratorかな。やったことないけど。

しかし、皆DCIに突っ込んでいくとか、勇敢すぎると思う。Coplienの名前が
出たら全力で逃げるところだろう。マルチパラダイムデザインの恐怖を
忘れたんだろうか。。。(ネタですよ。念のため。)

■ ソースコード

require 'rubygems'
require 'benchmark/ips'
require 'forwardable'
require 'delegate'

class ExampleClass
  def foo; 42; end
end

module ExampleMixin
  def foo; 43; end
end

class ExampleClassSend
  def initialize(role)
    @role = role
  end
  
  def method_missing(action, *args)
    @role.__send__(action, *args)
  end
end

class ExampleClassForwardable 
  extend Forwardable
  
  def initialize(role)
    @role = role
  end
  
  def_delegator :@role, :foo, :foo
end

class ExampleClassDelegate < SimpleDelegator
end

class ExampleRole
  def foo
    43; 
  end
end

@role = ExampleRole.new

Benchmark.ips do |bm|
  bm.report("without dci") { ExampleClass.new.foo }
  
  bm.report("with dci") do
    obj = ExampleClass.new
    obj.extend(ExampleMixin)
    obj.foo
  end
  
  bm.report("with dci(send)") do
    ExampleClassSend.new(@role).foo
  end
  
  bm.report("with dci(forwardable)") do
    ExampleClassForwardable.new(@role).foo
  end
  
  bm.report("with dci(delegate)") do
    ExampleClassDelegate.new(@role).foo
  end
end


Posted by あかさた
勉強がてら、Bootstrapを使ってブログの見た目を変えてみました。ついでに、Rails 1(!)から3.2に移行しました。

新しい方
http://akasata.com/

古い方
http://www.rmake-labo.com/akasata

見比べると全然違いますが、サイトの構造は、コメント、トラックバックなどのいくつかの機能を無くしたこと以外は変わっていません。BootstrapはレスポンシブWebデザインにも対応していることから、スマフォやタブレットでもそこそこ見えるようになっています。

ちなみに、コードのハイライトはgoogle-code-prettifyを使っています。

基本、はてなブログを使っているので、3年ほど更新していませんでしたが、こちらに乗り換えようかなと検討中。。。

Posted by あかさた
Railsでクラス数が増えてくるとフォルダ分けしたくなることがあります。その場合、Javaのパッケージと同じように、モデルをフォルダ分けして、モジュール下に宣言してやることになります。以下のような感じです。

class ModuleName::ModelName < ActiveRecord::Base
end


ところが、belongs_toとかhas_manyとかの関連を解決する際に、以下のようなエラーが出て手がつけられなくなることがあります。悪名高きActiveSupportの「XXX is not missing constant YYY」ですね。

ArgumentError in Hogehoge/Fugafuga#nanika
ModuleName is not missing constant ModelName

<<中略>>

c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:253:in
 `load_missing_constant'
c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:468:in
 `const_missing'
c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:486:in
 `send'
c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:486:in
 `const_missing'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/base.rb:1912:in `compute_type'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/reflection.rb:133:in `send'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/reflection.rb:133:in `klass'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/associations/
belongs_to_association.rb:44:in `find_target'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/associations/
association_proxy.rb:192:in `load_target'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/associations/
association_proxy.rb:99:in `reload'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/associations.rb:1092:in `image'

<<中略>>


Railsのソースコードを追った感じでは、load_missing_constantメソッドの中でModuleName.const_defined?(ModelName)していて、これtrueを返すと、上記の例外を投げます。嫌なにおいがぷんぷんとするのですが、あまり深追いしないようにします。

で、この現象、モデルやコントローラの中で、「ModelName」で呼び出していると発生するのですが、「ModuleName::ModelName」と書いてやると発生しなくなります。必ず再現するわけでもないようで、結構長いこと私はこの現象が発生していることに気づきませんでした。

結構はまったのが、本現象は、単一テーブル継承でtypeにモジュール名無しのモデル名を書き込んでしまっても発生することです。

本現象はRails2.1.2で発生していますが2.3.2でも発生しているっぽいです。この問題で2時間くらい悩んでしまった。。。

Posted by あかさた
RailsでSubdomainFuとRestfulAuthenticationを組み合わせて使おうとしたら、ログイン後のリダイレクトの処理(redirect_back_or_default)でサブドメインが渡らないことに気がつきました。(あたりまえですが・・・。)

とりあえずの処置として、AuthenticatedSystemのstore_locationを書き直すことにしました。RestfulAuthenticationでは、ユーザーが認証が必要なページにアクセスする際にstore_locationを呼び出して、ログイン処理後のリダイレクト先を保存するので、このタイミングにサブドメインも(というかURL丸ごと)保存することにしました。

def store_location
  session[:return_to] = request.protocol + request.env['HTTP_HOST'] + request.request_uri
end

def redirect_back_or_default(default)
  redirect_to(session[:return_to] || default)
  session[:return_to] = nil
end



意外とサブドメインを扱うのは面倒です。。。

Posted by あかさた
なでしこのクジラ飛行机さんと一緒に実践バグ管理という本を書きました。なかなかバグ管理のやり方(レポートの書き方からバグの管理まで)をまとめた本がないなぁと思い書いた本です。詳しい紹介は以下から。

そろそろバグ管理についてひとこと言っておくか - 平凡なエンジニアの独り言

Posted by あかさた
今まで作ってなかったのが不思議なくらいでしたが、某本の執筆で必要になったので、Kodougu にロバストネス図をつけました。とりあえずクラス図由来のものを作っています。コミュニケーション図由来のものも近いうちに出したいと思います。

ロバストネス図のサンプル

続きを読む

Posted by あかさた
ここしばらく POSA 本 を片手にアーキテクチャパターンを再勉強して記事にしています。アーキテクチャパターン Blackboard の記事ができたので紹介します。

八角研究所 : POSA 本でアーキテクチャパターンを勉強しよう(4) - アーキテクチャパターン「混沌から構造へ」より「Blackboard」
http://www.hakkaku.net/articles/20080825-262

過去の記事は以下の通りです。

■ 上記連載の趣旨

アーキテクチャパターンはシステムの基本となる構造を定義するための大規模なパターンです。デザインパターンのようにシステムの部分的な設計を支援するものではなく、システム全体の構造を対象にしています。

アーキテクチャレベルの判断は、部分的な設計判断よりリスクが高いことが多いわけですが、その割にはなかなか勉強する機会がありません。

そこで、アーキテクチャ設計を勉強できる数少ない本の一つであるPOSA 本 を片手にアーキテクチャパターンを勉強するための記事を書いてみることにしました。

しかし、パターンに対するイメージはさまざまです。構造を重視しすぎるあまり、「実際の開発で導き出される設計と何か違う」という理由で忌避する人がいることも事実です。パターンの紹介記事の中には、構造や実装のみを紹介することで、こうした傾向をあおっている節もあります。

# 小難しいから回避する人もいますが。。。

本当はパターンは、「なぜそのような設計判断をするか」「どのようなときにその設計を用いるのか」など、意思決定のプロセスを残し、あるいは読み手が学習するためのものです。本記事では、わかりやすさは重視しながらも、できる限りパターンのメリットを殺さないように書くことを心がけています。

Posted by あかさた