我正在尝试创建一个范围方法,该方法仅查询最近更新的记录(或者最近更新了它们的相关模型)。我相信生成的SQL语句看起来没问题,但是当应该有一些时,我没有看到任何结果。谢谢你的帮助!
控制器
class Api::V1::EncountersController < ApplicationController
respond_to :json
def index
if params.has_key?(:datestart)
...
elsif params.has_key?(:updated_since)
date = Date.parse(params[:updated_since])
respond_with(Encounter.by_updated_since(date),
:include => [:facility, :physician, :encounter_type, :group, :provider, :insurance],
:except => [:facility_id, :physician_id, :encounter_type_id, :group_id, :provider_id, :insurance_id])
else
...
end
end
模型
class Encounter < ApplicationRecord
validates :encounter_type, :physician, :facility, :datetime_start_utc_scheduled, :procedures, :presence => true
belongs_to :encounter_type
belongs_to :physician
belongs_to :facility
belongs_to :insurance
belongs_to :group, optional: true
has_many :encounter_procedures, :dependent => :destroy
has_many :procedures, through: :encounter_procedures
has_many :actuals, :dependent => :destroy
has_many :providers, through: :actuals
...
scope :by_updated_since, -> updated_at {
joins(:facility)
.joins(:physician)
.joins(:encounter_type)
.joins(:group)
.joins(:insurance)
.where("encounters.updated_at >= ? OR
facilities.updated_at >= ? OR
physicians.updated_at >= ? OR
encounter_types.updated_at >= ? OR
groups.updated_at >= ? OR
insurances.updated_at >= ?",
updated_at, updated_at, updated_at, updated_at, updated_at, updated_at)}
...
end
使用生成SQL登录
app/controllers/api/v1/encounters_controller.rb:12:in `index'
Started GET "/api/v1/encounters?updated_since=2017-08-01" for 127.0.0.1 at 2017-08-10 11:55:01 -0500
Processing by Api::V1::EncountersController#index as JSON
Parameters: {"updated_since"=>"2017-08-01"}
Encounter Load (32.2ms) SELECT "encounters".* FROM "encounters" INNER JOIN "facilities" ON "facilities"."id" = "encounters"."facility_id" INNER JOIN "physicians" ON "physicians"."id" = "encounters"."physician_id" INNER JOIN "encounter_types" ON "encounter_types"."id" = "encounters"."encounter_type_id" INNER JOIN "groups" ON "groups"."id" = "encounters"."group_id" INNER JOIN "insurances" ON "insurances"."id" = "encounters"."insurance_id" WHERE (encounters.updated_at >= '2017-08-01' OR
facilities.updated_at >= '2017-08-01' OR
physicians.updated_at >= '2017-08-01' OR
encounter_types.updated_at >= '2017-08-01' OR
groups.updated_at >= '2017-08-01' OR
insurances.updated_at >= '2017-08-01')
[active_model_serializers] Rendered ActiveModel::Serializer::CollectionSerializer with ActiveModelSerializers::Adapter::Attributes (0.12ms)
Completed 200 OK in 81ms (Views: 31.4ms | ActiveRecord: 32.2ms)
答案 0 :(得分:0)
您的问题:
ActiveRecord joins
生成INNER JOIN
,因此User.joins(:posts)
仅返回至少 1关联User
的{{1}}条记录。
我很确定如果你做一个简单的Post
,它将返回一个空列表。
<强>解决方案强>:
使用Encounter.joins(:facility, :physician, :encounter_type, :group, :insurance)
与includes
结合使用,如果没有关联记录,它将不会忽略Encounter记录:
references
在你的范围内:
Encounter.includes(:facility, :physician, :encounter_type, :group, :insurance).references(:facility, :physician, :encounter_type, :group, :insurance).where([...])
改进建议:
scope :by_updated_since, -> updated_at {
includes(:facility, :physician, :encounter_type, :group, :insurance)
.references(:facility, :physician, :encounter_type, :group, :insurance)
.where("encounters.updated_at >= ? OR
facilities.updated_at >= ? OR
physicians.updated_at >= ? OR
encounter_types.updated_at >= ? OR
groups.updated_at >= ? OR
insurances.updated_at >= ?",
updated_at, updated_at, updated_at, updated_at, updated_at, updated_at)}
但我担心scope :by_updated_since, ->(updated_at) {
relations = %i(facility physician encounter_type group insurance)
sql_cond = relations.map(&:pluralize).map { |table_name| "#{table_name}.updated_at >= :datetime" }.join(' OR ')
includes(*relations)
.references(*relations)
.where(sql_cond, datetime: updated_at) }
需要table_name而不是关系名称......