class Bullet::Detector::NPlusOneQuery

Public Class Methods

add_impossible_object(object) click to toggle source
# File lib/bullet/detector/n_plus_one_query.rb, line 38
def add_impossible_object(object)
  return unless Bullet.start?
  return unless Bullet.n_plus_one_query_enable?
  return unless object.primary_key_value

  Bullet.debug('Detector::NPlusOneQuery#add_impossible_object'.freeze, "object: #{object.bullet_key}")
  impossible_objects.add object.bullet_key
end
add_inversed_object(object, association) click to toggle source
# File lib/bullet/detector/n_plus_one_query.rb, line 47
def add_inversed_object(object, association)
  return unless Bullet.start?
  return unless Bullet.n_plus_one_query_enable?
  return unless object.primary_key_value

  Bullet.debug('Detector::NPlusOneQuery#add_inversed_object'.freeze, "object: #{object.bullet_key}, association: #{association}")
  inversed_objects.add object.bullet_key, association
end
add_possible_objects(object_or_objects) click to toggle source
# File lib/bullet/detector/n_plus_one_query.rb, line 28
def add_possible_objects(object_or_objects)
  return unless Bullet.start?
  return unless Bullet.n_plus_one_query_enable?
  objects = Array(object_or_objects)
  return if objects.map(&:primary_key_value).compact.empty?

  Bullet.debug('Detector::NPlusOneQuery#add_possible_objects'.freeze, "objects: #{objects.map(&:bullet_key).join(', '.freeze)}")
  objects.each { |object| possible_objects.add object.bullet_key }
end
association?(object, associations) click to toggle source

check if object => associations already exists in object_associations.

# File lib/bullet/detector/n_plus_one_query.rb, line 70
def association?(object, associations)
  value = object_associations[object.bullet_key]
  if value
    value.each do |v|
      # associations == v comparison order is important here because
      # v variable might be a squeel node where :== method is redefined,
      # so it does not compare values at all and return unexpected results
      result = v.is_a?(Hash) ? v.key?(associations) : associations == v
      return true if result
    end
  end

  false
end
call_association(object, associations) click to toggle source

executed when object.assocations is called. first, it keeps this method call for object.association. then, it checks if this associations call is unpreload.

if it is, keeps this unpreload associations and caller.
# File lib/bullet/detector/n_plus_one_query.rb, line 14
def call_association(object, associations)
  return unless Bullet.start?
  return unless Bullet.n_plus_one_query_enable?
  return unless object.primary_key_value
  return if inversed_objects.include?(object.bullet_key, associations)
  add_call_object_associations(object, associations)

  Bullet.debug('Detector::NPlusOneQuery#call_association'.freeze, "object: #{object.bullet_key}, associations: #{associations}")
  if !excluded_stacktrace_path? && conditions_met?(object, associations)
    Bullet.debug('detect n + 1 query', "object: #{object.bullet_key}, associations: #{associations}")
    create_notification caller_in_project, object.class.to_s, associations
  end
end
conditions_met?(object, associations) click to toggle source

decide whether the object.associations is unpreloaded or not.

# File lib/bullet/detector/n_plus_one_query.rb, line 57
def conditions_met?(object, associations)
  possible?(object) && !impossible?(object) && !association?(object, associations)
end
impossible?(object) click to toggle source
# File lib/bullet/detector/n_plus_one_query.rb, line 65
def impossible?(object)
  impossible_objects.include? object.bullet_key
end
possible?(object) click to toggle source
# File lib/bullet/detector/n_plus_one_query.rb, line 61
def possible?(object)
  possible_objects.include? object.bullet_key
end

Private Class Methods

create_notification(callers, klazz, associations) click to toggle source
# File lib/bullet/detector/n_plus_one_query.rb, line 87
def create_notification(callers, klazz, associations)
  notify_associations = Array(associations) - Bullet.get_whitelist_associations(:n_plus_one_query, klazz)

  if notify_associations.present?
    notice = Bullet::Notification::NPlusOneQuery.new(callers, klazz, notify_associations)
    Bullet.notification_collector.add(notice)
  end
end