rails3 первичный ключ bigint - PullRequest
8 голосов
/ 04 мая 2011

Я бы хотел создать поле первичного ключа с типом bigint (или string или что-то еще, кроме int) под Rails 3.

У меня есть заданная структура данных, например:

things
------
id bigint primary_key
name char(32)

Подход, который я сейчас пытаюсь использовать:

create_table :things, :id => false do |t| # That prevents the creation of (id int) PK
  t.integer :id, :limit => 8 # That makes the column type bigint
  t.string :name, :limit => 32
  t.primary_key :id # This is perfectly ignored :-(
end

Тип столбца будет правильным, но опция первичного ключа не будет присутствовать в sqlite3, и я подозреваю, что это относится и к MySQL.

Ответы [ 5 ]

4 голосов
/ 20 сентября 2012

У меня была такая же проблема. Я думаю, что самый простой способ для стола

accounts 
id bigint primary key 
name char 

есть

create_table :accounts do |t|
t.string :name
end
change_column :accounts, :id , "bigint NOT NULL AUTO_INCREMENT"
3 голосов
/ 30 сентября 2013

Для MySQL вы можете использовать «SERIAL», который является псевдонимом «BIGINT UNSIGNED NOT NULL AUTO_INCREMENT»

class ChangeUserIdToBigint < ActiveRecord::Migration
  def change
    change_column :users, :id, 'SERIAL'
  end
end
3 голосов
/ 04 мая 2011

Если бы я сам не так давно нашел ответ здесь: Используя Rails, как я могу установить свой первичный ключ, чтобы он не был столбцом целого типа?

Вам необходимо установить primary_key: false и затем использовать пользовательский оператор перед выполнением миграции.

РЕДАКТИРОВАТЬ 1: Вам необходимо проверить документы базы данных для точного запроса для выполнения. Он выполняется как обычный оператор SQL и должен быть специфичным для базы данных. Пример в вопросе, на который я ссылался, относится к Postgre SQL. Если вы используете MySQL, возможно, вам придется это изменить.

0 голосов
/ 17 января 2018

Если вы хотите преобразовать все таблицы в Postgres, вам нужно запустить этот код

class ConvertIntToBigint < ActiveRecord::Migration[5.1]
  def up
    query = <<-SQL
      SELECT tablename AS "tablename"
      FROM pg_tables
      WHERE schemaname = 'public';
    SQL
    connection.execute(query).each do |element|
      if column_exists?(element['tablename'], :id, :integer)
        change_table(element['tablename']) {|t| t.change :id, :bigint }
      end
    end
  end

  def down
  end
end
0 голосов
/ 08 января 2015

ответ скалогиру хорошо, но изменение не будет отражено в schema.rb. Таким образом, такие задачи, как db:schema:load и db:test:clone, не будут создавать идентичную структуру БД.

Требуется обходной путь для улучшения db:schema:load и задач db: test: clone rake, как описано здесь: http://www.lshift.net/blog/2013/09/30/changing-the-primary-key-type-in-ruby-on-rails-models/

Вот что я использовал, основываясь на этом обходном пути:

namespace :my_app do
  namespace :db do
    task :after_schema_load_and_db_test_clone => :environment do
    puts 'Changing primary key for :my_table'
    query = 'ALTER TABLE <my_table> CHANGE id id bigint DEFAULT NULL auto_increment'
    ActiveRecord::Base.connection.execute(query)
  end
end


Rake::Task['db:schema:load'].enhance do
  ::Rake::Task['my_app:db:after_schema_load_and_db_test_clone'].invoke
end

Rake::Task['db:test:clone'].enhance do
  ::Rake::Task['my_app:db:after_schema_load_and_db_test_clone'].invoke
end
...