Forum: Ruby on Rails Object isn't being saved when called through association

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Pat M. (Guest)
on 2006-04-10 16:14
(Received via mailing list)
I have three models in this small game I'm working on - the Game,
Players, and Turns.  A Player should be able to rescue another Player
on any given turn.  So it looks like this:

class Game
  has_many :players
  has_many :turns

  def rescue_player(p)
    t = turns.last
    t.rescued = p
    t.save
  end
end

class Turn
  belongs_to :rescued, :foreign_key => 'rescued_id', :class_name =>
'Player'
end

class Player
  belongs_to :game

  def rescue_player(p)
    game.rescue_player p
  end
end


What I'm finding is that if I take a player and do
player.rescue_player p

Then it doesn't actually save the results from the game#rescue_player
method.  But if I call game.rescue_player(p) directly, it does.  I
have no clue what's up, and it's confusing the hell out of me.  Am I
not allowed to access it like this or something?

Pat
Pat M. (Guest)
on 2006-04-10 16:39
(Received via mailing list)
One thing I've found is that the game object in Player#rescue_player
is not the same as the game object in Game#rescue_player.  Here's some
output from a test:

game is #<Game:0x245c36c>
player's game is #<Game:0x24471c4>
game id is 1
player's game id is 1

I think the objects ought to be the same, as the Player is related to
the Game...what's going on?

One last thing, I just tried reloading the game object after calling
player.rescue_player, and it reflected the rescued player..but that
seems like a pretty ugly hack really.  What am I doing wrong?

Pat
Justin F. (Guest)
on 2006-04-14 23:11
(Received via mailing list)
Pat M. wrote:
> the Game...what's going on?
>
> One last thing, I just tried reloading the game object after calling
> player.rescue_player, and it reflected the rescued player..but that
> seems like a pretty ugly hack really.  What am I doing wrong?

Active Record doesn't give you a unique in-memory representation of a
given database record. If you retrieve the same record more than once
you will get multiple instances representing it.

regards

   Justin
Pat M. (Guest)
on 2006-04-15 02:16
(Received via mailing list)
On 4/14/06, Justin F. <removed_email_address@domain.invalid> wrote:
> > I think the objects ought to be the same, as the Player is related to
> regards
>
>    Justin
> _______________________________________________
> Rails mailing list
> removed_email_address@domain.invalid
> http://lists.rubyonrails.org/mailman/listinfo/rails
>

Yeah, that's what I found...so is there any way I can use create the
DSL I want without resorting to lots of reload calls?

Pat
Justin F. (Guest)
on 2006-04-15 04:21
(Received via mailing list)
Pat M. wrote:
> On 4/14/06, Justin F. <removed_email_address@domain.invalid> wrote:

>> Active Record doesn't give you a unique in-memory representation of a
>> given database record. If you retrieve the same record more than once
>> you will get multiple instances representing it.
>
> Yeah, that's what I found...so is there any way I can use create the
> DSL I want without resorting to lots of reload calls?

By DSL do you just mean "domain model"?

I suggest that you code your application based on an understanding of
the limitations of Active Record, and refactor out redundancy. You might
find that you end up with generic code ensuring unique representation of
each entity within a user's session, or you might find that there are
only a few places where you need to guard against duplication.

regards

   Justin
Pat M. (Guest)
on 2006-04-15 04:30
(Received via mailing list)
On 4/14/06, Justin F. <removed_email_address@domain.invalid> wrote:
> By DSL do you just mean "domain model"?
I mean domain specific language.

One player should be able to rescue another player within the game.
Thus it would be really slick to be able to write
player.rescue another_player

That does modify the database as I need to, but it makes testing, as
well as some controller stuff, quite messy.  For example, I want to
display the game details on the page, and rescue the player.

def rescue_player
  @game = .......   # get's the game based on some session info
  player = ..... # again get's player info based on session
  another_player = Player.find params[:id]
  player.rescue another_player
  @game.reload
end

If I don't do @game.reload, the @game object won't accurately reflect
the db.  First of all I just think it's ugly to have to do that, and
secondly it's pretty easy to forget the reload, not know when I need
to call it, etc.

Pat
Justin F. (Guest)
on 2006-04-15 14:06
(Received via mailing list)
Pat M. wrote:
> I mean domain specific language.
>
> One player should be able to rescue another player within the game.
> Thus it would be really slick to be able to write
> player.rescue another_player

OK. To me, that just looks like a feature of the domain model -
straightforward OO, with no metaprogramming required. (Contrast this
with the DSL for associations in Rails: has_many, belongs_to, etc.)
>   @game.reload
> end
>
> If I don't do @game.reload, the @game object won't accurately reflect
> the db.  First of all I just think it's ugly to have to do that, and
> secondly it's pretty easy to forget the reload, not know when I need
> to call it, etc.

 From what you say, the game already contains information about the
players, so if you go to the database without involving the game, and
change anything, the game becomes out of date.

Perhaps you should do all finding of players (etc.) via the game, and
give it responsibility for holding these things uniquely.

regards

   Justin
This topic is locked and can not be replied to.