Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails: Creating child objects

I'm sure this is a very simple question, but I'm just a newbie so...

I have a model, Game, which has_many :piles. Pile, in turn, has_many :cards. I'm able to populate the Piles and Cards at creation of the Game, so my code at present looks something like:

class Game < ActiveRecord::Base
  has_many :piles

  def after_create
    1.upto(4) do |num|
      Pile.new("game_id" => id, "contents" => "c_type_#{num}")
    end
  end
end

class Pile < ActiveRecord::Base
  has_many :cards
  belongs_to :game

  def after_create
    1.upto(10) do |num|
      Card.new("pile_id" => id, "value" => num)
    end
  end
end

class Card < ActiveRecord::Base
  belongs_to :pile
end

Now this is all very well, but it feels wrong to be passing "game_id" => id when ActiveRecord knows that game_id is the foreign key and should refer to the parent game. But if I leave it off, the foreign key ends up unset. Is there a better way to do this?

(For a bonus, probably simpler, question; suppose Game also has_one :monkey. How best do I create the monkey from within the Game model?)

like image 877
Chowlett Avatar asked Jan 10 '10 19:01

Chowlett


1 Answers

Instead of:

Pile.new("game_id" => id, "contents" => "c_type_#{num}")

try:

piles.create("contents" => "c_type_#{num}")

It tries saving the created pile straight away. Or, if you really need that no saving takes place (which is the case with create), you can do:

new_pile = piles.build("contents" => "c_type_#{num}")

Similar for the Pile class and its cards.

As for has_one :monkey, you can do the following (from within a method of Game):

create_monkey("some_attr" => "some_value")
like image 193
mxgrn Avatar answered Oct 21 '22 07:10

mxgrn