yt 0.9.8 → 0.10.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/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
|