В первой версии вашего кода вы загружаете тот же ряд проигрывателей таблиц, но, хотя вы ожидаете, что рельсы будут достаточно умными, чтобы признать, что он уже загрузил этот ряд в память, рельсы не работают таким образом.Поэтому, когда вы выдаете + = 2 на игрока, он делает + + 2 на другом экземпляре, чем тот, на котором вы сделали - = 1.
Я настроил небольшой пример, чтобы показать, что естьтоже экземпляр той же строки:
ruby-1.8.7-p174 > p_instance_1 = Player.first
=> #<Player id: 1, actions: -1, created_at: "2010-10-13 17:07:22", updated_at: "2010-10-13 17:11:00">
ruby-1.8.7-p174 > c = Card.first
=> #<Card id: 1, player_id: 1, created_at: "2010-10-13 17:07:28", updated_at: "2010-10-13 17:07:28">
ruby-1.8.7-p174 > p_instance_2 = c.player
=> #<Player id: 1, actions: -1, created_at: "2010-10-13 17:07:22", updated_at: "2010-10-13 17:11:00">
ruby-1.8.7-p174 > p_instance_1.object_id
=> 2158703080
ruby-1.8.7-p174 > p_instance_2.object_id
=> 2156926840
ruby-1.8.7-p174 > p_instance_1.actions += 1
=> 0
ruby-1.8.7-p174 > p_instance_2.actions += 1
=> 0
Итак, наконец, поскольку вы не сохранили экземпляр с примененным + = 2, есть только один с сохраненным -1,
ОБНОВЛЕНИЕ
Вы можете попытаться обмануть рельсы, чтобы полностью использовать один и тот же экземпляр игрока.Это немного уродливо, но это работает.
class Player < 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 < ActiveRecord::Base
belongs_to :player
def play
player.actions += 2
end
end
, поэтому, когда вы вводите эти команды:
ruby-1.8.7-p174 > p = Player.first
=> #<Player id: 1, actions: 0, created_at: "2010-10-14 13:33:51", updated_at: "2010-10-14 13:33:51">
ruby-1.8.7-p174 > p.play_card(Card.first)
=> true
ruby-1.8.7-p174 > p
=> #<Player id: 1, actions: 0, created_at: "2010-10-14 13:33:51", updated_at: "2010-10-14 13:33:51">
ruby-1.8.7-p174 > p.reload
=> #<Player id: 1, actions: 1, created_at: "2010-10-14 13:33:51", updated_at: "2010-10-14 13:34:40">
У вас есть правильное количество действий в плеере и на карточке логов.загружается только один раз:
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
Подводя итог, я бы сказал, что в вашем дизайне кода что-то не так.Если я хорошо понимаю, то вам хотелось бы, чтобы каждый экземпляр AR строки таблицы был одним и тем же объектом в ObjectSpace, но я предполагаю, что если бы рельсы создавались таким образом, это привело бы к странному поведению, при котором вы могли бы работать с измененным объектом на половинув валидациях и других хуках.