On Tue, Oct 11, 2011 at 12:23 PM, Nikhil Goyal <[email protected]>wrote:

> I have user model and referral model. Referral model has user_id as
> field.
>
> Now when a new user is created, I need to call referral#create as well
> and pass it the id of the newly generated user to user_id of referral
> model. How can I do that.
>

I would suggest to not setting the user_id field in the referral object
manually in your code, but use the built-in mechanisms for:
* building the objects first in memory
* saving the object with its associated objects in one "atomic" save.

If you set

<pre>
class User < ActiveRecord::Base
  has_many :referrals
end
</pre>

You can do this:

<pre>
 $ rails c
Loading development environment (Rails 3.1.1.rc1)
001:0> u = User.new(:name => "Peter")
=> #<User id: nil, name: "Peter", created_at: nil, updated_at: nil>
002:0> r1 = u.referrals.build(:comment => "sailor")
=> #<Referral id: nil, user_id: nil, comment: "sailor", created_at: nil,
updated_at: nil>
003:0> r2 = u.referrals.build(:comment => "developer")
=> #<Referral id: nil, user_id: nil, comment: "developer", created_at: nil,
updated_at: nil>
004:0> u.save
   (0.4ms)  BEGIN
  SQL (77.3ms)  INSERT INTO "users" ("created_at", "name", "updated_at")
VALUES ($1, $2, $3) RETURNING "id"  [["created_at", Tue, 11 Oct 2011
10:56:14 UTC +00:00], ["name", "Peter"], ["updated_at", Tue, 11 Oct 2011
10:56:14 UTC +00:00]]
  SQL (1.0ms)  INSERT INTO "referrals" ("comment", "created_at",
"updated_at", "user_id") VALUES ($1, $2, $3, $4) RETURNING "id"
 [["comment", "sailor"], ["created_at", Tue, 11 Oct 2011 10:56:14 UTC
+00:00], ["updated_at", Tue, 11 Oct 2011 10:56:14 UTC +00:00], ["user_id",
2]]
  SQL (0.4ms)  INSERT INTO "referrals" ("comment", "created_at",
"updated_at", "user_id") VALUES ($1, $2, $3, $4) RETURNING "id"
 [["comment", "developer"], ["created_at", Tue, 11 Oct 2011 10:56:14 UTC
+00:00], ["updated_at", Tue, 11 Oct 2011 10:56:14 UTC +00:00], ["user_id",
2]]
   (0.9ms)  COMMIT
=> true
005:0> u
=> #<User id: 2, name: "Peter", created_at: "2011-10-11 10:56:14",
updated_at: "2011-10-11 10:56:14">
006:0> r1
=> #<Referral id: 2, user_id: 2, comment: "sailor", created_at: "2011-10-11
10:56:14", updated_at: "2011-10-11 10:56:14">
007:0> r2
=> #<Referral id: 3, user_id: 2, comment: "developer", created_at:
"2011-10-11 10:56:14", updated_at: "2011-10-11 10:56:14">
</pre>

The magic is that you can add multiple referrals to the user in memory
(without ever writing to
the database), and when you are fully done with preparing the user and
the referrals, you do
one "atomic" save which will write all object to database (or none if it
fails !).

To demonstrate that, I added to the referrals model a validation:

<pre>
 validates :comment,  :presence => true
</pre>

And make the validation fail:

<pre>
$ rails c
Loading development environment (Rails 3.1.1.rc1)
001:0> u2 = User.new(:name => "Jan")
=> #<User id: nil, name: "Jan", created_at: nil, updated_at: nil>
002:0> r1 = u2.referrals.build(:comment => "wanderer")
=> #<Referral id: nil, user_id: nil, comment: "wanderer", created_at: nil,
updated_at: nil>
003:0> r2 = u2.referrals.build ### no comment here !
=> #<Referral id: nil, user_id: nil, comment: nil, created_at: nil,
updated_at: nil>
004:0> u2.save
   (0.4ms)  BEGIN
   (0.4ms)  ROLLBACK
=> false
005:0> User.find_by_name("Jan")
  User Load (1.9ms)  SELECT "users".* FROM "users" WHERE "users"."name" =
'Jan' LIMIT 1
=> nil
</pre>

As you can see, nothing got saved, because I tried all saves in one "atomic"
save.

HTH,

Peter

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en.

Reply via email to