假设我有一个与协会相关的模型突发事件和员工:
事件
belongs_to :recipient, class_name: 'Employee', foreign_key: :recipient_id
belongs_to :responder, class_name: 'Employee', foreign_key: :responder_id
我希望在事件模型中有一个范围,可以在收件人和响应者的名称之间进行检索。
scope :report, -> {left_joins(:recipient, :responder).select('incidents.*', 'responder.name AS Responder Name', 'recipient.name AS Recipient Name')}
我尝试过这样的事情,但我总是得到“缺少FROM子句......”的错误。
我需要了解的是:
如何在select中引用已加入的关联,以便我可以distingush 响应者和收件人之间是同一个表的记录,但是根据不同的外键来表示?
答案 0 :(得分:3)
加入时需要对表进行别名:
SELECT
incidents.*,
recipient.name AS recipient_name,
responder.name AS responder_name
FROM "incidents"
LEFT JOIN
users recipient ON recipient.id = incidents.recipient_id
LEFT JOIN
users responder ON responder.id = incidents.responder_id
您还需要为所选列使用适当的别名 - "收件人姓名"不能很好地映射到ruby方法名称。
class Incident < ApplicationRecord
belongs_to :recipient, class_name: 'User'.freeze
belongs_to :responder, class_name: 'User'.freeze
def self.report
self.select('
incidents.*,
recipient.name AS recipient_name,
responder.name AS responder_name
')
.joins("LEFT JOIN users recipient ON recipient.id = incidents.recipient_id")
.joins("LEFT JOIN users responder ON responder.id = incidents.responder_id")
end
end
irb(main):028:0> Incident.report.map(&:attributes)
Incident Load (1.4ms) SELECT incidents.*, recipient.name AS recipient_name, responder.name AS responder_name FROM "incidents" LEFT JOIN users recipient ON recipient.id = incidents.recipient_id LEFT JOIN users responder ON responder.id = incidents.responder_id
=> [{"id"=>1, "recipient_id"=>1, "responder_id"=>2, "created_at"=>Thu, 08 Mar 2018 15:51:52 UTC +00:00, "updated_at"=>Thu, 08 Mar 2018 15:51:52 UTC +00:00, "recipient_name"=>"Bob", "responder_name"=>"Erika"}]
答案 1 :(得分:1)
我只使用includes
代替joins
并使用默认的getter方法而不是select
:
Incidents.includes(:recipient, :responder).each do |incident|
puts incident
puts incident.recipient.name
puts incident.responder.name
end