pexels 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f9609676bbaebe34889f5c6483f15f41831439eced062f91a7a1eb8fb0c1d8e
4
- data.tar.gz: a7be0c896cacd8e3bf02aaf5a87eaee7c0a7c3a17d1118b87f114da208972e0f
3
+ metadata.gz: 4a5483a85edfd47c6ae8585394c2f14e6de8e8eaf8b149e26594536411a821d4
4
+ data.tar.gz: '009e00ae30a63f652473bfecd7bc46c5dbfdb839b8c405d1cb5406b7898ce6ae'
5
5
  SHA512:
6
- metadata.gz: 506d3d399c0cc6655daead44255597131d162808b6b206e32aa7fd60022883703330f2527fb6d092b944ba31a9067b813f6e27f355f7dbc87dcbb3ab95984f2c
7
- data.tar.gz: c72ebaa5715f520f74a05941f384bcd1e6db62d45662f07f9a8afbc5236b85c6aa4527a1ccf6f2a74b9d95f36e42fe56c12333ee12411076a8cb6b0170c75105
6
+ metadata.gz: e55a644d3a0b7ee092796922eb6007d16667b1a5c1d794c66819e896bcde29df05d3129d5f508e48ffb2a54020f36c0fef21d4eb1f18384be0da741d81800012
7
+ data.tar.gz: e6421cd0f5ac1c92fd57c2af6239a4cb0001db5dcb8fb29349fab688d1508685e9e7ff755d9ffc420bbb365ec3f8fa2ef1fd3409653817aaeafb317833f67040
data/CHANGES.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Change log
2
2
 
3
+ ## 0.2.0
4
+ * Fixed incorrect URL for collections endpoints.
5
+ * Added pagination methods `next_page` and `prev_page` to `PaginatedResponse`.
6
+ * Added `total_pages` to `PaginatedResponse`.
7
+ * Extracted `Request` and `Response` objects for reusability.
8
+ * Added `Pexels/Ruby` `User-Agent` header to requests.
9
+
3
10
  ## 0.1.0
4
11
  * Add support for returning collections belonging to the API user.
5
12
  * Add support for returning media from a collection.
data/README.md CHANGED
@@ -33,7 +33,9 @@ client.photos.search('Cloud')
33
33
  ### Find a specific photo
34
34
 
35
35
  ```ruby
36
- client.photos[2014422] || client.photos.find(2014422)
36
+ client.photos[2014422]
37
+ # or
38
+ client.photos.find(2014422)
37
39
  ```
38
40
 
39
41
  ### Browse curated photos
@@ -51,7 +53,9 @@ client.videos.search('waves')
51
53
  ### Find a specific photo
52
54
 
53
55
  ```ruby
54
- client.videos[2014422] || client.videos.find(2014422)
56
+ client.videos[2014422]
57
+ # or
58
+ client.videos.find(2014422)
55
59
  ```
56
60
 
57
61
  ### Browse popular videos
@@ -60,6 +64,57 @@ client.videos[2014422] || client.videos.find(2014422)
60
64
  client.videos.popular
