Note that there are some explanatory texts on larger screens.

plurals
  1. PO"Contact has_many :addresses" does work when checking presence of :contact, within Address, but not with :contact_id (and without validation)
    primarykey
    data
    text
    <p>I really had a hard time tracking this problem down, and now I know what's going wrong, but don't know why, and whether it's a bug or not.</p> <pre><code>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 </code></pre> <p>I have a model <code>Contact</code> which <code>has_many :addresses</code>. Everything worked perfectly so far, until I decided to validate presence of <code>Address.contact_id</code>, which seems to break the <code>my_contact.addresses &lt;&lt; my_address</code> functionality! First of all how it used to work:</p> <pre><code>class Address &lt; ActiveRecord::Base belongs_to :contact validates :contact, :presence =&gt; true # ... end class Contact &lt; ActiveRecord::Base has_many :addresses # ... end </code></pre> <p>Here's the output of a test in the Rails console:</p> <pre><code>1.9.3p0 :001 &gt; c = FactoryGirl.create :contact =&gt; #&lt;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&gt; 1.9.3p0 :002 &gt; a = FactoryGirl.create :address =&gt; #&lt;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&gt; 1.9.3p0 :003 &gt; c.addresses =&gt; [] 1.9.3p0 :004 &gt; c.addresses &lt;&lt; a =&gt; [#&lt;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&gt;] 1.9.3p0 :005 &gt; c.addresses =&gt; [#&lt;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&gt;] 1.9.3p0 :006 &gt; c.save! =&gt; true 1.9.3p0 :007 &gt; c.reload 1.9.3p0 :008 &gt; c.addresses =&gt; [#&lt;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&gt;] </code></pre> <p>Everything works as expected, the Address#63 now belongs to Contact#71.</p> <p>I then read <a href="https://stackoverflow.com/a/11327575/1439143">here</a> that it doesn't make much sense to validate the presence of the belongs_to relationship name, but that I should validate its foreign key, and so I did:</p> <pre><code>class Address &lt; ActiveRecord::Base belongs_to :contact validates :contact_id, :presence =&gt; true # ... end </code></pre> <p>So here's the Rails console's log for exactly the same commands like above:</p> <pre><code>1.9.3p0 :009 &gt; c = FactoryGirl.create :contact =&gt; #&lt;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&gt; 1.9.3p0 :010 &gt; a = FactoryGirl.create :address =&gt; #&lt;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&gt; 1.9.3p0 :011 &gt; c.addresses =&gt; [] 1.9.3p0 :012 &gt; c.addresses &lt;&lt; a =&gt; [#&lt;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&gt;] 1.9.3p0 :013 &gt; c.addresses =&gt; [#&lt;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&gt;] =&gt; true 1.9.3p0 :015 &gt; c.reload =&gt; #&lt;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&gt; 1.9.3p0 :016 &gt; c.addresses =&gt; [] </code></pre> <p>As you can see, the address wasn't properly assigned to the contact! Its <code>:contact_id</code> stayed 85 although it should have changed after <code>c.addresses &lt;&lt; a</code>! Even scarier, when I remove the whole validation, it <strong>also</strong> doesn't work!</p> <pre><code>1.9.3p0 :009 &gt; c = FactoryGirl.create :contact =&gt; #&lt;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&gt; 1.9.3p0 :010 &gt; a = FactoryGirl.create :address =&gt; #&lt;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&gt; 1.9.3p0 :011 &gt; c.addresses =&gt; [] 1.9.3p0 :012 &gt; c.addresses &lt;&lt; a =&gt; [#&lt;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&gt;] 1.9.3p0 :013 &gt; c.addresses =&gt; [#&lt;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&gt;] 1.9.3p0 :014 &gt; c.save! =&gt; true 1.9.3p0 :015 &gt; c.reload =&gt; #&lt;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&gt; 1.9.3p0 :016 &gt; c.addresses =&gt; [] </code></pre> <p>Again, the very same scenario that the <code>:contact_id</code> does not change...</p> <p>Any help is highly appreciated, I've wasted about 6 hours already investigating this problem...</p> <p><strong>Update</strong></p> <p>The reason why I'm asking is that I have the following in an RSpec file:</p> <pre><code>let (:contact) do contact = create(:contact) contact.addresses &lt;&lt; create(:address) contact end </code></pre> <p>As said, this works with <code>validates :project, :presence =&gt; true</code>, but it doesn't without any validation or with <code>validates :project_id, :presence =&gt; true</code>.</p> <p>I could write it like this, so it works with <code>validates :project_id, :presence =&gt; true</code>, but it's just not how I guess it should behave (and it's not really DRY).</p> <pre><code>let (:contact) do contact = create(:contact) contact.addresses &lt;&lt; create(:address, :contact =&gt; contact) contact end </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload