how to generate migration to make references polymorphic
Asked Answered
C

4

151

I have a Products table and want to add a column:

t.references :imageable, :polymorphic => true

I was trying to generate migration for this by doing:

$ rails generate migration AddImageableToProducts imageable:references:polymorphic

but I am obviously doing it wrong. Can anybody make any suggestion? Thanks

When I try to manually put it in after generating the migration, I did it like this:

class AddImageableToProducts < ActiveRecord::Migration
  def self.up
    add_column :products, :imageable, :references, :polymorphic => true
  end

  def self.down
    remove_column :products, :imageable
  end
end

and it still hasn't worked

Carotenoid answered 4/4, 2011 at 4:31 Comment(2)
Not an answer, but to avoid confusion, are you sure you want this column on Products? The rails guide even has a Products example and the column is on Pictures guides.rubyonrails.org/…Basilicata
This can be handy: :references{polymorphic}. For example, rails generate migration AddImageableToProducts imageable:references:{polymorphic}. SourceFootwall
D
123

Before Rails 4 there was no built-in generator for polymorphic associations. If you are using an early version of Rails generate a blank migration and then modify it by hand according to your needs.

Update: You'll need to specify which table you're changing. According to this SO answer:

class AddImageableToProducts < ActiveRecord::Migration
  def up
    change_table :products do |t|
      t.references :imageable, polymorphic: true
    end
  end

  def down
    change_table :products do |t|
      t.remove_references :imageable, polymorphic: true
    end
  end
end

Rails 4 added a generator for polymorphic associations (see simon-olivier answer)

Dichloride answered 4/4, 2011 at 4:38 Comment(7)
Thank you very much Brandon. I was able to run the migration. I was wondering though, after you make :polymorphic => true and you open schema.rb are you supposed to see it in the schema as well?Carotenoid
After you run the migration, schema.rb should be updated, but it won't say anything about polymorphic. Instead, you should see the actual fields that Rails uses (the Rails Guides have more info).Dichloride
How do you add index to the references column? Do I need to index that?Longhorn
@Longhorn If I'm not mistaken, you do need to add them yourselves if you need them. You can just add indexes as normal in the migration file to imageable_type and/or imageable_id as necessary.Dichloride
Well if I try add_index :products, :imageable, unique: true It throws PG::UndefinedColumn: ERROR: column "imageable" does not exist. I think I need to manually add indexes for the two columns which are generated. Trying that.Longhorn
Yup. adding index to imageable_id and imageable_type worked. Thanks for your help.Longhorn
You should also index this as well: t.references :imageable, polymorphic: true, index: trueForbidden
H
318

What you are trying to do is not yet implemented in the stable version of rails so Michelle's answer is the right one for now. But this feature will be implemented in rails 4 and is already available in the edge version as follows (according to this CHANGELOG):

$ rails generate migration AddImageableToProducts imageable:references{polymorphic}

Some shells may need {polymorphic} escaped with a \:

$ rails generate migration AddImageableToProducts imageable:references\{polymorphic\}
Haem answered 4/3, 2013 at 15:2 Comment(6)
Tried this on 4.2, and I'm not sure if this is a bug, zsh, or something else, but the commandline was interpretted as a series of references (as types) with each letter of polymorphic, like: t.referencesp :imagable, treferenceso :imagable, etc.Eichhorn
@OzBarry, in zsh you'd need to escape the braces: $ rails generate migration AddImageableToProducts imageable:references\{polymorphic\}Alterative
For anyone curious, this generates a migration with change method containing: add_reference :products, :imageable, polymorphic: true, index: trueShivaree
Incase anyone trying to use the same in scaffold, this works with scaffold as well. Thanks! rijksHime
{polymorphic} needs to be escaped with the fish shell, e.g. \{polymorphic\} Demy
Rails official doc about polymorphic migration: guide on rubyonrails.orgColonial
D
123

Before Rails 4 there was no built-in generator for polymorphic associations. If you are using an early version of Rails generate a blank migration and then modify it by hand according to your needs.

Update: You'll need to specify which table you're changing. According to this SO answer:

class AddImageableToProducts < ActiveRecord::Migration
  def up
    change_table :products do |t|
      t.references :imageable, polymorphic: true
    end
  end

  def down
    change_table :products do |t|
      t.remove_references :imageable, polymorphic: true
    end
  end
end

Rails 4 added a generator for polymorphic associations (see simon-olivier answer)

Dichloride answered 4/4, 2011 at 4:38 Comment(7)
Thank you very much Brandon. I was able to run the migration. I was wondering though, after you make :polymorphic => true and you open schema.rb are you supposed to see it in the schema as well?Carotenoid
After you run the migration, schema.rb should be updated, but it won't say anything about polymorphic. Instead, you should see the actual fields that Rails uses (the Rails Guides have more info).Dichloride
How do you add index to the references column? Do I need to index that?Longhorn
@Longhorn If I'm not mistaken, you do need to add them yourselves if you need them. You can just add indexes as normal in the migration file to imageable_type and/or imageable_id as necessary.Dichloride
Well if I try add_index :products, :imageable, unique: true It throws PG::UndefinedColumn: ERROR: column "imageable" does not exist. I think I need to manually add indexes for the two columns which are generated. Trying that.Longhorn
Yup. adding index to imageable_id and imageable_type worked. Thanks for your help.Longhorn
You should also index this as well: t.references :imageable, polymorphic: true, index: trueForbidden
T
49

You could also do the following:

class AddImageableToProducts < ActiveRecord::Migration
  def change
    add_reference :products, :imageable, polymorphic: true, index: true
  end
end
Tequilater answered 24/11, 2014 at 21:38 Comment(1)
The index on imageable_id and imageable_type will be created even without index: true. At least on the recent versions of Rails which is 7.3 at the moment.Baca
A
20

You can try rails generate migration AddImageableToProducts imageable:references{polymorphic}

Anting answered 13/9, 2017 at 7:17 Comment(3)
{ and } need to be escaped with the fish shell at least, e.g. \{polymorphic\}Demy
Here is the link to the documentation about this: edgeguides.rubyonrails.org/…Pulitzer
Thanks Giovanni, that is very useful.Anting

© 2022 - 2024 — McMap. All rights reserved.