0

Is this even possible?

I have a mongoid class named Magazine, with some associations as well, that I would like to re-name to Publication. Problem is that I already have a bunch of users who have already made magazines, issues and articles.

Original Magazine model:

class Magazine
  # 1. Include mongoid stuff
  include Mongoid::Document
  include Mongoid::Timestamps
  include Mongoid::Slug

  # 2. Define fields
  field :title, type: String
  field :description, type: String
  field :live, type: Boolean, default: false
  field :show_walkthrough, type: Boolean, default: true

  # 3. Set attributes accesible
  attr_accessible :title, :description, :live, :show_walkthrough, :cover_image_attributes, :logo_image_attributes

  # 4. Set slug
  slug :title

  # 5. Set associations
  belongs_to :user
  has_many :issues, dependent: :delete, autosave: true
  has_one :foreword, :as => :articleable, :class_name => 'Article', dependent: :delete, autosave: true
  embeds_one :cover_image, :as => :imageable, :class_name => 'Image', cascade_callbacks: true, autobuild: true
  embeds_one :logo_image, :as => :imageable, :class_name => 'Image', cascade_callbacks: true, autobuild: true

  # 6. Accepting nested attributes
  accepts_nested_attributes_for :cover_image, :allow_destroy => true
  accepts_nested_attributes_for :logo_image, :allow_destroy => true

  # 7. Set validations
  validates_presence_of :title, :description, :cover_image, :logo_image
end

I know I can change the class-name to Publication and then do db.magazines.renameCollection( "publications" ) on the mongodb, but the associations doesn't follow along.

Any suggestions?

Holger Sindbaek
  • 2,278
  • 6
  • 41
  • 68
  • Is this really not possible? As I see it, I basically just need to change the relationship-names as well as the collection-name. I wouldn't know how to do that though. – Holger Sindbaek Jul 18 '13 at 02:44

2 Answers2

0

I looks like you have association fields in your Issue and Foreword models that probably refer to Magazine. So if you are happy enough to change the name of the class and underlying collection then renaming these association fields is your main problem. You may have something like:

class Issue
  belongs_to :magazine
end

You could redefine this association as belongs_to :publication. Assuming that are happy to fix all the references to Issue#magazine in your code then your remaining problem is that your issues collection will be full of documents that have a magazine_id field instead of publication_field. You have two options to fix the database mapping.

First option is to rename the field in the database. See mongoDB : renaming column name in collection

The second option is to declare the association so that it maps to the old database field by overriding the 'foreign key' name:

belongs_to :publication, foreign_key: :magazine_id

You will have to repeat this for the Foreword model and any others that reference Magazine.

Community
  • 1
  • 1
Steve
  • 15,606
  • 3
  • 44
  • 39
  • Thanks for clarifying. If I do option 1, rename the column name in the collection, then all the publication_id's disappear. That's not good. If I go with option 2 (which I think should be: belongs_to :publication, foreign_key: :magazine_id), then I get to keep the id's but the association still doesn't work. What am I doing wrong here? – Holger Sindbaek Jul 18 '13 at 08:33
  • You're right - I got the belongs_to round the wrong way, I will update that. As for option 1, it should preserve the values when you rename `magazine_id` to `publication_id`. Can you check that in the mongo shell? If that works and the association is renamed to `publication` then it should work. – Steve Jul 18 '13 at 10:29
  • When renaming magazine_id to publication_id, it does preserve the magazine_id, but the relation doesn't work anymore. The relation breaks. Why is that? – Holger Sindbaek Jul 18 '13 at 14:24
  • You also need to change the association name, e.g. `belongs_to :publication` and any references to the association in your code. – Steve Jul 18 '13 at 15:03
0

Just a heads up for polymorphism and class inheritance.

Mongoid handles inheritance and polymorphic associations by storing the class name as a document attribute.

On the class itself, this is stored as the "_type" attribute

For polymorphic associations like belongs_to :polymorphic_class mongoid adds an attribute "polymorphic_class_type", so that the class can be resolved (with Rails' .constantize) when browsing polymorphic associations.

So if you decide to change the class name, and you have inheritance or polymorphic associations, well you'll have to also rewrite all those attributes !

Cyril Duchon-Doris
  • 12,964
  • 9
  • 77
  • 164