この問題を追跡するのに本当に苦労しました。何が問題なのかはわかりましたが、その理由とバグかどうかはわかりません。
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
私はモデルを持ってContact
いhas_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