3

I have studied several questions on this topic today. I know that, I can use t.references in migration to add a reference. But, If a table has non-integer primary key, how do I add reference to that column?

I have a table with this definition

    create_table :sessions, id: false do |t|
      t.string  :session, primary_key: true, limit: 10  

      t.timestamps null: false
    end

How do I add a reference to the session column (the name doesn't matter here), which is a string from another table migration. I tested with t.references but that just add an integer column. I know that I can use add column. But how to do that without from create_table method directly?

Clarification for duplicate flag
This question is flagged as duplication of this question, but it is actually not. Because I am not asking about setting up table with non-default non-integer primary key, because I already set up that table. I am asking about referencing this type of table from another table.

Community
  • 1
  • 1
Anwar
  • 1,755
  • 1
  • 21
  • 32
  • possible duplicate of [rails non-integer primary key](http://stackoverflow.com/questions/23846090/rails-non-integer-primary-key) – ABMagil Aug 23 '15 at 16:38
  • 1
    @ABMagil I don't think its a duplicate since Anwar asks about *references* to non-integer primary keys – not the primary keys themselves. – eirikir Aug 23 '15 at 18:43

4 Answers4

4

Rather than using the references helper, you would need to use the string type, and add an index for faster lookups. If your other model is "Record":

rails generate migration AddSessionIdToRecords session:string:index

Which should generate a migration like so:

def change
  add_column :records, :session_id, :string
  add_index :records, :session_id
end

Since you're using unconventional naming, you'd need to specify the primary key in the model and the relation definition:

class Session < ActiveRecord::Base
  self.primary_key = "session"

  has_many :records, primary_key: "session"
end

class Record < ActiveRecord::Base
  belongs_to :session, primary_key: "session"
end
eirikir
  • 3,802
  • 3
  • 21
  • 39
  • I have setup almost like this, but i think, it is `foreign_key: "session"` instead of `primary_key: "session"`. You should check – Anwar Aug 24 '15 at 12:23
  • What did you name the column on your other table ("`records`")? That's the foreign_key, so if you named it `session`, the foreign_key would be `"session"` – eirikir Aug 24 '15 at 15:22
  • The point is I have to use foreign_key option, not primary_key option – Anwar Aug 24 '15 at 20:00
4

Since rails version 4.2.7 You can specify type into the add_reference helper. Suppose you have table records and you want to have reference of sessions inside records. Then you can do the following :

add_reference :records, :sessions, type: :string, foreign_key: {to_table: :sessions, primary_key: :session}
bilash.saha
  • 7,226
  • 2
  • 35
  • 40
2

Actually, you don't have to add primary_key in class Session & Record

def change
  add_column :records, :session_id, :string
  add_index :records, :session_id
  add_foreign_key :records, :sessions, column: :session_id, primary_key: "your_primary_key_name_in_sessions_table"
end

and that will be all.

Edison Su
  • 21
  • 1
1

I've arrived at the conclusion that, without using foreign_key which is introduced in rails 4.2, I can't truly reference another column, only creating index as suggested by this answer from eirikir.

From rails 4.2, I can use foreign key like this

In session Table migration

create table :sessions, id: false do |t|
  t.string "session", primary_key: true
  t.timestamp null: false
end

For a record table to reference the session primary key

create table :records do |t|
  t.string "session", null: false
  ..
  .. # other attributes
end

add_index :records, :session
add_foreign_key :records, :sessions, column: :session, primary_key: :session

Here, the column: option fixes, on which column i want to create the foreign key and the primary_key: option fixes, the primary key of the referenced table, which is here session.

Community
  • 1
  • 1
Anwar
  • 1,755
  • 1
  • 21
  • 32