1

我正在尝试跟随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' (...)

为什么?

4

1 回答 1

3

您应该使用关联“story_rating”方法进行推送/追加,而不是内部“评级”Array.push 以获得您想要遵循 John Nunemaker 的“Array Keys Allow For Modeling Simplicity”讨论的内容。不同之处在于,使用关联方法时,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
于 2012-05-08T19:08:18.667 回答