Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need to use add_index on migration for belongs_to/has_many relationship? (Rails 3.2, Active Record)

My question is quite simple but I failed to find a clear answer.

I build a daily deals Rails app.

  • Each deal has many products (has_many)

  • Each product belongs to a deal

Folowing 2.3 from Rails Guides, I'll use this in my migration:

   class CreateDeal < ActiveRecord::Migration
    def change
      create_table :deals do |t|
        t.string :name
        t.timestamps
      end

      create_table :products do |t|
        t.belongs_to :Deal
        t.timestamps
      end
    end
   end

Automatically, Rails/active records will add in the Product Table a column deals_id right?

Do I need to add an index on this deals_id column manually (like below) by adding to my migration add_index or is it done "automatically" because of the belongs_to/has_many relationship I have set?

create_table :products do |t|
  t.belongs_to :Deal
  t.timestamps

  add_index :products, :deals_id 
end
like image 459
Mathieu Avatar asked Sep 07 '13 12:09

Mathieu


3 Answers

You do need to add the index yourself... However, if you use the command line generator for the model and use belongs_to, Rails will add in the index into the migration...

e.g.

rails g model product deal:belongs_to

would produce

class CreateProducts < ActiveRecord::Migration
  def change
    create table :products do |t|
      t.belongs_to :deal

      t.timestamps
    end
    add_index :products, :deal_id
  end
end
like image 81
Helios de Guerra Avatar answered Oct 20 '22 19:10

Helios de Guerra


You would need to add the indexing yourself.

Also your migration isn't quite right, you need a 3rd table ie:

class CreateDeal < ActiveRecord::Migration
  def change
    create_table :deals do |t|
      t.string :name
      t.timestamps
    end

    create_table :products do |t|
      t.string :title
      t.timestamps
    end

    create_table :deals_products do |t|
      t.belongs_to :deal
      t.belongs_to :product
    end
  end
end

As per http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association

like image 44
veritas1 Avatar answered Oct 20 '22 20:10

veritas1


Mathieu, in situations of doubt like this, where you're not sure if something is being created or not created: it seems best to just explicitly create what you think is needed (in this case the index) and see what happens when you run the migration.

The logic behind this is that if your :deal_id column is already indexed and your migration tries to re-index it, it will get an error and the migration will rollback so you can fix it. However if you didn't add the index in your migration, you would obviously not get any errors but you'd have to take an extra step to check if the index exists.

class CreateDeal < ActiveRecord::Migration
  def change
    create_table :deals do |t|
      t.string :name
      t.timestamps
    end

    create_table :products do |t|
      t.belongs_to :Deal
      t.timestamps
    end

    add_index :products, :deal_id
  end
end

Note that you also want to add the index after the table creation process has complete. Using the add_index helper inside the create_table helper is probably going to cause an error.

like image 23
makewavesnotwar Avatar answered Oct 20 '22 20:10

makewavesnotwar