你如何通过关系使用Rails has_many来处理has_many条件?

时间:2012-08-06 19:26:06

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

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

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.我已经读过,通关联应该只用于has_many,而不是has_one,但我不认为这是这个问题的原因。

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

我尝试的另一件事是在进行别名之前动态重新定义has_many关联,在我进行查询之前就是这样: Event.has_one:event_intake,:conditions =&gt; ['product_instances_events_join.is_draft = 1'] 信不信由你,这实际上解决了webrick中的问题,但我对在多线程乘客环境中使用这种方法犹豫不决,因为我认为它等于修改一个可能影响其他线程的全局变量。此外,这是一个黑客。

有没有人有任何建议如何解决这个问题?非常感谢任何帮助。

1 个答案:

答案 0 :(得分: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而是开启或关闭整个关联。但我猜这不是重点。

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