2012-05-08 33 views
1

我試圖用http://mongotips.com/b/array-keys-allow-for-modeling-simplicity/BSON :: InvalidDocument:不能將對象序列化到BSON

我有一個故事文件和文件評級跟着一起。用戶將率一個故事,所以我想創造收視用戶爲這樣的一對多關係:

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' (...) 

爲什麼?

回答

3

你應該使用關聯的「story_rating」方法來進行push/append,而不是內部的「rating」Array.push來獲得你想要遵循John Nunemaker的「數組鍵允許建模簡單性」的討論。不同之處在於,使用關聯方法,MongoMapper會將BSON :: ObjectId引用插入到數組中,後者將Ruby StoryRating對象推入數組中,並且底層驅動程序驅動程序無法序列化它。

這是一個適合我的測試,它顯示了不同之處。希望這有助於。

測試

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 
+0

如此有用!謝謝! – joslinm

+0

不客氣,很高興提供幫助。 –