pexels 0.1.0 → 0.2.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 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
  - - ">="