1

我一直在从事一个大量使用模型关联的项目,而且似乎我发现了 has_many 或 has_one through 功能与 :conditions 功能冲突的情况。简而言之,问题在于 through 关联为 has_one through 关系中的中间表创建了表别名。但我不知道如何使该表别名出现在我定义的条件中。如果这很难理解,也许代码会有所帮助:

class Event < ActiveRecord::Base
  has_one :event_intake, :conditions => ['event_intakes.is_draft = 1']
  has_many :product_instances, :through => :event_intake
end

class EventIntake < ActiveRecord::Base
  belongs_to :event
  has_many :product_instances, :conditions => ['is_deleted = ?', '0']
end

class ProductInstance < ActiveRecord::Base
  belongs_to :event_intake
end

这是我得到的 MySQL 查询和错误:

Mysql2::Error: Unknown column 'event_intakes.is_draft' in 'on clause': 

SELECT DISTINCT `events`.id FROM `events` 
  LEFT OUTER JOIN `event_intakes` product_instances_events_join ON (`events`.`id` = `product_instances_events_join`.`event_id`) 
  LEFT OUTER JOIN `product_instances` ON (`product_instances`.`event_intake_id` = `product_instances_events_join`.`id`) AND event_intakes.is_draft = 1 
WHERE (product_instances.serial_number = '313') ORDER BY events.id DESC LIMIT 0, 50

through 关联将 event_intakes 表别名为“product_instances_events_join”。但是条件 event_intakes.is_draft 中的表并没有改变以匹配它。

我正在使用 rails 2.3.11,但我认为这个问题可能同样适用于 rails 3。我已经读过 through 关联应该只与 has_many 一起使用,而不是 has_one,但我认为这不是原因问题。

如果我只是将条件更改为“product_instances_events_join.is_draft = 1”,它将解决此特定情况的问题,但在没有表别名时会破坏它。如果我可以在 has_one 条件上使用字符串插值来获得正确的表名,那就太好了。像这样的东西: has_one :event_intake, :conditions => ["#{EventIntake.table_name}.is_draft = 1"] 我不认为上面的代码会起作用,因为发生别名时 EventIntake 的 table_name 不会改变。

我尝试过的另一件事是在进行查询之前立即重新定义 has_many 关联,在出现别名之前使用类似的东西: Event.has_one :event_intake, :conditions => ['product_instances_events_join.is_draft = 1'] 相信它与否,这实际上解决了 webrick 中的问题,但我对在多线程乘客环境中使用这种方法犹豫不决,因为我认为这无异于修改全局变量,这可能会影响其他线程。此外,这是一个黑客。

有没有人有任何建议如何解决这个问题?任何帮助将不胜感激。

4

1 回答 1

1

您可以将条件放在 :product_instances

class Event < ActiveRecord::Base
  has_one :event_intake 
  has_many :product_instances, :through => :event_intake,
               :conditions => ['event_intakes.is_draft = 1']
end

在 has_one 上设置条件似乎有点尴尬,因为您实际上不是在过滤 event_intakes 而是打开或关闭整个关联。但我想这不是重点。

另外,我确实理解,如果您有几个后续的“通过”关联,您希望通过中介条件过滤,那么这不是很干燥。这就是我发现自己的地方,这就是我在这里的机会。

于 2013-04-25T00:28:32.713 回答