Ben
Ben

Reputation: 3357

Namespace models with mongoid

This should not be too difficult, but I'm not finding any answer for it. Trying to organize my models in folders and embed documents with rails and mongoid.

My folder structure:

app/models/book.rb  Book
app/models/book/author.rb   Book::Author
app/models/book/author/bio.rb   Book::Author::Bio
app/models/book/author/interest.rb  Book::Author::Interest

My model classes:

class Book
    include Mongoid::Document
    include Mongoid::Timestamps
    belongs_to :user, inverse_of: :books
    embeds_many :authors
end
class Book::Author
    include Mongoid::Document
    include Mongoid::Timestamps
    belongs_to :book, inverse_of: :authors
    embeds_many :bios
end
class Book::Author::Bio
    include Mongoid::Document
    include Mongoid::Timestamps
    belongs_to :author, inverse_of: :bios
end
class Book::Author::Interest
    include Mongoid::Document
    include Mongoid::Timestamps
    belongs_to :author, inverse_of: :interests
end

When I do:

book = Book.new
book.author

Then I get uninitialized constant Author

Using mongoid 7.0.1 and rails 5.2

I tried to play around with the structure, the class names, etc. but I'm not sure what I'm missing.

Upvotes: 0

Views: 498

Answers (1)

Jagdeep Singh
Jagdeep Singh

Reputation: 4920

As per the comment by @mu is too short, you need to specify the class_name along with defined associations if they don't follow the convention. This is how you can make it work:

class Book
  include Mongoid::Document
  embeds_many :authors, class_name: 'Book::Author'
end

class Book::Author
  include Mongoid::Document

  # `embedded_in` will suit this relation better
  embedded_in :book, inverse_of: :authors
  embeds_many :bios, class_name: 'Book::Author::Bio'
end

class Book::Author::Bio
  include Mongoid::Document
  embedded_in :author, class_name: 'Book::Author', inverse_of: :bios
end

class Book::Author::Interest
  include Mongoid::Document

  # I don't see a relation `interests` anywhere in your models
  belongs_to :author, class_name: 'Book::Author', inverse_of: :interests
end

But, i am a little confused, why do you want to store them this way. Why would an author be embedded in a book as one author can have multiple books? I would change the structure to something like:

class Book
  include Mongoid::Document
  has_and_belongs_to_many :authors
end

class Author
  include Mongoid::Document
  has_and_belongs_to_many :books
  embeds_many :bios, class_name: 'Author::Bio'
  embeds_many :interests, class_name: 'Author::Interest'
end

class Author::Bio
  include Mongoid::Document
  embedded_in :author, inverse_of: :bios
end

# Not exactly sure what this model is for, so with limited information, i will keep it under namespace `Author`.
class Author::Interest
  include Mongoid::Document
  embedded_in :author, inverse_of: :interests
end

Upvotes: 2

Related Questions