3

示例场景:模型 Workerbelongs_to模型 Bucket。

请参阅以下查询:

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>

正如您所看到的,在where函数的情况下,传递一个实例,例如Bucket.first作品来代替确切的id. 所以有人会认为它也适用于该new功能。相反,它默默地失败了!

为什么它会这样工作?

4

3 回答 3

3

我相信这发生在ActiveRecord::PredicateBuilder中。如果该值是一个 ActiveRecord::Base 对象,您可以在那里看到它会调用id它。该new方法不会触发此代码,因此它的行为会有所不同。

我更喜欢明确并id直接传递。然而,在 Rails 4 中,您将能够做到这一点:

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

这与初始化非常相似:

Worker.new(bucket: Bucket.first)

一般来说,我建议传递一个id如果您正在设置/匹配的属性以_id.

更新:我还想指出,初始化将继承where条件。所以这将在 Rails 3.2 中工作:

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

我假设最终会通过 PredicateBuilder,但不确定。即使这有效,我也不推荐它。

于 2013-01-24T19:45:40.993 回答
0

据我了解,Bucket.first将返回一个即时对象,但Bucket.first.id只会返回即时对象的 id。

因此,另一方面,当您创建Worker.new和传递时bucket_id: Bucket.first,它实际上不起作用,

Worker.new bucket_id: Bucket.first.id 

它将传递正确的参数以创建新的 Worker。

于 2013-01-24T03:20:40.997 回答
0

当您使用时,.new您正在创建一个空白记录,但它还没有 ID。对于 Active Record,这经常用于表单。

这与 say .createwhich 不同,如果给定所需的有效参数,将创建带有 ID 的记录。类似地,选择Bucket.first具有 ID 的记录将获得具有 ID 的现有记录。

如果您使用.new,请设置所需的参数,然后执行 a.save您将获得一个 ID。

于 2013-01-24T03:36:04.973 回答