Как использовать длинный идентификатор в приложениях Rails?
Как изменить тип (по умолчанию) для идентификаторов ActiveRecord? Int не достаточно долго, я бы предпочел долго. Я был удивлен, что нет: долго для миграций - кто-то использует только десятичную дробь?
11 ответов
Кредиты для http://moeffju.net/blog/using-bigint-columns-in-rails-migrations
class CreateDemo < ActiveRecord::Migration
def self.up
create_table :demo, :id => false do |t|
t.integer :id, :limit => 8
end
end
end
- Смотрите опцию
:id => false
который отключает автоматическое создание поля id t.integer :id, :limit => 8
строка выдаст 64-битное целое поле
Чтобы установить тип столбца первичного ключа по умолчанию, файлы миграции не место, чтобы связываться с ними.
Вместо этого, просто вставьте это в нижней части вашего config/environment.rb
ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"
И все ваши таблицы должны быть созданы с предполагаемым типом столбца для id
:
+--------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------------+------+-----+---------+----------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
После того, как вы сделали то, что вы намеревались сделать, следующий вопрос, вероятно, звучит так: "Как мне сделать так, чтобы мои столбцы внешнего ключа были одинаковыми? поскольку не имеет смысла иметь первичный ключ people.id
как bigint(20) unsigned
, а также person_id
быть int(11)
или что-нибудь еще?
Для этих столбцов вы можете обратиться к другим предложениям, например,
t.column :author_id, 'BIGINT UNSIGNED'
t.integer :author_id, :limit => 8
ОБНОВЛЕНИЕ: @Notinlist, чтобы использовать произвольный столбец для первичного ключа в произвольных таблицах, вам нужно сделать create_table-change_column
танец:
create_table(:users) do |t|
# column definitions here..
end
change_column :users, :id, :float # or some other column type
например, если бы я хотел guid
вместо целых чисел с автоинкрементом,
create_table(:users, :primary_key => 'guid') do |t|
# column definitions here..
end
change_column :users, :guid, :string, :limit => 36
Это трудно установить для первичного ключа с миграциями, потому что Rails вставляет его автоматически.
Вы можете изменить любой столбец позже, как это:
change_column :foobars, :something_id, 'bigint'
Вы можете указать неосновные идентификаторы в качестве пользовательских типов при первоначальной миграции следующим образом:
create_table :tweets do |t|
t.column :twitter_id, 'bigint'
t.column :twitter_in_reply_to_status_id, 'bigint'
end
Там, где у меня есть "bigint", вы можете поместить любой текст, который ваша база данных будет использовать для типа столбца базы данных, который вы хотите использовать (например, "unsigned long").
Если вам нужен столбец id для bigint, самый простой способ сделать это - создать таблицу, а затем изменить столбец в той же миграции с помощью change_column.
В PostgreSQL и SQLite изменения схемы являются атомарными, поэтому в случае сбоя миграции ваша база данных не будет находиться в странном состоянии. С MySQL вам нужно быть более осторожным.
Согласно документации Rails API, возможны следующие варианты типа:
:string
:text
:integer
:float
:decimal
:datetime
:timestamp
:time
:date
:binary
:boolean
Вы можете использовать: десятичное, или вы можете выполнить команду напрямую, если вам нужно:
class MyMigration
def self.up
execute "ALTER TABLE my_table ADD id LONG"
end
end
Как указывалось в wappos, вы можете использовать вспомогательные параметры, такие как: limit, чтобы указать ActiveRecord, насколько большим должен быть столбец. Таким образом, вы бы использовали столбец: int с большим значением:limit.
Если кому-то это нужно для работы с PostgreSQL, создайте инициализатор следующим образом:
# config/initializers/bigint_primary_keys.rb
ActiveRecord::Base.establish_connection
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:primary_key] = 'bigserial primary key'
Из-за ленивой загрузки в Rails 3.2 (и, возможно, даже в более ранних версиях), ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
не потребуется, пока вы не установите соединение с базой данных.
В rails4
, ты можешь это сделать.
Ниже приведен пример создания Dummy
модель в 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
Что он сделал:
- Это использовать
serial8
как тип идентификатора, который является 64-битным целым числом, и определить его какprimary key
, - Это использовать
timestamptz
как тип datetime, который содержит информацию о часовом поясе, это важно для приложения, работающего в нескольких часовых поясах.
Заимствование из других решений, с учетом того, что работало для меня в последнее время.
Добавить в файл в config/initializers
, Он объявляет новый тип столбца (адаптировано по предложению chookeat).
ActiveRecord::ConnectionAdapters::Mysql2Adapter::NATIVE_DATABASE_TYPES[:long_primary_key] = "BIGINT(20) DEFAULT NULL auto_increment PRIMARY KEY"
Миграции, которые используют длинный идентификатор, таковы:
create_table :notification_logs, :id => false do |t|
t.column :id, :long_primary_key
# ...
end
Rails 3, MySQL:
t.column :foobar, :int, :limit => 8
Не дает мне bigint, только int. Тем не мение,
t.column :twitter_id, 'bigint'
работает отлично. (Хотя это связывает меня с MySQL.)
Вы можете сделать это так:
class CreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users, id: :bigserial do |t|
t.string :name
end
end
end
Я написал гем под названием https://github.com/garysweaver/activerecord-native_db_types_override, который позволяет вам изменять типы данных, которые будут использоваться в ваших миграциях.
В вашем Gemfile добавьте:
gem 'activerecord-native_db_types_override'
затем в config/environment.rb, чтобы использовать длинные идентификаторы в postgres, добавьте:
NativeDbTypesOverride.configure({
postgres: {
primary_key: { name: "bigserial primary key"}
}
})
Смотрите его README для получения актуальной информации.
Исправление к тому, как изменить значение по умолчанию primary key
тип столбца:
Вместо:
ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"
ты должен сделать:
ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT(8) UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"
иначе вы не сможете добавить foreign key
ограничения на уровне базы данных.