Как использовать длинный идентификатор в приложениях 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 ограничения на уровне базы данных.

Другие вопросы по тегам