title: Rails has_many relationship is weird
body: <p>I'm not sure if anyone has noticed this before because I couldn't find any topic on this issue. But assuming you have a Product model and a Cart model that sets <code>has_many :products</code>. and the Product model sets <code>belongs_to :cart</code>, the weird thing happens when you set a product instance's <code>cart_id</code> (which is the foreign key that refers to the id of the associated cart) to <code>nil</code>. Three things can happen:</p>
  
  <ol>
  <li><p>If you already retrieved the associated cart BEFORE setting the associated product's <code>cart_id</code> to <code>nil</code>, when you destroy that cart instance using its instance method <code>destroy()</code>, the associated product <strong>gets destroyed as well</strong>.</p></li>
  <li><p>If you retrieve the associated cart AFTER setting the associated product's <code>cart_id</code> to <code>nil</code>, when you destroy it using its instance method <code>destroy</code>, the associated product <strong>DOES NOT get destroyed</strong>.</p></li>
  <li><p>If you nullify the <code>cart_id</code> of the associated product and call the CLASS METHOD <code>destroy</code> on  Cart (<code>Cart.destroy(cart_id)</code>), the associated product <strong>DOES NOT get destroyed</strong></p></li>
  </ol>
  
  <p>I'm pretty sure this has sth to do with the implementation of <code>has_many</code>. Probably the state of the relationship gets hardwired to a model instance when you retrieve it. <strong>See the code below:</strong></p>
  
  <p>Here's the sample code I used to test the above (assuming you already have the 2 above-mentioned model tables)</p>
  
  <pre><code>Cart.create   # Assume this one has an id of 1
  Product.create(cart_id: 1)
  cart=Cart.find(1) # Retrieve the cart before
  Product.find(1).update_attribute!(cart_id: nil)
  cart.destroy
  Product.find_by_id(1)   # nil; the associated product was destroyed
  </code></pre>
  
  <hr>
  
  <pre><code>Cart.create # Assume this one has an id of 1
  Product.create(cart_id: 1)
  Product.find(1).update_attribute!(cart_id: nil)
  cart=Cart.find(1) # Retrieve the cart AFTER
  cart.destroy
  Product.find_by_id(1) # [&lt;Product id:1 cart_id:1 ....&gt;], the assoc product WAS NOT destroyed
  </code></pre>
  
  <hr>
  
  <pre><code>Cart.create # Assume this one has an id of 1
  Product.create(cart_id: 1)
  Product.find(1).update_attribute!(cart_id: nil)
  Cart.destroy(1)
  Product.find_by_id(1) # [&lt;Product id:1 cart_id:1 ....&gt;], the assoc product WAS NOT destroyed
  </code></pre>