简体   繁体   English

Rails 3 has_many至has_one

[英]rails 3 has_many through has_one

Suppose you have the following models: 假设您具有以下模型:

class Category < ActiveRecord::Base
  has_one :current_heat, class_name: 'Heat'
  has_many :scores, :through => :current_heat
end

class Heat < ActiveRecord::Base
  belongs_to :category
  has_many :scores
end

class Score < ActiveRecord::Base  
  belongs_to :heat
end

Surprisingly, when I invoke Category.first.scores ActiveRecord produces the following queries: 令人惊讶的是,当我调用Category.first.scores ActiveRecord会产生以下查询:

SELECT `categories`.* FROM `categories` LIMIT 1
SELECT * FROM `scores` INNER JOIN `heats` ON `scores`.`heat_id` = `heats`.`id` WHERE `heats`.`category_id` = 1

The above query ignores the has_one nature of Category#current_heat . 上面的查询忽略了Category#current_heat的has_one性质。 I would have expected something more like: 我本来期望更像:

SELECT `categories`.* FROM `categories` LIMIT 1
SELECT `heats`.* FROM `heats` WHERE `heats`.`category_id` = 1 LIMIT 1
SELECT * FROM `scores` WHERE `scores`.`heat_id` = 6

which is produced only when you explicitly traverse the has_one association from the root with Category.first.current_heat.scores . 仅当您使用Category.first.current_heat.scores从根显式遍历has_one关联时,才会生成该代码。

It's as if ActiveRecord is silently treating my has_one as a has_many. 就像ActiveRecord默默地将我的has_one视为has_many一样。 Can someone explain this behavior to me? 有人可以向我解释这种行为吗? Is there an elegant workaround or a "right way" to do it? 是否有优雅的解决方法或“正确的方法”来做到这一点?

Maybe you could remove the 也许您可以删除

has_many :scores, :through => :current_heat

and instead just delegate :scores through the has_one: 而是通过has_one委托:scores:

delegate :scores, :to => :current_heat

that would preserve your desired access method Category.first.scores. 这将保留您所需的访问方法Category.first.scores。

has_one doesn't really exist to babysit your database in this fashion. has_one确实不存在以这种方式来照料数据库。 It won't throw errors if there is more than one record that matches the foreign_key, it will just choose the first one. 如果有多个记录与foreign_key匹配,它不会抛出错误,它只会选择第一个。 It assumes you haven't errantly added extra records which would break the has_one relation on your own. 假定您没有错误地添加额外的记录,这些记录会自行破坏has_one关系。

In conclusion, the sql that it generates is fine as long as there is only one record attached to the Category. 总之,只要类别中仅附加一条记录,它生成的sql就可以了。 If somehow you've added extra records which shouldn't exist since it is a has_one , then it won't work, but it's not the job of activerecord to tell you that this has happened. 如果您以某种方式添加了额外的记录(由于它是has_one而不应该存在),那么它将不起作用,但是告诉您这已经发生不是activerecord的工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM