87 lines
2.3 KiB
Ruby
87 lines
2.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Including the `UnnestedInFilters::Dsl` module to an ActiveRecord
|
|
# model extends the interface of the following class instances to be
|
|
# able to use the `use_unnested_filters` method;
|
|
#
|
|
# - Model relation;
|
|
# `Model.where(...).use_unnested_filters`
|
|
# - All the association proxies
|
|
# `project.model_association.use_unnested_filters`
|
|
# - All the relation instances of the association
|
|
# `project.model_association.where(...).use_unnested_filters
|
|
#
|
|
# Note: The interface of the model itself won't be extended as we don't
|
|
# have a use-case for now(`Model.use_unnested_filters` won't work).
|
|
#
|
|
# Example usage of the API;
|
|
#
|
|
# relation = Vulnerabilities::Read.where(state: [1, 4])
|
|
# .use_unnested_filters
|
|
# .order(severity: :desc, vulnerability_id: :desc)
|
|
#
|
|
# relation.to_a # => Will load records by using the optimized query
|
|
#
|
|
# See `UnnestedInFilters::Rewriter` for the details about the optimizations applied.
|
|
#
|
|
# rubocop:disable Gitlab/ModuleWithInstanceVariables
|
|
module UnnestedInFilters
|
|
module Dsl
|
|
extend ActiveSupport::Concern
|
|
|
|
MODULES_TO_EXTEND = [
|
|
ActiveRecord::Relation,
|
|
ActiveRecord::Associations::CollectionProxy,
|
|
ActiveRecord::AssociationRelation
|
|
].freeze
|
|
|
|
included do
|
|
MODULES_TO_EXTEND.each do |mod|
|
|
delegate_mod = relation_delegate_class(mod)
|
|
delegate_mod.prepend(UnnestedInFilters::Dsl::Relation)
|
|
end
|
|
end
|
|
|
|
module Relation
|
|
def use_unnested_filters
|
|
spawn.use_unnested_filters!
|
|
end
|
|
|
|
def use_unnested_filters!
|
|
assert_mutability!
|
|
@values[:unnested_filters] = true
|
|
|
|
self
|
|
end
|
|
|
|
def use_unnested_filters?
|
|
@values.fetch(:unnested_filters, false)
|
|
end
|
|
|
|
def load(*)
|
|
return super if loaded? || !rewrite_query?
|
|
|
|
@records = unnested_filter_rewriter.rewrite.to_a
|
|
@loaded = true
|
|
|
|
self
|
|
end
|
|
|
|
def exists?(*)
|
|
return super unless rewrite_query?
|
|
|
|
unnested_filter_rewriter.rewrite.exists?
|
|
end
|
|
|
|
private
|
|
|
|
def rewrite_query?
|
|
use_unnested_filters? && unnested_filter_rewriter.rewrite?
|
|
end
|
|
|
|
def unnested_filter_rewriter
|
|
@unnested_filter_rewriter ||= UnnestedInFilters::Rewriter.new(self)
|
|
end
|
|
end
|
|
end
|
|
end
|