Closed threewordphrase closed 9 years ago
Interesting. More-or-less what you're asking is the point of this library: to provide binary UUIDs under an integer id compatible interface.
Could you post here what errors you're seeing? We've tried as best we can to confirm to the "normal" ActiveRecord conventions to make this possible.
I created a DB migration to convert the ID column to UUID, included ActiveUUID::UUID in my model, restarted webrick and then tried to load a record with an old ID (in this case, 82). Relevant lines from Rails log:
Parameters: {"utf8"=>"✓", "show"=>{"id"=>"82"}, "id"=>"presentation_report"}
Show Load (0.5ms) SELECT shows
.* FROM shows
WHERE shows
.id
= x'00000000000000000000000000003832' LIMIT 1
Completed 404 Not Found in 98ms (ActiveRecord: 7.2ms)
ActiveRecord::RecordNotFound (Couldn't find Show with 'id'=82):
My migration was just this one liner:
change_column :shows, :id, :uuid
IDs were appearing in their integer form when looking at the table in Sequel Pro. Perhaps I missed an installation step?
I haven't looked at this closely, but I don't think that a UUID conversion will keep your old IDs. E.g. in that request above, I don't think you'll be able to look up {"id" => "82"}
and have that map to the UUID you're expecting.
You might want to try keeping your id
column as an integer and then create an additional uuid
column. Then re-save each record (which will create a uuid for each one) and then use the uuid column in that way.
@crypticsymbols Look at using for_each
in your migration, which will load in batches of records at about ~1000 at a time but without running out of memory. For each one, you can just replace the existing id with a randomly generated ID from running SecureRandom.uuid
.
Well, the trouble is we need to keep the old integer IDs. We can certainly re-save each record, but it doesn't seem to want to take an integer value. After the migration:
2.2.1 :012 > s.id
=> #
Honestly I wasn't really expecting that to work ;). I also tried creating a new UUID column, setting that to an integer on a test, and then querying where uuid = 82 - but still no dice. Do I need to cast or convert it somehow?
Unless there's something obvious I'm missing, I don't want to take up too much time. We can deal with the performance hit of using string PKs.
Yes, what you're missing is that you can't store an integer in a uuid field. So, it sounds like you'll be best off adding a new column, generating uuids for that column, and then changing your primary key to be the uuid column.
Ah, gotcha. I misinterpreted the first comment about backwards compatibility. Thanks guys!
So the problem is that integer ids and binary ids aren't really interchangeable in that sort of "straightforward" way. You can keep your integer ids and uuids by doing the following:
id
s as integers (e.g. how you had it before you started using activeuuid
uuid
column, and make the uuid
column the binary uuid.If you do this, you'll be able to find by id in your old way and then also find by uuid using the new uuids.
In the past, I've even gone so far as to patch .find
to auto-detect whether it's an integer id or uuid and then automatically pick the right finder. (I think early versions of this plugin had that. But it isn't 100% reliable so something like that isn't in core.)
Backstory: We have an app that uses a bunch of serialization to store relationships. Converting the entire DB to UUIDs is kind of a non-starter if we can find a way around it. We are moving to UUIDs to support multi-master replication of new records, so we are hoping to maintain support of our old integer IDs.
I just tried a test install of this gem and it (predictably) breaks the old integer IDs. Is there a workaround to make preexisting integer IDs backward compatible, or are we stuck with a string-based strategy?