ROR - 如何在父模型的范围内使用子模型的范围
ROR - How to use child Model's scope in Parent model's scope
class Application < ActiveRecord::Base
has_many :documents, class_name: DocumentTracker.name
scope :with_pending_docs, -> {
includes(:documents) {
# not able to use DocumentTracker's scope here
DocumentTracker.status_pending
}
}
#...
end
class DocumentTracker < ActiveRecord::Base
enum: status[:pending, :rejected, :accepted]
scope :status_pending, -> {
where(status: statuses[:pending])
}
}
#...
end
我想执行类似的操作:
application = Application.with_pending_docs.find(100)
application.documents.each{ |document|
# do something with pending docs
}
我可以单独执行此操作,但这会触发其他查询,例如:
application = Application.includes(:documents).find(100) #(2 queries)
docs = application.documents.status_pending #(+1 query)
我可以为单个记录执行此操作,但它不会达到目的(单个+多个记录查询):
application = Application.find(100).documents.status_pending
在处理多个应用程序时,担心 运行 进入 N+1 查询问题,因此希望一次性完成它
也许,我缺少次要语法或格式,但无法使用 google 搜索
找到任何相关内容
Ruby:2.4.1
Rails : 5.1.0
您需要做类似的事情,就好像您使用 left outer join
和条件在纯 SQL 中编写查询一样:
class Application < ActiveRecord::Base
has_many :documents, class_name: DocumentTracker.name
has_many :pending_documents, -> { where({ status: 'pending' }) }, class_name: DocumentTracker.name
scope :with_pending_docs, -> { includes(:pending_documents).where.not(document_trakers: { id: nil }) }
end
然后您可以在 Application
的每个实例上调用 pending_documents
而无需获得 N+1 个查询:
Application.with_pending_docs.each { |app| p app.pending_documents }
在尝试了很多关键字之后,终于找到了以下答案:
我所做的总结(请注意,我已经在 Application 和 DocumentTracker 中各有一个作用域)
#Application Scope
scope :with_pending_docs, -> {
includes(:documents).
merge(DocumentTracker.status_pending)
.references(:documents)
}
查询:
Application.with_pending_docs.find(100)
#or
Application.with_pending_docs.where("applications.id > ?", 100)
希望这对以后的人有所帮助。
class Application < ActiveRecord::Base
has_many :documents, class_name: DocumentTracker.name
scope :with_pending_docs, -> {
includes(:documents) {
# not able to use DocumentTracker's scope here
DocumentTracker.status_pending
}
}
#...
end
class DocumentTracker < ActiveRecord::Base
enum: status[:pending, :rejected, :accepted]
scope :status_pending, -> {
where(status: statuses[:pending])
}
}
#...
end
我想执行类似的操作:
application = Application.with_pending_docs.find(100)
application.documents.each{ |document|
# do something with pending docs
}
我可以单独执行此操作,但这会触发其他查询,例如:
application = Application.includes(:documents).find(100) #(2 queries)
docs = application.documents.status_pending #(+1 query)
我可以为单个记录执行此操作,但它不会达到目的(单个+多个记录查询):
application = Application.find(100).documents.status_pending
在处理多个应用程序时,担心 运行 进入 N+1 查询问题,因此希望一次性完成它
也许,我缺少次要语法或格式,但无法使用 google 搜索
找到任何相关内容Ruby:2.4.1 Rails : 5.1.0
您需要做类似的事情,就好像您使用 left outer join
和条件在纯 SQL 中编写查询一样:
class Application < ActiveRecord::Base
has_many :documents, class_name: DocumentTracker.name
has_many :pending_documents, -> { where({ status: 'pending' }) }, class_name: DocumentTracker.name
scope :with_pending_docs, -> { includes(:pending_documents).where.not(document_trakers: { id: nil }) }
end
然后您可以在 Application
的每个实例上调用 pending_documents
而无需获得 N+1 个查询:
Application.with_pending_docs.each { |app| p app.pending_documents }
在尝试了很多关键字之后,终于找到了以下答案:
我所做的总结(请注意,我已经在 Application 和 DocumentTracker 中各有一个作用域)
#Application Scope
scope :with_pending_docs, -> {
includes(:documents).
merge(DocumentTracker.status_pending)
.references(:documents)
}
查询:
Application.with_pending_docs.find(100)
#or
Application.with_pending_docs.where("applications.id > ?", 100)
希望这对以后的人有所帮助。