4

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.

2
  • possible duplicate of rails non-integer primary key Commented Aug 23, 2015 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. Commented Aug 23, 2015 at 18:43

4 Answers 4

5

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}
Sign up to request clarification or add additional context in comments.

Comments

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

3 Comments

I have setup almost like this, but i think, it is foreign_key: "session" instead of primary_key: "session". You should check
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"
The point is I have to use foreign_key option, not primary_key option
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.

1 Comment

Why should I use :session_id as string?
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.