Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>In the first version of your code you are loading the same row of the table players but while you are expecting rails to be smart enough to recognize that it has already load this row in memory, rails doesn't work that way. So when you are issuing a +=2 on player it does he +=2 on another instance than the one on which you have done -=1.</p> <p>i've setup a little example to show that there are too instance of the same row:</p> <pre><code>ruby-1.8.7-p174 &gt; p_instance_1 = Player.first =&gt; #&lt;Player id: 1, actions: -1, created_at: "2010-10-13 17:07:22", updated_at: "2010-10-13 17:11:00"&gt; ruby-1.8.7-p174 &gt; c = Card.first =&gt; #&lt;Card id: 1, player_id: 1, created_at: "2010-10-13 17:07:28", updated_at: "2010-10-13 17:07:28"&gt; ruby-1.8.7-p174 &gt; p_instance_2 = c.player =&gt; #&lt;Player id: 1, actions: -1, created_at: "2010-10-13 17:07:22", updated_at: "2010-10-13 17:11:00"&gt; ruby-1.8.7-p174 &gt; p_instance_1.object_id =&gt; 2158703080 ruby-1.8.7-p174 &gt; p_instance_2.object_id =&gt; 2156926840 ruby-1.8.7-p174 &gt; p_instance_1.actions += 1 =&gt; 0 ruby-1.8.7-p174 &gt; p_instance_2.actions += 1 =&gt; 0 </code></pre> <p>So finally as you haven't save the instance with the +=2 applied, there's only the one with the -1 that is saved</p> <p>UPDATE</p> <p>You can try to trick rails to use the same instance of player all the way. This is a little bit ugly but it works.</p> <pre><code>class Player &lt; ActiveRecord::Base has_many :cards def play_card(card) raise "Not yours!" unless cards.include? card new_self = card.player card.play new_self.actions -= 1 new_self.save! end end class Card &lt; ActiveRecord::Base belongs_to :player def play player.actions += 2 end end </code></pre> <p>so when you input those commands:</p> <pre><code>ruby-1.8.7-p174 &gt; p = Player.first =&gt; #&lt;Player id: 1, actions: 0, created_at: "2010-10-14 13:33:51", updated_at: "2010-10-14 13:33:51"&gt; ruby-1.8.7-p174 &gt; p.play_card(Card.first) =&gt; true ruby-1.8.7-p174 &gt; p =&gt; #&lt;Player id: 1, actions: 0, created_at: "2010-10-14 13:33:51", updated_at: "2010-10-14 13:33:51"&gt; ruby-1.8.7-p174 &gt; p.reload =&gt; #&lt;Player id: 1, actions: 1, created_at: "2010-10-14 13:33:51", updated_at: "2010-10-14 13:34:40"&gt; </code></pre> <p>You have the right number of actions in player, and in the logs card is only loaded once:</p> <pre><code> Player Load (0.5ms) SELECT * FROM "players" LIMIT 1 Card Load (0.2ms) SELECT * FROM "cards" LIMIT 1 Card Load (0.2ms) SELECT "cards".id FROM "cards" WHERE ("cards"."id" = 1) AND ("cards".player_id = 1) LIMIT 1 Player Load (0.1ms) SELECT * FROM "players" WHERE ("players"."id" = 1) Player Update (0.6ms) UPDATE "players" SET "updated_at" = '2010-10-14 13:34:40', "actions" = 1 WHERE "id" = 1 </code></pre> <p>To sum up the whole thing, I would say that there's something wrong in your code design. If i understand well,what you would like is that every AR instance of a table row is the same object in the ObjectSpace, but I guess that if rails was build that way it would introduce strange behaviors where you could work on half backed object changed in validations and other hooks.</p>
    singulars
    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.
 

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