Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I add migration with multiple references to the same model in one table? Ruby/Rails

How do I create a migration with two fields that reference the same table? I have tables A, and image. A.image1_id will reference image, and A.image2_id will reference image also. There are only 2 images, not many. If I use

class AddFields < ActiveRecord::Migration    def change     change_table(:ticket) do |t|         t.references :image1_id         t.references :image2_id     end   end end 

I don't think that will work because it will add another _id to the end and probably won't know to use the 'image' model. I also thought about

change_table(:ticket) do |t|     t.references :image 

But then how do I add two of those? I also thought about adding

create_table :images do |t|   t.belongs_to :ticket   t.string :file 

But I only want 2, not many, and this doesn't appear to allow getting to the image from the ticket, like ticket.image1 or ticket.image2.

According to this documentation http://apidock.com/rails/v3.2.8/ActiveRecord/ConnectionAdapters/SchemaStatements/change_table which is all I could find, t.references doesn't appear to take any arguments either.

change_table(:suppliers) do |t|   t.references :company end 
like image 755
Chloe Avatar asked Feb 14 '13 04:02

Chloe


People also ask

How do I add a reference column in rails?

When you already have users and uploads tables and wish to add a new relationship between them. Then, run the migration using rake db:migrate . This migration will take care of adding a new column named user_id to uploads table (referencing id column in users table), PLUS it will also add an index on the new column.


2 Answers

You can do this simply with the add_column method in your migrations and set up the proper associations in your classes:

class AddFields < ActiveRecord::Migration   def change     add_column :tickets, :image_1_id, :integer     add_column :tickets, :image_2_id, :integer   end end  class Ticket < ActiveRecord::Base   belongs_to :image_1, :class_name => "Image"   belongs_to :image_2, :class_name => "Image" end  class Image < ActiveRecord::Base   has_many :primary_tickets, :class_name => "Ticket", :foreign_key => "image_1_id"   has_many :secondary_tickets, :class_name => "Ticket", :foreign_key => "image_2_id" end 

This blog post, Creating Multiple Associations with the Same Table, goes into more detail.

like image 185
rossta Avatar answered Sep 19 '22 04:09

rossta


In Rails 5.1 or greater you can do it like this:

Migration

class AddFields < ActiveRecord::Migration    def change     change_table(:tickets) do |t|         t.references :image1, foreign_key: { to_table: 'images' }         t.references :image2, foreign_key: { to_table: 'images' }     end   end end 

This will create the fields image1_id, and image2_id and make the database level references to the images table

Models

as in rossta's asnwer

class Ticket < ActiveRecord::Base   belongs_to :image_1, class_name: "Image"   belongs_to :image_2, class_name: "Image" end  class Image < ActiveRecord::Base   has_many :primary_tickets, class_name: "Ticket", foreign_key: "image_1_id"   has_many :secondary_tickets, class_name: "Ticket", foreign_key: "image_2_id" end 

FactoryBot

If you uses FactoryBot then your factory might look something like this:

FactoryBot.define do   factory :ticket do     association :image1, factory: :image     association :image2, factory: :image   end end 
like image 20
Toby 1 Kenobi Avatar answered Sep 22 '22 04:09

Toby 1 Kenobi