61
65
  ```
62
66
 
67
+ ### List all collections
68
+
69
+ Note: this is limited to collections belonging to the API user.
70
+
71
+ ```ruby
72
+ client.collections.all
73
+ ```
74
+
75
+ ### Get all media for a collection
76
+
77
+ ```ruby
78
+ client.collections['collection-id'].media
79
+ # or
80
+ client.collections.find('collection-id').media
81
+ ```
82
+
83
+ You can also filter for only `photos` or `videos`.
84
+
85
+ ```ruby
86
+ client.collections['collection-id', type: 'photos'].media
87
+ client.collections['collection-id', type: 'videos'].media
88
+ ```
89
+
90
+ ## Rate Limiting
91
+
92
+ After performing a request, you can access your remaining rate limit via the client.
93
+
94
+ ```ruby
95
+ client.ratelimit_remaining
96
+ ```
97
+
98
+ ## Pagination
99
+
100
+ Requests that return multiple objects are paginated. You can pass in `page` and `per_page` options to these requests to get a specific page. You can also access the total number of results by accessing `total_results` on the response.
101
+
102
+ Note: The Pexels API returns a maximum of 80 records for one request.
103
+
104
+ ```ruby
105
+ response = client.photos.search('dog', page: 2, per_page: 50)
106
+ response.total_results #=> 1000
107
+ response.total_pages #= 20
108
+ ```
109
+
110
+ If there are further pages, you can also paginate through the API client:
111
+
112
+ ```ruby
113
+ response = client.photos.search('dog', page: 2, per_page: 50)
114
+ response.prev_page # queries page 1
115
+ response.next_page # queries page 3
116
+ ```
117
+
63
118
  ## Running the test suite
64
119
 
65
120
  You'll need your own API key to run the test suite, you can get one on the [Pexels API Key management page](https://www.pexels.com/api/new/)
data/lib/pexels.rb CHANGED
@@ -23,6 +23,8 @@ module Pexels
23
23
  end
24
24
 
25
25
  require_relative 'pexels/client'
26
+ require_relative 'pexels/client/request'
27
+ require_relative 'pexels/client/response'
26
28
  require_relative 'pexels/client/collections'
27
29
  require_relative 'pexels/client/photos'
28
30
  require_relative 'pexels/client/videos'
data/lib/pexels/client.rb CHANGED
@@ -1,47 +1,29 @@
1
- require 'requests'
2
-
3
- class Pexels::Client
4
- attr_reader :api_key,
5
- :ratelimit_remaining
6
-
7
- def initialize(api_key = ENV['PEXELS_API_KEY'])
8
- @api_key = api_key
9
- end
10
-
11
- def photos
12
- @photos ||= Pexels::Client::Photos.new(self)
13
- end
14
-
15
- def videos
16
- @videos ||= Pexels::Client::Videos.new(self)
17
- end
18
-
19
- def collections
20
- @collections ||= Pexels::Client::Collections.new(self)
21
- end
22
-
23
- def request(path, method: 'GET', params: {})
24
- url = File.join(Pexels.api_base_url, path)
25
- headers = {
26
- 'Authorization' => api_key
27
- }.merge(Pexels.local_headers)
28
-
29
- puts "Requesting #{url} with #{headers}" if ENV['DEBUG']
30
-
31
- results = Requests.request(
32
- method,
33
- url,
34
- params: params,
35
- headers: headers
36
- )
37
-
38
- @ratelimit_remaining = results.headers['x-ratelimit-remaining']&.first&.to_i
39
-
40
- return JSON.parse(results.body)
41
- rescue StandardError => exception
42
- raise Pexels::APIError.new(exception)
1
+ module Pexels
2
+ class Client
3
+ attr_reader :api_key,
4
+ :ratelimit_remaining
5
+
6
+ def initialize(api_key = ENV['PEXELS_API_KEY'])
7
+ @api_key = api_key
8
+ end
9
+
10
+ def photos
11
+ @photos ||= Pexels::Client::Photos.new(self)
12
+ end
13
+
14
+ def videos
15
+ @videos ||= Pexels::Client::Videos.new(self)
16
+ end
17
+
18
+ def collections
19
+ @collections ||= Pexels::Client::Collections.new(self)
20
+ end
21
+
22
+ def request(path, method: 'GET', params: {})
23
+ request = Request.new(api_key, path, method, params)
24
+ request.call.tap do |response|
25
+ @ratelimit_remaining = response.ratelimit_remaining
26
+ end
27
+ end
43
28
  end
44
29
  end
45
-
46
- require 'pexels/client/photos'
47
- require 'pexels/client/videos'
@@ -5,7 +5,7 @@ class Pexels::Client::Collections
5
5
 
6
6
  def all(per_page: 15, page: 1)
7
7
  response = @client.request(
8
- '/collections',
8
+ "#{Pexels.api_version}/collections",
9
9
  params: {
10
10
  per_page: per_page,
11
11
  page: page
@@ -16,7 +16,7 @@ class Pexels::Client::Collections
16
16
 
17
17
  def [](id, type: nil, per_page: 15, page: 1)
18
18
  response = @client.request(
19
- "/collections/#{id}",
19
+ "#{Pexels.api_version}/collections/#{id}",
20
20
  params: {
21
21
  per_page: per_page,
22
22
  page: page,
@@ -6,7 +6,7 @@ class Pexels::Client::Photos
6
6
 
7
7
  def [](id)
8
8
  response = @client.request("#{Pexels.api_version}/photos/#{id}")
9
- Pexels::Photo.new(response)
9
+ Pexels::Photo.new(response.body)
10
10
  end
11
11
  alias_method :find, :[]
12
12
 
@@ -0,0 +1,53 @@
1
+ require 'requests'
2
+
3
+ module Pexels
4
+ class Client
5
+ class Request
6
+ attr_reader :api_key, :path, :method, :params
7
+
8
+ def initialize(api_key, path, method, params)
9
+ @api_key = api_key
10
+ @path = path
11
+ @method = method
12
+ @params = params
13
+ end
14
+
15
+ def call
16
+ log_request if ENV['DEBUG']
17
+
18
+ Response.new(self, execute)
19
+
20
+ rescue StandardError => exception
21
+ raise Pexels::APIError.new(exception)
22
+ end
23
+
24
+ private
25
+
26
+ def execute
27
+ Requests.request(
28
+ method,
29
+ url,
30
+ params: params,
31
+ headers: headers
32
+ )
33
+ end
34
+
35
+ def url
36
+ @url ||= File.join(Pexels.api_base_url, path)
37
+ end
38
+
39
+ def headers
40
+ @headers = {
41
+ 'Authorization' => api_key,
42
+ 'User-Agent' => "Pexels/Ruby (#{Pexels::VERSION})"
43
+ }.merge(Pexels.local_headers)
44
+ end
45
+
46
+ def log_request
47
+ puts "Requesting #{url}"
48
+ puts " → params: #{params}"
49
+ puts " → headers: #{headers}"
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,29 @@
1
+ require 'requests'
2
+
3
+ module Pexels
4
+ class Client
5
+ class Response
6
+ attr_reader :request, :response
7
+
8
+ def initialize(request, response)
9
+ @request = request
10
+ @response = response
11
+ end
12
+
13
+ def body
14
+ JSON.parse(response.body)
15
+
16
+ rescue JSON::JSONError => exception
17
+ raise Pexels::APIError.new(exception)
18
+ end
19
+
20
+ def headers
21
+ response.headers
22
+ end
23
+
24
+ def ratelimit_remaining
25
+ headers['x-ratelimit-remaining']&.first&.to_i
26
+ end
27
+ end
28
+ end
29
+ end
@@ -6,7 +6,7 @@ class Pexels::Client::Videos
6
6
 
7
7
  def [](id)
8
8
  response = @client.request("/videos/videos/#{id}")
9
- Pexels::Video.new(response)
9
+ Pexels::Video.new(response.body)
10
10
  end
11
11
  alias_method :find, :[]
12
12
 
@@ -5,7 +5,7 @@ module Pexels
5
5
 
6
6
  attr_reader :id
7
7
 
8
- def initialize(attrs)
8
+ def initialize(response)
9
9
  super
10
10
  @id = attrs.fetch('id')
11
11
  @data = attrs.fetch('media', []).map do |attrs|
@@ -3,7 +3,7 @@ module Pexels
3
3
  alias_method :collections, :data
4
4
  public :collections
5
5
 
6
- def initialize(attrs)
6
+ def initialize(response)
7
7
  super
8
8
  @data = attrs.fetch('collections', []).map { |attrs| Pexels::Collection.new(attrs) }
9
9
  end
@@ -1,3 +1,5 @@
1
+ require 'cgi'
2
+
1
3
  module Pexels
2
4
  class PaginatedResponse
3
5
  include Enumerable
@@ -5,18 +7,25 @@ module Pexels
5
7
  attr_reader :total_results,
6
8
  :page,
7
9
  :per_page,
8
- :next_page,
9
10
  :data
10
11
 
11
12
  private :data
12
13
 
13
- def initialize(attrs)
14
+ def initialize(response)
15
+ @response = response
16
+ @attrs = @response.body
17
+
14
18
  @total_results = attrs.fetch('total_results', nil)
15
19
  @page = attrs.fetch('page')
16
20
  @per_page = attrs.fetch('per_page')
21
+ @prev_page = attrs.fetch('prev_page', nil)
17
22
  @next_page = attrs.fetch('next_page', nil)
18
23
  end
19
24
 
25
+ def total_pages
26
+ total_results.fdiv(per_page).ceil
27
+ end
28
+
20
29
  def each(&block)
21
30
  if block_given?
22
31
  data.each(&block)
@@ -24,5 +33,31 @@ module Pexels
24
33
  to_enum(:each)
25
34
  end
26
35
  end
36
+
37
+ def next_page
38
+ return unless @next_page
39
+
40
+ request.params[:page] = extract_page(@next_page)
41
+ self.class.new(request.call)
42
+ end
43
+
44
+ def prev_page
45
+ return unless @prev_page
46
+
47
+ request.params[:page] = extract_page(@next_page)
48
+ self.class.new(request.call)
49
+ end
50
+
51
+ private
52
+
53
+ attr_reader :response, :attrs
54
+
55
+ def request
56
+ response.request
57
+ end
58
+
59
+ def extract_page(url)
60
+ CGI.parse(URI.parse(url).query)['page'].first
61
+ end
27
62
  end
28
63
  end
@@ -3,7 +3,7 @@ module Pexels
3
3
  alias_method :photos, :data
4
4
  public :photos
5
5
 
6
- def initialize(attrs)
6
+ def initialize(response)
7
7
  super
8
8
  @data = attrs.fetch('photos', []).map { |attrs| Pexels::Photo.new(attrs) }
9
9
 
@@ -1,3 +1,3 @@
1
1
  module Pexels
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -3,7 +3,7 @@ module Pexels
3
3
  alias_method :videos, :data
4
4
  public :videos
5
5
 
6
- def initialize(attrs)
6
+ def initialize(response)
7
7
  super
8
8
  @data = attrs.fetch('videos', []).map { |attrs| Pexels::Video.new(attrs) }
9
9
 
data/pexels.gemspec CHANGED
@@ -11,5 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.license = 'MIT'
12
12
  s.files = `git ls-files`.split("\n")
13
13
 
14
+ s.required_ruby_version = '>= 2.4.0'
15
+
14
16
  s.add_dependency('requests', '~> 1.0.2')
15
17
  end
data/test/client_test.rb CHANGED
@@ -15,7 +15,7 @@ class TestClient < Minitest::Test
15
15
  assert remaining >= 0
16
16
 
17
17
  @client.photos.search('test')
18
- assert_equal remaining, @client.ratelimit_remaining + 1
18
+ assert_equal @client.ratelimit_remaining, remaining - 1
19
19
  end
20
20
 
21
21
  def test_exceptions
@@ -26,7 +26,7 @@ class TestClient < Minitest::Test
26
26
  @client.photos.search('test')
27
27
  raise 'this shouldnt happen'
28
28
  rescue StandardError => exception
29
- assert exception.is_a? Pexels::APIError
29
+ assert_kind_of Pexels::APIError, exception
30
30
  assert exception.message != 'this shouldnt happen'
31
31
  end
32
32
  end
@@ -9,28 +9,30 @@ class TestCollections < Minitest::Test
9
9
  end
10
10
 
11
11
  def test_all
12
- search_result = @client.collections.all
12
+ collection = @client.collections.all
13
13
 
14
- assert search_result.is_a? Pexels::CollectionSet
15
- assert_equal search_result.per_page, 15
16
- assert_equal search_result.page, 1
14
+ assert_kind_of Pexels::CollectionSet, collection
15
+ assert_equal collection.per_page, 15
16
+ assert_equal collection.page, 1
17
17
 
18
- assert search_result.collections.is_a? Array
19
- assert search_result.collections.any?
20
- assert search_result.first.is_a? Pexels::Collection
18
+ assert collection.collections.is_a? Array
19
+ assert collection.collections.any?
20
+ assert collection.first.is_a? Pexels::Collection
21
21
 
22
- search_result_with_params = @client.collections.all(per_page: 1, page: 2)
23
- assert_equal search_result_with_params.per_page, 1
24
- assert_equal search_result_with_params.page, 2
25
- assert_equal search_result_with_params.collections.length, 1
22
+ collection_with_params = @client.collections.all(per_page: 1, page: 2)
23
+ assert_equal collection_with_params.per_page, 1
24
+ assert_equal collection_with_params.page, 2
25
+ assert_equal collection_with_params.collections.length, 1
26
+ assert_kind_of Pexels::CollectionSet, collection_with_params.next_page
27
+ assert_kind_of Pexels::CollectionSet, collection_with_params.prev_page
26
28
  end
27
29
 
28
30
  def test_get_collection_media
29
31
  collection = @client.collections[@collection.id]
30
- assert collection.is_a? Pexels::CollectionMediaSet
32
+ assert_kind_of Pexels::CollectionMediaSet, collection
31
33
  assert_equal collection.id, @collection.id
32
34
 
33
- assert collection.media.is_a? Array
35
+ assert_kind_of Array, collection.media
34
36
  assert collection.media.any?
35
37
 
36
38
  assert_includes([Pexels::Photo, Pexels::Video], collection.media.first.class)
@@ -41,29 +43,29 @@ class TestCollections < Minitest::Test
41
43
 
42
44
  def test_get_collection_photos
43
45
  collection = @client.collections[@collection.id, type: 'photos']
44
- assert collection.is_a? Pexels::CollectionMediaSet
45
- assert collection.media.is_a? Array
46
+ assert_kind_of Pexels::CollectionMediaSet, collection
47
+ assert_kind_of Array, collection.media
46
48
  assert collection.media.all? { |m| m.is_a?(Pexels::Photo) }
47
49
  end
48
50
 
49
51
  def test_get_collection_videos
50
52
  collection = @client.collections[@collection.id, type: 'videos']
51
- assert collection.is_a? Pexels::CollectionMediaSet
52
- assert collection.media.is_a? Array
53
+ assert_kind_of Pexels::CollectionMediaSet, collection
54
+ assert_kind_of Array, collection.media
53
55
  assert collection.media.all? { |m| m.is_a?(Pexels::Video) }
54
56
  end
55
57
 
56
58
  def test_get_collection_invalid_type
57
59
  collection = @client.collections[@collection.id, type: 'foo']
58
- assert collection.is_a? Pexels::CollectionMediaSet
59
- assert collection.media.is_a? Array
60
+ assert_kind_of Pexels::CollectionMediaSet, collection
61
+ assert_kind_of Array, collection.media
60
62
  assert collection.any?
61
63
  end
62
64
 
63
65
  def test_get_collection_pagination
64
66
  collection = @client.collections[@collection.id, per_page: 1, page: 1]
65
- assert collection.is_a? Pexels::CollectionMediaSet
66
- assert collection.media.is_a? Array
67
+ assert_kind_of Pexels::CollectionMediaSet, collection
68
+ assert_kind_of Array, collection.media
67
69
  assert collection.media.any?
68
70
 
69
71
  assert_equal collection.per_page, 1
data/test/photo_test.rb CHANGED
@@ -11,9 +11,9 @@ class TestPhoto < Minitest::Test
11
11
  def test_successful_searches
12
12
  search_result = @client.photos.search('test')
13
13
 
14
- assert search_result.is_a? Pexels::PhotoSet
15
- assert search_result.next_page.is_a? String
16
- assert search_result.total_results.is_a? Integer
14
+ assert_kind_of Pexels::PhotoSet, search_result
15
+ assert_kind_of Pexels::PhotoSet, search_result.next_page
16
+ assert_kind_of Integer, search_result.total_results
17
17
  assert_equal search_result.per_page, 15
18
18
  assert_equal search_result.page, 1
19
19
 
@@ -25,13 +25,14 @@ class TestPhoto < Minitest::Test
25
25
  assert_equal search_result_with_params.per_page, 1
26
26
  assert_equal search_result_with_params.page, 2
27
27
  assert_equal search_result_with_params.photos.length, 1
28
+ assert_kind_of Pexels::PhotoSet, search_result_with_params.prev_page
28
29
  end
29
30
 
30
31
  def test_curated_photos
31
32
  search_result = @client.photos.curated
32
33
 
33
- assert search_result.is_a? Pexels::PhotoSet
34
- assert search_result.next_page.is_a? String
34
+ assert_kind_of Pexels::PhotoSet, search_result
35
+ assert_kind_of Pexels::PhotoSet, search_result.next_page
35
36
  assert_equal search_result.per_page, 15
36
37
  assert_equal search_result.page, 1
37
38
 
@@ -43,6 +44,7 @@ class TestPhoto < Minitest::Test
43
44
  assert_equal search_result_with_params.per_page, 1
44
45
  assert_equal search_result_with_params.page, 2
45
46
  assert_equal search_result_with_params.photos.length, 1
47
+ assert_kind_of Pexels::PhotoSet, search_result_with_params.prev_page
46
48
  end
47
49
 
48
50
  def test_get_photo
data/test/video_test.rb CHANGED
@@ -11,8 +11,9 @@ class TestVideo < Minitest::Test
11
11
  def test_successful_searches
12
12
  search_result = @client.videos.search('test')
13
13
 
14
- assert search_result.is_a? Pexels::VideoSet
15
- assert search_result.total_results.is_a? Integer
14
+ assert_kind_of Pexels::VideoSet, search_result
15
+ assert_kind_of Pexels::VideoSet, search_result.next_page
16
+ assert_kind_of Integer, search_result.total_results
16
17
  assert_equal search_result.per_page, 15
17
18
  assert_equal search_result.page, 1
18
19
 
@@ -24,12 +25,14 @@ class TestVideo < Minitest::Test
24
25
  assert_equal search_result_with_params.per_page, 1
25
26
  assert_equal search_result_with_params.page, 2
26
27
  assert_equal search_result_with_params.videos.length, 1
28
+ assert_kind_of Pexels::VideoSet, search_result_with_params.prev_page
27
29
  end
28
30
 
29
31
  def test_popular_videos
30
32
  search_result = @client.videos.popular
31
33
 
32
- assert search_result.is_a? Pexels::VideoSet
34
+ assert_kind_of Pexels::VideoSet, search_result
35
+ assert_kind_of Pexels::VideoSet, search_result.next_page
33
36
  assert_equal search_result.per_page, 15
34
37
  assert_equal search_result.page, 1
35
38
 
@@ -41,6 +44,7 @@ class TestVideo < Minitest::Test
41
44
  assert_equal search_result_with_params.per_page, 1
42
45
  assert_equal search_result_with_params.page, 2
43
46
  assert_equal search_result_with_params.videos.length, 1
47
+ assert_kind_of Pexels::VideoSet, search_result_with_params.prev_page
44
48
  end
45
49
 
46
50
  def test_get_video
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pexels
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pexels dev team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-09 00:00:00.000000000 Z
11
+ date: 2021-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: requests
@@ -42,6 +42,8 @@ files:
42
42
  - lib/pexels/client.rb
43
43
  - lib/pexels/client/collections.rb
44
44
  - lib/pexels/client/photos.rb
45
+ - lib/pexels/client/request.rb
46
+ - lib/pexels/client/response.rb
45
47
  - lib/pexels/client/videos.rb
46
48
  - lib/pexels/collection.rb
47
49
  - lib/pexels/collection_media_set.rb
@@ -73,7 +75,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
73
75
  requirements:
74
76
  - - ">="
75
77
  - !ruby/object:Gem::Version
76
- version: '0'
78
+ version: 2.4.0
77
79
  required_rubygems_version: !ruby/object:Gem::Requirement
78
80
  requirements:
79
81
  - - ">="