我真的很难追踪这个问题,现在我知道出了什么问题,但不知道为什么,以及它是否是一个错误。
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>]
一切都按预期工作,地址#63 现在属于联系人#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
.
let (:contact) do
contact = create(:contact)
contact.addresses << create(:address, :contact => contact)
contact
end