BSON :: InvalidDocument:无法将对象序列化为BSON

时间:2012-05-08 01:26:00

标签: mongodb mongomapper

我正在尝试跟随http://mongotips.com/b/array-keys-allow-for-modeling-simplicity/

我有一个故事文档和一个评级文档。用户会对故事进行评分,因此我希望用户创建许多与评分相关的关系:

class StoryRating
  include MongoMapper::Document

  # key <name>, <type>
  key :user_id, ObjectId
  key :rating, Integer
  timestamps!

end

class Story
  include MongoMapper::Document

  # key <name>, <type>
  timestamps!
  key :title, String
  key :ratings, Array, :index => true

  many :story_ratings, :in => :ratings

end

然后

irb(main):006:0> s = Story.create  
irb(main):008:0> s.ratings.push(Rating.new(user_id: '0923ksjdfkjas'))  
irb(main):009:0> s.ratings.last.save  
=> true  
irb(main):010:0> s.save  
BSON::InvalidDocument: Cannot serialize an object of class StoryRating into BSON.  
    from /usr/local/lib/ruby/gems/1.9.1/gems/bson-1.6.2/lib/bson/bson_c.rb:24:in `serialize' (...)

为什么呢?

1 个答案:

答案 0 :(得分:3)

你应该使用关联“story_rating”方法来推送/追加而不是内部的“评级”Array.push来获得你想要遵循John Nunemaker的“Array Keys Allow For Modeling Simplicity”讨论。不同之处在于,使用关联方法,MongoMapper会将BSON :: ObjectId引用插入到数组中,后者将Ruby StoryRating对象推送到Array中,而底层驱动程序驱动程序无法将其序列化。

这是一个适合我的测试,它显示了不同之处。希望这会有所帮助。

测试

require 'test_helper'

class Object
  def to_pretty_json
    JSON.pretty_generate(JSON.parse(self.to_json))
  end
end

class StoryTest < ActiveSupport::TestCase
  def setup
    User.delete_all
    Story.delete_all
    StoryRating.delete_all
    @stories_coll = Mongo::Connection.new['free11513_mongomapper_bson_test']['stories']
  end

  test "Array Keys" do
    user = User.create(:name => 'Gary')
    story = Story.create(:title => 'A Tale of Two Cities')
    rating = StoryRating.create(:user_id => user.id, :rating => 5)
    assert_equal(1, StoryRating.count)
    story.ratings.push(rating)
    p story.ratings
    assert_raise(BSON::InvalidDocument) { story.save }
    story.ratings.pop
    story.story_ratings.push(rating) # note story.story_ratings, NOT story.ratings
    p story.ratings
    assert_nothing_raised(BSON::InvalidDocument) { story.save }
    assert_equal(1, Story.count)
    puts Story.all(:ratings => rating.id).to_pretty_json
  end
end

结果

Run options: --name=test_Array_Keys

# Running tests:

[#<StoryRating _id: BSON::ObjectId('4fa98c25e4d30b9765000003'), created_at: Tue, 08 May 2012 21:12:05 UTC +00:00, rating: 5, updated_at: Tue, 08 May 2012 21:12:05 UTC +00:00, user_id: BSON::ObjectId('4fa98c25e4d30b9765000001')>]
[BSON::ObjectId('4fa98c25e4d30b9765000003')]
[
  {
    "created_at": "2012-05-08T21:12:05Z",
    "id": "4fa98c25e4d30b9765000002",
    "ratings": [
      "4fa98c25e4d30b9765000003"
    ],
    "title": "A Tale of Two Cities",
    "updated_at": "2012-05-08T21:12:05Z"
  }
]
.

Finished tests in 0.023377s, 42.7771 tests/s, 171.1084 assertions/s.

1 tests, 4 assertions, 0 failures, 0 errors, 0 skips