rubyamf / rocketamf

52 stars 34 forks source link

RocketAMF native chokes on proxy array (commonly used in rails) #16

Open sharpone74 opened 10 years ago

sharpone74 commented 10 years ago

Using RocketAMF native

class ProxyArray
  instance_methods.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ }

  def proxy_method
     puts "you just called the proxy method!"
  end

  protected

  def method_missing(name, *args, &block)
    target.send(name, *args, &block)
  end

  def target
    @target ||= []
  end
end

baz = ProxyArray.new
=> []
baz << 1
=> [1]
baz << 2
=> [1, 2]
baz << 3
=> [1, 2, 3]
baz << 4
=> [1, 2, 3, 4]
baz.class
=> Array
RocketAMF.serialize baz, 3
ArgumentError: wrong number of arguments (0 for 1..4)
from /home/justinsharp/.rvm/gems/ruby-1.9.3-p194@cr2rails/bundler/gems/rocketamf-71f372747536/lib/rocketamf/class_mapping.rb:232:in `select'
RocketAMF.serialize baz + [], 3
=> "\n\aCflex.messaging.io.ArrayCollection\t\t\x01\x04\x01\x04\x02\x04\x03\x04\x04"

The second call works because adding [] to the proxy object produces a new true Array object.

Using RocketAMF pure

class ProxyArray
 instance_methods.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ }

 def proxy_method
   puts "you just called the proxy method!"
 end

 protected

 def method_missing(name, *args, &block)
   target.send(name, *args, &block)
 end

 def target
   @target ||= []
 end
end
=> nil

baz = ProxyArray.new
=> []
baz << 1
=> [1]
baz << 2
=> [1, 2]
baz << 3
=> [1, 2, 3]
baz << 4
=> [1, 2, 3, 4]
baz.class
=> Array
RocketAMF.serialize baz, 3
=> "\n\aCflex.messaging.io.ArrayCollection\t\t\x01\x04\x01\x04\x02\x04\x03\x04\x04"

The common use case for this would be if you were trying to serialize something like this code

class User < ActiveRecord::Base
  has_many :pets
end
class Pet < ActiveRecord::Base
  belongs_to :user
end

user = User.first
RocketAMF.serialize(user.pets, 3)

I trounced around in the C code a bit, but it's not immediately obvious to me what the problem is, as I don't have a lot of experience in native ruby C api. If I have some time I will put together a spec for this.