When is passing an instance instead of id done in Ruby on Rails ActiveRecord?

Example scenario: Model Worker belongs_to

model bucket.

See the following queries:

1.9.3p194 :045 > Worker.where(bucket_id: Bucket.first).count
   (0.7ms)  SELECT COUNT(*) FROM "workers" WHERE "workers"."bucket_id" = 1
 => 38
1.9.3p194 :046 > Worker.where(bucket_id: Bucket.first.id).count
   (0.7ms)  SELECT COUNT(*) FROM "workers" WHERE "workers"."bucket_id" = 1
 => 38

1.9.3p194 :047 > Worker.new bucket_id: Bucket.first
 => #<Worker id: nil, email: nil, created_at: nil, updated_at: nil, bucket_id: nil>
1.9.3p194 :048 > Worker.new bucket_id: Bucket.first.id
 => #<Worker id: nil, email: nil, created_at: nil, updated_at: nil, bucket_id: 2>

      

As you can see, in the case of a function, where

passing an instance like this Bucket.first

works instead of an exact one id

. So one would think it would work for a function as well new

. Instead, it fails!

Why does it work?

+3


source to share


3 answers


I believe this is happening in ActiveRecord :: PredicateBuilder . You can see if this value is an ActiveRecord :: Base object it calls it id

. The method new

does not run this code, so it will behave differently.

I prefer to be explicit and pass directly to id

. However upcoming in Rails 4 you will be able to do this:

Worker.where(bucket: Bucket.first).count

      

This goes well with initialization:

Worker.new(bucket: Bucket.first)

      



In general, I recommend passing id

in if the attribute you are setting / mapping ends with _id

.

Update: I also wanted to point out, initialization inherits conditions where

. So this will work in Rails 3.2:

Worker.where(bucket_id: Bucket.first).new

      

I am guessing what ultimately happens through PredicateBuilder, but not sure about it. Even though it works, I don't recommend it.

+3


source


From what I understand, Bucket.first

will return an instant object, but Bucket.first.id

will only return the id of the instant object.

So when you build Worker.new

and go through bucket_id: Bucket.first

, on the other hand, it won't work,



Worker.new bucket_id: Bucket.first.id 

      

it will accept the correct parameter to create a new Worker.

0


source


When you use .new

, you create an empty entry, but it doesn't have an ID yet. In Active Record, this is often used for forms.

This is in contrast to say .create

, which, if the required valid parameters are given, will create a record with an id. Likewise, selecting a record with Bucket.first

gets an existing record with an identifier.

If you are using .new

, set the required parameters and then execute .save

and then get the ID.

0


source







All Articles