Search code examples
ruby-on-railsrubymongodbmongoid4

Mongoid many to many relationship not working, what is wrong with my models?


I'm following the book Ruby and MongoDB Web Development, and and trying to follow the examples as much as possible, but for some reasons I'm not able to get it working.

This is what I have so far, models:

app/models/book.rb

class Book
     include Mongoid::Document

     field :title, type: String
     field :publisher, type: String
     field :published_on,  type: Date

     field :votes, type: Array

     belongs_to :author
     has_and_belongs_to_many :categories

     embeds_many :reviews
end

app/models/author.rb

class Author
     include Mongoid::Document

     field :name, type: String

     has_many :books
end

app/models/category.rb

class Category
     include Mongoid::Document

     field :comment, type: String
     field :username, type: String

     has_and_belongs_to_many :books
end

So far so good, then in the rails console

irb(main):001:0> b  = Book.new(title: "Oliver Twist", publisher: "Dover Publications", :published_on => Date.parse("2002-12-30"))
=> #<Book _id: 53c9215c456d655abb000000, title: "Oliver Twist", publisher: "Dover Publications", published_on: 2002-12-30 00:00:00 UTC, votes: nil, author_id: nil, category_ids: nil>

irb(main):002:0> Category.create(name: 'Fiction')
=> #<Category _id: 53c92161456d655abb010000, name: "Fiction", book_ids: nil>

irb(main):004:0* Category.create(name: 'Drama')
=> #<Category _id: 53c92166456d655abb020000, name: "Drama", book_ids: nil>
irb(main):005:0> b.categories << Category.first
=> [#<Category _id: 53c92161456d655abb010000, name: "Fiction", book_ids: [BSON::ObjectId('53c9215c456d655abb000000')]>]

irb(main):006:0> b.categories << Category.last
=> [#<Category _id: 53c92161456d655abb010000, name: "Fiction", book_ids: [BSON::ObjectId('53c9215c456d655abb000000')]>, #<Category _id: 53c92166456d655abb020000, name: "Drama", book_ids: [BSON::ObjectId('53c9215c456d655abb000000')]>]

irb(main):007:0> b.save
=> true
irb(main):008:0> b
=> #<Book _id: 53c9215c456d655abb000000, title: "Oliver Twist", publisher: "Dover Publications", published_on: 2002-12-30 00:00:00 UTC, votes: nil, author_id: nil, category_ids: [BSON::ObjectId('53c92161456d655abb010000'), BSON::ObjectId('53c92166456d655abb020000')]>

irb(main):009:0> Category.first
=> #<Category _id: 53c92161456d655abb010000, name: "Fiction", book_ids: nil>
irb(main):010:0>

The category object does not get updated, what is happening? What I'm doing wrong?. help!

Info: Rails 4, Mongoid 4, Ruby 2.1, MongoDB 2.6

Edit 1:

line embedded_in :book removed unnecessary line from file app/models/category.rb.


Solution

  • You should use autosave to support syntax of:

    b.categories << Category.first
    b.categories << Category.last
    

    to do this, add this to your models

    has_and_belongs_to_many :books, autosave: true

    has_and_belongs_to_many :categories, autosave: true

    to understand what happens, try following code in console without autosave:

    b  = Book.new(title: "Oliver Twist", publisher: "Dover Publications", :published_on => Date.parse("2002-12-30"))
    c1 = Category.create(name: 'Fiction')
    c2 = Category.create(name: 'Drama')
    b.categories << c1
    b.categories << c2
    b.save
    
    c1.changed?
    c2.changed?
    

    It change parent object, but not save it automatically.