2011-01-22 6 views
12

Я пишу сценарий миграции для создания таблицы с столбцом первичного ключа с именем guid и является VARCHAR(25). Проблема в том, что я чувствую, что мне нужно удвоить свои усилия, чтобы достичь того, что должно быть возможно за один шаг.Rails Migration Создать таблицу Первичный ключ

Если я бег:

create_table(:global_feeds, :primary_key => 'guid') do |t| 
    t.string :guid, :limit => 25 
    t.text :title 
    t.text :subtitle 

    ... 

    t.timestamps 
end 

Я получаю таблицу с первичным ключом называется guid не Колонка называется id (что я хочу). Однако проблема заключается в том, что столбец guid - это INT(11) с включенным автоматическим приращением. Так что я должен выполнить одну дополнительную команду:

change_column :global_feeds, :guid, :string, :limit => 25 

кажется немного свернутый придется в основном запустить два SQL команды, чтобы получить то, что я считаю, должно быть возможно в одном.

Любые предложения по оптимизации этого?

ответ

19

Я полагаю, вы используете MySql, так вот что вы можете попробовать

create_table :global_feeds, {:id => false} do |t| 
    t.string :guid 
    t.text :title 
    t.text :subtitle 
    t.timestamps 
end 
execute "ALTER TABLE global_feeds ADD PRIMARY KEY (guid);" 

Если вы не на MySql вы должны изменить запрос в команде execute работать на вашей БД двигателя. Я не уверен, что вы можете сделать это на SQLite. И не забудьте поставить эту строку где-то в global_feed.rb модели:

set_primary_key :guid 

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

+0

К сожалению, это все еще два оператора SQL, подобные моим. Вы только что перевернули порядок операций: сначала вы определяете тип столбца, а затем указываете первичный ключ. – Ryan

+0

Я думаю, вы не можете сделать это за одну операцию, но я думаю, что в этом нет ничего плохого. Это нормально для миграции, чтобы иметь два оператора для более сложных случаев. –

+0

Также я не уверен, что ActiveRecord отлично работает с не целочисленными первичными ключами вообще. –

4

Вам нужно использовать #column вместо #string. Например:

create_table(:global_feeds, :primary_key => 'guid') do |t| 
    t.column :guid, "varchar(25)", :null => false 
    ... 
end 

Обратите внимание, что varchar тип не является переносимым на базы данных, кроме MySQL.

+0

'синтаксическая ошибка, неожиданная '(', ожидая ключевое слово_end t.column: guid,: varchar (26),: null => false' С его помощью указывается скобка в конце varchar – Ryan

+0

Вы правы. Используйте' varchar (25) "' вместо ': varchar (25)'. – JellicleCat

3

Это возможно в Rails 3. попробовать:

def self.up 
    create_table(:signups, :id => false) do |t| 
     t.string :token, :primary => true 

проверить эту сущность для отличного решения для использования UUID, в качестве первичного ключа Col: https://gist.github.com/937739

+2

Не работает для меня на Rails 4 + MySQL – dolzenko

+0

См. ответ от @kakoni –

22

В Rails 4 вы можете сделать;

create_table :global_feeds, id: false do |t| 
    t.string :guid, primary_key: true 
... 
end 
+1

Он отлично работает в рельсах 4! –

+1

Это не должно быть строка, mysql с uuid должен быть двоичным (16) – Seed

+1

Он работает в Rails 5 :-) – Maybe1

0

В Rails 5, для thoes, которые получили проблему ArgumentError: Index name '*' on table '*' already exists когда rails db:setup с миграцией как из @kakoni, следующих работ для меня

create_table(:global_feeds, primary_key: :guid, id: false) do |t| 
    t.string :guid 
... 
end 

Для получения дополнительной информации обратитесь create_table.

Смежные вопросы