generate a model with a string field as primary key
No, you can't. By default the primary key is an auto-increment integer.
However, you can open the migration that was generated from the command, and change it (before running the rake db:migrate
command). The migration will likely have a create_table
command:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
# ...
end
end
end
If you read the create_table
documentation, you will notice you can pass two options. Specifically, you need to set :id
to false
to not generate an id
field, and you will need to specify the name of the primary key field.
create_table :users, id: false, primary_key: :email do |t|
How to add primary key to Rails?
In your migration file:
create_table :bookmarks, :primary_key => :bk_id do |t|
...
t.integer :bk_id
...
end
Do not forget to indicate it in your Model too:
class Bookmarks < ActiveRecord::Base
self.primary_key = 'bk_id'
end
ActiveRecord string primary key used in foreign keys
You can specify the primary key on a join. For example:
class Order < ActiveRecord::Base
belongs_to :system_currency, :primary_key => "iso_code"
end
More information can be found in the Rails API at http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-belongs_to
Is this what you are after or have I misunderstood your question?
Using Rails, how can I set my primary key to not be an integer-typed column?
Unfortunately, I've determined it's not possible to do it without using execute
.
Why it doesn't work
By examining the ActiveRecord source, we can find the code for create_table
:
In schema_statements.rb
:
def create_table(table_name, options={})
...
table_definition.primary_key(options[:primary_key] || Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
...
end
So we can see that when you try to specify a primary key in the create_table
options, it creates a primary key with that specified name (or, if none is specified, id
). It does this by calling the same method you can use inside a table definition block: primary_key
.
In schema_statements.rb
:
def primary_key(name)
column(name, :primary_key)
end
This just creates a column with the specified name of type :primary_key
. This is set to the following in the standard database adapters:
PostgreSQL: "serial primary key"
MySQL: "int(11) DEFAULT NULL auto_increment PRIMARY KEY"
SQLite: "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL"
The workaround
Since we're stuck with these as the primary key types, we have to use execute
to create a primary key that is not an integer (PostgreSQL's serial
is an integer using a sequence):
create_table :employees, {:id => false} do |t|
t.string :emp_id
t.string :first_name
t.string :last_name
end
execute "ALTER TABLE employees ADD PRIMARY KEY (emp_id);"
And as Sean McCleary mentioned, your ActiveRecord model should set the primary key using set_primary_key
:
class Employee < ActiveRecord::Base
set_primary_key :emp_id
...
end
Related Topics
Find Out If Current Time Is Between Two Times
To_D to Always Return 2 Decimals Places in Ruby
How to Get the Current Absolute Url in Ruby on Rails
How to Reload the Current Page in Ruby on Rails
Validation for Non-Negative Integers and Decimal Values
How to Convert a Bigdecimal to a 2-Decimal-Place String
Case Statement With Multiple Values in Each 'When' Block
Cannot Load Such File - Zlib Even After Using Rvm Pkg Install Zlib
Is Ruby Pass by Reference or by Value
Why Do Ruby Setters Need "Self." Qualification Within the Class
How to Dynamically Create a Local Variable
Understanding the Rails Authenticity Token
How to Understand Nil Vs. Empty Vs. Blank in Ruby
Difference Between "And" and && in Ruby