title: Postgres: Default for column (string) cannot be cast automatically to type enum
body: <p>I have a <code>status</code> column in a table that I want to be an enum. Originally I created that field as an integer, thinking that I would use the built in Rails enum functionality. Turns out that requires at least Rails 4.1, but I am using 4.0 and the process of upgrading is going to take some time.</p>
  
  <p>But thinking about how this all works, I realized that I can have <strong>either</strong> an ActiveRecord enum <strong>or</strong> a postgres enum, not both. I thought that in the long term having a more explicit postgres enum would be best. So, I wrote a migration to convert the <code>status</code> column from an integer to an enum.</p>
  
  <pre><code>execute "CREATE TYPE status_options AS ENUM ('pending', 'declined', 'approved');"
  change_column :site_applications, :status, "status_options USING status::status_options"
  </code></pre>
  
  <p>But, I get this error:</p>
  
  <pre><code>PG::CannotCoerce: ERROR:  cannot cast type integer to status_options
  ALTER TABLE "site_applications" ALTER COLUMN "status" TYPE status_options USING status::status_options
  </code></pre>
  
  <p>Everything that I have seen so far in my searchings tells me that <strong>should have worked</strong>, but it doesn't. I thought maybe the problem is that I just can't go from integer to enum. So be it. My solution was to first convert the column to a string and <em>then</em> try to convert it to enum.</p>
  
  <pre><code>change_column :site_applications, :status, :string
  execute "CREATE TYPE status_options AS ENUM ('pending', 'declined', 'approved');"
  change_column :site_applications, :status, "status_options USING status::status_options"
  </code></pre>
  
  <p>And that gives me the following error:</p>
  
  <pre><code>PG::DatatypeMismatch: ERROR:  default for column "status" cannot be cast automatically to type status_options
  ALTER TABLE "site_applications" ALTER COLUMN "status" TYPE status_options USING status::status_options
  </code></pre>
  
  <p>That led me to believe that this had something to do with the default value, so I tried specifying the default in the <code>change_column</code> declaration:</p>
  
  <pre><code>change_column :site_applications, :status, :string, default: "pending"
  </code></pre>
  
  <p>That successfully changes the column to a string with a default of "pending", but <code>change_column</code> fails with the same "default for column" error.</p>
  
  <p>I realize that I could simply drop the column all together and then recreate it exactly how I want, but at this point it's a matter of posterity. Why the heck can't I convert a column from integer or string to enum? Anyone?</p>
  
  <p><strong>UPDATE WITH ACCEPTED ANSWER</strong></p>
  
  <p>Based on Gary's answer down there, this is the migration that worked.</p>
  
  <pre><code>def up
    execute "ALTER TABLE site_applications ALTER status DROP DEFAULT;"
    execute "CREATE TYPE status_options AS ENUM ('pending', 'declined', 'approved');"
    change_column :site_applications, :status, "status_options USING status::status_options", default: "pending"
  end
  
  def down
    change_column :site_applications, :status, :string, default: "pending"
    execute "DROP TYPE status_options;"
  end
  </code></pre>