yt 0.0.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +24 -0
- data/.rspec +2 -0
- data/.travis.yml +10 -0
- data/.yardopts +1 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +78 -0
- data/HISTORY.md +37 -0
- data/MIT-LICENSE +20 -0
- data/README.md +325 -0
- data/Rakefile +1 -0
- data/TODO.md +11 -0
- data/bin/yt +31 -0
- data/lib/yt.rb +2 -0
- data/lib/yt/actions/delete.rb +27 -0
- data/lib/yt/actions/delete_all.rb +28 -0
- data/lib/yt/actions/insert.rb +29 -0
- data/lib/yt/actions/list.rb +65 -0
- data/lib/yt/actions/update.rb +25 -0
- data/lib/yt/associations.rb +33 -0
- data/lib/yt/associations/annotations.rb +15 -0
- data/lib/yt/associations/channels.rb +20 -0
- data/lib/yt/associations/details_sets.rb +20 -0
- data/lib/yt/associations/playlist_items.rb +26 -0
- data/lib/yt/associations/playlists.rb +22 -0
- data/lib/yt/associations/ratings.rb +39 -0
- data/lib/yt/associations/snippets.rb +20 -0
- data/lib/yt/associations/statuses.rb +14 -0
- data/lib/yt/associations/subscriptions.rb +38 -0
- data/lib/yt/associations/user_infos.rb +21 -0
- data/lib/yt/associations/videos.rb +14 -0
- data/lib/yt/collections/annotations.rb +43 -0
- data/lib/yt/collections/base.rb +13 -0
- data/lib/yt/collections/channels.rb +32 -0
- data/lib/yt/collections/details_sets.rb +32 -0
- data/lib/yt/collections/playlist_items.rb +50 -0
- data/lib/yt/collections/playlists.rb +56 -0
- data/lib/yt/collections/ratings.rb +32 -0
- data/lib/yt/collections/snippets.rb +38 -0
- data/lib/yt/collections/subscriptions.rb +67 -0
- data/lib/yt/collections/user_infos.rb +41 -0
- data/lib/yt/collections/videos.rb +32 -0
- data/lib/yt/config.rb +55 -0
- data/lib/yt/models/account.rb +68 -0
- data/lib/yt/models/annotation.rb +137 -0
- data/lib/yt/models/base.rb +11 -0
- data/lib/yt/models/channel.rb +17 -0
- data/lib/yt/models/configuration.rb +29 -0
- data/lib/yt/models/description.rb +98 -0
- data/lib/yt/models/details_set.rb +31 -0
- data/lib/yt/models/playlist.rb +65 -0
- data/lib/yt/models/playlist_item.rb +42 -0
- data/lib/yt/models/rating.rb +28 -0
- data/lib/yt/models/snippet.rb +48 -0
- data/lib/yt/models/status.rb +26 -0
- data/lib/yt/models/subscription.rb +35 -0
- data/lib/yt/models/user_info.rb +66 -0
- data/lib/yt/models/video.rb +16 -0
- data/lib/yt/utils/request.rb +85 -0
- data/lib/yt/version.rb +3 -0
- data/spec/associations/device_auth/channels_spec.rb +10 -0
- data/spec/associations/device_auth/details_sets_spec.rb +19 -0
- data/spec/associations/device_auth/playlist_items_spec.rb +42 -0
- data/spec/associations/device_auth/playlists_spec.rb +42 -0
- data/spec/associations/device_auth/ratings_spec.rb +30 -0
- data/spec/associations/device_auth/snippets_spec.rb +30 -0
- data/spec/associations/device_auth/subscriptions_spec.rb +27 -0
- data/spec/associations/device_auth/user_infos_spec.rb +10 -0
- data/spec/associations/device_auth/videos_spec.rb +22 -0
- data/spec/associations/no_auth/annotations_spec.rb +15 -0
- data/spec/associations/server_auth/channels_spec.rb +2 -0
- data/spec/associations/server_auth/details_sets_spec.rb +18 -0
- data/spec/associations/server_auth/playlist_items_spec.rb +17 -0
- data/spec/associations/server_auth/playlists_spec.rb +17 -0
- data/spec/associations/server_auth/ratings_spec.rb +2 -0
- data/spec/associations/server_auth/snippets_spec.rb +28 -0
- data/spec/associations/server_auth/subscriptions_spec.rb +2 -0
- data/spec/associations/server_auth/user_infos_spec.rb +2 -0
- data/spec/associations/server_auth/videos_spec.rb +20 -0
- data/spec/collections/annotations_spec.rb +6 -0
- data/spec/collections/channels_spec.rb +6 -0
- data/spec/collections/details_sets_spec.rb +6 -0
- data/spec/collections/playlist_items_spec.rb +23 -0
- data/spec/collections/playlists_spec.rb +26 -0
- data/spec/collections/ratings_spec.rb +6 -0
- data/spec/collections/snippets_spec.rb +6 -0
- data/spec/collections/subscriptions_spec.rb +30 -0
- data/spec/collections/user_infos_spec.rb +6 -0
- data/spec/collections/videos_spec.rb +6 -0
- data/spec/models/annotation_spec.rb +131 -0
- data/spec/models/channel_spec.rb +13 -0
- data/spec/models/description_spec.rb +94 -0
- data/spec/models/details_set_spec.rb +23 -0
- data/spec/models/playlist_item_spec.rb +32 -0
- data/spec/models/playlist_spec.rb +52 -0
- data/spec/models/rating_spec.rb +13 -0
- data/spec/models/snippet_spec.rb +66 -0
- data/spec/models/status_spec.rb +42 -0
- data/spec/models/subscription_spec.rb +37 -0
- data/spec/models/user_info_spec.rb +69 -0
- data/spec/models/video_spec.rb +13 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/device_app.rb +16 -0
- data/spec/support/server_app.rb +10 -0
- data/yt.gemspec +30 -0
- metadata +209 -17
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
data/TODO.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
* find by url (either video or channel or.. playlist)
|
|
2
|
+
* Google accounts?
|
|
3
|
+
* ENV support
|
|
4
|
+
|
|
5
|
+
* add has_one :status to video
|
|
6
|
+
|
|
7
|
+
* operations like subscribe that require authentication should not fail if
|
|
8
|
+
called on Yt::Channel without auth but, similarly to account, show the prompt
|
|
9
|
+
or ask for the device code
|
|
10
|
+
|
|
11
|
+
* scope
|
data/bin/yt
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require 'yt'
|
|
5
|
+
rescue LoadError
|
|
6
|
+
require 'rubygems'
|
|
7
|
+
require 'yt'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
############################
|
|
11
|
+
|
|
12
|
+
Yt.configure do |config|
|
|
13
|
+
config.scenario = :server_app
|
|
14
|
+
config.api_key = ENV['YT_TEST_APP_SERVER_API_KEY']
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
############################
|
|
18
|
+
|
|
19
|
+
channel = Yt::Channel.new id: ARGV[0] || 'UCxO1tY8h1AhOz0T4ENwmpow'
|
|
20
|
+
|
|
21
|
+
puts "Title: #{channel.title}"
|
|
22
|
+
puts "Description: #{channel.description}"
|
|
23
|
+
puts "Thumbnail: #{channel.thumbnail_url}"
|
|
24
|
+
puts "Videos: "
|
|
25
|
+
channel.videos.each do |video|
|
|
26
|
+
puts " Annotations: #{video.annotations.count}"
|
|
27
|
+
puts " Duration: #{video.duration}s"
|
|
28
|
+
puts " Title: #{video.title}"
|
|
29
|
+
puts " Description: #{video.description}"
|
|
30
|
+
puts " Thumbnail: #{video.thumbnail_url}"
|
|
31
|
+
end
|
data/lib/yt.rb
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'yt/utils/request'
|
|
2
|
+
|
|
3
|
+
module Yt
|
|
4
|
+
module Actions
|
|
5
|
+
module Delete
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def do_delete(extra_delete_params = {})
|
|
10
|
+
request = Request.new delete_params.merge(extra_delete_params)
|
|
11
|
+
response = request.run
|
|
12
|
+
raise unless response.is_a? Net::HTTPNoContent
|
|
13
|
+
yield response.body
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def delete_params
|
|
17
|
+
{}.tap do |params|
|
|
18
|
+
params[:method] = :delete
|
|
19
|
+
params[:format] = :json
|
|
20
|
+
params[:host] = 'www.googleapis.com'
|
|
21
|
+
params[:scope] = 'https://www.googleapis.com/auth/youtube'
|
|
22
|
+
params[:auth] = @auth
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'yt/actions/list'
|
|
2
|
+
require 'yt/utils/request'
|
|
3
|
+
|
|
4
|
+
module Yt
|
|
5
|
+
module Actions
|
|
6
|
+
module DeleteAll
|
|
7
|
+
include List
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def do_delete_all(params = {})
|
|
12
|
+
where(params).map do |item|
|
|
13
|
+
yield item if block_given?
|
|
14
|
+
item.delete
|
|
15
|
+
end.tap { @items = [] }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def where(params = {})
|
|
19
|
+
list.find_all do |item|
|
|
20
|
+
params.all? do |method, value|
|
|
21
|
+
# TODO: could be symbol etc...
|
|
22
|
+
item.respond_to?(method) && item.send(method) == value
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'yt/utils/request'
|
|
2
|
+
|
|
3
|
+
module Yt
|
|
4
|
+
module Actions
|
|
5
|
+
module Insert
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def do_insert(extra_insert_params = {})
|
|
10
|
+
request = Request.new insert_params.merge(extra_insert_params)
|
|
11
|
+
response = request.run
|
|
12
|
+
raise unless response.is_a? Net::HTTPOK
|
|
13
|
+
@items = []
|
|
14
|
+
new_item response.body
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def insert_params
|
|
18
|
+
{}.tap do |params|
|
|
19
|
+
params[:method] = :post
|
|
20
|
+
params[:format] = :json
|
|
21
|
+
params[:host] = 'www.googleapis.com'
|
|
22
|
+
params[:body_type] = :json
|
|
23
|
+
params[:scope] = 'https://www.googleapis.com/auth/youtube'
|
|
24
|
+
params[:auth] = @auth
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'yt/utils/request'
|
|
2
|
+
|
|
3
|
+
module Yt
|
|
4
|
+
module Actions
|
|
5
|
+
module List
|
|
6
|
+
|
|
7
|
+
delegate :count, :first, :any?, :each, :map, to: :list
|
|
8
|
+
alias size count
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def list
|
|
13
|
+
@last_index, @page_token = 0, nil
|
|
14
|
+
Enumerator.new do |items|
|
|
15
|
+
while next_item = find_next
|
|
16
|
+
items << next_item
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def find_next
|
|
22
|
+
@items ||= []
|
|
23
|
+
if @items[@last_index].nil? && more_pages?
|
|
24
|
+
more_items = next_page.map{|data| new_item data}
|
|
25
|
+
@items.concat more_items
|
|
26
|
+
end
|
|
27
|
+
@items[(@last_index +=1) -1]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# To be overriden by the subclasses
|
|
31
|
+
def new_item(data)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def more_pages?
|
|
35
|
+
@last_index.zero? || !@page_token.nil?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def next_page
|
|
39
|
+
params = list_params.dup
|
|
40
|
+
params[:params][:pageToken] = @page_token if @page_token
|
|
41
|
+
next_page = fetch_page params
|
|
42
|
+
@page_token = next_page[:token]
|
|
43
|
+
next_page[:items]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def fetch_page(params = {})
|
|
47
|
+
request = Request.new params
|
|
48
|
+
response = request.run
|
|
49
|
+
raise unless response.is_a? Net::HTTPOK
|
|
50
|
+
token = response.body['nextPageToken']
|
|
51
|
+
items = response.body.fetch 'items', []
|
|
52
|
+
{items: items, token: token}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def list_params
|
|
56
|
+
{}.tap do |params|
|
|
57
|
+
params[:method] = :get
|
|
58
|
+
params[:format] = :json
|
|
59
|
+
params[:host] = 'www.googleapis.com'
|
|
60
|
+
params[:auth] = @auth
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'yt/utils/request'
|
|
2
|
+
|
|
3
|
+
module Yt
|
|
4
|
+
module Actions
|
|
5
|
+
module Update
|
|
6
|
+
def do_update(extra_update_params = {}, options = {})
|
|
7
|
+
request = Request.new update_params.deep_merge(extra_update_params)
|
|
8
|
+
response = request.run
|
|
9
|
+
expected_response = options.fetch :expect, Net::HTTPNoContent
|
|
10
|
+
raise unless response.is_a? expected_response
|
|
11
|
+
yield response.body
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def update_params
|
|
15
|
+
{}.tap do |params|
|
|
16
|
+
params[:method] = :put
|
|
17
|
+
params[:format] = :json
|
|
18
|
+
params[:host] = 'www.googleapis.com'
|
|
19
|
+
params[:scope] = 'https://www.googleapis.com/auth/youtube'
|
|
20
|
+
params[:auth] = @auth
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
|
2
|
+
require 'active_support/dependencies/autoload'
|
|
3
|
+
require 'active_support/core_ext/string/inflections' # for camelize
|
|
4
|
+
|
|
5
|
+
module Yt
|
|
6
|
+
module Associations
|
|
7
|
+
# @note: Using Autoload to avoid circular dependencies.
|
|
8
|
+
# For instance: Yt::Channel requires Yt::Base, which requires
|
|
9
|
+
# Yt::Associations, which requires Yt::Associations::Subscription,
|
|
10
|
+
# which requires Yt::Subscription, which requires Yt::Base
|
|
11
|
+
extend ActiveSupport::Autoload
|
|
12
|
+
|
|
13
|
+
autoload :Annotations
|
|
14
|
+
autoload :Channels
|
|
15
|
+
autoload :DetailsSets
|
|
16
|
+
autoload :PlaylistItems
|
|
17
|
+
autoload :Playlists
|
|
18
|
+
autoload :Ratings
|
|
19
|
+
autoload :Snippets
|
|
20
|
+
autoload :Statuses
|
|
21
|
+
autoload :Subscriptions
|
|
22
|
+
autoload :UserInfos
|
|
23
|
+
autoload :Videos
|
|
24
|
+
|
|
25
|
+
def has_many(attributes, options = {})
|
|
26
|
+
mod = attributes.to_s.sub(/.*\./, '').camelize
|
|
27
|
+
include "Yt::Associations::#{mod.pluralize}".constantize
|
|
28
|
+
delegate *options[:delegate], to: attributes if options[:delegate]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
alias has_one has_many
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'yt/collections/annotations'
|
|
2
|
+
|
|
3
|
+
module Yt
|
|
4
|
+
module Associations
|
|
5
|
+
# Provides the `has_many :annotations` method to YouTube resources,
|
|
6
|
+
# which allows to access to content annotation set-specific methods.
|
|
7
|
+
# YouTube resources with annotations are: videos.
|
|
8
|
+
module Annotations
|
|
9
|
+
def annotations
|
|
10
|
+
@annotations ||= Collections::Annotations.by_video self
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'yt/collections/channels'
|
|
2
|
+
|
|
3
|
+
module Yt
|
|
4
|
+
module Associations
|
|
5
|
+
# Provides the `has_one :channel` method to YouTube resources, which
|
|
6
|
+
# allows to access to channel-specific methods like.
|
|
7
|
+
# YouTube resources with a channel are: account.
|
|
8
|
+
module Channels
|
|
9
|
+
def channel
|
|
10
|
+
@channel ||= channels.first
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def channels
|
|
16
|
+
@channels ||= Collections::Channels.by_account self
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'yt/collections/details_sets'
|
|
2
|
+
|
|
3
|
+
module Yt
|
|
4
|
+
module Associations
|
|
5
|
+
# Provides the `has_one :details_set` method to YouTube resources, which
|
|
6
|
+
# allows to access to content detail set-specific methods like `duration`.
|
|
7
|
+
# YouTube resources with content details are: videos.
|
|
8
|
+
module DetailsSets
|
|
9
|
+
def details_set
|
|
10
|
+
@detail_set ||= details_sets.first
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def details_sets
|
|
16
|
+
@details_sets ||= Collections::DetailsSets.by_video self
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'yt/collections/playlist_items'
|
|
2
|
+
|
|
3
|
+
module Yt
|
|
4
|
+
module Associations
|
|
5
|
+
# Provides the `has_many :playlist_items` method to YouTube resources, which
|
|
6
|
+
# allows to invoke playlist_item-related methods, such as .add_video.
|
|
7
|
+
# YouTube resources with playlist items are: playlists.
|
|
8
|
+
module PlaylistItems
|
|
9
|
+
def playlist_items
|
|
10
|
+
@playlist_items ||= Collections::PlaylistItems.by_playlist self
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def add_video(video_id)
|
|
14
|
+
playlist_items.insert id: video_id, kind: :video
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def add_videos(video_ids = [])
|
|
18
|
+
video_ids.map{|video_id| add_video video_id}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def delete_playlist_items(attrs = {})
|
|
22
|
+
playlist_items.delete_all attrs
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'yt/collections/playlists'
|
|
2
|
+
|
|
3
|
+
module Yt
|
|
4
|
+
module Associations
|
|
5
|
+
# Provides the `has_many :playlists` method to YouTube resources, which
|
|
6
|
+
# allows to invoke playlist-related methods, such as .create_playlist.
|
|
7
|
+
# YouTube resources with playlist are: channels.
|
|
8
|
+
module Playlists
|
|
9
|
+
def playlists
|
|
10
|
+
@playlists ||= Collections::Playlists.by_channel self
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def create_playlist(params = {})
|
|
14
|
+
playlists.insert params
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def delete_playlists(attrs = {})
|
|
18
|
+
playlists.delete_all attrs
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'yt/collections/ratings'
|
|
2
|
+
|
|
3
|
+
module Yt
|
|
4
|
+
module Associations
|
|
5
|
+
# Provides the `has_one :rating` method to YouTube resources, which
|
|
6
|
+
# allows to invoke rating-related methods, such as .like.
|
|
7
|
+
# YouTube resources with rating are: videos.
|
|
8
|
+
module Ratings
|
|
9
|
+
def rating
|
|
10
|
+
@rating ||= ratings.first
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def liked?
|
|
14
|
+
rating.rating == :like
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def like
|
|
18
|
+
rating.update :like
|
|
19
|
+
liked?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def dislike
|
|
23
|
+
rating.update :dislike
|
|
24
|
+
!liked?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def unlike
|
|
28
|
+
rating.update :none
|
|
29
|
+
!liked?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def ratings
|
|
35
|
+
@ratings ||= Collections::Ratings.by_video self
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'yt/collections/snippets'
|
|
2
|
+
|
|
3
|
+
module Yt
|
|
4
|
+
module Associations
|
|
5
|
+
# Provides the `has_one :snippet` method to YouTube resources, which
|
|
6
|
+
# allows to access to content detail set-specific methods like `title`.
|
|
7
|
+
# YouTube resources with content details are: videos and channels.
|
|
8
|
+
module Snippets
|
|
9
|
+
def snippet
|
|
10
|
+
@snippet ||= snippets.first
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def snippets
|
|
16
|
+
@snippets ||= Collections::Snippets.by_resource self
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'yt/models/status'
|
|
2
|
+
|
|
3
|
+
module Yt
|
|
4
|
+
module Associations
|
|
5
|
+
# Provides the `has_one :status` method to YouTube resources, which
|
|
6
|
+
# allows to access to status-specific methods like `public?`.
|
|
7
|
+
# YouTube resources with status are: playlists.
|
|
8
|
+
module Statuses
|
|
9
|
+
def status
|
|
10
|
+
@status
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|