Problems Setting a Custom Primary Key in a Rails 4 Migration

Problems setting a custom primary key in a Rails 4 migration

Take a look at this answer. Try to execute "ALTER TABLE shareholders ADD PRIMARY KEY (uid);" without specifying primary_key parameter in create_table block.

I suggest to write your migration like this (so you could rollback normally):

class CreateShareholders < ActiveRecord::Migration
def up
create_table :shareholders, id: false do |t|
t.integer :uid, limit: 8
t.string :name
t.integer :shares

t.timestamps
end
execute "ALTER TABLE shareholders ADD PRIMARY KEY (uid);"
end

def down
drop_table :shareholders
end
end

UPD: There is natural way (found here), but only with int4 type:

class CreateShareholders < ActiveRecord::Migration
def change
create_table :shareholders, id: false do |t|
t.primary_key :uid
t.string :name
t.integer :shares

t.timestamps
end
end
end

Change Primary Key Issue Rails 4.0

The answer seemed to be that the OP separated the migration into 3 files:

1. Remove `:id` column
2. Rename `:contractId` column to `:id`
3. run `execute "ALTER TABLE contracts ADD PRIMARY KEY (id);"`

This allowed the OP to successfully run the migration

Some other resources:

  • Using Rails, how can I set my primary key to not be an integer-typed column?
  • Problems setting a custom primary key in a Rails 4 migration

Specify custom primary key in migration


 create_table(:my_table, :primary_key => 'userID') do |t|
# Primary key column will be created automatically
# Do not create here
# t.column :userID, :integer, :null => false
...
end

Or

create_table :my_table, {:id => false} do |t|
t.integer :userID
t.string :apikey
t.integer :characterID
t.timestamps
end
execute "ALTER TABLE my_table ADD PRIMARY KEY (userID);"

And don't forget to put this line somewhere in model:

 set_primary_key :userID

How to set primary key in ruby on rails migration?

Don't do this. Use the built-in id field as the primary key. If you're going to use Rails, you should build your app the "Rails way" unless you have very good reason not to.

If you really want to do this, you can pass a :primary_key option to create_table:

create_table :customers, :primary_key => :idClient do |t|
# ...
end

You'll also need to tell your model the name of its primary key via self.primary_key = "idClient"

Rails Model - custom primary key with ID as a custom column

I'd avoid using id this way by renaming it to something else. In rails id is whatever the @primary_key is set to. There is a whole module dedicated to it, that defines id attribute methods:

https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/PrimaryKey.html

These methods can be overridden, but shouldn't:

class Car < ApplicationRecord
self.primary_key = "auto_id"

def id= value
_write_attribute("id", value)
end

def id
_read_attribute("id")
end
end

"id" is hardcoded in write_attribute to use primary_key, so we can't use write_attribute to set id attribute itself.

Also, id methods are used in other places. Overriding them is a bad idea.

>> Car.create(id: "99")
=> #<Car:0x00007f723e801788 auto_id: nil, id: "99">
# ^
# NOTE: Even though car has been saved, `auto_id` is still `nil`
# but only in `car` object. Because we have overridden
# `id`, primary key is read from `id` column and then `id`
# attribute is set in `id=`. `auto_id` is bypassed.

>> Car.last
=> #<Car:0x00007f774d9e8dd0 auto_id: 1, id: "99">

# NOTE: Other methods are broken whenever `id` is used

>> Car.last.to_key
=> ["99"]
>> Car.last.to_gid
=> #<GlobalID:0x00007f774f4def68 @uri=#<URI::GID gid://stackoverflow/Car/99>>

A better way is to not touch id methods:

class Car < ApplicationRecord
self.primary_key = "auto_id"

def id_attribute= value
_write_attribute("id", value)
end

def id_attribute
_read_attribute("id")
end
end
>> car = Car.create(id_attribute: "99")
=> #<Car:0x00007fb1e44d9458 auto_id: 2, id: "99">

>> car.id_attribute
=> "99"
>> car.id
=> 2
>> car.auto_id
=> 2

Overriding primary key column in Rails 4 and SQLite

OK, I've found the solution for myself: execute each SQL statement independently:

execute "DROP TABLE requests;"
execute "CREATE TABLE requests (id TEXT NOT NULL PRIMARY KEY, name TEXT);"

EDIT

A more elegant solution to prevent creating the table by hand, specially when the table has many columns and we want to keep it synced with the call to ActiveRecord's create_table method:

#Get from SQLite's master table the SQL statement that creates the table, 
#and that was initially generated by Rails
sql = select_value("SELECT sql FROM sqlite_master WHERE type='table' AND name='requests'")

#Only replace the definition of the 'id' column by adding the PRIMARY KEY
#constraint
sql.gsub!(/"id" [^,]+/, '"id" VARCHAR(255) NOT NULL PRIMARY KEY')

#Delete the original table
drop_table :requests

#Create the table again
execute sql

Rails Migration Create Table Primary Key

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.

Rails 4.2.7 mysql set two custom primary key

Having two primary key in a single table doesn't make sense. If you really have two keys that will always uniquely identify data, you can have a combined key of those two keys, and that combined key will act as a primary key.

Here's is how you can accomplish this in Rails:

class CreateLikes < ActiveRecord::Migration
create_table :likes, id: false do |t|
t.string :ip, limit: 39
t.references :post, index: true, foreign_key: true

t.timestamps null: false
end
execute "ALTER TABLE likes ADD PRIMARY KEY (ip,post_id);"
end

And in your Like model:

class Like < ActiveRecord::Base
self.primary_keys = :ip, :post_id
end

How to change primary key in rails migration file?

You could execute arbitrary SQL in your migration:

execute "ALTER TABLE `products` DROP PRIMARY KEY"

and then add the new column:

add_column :products, :id, :primary_key

See:

Remove Primary Key in MySQL

how to add a primary key to a table in rails

http://thinkwhere.wordpress.com/2009/05/09/adding-a-primary-key-id-to-table-in-rails/

http://api.rubyonrails.org/classes/ActiveRecord/Migration.html



Related Topics



Leave a reply



Submit