module Yt::Associations::HasReports

@private Provides methods to access the analytics reports of a resource.

Public Instance Methods

has_report(metric, type) click to toggle source

Defines a public instance methods to access the reports of a resource for a specific metric. @param [Symbol] metric the metric to access the reports of. @param [Class] type The class to cast the returned values to. @example Adds comments on a Channel resource.

class Channel < Resource
  has_report :comments, Integer
end
# File lib/yt/associations/has_reports.rb, line 212
def has_report(metric, type)
  require 'yt/collections/reports'

  define_metric_method metric
  define_reports_method metric, type
  define_range_metric_method metric
  define_all_metric_method metric, type
end

Private Instance Methods

define_all_metric_method(metric, type) click to toggle source
# File lib/yt/associations/has_reports.rb, line 297
def define_all_metric_method(metric, type)
  define_method "all_#{metric}" do
    # @note Asking for the "estimated_revenue" metric of a day in which a channel
    # made 0 USD returns the wrong "nil". But adding to the request the
    # "estimatedMinutesWatched" metric returns the correct value 0.
    metrics = {metric => type}
    metrics[:estimated_minutes_watched] = Integer if metric == :estimated_revenue
    Collections::Reports.of(self).tap{|reports| reports.metrics = metrics}
  end
  private "all_#{metric}"
end
define_metric_method(metric) click to toggle source
# File lib/yt/associations/has_reports.rb, line 248
def define_metric_method(metric)
  define_method metric do |options = {}|
    from = options[:since] || options[:from] || (options[:by].in?([:day, :month]) ? 5.days.ago : '2005-02-01')
    to = options[:until] || options[:to] || Date.today
    location = options[:in]
    country = location.is_a?(Hash) ? location[:country] : location
    state = location[:state] if location.is_a?(Hash)
    dimension = options[:by] || (metric == :viewer_percentage ? :gender_age_group : :range)
    videos = options[:videos]
    historical = options[:historical].to_s if [true, false].include?(options[:historical])
    if dimension == :month
      from = from.to_date.beginning_of_month
      to = to.to_date.beginning_of_month
    end
    range = Range.new *[from, to].map(&:to_date)

    ivar = instance_variable_get "@#{metric}_#{dimension}_#{country}_#{state}"
    instance_variable_set "@#{metric}_#{dimension}_#{country}_#{state}", ivar || {}
    results = case dimension
    when :day
      Hash[*range.flat_map do |date|
        [date, instance_variable_get("@#{metric}_#{dimension}_#{country}_#{state}")[date] ||= send("range_#{metric}", range, dimension, country, state, videos, historical)[date]]
      end]
    else
      instance_variable_get("@#{metric}_#{dimension}_#{country}_#{state}")[range] ||= send("range_#{metric}", range, dimension, country, state, videos, historical)
    end
    lookup_class = case options[:by]
      when :video, :related_video then Yt::Collections::Videos
      when :playlist then Yt::Collections::Playlists
    end
    if lookup_class
      includes = options.fetch(:includes, [:id]).join(',').camelize(:lower)
      items = lookup_class.new(auth: auth).where(part: includes, id: results.keys.join(','))
      results.transform_keys{|id| items.find{|item| item.id == id}}.reject{|k, _| k.nil?}
    else
      results
    end
  end
end
define_range_metric_method(metric) click to toggle source
# File lib/yt/associations/has_reports.rb, line 288
def define_range_metric_method(metric)
  define_method "range_#{metric}" do |date_range, dimension, country, state, videos, historical|
    ivar = instance_variable_get "@range_#{metric}_#{dimension}_#{country}_#{state}"
    instance_variable_set "@range_#{metric}_#{dimension}_#{country}_#{state}", ivar || {}
    instance_variable_get("@range_#{metric}_#{dimension}_#{country}_#{state}")[date_range] ||= send("all_#{metric}").within date_range, country, state, dimension, videos, historical
  end
  private "range_#{metric}"
end
define_reports_method(metric, type) click to toggle source
# File lib/yt/associations/has_reports.rb, line 223
def define_reports_method(metric, type)
  (@metrics ||= {})[metric] = type
  define_method :reports do |options = {}|
    from = options[:since] || options[:from] || (options[:by].in?([:day, :month]) ? 5.days.ago : '2005-02-01')
    to = options[:until] || options[:to] || Date.today
    location = options[:in]
    country = location.is_a?(Hash) ? location[:country] : location
    state = location[:state] if location.is_a?(Hash)
    dimension = options[:by] || (metric == :viewer_percentage ? :gender_age_group : :range)
    videos = options[:videos]
    historical = options[:historical].to_s if [true, false].include?(options[:historical])
    if dimension == :month
      from = from.to_date.beginning_of_month
      to = to.to_date.beginning_of_month
    end
    date_range = Range.new *[from, to].map(&:to_date)

    only = options.fetch :only, []
    reports = Collections::Reports.of(self).tap do |reports|
      reports.metrics = self.class.instance_variable_get(:@metrics).select{|k, v| k.in? only}
    end
    reports.within date_range, country, state, dimension, videos, historical
  end unless defined?(reports)
end