什么时候传递实例来代替id在Ruby on Rails ActiveRecord中工作



示例场景:模型工作线程belongs_to模型存储桶。

请参阅以下查询:

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功能。相反,它默默地失败了!

为什么它以这种方式工作?

我相信这发生在ActiveRecord::P redicateBuilder中。您可以在那里看到该值是否是它将在其上调用id的 ActiveRecord::Base 对象。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,但不确定。即使这有效,我也不推荐它。

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

这与.create不同,如果给定所需的有效参数,则将创建具有 ID 的记录。 同样,选择具有 Bucket.first 的记录将获取具有 ID 的现有记录。

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

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

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

Worker.new bucket_id: Bucket.first.id 

它将传递正确的参数以创建新的工作线程。

相关内容

  • 没有找到相关文章

最新更新