0

Whenever a User object is created, I want a UserInfo object to be created too, and linked to it.

Unfortunately this does not create any UserInfo:

class User < ActiveRecord::Base
  has_one :user_info
  ...

  def init
    self.user_info = user_info
    self.save!
  end

Why is the init method not called? How to reach my goal?

Nicolas Raoul
  • 58,567
  • 58
  • 222
  • 373

3 Answers3

1

sombe's technique is right, but his details aren't ideal. In fact, since create_user_info is already a method on User instances, all you want is something like:

class User < ActiveRecord::Base
  has_one :user_info
  before_create :create_user_info
end

Edit: init doesn't do anything particularly magical under Rails (I... don't think it does under basic Ruby either - are you thinking of initialize? I'll assume you are). initialize is fired off when an instance of the Ruby class is created in memory. That's divorced by quite some margin from an instance of the model being created in the database; a new class instance could be due to you calling build (and not saving yet), or even due to reading an instance out of the database.

If you want to step in on database operations, you need to make use of the ActiveRecord callbacks. You might find my answer to this question useful.

Community
  • 1
  • 1
Chowlett
  • 45,935
  • 20
  • 116
  • 150
1

before_save callback triggers on create and update. I'd suggest to use after_create because before_create can return errors

class User < ActiveRecord::Base
  has_one :user_info
  ...

  after_create do
    create_user_info
end
Anatoly
  • 15,298
  • 5
  • 53
  • 77
  • That's true, before_create could return errors. In which case you have to ask; Do I want to create a User even if the UserInfo creation fails (use after_create), or do I want to fail the whole User creation in that case (use before_create)? – Chowlett Jul 19 '11 at 08:11
  • actually I'd doing such tasks another way. In controller **@user.valid? && @user_info.valid? && @user.save**. Another way is to use **acceptence_nested_attributes** – Anatoly Jul 19 '11 at 08:17
0

In your User model, use a before_save filter instead of init like this:

before_save :create_user_info

...

private

def create_user_info 
   user_info = UserInfo.new
   if user_info.save
       self.user_info_id = user_info.id
   end
end
Gal
  • 23,122
  • 32
  • 97
  • 118