I'm using Rails migrations to manage a database schema, and I'm creating a simple table where I'd like to use a non-integer value as the primary key (in particular, a string). To abstract away from my problem, let's say there's a table employees
where employees are identified by an alphanumeric string, e.g. "134SNW"
.
I've tried creating the table in a migration like this:
create_table :employees, {:primary_key => :emp_id} do |t|
t.string :emp_id
t.string :first_name
t.string :last_name
end
What this gives me is what seems like it completely ignored the line t.string :emp_id
and went ahead and made it an integer column. Is there some other way to have rails generate the PRIMARY_KEY constraint (I'm using PostgreSQL) for me, without having to write the SQL in an execute
call?
NOTE: I know it's not best to use string columns as primary keys, so please no answers just saying to add an integer primary key. I may add one anyway, but this question is still valid.
I have one way of handling this. The executed SQL is ANSI SQL so it will likely work on most ANSI SQL compliant relational databases. I have tested that this works for MySQL.
Migration:
In your model do this:
In Rails 5 you can do
See create_table documentation.
I have tried it in Rails 4.2. To add your custom primary key, you can write your migration as :
While looking at the documentation of
column(name, type, options = {})
and read the line :I got the above ides as i have shown. Here is the table meta data after running this migration :
And from Rails console :
I know this is an old thread I stumbled across... but I'm kind of shocked no one mentioned DataMapper.
I find if you need to stray out of the ActiveRecord convention, I've found that it is a great alternative. Also its a better approach for legacy and you can support the database "as-is".
Ruby Object Mapper (DataMapper 2) holds a lot of promise and build on AREL principles, too!
It looks like it is possible to do using this approach:
That will make the column widget_id the primary key for the Widget class, then it is up to you to populate the field when objects are created. You should be able to do so using the before create callback.
So something along the lines of
I am on Rails 2.3.5 and my following way works with SQLite3
There is no need for :id => false.