Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rails migration: postgresql for md5 of random string as default

Rails 3 + postgresql

I want to have a sha of a random string for a default value of a column.

So, in my migration I have:

t.string :uniqueid, default: md5(random()::text)

However i can not get this to actually produce anything, I've used backticks, quotes,etc. From examples that I've seen it seems like that pg function only works in a SELECT statement.

Is that accurate? Any ideas on how I could achieve this?

Thanks

like image 420
cbrulak Avatar asked Mar 01 '13 07:03

cbrulak


2 Answers

Note: You probably want to look at brcebn's answer if you're using a more recent version of Rails.


Rails will try to interpret this:

t.string :uniqueid, default: md5(random()::text)

as Ruby code and :default => md5(...) doesn't mean anything in Ruby. If you quote it, then Rails will think it is a string and make the default value for uniqueid the string 'md5(random()::text)' and that's not going to help.

If you want to use a function call in a column default, you can do the alter table by hand:

connection.execute(%q{
    alter table your_table alter column uniqueid set default md5(random()::text)
})

That will get you the default you want in the database but you might notice that there's no mention of the new default in your schema.rb. If you want a usable schema then you'll have to use an SQL schema instead by putting this in your application.rb:

config.active_record.schema_format = :sql

Then delete your schema.rb and use structure.sql instead. Note that SQL schema dumps were broken until 3.2 and there are schema loading problems in various Rails versions (but you can always psql < structure.sql your way around that). On the upside, SQL schema dumps will keep track of fancy things real foreign keys, check constraints, triggers, ...

BTW, if you really want SHA then you'll want to look at the digest function from pgcrypto.

like image 126
mu is too short Avatar answered Nov 04 '22 23:11

mu is too short


You can also do

t.string :token, default: -> { "md5((random())::text)" }, null: false

Edit : Even if this generates a random string with 32 digits, it does not mean it's unique. I thought so but I just had a unique index error.

like image 38
brcebn Avatar answered Nov 04 '22 22:11

brcebn