Rails 4嵌套了连接表上具有多个关联的where子句

时间:2017-02-07 00:46:40

标签: ruby-on-rails ruby-on-rails-4 activerecord where-clause

我有一个Order模型,它与VoyageLeg模型(后来属于一个端口)有两个关联,如下所示:

class Order < ActiveRecord::Base
  belongs_to :boarding_leg, class_name: "VoyageLeg"
  belongs_to :disembarking_leg, class_name: "VoyageLeg"
end

class VoyageLeg < ActiveRecord::Base
  belongs_to :port
  has_many :orders_boarding, class_name: "Order", inverse_of: :boarding_leg, :foreign_key => 'boarding_leg_id'
  has_many :orders_disembarking, class_name: "Order", inverse_of: :disembarking_leg, :foreign_key => 'disembarking_leg_id'
end

我可以为boarding_leg上的端口执行where子句,如下所示:

Order.joins(boarding_leg: :port).where(ports: {code: "AKL"}).count

但是如何在boarding_leg上为一个端口代码执行where子句,在disembarking_leg上执行不同的端口代码?

当我这样做时:

Order.joins(boarding_leg: :port).where(ports: {code: "ALK"}).joins(:disembarking_leg).where(ports: {code: "WLG"}).count

生成的SQL是:

SELECT COUNT(*) FROM "orders" INNER JOIN "voyage_legs" ON "voyage_legs"."id" = "orders"."boarding_leg_id" AND "voyage_legs"."deleted_at" IS NULL INNER JOIN "ports" ON "ports"."id" = "voyage_legs"."port_id" AND "ports"."deleted_at" IS NULL INNER JOIN "voyage_legs" "disembarking_legs_orders" ON "disembarking_legs_orders"."id" = "orders"."disembarking_leg_id" AND "disembarking_legs_orders"."deleted_at" IS NULL WHERE "orders"."deleted_at" IS NULL AND "ports"."code" = 'ALK' AND "ports"."code" = 'WLG'

所以它永远不会返回任何东西,因为端口代码不能同时是WLG和AKL - 我需要一种方法来使where子句特定于连接。

1 个答案:

答案 0 :(得分:0)

我能做的最好(正如@max所建议的那样)是将更多内容写成SQL。我为连接创建了一个别名,然后我可以引用特定连接到别名端口连接,然后引用特定端口,如下所示:

Order.joins('INNER JOIN voyage_legs boarding_legs ON boarding_legs.id = orders.boarding_leg_id AND boarding_legs.deleted_at IS NULL INNER JOIN ports boarding_ports ON boarding_ports.id = boarding_legs.port_id AND boarding_ports.deleted_at IS NULL INNER JOIN voyage_legs disembarking_legs ON disembarking_legs.id = orders.disembarking_leg_id AND disembarking_legs.deleted_at IS NULL INNER JOIN ports disembarking_ports ON disembarking_ports.id = disembarking_legs.port_id AND disembarking_ports.deleted_at IS NULL').where('boarding_ports.code = :boarding_code AND disembarking_ports.code = :disembarking_code', boarding_code: "AKL", disembarking_code: "WLG").count