module Bullet::ActiveRecord

def self.enable

def self.enable
  require 'active_record'
  ::ActiveRecord::Base.class_eval do
    class << self
      alias_method :origin_find_by_sql, :find_by_sql
      def find_by_sql(sql, binds = [])
        result = origin_find_by_sql(sql, binds)
        if Bullet.start?
          if result.is_a? Array
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          elsif result.is_a? ::ActiveRecord::Base
            Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
            Bullet::Detector::CounterCache.add_impossible_object(result)
          end
        end
        result
      end
    end
  end
  ::ActiveRecord::Relation.class_eval do
    alias_method :origin_to_a, :to_a
    # if select a collection of objects, then these objects have possible to cause N+1 query.
    # if select only one object, then the only one object has impossible to cause N+1 query.
    def to_a
      records = origin_to_a
      if Bullet.start?
        if records.size > 1
          Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
          Bullet::Detector::CounterCache.add_possible_objects(records)
        elsif records.size == 1
          Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
          Bullet::Detector::CounterCache.add_impossible_object(records.first)
        end
      end
      records
    end
  end
  ::ActiveRecord::Persistence.class_eval do
    def _create_record_with_bullet(*args)
      _create_record_without_bullet(*args).tap do
        Bullet::Detector::NPlusOneQuery.update_inversed_object(self)
        Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
      end
    end
    alias_method_chain :_create_record, :bullet
  end
  ::ActiveRecord::Associations::Preloader.class_eval do
    # include query for one to many associations.
    # keep this eager loadings.
    alias_method :origin_initialize, :initialize
    def initialize(records, associations, preload_scope = nil)
      origin_initialize(records, associations, preload_scope)
      if Bullet.start?
        records = [records].flatten.compact.uniq
        return if records.empty?
        records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
        Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
      end
    end
  end
  ::ActiveRecord::FinderMethods.class_eval do
    # add includes in scope
    alias_method :origin_find_with_associations, :find_with_associations
    def find_with_associations
      records = origin_find_with_associations
      if Bullet.start?
        associations = (eager_load_values + includes_values).uniq
        records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
        Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
      end
      records
    end
  end
  ::ActiveRecord::Associations::JoinDependency.class_eval do
    alias_method :origin_instantiate, :instantiate
    alias_method :origin_construct_association, :construct_association
    def instantiate(rows)
      @bullet_eager_loadings = {}
      records = origin_instantiate(rows)
      if Bullet.start?
        @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
          objects = eager_loadings_hash.keys
          Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
        end
      end
      records
    end
    # call join associations
    def construct_association(record, join, row)
      result = origin_construct_association(record, join, row)
      if Bullet.start?
        associations = [join.reflection.name]
        if join.reflection.nested?
          associations << join.reflection.through_reflection.name
        end
        associations.each do |association|
          Bullet::Detector::Association.add_object_associations(record, association)
          Bullet::Detector::NPlusOneQuery.call_association(record, association)
          @bullet_eager_loadings[record.class] ||= {}
          @bullet_eager_loadings[record.class][record] ||= Set.new
          @bullet_eager_loadings[record.class][record] << association
        end
      end
      result
    end
  end
  ::ActiveRecord::Associations::CollectionAssociation.class_eval do
    # call one to many associations
    alias_method :origin_load_target, :load_target
    def load_target
      Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start?
      origin_load_target
    end
    alias_method :origin_include?, :include?
    def include?(object)
      Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start?
      origin_include?(object)
    end
  end
  ::ActiveRecord::Associations::HasManyAssociation.class_eval do
    alias_method :origin_empty?, :empty?
    def empty?
      if Bullet.start? && !loaded? && !has_cached_counter?(@reflection)
        Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
      end
      origin_empty?
    end
  end
  ::ActiveRecord::Associations::HasAndBelongsToManyAssociation.class_eval do
    alias_method :origin_empty?, :empty?
    def empty?
      Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start? && !loaded?
      origin_empty?
    end
  end
  ::ActiveRecord::Associations::SingularAssociation.class_eval do
    # call has_one and belongs_to associations
    alias_method :origin_reader, :reader
    def reader(force_reload = false)
      result = origin_reader(force_reload)
      if Bullet.start?
        unless @inversed
          Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
          Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        end
      end
      result
    end
  end
  ::ActiveRecord::Associations::HasManyAssociation.class_eval do
    alias_method :origin_has_cached_counter?, :has_cached_counter?
    def has_cached_counter?(reflection = reflection())
      result = origin_has_cached_counter?(reflection)
      Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name) if Bullet.start? && !result
      result
    end
  end
  ::ActiveRecord::Associations::CollectionProxy.class_eval do
    def count(column_name = nil, options = {})
      if Bullet.start?
        Bullet::Detector::CounterCache.add_counter_cache(proxy_association.owner, proxy_association.reflection.name)
        Bullet::Detector::NPlusOneQuery.call_association(proxy_association.owner, proxy_association.reflection.name)
      end
      super(column_name, options)
    end
  end
end

def self.enable

def self.enable
  require 'active_record'
  ::ActiveRecord::Base.class_eval do
    class << self
      alias_method :origin_find_by_sql, :find_by_sql
      def find_by_sql(sql, binds = [])
        result = origin_find_by_sql(sql, binds)
        if Bullet.start?
          if result.is_a? Array
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          elsif result.is_a? ::ActiveRecord::Base
            Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
            Bullet::Detector::CounterCache.add_impossible_object(result)
          end
        end
        result
      end
    end
  end
  ::ActiveRecord::Relation.class_eval do
    alias_method :origin_to_a, :to_a
    # if select a collection of objects, then these objects have possible to cause N+1 query.
    # if select only one object, then the only one object has impossible to cause N+1 query.
    def to_a
      records = origin_to_a
      if Bullet.start?
        if records.first.class.name !~ /^HABTM_/
          if records.size > 1
            Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
            Bullet::Detector::CounterCache.add_possible_objects(records)
          elsif records.size == 1
            Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
            Bullet::Detector::CounterCache.add_impossible_object(records.first)
          end
        end
      end
      records
    end
  end
  ::ActiveRecord::Persistence.class_eval do
    def _create_record_with_bullet(*args)
      _create_record_without_bullet(*args).tap do
        Bullet::Detector::NPlusOneQuery.update_inversed_object(self)
        Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
      end
    end
    alias_method_chain :_create_record, :bullet
  end
  ::ActiveRecord::Associations::Preloader.class_eval do
    alias_method :origin_preloaders_on, :preloaders_on
    def preloaders_on(association, records, scope)
      if Bullet.start?
        records.compact!
        if records.first.class.name !~ /^HABTM_/
          records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
          Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
        end
      end
      origin_preloaders_on(association, records, scope)
    end
  end
  ::ActiveRecord::FinderMethods.class_eval do
    # add includes in scope
    alias_method :origin_find_with_associations, :find_with_associations
    def find_with_associations
      return origin_find_with_associations { |r| yield r } if block_given?
      records = origin_find_with_associations
      if Bullet.start?
        associations = (eager_load_values + includes_values).uniq
        records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
        Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
      end
      records
    end
  end
  ::ActiveRecord::Associations::JoinDependency.class_eval do
    alias_method :origin_instantiate, :instantiate
    alias_method :origin_construct_model, :construct_model
    def instantiate(result_set, aliases)
      @bullet_eager_loadings = {}
      records = origin_instantiate(result_set, aliases)
      if Bullet.start?
        @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
          objects = eager_loadings_hash.keys
          Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
        end
      end
      records
    end
    # call join associations
    def construct_model(record, node, row, model_cache, id, aliases)
      result = origin_construct_model(record, node, row, model_cache, id, aliases)
      if Bullet.start?
        associations = [node.reflection.name]
        if node.reflection.nested?
          associations << node.reflection.through_reflection.name
        end
        associations.each do |association|
          Bullet::Detector::Association.add_object_associations(record, association)
          Bullet::Detector::NPlusOneQuery.call_association(record, association)
          @bullet_eager_loadings[record.class] ||= {}
          @bullet_eager_loadings[record.class][record] ||= Set.new
          @bullet_eager_loadings[record.class][record] << association
        end
      end
      result
    end
  end
  ::ActiveRecord::Associations::CollectionAssociation.class_eval do
    # call one to many associations
    alias_method :origin_load_target, :load_target
    def load_target
      Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start? && !@inversed
      origin_load_target
    end
    alias_method :origin_empty?, :empty?
    def empty?
      if Bullet.start? && !has_cached_counter?(@reflection)
        Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
      end
      origin_empty?
    end
    alias_method :origin_include?, :include?
    def include?(object)
      Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start?
      origin_include?(object)
    end
  end
  ::ActiveRecord::Associations::SingularAssociation.class_eval do
    # call has_one and belongs_to associations
    alias_method :origin_reader, :reader
    def reader(force_reload = false)
      result = origin_reader(force_reload)
      if Bullet.start?
        if @owner.class.name !~ /^HABTM_/ && !@inversed
          Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
          Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        end
      end
      result
    end
  end
  ::ActiveRecord::Associations::HasManyAssociation.class_eval do
    alias_method :origin_count_records, :count_records
    def count_records
      result = has_cached_counter?
      Bullet::Detector::CounterCache.add_counter_cache(@owner, @reflection.name) if Bullet.start? && !result
      origin_count_records
    end
  end
  ::ActiveRecord::Associations::CollectionProxy.class_eval do
    def count(column_name = nil, options = {})
      if Bullet.start?
        Bullet::Detector::CounterCache.add_counter_cache(proxy_association.owner, proxy_association.reflection.name)
        Bullet::Detector::NPlusOneQuery.call_association(proxy_association.owner, proxy_association.reflection.name)
      end
      super(column_name, options)
    end
  end
end

def self.enable

def self.enable
  require 'active_record'
  ::ActiveRecord::Base.class_eval do
    class << self
      alias_method :origin_find, :find
      def find(*args)
        result = origin_find(*args)
        if Bullet.start?
          if result.is_a? Array
            Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
            Bullet::Detector::CounterCache.add_possible_objects(result)
          elsif result.is_a? ::ActiveRecord::Base
            Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
            Bullet::Detector::CounterCache.add_impossible_object(result)
          end
        end
        result
      end
      alias_method :origin_find_by_sql, :find_by_sql
      def find_by_sql(sql, binds = [])
        result = origin_find_by_sql(sql, binds)
        if Bullet.start?
          if result.is_a? Array
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          elsif result.is_a? ::ActiveRecord::Base
            Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
            Bullet::Detector::CounterCache.add_impossible_object(result)
          end
        end
        result
      end
    end
  end
  ::ActiveRecord::Persistence.class_eval do
    def _create_record_with_bullet(*args)
      _create_record_without_bullet(*args).tap do
        Bullet::Detector::NPlusOneQuery.update_inversed_object(self)
        Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
      end
    end
    alias_method_chain :_create_record, :bullet
  end
  ::ActiveRecord::Relation.class_eval do
    alias_method :origin_to_a, :to_a
    # if select a collection of objects, then these objects have possible to cause N+1 query.
    # if select only one object, then the only one object has impossible to cause N+1 query.
    def to_a
      records = origin_to_a
      if Bullet.start?
        if records.first.class.name !~ /^HABTM_/
          if records.size > 1
            Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
            Bullet::Detector::CounterCache.add_possible_objects(records)
          elsif records.size == 1
            Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
            Bullet::Detector::CounterCache.add_impossible_object(records.first)
          end
        end
      end
      records
    end
  end
  ::ActiveRecord::Associations::Preloader.class_eval do
    alias_method :origin_preloaders_on, :preloaders_on
    def preloaders_on(association, records, scope)
      if Bullet.start?
        records.compact!
        if records.first.class.name !~ /^HABTM_/
          records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
          Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
        end
      end
      origin_preloaders_on(association, records, scope)
    end
  end
  ::ActiveRecord::FinderMethods.class_eval do
    # add includes in scope
    alias_method :origin_find_with_associations, :find_with_associations
    def find_with_associations
      return origin_find_with_associations { |r| yield r } if block_given?
      records = origin_find_with_associations
      if Bullet.start?
        associations = (eager_load_values + includes_values).uniq
        records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
        Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
      end
      records
    end
  end
  ::ActiveRecord::Associations::JoinDependency.class_eval do
    alias_method :origin_instantiate, :instantiate
    alias_method :origin_construct, :construct
    alias_method :origin_construct_model, :construct_model
    def instantiate(result_set, aliases)
      @bullet_eager_loadings = {}
      records = origin_instantiate(result_set, aliases)
      if Bullet.start?
        @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
          objects = eager_loadings_hash.keys
          Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
        end
      end
      records
    end
    def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
      if Bullet.start?
        unless ar_parent.nil?
          parent.children.each do |node|
            key = aliases.column_alias(node, node.primary_key)
            id = row[key]
            next unless id.nil?
            associations = [node.reflection.name]
            if node.reflection.nested?
              associations << node.reflection.through_reflection.name
            end
            associations.each do |association|
              Bullet::Detector::Association.add_object_associations(ar_parent, association)
              Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
              @bullet_eager_loadings[ar_parent.class] ||= {}
              @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
              @bullet_eager_loadings[ar_parent.class][ar_parent] << association
            end
          end
        end
      end
      origin_construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
    end
    # call join associations
    def construct_model(record, node, row, model_cache, id, aliases)
      result = origin_construct_model(record, node, row, model_cache, id, aliases)
      if Bullet.start?
        associations = [node.reflection.name]
        if node.reflection.nested?
          associations << node.reflection.through_reflection.name
        end
        associations.each do |association|
          Bullet::Detector::Association.add_object_associations(record, association)
          Bullet::Detector::NPlusOneQuery.call_association(record, association)
          @bullet_eager_loadings[record.class] ||= {}
          @bullet_eager_loadings[record.class][record] ||= Set.new
          @bullet_eager_loadings[record.class][record] << association
        end
      end
      result
    end
  end
  ::ActiveRecord::Associations::CollectionAssociation.class_eval do
    # call one to many associations
    alias_method :origin_load_target, :load_target
    def load_target
      records = origin_load_target
      if Bullet.start?
        Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) unless @inversed
        if records.first.class.name !~ /^HABTM_/
          if records.size > 1
            Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
            Bullet::Detector::CounterCache.add_possible_objects(records)
          elsif records.size == 1
            Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
            Bullet::Detector::CounterCache.add_impossible_object(records.first)
          end
        end
      end
      records
    end
    alias_method :origin_empty?, :empty?
    def empty?
      if Bullet.start? && !has_cached_counter?(@reflection)
        Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
      end
      origin_empty?
    end
    alias_method :origin_include?, :include?
    def include?(object)
      Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start?
      origin_include?(object)
    end
  end
  ::ActiveRecord::Associations::SingularAssociation.class_eval do
    # call has_one and belongs_to associations
    alias_method :origin_reader, :reader
    def reader(force_reload = false)
      result = origin_reader(force_reload)
      if Bullet.start?
        if @owner.class.name !~ /^HABTM_/ && !@inversed
          Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
          if Bullet::Detector::NPlusOneQuery.impossible?(@owner)
            Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
          else
            Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
          end
        end
      end
      result
    end
  end
  ::ActiveRecord::Associations::HasManyAssociation.class_eval do
    alias_method :origin_many_empty?, :empty?
    def empty?
      result = origin_many_empty?
      if Bullet.start? && !has_cached_counter?(@reflection)
        Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
      end
      result
    end
    alias_method :origin_count_records, :count_records
    def count_records
      result = has_cached_counter?
      Bullet::Detector::CounterCache.add_counter_cache(@owner, @reflection.name) if Bullet.start? && !result
      origin_count_records
    end
  end
  ::ActiveRecord::Associations::CollectionProxy.class_eval do
    def count(column_name = nil, options = {})
      if Bullet.start?
        Bullet::Detector::CounterCache.add_counter_cache(proxy_association.owner, proxy_association.reflection.name)
        Bullet::Detector::NPlusOneQuery.call_association(proxy_association.owner, proxy_association.reflection.name)
      end
      super(column_name, options)
    end
  end
