Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use default sql expression with ActiveRecord?

I'm trying to use default values for a model in rails. The best documented way of doing this that I have seen is using the :default parameter in a migration. However, it looks like this only works for values. I am trying to set a default expression, specifically currval('customers_id_seq'::regclass). I can add the default expression by hand, but I can't figure out how to tell rails to use a default value. How can I use this default when creating model objects?

EDIT Here is a more specific example:

class CreateTestmodels < ActiveRecord::Migration
  def up
    create_table :testmodels do |t|
      t.integer :idxfield, :null=>false
      t.string :datafield
      t.timestamps

    end
    execute("ALTER TABLE testmodels ALTER COLUMN idxfield SET DEFAULT currval('testmodels_id_seq'::regclass)")
  end

  def down
    drop_table :testmodels
  end
end

With this migration, I can run insert into testmodels (datafield) VALUES ('sometestdata');, which will add a row to the table where idxfield defaults to id.

However, if I run Testmodel.create(:datafield=>"testdata") from the rails console, it substitutes null for idxfield and throws an exception.

like image 409
Belly Avatar asked Nov 04 '22 14:11

Belly


2 Answers

For anyone coming across this now, you can use an expression in a default value migration by wrapping it in a lambda: https://github.com/rails/rails/pull/20005

e.g.

create_table :posts do |t|
  t.datetime :published_at, default: -> { 'NOW()' }
end
like image 129
Ibrahim Avatar answered Nov 09 '22 11:11

Ibrahim


Sounds like you're trying to use Postgres sequences, which rails will use in all primary key definitions in migrations.

If you need to add it to non-primary key column then you will need to run an ALTER TABLE outside of the create_table and add it yourself, like

  execute("ALTER TABLE users ADD COLUMN foo INTEGER default nextval('users_id_seq'::regclass)")
like image 28
Cody Caughlan Avatar answered Nov 09 '22 11:11

Cody Caughlan