質問

I'm making a Ruby Sinatra application that uses mongomapper and most of my responses will be in the JSON form.

Confusion

Now I've come across a number of different things that have to do with JSON.

  1. The Std-lib 1.9.3 JSON class: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/json/rdoc/JSON.html
  2. The JSON Gem: http://flori.github.io/json/
  3. ActiveSupport JSON http://api.rubyonrails.org/classes/ActiveSupport/JSON.html because I'm using MongoMapper which uses ActiveSupport.

What works

I'm using a single method to handle responses:

def handleResponse(data, haml_path, haml_locals)
  case true
    when request.accept.include?("application/json") #JSON requested
      return data.to_json
    when request.accept.include?("text/html") #HTML requested
      return haml(haml_path.to_sym, :locals => haml_locals, :layout => !request.xhr?)
    else # Unknown/unsupported type requested
      return 406 # Not acceptable
  end
end

the line:

return data.to_json

works when data is an instance of one of my MongoMapper model classes:

class DeviceType

  include MongoMapper::Document
  plugin MongoMapper::Plugins::IdentityMap

  connection Mongo::Connection.new($_DB_SERVER_CNC)
  set_database_name $_DB_NAME

  key :name,  String, :required => true, :unique => true

  timestamps!

end

I suspect in this case the to_json method comes somewhere from ActiveSupport and is further implemented in the mongomapper framework.

What doesn't work

I'm using the same method to handle errors too. The error class I'm using is one of my own:

# Superclass for all CRUD errors on a specific entity.
class EntityCrudError < StandardError
  attr_reader :action # :create, :update, :read or :delete
  attr_reader :model # Model class
  attr_reader :entity # Entity on which the error occured, or an ID for which no entity was found.
  def initialize(action, model, entity = nil)
    @action = action
    @model = model
    @entity = entity
  end
end

Of course, when calling to_json on an instance of this class, it doesn't work. Not in a way that makes perfect sense: apparantly this method is actually defined. I've no clue where it would come from. From the stack trace, apparently it is activesupport:

 Unexpected error while processing request: object references itself
object references itself
        /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/activesupport-3.2.13/lib/active_support/json/encoding.rb:75:in `check_for_circular_references'
        /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/activesupport-3.2.13/lib/active_support/json/encoding.rb:46:in `encode'
        /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/activesupport-3.2.13/lib/active_support/json/encoding.rb:246:in `block in encode_json'
        /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/activesupport-3.2.13/lib/active_support/json/encoding.rb:246:in `each'
        /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/activesupport-3.2.13/lib/active_support/json/encoding.rb:246:in `map'
        /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/activesupport-3.2.13/lib/active_support/json/encoding.rb:246:in `encode_json'

But where is this method actually defined in my class?

The question

I will need to override the method in my class like this:

# Superclass for all CRUD errors on a specific entity.
class EntityCrudError < StandardError

  def to_json
    #fields to json
  end

end

But I don't know how to proceed. Given the 3 ways mentioned at the top, what's the best option for me?

役に立ちましたか?

解決

As it turned out, I didn't need to do anything special.

I had not suspected this soon enough, but the problem is this:

class EntityCrudError < StandardError
  ..
  attr_reader :model # Model class
  ..
end

This field contains the effective model class:

class DeviceType
  ..
  ..
end

And this let to circular references. I now replaced this with just the class name, which will do for my purposes. Now to_json doesn't complain anymore and I'm happy too :)

I'm still wondering what's the difference between all these JSON implementations though.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top