添加范围时忽略Rails HABTM finder_sql

时间:2014-08-26 19:36:31

标签: ruby-on-rails ruby-on-rails-3.2 rails-activerecord arel has-and-belongs-to-many

我有一个自定义连接表设置来管理HABTM关系。我为:finder_sql选项编写了自定义SQL,因为我的连接表是多态关系。这适用于基本情况,但是当我向引用添加其他范围时,似乎完全忽略了我的:finder_sql

联接表如下所示:

Table "public.question_template_joins"
        Column        |          Type          | Modifiers | Storage  | Description
----------------------+------------------------+-----------+----------+-------------
 question_template_id | integer                |           | plain    |
 template_owner_id    | integer                |           | plain    |
 template_owner_type  | character varying(255) |           | extended |

HABTM关系在这样的模型上定义:

finder_sql = proc { <<-SQL
  SELECT DISTINCT question_templates.* FROM question_templates
  INNER JOIN question_template_joins ON question_templates.id = question_template_joins.question_template_id
  WHERE question_template_joins.template_owner_id = #{id}
    AND question_template_joins.template_owner_type = '#{self.class.table_name}'
SQL
}
has_and_belongs_to_many :question_templates, finder_sql: finder_sql

如果我这样打电话,一切正常:

> template = SurveyTemplate.first
> template.question_templates

正确查询:

  QuestionTemplate Load (5.2ms)   SELECT DISTINCT question_templates.* FROM question_templates
 INNER JOIN question_template_joins ON question_templates.id = question_template_joins.question_template_id
 WHERE question_template_joins.template_owner_id = 4
 AND question_template_joins.template_owner_type = 'survey_templates'

如果我将范围链接到这样的调用上,那么中断的情况就是:

class QuestionTemplate < ActiveRecord::Base
  scope :active, where(active: true)
end

> template = SurveyTemplate.first
> template.question_templates.active    # added active to call

实际查询不正确:

QuestionTemplate Load (0.3ms)  SELECT "question_templates".* FROM "question_templates" 
  INNER JOIN "question_templates_survey_templates" ON "question_templates"."id" = 
  "question_templates_survey_templates"."question_template_id" WHERE 
  "question_templates_survey_templates"."survey_template_id" = 4 AND 
  "question_templates"."active" = 't'


ActiveRecord::StatementInvalid: PG::Error: ERROR:  relation 
"question_templates_survey_templates" does not exist

它已恢复为尝试默认的HABTM查找。

为什么ActiveRecord / AREL在添加范围时会忽略我的:finder_sql

我该怎么做才能纠正它?

1 个答案:

答案 0 :(得分:0)

假设你还有这个问题,我想一些细节不足以让我给出一个自信的答案。根据您提供的信息,您所做的一些事情可能会使ActiveRecord逻辑混乱。

  1. 您已在QuestionTemplate和SurveyTemplate之间创建了一个不遵循Rails约定的连接表。默认情况下,Rails假定连接表名称为question_templates_survey_templates,但看起来您希望使用名为question_template_joins的其他连接表。如果您想使用联接表,则必须在声明HABTM时指定(例如has_and_belongs_to_many :question_templates, finder_sql: finder_sql, join_table: "question_template_joins")。使用此选项可能会简化/减少:finder_sql
  2. 我不相信Rails足够聪明,可以在反向相关的HABTM类之间连接选项。虽然您为SurveyTemplate提供了:finder_sql来查找其QuestionTemplates,但您可能需要为QuestionTemplate提供不同的:finder_sql来查找其SurveyTemplates。
  3. 我怀疑#2因为我不完全理解你在QuestionTemplate和SurveyTemplate之间的理想关系。如果你想要Rails到#34; Just Work&#34;,切换到Rails默认连接表(question_templates_survey_templates)可能会解决你的问题。但是,假设您在自定义template_owner_type中指定了question_template_joins列,我认为您已为该所有者类型指定了一定程度的重要性;如果是这样,我不确定Rails默认HABTM是否能够满足您的需求。

    有一些方法可以使用/围绕ActiveRecord,但是如果不知道QuestionTemplate和SurveyTemplate之间确切的理想关系,就很难给出任何具体的答案。