Ryan
Ryan

Reputation: 6642

Rails Migration Create Table Primary Key

I am writing a migration script to create a table with a primary key column that is named guid and is a VARCHAR(25). The issue is I feel like I am having to double my effort to achieve what should be possible in one step.

If I run:

create_table(:global_feeds, :primary_key => 'guid') do |t|
  t.string :guid, :limit => 25
  t.text :title
  t.text :subtitle

  ...

  t.timestamps
end

I get a table with a primary key called guid no column called id (which is what I want). However, the issue is the guid column is an INT(11) with auto increment turned on. So I have to run one additional command:

change_column :global_feeds, :guid, :string, :limit => 25

Seems a bit convoluted to have to basically run two SQL commands to get what I believe should be possible in one.

Any suggestions on how to optimize this?

Upvotes: 18

Views: 39643

Answers (5)

Galaxy
Galaxy

Reputation: 1279

In Rails 5, for thoes who got problem ArgumentError: Index name '*' on table '*' already exists when rails db:setup with migration as from @kakoni, the following works for me

create_table(:global_feeds, primary_key: :guid, id: false) do |t|
  t.string :guid
 ...
end

For more information, check create_table.

Upvotes: 1

kakoni
kakoni

Reputation: 5120

In Rails 4 you can do;

create_table :global_feeds, id: false do |t|
  t.string :guid, primary_key: true
 ...
end

Upvotes: 30

Philip Wernersbach
Philip Wernersbach

Reputation: 461

You need to use #column instead of #string. For instance:

create_table(:global_feeds, :primary_key => 'guid') do |t|
  t.column :guid, "varchar(25)", :null => false
  ...
end

Note that the varchar type is not portable to databases other than MySQL.

Upvotes: 4

Max Al Farakh
Max Al Farakh

Reputation: 4486

I suppose you're using mySQL, so here is what you can try

create_table :global_feeds, {:id => false} do |t|
  t.string :guid
  t.text :title
  t.text :subtitle
  t.timestamps
end
execute "ALTER TABLE global_feeds ADD PRIMARY KEY (guid);"

If you're not on mySQL you should change the query in the execute command to work on your DB engine. I'm not sure if you can do that on SQLite though. And don't forget to put this line somewhere in global_feed.rb model:

set_primary_key :guid

Anyway you're getting the most out of Rails while you're sticking to its conventions. Changing primary key name and type might not be a very good idea.

Upvotes: 23

Jordan Sitkin
Jordan Sitkin

Reputation: 2343

This is possible in Rails 3. try:

  def self.up
    create_table(:signups, :id => false) do |t|
      t.string :token, :primary => true

check out this gist for a great solution for using UUIDs as a primary key col: https://gist.github.com/937739

Upvotes: 3

Related Questions