127
127

Reputation: 113

Rails fails creating migration with NOW() default value to Postgres

Common way I use it is

psql > ALTER TABLE transactions ALTER COLUMN date SET DEFAULT CURRENT_TIMESTAMP\g

it works fine.

In my RoR app I've tried to create migrations in two ways.

1.

class TransactionsSetDefaultDateChange < ActiveRecord::Migration
  change_column :transactions, :date, :datetime, :null=>false, :default=>'CURRENT_TIMESTAMP'
end

2.

class TransactionsSetDefaultDateChange < ActiveRecord::Migration
 execute <<-SQL
    ALTER TABLE transactions ALTER COLUMN date SET DEFAULT CURRENT_TIMESTAMP
 SQL
end

Both failed. Any ideas why?

PS this case works with migration ("rake db:migrate") but is not applied correctly on "rake db:setup" (loses SQL statement)

class TransactionsSetDefaultDateChange < ActiveRecord::Migration
 def change
 execute <<-SQL
    ALTER TABLE transactions ALTER COLUMN date SET DEFAULT CURRENT_TIMESTAMP
 SQL
 end
end

Upvotes: 8

Views: 7337

Answers (4)

derrek
derrek

Reputation: 335

For Rails 5+ this works now

... null: false, default: -> { 'NOW()' } ...

Produces something like this in Postgresql Modifiers

not null default now()

Upvotes: 13

builder
builder

Reputation: 251

Your question and answers here got me going. With Rails 4.2.4 and Postgres 9.3, the following migration code worked for me:

    create_table :goodies do |t|
      t.datetime :last_read_at, null: false
    end
    execute "ALTER TABLE goodies ALTER COLUMN last_read_at SET DEFAULT CURRENT_TIMESTAMP"

It produced a piece of working SQL:

    last_read_at timestamp without time zone NOT NULL DEFAULT now(),

Upvotes: 9

naaano
naaano

Reputation: 21

a correct/clean/neat way to achieve this is with this migration:

class TransactionsSetDefaultDateChange < ActiveRecord::Migration
  change_column :transactions, :date, :datetime, :null=>false, :default=>'now()'
end

Therefore, you have:

  • a standard migration, no specific sql commands which raise IrreversibleMigration.
  • the standard postgresql way of setting current timestamps with timezone
  • no need for triggers/filters at application level: Look at the output of Transaction.new.date
  • works with other RDBMS like mysql

Upvotes: -7

127
127

Reputation: 113

Of course we can do it in postgres. Check out my example with current_timestamp. It creates column with "default NOW()". Strange that rails AR does not support such a core feature. But it's not the point. The solution is to fix model this way

before_create :record_date 
protected 
def record_date 
    self.date = read_attribute(:date) || Time.now 
end 

So, thank you!

Upvotes: 2

Related Questions