0

So, I'm using the Ruby MongoDB driver and I want to insert and object like this:

 db.insert_one({
  'game_id' => @token,
  'board' => {
    'tiles' => @board.tiles
  }
})

where @board is an instance of a Board class.

class Board
 attr_accessor :tiles
  def initialize()
    @tiles = [Tile.new, Tile.new]
  end
end

and Tile

class Tile
  def initialize()
    @x = 1, @y = 1
  end
  def to_json(options)
    {"x" => @x, "y" => @y}.to_json
  end
end

So at the end, 'tiles' field should look like this:

'tiles': [{x:1, y:1}, {x:1, y:1}]

I'm getting this error:

undefined method `bson_type' for #<Tile:0x007ff7148d2440>

The gems I'm using: 'sinatra', 'mongo (2.0.4)' and 'bson_ext' (all required using Bundler.require). Thanks!

Marcos
  • 4,643
  • 7
  • 33
  • 60
  • The error is telling you that the driver doesn't know how to put a `Tile` instance into MongoDB, MongoDB doesn't know what to do with `Tile`s and no one will automatically call `to_json` for you. – mu is too short Jun 11 '15 at 02:25
  • I've tried calling to_json, but it inserts the content as a String (a json string), not as an Array. – Marcos Jun 11 '15 at 08:00
  • `to_json` returns a string, `as_json` returns a Hash. Yes, the naming is a bit confusing. Sorry, that wasn't my clearest comment ever. – mu is too short Jun 11 '15 at 17:11

1 Answers1

2

You can simply transform @board.tiles from collection of Objects to collection of ruby Hashes:

class Tile
  def initialize()
    @x = 1, @y = 1
  end
  def raw_data
    {"x" => @x, "y" => @y}
  end
end

db.insert_one({
  'game_id' => @token,
  'board' => {
    'tiles' => @board.tiles.map(&:raw_data)
  }
})

For more complex thing I recommend you to use mongoid http://mongoid.org/en/mongoid/

  • (I cannot prove the code right now) But that would insert a (json )string and not an array, right? I'm aware of Mongoid, I just thought my problem was easy enough to use the native driver :p Thanks! – Marcos Jun 11 '15 at 07:59
  • @enrmarc You are almost right. There was a problem in my solution. It was transforming `tiles` to array of strings. But now I modified it to return an array of hashes – Rostyslav Diachok Jun 11 '15 at 11:52