lib/bullet/association.rb in flyerhzm-bullet-1.4.1 vs lib/bullet/association.rb in flyerhzm-bullet-1.5.0

- old
+ new

@@ -1,226 +1,92 @@ module Bullet - class BulletAssociationError < StandardError - end - class Association class <<self - @@alert = nil - @@bullet_logger = nil - @@console = nil - @@growl = nil - @@growl_password = nil - @@rails_logger = nil + include Bullet::Notification - ################################################### - # Configurations - ################################################### - def alert=(alert) - @@alert = alert - end - - def console=(console) - @@console = console - end - - def growl=(growl) - if growl - begin - require 'ruby-growl' - growl = Growl.new('localhost', 'ruby-growl', ['Bullet Notification'], nil, @@growl_password) - growl.notify('Bullet Notification', 'Bullet Notification', 'Bullet Growl notifications have been turned on') - rescue MissingSourceFile - raise BulletAssociationError.new('You must install the ruby-growl gem to use Growl notifications: `sudo gem install ruby-growl`') - end - end - @@growl = growl - end - - def growl_password=(growl_password) - @@growl_password = growl_password - end - - def bullet_logger=(bullet_logger) - if @@bullet_logger = bullet_logger - @@logger_file = File.open(Bullet::BulletLogger::LOG_FILE, 'a+') - @@logger = Bullet::BulletLogger.new(@@logger_file) - end - end - - def rails_logger=(rails_logger) - @@rails_logger = rails_logger - end - - ##################################################### - # login control interface - ##################################################### def start_request - # puts "start request" end def end_request - # puts "end request" @@object_associations = nil @@unpreload_associations = nil @@unused_preload_associations = nil @@callers = nil @@possible_objects = nil @@impossible_objects = nil @@call_object_associations = nil @@eager_loadings = nil end - def has_bad_assocations? + def notification? check_unused_preload_associations has_unpreload_associations? or has_unused_preload_associations? end - ###################################################### - # Notifications - ###################################################### - def javascript_notification - str = '' - if @@alert || @@console - response = notification_response - end - if @@alert - str << wrap_js_association("alert(#{response.join("\n").inspect});") - end - if @@console - title = [] - title << unused_preload_messages.first.first unless unused_preload_messages.empty? - title << unpreload_messages.first.first unless unpreload_messages.empty? - code = <<-CODE - if (typeof(console) !== 'undefined') { - - if (console.groupCollapsed && console.groupEnd && console.log) { - - console.groupCollapsed(#{title.join(', ').inspect}); - console.log(#{response.join("\n").inspect}); - console.log(#{call_stack_messages.join("\n").inspect}); - console.groupEnd(); - - } else if (console.log) { - - console.log(#{response.join("\n").inspect}); - } - } - CODE - str << wrap_js_association(code) - end - str - end - - def growl_notification - if @@growl - response = notification_response - begin - growl = Growl.new('localhost', 'ruby-growl', ['Bullet Notification'], nil, @@growl_password) - growl.notify('Bullet Notification', 'Bullet Notification', response.join("\n")) - rescue - end - end - end - - def log_notificatioin(path) - if (@@bullet_logger || @@rails_logger) && (!unpreload_associations.empty? || !unused_preload_associations.empty?) - Rails.logger.warn '' if @@rails_logger - unused_preload_messages(path).each do |message| - @@logger.info(message.join("\n")) if @@bullet_logger - Rails.logger.warn(message.join("\n")) if @@rails_logger - end - unpreload_messages(path).each do |message| - @@logger.info(message.join("\n")) if @@bullet_logger - Rails.logger.warn(message.join("\n")) if @@rails_logger - end - call_stack_messages.each do |message| - @@logger.info(message.join("\n")) if @@bullet_logger - Rails.logger.warn(message.join("\n")) if @@rails_logger - end - @@logger_file.flush if @@bullet_logger - end - end - def add_unpreload_associations(klazz, associations) - # puts "add unpreload associations, #{klazz} => #{associations.inspect}" unpreload_associations[klazz] ||= [] unpreload_associations[klazz] << associations unique(unpreload_associations[klazz]) end def add_unused_preload_associations(klazz, associations) - # puts "add unused preload associations, #{klazz} => #{associations.inspect}" unused_preload_associations[klazz] ||= [] unused_preload_associations[klazz] << associations unique(unused_preload_associations[klazz]) end def add_association(object, associations) - # puts "add associations, #{object} => #{associations.inspect}" object_associations[object] ||= [] object_associations[object] << associations unique(object_associations[object]) end - ################################################### - # interface for active record - ################################################### def add_call_object_associations(object, associations) - # puts "add call object associations, #{object} => #{associations.inspect}" call_object_associations[object] ||= [] call_object_associations[object] << associations unique(call_object_associations[object]) end def add_possible_objects(objects) - # puts "add possible objects, #{objects.inspect}" klazz= objects.first.class possible_objects[klazz] ||= [] possible_objects[klazz] << objects unique(possible_objects[klazz]) end def add_impossible_object(object) - # puts "add impossible object, #{object}" klazz = object.class impossible_objects[klazz] ||= [] impossible_objects[klazz] << object impossible_objects[klazz].uniq! end def add_klazz_associations(klazz, associations) - # puts "define associations, #{klazz} => #{associations.inspect}" klazz_associations[klazz] ||= [] klazz_associations[klazz] << associations unique(klazz_associations[klazz]) end def add_eager_loadings(objects, associations) - # puts "add eager loadings, #{objects.inspect} => #{associations.inspect}" objects = Array(objects) eager_loadings[objects] ||= [] eager_loadings[objects] << associations unique(eager_loadings[objects]) end def define_association(klazz, associations) - # puts "define association, #{klazz} => #{associations.inspect}" add_klazz_associations(klazz, associations) end def call_association(object, associations) - # puts "call association, #{object} => #{associations.inspect}" add_call_object_associations(object, associations) if unpreload_associations?(object, associations) add_unpreload_associations(object.class, associations) caller_in_project end end - ############################################ - # for rspec - ############################################ def check_unused_preload_associations object_associations.each do |object, association| related_objects = eager_loadings.select {|key, value| key.include?(object) and value == association}.collect(&:first).flatten call_object_association = related_objects.collect { |related_object| call_object_associations[related_object] }.compact.flatten.uniq diff_object_association = (association - call_object_association).reject {|a| a.is_a? Hash} @@ -234,119 +100,124 @@ def has_unpreload_associations? !unpreload_associations.empty? end - private - def unpreload_associations?(object, associations) - klazz = object.class - (!possible_objects[klazz].nil? and possible_objects[klazz].include?(object)) and - (impossible_objects[klazz].nil? or !impossible_objects[klazz].include?(object)) and - (object_associations[object].nil? or !object_associations[object].include?(associations)) - end + def unpreload_associations?(object, associations) + klazz = object.class + (!possible_objects[klazz].nil? and possible_objects[klazz].include?(object)) and + (impossible_objects[klazz].nil? or !impossible_objects[klazz].include?(object)) and + (object_associations[object].nil? or !object_associations[object].include?(associations)) + end - def notification_response - response = [] - if has_unused_preload_associations? - response << unused_preload_messages.join("\n") + def notification_response + response = [] + if has_unused_preload_associations? + response << unused_preload_messages.join("\n") + end + if has_unpreload_associations? + response << unpreload_messages.join("\n") + end + response end - if has_unpreload_associations? - response << unpreload_messages.join("\n") + + def console_title + title = [] + title << unused_preload_messages.first.first unless unused_preload_messages.empty? + title << unpreload_messages.first.first unless unpreload_messages.empty? end - response - end - def unused_preload_messages(path = nil) - messages = [] - unused_preload_associations.each do |klazz, associations| - messages << [ - "Unused Eager Loading #{path ? "in #{path}" : 'detected'}", - klazz_associations_str(klazz, associations), - " Remove from your finder: #{associations_str(associations)}" - ] + def log_messages(path = nil) + messages = [] + messages << unused_preload_messages(path) + messages << unpreload_messages(path) + messages << call_stack_messages end - messages - end - def unpreload_messages(path = nil) - messages = [] - unpreload_associations.each do |klazz, associations| - messages << [ - "N+1 Query #{path ? "in #{path}" : 'detected'}", - klazz_associations_str(klazz, associations), - " Add to your finder: #{associations_str(associations)}" - ] + def unused_preload_messages(path = nil) + messages = [] + unused_preload_associations.each do |klazz, associations| + messages << [ + "Unused Eager Loading #{path ? "in #{path}" : 'detected'}", + klazz_associations_str(klazz, associations), + " Remove from your finder: #{associations_str(associations)}" + ] + end + messages end - messages - end - def klazz_associations_str(klazz, associations) - " #{klazz} => [#{associations.map(&:inspect).join(', ')}]" - end + def unpreload_messages(path = nil) + messages = [] + unpreload_associations.each do |klazz, associations| + messages << [ + "N+1 Query #{path ? "in #{path}" : 'detected'}", + klazz_associations_str(klazz, associations), + " Add to your finder: #{associations_str(associations)}" + ] + end + messages + end - def associations_str(associations) - ":include => #{associations.map{|a| a.to_sym unless a.is_a? Hash}.inspect}" - end + def call_stack_messages + callers.inject([]) do |messages, c| + messages << ['N+1 Query method call stack', c.collect {|line| " #{line}"}].flatten + end + end - def wrap_js_association(message) - str = '' - str << "<script type=\"text/javascript\">/*<![CDATA[*/" - str << message - str << "/*]]>*/</script>\n" - end + def klazz_associations_str(klazz, associations) + " #{klazz} => [#{associations.map(&:inspect).join(', ')}]" + end - def call_stack_messages - callers.inject([]) do |messages, c| - messages << ['N+1 Query method call stack', c.collect {|line| " #{line}"}].flatten + def associations_str(associations) + ":include => #{associations.map{|a| a.to_sym unless a.is_a? Hash}.inspect}" end - end - - def unique(array) - array.flatten! - array.uniq! - end + + def unique(array) + array.flatten! + array.uniq! + end - def unpreload_associations - @@unpreload_associations ||= {} - end + def unpreload_associations + @@unpreload_associations ||= {} + end - def unused_preload_associations - @@unused_preload_associations ||= {} - end + def unused_preload_associations + @@unused_preload_associations ||= {} + end - def object_associations - @@object_associations ||= {} - end + def object_associations + @@object_associations ||= {} + end - def call_object_associations - @@call_object_associations ||= {} - end + def call_object_associations + @@call_object_associations ||= {} + end - def possible_objects - @@possible_objects ||= {} - end + def possible_objects + @@possible_objects ||= {} + end - def impossible_objects - @@impossible_objects ||= {} - end + def impossible_objects + @@impossible_objects ||= {} + end - def klazz_associations - @@klazz_associations ||= {} - end + def klazz_associations + @@klazz_associations ||= {} + end - def eager_loadings - @@eager_loadings ||= {} - end + def eager_loadings + @@eager_loadings ||= {} + end - VENDOR_ROOT = File.join(RAILS_ROOT, 'vendor') - def caller_in_project - callers << caller.select {|c| c =~ /#{RAILS_ROOT}/}.reject {|c| c =~ /#{VENDOR_ROOT}/} - callers.uniq! - end + VENDOR_ROOT = File.join(RAILS_ROOT, 'vendor') + def caller_in_project + callers << caller.select {|c| c =~ /#{RAILS_ROOT}/}.reject {|c| c =~ /#{VENDOR_ROOT}/} + callers.uniq! + end - def callers - @@callers ||= [] - end + def callers + @@callers ||= [] + end end end end