yt 0.9.8 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -4
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/lib/yt/actions/list.rb +12 -3
- data/lib/yt/collections/annotations.rb +9 -0
- data/lib/yt/models/policy.rb +3 -2
- data/lib/yt/version.rb +1 -1
- data/spec/collections/videos_spec.rb +14 -1
- data/spec/models/policy_spec.rb +2 -2
- data/spec/requests/as_account/channel_spec.rb +8 -4
- data/spec/requests/as_content_owner/content_owner_spec.rb +2 -3
- data/spec/requests/as_server_app/channel_spec.rb +2 -1
- data/spec/requests/unauthenticated/video_spec.rb +2 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15eb05d2e208d7879df8f1782afe21ce6180a00b
|
4
|
+
data.tar.gz: 6988cf951189228e648dab9af35584be0ba41370
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 800515d67a7c6b4a905d2fd2f70c65f51552a26848a540d0abd603dc2b7c65dc89c30a94ea079e0a1744594cbfe981e5359b8ac1780f97d94d26c3a6de7005f1
|
7
|
+
data.tar.gz: 0b97816f0f4dcefbb5fc50794abae380293f19cb1db44aa10ca0ccaa2af7056700809aff7fdcf6181a8b88db59ba5735d02c6bea397ae4f6de21d806fb1d8a38
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,33 @@ For more information about changelogs, check
|
|
6
6
|
[Keep a Changelog](http://keepachangelog.com) and
|
7
7
|
[Vandamme](http://tech-angels.github.io/vandamme).
|
8
8
|
|
9
|
+
## 0.10.0 - 2014-08-11
|
10
|
+
|
11
|
+
**How to upgrade**
|
12
|
+
|
13
|
+
If your code never calls the `size` method to count how many items a list of
|
14
|
+
results has (e.g., how many videos an account has), then you are good to go.
|
15
|
+
|
16
|
+
If it does, then be aware that `size` will now return try to the number of
|
17
|
+
items as specified in the "totalResults" field of the first page of the YouTube
|
18
|
+
response, rather than loading *all* the pages (possibly thousands) and counting
|
19
|
+
exactly how many items are returned.
|
20
|
+
|
21
|
+
If this is acceptable, then you are good to go.
|
22
|
+
If you want the old behavior, replace `size` with `count`:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
account = Yt::Account.new access_token: 'ya29...'
|
26
|
+
# old behavior
|
27
|
+
account.videos.size # => retrieved *all* the pages of the account’s videos
|
28
|
+
# new behavior
|
29
|
+
account.videos.size # => retrieves only the first page, returning the totalResults counter
|
30
|
+
account.videos.count # => retrieves *all* the pages of the account’s videos
|
31
|
+
```
|
32
|
+
|
33
|
+
* [ENHANCEMENT] Calling `size` on a collection does not load all the pages of the collection
|
34
|
+
* [ENHANCEMENT] Alias `policy.time_updated` to more coherent `policy.updated_at`
|
35
|
+
|
9
36
|
## 0.9.8 - 2014-08-11
|
10
37
|
|
11
38
|
* [FEATURE] Add `.content_owner` and `.linked_at` to channels managed by a CMS content owner
|
@@ -117,18 +144,21 @@ If your code never declares instances of `Yt::Channel`, or never calls the
|
|
117
144
|
|
118
145
|
If it does, then be aware that `subscribe` will not raise an error anymore if
|
119
146
|
a YouTube user tries to subscribe to her/his own YouTube channel. Instead,
|
120
|
-
`subscribe` will simply return `nil`.
|
121
|
-
|
147
|
+
`subscribe` will simply return `nil`.
|
148
|
+
|
149
|
+
If this is acceptable, then you are good to go.
|
150
|
+
If you want the old behavior, replace `subscribe` with `subscribe!`:
|
122
151
|
|
123
152
|
```ruby
|
124
153
|
account = Yt::Account.new access_token: 'ya29...'
|
125
154
|
channel = account.channel
|
126
155
|
# old behavior
|
127
|
-
channel.subscribe # =>
|
156
|
+
channel.subscribe # => raised an error
|
128
157
|
# new behavior
|
129
158
|
channel.subscribe # => nil
|
130
|
-
channel.subscribe! # =>
|
159
|
+
channel.subscribe! # => raises an error
|
131
160
|
```
|
161
|
+
|
132
162
|
* [ENHANCEMENT] `channel.subscribe` does not raise error when trying to subscribe to one’s own channel
|
133
163
|
|
134
164
|
## 0.7 - 2014/06/18
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -41,7 +41,7 @@ To install on your system, run
|
|
41
41
|
|
42
42
|
To use inside a bundled Ruby project, add this line to the Gemfile:
|
43
43
|
|
44
|
-
gem 'yt', '~> 0.
|
44
|
+
gem 'yt', '~> 0.10.0'
|
45
45
|
|
46
46
|
Since the gem follows [Semantic Versioning](http://semver.org),
|
47
47
|
indicating the full version in your Gemfile (~> *major*.*minor*.*patch*)
|
data/lib/yt/actions/list.rb
CHANGED
@@ -4,8 +4,8 @@ require 'yt/errors/no_items'
|
|
4
4
|
module Yt
|
5
5
|
module Actions
|
6
6
|
module List
|
7
|
-
delegate :count, :first, :any?, :each, :map, :flat_map, :find,
|
8
|
-
|
7
|
+
delegate :count, :first, :any?, :each, :map, :flat_map, :find,
|
8
|
+
:size, to: :list
|
9
9
|
|
10
10
|
def first!
|
11
11
|
first.tap{|item| raise Errors::NoItems, last_request unless item}
|
@@ -15,7 +15,7 @@ module Yt
|
|
15
15
|
|
16
16
|
def list
|
17
17
|
@last_index, @page_token = 0, nil
|
18
|
-
Enumerator.new do |items|
|
18
|
+
Enumerator.new(-> {total_results}) do |items|
|
19
19
|
while next_item = find_next
|
20
20
|
items << next_item
|
21
21
|
end
|
@@ -23,6 +23,15 @@ module Yt
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
# @private
|
27
|
+
# Returns the total number of items that YouTube can provide for the
|
28
|
+
# given request, either all in one page or in consecutive pages.
|
29
|
+
def total_results
|
30
|
+
response = request(list_params).run
|
31
|
+
total_results = response.body.fetch('pageInfo', {})['totalResults']
|
32
|
+
total_results ||= response.body.fetch(items_key, []).size
|
33
|
+
end
|
34
|
+
|
26
35
|
def find_next
|
27
36
|
@items ||= []
|
28
37
|
if @items[@last_index].nil? && more_pages?
|
@@ -46,6 +46,15 @@ module Yt
|
|
46
46
|
expected?(error) ? [] : raise(error)
|
47
47
|
end
|
48
48
|
|
49
|
+
# @private
|
50
|
+
# @note Annotations overwrites +total_results+ since `items_key` is
|
51
|
+
# not `items` for annotations.
|
52
|
+
# @todo Remove this function by extracting the keys used by annotations
|
53
|
+
# in a method and reusing them both in `next_page` and `total_results`.
|
54
|
+
def total_results
|
55
|
+
count
|
56
|
+
end
|
57
|
+
|
49
58
|
# Since there is no API endpoint, retrieving annotations of unknown
|
50
59
|
# videos or of private videos (to which YouTube responds with 403)
|
51
60
|
# should not raise an error, but simply not return any annotation.
|
data/lib/yt/models/policy.rb
CHANGED
@@ -29,9 +29,10 @@ module Yt
|
|
29
29
|
end
|
30
30
|
|
31
31
|
# @return [String] the time the policy was updated.
|
32
|
-
def
|
33
|
-
@
|
32
|
+
def updated_at
|
33
|
+
@updated_at ||= Time.parse @data['timeUpdated']
|
34
34
|
end
|
35
|
+
alias time_updated updated_at
|
35
36
|
|
36
37
|
# @return [Array<PolicyRule>] a list of rules that specify the action
|
37
38
|
# that YouTube should take and may optionally specify the conditions
|
data/lib/yt/version.rb
CHANGED
@@ -6,9 +6,22 @@ describe Yt::Collections::Videos do
|
|
6
6
|
subject(:collection) { Yt::Collections::Videos.new parent: channel }
|
7
7
|
let(:channel) { Yt::Channel.new id: 'any-id' }
|
8
8
|
let(:page) { {items: [], token: 'any-token'} }
|
9
|
-
|
9
|
+
|
10
|
+
describe '#size' do
|
11
|
+
describe 'sends only one request and return the total results' do
|
12
|
+
let(:total_results) { 123456 }
|
13
|
+
before do
|
14
|
+
expect_any_instance_of(Yt::Request).to receive(:run).once do
|
15
|
+
double(body: {'pageInfo'=>{'totalResults'=>total_results}})
|
16
|
+
end
|
17
|
+
end
|
18
|
+
it { expect(collection.size).to be total_results }
|
19
|
+
end
|
20
|
+
end
|
10
21
|
|
11
22
|
describe '#count' do
|
23
|
+
let(:query) { {q: 'search string'} }
|
24
|
+
|
12
25
|
context 'called once with .where(query) and once without' do
|
13
26
|
after do
|
14
27
|
collection.where(query).count
|
data/spec/models/policy_spec.rb
CHANGED
@@ -25,10 +25,10 @@ describe Yt::Policy do
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
describe '#
|
28
|
+
describe '#updated_at' do
|
29
29
|
context 'given fetching a policy returns a timeUpdated' do
|
30
30
|
let(:data) { {"timeUpdated"=>"1970-01-16T20:33:03.675Z"} }
|
31
|
-
it { expect(policy.
|
31
|
+
it { expect(policy.updated_at.year).to be 1970 }
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -42,12 +42,15 @@ describe Yt::Channel, :device_app do
|
|
42
42
|
it { expect(channel.unsubscribe!).to be_truthy }
|
43
43
|
end
|
44
44
|
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
45
|
+
# @note: these tests are slow because they go through multiple pages of
|
46
|
+
# results and do so to test that we can overcome YouTube’s limitation of
|
47
|
+
# only returning the first 500 results for each query.
|
48
|
+
# @note: in principle, the following three counters should match, but in
|
49
|
+
# reality +video_count+ and +size+ are only approximations.
|
48
50
|
context 'with more than 500 videos' do
|
49
51
|
let(:id) { 'UCsmvakQZlvGsyjyOhmhvOsw' }
|
50
52
|
it { expect(channel.video_count).to be > 500 }
|
53
|
+
it { expect(channel.videos.size).to be > 500 }
|
51
54
|
it { expect(channel.videos.count).to be > 500 }
|
52
55
|
end
|
53
56
|
end
|
@@ -126,7 +129,8 @@ describe Yt::Channel, :device_app do
|
|
126
129
|
# NOTE: This test is just a reflection of YouTube irrational behavior of
|
127
130
|
# returns 0 results if the name of an unknown channel starts with UC, but
|
128
131
|
# returning 100,000 results otherwise (ignoring the channel filter).
|
129
|
-
it { expect(channel.videos.count).to
|
132
|
+
it { expect(channel.videos.count).to be_zero }
|
133
|
+
it { expect(channel.videos.size).to be_zero }
|
130
134
|
end
|
131
135
|
end
|
132
136
|
end
|
@@ -3,8 +3,7 @@ require 'yt/models/content_owner'
|
|
3
3
|
|
4
4
|
describe Yt::ContentOwner, :partner do
|
5
5
|
describe '.partnered_channels' do
|
6
|
-
|
7
|
-
# it { expect($content_owner.partnered_channels.size).to be > 0 }
|
6
|
+
it { expect($content_owner.partnered_channels.size).to be > 0 }
|
8
7
|
it { expect($content_owner.partnered_channels.first).to be_a Yt::Channel }
|
9
8
|
end
|
10
9
|
|
@@ -129,7 +128,7 @@ describe Yt::ContentOwner, :partner do
|
|
129
128
|
it 'returns valid metadata' do
|
130
129
|
expect(policy.id).to be_a String
|
131
130
|
expect(policy.name).to be_a String
|
132
|
-
expect(policy.
|
131
|
+
expect(policy.updated_at).to be_a Time
|
133
132
|
expect(rule.action).to be_in Yt::PolicyRule::ACTIONS
|
134
133
|
expect(rule.included_territories).to be_an Array
|
135
134
|
expect(rule.excluded_territories).to be_an Array
|
@@ -36,7 +36,8 @@ describe Yt::Channel, :server_app do
|
|
36
36
|
# NOTE: This test is just a reflection of YouTube irrational behavior of
|
37
37
|
# returns 0 results if the name of an unknown channel starts with UC, but
|
38
38
|
# returning 100,000 results otherwise (ignoring the channel filter).
|
39
|
-
it { expect(channel.videos.count).to
|
39
|
+
it { expect(channel.videos.count).to be_zero }
|
40
|
+
it { expect(channel.videos.size).to be_zero }
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
@@ -9,6 +9,7 @@ describe Yt::Video do
|
|
9
9
|
|
10
10
|
it { expect(video.annotations).to be_a Yt::Collections::Annotations }
|
11
11
|
it { expect(video.annotations.first).to be_a Yt::Annotation }
|
12
|
+
it { expect(video.annotations.size).to be > 0 }
|
12
13
|
end
|
13
14
|
|
14
15
|
context 'given a private video' do
|
@@ -16,5 +17,6 @@ describe Yt::Video do
|
|
16
17
|
|
17
18
|
it { expect(video.annotations).to be_a Yt::Collections::Annotations }
|
18
19
|
it { expect(video.annotations.count).to be_zero }
|
20
|
+
it { expect(video.annotations.size).to be_zero }
|
19
21
|
end
|
20
22
|
end
|