0

私はこのようなことをする方法を理解しようとしています:

event = Event.new
loc = Location.new
loc.name = "test"
loc.save
event.locations << loc
event.save!

イベントと場所が多対多の関係にある場合。ただし、次のエラーが発生し続けます。

ActiveRecord::RecordInvalid: Validation failed: Event locations is invalid

最初にイベントを保存するとうまくいきますが、作業中のコンテキストではそのオプションがありません。

ここに私のモデルがあります:

class Event < ActiveRecord::Base
  #belongs_to :user
  has_many :event_locations
  has_many :locations, :through => :event_locations

  accepts_nested_attributes_for :locations
end

class EventLocation < ActiveRecord::Base
  belongs_to :event
  belongs_to :location

  validates_presence_of :event
  validates_presence_of :location

  accepts_nested_attributes_for :location
end

class Location < ActiveRecord::Base
  has_many :event_locations
  has_many :events, :through => :event_locations
end

ここで、結合モデル EventLocation の検証がこの問題の原因であることがわかりました。

これは検証しないほうがいいですか?それが行われる別の方法はありますか?

4

1 に答える 1

1

TL;DR

次のいずれかを試してください

class EventLocation < ActiveRecord::Base
  belongs_to :event
  belongs_to :location

  validates_presence_of :event_id
  validates_presence_of :location_id

  accepts_nested_attributes_for :location
end

EventLocationまたは -他に何も必要ない場合- b)

class Event < ActiveRecord::Base
  #belongs_to :user
  has_and_belongs_to_many :locations

  accepts_nested_attributes_for :locations
end

class Location < ActiveRecord::Base
  has_and_belongs_to_many :events
end

どうしたの?

「衝突」モデルでは、問題の原因となるEventLocation両方の存在を検証します。:location:event

なぜこれが起こっているのか、そしてどのように対処するのかを理解するには、まず検証システムがどのように機能し、モデルを:through-collection に追加するとどうなるかを理解する必要があります。

検証

この特定のケースでは、 we validate_presence_ofsomething と that は、その何かを見て、それが存在するかどうかを確認するようにモデルに指示します。

簡略化:

validates_presence_of :something

保存すると、

model.save if model.something.present?

したがって、これは正しいことをチェックする必要があります。

:throughコレクションについて

上記は明らかに期待どおりに機能しないため、次のように推測できます。

event.locations << loc

実際には設定しない

EventLocation.new(location: loc)

したがって、実際に起こる可能性があるのは、Rails が ID を次のように「ただ」設定するということです。

EventLocation.new(location_id: loc.id)

どういう意味ですか?

上記が正しいと仮定すると、関連付けられたオブジェクトの代わりに ID の存在を検証することで、ここでうまくいくかもしれません。

なぜわざわざ?

もちろん、バリデーションは一般的に悪い考えではありませんが、代わりの方法があるかもしれませんhas_and_belongs_to_many。そのメソッドには多くの魔法が詰め込まれており、モデルがアタッチされている必要のないコリジョン テーブルをモデルが処理できるようになっています。

一般的に言えば、ビジネス ロジックや追加データを 2 つのテーブルの競合にアタッチする必要がない場合は実行 (および検証) する代わりに、魔法の組み込み (habtm) を使用して正しいことを行います。手動で。

于 2013-10-29T22:57:57.460 に答える