Como usar long id em aplicações Rails?
-
21-08-2019 - |
Pergunta
Como posso mudar o tipo (padrão) para IDs de ActiveRecord? int não é suficientemente longo, eu preferiria muito tempo. Fiquei surpreso que não existe:? Muito tempo para as migrações - é que uma pessoa apenas usar alguns decimal
Solução
Créditos para http://moeffju.net/blog/using- bigint-colunas-in-rails-migrações
class CreateDemo < ActiveRecord::Migration
def self.up
create_table :demo, :id => false do |t|
t.integer :id, :limit => 8
end
end
end
- Veja a
:id => false
opção que desativa a criação automática do campo id - A linha de
t.integer :id, :limit => 8
irá produzir um campo inteiro de 64 bit
Outras dicas
Para definir o Padrão tipo de coluna de chave primária , os arquivos de migração não são o lugar para mexer com.
Em vez disso, apenas manter isso no fundo de sua config/environment.rb
ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"
E todas as suas tabelas deve ser criado com o tipo de coluna destina-se a id
:
+--------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------------+------+-----+---------+----------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
Depois de ter feito o que você se propôs a fazer ... a próxima pergunta é, provavelmente, "Como posso fazer minha colunas de chave do mesmo tipo de coluna externa?" uma vez que não faz sentido ter people.id
chave primária como bigint(20) unsigned
e person_id
ser int(11)
ou qualquer outra coisa?
Para essas colunas, você pode consultar as outras sugestões, por exemplo.
t.column :author_id, 'BIGINT UNSIGNED'
t.integer :author_id, :limit => 8
Atualizar : @Notinlist, para usar coluna arbitrário para chave primária nas tabelas arbitrárias que você precisa fazer a dança create_table-change_column
:
create_table(:users) do |t|
# column definitions here..
end
change_column :users, :id, :float # or some other column type
por exemplo. se eu queria guid
em vez de números inteiros auto-incremento,
create_table(:users, :primary_key => 'guid') do |t|
# column definitions here..
end
change_column :users, :guid, :string, :limit => 36
Isso é difícil de definir para a chave primária com as migrações porque Rails coloca automaticamente.
Você pode alterar qualquer coluna mais tarde como esta:
change_column :foobars, :something_id, 'bigint'
Você pode especificar IDs não-primárias como tipos personalizados na sua migração inicial como esta:
create_table :tweets do |t|
t.column :twitter_id, 'bigint'
t.column :twitter_in_reply_to_status_id, 'bigint'
end
Onde eu tenho "bigint", você pode colocar qualquer texto que seu banco de dados usaria para o tipo de coluna de banco de dados que deseja usar (por exemplo, "unsigned long").
Se você precisa de sua coluna id ser um bigint, a maneira mais fácil de fazer isso seria a de criar a tabela, em seguida, altere a coluna na mesma migração com change_column.
Com PostgreSQL e SQLite, alterações de esquema são atômicas para que isso não vai deixar seu banco de dados em um estado estranho se a migração falhar. Com o MySQL você precisa ser mais cuidadoso.
De acordo com a documentação da API do Rails, as opções possíveis para o tipo são:
:string
:text
:integer
:float
:decimal
:datetime
:timestamp
:time
:date
:binary
:boolean
Você pode usar: decimal, ou você pode executar um comando diretamente se você precisa:
class MyMigration
def self.up
execute "ALTER TABLE my_table ADD id LONG"
end
end
Como wappos apontou, você pode usar opções auxiliares como: limite para dizer ActiveRecord como grande você deseja que a coluna seja. Então, você usaria o: coluna int com um maior:. Limite
Se alguém precisa desse ao trabalho com PostgreSQL, criar um inicializador assim:
# config/initializers/bigint_primary_keys.rb
ActiveRecord::Base.establish_connection
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:primary_key] = 'bigserial primary key'
Por causa de carregamento lento no Rails 3.2 (e versões talvez até antes), ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
não serão necessários até que você estabelecer a conexão banco de dados.
Em rails4
, você pode fazê-lo.
A seguir é um exemplo para criar um modelo Dummy
em rails4
& postgres
,
xxx_migrate_dummies.rb:
class CreateDummies < ActiveRecord::Migration
def change
create_table :dummies, :id => false do |t|
t.column :id, :serial8, primary_key: true
t.string :name, :limit => 50, null: false
t.integer :size, null: false
t.column :create_date, :timestamptz, null: false
end
end
end
O que ele fez:
- usar
serial8
como tipo ID, que é de 64 bits número inteiro, e definem comoprimary key
. - usar
timestamptz
como datetime tipo, que contêm a informação de fuso horário, isso é importante para uma aplicação que atravessar vários fusos horários.
Rails 3, MySQL:
t.column :foobar, :int, :limit => 8
não me dá um bigint apenas um int. No entanto,
t.column :twitter_id, 'bigint'
funciona bem. (Embora não me amarrar ao MySQL.)
O empréstimo de outras soluções, ajustadas para o que funcionou para mim recentemente.
Adicionar a um arquivo em config/initializers
. Ele declara um novo tipo de coluna (adaptado de sugestão de chookeat).
ActiveRecord::ConnectionAdapters::Mysql2Adapter::NATIVE_DATABASE_TYPES[:long_primary_key] = "BIGINT(20) DEFAULT NULL auto_increment PRIMARY KEY"
As migrações que usam uma longa id são como tal:
create_table :notification_logs, :id => false do |t|
t.column :id, :long_primary_key
# ...
end
Eu escrevi uma jóia chamado activerecord-native_db_types_override que lhe permite alterar os tipos de dados que serão usados em suas migrações.
Em seu Gemfile, adicione:
gem 'activerecord-native_db_types_override'
, em seguida, no config / environment.rb, para usar ids longos no Postgres, adicione:
NativeDbTypesOverride.configure({
postgres: {
primary_key: { name: "bigserial primary key"}
}
})
Veja a sua README para up-to-date informações.
Você pode fazê-lo como este:
class CreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users, id: :bigserial do |t|
t.string :name
end
end
end
Correção de como alterar o tipo de coluna primary key
padrão:
Em vez de:
ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"
você deve fazer:
ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT(8) UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"
ou então você não será capaz de adicionar restrições foreign key
na camada de banco de dados.