class Yt::Relation

Provides methods to iterate through collections of YouTube resources. @private

Public Class Methods

new(item_class, options = {}, &item_block) click to toggle source

@param [Class] item_class the class of objects to initialize when

iterating through a collection of YouTube resources.

@yield [Hash] the options to change which items to iterate through.

# File lib/yt/relation.rb, line 10
def initialize(item_class, options = {}, &item_block)
  @options = {parts: %i(id), limit: Float::INFINITY, item_class: item_class,
    initial_items: -> {[]}, extract_items: -> (body) {body['items']}}
  @options.merge! options
  @item_block = item_block
end

Public Instance Methods

attributes_for_new_item(item) click to toggle source
# File lib/yt/relation.rb, line 47
def attributes_for_new_item(item)
  {}.tap do |matching_parts|
    item.each_key do |key|
      part = key.gsub(/([A-Z])/) { "_#{$1.downcase}" }.to_sym
      if @options[:parts].include? part
        matching_parts[part] = item[key]
      end
    end
  end
end
each() { |next_item| ... } click to toggle source

Let's start without memoizing

# File lib/yt/relation.rb, line 18
def each
  @last_index = 0
  while next_item = find_next
    break if @last_index > @options[:limit]
    yield next_item
  end
end
find_next() click to toggle source
# File lib/yt/relation.rb, line 26
def find_next
  @items ||= initial_items.dup
  if @items[@last_index].nil? && more_pages?
    response = Response.new(@options, &@item_block).run
    more_items = @options[:extract_items].call(response.body).map do |item|
      @options[:item_class].new attributes_for_new_item(item)
    end
    @options.merge! offset: response.body['nextPageToken'] if response.body
    @items.concat more_items
  end
  @items[(@last_index +=1) -1]
end
initial_items() click to toggle source
# File lib/yt/relation.rb, line 43
def initial_items
  @initial_items ||= @options[:initial_items].call
end
inspect() click to toggle source

@return [String] a representation of the Yt::Relation instance.

# File lib/yt/relation.rb, line 96
def inspect
  entries = take(3).map!(&:inspect)
  if entries.size == 3
    entries[2] = '...'
  end

  "#<#{self.class.name} [#{entries.join(', ')}]>"
end
limit(max_results) click to toggle source

Specifies how many items to fetch when hitting the data API. @param [Integer] max_results The maximum number of items to fetch. @return [Yt::Relation] itself.

# File lib/yt/relation.rb, line 90
def limit(max_results)
  @options.merge! limit: max_results
  self
end
more_pages?() click to toggle source
# File lib/yt/relation.rb, line 39
def more_pages?
  (@last_index == initial_items.size) || !@options[:offset].nil?
end
select(*parts) click to toggle source

Specifies which parts of the resource to fetch when hitting the data API. @param [Array<Symbol>] parts The parts to fetch. @return [Yt::Relation] itself.

# File lib/yt/relation.rb, line 68
def select(*parts)
  if @options[:parts] != parts + %i(id)
    @items = nil
    @options.merge! parts: (parts + %i(id))
  end
  self
end
size() click to toggle source

@return [Integer] the estimated number of items in the collection.

# File lib/yt/relation.rb, line 59
def size
  size_options = @options.merge parts: %i(id), limit: 1
  @response = Response.new(size_options, &@item_block).run
  [@response.body['pageInfo']['totalResults'], @options[:limit]].min
end
where(conditions = {}) click to toggle source

Specifies which items to fetch when hitting the data API. @param [Hash<Symbol, String>] conditions The conditions for the items. @return [Yt::Relation] itself.

# File lib/yt/relation.rb, line 79
def where(conditions = {})
  if @options[:conditions] != conditions
    @items = []
    @options.merge! conditions: conditions
  end
  self
end