pexels 0.0.3 → 0.3.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: fd0b9df9874a218b1f0553181a9fafe4f78719c7323acd8b74015ed8c472f99c
4
- data.tar.gz: 327f7cbd27a846c8a05cc1cb89061ec31e4aee6e885a2e6776b1c802ef3cc104
3
+ metadata.gz: fbc208fe2d27e3dca7c1b94e0e2a3901334d06b9cf3460d952a44aea437bd82e
4
+ data.tar.gz: f4796400297cf53c41b0740eb57ae9b70efd697018d20c17c0e91f92c9030dc6
5
5
  SHA512:
6
- metadata.gz: 3a0d3dacb30401f4d1e0de8322ec47f0e8949dbfe53b216832aa0a79361666f5cbb5c9838ab8ac904333537040d6a9639152b6ad7de5098325e1488619971116
7
- data.tar.gz: 30d628a14aa5d60094501448caae6747deb8e4ea56f5b6e5cfa4c59da65bda750a3d3247c4f09b6bb47dec3a996335dca346d85470db0b65f07aee7c7c70a2b9
6
+ metadata.gz: e050b1e25f4f66b370f1acd2695af58305cd221e7c7d9a67cf4f989bdc3959af172aaebc65b545507992af0a6d24594e19601f316f5b1e2145ebbbc59eae46ce
7
+ data.tar.gz: 5a334832f860fcbb21dde178bdd871491d70efdeccfa5515309186596fcd1884b4ca3884bd6a6574343daa40623524ce20137366096460a015372a09365020aa
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  .gems.up.to.date
2
2
  .env
3
3
  *.gem
4
+ .headers
data/CHANGES.md ADDED
@@ -0,0 +1,25 @@
1
+ # Change log
2
+
3
+ ## 0.3.0
4
+ * Add support for photo and video search with filters.
5
+ * Added `avg_color` attribute to `Photo` object.
6
+
7
+ ## 0.2.1
8
+ * Added `type`, `photo?` and `video?` helper methods to `Photo` and `Video` classes.
9
+
10
+ ## 0.2.0
11
+ * Fixed incorrect URL for collections endpoints.
12
+ * Added pagination methods `next_page` and `prev_page` to `PaginatedResponse`.
13
+ * Added `total_pages` to `PaginatedResponse`.
14
+ * Extracted `Request` and `Response` objects for reusability.
15
+ * Added `Pexels/Ruby` `User-Agent` header to requests.
16
+
17
+ ## 0.1.0
18
+ * Add support for returning collections belonging to the API user.
19
+ * Add support for returning media from a collection.
20
+
21
+ ## 0.0.4
22
+ * Add `find` as an alias for `photos[]` and `videos[]`.
23
+
24
+ ## 0.0.3
25
+ * Initial release.
data/README.md CHANGED
@@ -12,7 +12,7 @@ Or add it to your `Gemfile` and run `bundle install`.
12
12
 
13
13
  ## Documentation
14
14
 
15
- See the API docs [here](https://www.pexels.com/api/documentation/?language=js)
15
+ See the API docs [here](https://www.pexels.com/api/documentation/?language=rb)
16
16
 
17
17
 
18
18
  ## Basic usage
@@ -34,6 +34,8 @@ client.photos.search('Cloud')
34
34
 
35
35
  ```ruby
36
36
  client.photos[2014422]
37
+ # or
38
+ client.photos.find(2014422)
37
39
  ```
38
40
 
39
41
  ### Browse curated photos
@@ -52,6 +54,8 @@ client.videos.search('waves')
52
54
 
53
55
  ```ruby
54
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]
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
@@ -1,19 +1,44 @@
1
1
  module Pexels
2
- @api_base_url = 'https://api.pexels.com'
2
+ @api_base_url = ENV['PEXELS_API_BASE_URL'] || 'https://api.pexels.com'
3
+ @api_version = ENV['PEXELS_API_VERSION'] || 'v1'
3
4
 
4
5
  class << self
5
- attr_reader :api_base_url
6
+ attr_reader :api_base_url, :api_version
7
+
8
+ # Local headers can be defined inside a `.headers` file at the project root,
9
+ # with the following format:
10
+ #
11
+ # header1=value
12
+ # header2=value
13
+ # etc.
14
+ #
15
+ def local_headers
16
+ @local_headers ||= if File.exist?('.headers')
17
+ File.read('.headers').split.to_h { |header| header.split('=') }
18
+ else
19
+ {}
20
+ end
21
+ end
6
22
  end
7
23
  end
8
24
 
9
25
  require_relative 'pexels/client'
26
+ require_relative 'pexels/client/request'
27
+ require_relative 'pexels/client/response'
28
+ require_relative 'pexels/client/search_filters'
29
+ require_relative 'pexels/client/collections'
10
30
  require_relative 'pexels/client/photos'
11
31
  require_relative 'pexels/client/videos'
12
32
  require_relative 'pexels/version'
13
33
  require_relative 'pexels/errors'
34
+ require_relative 'pexels/collection'
14
35
  require_relative 'pexels/photo'
15
36
  require_relative 'pexels/video'
16
37
  require_relative 'pexels/video/file'
17
38
  require_relative 'pexels/video/picture'
18
39
  require_relative 'pexels/user'
19
- require_relative 'pexels/response'
40
+ require_relative 'pexels/paginated_response'
41
+ require_relative 'pexels/collection_set'
42
+ require_relative 'pexels/collection_media_set'
43
+ require_relative 'pexels/photo_set'
44
+ require_relative 'pexels/video_set'
data/lib/pexels/client.rb CHANGED
@@ -1,39 +1,29 @@
1
- require 'requests'
2
-
3
- class Pexels::Client
4
- attr_reader :api_key,
5
- :ratelimit_remaining
6
-
7
-
8
- def initialize(api_key = ENV['PEXELS_API_KEY'])
9
- @api_key = api_key
10
- end
11
-
12
- def photos
13
- @photos ||= Pexels::Client::Photos.new(self)
14
- end
15
-
16
- def videos
17
- @videos ||= Pexels::Client::Videos.new(self)
18
- end
19
-
20
- def request(path, method: 'GET', params: {})
21
- results = Requests.request(
22
- method,
23
- "#{Pexels.api_base_url}#{path}",
24
- params: params,
25
- headers: {
26
- 'Authorization' => api_key
27
- }
28
- )
29
-
30
- @ratelimit_remaining = results.headers['x-ratelimit-remaining'].first.to_i
31
-
32
- return JSON.parse(results.body)
33
- rescue StandardError => exception
34
- 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
35
28
  end
36
29
  end
37
-
38
- require 'pexels/client/photos'
39
- require 'pexels/client/videos'
@@ -0,0 +1,29 @@
1
+ class Pexels::Client::Collections
2
+ def initialize(client)
3
+ @client = client
4
+ end
5
+
6
+ def all(per_page: 15, page: 1)
7
+ response = @client.request(
8
+ "#{Pexels.api_version}/collections",
9
+ params: {
10
+ per_page: per_page,
11
+ page: page
12
+ })
13
+
14
+ Pexels::CollectionSet.new(response)
15
+ end
16
+
17
+ def [](id, type: nil, per_page: 15, page: 1)
18
+ response = @client.request(
19
+ "#{Pexels.api_version}/collections/#{id}",
20
+ params: {
21
+ per_page: per_page,
22
+ page: page,
23
+ type: type
24
+ })
25
+
26
+ Pexels::CollectionMediaSet.new(response)
27
+ end
28
+ alias_method :find, :[]
29
+ end
@@ -1,37 +1,56 @@
1
- class Pexels::Client::Photos
1
+ module Pexels
2
+ class Client
3
+ class Photos
4
+ include SearchFilters
2
5
 
3
- def initialize(client)
4
- @client = client
5
- end
6
+ def initialize(client)
7
+ @client = client
8
+ end
6
9
 
7
- def [](id)
8
- response = @client.request("/v1/photos/#{id}")
9
- Pexels::Photo.new(response)
10
- end
10
+ def [](id)
11
+ response = @client.request("#{Pexels.api_version}/photos/#{id}")
12
+ Pexels::Photo.new(response.body)
13
+ end
14
+ alias_method :find, :[]
11
15
 
12
- def search(query, per_page: 15, page: 1, locale: 'en-US')
13
- response = @client.request(
14
- '/v1/search',
15
- params: {
16
- query: query,
17
- per_page: per_page,
18
- page: page,
19
- locale: locale
20
- }
21
- )
22
-
23
- Pexels::Response.new(response)
24
- end
16
+ def search(query, per_page: 15, page: 1, locale: 'en-US', orientation: nil, size: nil, color: nil)
17
+ validate_search_params(orientation, size, color)
18
+
19
+ response = @client.request(
20
+ "#{Pexels.api_version}/search",
21
+ params: {
22
+ query: query,
23
+ per_page: per_page,
24
+ page: page,
25
+ locale: locale,
26
+ orientation: orientation,
27
+ size: size,
28
+ color: color
29
+ }.compact
30
+ )
31
+
32
+ Pexels::PhotoSet.new(response)
33
+ end
34
+
35
+ def curated(per_page: 15, page: 1)
36
+ response = @client.request(
37
+ "#{Pexels.api_version}/curated",
38
+ params: {
39
+ per_page: per_page,
40
+ page: page
41
+ }
42
+ )
43
+
44
+ Pexels::PhotoSet.new(response)
45
+ end
25
46
 
26
- def curated(per_page: 15, page: 1)
27
- response = @client.request(
28
- '/v1/curated',
29
- params: {
30
- per_page: per_page,
31
- page: page,
32
- }
33
- )
47
+ private
34
48
 
35
- Pexels::Response.new(response)
49
+ def validate_search_params(orientation, size, color)
50
+ validate_orientation(orientation) &&
51
+ validate_size(size) &&
52
+ validate_color(color)
53
+ end
54
+ end
36
55
  end
37
56
  end
@@ -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
@@ -0,0 +1,31 @@
1
+ module Pexels
2
+ class Client
3
+ module SearchFilters
4
+ ORIENTATIONS = %w(portrait landscape square).freeze
5
+ SIZES = %w(small medium large).freeze
6
+ COLORS = %w(red orange yellow green turquoise blue violet pink brown black gray white).freeze
7
+
8
+ def validate_orientation(orientation)
9
+ return true unless orientation
10
+ return true if ORIENTATIONS.include?(orientation.to_s)
11
+
12
+ raise ArgumentError, "`orientation` must be one of #{ORIENTATIONS.join(', ')}."
13
+ end
14
+
15
+ def validate_size(size)
16
+ return true unless size
17
+ return true if SIZES.include?(size.to_s)
18
+
19
+ raise ArgumentError, "`size` must be one of #{SIZES.join(', ')}."
20
+ end
21
+
22
+ def validate_color(color)
23
+ return true unless color
24
+ return true if COLORS.include?(color.to_s)
25
+ return true if color.to_s =~ /\A#?(?:[0-9a-f]{3}){1,2}\z/i
26
+
27
+ raise ArgumentError, "`color` must be one of #{COLORS.join(', ')} or a valid hex code."
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,36 +1,53 @@
1
- class Pexels::Client::Videos
1
+ module Pexels
2
+ class Client
3
+ class Videos
4
+ include SearchFilters
2
5
 
3
- def initialize(client)
4
- @client = client
5
- end
6
+ def initialize(client)
7
+ @client = client
8
+ end
6
9
 
7
- def [](id)
8
- response = @client.request("/videos/videos/#{id}")
9
- Pexels::Video.new(response)
10
- end
10
+ def [](id)
11
+ response = @client.request("/videos/videos/#{id}")
12
+ Pexels::Video.new(response.body)
13
+ end
14
+ alias_method :find, :[]
11
15
 
12
- def search(query, per_page: 15, page: 1)
13
- response = @client.request(
14
- '/videos/search',
15
- params: {
16
- query: query,
17
- per_page: per_page,
18
- page: page,
19
- }
20
- )
21
-
22
- Pexels::Response.new(response)
23
- end
16
+ def search(query, per_page: 15, page: 1, orientation: nil, size: nil)
17
+ validate_search_params(orientation, size)
18
+
19
+ response = @client.request(
20
+ '/videos/search',
21
+ params: {
22
+ query: query,
23
+ per_page: per_page,
24
+ page: page,
25
+ orientation: orientation,
26
+ size: size
27
+ }.compact
28
+ )
29
+
30
+ Pexels::VideoSet.new(response)
31
+ end
32
+
33
+ def popular(per_page: 15, page: 1)
34
+ response = @client.request(
35
+ '/videos/popular',
36
+ params: {
37
+ per_page: per_page,
38
+ page: page,
39
+ }
40
+ )
41
+
42
+ Pexels::VideoSet.new(response)
43
+ end
24
44
 
25
- def popular(per_page: 15, page: 1)
26
- response = @client.request(
27
- '/videos/popular',
28
- params: {
29
- per_page: per_page,
30
- page: page,
31
- }
32
- )
45
+ private
33
46
 
34
- Pexels::Response.new(response)
47
+ def validate_search_params(orientation, size)
48
+ validate_orientation(orientation) &&
49
+ validate_size(size)
50
+ end
51
+ end
35
52
  end
36
53
  end
@@ -0,0 +1,25 @@
1
+ module Pexels
2
+ class Collection
3
+ attr_reader :id,
4
+ :title,
5
+ :description,
6
+ :private,
7
+ :media_count,
8
+ :photos_count,
9
+ :videos_count
10
+
11
+
12
+ def initialize(attrs)
13
+ @id = attrs.fetch('id')
14
+ @title = attrs.fetch('title')
15
+ @description = attrs.fetch('description')
16
+ @private = attrs.fetch('private')
17
+ @media_count = attrs.fetch('media_count')
18
+ @photos_count = attrs.fetch('photos_count')
19
+ @videos_count = attrs.fetch('videos_count')
20
+
21
+ rescue KeyError => exception
22
+ raise Pexels::MalformedAPIResponseError.new(exception)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ module Pexels
2
+ class CollectionMediaSet < PaginatedResponse
3
+ alias_method :media, :data
4
+ public :media
5
+
6
+ attr_reader :id
7
+
8
+ def initialize(response)
9
+ super
10
+ @id = attrs.fetch('id')
11
+ @data = attrs.fetch('media', []).map do |attrs|
12
+ if attrs['type'] == 'Photo'
13
+ Pexels::Photo.new(attrs)
14
+ elsif attrs['type'] == 'Video'
15
+ Pexels::Video.new(attrs)
16
+ end
17
+ end
18
+
19
+ rescue KeyError => exception
20
+ raise Pexels::MalformedAPIResponseError.new(exception)
21
+ end
22
+
23
+ def photos
24
+ @photos ||= media.select { |m| m.is_a?(Pexels::Photo) }
25
+ end
26
+
27
+ def videos
28
+ @videos ||= media.select { |m| m.is_a?(Pexels::Video) }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,11 @@
1
+ module Pexels
2
+ class CollectionSet < PaginatedResponse
3
+ alias_method :collections, :data
4
+ public :collections
5
+
6
+ def initialize(response)
7
+ super
8
+ @data = attrs.fetch('collections', []).map { |attrs| Pexels::Collection.new(attrs) }
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,63 @@
1
+ require 'cgi'
2
+
3
+ module Pexels
4
+ class PaginatedResponse
5
+ include Enumerable
6
+
7
+ attr_reader :total_results,
8
+ :page,
9
+ :per_page,
10
+ :data
11
+
12
+ private :data
13
+
14
+ def initialize(response)
15
+ @response = response
16
+ @attrs = @response.body
17
+
18
+ @total_results = attrs.fetch('total_results', nil)
19
+ @page = attrs.fetch('page')
20
+ @per_page = attrs.fetch('per_page')
21
+ @prev_page = attrs.fetch('prev_page', nil)
22
+ @next_page = attrs.fetch('next_page', nil)
23
+ end
24
+
25
+ def total_pages
26
+ total_results.fdiv(per_page).ceil
27
+ end
28
+
29
+ def each(&block)
30
+ if block_given?
31
+ data.each(&block)
32
+ else
33
+ to_enum(:each)
34
+ end
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
62
+ end
63
+ end
data/lib/pexels/photo.rb CHANGED
@@ -4,8 +4,8 @@ class Pexels::Photo
4
4
  :height,
5
5
  :url,
6
6
  :user,
7
- :src
8
-
7
+ :src,
8
+ :avg_color
9
9
 
10
10
  def initialize(attrs)
11
11
  @id = attrs.fetch('id')
@@ -18,8 +18,21 @@ class Pexels::Photo
18
18
  url: attrs.fetch('photographer_url')
19
19
  )
20
20
  @src = attrs.fetch('src')
21
+ @avg_color = attrs.fetch('avg_color')
21
22
 
22
23
  rescue KeyError => exception
23
24
  raise Pexels::MalformedAPIResponseError.new(exception)
24
25
  end
26
+
27
+ def type
28
+ 'Photo'
29
+ end
30
+
31
+ def photo?
32
+ true
33
+ end
34
+
35
+ def video?
36
+ false
37
+ end
25
38
  end
@@ -0,0 +1,14 @@
1
+ module Pexels
2
+ class PhotoSet < PaginatedResponse
3
+ alias_method :photos, :data
4
+ public :photos
5
+
6
+ def initialize(response)
7
+ super
8
+ @data = attrs.fetch('photos', []).map { |attrs| Pexels::Photo.new(attrs) }
9
+
10
+ rescue KeyError => exception
11
+ raise Pexels::MalformedAPIResponseError.new(exception)
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module Pexels
2
- VERSION = '0.0.3'
2
+ VERSION = '0.3.0'
3
3
  end
data/lib/pexels/video.rb CHANGED
@@ -31,4 +31,16 @@ class Pexels::Video
31
31
  rescue KeyError => exception
32
32
  raise Pexels::MalformedAPIResponseError.new(exception)
33
33
  end
34
+
35
+ def type
36
+ 'Video'
37
+ end
38
+
39
+ def photo?
40
+ false
41
+ end
42
+
43
+ def video?
44
+ true
45
+ end
34
46
  end
@@ -0,0 +1,14 @@
1
+ module Pexels
2
+ class VideoSet < PaginatedResponse
3
+ alias_method :videos, :data
4
+ public :videos
5
+
6
+ def initialize(response)
7
+ super
8
+ @data = attrs.fetch('videos', []).map { |attrs| Pexels::Video.new(attrs) }
9
+
10
+ rescue KeyError => exception
11
+ raise Pexels::MalformedAPIResponseError.new(exception)
12
+ end
13
+ end
14
+ end
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
@@ -0,0 +1,82 @@
1
+ require 'minitest/autorun'
2
+ require 'pexels'
3
+
4
+ class TestCollections < Minitest::Test
5
+
6
+ def setup
7
+ @client = Pexels::Client.new(ENV.fetch('PEXELS_API_KEY'))
8
+ @collection = @client.collections.all(per_page: 1).first
9
+ end
10
+
11
+ def test_all
12
+ collection = @client.collections.all
13
+
14
+ assert_kind_of Pexels::CollectionSet, collection
15
+ assert_equal collection.per_page, 15
16
+ assert_equal collection.page, 1
17
+
18
+ assert collection.collections.is_a? Array
19
+ assert collection.collections.any?
20
+ assert collection.first.is_a? Pexels::Collection
21
+
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
28
+ end
29
+
30
+ def test_get_collection_media
31
+ collection = @client.collections[@collection.id]
32
+ assert_kind_of Pexels::CollectionMediaSet, collection
33
+ assert_equal collection.id, @collection.id
34
+
35
+ assert_kind_of Array, collection.media
36
+ assert collection.media.any?
37
+
38
+ assert_includes([Pexels::Photo, Pexels::Video], collection.media.first.class)
39
+
40
+ refute_includes([Pexels::Video], collection.photos.map(&:class))
41
+ refute_includes([Pexels::Photo], collection.videos.map(&:class))
42
+ end
43
+
44
+ def test_get_collection_photos
45
+ collection = @client.collections[@collection.id, type: 'photos']
46
+ assert_kind_of Pexels::CollectionMediaSet, collection
47
+ assert_kind_of Array, collection.media
48
+ assert collection.media.all? { |m| m.is_a?(Pexels::Photo) }
49
+ end
50
+
51
+ def test_get_collection_videos
52
+ collection = @client.collections[@collection.id, type: 'videos']
53
+ assert_kind_of Pexels::CollectionMediaSet, collection
54
+ assert_kind_of Array, collection.media
55
+ assert collection.media.all? { |m| m.is_a?(Pexels::Video) }
56
+ end
57
+
58
+ def test_get_collection_invalid_type
59
+ collection = @client.collections[@collection.id, type: 'foo']
60
+ assert_kind_of Pexels::CollectionMediaSet, collection
61
+ assert_kind_of Array, collection.media
62
+ assert collection.any?
63
+ end
64
+
65
+ def test_get_collection_pagination
66
+ collection = @client.collections[@collection.id, per_page: 1, page: 1]
67
+ assert_kind_of Pexels::CollectionMediaSet, collection
68
+ assert_kind_of Array, collection.media
69
+ assert collection.media.any?
70
+
71
+ assert_equal collection.per_page, 1
72
+ assert_equal collection.page, 1
73
+ assert_equal collection.media.length, 1
74
+ end
75
+
76
+ def test_invalid_get_collection
77
+ error = assert_raises(Pexels::APIError) do
78
+ @client.collections['this-is-not-a-valid-id']
79
+ end
80
+ assert error.message, 'Not Found'
81
+ end
82
+ end
data/test/photo_test.rb CHANGED
@@ -5,44 +5,46 @@ class TestPhoto < Minitest::Test
5
5
 
6
6
  def setup
7
7
  @client = Pexels::Client.new(ENV.fetch('PEXELS_API_KEY'))
8
- @photo = @client.photos.search('test', per_page: 1).photos.first
8
+ @photo = @client.photos.search('test', per_page: 1).first
9
9
  end
10
10
 
11
11
  def test_successful_searches
12
12
  search_result = @client.photos.search('test')
13
13
 
14
- assert search_result.is_a? Pexels::Response
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
 
20
20
  assert search_result.photos.is_a? Array
21
21
  assert search_result.photos.any?
22
- assert search_result.photos.first.is_a? Pexels::Photo
22
+ assert search_result.first.is_a? Pexels::Photo
23
23
 
24
24
  search_result_with_params = @client.photos.search('test', per_page: 1, page: 2)
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::Response
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
 
38
39
  assert search_result.photos.is_a? Array
39
40
  assert search_result.photos.any?
40
- assert search_result.photos.first.is_a? Pexels::Photo
41
+ assert search_result.first.is_a? Pexels::Photo
41
42
 
42
43
  search_result_with_params = @client.photos.curated(per_page: 1, page: 2)
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
@@ -58,13 +60,51 @@ class TestPhoto < Minitest::Test
58
60
  assert_equal photo.user.url, @photo.user.url
59
61
  assert_equal photo.user.id, @photo.user.id
60
62
  assert_equal photo.src, @photo.src
63
+ assert_equal photo.avg_color, @photo.avg_color
64
+
65
+ assert photo.photo?
66
+ assert_equal photo.type, 'Photo'
67
+ refute photo.video?
61
68
  end
62
69
 
63
70
  def test_invalid_get_photo
64
- photo = @client.photos['this-is-not-a-valid-id']
65
- raise 'This should not happen'
66
- rescue StandardError => exception
67
- assert exception.is_a? Pexels::APIError
68
- assert_equal exception.message, 'Not Found'
71
+ error = assert_raises(Pexels::APIError) do
72
+ @client.photos['this-is-not-a-valid-id']
73
+ end
74
+ assert_equal 'Not Found', error.message
75
+ end
76
+
77
+ def test_invalid_orientation
78
+ error = assert_raises(ArgumentError) do
79
+ @client.photos.search('dog', orientation: 'foo')
80
+ end
81
+ assert_match '`orientation` must be one of', error.message
82
+ end
83
+
84
+ def test_invalid_size
85
+ error = assert_raises(ArgumentError) do
86
+ @client.photos.search('dog', size: 'foo')
87
+ end
88
+ assert_match '`size` must be one of', error.message
89
+ end
90
+
91
+ def test_invalid_color
92
+ error = assert_raises(ArgumentError) do
93
+ @client.photos.search('dog', color: 'foo')
94
+ end
95
+ assert_match '`color` must be one of', error.message
96
+ end
97
+
98
+ def test_invalid_color_hex
99
+ error = assert_raises(ArgumentError) do
100
+ @client.photos.search('dog', color: '#gggggg')
101
+ end
102
+ assert_match '`color` must be one of', error.message
103
+ end
104
+
105
+ def test_search_filters
106
+ search_result = @client.photos.search('dog', color: '#FF0000', size: :large, orientation: :square)
107
+ assert_kind_of Pexels::PhotoSet, search_result
108
+ assert search_result.photos.any?
69
109
  end
70
110
  end
data/test/video_test.rb CHANGED
@@ -5,42 +5,46 @@ class TestVideo < Minitest::Test
5
5
 
6
6
  def setup
7
7
  @client = Pexels::Client.new(ENV.fetch('PEXELS_API_KEY'))
8
- @video = @client.videos.search('test', per_page: 1).videos.first
8
+ @video = @client.videos.search('test', per_page: 1).first
9
9
  end
10
10
 
11
11
  def test_successful_searches
12
12
  search_result = @client.videos.search('test')
13
13
 
14
- assert search_result.is_a? Pexels::Response
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
 
19
20
  assert search_result.videos.is_a? Array
20
21
  assert search_result.videos.any?
21
- assert search_result.videos.first.is_a? Pexels::Video
22
+ assert search_result.first.is_a? Pexels::Video
22
23
 
23
24
  search_result_with_params = @client.videos.search('test', per_page: 1, page: 2)
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::Response
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
 
36
39
  assert search_result.videos.is_a? Array
37
40
  assert search_result.videos.any?
38
- assert search_result.videos.first.is_a? Pexels::Video
41
+ assert search_result.first.is_a? Pexels::Video
39
42
 
40
43
  search_result_with_params = @client.videos.popular(per_page: 1, page: 2)
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
@@ -53,6 +57,10 @@ class TestVideo < Minitest::Test
53
57
  assert_equal video.height, @video.height
54
58
  assert_equal video.url, @video.url
55
59
 
60
+ assert video.video?
61
+ assert_equal video.type, 'Video'
62
+ refute video.photo?
63
+
56
64
  assert video.user.is_a?(Pexels::User)
57
65
  assert_equal video.user.name, @video.user.name
58
66
  assert_equal video.user.url, @video.user.url
@@ -66,14 +74,29 @@ class TestVideo < Minitest::Test
66
74
  end
67
75
 
68
76
  def test_invalid_get_video
69
- video = @client.videos['this-is-not-a-valid-id']
70
- raise 'This should not happen'
71
- rescue StandardError => exception
72
- assert exception.is_a? Pexels::APIError
73
- #assert_equal exception.message, 'Not Found'
74
- #
75
- ## This is incorrect behavior from the API, which we should change
76
- # once its fixed.
77
- assert_equal exception.message, 'Internal Server Error'
77
+ error = assert_raises(Pexels::APIError) do
78
+ @client.videos['this-is-not-a-valid-id']
79
+ end
80
+ assert_equal 'Not Found', error.message
81
+ end
82
+
83
+ def test_invalid_orientation
84
+ error = assert_raises(ArgumentError) do
85
+ @client.photos.search('dog', orientation: 'foo')
86
+ end
87
+ assert_match '`orientation` must be one of', error.message
88
+ end
89
+
90
+ def test_invalid_size
91
+ error = assert_raises(ArgumentError) do
92
+ @client.photos.search('dog', size: 'foo')
93
+ end
94
+ assert_match '`size` must be one of', error.message
95
+ end
96
+
97
+ def test_search_filters
98
+ search_result = @client.videos.search('cat', size: :medium, orientation: :square)
99
+ assert_kind_of Pexels::VideoSet, search_result
100
+ assert search_result.videos.any?
78
101
  end
79
102
  end
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.0.3
4
+ version: 0.3.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: 2020-05-20 00:00:00.000000000 Z
11
+ date: 2021-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: requests
@@ -34,23 +34,34 @@ files:
34
34
  - ".env.sample"
35
35
  - ".gems"
36
36
  - ".gitignore"
37
+ - CHANGES.md
37
38
  - LICENSE
38
39
  - Makefile
39
40
  - README.md
40
41
  - lib/pexels.rb
41
42
  - lib/pexels/client.rb
43
+ - lib/pexels/client/collections.rb
42
44
  - lib/pexels/client/photos.rb
45
+ - lib/pexels/client/request.rb
46
+ - lib/pexels/client/response.rb
47
+ - lib/pexels/client/search_filters.rb
43
48
  - lib/pexels/client/videos.rb
49
+ - lib/pexels/collection.rb
50
+ - lib/pexels/collection_media_set.rb
51
+ - lib/pexels/collection_set.rb
44
52
  - lib/pexels/errors.rb
53
+ - lib/pexels/paginated_response.rb
45
54
  - lib/pexels/photo.rb
46
- - lib/pexels/response.rb
55
+ - lib/pexels/photo_set.rb
47
56
  - lib/pexels/user.rb
48
57
  - lib/pexels/version.rb
49
58
  - lib/pexels/video.rb
50
59
  - lib/pexels/video/file.rb
51
60
  - lib/pexels/video/picture.rb
61
+ - lib/pexels/video_set.rb
52
62
  - pexels.gemspec
53
63
  - test/client_test.rb
64
+ - test/collection_test.rb
54
65
  - test/photo_test.rb
55
66
  - test/video_test.rb
56
67
  homepage: https://github.com/pexels/pexels-ruby
@@ -65,7 +76,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
65
76
  requirements:
66
77
  - - ">="
67
78
  - !ruby/object:Gem::Version
68
- version: '0'
79
+ version: 2.4.0
69
80
  required_rubygems_version: !ruby/object:Gem::Requirement
70
81
  requirements:
71
82
  - - ">="
@@ -1,20 +0,0 @@
1
- class Pexels::Response
2
- attr_reader :photos,
3
- :videos,
4
- :total_results,
5
- :page,
6
- :per_page,
7
- :next_page
8
-
9
- def initialize(attrs, type: :Photo)
10
- @total_results = attrs.fetch('total_results', nil)
11
- @page = attrs.fetch('page')
12
- @per_page = attrs.fetch('per_page')
13
- @next_page = attrs.fetch('next_page', nil)
14
-
15
- @photos = attrs.fetch('photos', []).map { |attrs| Pexels::Photo.new(attrs) }
16
- @videos = attrs.fetch('videos', []).map { |attrs| Pexels::Video.new(attrs) }
17
-
18
- return self
19
- end
20
- end