Миграция 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 и либо

  1. Не используйте внешние ключи вообще; просто укажите свои каскады в ассоциациях ActiveRecord
  2. Использовать execute метод миграции, как описано в связанном примере выше (и просто убедитесь, что все разные RDBMS поддерживают все, что вы положили в execute методы)
  3. Прекратите использование SQLite в разработке, если вы настаиваете на использовании внешних ключей. В любом случае вы не собираетесь использовать SQLite в производственной среде, и уже используете более качественную RDMS (MySQL, "лучше" в том смысле, что она имеет поддержку внешнего ключа, которую вы ищете) на других машинах.

Как вы указали в комментариях, в SQLite отсутствует поддержка добавления внешних ключей после создания таблицы; они не могут быть добавлены путем дальнейшей миграции в Rails. Я лично предлагаю вам использовать вариант 1 или 3, так как будет сложнее создать решение с помощью execute команды в миграциях, которые удовлетворяют ограничениям SQLite и имеют тот же конечный результат в других RDMS'.

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