end

def self.enable

def self.enable
  require 'active_record'
  ::ActiveRecord::Base.extend(
    Module.new do
      def find_by_sql(sql, binds = [], preparable: nil, &block)
        result = super
        if Bullet.start?
          if result.is_a? Array
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          elsif result.is_a? ::ActiveRecord::Base
            Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
            Bullet::Detector::CounterCache.add_impossible_object(result)
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Base.prepend(SaveWithBulletSupport)
  ::ActiveRecord::Relation.prepend(
    Module.new do
      # if select a collection of objects, then these objects have possible to cause N+1 query.
      # if select only one object, then the only one object has impossible to cause N+1 query.
      def records
        result = super
        if Bullet.start?
          if result.first.class.name !~ /^HABTM_/
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Preloader.prepend(
    Module.new do
      def preloaders_for_one(association, records, scope)
        if Bullet.start?
          records.compact!
          if records.first.class.name !~ /^HABTM_/
            records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
          end
        end
        super
      end
    end
  )
  ::ActiveRecord::FinderMethods.prepend(
    Module.new do
      # add includes in scope
      def find_with_associations
        return super { |r| yield r } if block_given?
        records = super
        if Bullet.start?
          associations = (eager_load_values + includes_values).uniq
          records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
          Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
        end
        records
      end
    end
  )
  ::ActiveRecord::Associations::JoinDependency.prepend(
    Module.new do
      if ::ActiveRecord::Associations::JoinDependency.instance_method(:instantiate).parameters.last[0] == :block
        # ActiveRecord >= 5.1.5
        def instantiate(result_set, &block)
          @bullet_eager_loadings = {}
          records = super
          if Bullet.start?
            @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
              objects = eager_loadings_hash.keys
              Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
                objects,
                eager_loadings_hash[objects.first].to_a
              )
            end
          end
          records
        end
      else
        # ActiveRecord <= 5.1.4
        def instantiate(result_set, aliases)
          @bullet_eager_loadings = {}
          records = super
          if Bullet.start?
            @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
              objects = eager_loadings_hash.keys
              Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
                objects,
                eager_loadings_hash[objects.first].to_a
              )
            end
          end
          records
        end
      end
      def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
        if Bullet.start?
          unless ar_parent.nil?
            parent.children.each do |node|
              key = aliases.column_alias(node, node.primary_key)
              id = row[key]
              next unless id.nil?
              associations = [node.reflection.name]
              if node.reflection.through_reflection?
                associations << node.reflection.through_reflection.name
              end
              associations.each do |association|
                Bullet::Detector::Association.add_object_associations(ar_parent, association)
                Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
                @bullet_eager_loadings[ar_parent.class] ||= {}
                @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
                @bullet_eager_loadings[ar_parent.class][ar_parent] << association
              end
            end
          end
        end
        super
      end
      # call join associations
      def construct_model(record, node, row, model_cache, id, aliases)
        result = super
        if Bullet.start?
          associations = [node.reflection.name]
          if node.reflection.through_reflection?
            associations << node.reflection.through_reflection.name
          end
          associations.each do |association|
            Bullet::Detector::Association.add_object_associations(record, association)
            Bullet::Detector::NPlusOneQuery.call_association(record, association)
            @bullet_eager_loadings[record.class] ||= {}
            @bullet_eager_loadings[record.class][record] ||= Set.new
            @bullet_eager_loadings[record.class][record] << association
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::CollectionAssociation.prepend(
    Module.new do
      def load_target
        records = super
        if Bullet.start?
          if is_a? ::ActiveRecord::Associations::ThroughAssociation
            refl = reflection.through_reflection
            association = owner.association(refl.name)
            if association.loaded?
              Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if refl.through_reflection?
                refl = refl.through_reflection while refl.through_reflection?
                Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
              end
            end
          end
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
          if records.first.class.name !~ /^HABTM_/
            if records.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
              Bullet::Detector::CounterCache.add_possible_objects(records)
            elsif records.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
              Bullet::Detector::CounterCache.add_impossible_object(records.first)
            end
          end
        end
        records
      end
      def empty?
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        super
      end
      def include?(object)
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
        super
      end
    end
  )
  ::ActiveRecord::Associations::SingularAssociation.prepend(
    Module.new do
      # call has_one and belongs_to associations
      def target
        result = super()
        if Bullet.start?
          if owner.class.name !~ /^HABTM_/ && !@inversed
            Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
            if Bullet::Detector::NPlusOneQuery.impossible?(owner)
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
            else
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
    Module.new do
      def empty?
        result = super
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        result
      end
      def count_records
        result = reflection.has_cached_counter?
        if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionProxy.prepend(
    Module.new do
      def count(column_name = nil)
        if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(
            proxy_association.owner,
            proxy_association.reflection.name
          )
          Bullet::Detector::NPlusOneQuery.call_association(
            proxy_association.owner,
            proxy_association.reflection.name
          )
        end
        super(column_name)
      end
    end
  )
end

def self.enable

def self.enable
  require 'active_record'
  ::ActiveRecord::Base.extend(
    Module.new do
      def find_by_sql(sql, binds = [], preparable: nil, &block)
        result = super
        if Bullet.start?
          if result.is_a? Array
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          elsif result.is_a? ::ActiveRecord::Base
            Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
            Bullet::Detector::CounterCache.add_impossible_object(result)
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Base.prepend(SaveWithBulletSupport)
  ::ActiveRecord::Relation.prepend(
    Module.new do
      # if select a collection of objects, then these objects have possible to cause N+1 query.
      # if select only one object, then the only one object has impossible to cause N+1 query.
      def records
        result = super
        if Bullet.start?
          if result.first.class.name !~ /^HABTM_/
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Preloader.prepend(
    Module.new do
      def preloaders_for_one(association, records, scope)
        if Bullet.start?
          records.compact!
          if records.first.class.name !~ /^HABTM_/
            records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
          end
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::JoinDependency.prepend(
    Module.new do
      def instantiate(result_set, &block)
        @bullet_eager_loadings = {}
        records = super
        if Bullet.start?
          @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
            objects = eager_loadings_hash.keys
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
              objects,
              eager_loadings_hash[objects.first].to_a
            )
          end
        end
        records
      end
      def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
        if Bullet.start?
          unless ar_parent.nil?
            parent.children.each do |node|
              key = aliases.column_alias(node, node.primary_key)
              id = row[key]
              next unless id.nil?
              associations = [node.reflection.name]
              if node.reflection.through_reflection?
                associations << node.reflection.through_reflection.name
              end
              associations.each do |association|
                Bullet::Detector::Association.add_object_associations(ar_parent, association)
                Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
                @bullet_eager_loadings[ar_parent.class] ||= {}
                @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
                @bullet_eager_loadings[ar_parent.class][ar_parent] << association
              end
            end
          end
        end
        super
      end
      # call join associations
      def construct_model(record, node, row, model_cache, id, aliases)
        result = super
        if Bullet.start?
          associations = [node.reflection.name]
          if node.reflection.through_reflection?
            associations << node.reflection.through_reflection.name
          end
          associations.each do |association|
            Bullet::Detector::Association.add_object_associations(record, association)
            Bullet::Detector::NPlusOneQuery.call_association(record, association)
            @bullet_eager_loadings[record.class] ||= {}
            @bullet_eager_loadings[record.class][record] ||= Set.new
            @bullet_eager_loadings[record.class][record] << association
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Association.prepend(
    Module.new do
      def inversed_from(record)
        if Bullet.start?
          Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionAssociation.prepend(
    Module.new do
      def load_target
        records = super
        if Bullet.start?
          if is_a? ::ActiveRecord::Associations::ThroughAssociation
            association = owner.association(reflection.through_reflection.name)
            if association.loaded?
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if reflection.through_reflection != through_reflection
                Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
              end
            end
          end
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
          if records.first.class.name !~ /^HABTM_/
            if records.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
              Bullet::Detector::CounterCache.add_possible_objects(records)
            elsif records.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
              Bullet::Detector::CounterCache.add_impossible_object(records.first)
            end
          end
        end
        records
      end
      def empty?
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        super
      end
      def include?(object)
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
        super
      end
    end
  )
  ::ActiveRecord::Associations::SingularAssociation.prepend(
    Module.new do
      # call has_one and belongs_to associations
      def target
        result = super()
        if Bullet.start?
          if owner.class.name !~ /^HABTM_/ && !@inversed
            if is_a? ::ActiveRecord::Associations::ThroughAssociation
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
              association = owner.association reflection.through_reflection.name
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if reflection.through_reflection != through_reflection
                Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
              end
            end
            Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
            if Bullet::Detector::NPlusOneQuery.impossible?(owner)
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
            else
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
    Module.new do
      def empty?
        result = super
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        result
      end
      def count_records
        result = reflection.has_cached_counter?
        if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionProxy.prepend(
    Module.new do
      def count(column_name = nil)
        if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(
            proxy_association.owner,
            proxy_association.reflection.name
          )
          Bullet::Detector::NPlusOneQuery.call_association(
            proxy_association.owner,
            proxy_association.reflection.name
          )
        end
        super(column_name)
      end
    end
  )
end

def self.enable

def self.enable
  require 'active_record'
  ::ActiveRecord::Base.extend(
    Module.new do
      def find_by_sql(sql, binds = [], preparable: nil, &block)
        result = super
        if Bullet.start?
          if result.is_a? Array
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          elsif result.is_a? ::ActiveRecord::Base
            Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
            Bullet::Detector::CounterCache.add_impossible_object(result)
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Base.prepend(SaveWithBulletSupport)
  ::ActiveRecord::Relation.prepend(
    Module.new do
      # if select a collection of objects, then these objects have possible to cause N+1 query.
      # if select only one object, then the only one object has impossible to cause N+1 query.
      def records
        result = super
        if Bullet.start?
          if result.first.class.name !~ /^HABTM_/
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Preloader.prepend(
    Module.new do
      def preloaders_for_one(association, records, scope, polymorphic_parent)
        if Bullet.start?
          records.compact!
          if records.first.class.name !~ /^HABTM_/
            records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
          end
        end
        super
      end
      def preloaders_for_reflection(reflection, records, scope)
        if Bullet.start?
          records.compact!
          if records.first.class.name !~ /^HABTM_/
            records.each { |record| Bullet::Detector::Association.add_object_associations(record, reflection.name) }
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, reflection.name)
          end
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(
    Module.new do
      def preloaded_records
        if Bullet.start? && !defined?(@preloaded_records)
          source_preloaders.each do |source_preloader|
            reflection_name = source_preloader.send(:reflection).name
            source_preloader.send(:owners).each do |owner|
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
            end
          end
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::JoinDependency.prepend(
    Module.new do
      def instantiate(result_set, &block)
        @bullet_eager_loadings = {}
        records = super
        if Bullet.start?
          @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
            objects = eager_loadings_hash.keys
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
              objects,
              eager_loadings_hash[objects.first].to_a
            )
          end
        end
        records
      end
      def construct(ar_parent, parent, row, seen, model_cache)
        if Bullet.start?
          unless ar_parent.nil?
            parent.children.each do |node|
              key = aliases.column_alias(node, node.primary_key)
              id = row[key]
              next unless id.nil?
              associations = [node.reflection.name]
              if node.reflection.through_reflection?
                associations << node.reflection.through_reflection.name
              end
              associations.each do |association|
                Bullet::Detector::Association.add_object_associations(ar_parent, association)
                Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
                @bullet_eager_loadings[ar_parent.class] ||= {}
                @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
                @bullet_eager_loadings[ar_parent.class][ar_parent] << association
              end
            end
          end
        end
        super
      end
      # call join associations
      def construct_model(record, node, row, model_cache, id)
        result = super
        if Bullet.start?
          associations = [node.reflection.name]
          if node.reflection.through_reflection?
            associations << node.reflection.through_reflection.name
          end
          associations.each do |association|
            Bullet::Detector::Association.add_object_associations(record, association)
            Bullet::Detector::NPlusOneQuery.call_association(record, association)
            @bullet_eager_loadings[record.class] ||= {}
            @bullet_eager_loadings[record.class][record] ||= Set.new
            @bullet_eager_loadings[record.class][record] << association
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Association.prepend(
    Module.new do
      def inversed_from(record)
        if Bullet.start?
          Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionAssociation.prepend(
    Module.new do
      def load_target
        records = super
        if Bullet.start?
          if is_a? ::ActiveRecord::Associations::ThroughAssociation
            association = owner.association(reflection.through_reflection.name)
            if association.loaded?
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if reflection.through_reflection != through_reflection
                Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
              end
            end
          end
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
          if records.first.class.name !~ /^HABTM_/
            if records.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
              Bullet::Detector::CounterCache.add_possible_objects(records)
            elsif records.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
              Bullet::Detector::CounterCache.add_impossible_object(records.first)
            end
          end
        end
        records
      end
      def empty?
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        super
      end
      def include?(object)
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
        super
      end
    end
  )
  ::ActiveRecord::Associations::SingularAssociation.prepend(
    Module.new do
      # call has_one and belongs_to associations
      def target
        result = super()
        if Bullet.start?
          if owner.class.name !~ /^HABTM_/ && !@inversed
            if is_a? ::ActiveRecord::Associations::ThroughAssociation
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
              association = owner.association(reflection.through_reflection.name)
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if reflection.through_reflection != through_reflection
                Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
              end
            end
            Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
            if Bullet::Detector::NPlusOneQuery.impossible?(owner)
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
            else
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
    Module.new do
      def empty?
        result = super
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        result
      end
      def count_records
        result = reflection.has_cached_counter?
        if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionProxy.prepend(
    Module.new do
      def count(column_name = nil)
        if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(
            proxy_association.owner,
            proxy_association.reflection.name
          )
          Bullet::Detector::NPlusOneQuery.call_association(
            proxy_association.owner,
            proxy_association.reflection.name
          )
        end
        super(column_name)
      end
    end
  )
end

def self.enable

def self.enable
  require 'active_record'
  ::ActiveRecord::Base.extend(
    Module.new do
      def find_by_sql(sql, binds = [], preparable: nil, &block)
        result = super
        if Bullet.start?
          if result.is_a? Array
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          elsif result.is_a? ::ActiveRecord::Base
            Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
            Bullet::Detector::CounterCache.add_impossible_object(result)
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Base.prepend(SaveWithBulletSupport)
  ::ActiveRecord::Relation.prepend(
    Module.new do
      # if select a collection of objects, then these objects have possible to cause N+1 query.
      # if select only one object, then the only one object has impossible to cause N+1 query.
      def records
        result = super
        if Bullet.start?
          if result.first.class.name !~ /^HABTM_/
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Preloader.prepend(
    Module.new do
      def preloaders_for_one(association, records, scope, polymorphic_parent)
        if Bullet.start?
          records.compact!
          if records.first.class.name !~ /^HABTM_/
            records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
          end
        end
        super
      end
      def preloaders_for_reflection(reflection, records, scope)
        if Bullet.start?
          records.compact!
          if records.first.class.name !~ /^HABTM_/
            records.each { |record| Bullet::Detector::Association.add_object_associations(record, reflection.name) }
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, reflection.name)
          end
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(
    Module.new do
      def preloaded_records
        if Bullet.start? && !defined?(@preloaded_records)
          source_preloaders.each do |source_preloader|
            reflection_name = source_preloader.send(:reflection).name
            source_preloader.send(:owners).each do |owner|
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
            end
          end
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::JoinDependency.prepend(
    Module.new do
      def instantiate(result_set, strict_loading_value, &block)
        @bullet_eager_loadings = {}
        records = super
        if Bullet.start?
          @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
            objects = eager_loadings_hash.keys
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
              objects,
              eager_loadings_hash[objects.first].to_a
            )
          end
        end
        records
      end
      def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
        if Bullet.start?
          unless ar_parent.nil?
            parent.children.each do |node|
              key = aliases.column_alias(node, node.primary_key)
              id = row[key]
              next unless id.nil?
              associations = [node.reflection.name]
              if node.reflection.through_reflection?
                associations << node.reflection.through_reflection.name
              end
              associations.each do |association|
                Bullet::Detector::Association.add_object_associations(ar_parent, association)
                Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
                @bullet_eager_loadings[ar_parent.class] ||= {}
                @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
                @bullet_eager_loadings[ar_parent.class][ar_parent] << association
              end
            end
          end
        end
        super
      end
      # call join associations
      def construct_model(record, node, row, model_cache, id, strict_loading_value)
        result = super
        if Bullet.start?
          associations = [node.reflection.name]
          if node.reflection.through_reflection?
            associations << node.reflection.through_reflection.name
          end
          associations.each do |association|
            Bullet::Detector::Association.add_object_associations(record, association)
            Bullet::Detector::NPlusOneQuery.call_association(record, association)
            @bullet_eager_loadings[record.class] ||= {}
            @bullet_eager_loadings[record.class][record] ||= Set.new
            @bullet_eager_loadings[record.class][record] << association
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Association.prepend(
    Module.new do
      def inversed_from(record)
        if Bullet.start?
          Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionAssociation.prepend(
    Module.new do
      def load_target
        records = super
        if Bullet.start?
          if is_a? ::ActiveRecord::Associations::ThroughAssociation
            association = owner.association(reflection.through_reflection.name)
            if association.loaded?
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if reflection.through_reflection != through_reflection
                Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
              end
            end
          end
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
          if records.first.class.name !~ /^HABTM_/
            if records.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
              Bullet::Detector::CounterCache.add_possible_objects(records)
            elsif records.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
              Bullet::Detector::CounterCache.add_impossible_object(records.first)
            end
          end
        end
        records
      end
      def empty?
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        super
      end
      def include?(object)
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
        super
      end
    end
  )
  ::ActiveRecord::Associations::SingularAssociation.prepend(
    Module.new do
      # call has_one and belongs_to associations
      def target
        result = super()
        if Bullet.start?
          if owner.class.name !~ /^HABTM_/ && !@inversed
            if is_a? ::ActiveRecord::Associations::ThroughAssociation
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
              association = owner.association(reflection.through_reflection.name)
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if reflection.through_reflection != through_reflection
                Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
              end
            end
            Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
            if Bullet::Detector::NPlusOneQuery.impossible?(owner)
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
            else
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
    Module.new do
      def empty?
        result = super
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        result
      end
      def count_records
        result = reflection.has_cached_counter?
        if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionProxy.prepend(
    Module.new do
      def count(column_name = nil)
        if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(
            proxy_association.owner,
            proxy_association.reflection.name
          )
          Bullet::Detector::NPlusOneQuery.call_association(
            proxy_association.owner,
            proxy_association.reflection.name
          )
        end
        super(column_name)
      end
    end
  )
end

def self.enable

def self.enable
  require 'active_record'
  ::ActiveRecord::Base.extend(
    Module.new do
      def find_by_sql(sql, binds = [], preparable: nil, &block)
        result = super
        if Bullet.start?
          if result.is_a? Array
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          elsif result.is_a? ::ActiveRecord::Base
            Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
            Bullet::Detector::CounterCache.add_impossible_object(result)
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Base.prepend(SaveWithBulletSupport)
  ::ActiveRecord::Relation.prepend(
    Module.new do
      # if select a collection of objects, then these objects have possible to cause N+1 query.
      # if select only one object, then the only one object has impossible to cause N+1 query.
      def records
        result = super
        if Bullet.start?
          if result.first.class.name !~ /^HABTM_/
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Preloader::Batch.prepend(
    Module.new do
      def call
        if Bullet.start?
          @preloaders.each do |preloader|
            preloader.records.each { |record|
              Bullet::Detector::Association.add_object_associations(record, preloader.associations)
            }
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
          end
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::Preloader::Branch.prepend(
    Module.new do
      def preloaders_for_reflection(reflection, reflection_records)
        if Bullet.start?
          reflection_records.compact!
          if reflection_records.first.class.name !~ /^HABTM_/
            reflection_records.each { |record|
              Bullet::Detector::Association.add_object_associations(record, reflection.name)
            }
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
          end
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(
    Module.new do
      def source_preloaders
        if Bullet.start? && !defined?(@source_preloaders)
          preloaders = super
          preloaders.each do |preloader|
            reflection_name = preloader.send(:reflection).name
            preloader.send(:owners).each do |owner|
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
            end
          end
        else
          super
        end
      end
    end
  )
  ::ActiveRecord::Associations::JoinDependency.prepend(
    Module.new do
      def instantiate(result_set, strict_loading_value, &block)
        @bullet_eager_loadings = {}
        records = super
        if Bullet.start?
          @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
            objects = eager_loadings_hash.keys
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
              objects,
              eager_loadings_hash[objects.first].to_a
            )
          end
        end
        records
      end
      def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
        if Bullet.start?
          unless ar_parent.nil?
            parent.children.each do |node|
              key = aliases.column_alias(node, node.primary_key)
              id = row[key]
              next unless id.nil?
              associations = [node.reflection.name]
              if node.reflection.through_reflection?
                associations << node.reflection.through_reflection.name
              end
              associations.each do |association|
                Bullet::Detector::Association.add_object_associations(ar_parent, association)
                Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
                @bullet_eager_loadings[ar_parent.class] ||= {}
                @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
                @bullet_eager_loadings[ar_parent.class][ar_parent] << association
              end
            end
          end
        end
        super
      end
      # call join associations
      def construct_model(record, node, row, model_cache, id, strict_loading_value)
        result = super
        if Bullet.start?
          associations = [node.reflection.name]
          if node.reflection.through_reflection?
            associations << node.reflection.through_reflection.name
          end
          associations.each do |association|
            Bullet::Detector::Association.add_object_associations(record, association)
            Bullet::Detector::NPlusOneQuery.call_association(record, association)
            @bullet_eager_loadings[record.class] ||= {}
            @bullet_eager_loadings[record.class][record] ||= Set.new
            @bullet_eager_loadings[record.class][record] << association
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Association.prepend(
    Module.new do
      def inversed_from(record)
        if Bullet.start?
          Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
        end
        super
      end
      def inversed_from_queries(record)
        if Bullet.start? && inversable?(record)
          Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionAssociation.prepend(
    Module.new do
      def load_target
        records = super
        if Bullet.start?
          if is_a? ::ActiveRecord::Associations::ThroughAssociation
            association = owner.association(reflection.through_reflection.name)
            if association.loaded?
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if reflection.through_reflection != through_reflection
                Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
              end
            end
          end
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
          if records.first.class.name !~ /^HABTM_/
            if records.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
              Bullet::Detector::CounterCache.add_possible_objects(records)
            elsif records.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
              Bullet::Detector::CounterCache.add_impossible_object(records.first)
            end
          end
        end
        records
      end
      def empty?
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        super
      end
      def include?(object)
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
        super
      end
    end
  )
  ::ActiveRecord::Associations::SingularAssociation.prepend(
    Module.new do
      # call has_one and belongs_to associations
      def reader
        result = super
        if Bullet.start?
          if owner.class.name !~ /^HABTM_/
            if is_a? ::ActiveRecord::Associations::ThroughAssociation
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
              association = owner.association(reflection.through_reflection.name)
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if reflection.through_reflection != through_reflection
                Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
              end
            end
            Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
            if Bullet::Detector::NPlusOneQuery.impossible?(owner)
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
            else
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
    Module.new do
      def empty?
        result = super
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        result
      end
      def count_records
        result = reflection.has_cached_counter?
        if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionProxy.prepend(
    Module.new do
      def count(column_name = nil)
        if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(
            proxy_association.owner,
            proxy_association.reflection.name
          )
          Bullet::Detector::NPlusOneQuery.call_association(
            proxy_association.owner,
            proxy_association.reflection.name
          )
        end
        super(column_name)
      end
    end
  )
end

def self.enable

def self.enable
  require 'active_record'
  ::ActiveRecord::Base.extend(
    Module.new do
      def find_by_sql(sql, binds = [], preparable: nil, &block)
        result = super
        if Bullet.start?
          if result.is_a? Array
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          elsif result.is_a? ::ActiveRecord::Base
            Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
            Bullet::Detector::CounterCache.add_impossible_object(result)
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Base.prepend(SaveWithBulletSupport)
  ::ActiveRecord::Relation.prepend(
    Module.new do
      # if select a collection of objects, then these objects have possible to cause N+1 query.
      # if select only one object, then the only one object has impossible to cause N+1 query.
      def records
        result = super
        if Bullet.start?
          if result.first.class.name !~ /^HABTM_/
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Preloader::Batch.prepend(
    Module.new do
      def call
        if Bullet.start?
          @preloaders.each do |preloader|
            preloader.records.each { |record|
              Bullet::Detector::Association.add_object_associations(record, preloader.associations)
            }
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
          end
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::Preloader::Branch.prepend(
    Module.new do
      def preloaders_for_reflection(reflection, reflection_records)
        if Bullet.start?
          reflection_records.compact!
          if reflection_records.first.class.name !~ /^HABTM_/
            reflection_records.each { |record|
              Bullet::Detector::Association.add_object_associations(record, reflection.name)
            }
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
          end
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(
    Module.new do
      def source_preloaders
        if Bullet.start? && !defined?(@source_preloaders)
          preloaders = super
          preloaders.each do |preloader|
            reflection_name = preloader.send(:reflection).name
            preloader.send(:owners).each do |owner|
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
            end
          end
        else
          super
        end
      end
    end
  )
  ::ActiveRecord::Associations::JoinDependency.prepend(
    Module.new do
      def instantiate(result_set, strict_loading_value, &block)
        @bullet_eager_loadings = {}
        records = super
        if Bullet.start?
          @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
            objects = eager_loadings_hash.keys
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
              objects,
              eager_loadings_hash[objects.first].to_a
            )
          end
        end
        records
      end
      def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
        if Bullet.start?
          unless ar_parent.nil?
            parent.children.each do |node|
              key = aliases.column_alias(node, node.primary_key)
              id = row[key]
              next unless id.nil?
              associations = [node.reflection.name]
              if node.reflection.through_reflection?
                associations << node.reflection.through_reflection.name
              end
              associations.each do |association|
                Bullet::Detector::Association.add_object_associations(ar_parent, association)
                Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
                @bullet_eager_loadings[ar_parent.class] ||= {}
                @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
                @bullet_eager_loadings[ar_parent.class][ar_parent] << association
              end
            end
          end
        end
        super
      end
      # call join associations
      def construct_model(record, node, row, model_cache, id, strict_loading_value)
        result = super
        if Bullet.start?
          associations = [node.reflection.name]
          if node.reflection.through_reflection?
            associations << node.reflection.through_reflection.name
          end
          associations.each do |association|
            Bullet::Detector::Association.add_object_associations(record, association)
            Bullet::Detector::NPlusOneQuery.call_association(record, association)
            @bullet_eager_loadings[record.class] ||= {}
            @bullet_eager_loadings[record.class][record] ||= Set.new
            @bullet_eager_loadings[record.class][record] << association
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Association.prepend(
    Module.new do
      def inversed_from(record)
        if Bullet.start?
          Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
        end
        super
      end
      def inversed_from_queries(record)
        if Bullet.start? && inversable?(record)
          Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionAssociation.prepend(
    Module.new do
      def load_target
        records = super
        if Bullet.start?
          if is_a? ::ActiveRecord::Associations::ThroughAssociation
            association = owner.association(reflection.through_reflection.name)
            if association.loaded?
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if reflection.through_reflection != through_reflection
                Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
              end
            end
          end
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
          if records.first.class.name !~ /^HABTM_/
            if records.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
              Bullet::Detector::CounterCache.add_possible_objects(records)
            elsif records.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
              Bullet::Detector::CounterCache.add_impossible_object(records.first)
            end
          end
        end
        records
      end
      def empty?
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        super
      end
      def include?(object)
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
        super
      end
    end
  )
  ::ActiveRecord::Associations::SingularAssociation.prepend(
    Module.new do
      # call has_one and belongs_to associations
      def reader
        result = super
        if Bullet.start?
          if owner.class.name !~ /^HABTM_/
            if is_a? ::ActiveRecord::Associations::ThroughAssociation
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
              association = owner.association(reflection.through_reflection.name)
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if reflection.through_reflection != through_reflection
                Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
              end
            end
            Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
            if Bullet::Detector::NPlusOneQuery.impossible?(owner)
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
            else
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
    Module.new do
      def empty?
        result = super
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        result
      end
      def count_records
        result = reflection.has_cached_counter?
        if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionProxy.prepend(
    Module.new do
      def count(column_name = nil)
        if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(
            proxy_association.owner,
            proxy_association.reflection.name
          )
          Bullet::Detector::NPlusOneQuery.call_association(
            proxy_association.owner,
            proxy_association.reflection.name
          )
        end
        super(column_name)
      end
    end
  )
end

def self.enable

def self.enable
  require 'active_record'
  ::ActiveRecord::Base.extend(
    Module.new do
      def find_by_sql(sql, binds = [], preparable: nil, allow_retry: false, &block)
        result = super
        if Bullet.start?
          if result.is_a? Array
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          elsif result.is_a? ::ActiveRecord::Base
            Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
            Bullet::Detector::CounterCache.add_impossible_object(result)
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Base.prepend(SaveWithBulletSupport)
  ::ActiveRecord::Relation.prepend(
    Module.new do
      # if select a collection of objects, then these objects have possible to cause N+1 query.
      # if select only one object, then the only one object has impossible to cause N+1 query.
      def records
        result = super
        if Bullet.start?
          if result.first.class.name !~ /^HABTM_/
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Preloader::Batch.prepend(
    Module.new do
      def call
        if Bullet.start?
          @preloaders.each do |preloader|
            preloader.records.each { |record|
              Bullet::Detector::Association.add_object_associations(record, preloader.associations)
            }
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
          end
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::Preloader::Branch.prepend(
    Module.new do
      def preloaders_for_reflection(reflection, reflection_records)
        if Bullet.start?
          reflection_records.compact!
          if reflection_records.first.class.name !~ /^HABTM_/
            reflection_records.each { |record|
              Bullet::Detector::Association.add_object_associations(record, reflection.name)
            }
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
          end
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(
    Module.new do
      def source_preloaders
        if Bullet.start? && !defined?(@source_preloaders)
          preloaders = super
          preloaders.each do |preloader|
            reflection_name = preloader.send(:reflection).name
            preloader.send(:owners).each do |owner|
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
            end
          end
        else
          super
        end
      end
    end
  )
  ::ActiveRecord::Associations::JoinDependency.prepend(
    Module.new do
      def instantiate(result_set, strict_loading_value, &block)
        @bullet_eager_loadings = {}
        records = super
        if Bullet.start?
          @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
            objects = eager_loadings_hash.keys
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
              objects,
              eager_loadings_hash[objects.first].to_a
            )
          end
        end
        records
      end
      def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
        if Bullet.start?
          unless ar_parent.nil?
            parent.children.each do |node|
              key = aliases.column_alias(node, node.primary_key)
              id = row[key]
              next unless id.nil?
              associations = [node.reflection.name]
              if node.reflection.through_reflection?
                associations << node.reflection.through_reflection.name
              end
              associations.each do |association|
                Bullet::Detector::Association.add_object_associations(ar_parent, association)
                Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
                @bullet_eager_loadings[ar_parent.class] ||= {}
                @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
                @bullet_eager_loadings[ar_parent.class][ar_parent] << association
              end
            end
          end
        end
        super
      end
      # call join associations
      def construct_model(record, node, row, model_cache, id, strict_loading_value)
        result = super
        if Bullet.start?
          associations = [node.reflection.name]
          if node.reflection.through_reflection?
            associations << node.reflection.through_reflection.name
          end
          associations.each do |association|
            Bullet::Detector::Association.add_object_associations(record, association)
            Bullet::Detector::NPlusOneQuery.call_association(record, association)
            @bullet_eager_loadings[record.class] ||= {}
            @bullet_eager_loadings[record.class][record] ||= Set.new
            @bullet_eager_loadings[record.class][record] << association
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Association.prepend(
    Module.new do
      def inversed_from(record)
        if Bullet.start?
          Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
        end
        super
      end
      def inversed_from_queries(record)
        if Bullet.start? && inversable?(record)
          Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionAssociation.prepend(
    Module.new do
      def load_target
        records = super
        if Bullet.start?
          if is_a? ::ActiveRecord::Associations::ThroughAssociation
            association = owner.association(reflection.through_reflection.name)
            if association.loaded?
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if reflection.through_reflection != through_reflection
                Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
              end
            end
          end
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
          if records.first.class.name !~ /^HABTM_/
            if records.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
              Bullet::Detector::CounterCache.add_possible_objects(records)
            elsif records.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
              Bullet::Detector::CounterCache.add_impossible_object(records.first)
            end
          end
        end
        records
      end
      def empty?
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        super
      end
      def include?(object)
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
        super
      end
    end
  )
  ::ActiveRecord::Associations::SingularAssociation.prepend(
    Module.new do
      # call has_one and belongs_to associations
      def reader
        result = super
        if Bullet.start?
          if owner.class.name !~ /^HABTM_/
            if is_a? ::ActiveRecord::Associations::ThroughAssociation
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
              association = owner.association(reflection.through_reflection.name)
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if reflection.through_reflection != through_reflection
                Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
              end
            end
            Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
            if Bullet::Detector::NPlusOneQuery.impossible?(owner)
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
            else
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
    Module.new do
      def empty?
        result = super
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        result
      end
      def count_records
        result = reflection.has_cached_counter?
        if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionProxy.prepend(
    Module.new do
      def count(column_name = nil)
        if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(
            proxy_association.owner,
            proxy_association.reflection.name
          )
          Bullet::Detector::NPlusOneQuery.call_association(
            proxy_association.owner,
            proxy_association.reflection.name
          )
        end
        super(column_name)
      end
    end
  )
end

def self.enable

def self.enable
  require 'active_record'
  ::ActiveRecord::Base.extend(
    Module.new do
      def find_by_sql(sql, binds = [], preparable: nil, allow_retry: false, &block)
        result = super
        if Bullet.start?
          if result.is_a? Array
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          elsif result.is_a? ::ActiveRecord::Base
            Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
            Bullet::Detector::CounterCache.add_impossible_object(result)
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Base.prepend(SaveWithBulletSupport)
  ::ActiveRecord::Relation.prepend(
    Module.new do
      # if select a collection of objects, then these objects have possible to cause N+1 query.
      # if select only one object, then the only one object has impossible to cause N+1 query.
      def records
        result = super
        if Bullet.start?
          if result.first.class.name !~ /^HABTM_/
            if result.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
              Bullet::Detector::CounterCache.add_possible_objects(result)
            elsif result.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
              Bullet::Detector::CounterCache.add_impossible_object(result.first)
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Preloader::Batch.prepend(
    Module.new do
      def call
        if Bullet.start?
          @preloaders.each do |preloader|
            preloader.records.each { |record|
              Bullet::Detector::Association.add_object_associations(record, preloader.associations)
            }
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
          end
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::Preloader::Branch.prepend(
    Module.new do
      def preloaders_for_reflection(reflection, reflection_records)
        if Bullet.start?
          reflection_records.compact!
          if reflection_records.first.class.name !~ /^HABTM_/
            reflection_records.each { |record|
              Bullet::Detector::Association.add_object_associations(record, reflection.name)
            }
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
          end
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(
    Module.new do
      def source_preloaders
        if Bullet.start? && !defined?(@source_preloaders)
          preloaders = super
          preloaders.each do |preloader|
            reflection_name = preloader.send(:reflection).name
            preloader.send(:owners).each do |owner|
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
            end
          end
        else
          super
        end
      end
    end
  )
  ::ActiveRecord::Associations::JoinDependency.prepend(
    Module.new do
      def instantiate(result_set, strict_loading_value, &block)
        @bullet_eager_loadings = {}
        records = super
        if Bullet.start?
          @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
            objects = eager_loadings_hash.keys
            Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
              objects,
              eager_loadings_hash[objects.first].to_a
            )
          end
        end
        records
      end
      def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
        if Bullet.start?
          unless ar_parent.nil?
            parent.children.each do |node|
              key = aliases.column_alias(node, node.primary_key)
              id = row[key]
              next unless id.nil?
              associations = [node.reflection.name]
              if node.reflection.through_reflection?
                associations << node.reflection.through_reflection.name
              end
              associations.each do |association|
                Bullet::Detector::Association.add_object_associations(ar_parent, association)
                Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
                @bullet_eager_loadings[ar_parent.class] ||= {}
                @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
                @bullet_eager_loadings[ar_parent.class][ar_parent] << association
              end
            end
          end
        end
        super
      end
      # call join associations
      def construct_model(record, node, row, model_cache, id, strict_loading_value)
        result = super
        if Bullet.start?
          associations = [node.reflection.name]
          if node.reflection.through_reflection?
            associations << node.reflection.through_reflection.name
          end
          associations.each do |association|
            Bullet::Detector::Association.add_object_associations(record, association)
            Bullet::Detector::NPlusOneQuery.call_association(record, association)
            @bullet_eager_loadings[record.class] ||= {}
            @bullet_eager_loadings[record.class][record] ||= Set.new
            @bullet_eager_loadings[record.class][record] << association
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::Association.prepend(
    Module.new do
      def inversed_from(record)
        if Bullet.start?
          Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
        end
        super
      end
      def inversed_from_queries(record)
        if Bullet.start? && inversable?(record)
          Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionAssociation.prepend(
    Module.new do
      def load_target
        records = super
        if Bullet.start?
          if is_a? ::ActiveRecord::Associations::ThroughAssociation
            association = owner.association(reflection.through_reflection.name)
            if association.loaded?
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if reflection.through_reflection != through_reflection
                Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
              end
            end
          end
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
          if records.first.class.name !~ /^HABTM_/
            if records.size > 1
              Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
              Bullet::Detector::CounterCache.add_possible_objects(records)
            elsif records.size == 1
              Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
              Bullet::Detector::CounterCache.add_impossible_object(records.first)
            end
          end
        end
        records
      end
      def empty?
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        super
      end
      def include?(object)
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
        super
      end
    end
  )
  ::ActiveRecord::Associations::SingularAssociation.prepend(
    Module.new do
      # call has_one and belongs_to associations
      def reader
        result = super
        if Bullet.start?
          if owner.class.name !~ /^HABTM_/
            if is_a? ::ActiveRecord::Associations::ThroughAssociation
              Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
              association = owner.association(reflection.through_reflection.name)
              Array.wrap(association.target).each do |through_record|
                Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
              end
              if reflection.through_reflection != through_reflection
                Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
              end
            end
            Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
            if Bullet::Detector::NPlusOneQuery.impossible?(owner)
              Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
            else
              Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
            end
          end
        end
        result
      end
    end
  )
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
    Module.new do
      def empty?
        result = super
        if Bullet.start? && !reflection.has_cached_counter?
          Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
        end
        result
      end
      def count_records
        result = reflection.has_cached_counter?
        if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
        end
        super
      end
    end
  )
  ::ActiveRecord::Associations::CollectionProxy.prepend(
    Module.new do
      def count(column_name = nil)
        if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
          Bullet::Detector::CounterCache.add_counter_cache(
            proxy_association.owner,
            proxy_association.reflection.name
          )
          Bullet::Detector::NPlusOneQuery.call_association(
            proxy_association.owner,
            proxy_association.reflection.name
          )
        end
        super(column_name)
      end
    end
  )
end

def _create_record_with_bullet(*args)

def _create_record_with_bullet(*args)
  _create_record_without_bullet(*args).tap do
    Bullet::Detector::NPlusOneQuery.update_inversed_object(self)
    Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
  end
end

def _create_record_with_bullet(*args)

def _create_record_with_bullet(*args)
  _create_record_without_bullet(*args).tap do
    Bullet::Detector::NPlusOneQuery.update_inversed_object(self)
    Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
  end
end

def _create_record_with_bullet(*args)

def _create_record_with_bullet(*args)
  _create_record_without_bullet(*args).tap do
    Bullet::Detector::NPlusOneQuery.update_inversed_object(self)
    Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
  end
end

def call

def call
  if Bullet.start?
    @preloaders.each do |preloader|
      preloader.records.each { |record|
        Bullet::Detector::Association.add_object_associations(record, preloader.associations)
      }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
    end
  end
  super
end

def call

def call
  if Bullet.start?
    @preloaders.each do |preloader|
      preloader.records.each { |record|
        Bullet::Detector::Association.add_object_associations(record, preloader.associations)
      }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
    end
  end
  super
end

def call

def call
  if Bullet.start?
    @preloaders.each do |preloader|
      preloader.records.each { |record|
        Bullet::Detector::Association.add_object_associations(record, preloader.associations)
      }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
    end
  end
  super
end

def call

def call
  if Bullet.start?
    @preloaders.each do |preloader|
      preloader.records.each { |record|
        Bullet::Detector::Association.add_object_associations(record, preloader.associations)
      }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
    end
  end
  super
end

def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)

def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
  if Bullet.start?
    unless ar_parent.nil?
      parent.children.each do |node|
        key = aliases.column_alias(node, node.primary_key)
        id = row[key]
        next unless id.nil?
        associations = [node.reflection.name]
        if node.reflection.nested?
          associations << node.reflection.through_reflection.name
        end
        associations.each do |association|
          Bullet::Detector::Association.add_object_associations(ar_parent, association)
          Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
          @bullet_eager_loadings[ar_parent.class] ||= {}
          @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
          @bullet_eager_loadings[ar_parent.class][ar_parent] << association
        end
      end
    end
  end
  origin_construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
end

def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)

def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
  if Bullet.start?
    unless ar_parent.nil?
      parent.children.each do |node|
        key = aliases.column_alias(node, node.primary_key)
        id = row[key]
        next unless id.nil?
        associations = [node.reflection.name]
        if node.reflection.through_reflection?
          associations << node.reflection.through_reflection.name
        end
        associations.each do |association|
          Bullet::Detector::Association.add_object_associations(ar_parent, association)
          Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
          @bullet_eager_loadings[ar_parent.class] ||= {}
          @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
          @bullet_eager_loadings[ar_parent.class][ar_parent] << association
        end
      end
    end
  end
  super
end

def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)

def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
  if Bullet.start?
    unless ar_parent.nil?
      parent.children.each do |node|
        key = aliases.column_alias(node, node.primary_key)
        id = row[key]
        next unless id.nil?
        associations = [node.reflection.name]
        if node.reflection.through_reflection?
          associations << node.reflection.through_reflection.name
        end
        associations.each do |association|
          Bullet::Detector::Association.add_object_associations(ar_parent, association)
          Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
          @bullet_eager_loadings[ar_parent.class] ||= {}
          @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
          @bullet_eager_loadings[ar_parent.class][ar_parent] << association
        end
      end
    end
  end
  super
end

def construct(ar_parent, parent, row, seen, model_cache)

def construct(ar_parent, parent, row, seen, model_cache)
  if Bullet.start?
    unless ar_parent.nil?
      parent.children.each do |node|
        key = aliases.column_alias(node, node.primary_key)
        id = row[key]
        next unless id.nil?
        associations = [node.reflection.name]
        if node.reflection.through_reflection?
          associations << node.reflection.through_reflection.name
        end
        associations.each do |association|
          Bullet::Detector::Association.add_object_associations(ar_parent, association)
          Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
          @bullet_eager_loadings[ar_parent.class] ||= {}
          @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
          @bullet_eager_loadings[ar_parent.class][ar_parent] << association
        end
      end
    end
  end
  super
end

def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)

def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
  if Bullet.start?
    unless ar_parent.nil?
      parent.children.each do |node|
        key = aliases.column_alias(node, node.primary_key)
        id = row[key]
        next unless id.nil?
        associations = [node.reflection.name]
        if node.reflection.through_reflection?
          associations << node.reflection.through_reflection.name
        end
        associations.each do |association|
          Bullet::Detector::Association.add_object_associations(ar_parent, association)
          Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
          @bullet_eager_loadings[ar_parent.class] ||= {}
          @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
          @bullet_eager_loadings[ar_parent.class][ar_parent] << association
        end
      end
    end
  end
  super
end

def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)

def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
  if Bullet.start?
    unless ar_parent.nil?
      parent.children.each do |node|
        key = aliases.column_alias(node, node.primary_key)
        id = row[key]
        next unless id.nil?
        associations = [node.reflection.name]
        if node.reflection.through_reflection?
          associations << node.reflection.through_reflection.name
        end
        associations.each do |association|
          Bullet::Detector::Association.add_object_associations(ar_parent, association)
          Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
          @bullet_eager_loadings[ar_parent.class] ||= {}
          @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
          @bullet_eager_loadings[ar_parent.class][ar_parent] << association
        end
      end
    end
  end
  super
end

def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)

def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
  if Bullet.start?
    unless ar_parent.nil?
      parent.children.each do |node|
        key = aliases.column_alias(node, node.primary_key)
        id = row[key]
        next unless id.nil?
        associations = [node.reflection.name]
        if node.reflection.through_reflection?
          associations << node.reflection.through_reflection.name
        end
        associations.each do |association|
          Bullet::Detector::Association.add_object_associations(ar_parent, association)
          Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
          @bullet_eager_loadings[ar_parent.class] ||= {}
          @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
          @bullet_eager_loadings[ar_parent.class][ar_parent] << association
        end
      end
    end
  end
  super
end

def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)

def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
  if Bullet.start?
    unless ar_parent.nil?
      parent.children.each do |node|
        key = aliases.column_alias(node, node.primary_key)
        id = row[key]
        next unless id.nil?
        associations = [node.reflection.name]
        if node.reflection.through_reflection?
          associations << node.reflection.through_reflection.name
        end
        associations.each do |association|
          Bullet::Detector::Association.add_object_associations(ar_parent, association)
          Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
          @bullet_eager_loadings[ar_parent.class] ||= {}
          @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
          @bullet_eager_loadings[ar_parent.class][ar_parent] << association
        end
      end
    end
  end
  super
end

def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)

def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
  if Bullet.start?
    unless ar_parent.nil?
      parent.children.each do |node|
        key = aliases.column_alias(node, node.primary_key)
        id = row[key]
        next unless id.nil?
        associations = [node.reflection.name]
        if node.reflection.through_reflection?
          associations << node.reflection.through_reflection.name
        end
        associations.each do |association|
          Bullet::Detector::Association.add_object_associations(ar_parent, association)
          Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
          @bullet_eager_loadings[ar_parent.class] ||= {}
          @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
          @bullet_eager_loadings[ar_parent.class][ar_parent] << association
        end
      end
    end
  end
  super
end

def construct_association(record, join, row)

call join associations
def construct_association(record, join, row)
  result = origin_construct_association(record, join, row)
  if Bullet.start?
    associations = [join.reflection.name]
    if join.reflection.nested?
      associations << join.reflection.through_reflection.name
    end
    associations.each do |association|
      Bullet::Detector::Association.add_object_associations(record, association)
      Bullet::Detector::NPlusOneQuery.call_association(record, association)
      @bullet_eager_loadings[record.class] ||= {}
      @bullet_eager_loadings[record.class][record] ||= Set.new
      @bullet_eager_loadings[record.class][record] << association
    end
  end
  result
end

def construct_model(record, node, row, model_cache, id, aliases)

call join associations
def construct_model(record, node, row, model_cache, id, aliases)
  result = origin_construct_model(record, node, row, model_cache, id, aliases)
  if Bullet.start?
    associations = [node.reflection.name]
    if node.reflection.nested?
      associations << node.reflection.through_reflection.name
    end
    associations.each do |association|
      Bullet::Detector::Association.add_object_associations(record, association)
      Bullet::Detector::NPlusOneQuery.call_association(record, association)
      @bullet_eager_loadings[record.class] ||= {}
      @bullet_eager_loadings[record.class][record] ||= Set.new
      @bullet_eager_loadings[record.class][record] << association
    end
  end
  result
end

def construct_model(record, node, row, model_cache, id, aliases)

call join associations
def construct_model(record, node, row, model_cache, id, aliases)
  result = origin_construct_model(record, node, row, model_cache, id, aliases)
  if Bullet.start?
    associations = [node.reflection.name]
    if node.reflection.nested?
      associations << node.reflection.through_reflection.name
    end
    associations.each do |association|
      Bullet::Detector::Association.add_object_associations(record, association)
      Bullet::Detector::NPlusOneQuery.call_association(record, association)
      @bullet_eager_loadings[record.class] ||= {}
      @bullet_eager_loadings[record.class][record] ||= Set.new
      @bullet_eager_loadings[record.class][record] << association
    end
  end
  result
end

def construct_model(record, node, row, model_cache, id, aliases)

call join associations
def construct_model(record, node, row, model_cache, id, aliases)
  result = super
  if Bullet.start?
    associations = [node.reflection.name]
    if node.reflection.through_reflection?
      associations << node.reflection.through_reflection.name
    end
    associations.each do |association|
      Bullet::Detector::Association.add_object_associations(record, association)
      Bullet::Detector::NPlusOneQuery.call_association(record, association)
      @bullet_eager_loadings[record.class] ||= {}
      @bullet_eager_loadings[record.class][record] ||= Set.new
      @bullet_eager_loadings[record.class][record] << association
    end
  end
  result
end

def construct_model(record, node, row, model_cache, id, aliases)

call join associations
def construct_model(record, node, row, model_cache, id, aliases)
  result = super
  if Bullet.start?
    associations = [node.reflection.name]
    if node.reflection.through_reflection?
      associations << node.reflection.through_reflection.name
    end
    associations.each do |association|
      Bullet::Detector::Association.add_object_associations(record, association)
      Bullet::Detector::NPlusOneQuery.call_association(record, association)
      @bullet_eager_loadings[record.class] ||= {}
      @bullet_eager_loadings[record.class][record] ||= Set.new
      @bullet_eager_loadings[record.class][record] << association
    end
  end
  result
end

def construct_model(record, node, row, model_cache, id)

call join associations
def construct_model(record, node, row, model_cache, id)
  result = super
  if Bullet.start?
    associations = [node.reflection.name]
    if node.reflection.through_reflection?
      associations << node.reflection.through_reflection.name
    end
    associations.each do |association|
      Bullet::Detector::Association.add_object_associations(record, association)
      Bullet::Detector::NPlusOneQuery.call_association(record, association)
      @bullet_eager_loadings[record.class] ||= {}
      @bullet_eager_loadings[record.class][record] ||= Set.new
      @bullet_eager_loadings[record.class][record] << association
    end
  end
  result
end

def construct_model(record, node, row, model_cache, id, strict_loading_value)

call join associations
def construct_model(record, node, row, model_cache, id, strict_loading_value)
  result = super
  if Bullet.start?
    associations = [node.reflection.name]
    if node.reflection.through_reflection?
      associations << node.reflection.through_reflection.name
    end
    associations.each do |association|
      Bullet::Detector::Association.add_object_associations(record, association)
      Bullet::Detector::NPlusOneQuery.call_association(record, association)
      @bullet_eager_loadings[record.class] ||= {}
      @bullet_eager_loadings[record.class][record] ||= Set.new
      @bullet_eager_loadings[record.class][record] << association
    end
  end
  result
end

def construct_model(record, node, row, model_cache, id, strict_loading_value)

call join associations
def construct_model(record, node, row, model_cache, id, strict_loading_value)
  result = super
  if Bullet.start?
    associations = [node.reflection.name]
    if node.reflection.through_reflection?
      associations << node.reflection.through_reflection.name
    end
    associations.each do |association|
      Bullet::Detector::Association.add_object_associations(record, association)
      Bullet::Detector::NPlusOneQuery.call_association(record, association)
      @bullet_eager_loadings[record.class] ||= {}
      @bullet_eager_loadings[record.class][record] ||= Set.new
      @bullet_eager_loadings[record.class][record] << association
    end
  end
  result
end

def construct_model(record, node, row, model_cache, id, strict_loading_value)

call join associations
def construct_model(record, node, row, model_cache, id, strict_loading_value)
  result = super
  if Bullet.start?
    associations = [node.reflection.name]
    if node.reflection.through_reflection?
      associations << node.reflection.through_reflection.name
    end
    associations.each do |association|
      Bullet::Detector::Association.add_object_associations(record, association)
      Bullet::Detector::NPlusOneQuery.call_association(record, association)
      @bullet_eager_loadings[record.class] ||= {}
      @bullet_eager_loadings[record.class][record] ||= Set.new
      @bullet_eager_loadings[record.class][record] << association
    end
  end
  result
end

def construct_model(record, node, row, model_cache, id, strict_loading_value)

call join associations
def construct_model(record, node, row, model_cache, id, strict_loading_value)
  result = super
  if Bullet.start?
    associations = [node.reflection.name]
    if node.reflection.through_reflection?
      associations << node.reflection.through_reflection.name
    end
    associations.each do |association|
      Bullet::Detector::Association.add_object_associations(record, association)
      Bullet::Detector::NPlusOneQuery.call_association(record, association)
      @bullet_eager_loadings[record.class] ||= {}
      @bullet_eager_loadings[record.class][record] ||= Set.new
      @bullet_eager_loadings[record.class][record] << association
    end
  end
  result
end

def construct_model(record, node, row, model_cache, id, strict_loading_value)

call join associations
def construct_model(record, node, row, model_cache, id, strict_loading_value)
  result = super
  if Bullet.start?
    associations = [node.reflection.name]
    if node.reflection.through_reflection?
      associations << node.reflection.through_reflection.name
    end
    associations.each do |association|
      Bullet::Detector::Association.add_object_associations(record, association)
      Bullet::Detector::NPlusOneQuery.call_association(record, association)
      @bullet_eager_loadings[record.class] ||= {}
      @bullet_eager_loadings[record.class][record] ||= Set.new
      @bullet_eager_loadings[record.class][record] << association
    end
  end
  result
end

def count(column_name = nil, options = {})

def count(column_name = nil, options = {})
  if Bullet.start?
    Bullet::Detector::CounterCache.add_counter_cache(proxy_association.owner, proxy_association.reflection.name)
    Bullet::Detector::NPlusOneQuery.call_association(proxy_association.owner, proxy_association.reflection.name)
  end
  super(column_name, options)
end

def count(column_name = nil, options = {})

def count(column_name = nil, options = {})
  if Bullet.start?
    Bullet::Detector::CounterCache.add_counter_cache(proxy_association.owner, proxy_association.reflection.name)
    Bullet::Detector::NPlusOneQuery.call_association(proxy_association.owner, proxy_association.reflection.name)
  end
  super(column_name, options)
end

def count(column_name = nil, options = {})

def count(column_name = nil, options = {})
  if Bullet.start?
    Bullet::Detector::CounterCache.add_counter_cache(proxy_association.owner, proxy_association.reflection.name)
    Bullet::Detector::NPlusOneQuery.call_association(proxy_association.owner, proxy_association.reflection.name)
  end
  super(column_name, options)
end

def count(column_name = nil)

def count(column_name = nil)
  if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(
      proxy_association.owner,
      proxy_association.reflection.name
    )
    Bullet::Detector::NPlusOneQuery.call_association(
      proxy_association.owner,
      proxy_association.reflection.name
    )
  end
  super(column_name)
end

def count(column_name = nil)

def count(column_name = nil)
  if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(
      proxy_association.owner,
      proxy_association.reflection.name
    )
    Bullet::Detector::NPlusOneQuery.call_association(
      proxy_association.owner,
      proxy_association.reflection.name
    )
  end
  super(column_name)
end

def count(column_name = nil)

def count(column_name = nil)
  if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(
      proxy_association.owner,
      proxy_association.reflection.name
    )
    Bullet::Detector::NPlusOneQuery.call_association(
      proxy_association.owner,
      proxy_association.reflection.name
    )
  end
  super(column_name)
end

def count(column_name = nil)

def count(column_name = nil)
  if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(
      proxy_association.owner,
      proxy_association.reflection.name
    )
    Bullet::Detector::NPlusOneQuery.call_association(
      proxy_association.owner,
      proxy_association.reflection.name
    )
  end
  super(column_name)
end

def count(column_name = nil)

def count(column_name = nil)
  if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(
      proxy_association.owner,
      proxy_association.reflection.name
    )
    Bullet::Detector::NPlusOneQuery.call_association(
      proxy_association.owner,
      proxy_association.reflection.name
    )
  end
  super(column_name)
end

def count(column_name = nil)

def count(column_name = nil)
  if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(
      proxy_association.owner,
      proxy_association.reflection.name
    )
    Bullet::Detector::NPlusOneQuery.call_association(
      proxy_association.owner,
      proxy_association.reflection.name
    )
  end
  super(column_name)
end

def count(column_name = nil)

def count(column_name = nil)
  if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(
      proxy_association.owner,
      proxy_association.reflection.name
    )
    Bullet::Detector::NPlusOneQuery.call_association(
      proxy_association.owner,
      proxy_association.reflection.name
    )
  end
  super(column_name)
end

def count(column_name = nil)

def count(column_name = nil)
  if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(
      proxy_association.owner,
      proxy_association.reflection.name
    )
    Bullet::Detector::NPlusOneQuery.call_association(
      proxy_association.owner,
      proxy_association.reflection.name
    )
  end
  super(column_name)
end

def count_records

def count_records
  result = has_cached_counter?
  Bullet::Detector::CounterCache.add_counter_cache(@owner, @reflection.name) if Bullet.start? && !result
  origin_count_records
end

def count_records

def count_records
  result = has_cached_counter?
  Bullet::Detector::CounterCache.add_counter_cache(@owner, @reflection.name) if Bullet.start? && !result
  origin_count_records
end

def count_records

def count_records
  result = reflection.has_cached_counter?
  if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
  end
  super
end

def count_records

def count_records
  result = reflection.has_cached_counter?
  if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
  end
  super
end

def count_records

def count_records
  result = reflection.has_cached_counter?
  if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
  end
  super
end

def count_records

def count_records
  result = reflection.has_cached_counter?
  if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
  end
  super
end

def count_records

def count_records
  result = reflection.has_cached_counter?
  if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
  end
  super
end

def count_records

def count_records
  result = reflection.has_cached_counter?
  if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
  end
  super
end

def count_records

def count_records
  result = reflection.has_cached_counter?
  if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
  end
  super
end

def count_records

def count_records
  result = reflection.has_cached_counter?
  if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
    Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
  end
  super
end

def empty?

def empty?
  if Bullet.start? && !loaded? && !has_cached_counter?(@reflection)
    Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
  end
  origin_empty?
end

def empty?

def empty?
  Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start? && !loaded?
  origin_empty?
end

def empty?

def empty?
  if Bullet.start? && !has_cached_counter?(@reflection)
    Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
  end
  origin_empty?
end

def empty?

def empty?
  if Bullet.start? && !has_cached_counter?(@reflection)
    Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
  end
  origin_empty?
end

def empty?

def empty?
  result = origin_many_empty?
  if Bullet.start? && !has_cached_counter?(@reflection)
    Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
  end
  result
end

def empty?

def empty?
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  super
end

def empty?

def empty?
  result = super
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  result
end

def empty?

def empty?
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  super
end

def empty?

def empty?
  result = super
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  result
end

def empty?

def empty?
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  super
end

def empty?

def empty?
  result = super
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  result
end

def empty?

def empty?
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  super
end

def empty?

def empty?
  result = super
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  result
end

def empty?

def empty?
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  super
end

def empty?

def empty?
  result = super
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  result
end

def empty?

def empty?
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  super
end

def empty?

def empty?
  result = super
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  result
end

def empty?

def empty?
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  super
end

def empty?

def empty?
  result = super
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  result
end

def empty?

def empty?
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  super
end

def empty?

def empty?
  result = super
  if Bullet.start? && !reflection.has_cached_counter?
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
  end
  result
end

def find(*args)

def find(*args)
  result = origin_find(*args)
  if Bullet.start?
    if result.is_a? Array
      Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
      Bullet::Detector::CounterCache.add_possible_objects(result)
    elsif result.is_a? ::ActiveRecord::Base
      Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
      Bullet::Detector::CounterCache.add_impossible_object(result)
    end
  end
  result
end

def find_by_sql(sql, binds = [])

def find_by_sql(sql, binds = [])
  result = origin_find_by_sql(sql, binds)
  if Bullet.start?
    if result.is_a? Array
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    elsif result.is_a? ::ActiveRecord::Base
      Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
      Bullet::Detector::CounterCache.add_impossible_object(result)
    end
  end
  result
end

def find_by_sql(sql, binds = [])

def find_by_sql(sql, binds = [])
  result = origin_find_by_sql(sql, binds)
  if Bullet.start?
    if result.is_a? Array
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    elsif result.is_a? ::ActiveRecord::Base
      Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
      Bullet::Detector::CounterCache.add_impossible_object(result)
    end
  end
  result
end

def find_by_sql(sql, binds = [])

def find_by_sql(sql, binds = [])
  result = origin_find_by_sql(sql, binds)
  if Bullet.start?
    if result.is_a? Array
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    elsif result.is_a? ::ActiveRecord::Base
      Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
      Bullet::Detector::CounterCache.add_impossible_object(result)
    end
  end
  result
end

def find_by_sql(sql, binds = [], preparable: nil, &block)

def find_by_sql(sql, binds = [], preparable: nil, &block)
  result = super
  if Bullet.start?
    if result.is_a? Array
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    elsif result.is_a? ::ActiveRecord::Base
      Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
      Bullet::Detector::CounterCache.add_impossible_object(result)
    end
  end
  result
end

def find_by_sql(sql, binds = [], preparable: nil, &block)

def find_by_sql(sql, binds = [], preparable: nil, &block)
  result = super
  if Bullet.start?
    if result.is_a? Array
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    elsif result.is_a? ::ActiveRecord::Base
      Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
      Bullet::Detector::CounterCache.add_impossible_object(result)
    end
  end
  result
end

def find_by_sql(sql, binds = [], preparable: nil, &block)

def find_by_sql(sql, binds = [], preparable: nil, &block)
  result = super
  if Bullet.start?
    if result.is_a? Array
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    elsif result.is_a? ::ActiveRecord::Base
      Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
      Bullet::Detector::CounterCache.add_impossible_object(result)
    end
  end
  result
end

def find_by_sql(sql, binds = [], preparable: nil, &block)

def find_by_sql(sql, binds = [], preparable: nil, &block)
  result = super
  if Bullet.start?
    if result.is_a? Array
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    elsif result.is_a? ::ActiveRecord::Base
      Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
      Bullet::Detector::CounterCache.add_impossible_object(result)
    end
  end
  result
end

def find_by_sql(sql, binds = [], preparable: nil, &block)

def find_by_sql(sql, binds = [], preparable: nil, &block)
  result = super
  if Bullet.start?
    if result.is_a? Array
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    elsif result.is_a? ::ActiveRecord::Base
      Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
      Bullet::Detector::CounterCache.add_impossible_object(result)
    end
  end
  result
end

def find_by_sql(sql, binds = [], preparable: nil, &block)

def find_by_sql(sql, binds = [], preparable: nil, &block)
  result = super
  if Bullet.start?
    if result.is_a? Array
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    elsif result.is_a? ::ActiveRecord::Base
      Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
      Bullet::Detector::CounterCache.add_impossible_object(result)
    end
  end
  result
end

def find_by_sql(sql, binds = [], preparable: nil, allow_retry: false, &block)

def find_by_sql(sql, binds = [], preparable: nil, allow_retry: false, &block)
  result = super
  if Bullet.start?
    if result.is_a? Array
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    elsif result.is_a? ::ActiveRecord::Base
      Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
      Bullet::Detector::CounterCache.add_impossible_object(result)
    end
  end
  result
end

def find_by_sql(sql, binds = [], preparable: nil, allow_retry: false, &block)

def find_by_sql(sql, binds = [], preparable: nil, allow_retry: false, &block)
  result = super
  if Bullet.start?
    if result.is_a? Array
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    elsif result.is_a? ::ActiveRecord::Base
      Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
      Bullet::Detector::CounterCache.add_impossible_object(result)
    end
  end
  result
end

def find_with_associations

def find_with_associations
  records = origin_find_with_associations
  if Bullet.start?
    associations = (eager_load_values + includes_values).uniq
    records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
    Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
  end
  records
end

def find_with_associations

def find_with_associations
  return origin_find_with_associations { |r| yield r } if block_given?
  records = origin_find_with_associations
  if Bullet.start?
    associations = (eager_load_values + includes_values).uniq
    records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
    Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
  end
  records
end

def find_with_associations

def find_with_associations
  return origin_find_with_associations { |r| yield r } if block_given?
  records = origin_find_with_associations
  if Bullet.start?
    associations = (eager_load_values + includes_values).uniq
    records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
    Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
  end
  records
end

def find_with_associations

add includes in scope
def find_with_associations
  return super { |r| yield r } if block_given?
  records = super
  if Bullet.start?
    associations = (eager_load_values + includes_values).uniq
    records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
    Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
  end
  records
end

def has_cached_counter?(reflection = reflection())

def has_cached_counter?(reflection = reflection())
  result = origin_has_cached_counter?(reflection)
  Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name) if Bullet.start? && !result
  result
end

def include?(object)

def include?(object)
  Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start?
  origin_include?(object)
end

def include?(object)

def include?(object)
  Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start?
  origin_include?(object)
end

def include?(object)

def include?(object)
  Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start?
  origin_include?(object)
end

def include?(object)

def include?(object)
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
  super
end

def include?(object)

def include?(object)
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
  super
end

def include?(object)

def include?(object)
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
  super
end

def include?(object)

def include?(object)
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
  super
end

def include?(object)

def include?(object)
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
  super
end

def include?(object)

def include?(object)
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
  super
end

def include?(object)

def include?(object)
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
  super
end

def include?(object)

def include?(object)
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
  super
end

def initialize(records, associations, preload_scope = nil)

def initialize(records, associations, preload_scope = nil)
  origin_initialize(records, associations, preload_scope)
  if Bullet.start?
    records = [records].flatten.compact.uniq
    return if records.empty?
    records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
    Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
  end
end

def instantiate(rows)

def instantiate(rows)
  @bullet_eager_loadings = {}
  records = origin_instantiate(rows)
  if Bullet.start?
    @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
      objects = eager_loadings_hash.keys
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
    end
  end
  records
end

def instantiate(result_set, aliases)

def instantiate(result_set, aliases)
  @bullet_eager_loadings = {}
  records = origin_instantiate(result_set, aliases)
  if Bullet.start?
    @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
      objects = eager_loadings_hash.keys
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
    end
  end
  records
end

def instantiate(result_set, aliases)

def instantiate(result_set, aliases)
  @bullet_eager_loadings = {}
  records = origin_instantiate(result_set, aliases)
  if Bullet.start?
    @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
      objects = eager_loadings_hash.keys
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
    end
  end
  records
end

def instantiate(result_set, &block)

ActiveRecord >= 5.1.5
def instantiate(result_set, &block)
  @bullet_eager_loadings = {}
  records = super
  if Bullet.start?
    @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
      objects = eager_loadings_hash.keys
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
        objects,
        eager_loadings_hash[objects.first].to_a
      )
    end
  end
  records
end

def instantiate(result_set, aliases)

ActiveRecord <= 5.1.4
def instantiate(result_set, aliases)
  @bullet_eager_loadings = {}
  records = super
  if Bullet.start?
    @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
      objects = eager_loadings_hash.keys
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
        objects,
        eager_loadings_hash[objects.first].to_a
      )
    end
  end
  records
end

def instantiate(result_set, &block)

def instantiate(result_set, &block)
  @bullet_eager_loadings = {}
  records = super
  if Bullet.start?
    @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
      objects = eager_loadings_hash.keys
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
        objects,
        eager_loadings_hash[objects.first].to_a
      )
    end
  end
  records
end

def instantiate(result_set, &block)

def instantiate(result_set, &block)
  @bullet_eager_loadings = {}
  records = super
  if Bullet.start?
    @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
      objects = eager_loadings_hash.keys
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
        objects,
        eager_loadings_hash[objects.first].to_a
      )
    end
  end
  records
end

def instantiate(result_set, strict_loading_value, &block)

def instantiate(result_set, strict_loading_value, &block)
  @bullet_eager_loadings = {}
  records = super
  if Bullet.start?
    @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
      objects = eager_loadings_hash.keys
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
        objects,
        eager_loadings_hash[objects.first].to_a
      )
    end
  end
  records
end

def instantiate(result_set, strict_loading_value, &block)

def instantiate(result_set, strict_loading_value, &block)
  @bullet_eager_loadings = {}
  records = super
  if Bullet.start?
    @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
      objects = eager_loadings_hash.keys
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
        objects,
        eager_loadings_hash[objects.first].to_a
      )
    end
  end
  records
end

def instantiate(result_set, strict_loading_value, &block)

def instantiate(result_set, strict_loading_value, &block)
  @bullet_eager_loadings = {}
  records = super
  if Bullet.start?
    @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
      objects = eager_loadings_hash.keys
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
        objects,
        eager_loadings_hash[objects.first].to_a
      )
    end
  end
  records
end

def instantiate(result_set, strict_loading_value, &block)

def instantiate(result_set, strict_loading_value, &block)
  @bullet_eager_loadings = {}
  records = super
  if Bullet.start?
    @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
      objects = eager_loadings_hash.keys
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
        objects,
        eager_loadings_hash[objects.first].to_a
      )
    end
  end
  records
end

def instantiate(result_set, strict_loading_value, &block)

def instantiate(result_set, strict_loading_value, &block)
  @bullet_eager_loadings = {}
  records = super
  if Bullet.start?
    @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
      objects = eager_loadings_hash.keys
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
        objects,
        eager_loadings_hash[objects.first].to_a
      )
    end
  end
  records
end

def inversed_from(record)

def inversed_from(record)
  if Bullet.start?
    Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
  end
  super
end

def inversed_from(record)

def inversed_from(record)
  if Bullet.start?
    Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
  end
  super
end

def inversed_from(record)

def inversed_from(record)
  if Bullet.start?
    Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
  end
  super
end

def inversed_from(record)

def inversed_from(record)
  if Bullet.start?
    Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
  end
  super
end

def inversed_from(record)

def inversed_from(record)
  if Bullet.start?
    Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
  end
  super
end

def inversed_from(record)

def inversed_from(record)
  if Bullet.start?
    Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
  end
  super
end

def inversed_from(record)

def inversed_from(record)
  if Bullet.start?
    Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
  end
  super
end

def inversed_from_queries(record)

def inversed_from_queries(record)
  if Bullet.start? && inversable?(record)
    Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
  end
  super
end

def inversed_from_queries(record)

def inversed_from_queries(record)
  if Bullet.start? && inversable?(record)
    Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
  end
  super
end

def inversed_from_queries(record)

def inversed_from_queries(record)
  if Bullet.start? && inversable?(record)
    Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
  end
  super
end

def inversed_from_queries(record)

def inversed_from_queries(record)
  if Bullet.start? && inversable?(record)
    Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
  end
  super
end

def load_target

def load_target
  Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start?
  origin_load_target
end

def load_target

def load_target
  Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start? && !@inversed
  origin_load_target
end

def load_target

def load_target
  records = origin_load_target
  if Bullet.start?
    Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) unless @inversed
    if records.first.class.name !~ /^HABTM_/
      if records.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
        Bullet::Detector::CounterCache.add_possible_objects(records)
      elsif records.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
        Bullet::Detector::CounterCache.add_impossible_object(records.first)
      end
    end
  end
  records
end

def load_target

def load_target
  records = super
  if Bullet.start?
    if is_a? ::ActiveRecord::Associations::ThroughAssociation
      refl = reflection.through_reflection
      association = owner.association(refl.name)
      if association.loaded?
        Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if refl.through_reflection?
          refl = refl.through_reflection while refl.through_reflection?
          Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
        end
      end
    end
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
    if records.first.class.name !~ /^HABTM_/
      if records.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
        Bullet::Detector::CounterCache.add_possible_objects(records)
      elsif records.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
        Bullet::Detector::CounterCache.add_impossible_object(records.first)
      end
    end
  end
  records
end

def load_target

def load_target
  records = super
  if Bullet.start?
    if is_a? ::ActiveRecord::Associations::ThroughAssociation
      association = owner.association(reflection.through_reflection.name)
      if association.loaded?
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if reflection.through_reflection != through_reflection
          Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
        end
      end
    end
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
    if records.first.class.name !~ /^HABTM_/
      if records.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
        Bullet::Detector::CounterCache.add_possible_objects(records)
      elsif records.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
        Bullet::Detector::CounterCache.add_impossible_object(records.first)
      end
    end
  end
  records
end

def load_target

def load_target
  records = super
  if Bullet.start?
    if is_a? ::ActiveRecord::Associations::ThroughAssociation
      association = owner.association(reflection.through_reflection.name)
      if association.loaded?
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if reflection.through_reflection != through_reflection
          Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
        end
      end
    end
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
    if records.first.class.name !~ /^HABTM_/
      if records.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
        Bullet::Detector::CounterCache.add_possible_objects(records)
      elsif records.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
        Bullet::Detector::CounterCache.add_impossible_object(records.first)
      end
    end
  end
  records
end

def load_target

def load_target
  records = super
  if Bullet.start?
    if is_a? ::ActiveRecord::Associations::ThroughAssociation
      association = owner.association(reflection.through_reflection.name)
      if association.loaded?
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if reflection.through_reflection != through_reflection
          Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
        end
      end
    end
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
    if records.first.class.name !~ /^HABTM_/
      if records.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
        Bullet::Detector::CounterCache.add_possible_objects(records)
      elsif records.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
        Bullet::Detector::CounterCache.add_impossible_object(records.first)
      end
    end
  end
  records
end

def load_target

def load_target
  records = super
  if Bullet.start?
    if is_a? ::ActiveRecord::Associations::ThroughAssociation
      association = owner.association(reflection.through_reflection.name)
      if association.loaded?
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if reflection.through_reflection != through_reflection
          Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
        end
      end
    end
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
    if records.first.class.name !~ /^HABTM_/
      if records.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
        Bullet::Detector::CounterCache.add_possible_objects(records)
      elsif records.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
        Bullet::Detector::CounterCache.add_impossible_object(records.first)
      end
    end
  end
  records
end

def load_target

def load_target
  records = super
  if Bullet.start?
    if is_a? ::ActiveRecord::Associations::ThroughAssociation
      association = owner.association(reflection.through_reflection.name)
      if association.loaded?
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if reflection.through_reflection != through_reflection
          Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
        end
      end
    end
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
    if records.first.class.name !~ /^HABTM_/
      if records.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
        Bullet::Detector::CounterCache.add_possible_objects(records)
      elsif records.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
        Bullet::Detector::CounterCache.add_impossible_object(records.first)
      end
    end
  end
  records
end

def load_target

def load_target
  records = super
  if Bullet.start?
    if is_a? ::ActiveRecord::Associations::ThroughAssociation
      association = owner.association(reflection.through_reflection.name)
      if association.loaded?
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if reflection.through_reflection != through_reflection
          Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
        end
      end
    end
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
    if records.first.class.name !~ /^HABTM_/
      if records.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
        Bullet::Detector::CounterCache.add_possible_objects(records)
      elsif records.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
        Bullet::Detector::CounterCache.add_impossible_object(records.first)
      end
    end
  end
  records
end

def load_target

def load_target
  records = super
  if Bullet.start?
    if is_a? ::ActiveRecord::Associations::ThroughAssociation
      association = owner.association(reflection.through_reflection.name)
      if association.loaded?
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if reflection.through_reflection != through_reflection
          Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
        end
      end
    end
    Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
    if records.first.class.name !~ /^HABTM_/
      if records.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
        Bullet::Detector::CounterCache.add_possible_objects(records)
      elsif records.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
        Bullet::Detector::CounterCache.add_impossible_object(records.first)
      end
    end
  end
  records
end

def preloaded_records

def preloaded_records
  if Bullet.start? && !defined?(@preloaded_records)
    source_preloaders.each do |source_preloader|
      reflection_name = source_preloader.send(:reflection).name
      source_preloader.send(:owners).each do |owner|
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
      end
    end
  end
  super
end

def preloaded_records

def preloaded_records
  if Bullet.start? && !defined?(@preloaded_records)
    source_preloaders.each do |source_preloader|
      reflection_name = source_preloader.send(:reflection).name
      source_preloader.send(:owners).each do |owner|
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
      end
    end
  end
  super
end

def preloaders_for_one(association, records, scope)

def preloaders_for_one(association, records, scope)
  if Bullet.start?
    records.compact!
    if records.first.class.name !~ /^HABTM_/
      records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
    end
  end
  super
end

def preloaders_for_one(association, records, scope)

def preloaders_for_one(association, records, scope)
  if Bullet.start?
    records.compact!
    if records.first.class.name !~ /^HABTM_/
      records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
    end
  end
  super
end

def preloaders_for_one(association, records, scope, polymorphic_parent)

def preloaders_for_one(association, records, scope, polymorphic_parent)
  if Bullet.start?
    records.compact!
    if records.first.class.name !~ /^HABTM_/
      records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
    end
  end
  super
end

def preloaders_for_one(association, records, scope, polymorphic_parent)

def preloaders_for_one(association, records, scope, polymorphic_parent)
  if Bullet.start?
    records.compact!
    if records.first.class.name !~ /^HABTM_/
      records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
    end
  end
  super
end

def preloaders_for_reflection(reflection, records, scope)

def preloaders_for_reflection(reflection, records, scope)
  if Bullet.start?
    records.compact!
    if records.first.class.name !~ /^HABTM_/
      records.each { |record| Bullet::Detector::Association.add_object_associations(record, reflection.name) }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, reflection.name)
    end
  end
  super
end

def preloaders_for_reflection(reflection, records, scope)

def preloaders_for_reflection(reflection, records, scope)
  if Bullet.start?
    records.compact!
    if records.first.class.name !~ /^HABTM_/
      records.each { |record| Bullet::Detector::Association.add_object_associations(record, reflection.name) }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, reflection.name)
    end
  end
  super
end

def preloaders_for_reflection(reflection, reflection_records)

def preloaders_for_reflection(reflection, reflection_records)
  if Bullet.start?
    reflection_records.compact!
    if reflection_records.first.class.name !~ /^HABTM_/
      reflection_records.each { |record|
        Bullet::Detector::Association.add_object_associations(record, reflection.name)
      }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
    end
  end
  super
end

def preloaders_for_reflection(reflection, reflection_records)

def preloaders_for_reflection(reflection, reflection_records)
  if Bullet.start?
    reflection_records.compact!
    if reflection_records.first.class.name !~ /^HABTM_/
      reflection_records.each { |record|
        Bullet::Detector::Association.add_object_associations(record, reflection.name)
      }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
    end
  end
  super
end

def preloaders_for_reflection(reflection, reflection_records)

def preloaders_for_reflection(reflection, reflection_records)
  if Bullet.start?
    reflection_records.compact!
    if reflection_records.first.class.name !~ /^HABTM_/
      reflection_records.each { |record|
        Bullet::Detector::Association.add_object_associations(record, reflection.name)
      }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
    end
  end
  super
end

def preloaders_for_reflection(reflection, reflection_records)

def preloaders_for_reflection(reflection, reflection_records)
  if Bullet.start?
    reflection_records.compact!
    if reflection_records.first.class.name !~ /^HABTM_/
      reflection_records.each { |record|
        Bullet::Detector::Association.add_object_associations(record, reflection.name)
      }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
    end
  end
  super
end

def preloaders_on(association, records, scope)

def preloaders_on(association, records, scope)
  if Bullet.start?
    records.compact!
    if records.first.class.name !~ /^HABTM_/
      records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
    end
  end
  origin_preloaders_on(association, records, scope)
end

def preloaders_on(association, records, scope)

def preloaders_on(association, records, scope)
  if Bullet.start?
    records.compact!
    if records.first.class.name !~ /^HABTM_/
      records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
      Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
    end
  end
  origin_preloaders_on(association, records, scope)
end

def reader(force_reload = false)

def reader(force_reload = false)
  result = origin_reader(force_reload)
  if Bullet.start?
    unless @inversed
      Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
      Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
    end
  end
  result
end

def reader(force_reload = false)

def reader(force_reload = false)
  result = origin_reader(force_reload)
  if Bullet.start?
    if @owner.class.name !~ /^HABTM_/ && !@inversed
      Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
      Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
    end
  end
  result
end

def reader(force_reload = false)

def reader(force_reload = false)
  result = origin_reader(force_reload)
  if Bullet.start?
    if @owner.class.name !~ /^HABTM_/ && !@inversed
      Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
      if Bullet::Detector::NPlusOneQuery.impossible?(@owner)
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
      else
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
      end
    end
  end
  result
end

def reader

call has_one and belongs_to associations
def reader
  result = super
  if Bullet.start?
    if owner.class.name !~ /^HABTM_/
      if is_a? ::ActiveRecord::Associations::ThroughAssociation
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
        association = owner.association(reflection.through_reflection.name)
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if reflection.through_reflection != through_reflection
          Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
        end
      end
      Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
      if Bullet::Detector::NPlusOneQuery.impossible?(owner)
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
      else
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
      end
    end
  end
  result
end

def reader

call has_one and belongs_to associations
def reader
  result = super
  if Bullet.start?
    if owner.class.name !~ /^HABTM_/
      if is_a? ::ActiveRecord::Associations::ThroughAssociation
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
        association = owner.association(reflection.through_reflection.name)
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if reflection.through_reflection != through_reflection
          Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
        end
      end
      Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
      if Bullet::Detector::NPlusOneQuery.impossible?(owner)
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
      else
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
      end
    end
  end
  result
end

def reader

call has_one and belongs_to associations
def reader
  result = super
  if Bullet.start?
    if owner.class.name !~ /^HABTM_/
      if is_a? ::ActiveRecord::Associations::ThroughAssociation
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
        association = owner.association(reflection.through_reflection.name)
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if reflection.through_reflection != through_reflection
          Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
        end
      end
      Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
      if Bullet::Detector::NPlusOneQuery.impossible?(owner)
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
      else
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
      end
    end
  end
  result
end

def reader

call has_one and belongs_to associations
def reader
  result = super
  if Bullet.start?
    if owner.class.name !~ /^HABTM_/
      if is_a? ::ActiveRecord::Associations::ThroughAssociation
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
        association = owner.association(reflection.through_reflection.name)
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if reflection.through_reflection != through_reflection
          Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
        end
      end
      Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
      if Bullet::Detector::NPlusOneQuery.impossible?(owner)
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
      else
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
      end
    end
  end
  result
end

def records

if select only one object, then the only one object has impossible to cause N+1 query.
if select a collection of objects, then these objects have possible to cause N+1 query.
def records
  result = super
  if Bullet.start?
    if result.first.class.name !~ /^HABTM_/
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    end
  end
  result
end

def records

if select only one object, then the only one object has impossible to cause N+1 query.
if select a collection of objects, then these objects have possible to cause N+1 query.
def records
  result = super
  if Bullet.start?
    if result.first.class.name !~ /^HABTM_/
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    end
  end
  result
end

def records

if select only one object, then the only one object has impossible to cause N+1 query.
if select a collection of objects, then these objects have possible to cause N+1 query.
def records
  result = super
  if Bullet.start?
    if result.first.class.name !~ /^HABTM_/
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    end
  end
  result
end

def records

if select only one object, then the only one object has impossible to cause N+1 query.
if select a collection of objects, then these objects have possible to cause N+1 query.
def records
  result = super
  if Bullet.start?
    if result.first.class.name !~ /^HABTM_/
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    end
  end
  result
end

def records

if select only one object, then the only one object has impossible to cause N+1 query.
if select a collection of objects, then these objects have possible to cause N+1 query.
def records
  result = super
  if Bullet.start?
    if result.first.class.name !~ /^HABTM_/
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    end
  end
  result
end

def records

if select only one object, then the only one object has impossible to cause N+1 query.
if select a collection of objects, then these objects have possible to cause N+1 query.
def records
  result = super
  if Bullet.start?
    if result.first.class.name !~ /^HABTM_/
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    end
  end
  result
end

def records

if select only one object, then the only one object has impossible to cause N+1 query.
if select a collection of objects, then these objects have possible to cause N+1 query.
def records
  result = super
  if Bullet.start?
    if result.first.class.name !~ /^HABTM_/
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    end
  end
  result
end

def records

if select only one object, then the only one object has impossible to cause N+1 query.
if select a collection of objects, then these objects have possible to cause N+1 query.
def records
  result = super
  if Bullet.start?
    if result.first.class.name !~ /^HABTM_/
      if result.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
        Bullet::Detector::CounterCache.add_possible_objects(result)
      elsif result.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
        Bullet::Detector::CounterCache.add_impossible_object(result.first)
      end
    end
  end
  result
end

def source_preloaders

def source_preloaders
  if Bullet.start? && !defined?(@source_preloaders)
    preloaders = super
    preloaders.each do |preloader|
      reflection_name = preloader.send(:reflection).name
      preloader.send(:owners).each do |owner|
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
      end
    end
  else
    super
  end
end

def source_preloaders

def source_preloaders
  if Bullet.start? && !defined?(@source_preloaders)
    preloaders = super
    preloaders.each do |preloader|
      reflection_name = preloader.send(:reflection).name
      preloader.send(:owners).each do |owner|
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
      end
    end
  else
    super
  end
end

def source_preloaders

def source_preloaders
  if Bullet.start? && !defined?(@source_preloaders)
    preloaders = super
    preloaders.each do |preloader|
      reflection_name = preloader.send(:reflection).name
      preloader.send(:owners).each do |owner|
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
      end
    end
  else
    super
  end
end

def source_preloaders

def source_preloaders
  if Bullet.start? && !defined?(@source_preloaders)
    preloaders = super
    preloaders.each do |preloader|
      reflection_name = preloader.send(:reflection).name
      preloader.send(:owners).each do |owner|
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
      end
    end
  else
    super
  end
end

def target

call has_one and belongs_to associations
def target
  result = super()
  if Bullet.start?
    if owner.class.name !~ /^HABTM_/ && !@inversed
      Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
      if Bullet::Detector::NPlusOneQuery.impossible?(owner)
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
      else
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
      end
    end
  end
  result
end

def target

call has_one and belongs_to associations
def target
  result = super()
  if Bullet.start?
    if owner.class.name !~ /^HABTM_/ && !@inversed
      if is_a? ::ActiveRecord::Associations::ThroughAssociation
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
        association = owner.association reflection.through_reflection.name
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if reflection.through_reflection != through_reflection
          Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
        end
      end
      Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
      if Bullet::Detector::NPlusOneQuery.impossible?(owner)
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
      else
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
      end
    end
  end
  result
end

def target

call has_one and belongs_to associations
def target
  result = super()
  if Bullet.start?
    if owner.class.name !~ /^HABTM_/ && !@inversed
      if is_a? ::ActiveRecord::Associations::ThroughAssociation
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
        association = owner.association(reflection.through_reflection.name)
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if reflection.through_reflection != through_reflection
          Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
        end
      end
      Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
      if Bullet::Detector::NPlusOneQuery.impossible?(owner)
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
      else
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
      end
    end
  end
  result
end

def target

call has_one and belongs_to associations
def target
  result = super()
  if Bullet.start?
    if owner.class.name !~ /^HABTM_/ && !@inversed
      if is_a? ::ActiveRecord::Associations::ThroughAssociation
        Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
        association = owner.association(reflection.through_reflection.name)
        Array.wrap(association.target).each do |through_record|
          Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
        end
        if reflection.through_reflection != through_reflection
          Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
        end
      end
      Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
      if Bullet::Detector::NPlusOneQuery.impossible?(owner)
        Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
      else
        Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
      end
    end
  end
  result
end

def to_a

if select only one object, then the only one object has impossible to cause N+1 query.
if select a collection of objects, then these objects have possible to cause N+1 query.
def to_a
  records = origin_to_a
  if Bullet.start?
    if records.size > 1
      Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
      Bullet::Detector::CounterCache.add_possible_objects(records)
    elsif records.size == 1
      Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
      Bullet::Detector::CounterCache.add_impossible_object(records.first)
    end
  end
  records
end

def to_a

if select only one object, then the only one object has impossible to cause N+1 query.
if select a collection of objects, then these objects have possible to cause N+1 query.
def to_a
  records = origin_to_a
  if Bullet.start?
    if records.first.class.name !~ /^HABTM_/
      if records.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
        Bullet::Detector::CounterCache.add_possible_objects(records)
      elsif records.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
        Bullet::Detector::CounterCache.add_impossible_object(records.first)
      end
    end
  end
  records
end

def to_a

if select only one object, then the only one object has impossible to cause N+1 query.
if select a collection of objects, then these objects have possible to cause N+1 query.
def to_a
  records = origin_to_a
  if Bullet.start?
    if records.first.class.name !~ /^HABTM_/
      if records.size > 1
        Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
        Bullet::Detector::CounterCache.add_possible_objects(records)
      elsif records.size == 1
        Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
        Bullet::Detector::CounterCache.add_impossible_object(records.first)
      end
    end
  end
  records
end