如何使用Ruby on Rails 5.2编写复杂的联接查询?

时间:2019-02-22 21:39:04

标签: ruby-on-rails activerecord

我的应用程序以多种语言管理业务规则描述。要显示业务规则的索引(名称和描述),我需要将BusinessRule模型加入Translation模型。翻译模型是多态的:

 Table name: translations

  id            :integer          not null, primary key
  document_type :string
  document_id   :bigint(8)
  field_name    :string(30)       not null
  language      :string(2)        not null
  translation   :text
  searchable    :tsvector
  created_at    :datetime         not null
  updated_at    :datetime         not null

为了简化操作,我在 business_rule.rb 模型中定义了与业务规则的关系的别名:

  has_many :name_translations, -> { where("field_name='name'") }, class_name: 'Translation', as: :document
  has_many :description_translations, -> { where("field_name='description'") }, class_name: 'Translation', as: :document

要建立索引,我需要使外部规则分别与当前用户语言的name_translations和description_translations联接到业务规则中,该语言将变为SQL:

select BR.code, TR1.translation as name, TR2.translation as description
from dqm_app.business_rules BR
left outer join dqm_app.translations TR1 on (TR1.document_id = BR.id and TR1.field_name='name' and TR1.language='en')
left outer join dqm_app.translations TR2 on (TR2.document_id = BR.id and TR2.field_name='description' and TR2.language='en')

我尝试将其转换为(假设用户的语言是英语):

@business_rules = BusinessRule.left_outer_joins(:name_translations, :description_translations).
where(:name_translations.language = 'en' and description_translations.language = 'en')

这引起了两个问题:

  

1-ActiveRecord :: StatementInvalid(PG :: AmbiguousColumn:ERROR:列   引用“ field_name”不明确) [当然,它在查询中出现两次]

2-其中条件不正确,我不知道该如何构建。

你能帮我吗?

非常感谢!

2 个答案:

答案 0 :(得分:1)

要解决(1)更改范围以使用哈希语法,Rails将添加歧义,例如。

has_many :name_translations, -> { where(field_name: 'name') }, class_name: 'Translation', as: :document

要解决(2),要视情况而定,BusinessRule中是否存在存储语言的字段?如果可以的话,如果知道Rails会将BusinessRule实例本身传递给作用域,则可以执行以下操作:

has_many :name_translations, -> br { where(field_name: 'name', language: br.language) }, class_name: 'Translation', as: :document

答案 1 :(得分:0)

多亏了我,我终于解决了两个问题:

1-在BusinessRule模型中使用哈希语法添加了歧义消除

has_many :name_translations, -> { where(field_name: 'name') }, class_name: 'Translation', as: :document
has_many :description_translations, -> { where(field_name: 'description') }, class_name: 'Translation', as: :document

2-由于BusinessRule模型不存储语言,但是用户的个人资料存储,因此在索引方法中,我添加了一个where子句,该子句引用 translations 表:

  @business_rules = BusinessRule.left_outer_joins(:name_translations, :description_translations).
    where(translations: {language: user_language})

请注意,我没有设法在where子句中引用:name_translations或:description_translations。