:yの悲劇

Posted by nanki Thu, 21 Dec 2006 09:51:00 GMT

GPS情報を格納するのに、

class Entry < ActiveRecord::Base
  has_one :location
end

class Location < ActiveRecord::Base
  # 実際にはGeometry型で格納するので、アクセサを定義
  def x
    point.x
  end
  def y
    point.y
  end
end

こんなモデルを作ると・・・

$ script/console
>> entry = Entry.find(:first)
>> entry.location.x
=> 135.0
>> entry.location.y
=> 35.0
>> entry.location.send :x
=> 135.0
>> entry.location.send :y
ArgumentError: wrong number of arguments (0 for 1)
        from (irb):35:in `y'
        from (irb):35:in `send'
        from (irb):35

xは大丈夫なのにyはだめ?

yの正体は、pのようにyamlを吐くprivate method、Kernel#y in yaml.rb。 何故だ?

entry.location の中身は、実はAssociationProxyで、ActiveRecordのソースを見るとこんな風になっている。

# lib/active_record/associations/association_proxy.rb
module ActiveRecord
  module Associations
    class AssociationProxy #:nodoc:
      attr_reader :reflection
      alias_method :proxy_respond_to?, :respond_to?
      alias_method :proxy_extend, :extend
      instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?|^proxy_respond_to\?|^proxy_extend|^send)/ }

entry.location.send :x すると、AssocationProxy#xが無いのでtargetにsendされるが、entry.location.send :y だと、Kernel#yが見つかってしまうのか・・・

当然entry.location.target.send :y だとうまくいく。

Ruby1.9 だとsendの仕様が違ってうまくいきそう。

Posted in , ,  | Tags ,  | 4 comments | no trackbacks

Comments

  1. keisuken said about 3 hours later:

    微妙に今やってるのと重なる(もしかして同じ構成のシステム(^^;). とりあえずこちらはlatitude,longitudeにしてます. #Google Mapsが分秒単位じゃなくてはまった口 Ruby勉強ネタになるのかな.

  2. nanki said about 19 hours later:

    名前を変更するのが一番早い解決法だったんですが・・・

    せっかくなので原因を探ってみました。 メタ情報を得るメソッド類もほとんどundefされているので、ソースを見るまで意味不明で。

    位置情報を扱うと、コアの部分は似たような構成になりますね。

  3. babie said 20 days later:

    人柱ありがとう!w latitude, longitude にしまつ。

  4. nanki said 20 days later:

    AssociationProxy において、private なメソッドにアクセスできてしまうsend を使ってるのがおかしな話なんですが。

    パッチ書く気力が起きない・・・

Trackbacks

Use the following link to trackback from your own site:
http://blog.netswitch.jp/articles/trackback/3915

(leave url/email »)

   Comment Markup Help Preview comment