简体   繁体   English

Rails和PSQL:如何使用回退值将STRING类型的列转换为UUID

[英]Rails & PSQL: how to convert a column of type STRING to UUID with a fallback value

I'm using an extension called 'pgcrypto' to add a support for UUIDs. 我正在使用名为'pgcrypto'的扩展来添加对UUID的支持。

Currently I have a column called creator_id of type string but I want to change its type to UUID. 目前我有一个名为creator_id的列类型为string,但我想将其类型更改为UUID。

At first I tried: 起初我尝试过:

change_column :communities, :creator_id, :uuid

And I got this: 我得到了这个:

PG::DatatypeMismatch: ERROR:  column "creator_id" cannot be cast automatically to type uuid
HINT:  You might need to specify "USING creator_id::uuid".

So I tried: 所以我尝试过:

change_column :communities, :creator_id, "uuid USING creator_id::uuid"

The problem is, during early stages of development it was filled with placeholder values that don't even look like a UUID, so I'm getting the following error: 问题是,在开发的早期阶段,它充满了占位符值甚至看起来不像UUID,所以我收到以下错误:

PG::InvalidTextRepresentation: ERROR:  invalid input syntax for type uuid

So I want to fallback to some default UUID when such an exception is raised. 所以我想在引发这样的异常时回退到某个默认的UUID。 How do I achieve that? 我如何实现这一目标?

First, create a migration with uuid-ossp and pgcrypto 首先,使用uuid-ossppgcrypto创建迁移

class EnableUuidExtension < ActiveRecord::Migration[5.2]
      def change
        enable_extension 'uuid-ossp'
        enable_extension 'pgcrypto'
      end
    end

Then, create another migration to convert id into uuid . 然后,创建另一个迁移以将id转换为uuid For instance, 例如,

class ChangeIdToUuidInUser < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :uuid, :uuid, default: 'uuid_generate_v4()', null: false
    change_table :users do |t|
      t.remove :id
      t.rename :uuid, :id
    end
    execute 'ALTER TABLE users ADD PRIMARY KEY (id);'
  end
end

After then open postgres database with this command psql -U username databaseName You will enter in postgres shell, run following command 然后使用此命令打开postgres数据库psql -U username databaseName您将在postgres shell中输入,运行以下命令

=# CREATE EXTENSION pgcrypto;
=# \q

Finally, run rails db:migrate 最后,运行rails db:migrate

This is what I ended up doing: 这就是我最终做的事情:

class UpdateCreatorIdInCommunities < ActiveRecord::Migration[5.1]
    def up
        execute "CREATE OR REPLACE FUNCTION string_to_uuid(text, uuid) RETURNS uuid AS $$
        BEGIN
          RETURN $1::uuid;
        EXCEPTION
          WHEN invalid_text_representation THEN
            RETURN $2;
        END;
        $$ language plpgsql immutable;"
        last_user_created = User.order(:created_at).last
        user_id = last_user_created ? quote(last_user_created.id) : "NULL"
        change_column :communities, :creator_id, "uuid USING string_to_uuid(\"creator_id\", #{user_id})"
    end

    def down
        change_column :communities, :creator_id, :string
    end
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM