Usando UUID no Rails 7 com PostgreSQL

xandekk

Alexandre

Posted on December 6, 2022

Usando UUID no Rails 7 com PostgreSQL

Esse post vai ser uma rápida instalação de uuid no rails 7.

Vamos começar criando uma nova aplicação e depois vamos tentar trocar o id padrão para uuid em um projeto existente.

Se você não sabe o que é uuid, eu recomendo esse post.

Índice


Criando um projeto

A nossa aplicação vai usar o PostgreSQL como banco de dado.

rails new uuid_rails -d=postgresql
Enter fullscreen mode Exit fullscreen mode

Para ser capaz de usar uuid no postgresql, tem que ativar a extensão pgcrypto.

Então vamos criar uma migração para isso.

rails g migration enable_uuid
Enter fullscreen mode Exit fullscreen mode

Abra o arquivo db/migrate/enable_uuid.rb e adicione o enable_extension 'pgcrypto', como você pode ver abaixo.

# db/migrate/enable_uuid
class EnableUuid < ActiveRecord::Migration[7.0]
  def change
    enable_extension 'pgcrypto'
  end
end
Enter fullscreen mode Exit fullscreen mode

Uma rápida explicação sobre esse pgcrypto.

Essa extensão permite que nós sejamos capaz de usar função de criptografia e tem uma função chamado gen_random_uuid que ele gera um uuid para gente.

Bem, agora vamos colocar o uuid como chave primária.

Definindo o uuid como chave primária

Vamos criar um generator para evitar o trabalho manual.

Crie um arquivo chamado de generators.rb no config/initializers/ e coloque o código a seguir.

# config/initializers/generators.rb
Rails.application.config.generators do |g|
  g.orm :active_record, primary_key_type: :uuid
end
Enter fullscreen mode Exit fullscreen mode

Agora qualquer modelo criado, vai usar o uuid como chave primária.

Então vamos criar um modelo para ver que está funcionando.

Criando o nosso modelo

Vamos criar um modelo chamado de publicação com título.

rails g model Publicacao titulo
Enter fullscreen mode Exit fullscreen mode

Abra o arquivo db/migrate/create_publicacaos.rb para observar um coisa.

# db/migrate/create_publicacaos.rb
class CreatePublicacaos < ActiveRecord::Migration[7.0]
  def change
    create_table :publicacaos, id: :uuid do |t|
      t.string :titulo

      t.timestamps
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

Podemos ver que ele está passando um argumento chamado id com valor :uuid, Então até aqui, ele fez um trabalho correto.

Agora vamos criar o banco de dados e migrar.

rails db:create db:migrate
Enter fullscreen mode Exit fullscreen mode

Abra o rails console para criar uma nova publicação.

rails console

irb(main):001:0> Publicacao.create(titulo: "Nossa primeira publicação")

  TRANSACTION (0.4ms)  BEGIN
  Publicacao Create (7.0ms)  INSERT INTO "publicacaos" ("titulo", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["titulo", "Nossa primeira publicação"], ["created_at", "2022-12-06 10:43:48.903056"], ["updated_at", "2022-12-06 10:43:48.903056"]]
  TRANSACTION (1.3ms)  COMMIT
=> 
#<Publicacao:0x00007fe438a57340
 id: "fb030e22-5d0d-47d3-a856-cc5a028da2d3",
 titulo: "Nossa primeira publicação",
 created_at: Tue, 06 Dec 2022 10:43:48.903056000 UTC +00:00,
 updated_at: Tue, 06 Dec 2022 10:43:48.903056000 UTC +00:00>

Enter fullscreen mode Exit fullscreen mode

Podemos ver que o id está com formato de uuid, então vamos criar outro para confirmar.

irb(main):002:0> Publicacao.create(titulo: "Nossa segunda publicação")

  TRANSACTION (0.9ms)  BEGIN
  Publicacao Create (0.9ms)  INSERT INTO "publicacaos" ("titulo", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["titulo", "Nossa segunda publicação"], ["created_at", "2022-12-06 10:45:00.606342"], ["updated_at", "2022-12-06 10:45:00.606342"]]
  TRANSACTION (4.0ms)  COMMIT
=> 
#<Publicacao:0x00007fe43a2b6490
 id: "4f539d04-43d4-427a-bcc8-b3fc54f3c3db",
 titulo: "Nossa segunda publicação",
 created_at: Tue, 06 Dec 2022 10:45:00.606342000 UTC +00:00,
 updated_at: Tue, 06 Dec 2022 10:45:00.606342000 UTC +00:00>
Enter fullscreen mode Exit fullscreen mode

De fato, está criando o id como uuid.

Com isso, acabamos aqui, mas agora vamos para aqueles que quer mudar o id padrão para uuid com um projeto existente.

Trocando id padrão para uuid em um projeto existente

Eu recomendo que você crie um backup do seu banco de dados antes de tentar aplicar isso no projeto existente.

Vamos criar um aplicação que use id padrão e depois mudarei ele.

rails new id_para_uuid_rails -d=postgresql

cd id_para_uuid_rails/
rails g model Publicacao titulo
rails db:create db:migrate
Enter fullscreen mode Exit fullscreen mode

Agora vamos criar milhares de publicação.

Vamos para rails console.

rails console

irb(main):001:1> 1000.times do |i|
irb(main):002:1*   Publicacao.create titulo: i
irb(main):003:1> end
...
Enter fullscreen mode Exit fullscreen mode

Pronto nós temos mil publicações e eles estão usando id padrão, agora vamos transformar eles em uuid.

Como eu estou usando PostgreSQL como banco de dado, vamos adicionar a extensão pgcrypto.

Para isso, vamos criar uma migração.

rails g migration enable_uuid
Enter fullscreen mode Exit fullscreen mode

Agora vamos adicionar enable_extension 'pgcrypto' no db/migrate/enable_uuid.

# db/migrate/enable_uuid
class EnableUuid < ActiveRecord::Migration[7.0]
  def change
    enable_extension 'pgcrypto'
  end
end
Enter fullscreen mode Exit fullscreen mode

Agora vamos mudar o id.

Crie uma migração para fazer isso.

rails g migration IdToUUID
Enter fullscreen mode Exit fullscreen mode

E adicione o código abaixo no db/migrate/id_to_uuid.

# db/migrate/id_to_uuid 
class IdToUuid < ActiveRecord::Migration[7.0]
  def change
    add_column :publicacaos, :uuid, :uuid, default: "gen_random_uuid()", null: false

    change_table :publicacaos do |t|
      t.remove :id
      t.rename :uuid, :id
    end

    execute "ALTER TABLE publicacaos ADD PRIMARY KEY (id);"
  end
end
Enter fullscreen mode Exit fullscreen mode

OBS: Se você está mudando em seu projeto, basta trocar a tabela publicacaos para a tabela que você está mudando, e se você quer mudar todos as tabelas, vai tem que copiar e colar, por exemplo:

# db/migrate/id_to_uuid 
class IdToUuid < ActiveRecord::Migration[7.0]
  def change
    add_column :publicacaos, :uuid, :uuid, default: "gen_random_uuid()", null: false
    add_column :comentarios, :uuid, :uuid, default: "gen_random_uuid()", null: false


    change_table :publicacaos do |t|
      t.remove :id
      t.rename :uuid, :id
    end

    change_table :comentarios do |t|
      t.remove :id
      t.rename :uuid, :id
    end

    execute "ALTER TABLE publicacaos ADD PRIMARY KEY (id);"
    execute "ALTER TABLE comentarios ADD PRIMARY KEY (id);"
  end
end
Enter fullscreen mode Exit fullscreen mode

Bem, vamos continuar.

Agora vamos migrar e rodar o rails console para ver se funcionou.

rails db:migrate
...
rails console

irb(main):001:0> Publicacao.first
  Publicacao Load (1.6ms)  SELECT "publicacaos".* FROM "publicacaos" ORDER BY "publicacaos"."id" ASC LIMIT $1  [["LIMIT", 1]]                            
=>                                                                    
#<Publicacao:0x00007f7cd4d96838                                       
 titulo: "299",                                                       
 created_at: Tue, 06 Dec 2022 12:00:24.017099000 UTC +00:00,          
 updated_at: Tue, 06 Dec 2022 12:00:24.017099000 UTC +00:00,          
 id: "002b5dbd-6087-4437-959a-32c06cf96c11"> 
Enter fullscreen mode Exit fullscreen mode

Podemos ver que o id está de fato em uuid, mas vamos ver se todos estão realmente em formato de uuid.

irb(main):002:0> Publicacao.all.all? { |p| p.id.match? /^.{8}-.{4}-.{4}-.{17}$/ }
  Publicacao Load (4.0ms)  SELECT "publicacaos".* FROM "publicacaos"
=> true
Enter fullscreen mode Exit fullscreen mode

Deu true, quer dizer que todos eles estão como uuid.

Com isso, nós acabamos aqui.

Caso tenha dado erro, comente o erro, que tentarei te ajudar.

Bem, então é isso, Tchau!

💖 💪 🙅 🚩
xandekk
Alexandre

Posted on December 6, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Usando UUID no Rails 7 com PostgreSQL
postgres Usando UUID no Rails 7 com PostgreSQL

December 6, 2022