rails 3 has_many通过has_one

时间:2012-09-26 16:24:25

标签: ruby-on-rails activerecord has-many-through

假设您有以下型号:

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

令人惊讶的是,当我调用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

上述查询忽略了Category#current_heat的has_one性质。我原本期待的更像是:

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

仅当您使用Category.first.current_heat.scores显式遍历根目录中的has_one关联时才会生成。

好像ActiveRecord正在默默地将我的has_one视为has_many。有人可以向我解释这种行为吗?是否有优雅的解决方法或“正确的方法”来做到这一点?

2 个答案:

答案 0 :(得分:5)

也许你可以删除

has_many :scores, :through => :current_heat

而只是通过has_one:

委派:得分
delegate :scores, :to => :current_heat

将保留您所需的访问方法Category.first.scores。

答案 1 :(得分:0)

has_one并不存在以这种方式照顾您的数据库。如果有多个记录与foreign_key匹配,它不会抛出错误,它只会选择第一个。它假设您没有错误地添加额外的记录,这些记录会破坏has_one关系。

总之,只要只有一个记录附加到类别,它生成的sql就可以了。如果你以某种方式添加了不应该存在的额外记录,因为它是has_one,那么它将不起作用,但是它不是activerecord的工作,告诉你这已经发生了。