0

この問題を追跡するのに本当に苦労しました。何が問題なのかはわかりましたが、その理由とバグかどうかはわかりません。

macbuech:iq josh$ ruby -v
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-darwin11.4.0]
macbuech:iq josh$ rails -v
Rails 3.2.1

私はモデルを持ってContacthas_many :addressesます。Address.contact_id機能を壊しているように見えるの存在を検証することを決定するまで、これまでのところすべてが完全にmy_contact.addresses << my_address機能していました! まず第一に、それがどのように機能していたか:

class Address < ActiveRecord::Base
  belongs_to :contact
  validates :contact, :presence => true
  # ...
end

class Contact < ActiveRecord::Base
  has_many :addresses
  # ...
end

Rails コンソールでのテストの出力は次のとおりです。

1.9.3p0 :001 > c = FactoryGirl.create :contact
 => #<Contact id: 71, corporate: false, companyname: nil, firstname: nil, middlename: nil, lastname: "Doe", initials: nil, nickname: nil, gender: "male", title: nil, profession: nil, department: nil, birthday: nil, spouse: nil, kids: nil, superior: nil, assistant: nil, contacttype_id: 71, language_id: nil> 
1.9.3p0 :002 > a = FactoryGirl.create :address
 => #<Address id: 63, active: true, standard: false, street: "Mustergasse 123", extraline1: nil, extraline2: nil, city: "Musterhausen", zip: 8088, province: nil, pobox: nil, latitude: nil, longitude: nil, validfrom: nil, validto: nil, label: nil, description: nil, contact_id: 72, addresstype_id: 63, country_id: 63> 
1.9.3p0 :003 > c.addresses
 => [] 
1.9.3p0 :004 > c.addresses << a
 => [#<Address id: 63, active: true, standard: false, street: "Mustergasse 123", extraline1: nil, extraline2: nil, city: "Musterhausen", zip: 8088, province: nil, pobox: nil, latitude: nil, longitude: nil, validfrom: nil, validto: nil, label: nil, description: nil, contact_id: 71, addresstype_id: 63, country_id: 63>] 
1.9.3p0 :005 > c.addresses
 => [#<Address id: 63, active: true, standard: false, street: "Mustergasse 123", extraline1: nil, extraline2: nil, city: "Musterhausen", zip: 8088, province: nil, pobox: nil, latitude: nil, longitude: nil, validfrom: nil, validto: nil, label: nil, description: nil, contact_id: 71, addresstype_id: 63, country_id: 63>] 
1.9.3p0 :006 > c.save!
 => true 
1.9.3p0 :007 > c.reload
1.9.3p0 :008 > c.addresses
 => [#<Address id: 63, active: true, standard: false, street: "Mustergasse 123", extraline1: nil, extraline2: nil, city: "Musterhausen", zip: "8088", province: nil, pobox: nil, latitude: nil, longitude: nil, validfrom: nil, validto: nil, label: nil, description: nil, contact_id: 71, addresstype_id: 63, country_id: 63>]     

すべてが期待どおりに機能し、Address#63 は Contact#71 に属しています。

次に、belongs_to リレーションシップ名の存在を検証するのはあまり意味がないことをここで読みましたが、その外部キーを検証する必要があるため、次のようにしました。

class Address < ActiveRecord::Base
  belongs_to :contact
  validates :contact_id, :presence => true
  # ...
end

したがって、上記とまったく同じコマンドのRailsコンソールのログは次のとおりです。

1.9.3p0 :009 > c = FactoryGirl.create :contact
 => #<Contact id: 84, corporate: false, companyname: nil, firstname: nil, middlename: nil, lastname: "Doe", initials: nil, nickname: nil, gender: "male", title: nil, profession: nil, department: nil, birthday: nil, spouse: nil, kids: nil, superior: nil, assistant: nil, contacttype_id: 84, language_id: nil> 
1.9.3p0 :010 > a = FactoryGirl.create :address
 => #<Address id: 74, active: true, standard: false, street: "Mustergasse 123", extraline1: nil, extraline2: nil, city: "Musterhausen", zip: 8088, province: nil, pobox: nil, latitude: nil, longitude: nil, validfrom: nil, validto: nil, label: nil, description: nil, contact_id: 85, addresstype_id: 74, country_id: 74> 
1.9.3p0 :011 > c.addresses
 => [] 
1.9.3p0 :012 > c.addresses << a
 => [#<Address id: 74, active: true, standard: false, street: "Mustergasse 123", extraline1: nil, extraline2: nil, city: "Musterhausen", zip: 8088, province: nil, pobox: nil, latitude: nil, longitude: nil, validfrom: nil, validto: nil, label: nil, description: nil, contact_id: 85, addresstype_id: 74, country_id: 74>] 
1.9.3p0 :013 > c.addresses
 => [#<Address id: 74, active: true, standard: false, street: "Mustergasse 123", extraline1: nil, extraline2: nil, city: "Musterhausen", zip: 8088, province: nil, pobox: nil, latitude: nil, longitude: nil, validfrom: nil, validto: nil, label: nil, description: nil, contact_id: 85, addresstype_id: 74, country_id: 74>] 
 => true 
1.9.3p0 :015 > c.reload
 => #<Contact id: 84, corporate: false, companyname: nil, firstname: nil, middlename: nil, lastname: "Doe", initials: nil, nickname: nil, gender: "male", title: nil, profession: nil, department: nil, birthday: nil, spouse: nil, kids: nil, superior: nil, assistant: nil, contacttype_id: 84, language_id: nil> 
1.9.3p0 :016 > c.addresses
 => [] 

ご覧のとおり、アドレスが連絡先に適切に割り当てられていません! :contact_idその後変更する必要がありましたが、85のままでしたc.addresses << a!さらに恐ろしいことに、検証全体を削除して機能しません!

1.9.3p0 :009 > c = FactoryGirl.create :contact
 => #<Contact id: 97, corporate: false, companyname: nil, firstname: nil, middlename: nil, lastname: "Doe", initials: nil, nickname: nil, gender: "male", title: nil, profession: nil, department: nil, birthday: nil, spouse: nil, kids: nil, superior: nil, assistant: nil, contacttype_id: 97, language_id: nil> 
1.9.3p0 :010 > a = FactoryGirl.create :address
 => #<Address id: 85, active: true, standard: false, street: "Mustergasse 123", extraline1: nil, extraline2: nil, city: "Musterhausen", zip: 8088, province: nil, pobox: nil, latitude: nil, longitude: nil, validfrom: nil, validto: nil, label: nil, description: nil, contact_id: 98, addresstype_id: 85, country_id: 85> 
1.9.3p0 :011 > c.addresses
 => [] 
1.9.3p0 :012 > c.addresses << a
 => [#<Address id: 85, active: true, standard: false, street: "Mustergasse 123", extraline1: nil, extraline2: nil, city: "Musterhausen", zip: 8088, province: nil, pobox: nil, latitude: nil, longitude: nil, validfrom: nil, validto: nil, label: nil, description: nil, contact_id: 98, addresstype_id: 85, country_id: 85>] 
1.9.3p0 :013 > c.addresses
 => [#<Address id: 85, active: true, standard: false, street: "Mustergasse 123", extraline1: nil, extraline2: nil, city: "Musterhausen", zip: 8088, province: nil, pobox: nil, latitude: nil, longitude: nil, validfrom: nil, validto: nil, label: nil, description: nil, contact_id: 98, addresstype_id: 85, country_id: 85>] 
1.9.3p0 :014 > c.save!
 => true 
1.9.3p0 :015 > c.reload
 => #<Contact id: 97, corporate: false, companyname: nil, firstname: nil, middlename: nil, lastname: "Doe", initials: nil, nickname: nil, gender: "male", title: nil, profession: nil, department: nil, birthday: nil, spouse: nil, kids: nil, superior: nil, assistant: nil, contacttype_id: 97, language_id: nil> 
1.9.3p0 :016 > c.addresses
 => [] 

繰り返しますが、:contact_id変わらないというまったく同じシナリオ...

どんな助けでも大歓迎です.私はすでにこの問題を調査するために約6時間を無駄にしました...

アップデート

私が尋ねている理由は、RSpec ファイルに次のものが含まれているからです。

let (:contact) do
  contact = create(:contact)
  contact.addresses << create(:address)
  contact
end

前述のように、これは で機能しvalidates :project, :presence => trueますが、検証なしまたは では機能しませんvalidates :project_id, :presence => true

私はこのように書くことができたので、 で動作しますvalidates :project_id, :presence => trueが、それは私が推測する方法ではありません (そして、実際には DRY ではありません)。

let (:contact) do
  contact = create(:contact)
  contact.addresses << create(:address, :contact => contact)
  contact
end
4

1 に答える 1

0

このような状況では、私は常に関連付けによってアドレスを作成します。

c.addresses.create

では、contact_id を検証してこれを行うとどうなるでしょうか?

于 2012-07-09T10:24:13.647 に答える