2014年4月2日水曜日

has-a関係でmethod_missingを使う


上図のように、クラス間が「has-a関係」になっている場合、Noodleクラス側からSoupクラスの属性を参照するには、
irb(main):001:0> Noodle.first.soup.aji
=> "こってり"
のようにして、包含しているSoupクラスを毎回指定する必要がある。

Soupクラスの属性がNoodleクラスの属性であるかのように見せるためには、
  def aji
    return soup.aji
  end
irb(main):003:0> Noodle.first.aji
=> "こってり"
のように、Noodleクラス側でSoupクラスの属性を返すメソッドを実装すれば良いだのだが、属性の数が多いと面倒である。

そこで下記のように、method_missingというメソッドを使って、Noodleクラスに存在しない属性が参照された場合は自動的にSoupクラスの属性を参照して返すように記述すると、
  def method_missing(method, *args)
    eval("soup." + method.to_s)
  end
irb(main):006:0* Noodle.first.aji
=> "こってり"
Soupクラスの属性すべてがSoupクラスを指定しなくても参照できるようになった。

2014年2月2日日曜日

Processing.jsでマウスの現在位置がずれる(Chrome限定)

左のように、ブラウザの縦スクロールが必要なほど長い Canvasを設定すると、マウスのY座標の現在位置がずれる。

具体的には、左のインナーフレームの任意の場所をクリックすると、クリックした場所を中心とした半径50pxの白丸が描かれる。

ところが、ブラウザを一番下まで縦スクロールさせた状態では、フレームの下の方をクリックしても白丸が表示されない。

マウスをかなり画面の上の方まで持って行ってからクリックをすると、ようやく白丸が表示されるが、現在地よりもかなり下の場所に表示されてしまう。

ブラウザ上では、スクロールした分だけ現在地が調整されているにも関わらず、Processing.js側では、単純に現在地にスクロールした分の距離が足されているようだ。

これはどうもChrome限定のバグのようで、FireFoxやInternetExplorerでは正常に表示されている。

Processing.jsのBug Trackerには既に同様のエラーが登録されているようなので、修正版のリリースを待ちたい。

Mouse position bug in Chrome 32.0.1700.102
http://processing-js.lighthouseapp.com/projects/41284/tickets/2066-mouse-position-bug-in-chrome-3201700102#ticket-2066-1

今回使用したテスト用のコードは下記のようになっている。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
    <script src="processing-1.4.1.js" type="text/javascript"></script>
    <script type="text/processing" data-processing-target="mycanvas">
    int selectedX = null;
    int selectedY = null;

    void setup() {
      frameRate(3);
      size(100, 1000);
    }
    void draw() {
      background(0);
      fill(255);

      if (selectedX != null && selectedY != null) {
        ellipse(selectedX, selectedY, 50, 50);
      }
    }
    void mousePressed() {
      selectedX = mouseX
      selectedY = mouseY
    }
    </script>
  </head>
  <body>
    <p>
    <canvas id="mycanvas"></canvas>
    </p>
  </body>
</html>