【问题标题】:How do you get Rails has_many through relations to work with has_many conditions?你如何通过关系让 Rails has_many 与 has_many 条件一起工作?
【发布时间】:2012-08-03 19:08:18
【问题描述】:

我一直在从事一个大量使用模型关联的项目,似乎我发现了一个案例,其中 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

通过关联将 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 中的问题,但我对在多线程乘客环境中使用这种方法犹豫不决,因为我认为这无异于修改全局变量,这可能会影响其他线程。此外,这是一个 hack。

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

【问题讨论】:

  • 什么,没人知道吗?谁能回答这个问题,就可以获得免费糖果。

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


【解决方案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 而是打开或关闭整个关联。但我想这不是重点。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    相关资源
    最近更新 更多