Подтвердить что ты не робот

Почему миграция Rails определяет внешние ключи в приложении, но не в базе данных?

Если я определяю модель Customer и Order, в которой a Customer "имеет много" Orders, а Order "принадлежит" Customer, в Rails мы говорим о Order имея внешний ключ от Customer до customer_id, но мы не имеем в виду, что это применяется в базе данных.

Поскольку Rails не определяет это как ограничение на уровне базы данных, существует риск нарушения целостности данных, возможно, вне приложения (или внутри, если вы получаете одновременные запросы?), если только вы не применяете ограничение в базе данных вручную.

Почему Rails не определяет внешний ключ на уровне базы данных или есть способ получить Rails для этого?

class Customer < ActiveRecord::Base
  has_many :orders
end

class Order < ActiveRecord::Base
    belongs_to :customer
end

ActiveRecord::Schema.define(:version => 1) do

  create_table "customers", :force => true do |t|
    t.string   "name"
  end

  create_table "orders", :force => true do |t|
    t.string   "item_name"
    t.integer  "customer_id"
  end

end
4b9b3361

Ответ 1

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

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

В принципе, соглашения Rails обрабатывали базу данных как статическое устройство хранения данных, а не активную СУБД. Rails 2.0, наконец, поддерживает некоторые более реалистичные возможности баз данных SQL. Неудивительно, что результатом будет то, что разработка с Rails станет более сложной, чем в версии 1.0.

Ответ 2

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

Проверки и проверки уровня приложений доступны для простых, быстрых, понятных для человека (думаю, сообщений об ошибках), которые работают в 99,99% случаев. Если ваше приложение требует более того, вы должны использовать ограничения уровня базы данных.

Я думаю, что эта "философия" возникла из-за используемых исходных систем тестирования: внешние ключи просто оказались гигантскими проблемами при использовании светильников. Это похоже на то, что "ошибка" становится "функцией", потому что никто ее не исправляет. (Если я забываю историю, кто-то меня исправляет.)

Как минимум, в сообществе Rails растет движение, чтобы обеспечить целостность с базой данных. Просмотрите этот пост в блоге из прошлого месяца. Она даже ссылается на некоторые плагины, которые помогают поддерживать обработку ошибок (и другое сообщение в блоге, которое ссылается на большее количество плагинов). Сделайте еще несколько поисковых запросов Google; Я видел другие плагины, которые добавляют поддержку миграции для создания внешних ключей.

Теперь, что является частью основной концепции Rails: не беспокойтесь о вещах, если вам на самом деле не нужно. Для многих веб-приложений, вероятно, хорошо, если небольшой (возможно, крошечный) процент записей содержит недопустимые данные. Страницы, которые могут быть затронуты, могут быть очень редко просмотрены, или ошибка может быть обработана изящно уже. Или, может быть, он дешевле (как в случае с холодными наличными деньгами), чтобы обрабатывать проблемы вручную в течение следующих 6 месяцев по мере того, как приложение растет, чем тратить время на разработку ресурсов для каждого случая. В принципе, если ваши прецеденты не кажутся важными, и это действительно может быть вызвано только условием гонки, которое может случиться с запросами 1/10000000... ну, стоит ли это?

Итак, мое предсказание заключается в том, что инструменты будут spring до тех пор, пока по умолчанию не удастся справиться со всей ситуацией, и в итоге они будут объединены в Rails 3. В то же время, если ваше приложение действительно нуждается в нем, добавьте их. Это вызовет легкую головную боль, но ничего не получится с помощью mocks и stub. И если ваше приложение действительно не нуждается в этом... ну, вы уже все хорошо.:)

Ответ 3

После многих десятилетий в отрасли я твердо верю, что хороший дизайн базы данных сохранит приложение из многих проблем, особенно когда оно претерпевает улучшения. Если известно, что конкретное ограничение будет поддерживать целостность базы данных даже после проскальзывания программного обеспечения (я уверен, что я не единственный, кто это сделал), тогда он обязательно должен применяться к базе данных, если это возможно. Поэтому я призывал бы людей использовать внешние ключи, когда это было возможно. Я также хотел бы рассмотреть возможность использования тестов для обеспечения целостности данных. Ибо мы все знаем о законе мурфи.

Ответ 4

Одна ошибка, которую делают многие люди, - это запутывающие миграции с моделью. Миграции просто изменяют базу данных и не имеют ничего общего с моделями, которые вы определили. В результате этой путаницы многие плагины с внешним ключом пытаются объединить модель с миграциями и сделать слишком много магических вещей.

Для миграции я бы использовал http://github.com/matthuhiggins/foreigner/tree/master. Вам не нужно менять свои модели, чтобы заставить внешние ключи работать с Rails.

Ответ 5

Он создает столбец customer_id (очевидно). По большей части Rails верит в принуждение ограничений и валидации на уровне приложений, а не на уровне базы данных; почему столбцы по умолчанию в Rails могут содержать значения NULL, даже если у вас есть validates_presence_of или что-то в этом роде. Представление разработчиков Rails заключается в том, что такие ограничения должны обрабатываться приложением, а не базой данных.