balvig/spyke

calling to_json on Spyke object results in infinite loop

wired9 opened this issue · 1 comments

Here's the very basic example to reproduce:
A server which has model Foo with one attribute bar, and controller like this:

class FoosController < ApplicationController
  def index
    @foos = Foo.all
    render json: @foos
  end

  def show
    @foo = Foo.find(params[:id])
    render json: @foo
  end
end

A client with config like this:

class JSONParser < Faraday::Response::Middleware
  def parse(body)
    json = MultiJson.load(body, symbolize_keys: true)
    {
      data: json,
    }
  end
end

Spyke::Base.connection = Faraday.new(url: 'http://127.0.0.1:3000/') do |c|
  c.request   :json
  c.use       JSONParser
  c.adapter   Faraday.default_adapter
end

And Spyke model Foo:

class Foo < Spyke::Base
end

Now, in console in client:

2.1.2 :008 >   foo = Foo.all.first
  Spyke (13.4ms)  GET http://127.0.0.1:3000/foos [200]
 => #<Foo(foos/(:id)) id: 1 bar: "asdasdasd" created_at: "2015-10-28T03:02:06.890Z" updated_at: "2015-10-28T03:02:06.890Z">

2.1.2 :009 > foo.to_json
  Spyke (15.4ms)  GET http://127.0.0.1:3000/foos [200]
  Spyke (8.8ms)  GET http://127.0.0.1:3000/foos [200]
  Spyke (8.1ms)  GET http://127.0.0.1:3000/foos [200]
  Spyke (19.8ms)  GET http://127.0.0.1:3000/foos [200]
  Spyke (9.1ms)  GET http://127.0.0.1:3000/foos [200]
  Spyke (11.0ms)  GET http://127.0.0.1:3000/foos [200]
  Spyke (10.9ms)  GET http://127.0.0.1:3000/foos [200]
  Spyke (7.1ms)  GET http://127.0.0.1:3000/foos [200]
 ...etc

A workaround is to exclude 'scope' attribute from serialization:

class Foo < Spyke::Base
  def to_json(options = {})
    options[:except] = Array(options[:except])
    options[:except] << 'scope'
    super(options)
  end
end
2.1.2 :001 > foo = Foo.all.first
  Spyke (12.8ms)  GET http://127.0.0.1:3000/foos [200]
 => #<Foo(foos/(:id)) id: 1 bar: "asdasdasd" created_at: "2015-10-28T03:02:06.890Z" updated_at: "2015-10-28T03:02:06.890Z"> 
2.1.2 :002 > foo.to_json
 => "{\"attributes\":{\"id\":1,\"bar\":\"asdasdasd\",\"created_at\":\"2015-10-28T03:02:06.890Z\",\"updated_at\":\"2015-10-28T03:02:06.890Z\"},\"uri_template\":\"foos/(:id)\"}" 

Wow, thanks for spotting this! And for the detailed report on how to reproduce it.
Fixed in 4.0.1!