0

我正在处理我们应用程序中的一个小错误,我将在此处尝试对其进行简化。

我有这个公司模型(实际模型有更多关联,但这里显示了问题):

class Company < ActiveRecord::Base
  has_many :contacts

  def self.search(query, page=1)
    companies = includes(:contacts).order("companies.name ASC")

    if query.present?
      companies = companies.where(%(
        companies.name ILIKE :q,
        OR contacts.name ILIKE :q
      ), q: "%#{query}%")
    end

    companies.paginate(page: page)
  end
end

现在这主要工作得很好。唯一的问题是当一家公司有 2 个或更多联系人时,用户会根据其中一个联系人姓名进行搜索。正确找到公司,我们的自动完成 UI 显示公司。然而,当用户从自动完成中选择公司时,他们应该能够从下拉列表中选择一个联系人,但下拉列表最终只包含他们过滤到的一个联系人。公司应根据其搜索条件进行过滤,但该下拉列表仍应包含公司的所有联系人供用户选择。

我知道它为什么这样做,这是因为 Rails 在查询运行时会自动加载所有关联,这样它既可以获取所有关联属性,又可以同时包含所有条件。

它正在运行一个select {every_attribute_from_every_included_table} left outer join {all_included_tables}查询,但我想要它做的是:

select companies.* from companies
left outer join contacts <and other included tables> on <join criteria>
where <filter criteria>

要过滤后跟 a 的公司:

select contacts.* from contacts
where company_id IN (<company_ids from previous query>)

如果includewhere如果该子句中不涉及这些表,

Rails 在这里做了太多的魔法,我希望它恢复正常的魔法,而不是特殊的魔法!我怎样才能做到这一点?或者有什么更好的方法来完成我想要完成的事情(仍然根据联系人姓名进行过滤,但在我打电话时不要阻止其他联系人被包括在内company.contacts)。

4

2 回答 2

1

Okay, let's do the query as you want

select companies.* from companies
left outer join contacts <and other included tables> on <join criteria>
where <filter criteria>

Let's manually override the .joins(...)

Company.includes(:contacts).
        joins("left outer join contacts c on c.company_id = companies.id").
        where(...)

This will leave the :contacts relation untouched, joining instead on a separate 'alias' of the same contacts table.

于 2013-06-10T23:19:47.073 回答
0

我看到您需要两个查询:

  • 一个选择公司(或公司)
  • 一个选择(选定的)公司的联系人

使用 Rails 魔法,您可以通过以下方式选择公司joins

@companies = Company.joins(:contacts).where(...).uniq

给予SELECT DISTINCT "companies".* FROM "companies" INNER JOIN "contacts" ON ... WHERE (...)

然后获取特定公司的所有联系人:

company= @companies.first
@contacts = company.contacts
于 2013-06-10T22:25:25.010 回答