Sha256: fc1a297bef280a19548e2ea1b0511ea25ff7e3e0609d3e93c909437d10c78749

Contents?: true

Size: 1.8 KB

Versions: 5

Compression:

Stored size: 1.8 KB

Contents

module Polo
  class Collector

    def initialize(base_class, id, dependency_tree={})
      @base_class = base_class
      @id = id
      @dependency_tree = dependency_tree
      @selects = []
    end

    # Public: Traverses the dependency tree and collects every SQL query.
    #
    # This is done by wrapping a top level call to includes(...) with a
    # ActiveSupport::Notifications block and collecting every generate SQL query.
    #
    def collect
      unprepared_statement do
        ActiveSupport::Notifications.subscribed(collector, 'sql.active_record') do
          base_finder = @base_class.includes(@dependency_tree).where(@base_class.primary_key => @id)
          collect_sql(@base_class, base_finder.to_sql)
          base_finder.to_a
        end
      end

      @selects.compact.uniq
    end

    private

    # Internal: Store ActiveRecord queries in @selects
    #
    # Collector will intersect every ActiveRecord query performed within the
    # ActiveSupport::Notifications.subscribed block defined in #run and store
    # the resulting SQL query in @selects
    #
    def collector
      lambda do |name, start, finish, id, payload|
        return unless payload[:name] =~ /^(.*) Load$/
        begin
          class_name = $1.constantize
          sql = payload[:sql]
          collect_sql(class_name, sql)
        rescue ActiveRecord::StatementInvalid, NameError
          # invalid table name (common when prefetching schemas)
        end
      end
    end

    def collect_sql(klass, sql)
      @selects << {
        klass: klass,
        sql: sql
      }
    end

    def unprepared_statement
      if ActiveRecord::Base.connection.respond_to?(:unprepared_statement)
        ActiveRecord::Base.connection.unprepared_statement do
          yield
        end
      else
        yield
      end
    end
  end
end

Version data entries

5 entries across 5 versions & 1 rubygems

Version Path
polo-0.5.0 lib/polo/collector.rb
polo-0.4.1 lib/polo/collector.rb
polo-0.4.0 lib/polo/collector.rb
polo-0.3.0 lib/polo/collector.rb
polo-0.2.0 lib/polo/collector.rb