Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Unfortunately, I've determined it's not possible to do it without using <code>execute</code>.</p> <h2>Why it doesn't work</h2> <p>By examining the ActiveRecord source, we can find the code for <code>create_table</code>:</p> <p>In <a href="http://github.com/rails/rails/blob/5a7d31913bb16977ec85d55de34ac0d79b512d62/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb#L161" rel="nofollow noreferrer"><code>schema_statements.rb</code></a>:</p> <pre><code>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 </code></pre> <p>So we can see that when you try to specify a primary key in the <code>create_table</code> options, it creates a primary key with that specified name (or, if none is specified, <code>id</code>). It does this by calling the same method you can use inside a table definition block: <code>primary_key</code>.</p> <p>In <a href="https://github.com/rails/rails/blob/a63f7a136401b59db52fb802180f6c9793d83bc2/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb#L89" rel="nofollow noreferrer"><code>schema_statements.rb</code></a>:</p> <pre><code>def primary_key(name) column(name, :primary_key) end </code></pre> <p>This just creates a column with the specified name of type <code>:primary_key</code>. This is set to the following in the standard database adapters:</p> <pre><code>PostgreSQL: "serial primary key" MySQL: "int(11) DEFAULT NULL auto_increment PRIMARY KEY" SQLite: "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL" </code></pre> <h2>The workaround</h2> <p>Since we're stuck with these as the primary key types, we have to use <code>execute</code> to create a primary key that is not an integer (PostgreSQL's <code>serial</code> is an integer using a sequence):</p> <pre><code>create_table :employees, {:id =&gt; 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);" </code></pre> <p>And as <a href="https://stackoverflow.com/questions/1200568/using-rails-how-can-i-set-my-primary-key-to-not-be-an-integer-typed-column/1429146#1429146">Sean McCleary mentioned</a>, your ActiveRecord model should set the primary key using <code>set_primary_key</code>:</p> <pre><code>class Employee &lt; ActiveRecord::Base set_primary_key :emp_id ... end </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload