Миграция SQLite удаляет add_index и add_foreign_key из файла schema.rb
Я использую SQLite3 и MySQL в одном проекте Rails, но на двух разных компьютерах. Я заметил, что schema.rb
который генерируется при запуске всех миграций, выглядит по-разному для обеих сред. Когда я запускаю миграции в среде SQLite3, следующие операторы удаляются из schema.rb
файл.
add_index "places", ["user_id"], :name => "places_user_id_fk"
add_foreign_key "places", "users", :name => "places_user_id_fk"
Пожалуйста, обратите внимание, что я использую драгоценный камень иностранца, который продлевает миграцию с add_foreign_key
а также remove_foreign_key
,
Вот миграции и модель, имеющие отношение к проблеме:
# 20130123004056_create_places.rb
class CreatePlaces < ActiveRecord::Migration
def change
create_table :places do |t|
t.string :name
t.string :location
t.integer :user_id
t.timestamps
end
end
end
...
# 20130123234250_add_foreign_key.rb
class AddForeignKey < ActiveRecord::Migration
def change
add_foreign_key(:places, :users)
end
end
...
# user.rb
class User < ActiveRecord::Base
has_many :places
end
...
# place.rb
class Place < ActiveRecord::Base
belongs_to :user
end
Вопрос: Как я могу определить отношения между users
а также places
таким образом, SQLite3 и MySQL могут справиться с этим?
1 ответ
foreigner
README четко заявляет
Поддерживаются следующие адаптеры:
- sqlite (методы с внешним ключом не допускаются)
Таким образом, ваша база данных SQLite не имеет ограничений внешнего ключа, потому что foreigner
не поддерживает их. когда db/schema.rb
генерируется из базы данных SQLite, поэтому внешние ключи не указаны.
Руководство по миграции на Rails довольно часто упоминает внешние ключи
Если вам нужно выполнить задачи, специфичные для вашей базы данных (например, создать ограничение внешнего ключа), тогда
execute
метод позволяет выполнить произвольный SQL
Есть даже пример того, как добавить / удалить внешний ключ.
Использовав foreigner
когда вы впервые начинаете с Rails, я предлагаю вам удалить его из вашего Gemfile
и либо
- Не используйте внешние ключи вообще; просто укажите свои каскады в ассоциациях ActiveRecord
- Использовать
execute
метод миграции, как описано в связанном примере выше (и просто убедитесь, что все разные RDBMS поддерживают все, что вы положили вexecute
методы) - Прекратите использование SQLite в разработке, если вы настаиваете на использовании внешних ключей. В любом случае вы не собираетесь использовать SQLite в производственной среде, и уже используете более качественную RDMS (MySQL, "лучше" в том смысле, что она имеет поддержку внешнего ключа, которую вы ищете) на других машинах.
Как вы указали в комментариях, в SQLite отсутствует поддержка добавления внешних ключей после создания таблицы; они не могут быть добавлены путем дальнейшей миграции в Rails. Я лично предлагаю вам использовать вариант 1 или 3, так как будет сложнее создать решение с помощью execute
команды в миграциях, которые удовлетворяют ограничениям SQLite и имеют тот же конечный результат в других RDMS'.