35

a が「多く」、 が「に属する」モデルCustomerを定義する場合、Rails ではスルーへの外部キーを持つことについて話しますが、これがデータベースで強制されるという意味ではありません。OrderCustomerOrdersOrderCustomerOrderCustomercustomer_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
4

5 に答える 5

22

Rails には、データベースではなくアプリケーションでデータの整合性を強制するという規則がいくつかあります。

たとえば、Rails は、ポリモーフィック アソシエーションなど、外部キーを使用できない一部のデータベース設計もサポートしています。

基本的に、Rails の規則では、データベースをアクティブな RDBMS ではなく、静的なデータ ストレージ デバイスとして扱ってきました。Rails 2.0 は、SQL データベースのより現実的な機能をついにサポートします。その結果、Rails を使用した開発がバージョン 1.0 よりも複雑になることは驚くことではありません。

于 2009-05-29T22:40:34.080 に答える
13

この問題にしばらく取り組んだ後、外部キーがデータベースによって強制されるべきではないというのは、Rails の核となる哲学の一部ではないと思います。

アプリケーション レベルの検証とチェックは、99.99% の確率で機能する、簡単、迅速、人間が判読できる (エラー メッセージを考えてください) チェックを提供するためにあります。アプリケーションがそれ以上を必要とする場合は、データベース レベルの制約を使用する必要があります。

この「哲学」は、元のテスト フレームワークが使用されたために進化したと思います。外部キーは、フィクスチャを使用するときに非常に面倒であることが証明されました。誰も修正しないために「バグ」が「機能」になるようなものです。(歴史の記憶が間違っている場合は、誰かが訂正してください。)

少なくとも、Rails コミュニティ内では、データベースとの整合性を強化する動きが高まっています。 先月のこちらのブログ記事をご覧ください。 彼女は、エラー処理のサポートを提供するのに役立ついくつかのプラグインへのリンクも示しています (さらに別のプラグインへのリンクを掲載した別のブログ記事も参照してください)。さらにいくつかの Google 検索を行います。移行のサポートを追加して外部キーを作成する他のプラグインも見ました。

さて、 Rails の核となる哲学の一部次のとおりです。実際に必要でない限り、心配する必要はありません。多くの Web アプリケーションでは、レコードのごく一部 (おそらく非常に小さい) に無効なデータが含まれていても問題ありません。影響を受ける可能性のあるページが表示されることはほとんどないか、またはエラーがすでに適切に処理されている可能性があります。または、アプリケーションが成長するにつれて、次の 6 か月間は手動で問題を処理する方が、すべての不測の事態に備えて開発リソースを計画するよりも安価です (現金のように)。基本的に、あなたのユースケースがそれをすべて重要に思わせず、実際には1/10000000リクエストが発生する可能性のある競合状態によってのみ引き起こされる可能性がある場合...まあ、それだけの価値はありますか?

したがって、私の予測では、デフォルトで状況全体をより適切に処理するツールが出現し、最終的には Rails 3 にマージされるでしょう。それまでの間、アプリが本当に必要な場合は追加してください。テストで少し頭が痛くなるかもしれませんが、モックやスタブを使えば何も問題はありません。そして、あなたのアプリが本当にそれを必要としないなら... まあ、あなたはもう大丈夫です. :)

于 2009-05-30T01:15:05.843 に答える
6

業界で何十年も働いてきた私は、優れたデータベース設計によってアプリケーションが多くの問題から救われると固く信じています。特定の制約がプログラミングの誤りの後でもデータベースの整合性を維持することがわかっている場合 (そうするのは私だけではないと確信しています)、可能な場合は必ずそれをデータベースに適用する必要があります。そのため、可能な限り外部キーを使用することをお勧めします。また、テストを使用してデータの完全性を提供することも検討します。私たちは皆、マーフィーの法則について知っています。

于 2011-03-23T17:32:19.763 に答える
4

多くの人が犯す間違いの 1 つは、移行とモデルを混同することです。移行は単にデータベースを変更するだけで、定義したモデルとは何の関係もありません。この混乱の結果、多くの外部キー プラグインは、モデルと移行を組み合わせて、あまりにも多くの魔法のようなことをしようとします。

移行には、http://github.com/matthhiggins/foreigner/tree/masterを使用します。Rails で動作する外部キーを取得するためにモデルを変更する必要はありません。

于 2009-09-04T00:31:52.777 に答える
2

列を作成しcustomer_idます(明らかに)。ただし、ほとんどの場合、Rails は、データベース レベルではなく、アプリケーションレベルで制約と検証を強制することを信じています。そのため、デフォルトでは、Rails の列には、またはそのようなものNULLがある場合でも、値が含まれる場合がありますvalidates_presence_of。Rails の開発者は、このような制約はデータベースではなくアプリケーションで処理する必要があると考えています。

于 2009-05-29T22:37:23.057 に答える