breathe 0.1.3 → 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: b556ec113d7d5c5f9666a7107c86707b4aa28bec7932eb7607c090631c07250c
4
- data.tar.gz: c5b26bce036fd4324e154b0df6e68e10c94e441691e015bb2bb9cd5ac702dc52
3
+ metadata.gz: 50f00c9264cf4b355d988467f0410baeb78606cdc27ceba2e28a3e5671771f0c
4
+ data.tar.gz: 8d815287afcee0bd8e58281869ae4bbb86df13f37fe15498b03c48d7f591d0a0
5
5
  SHA512:
6
- metadata.gz: f0af79e4598c36081ae9705f8b90bec086a54530a008644e4dbce0f7158094e32744d90f7f6677b232caa90cebd55851afaf31d4fe8bd9813b7d4471aa452ef6
7
- data.tar.gz: 0fefc175a63493210d9c5c81e31b11539e5b08b77ac2e6d626285fdd7552846668cf2a4d670b2f59e742d71e48ffb0c65c6c7b799aaacc085a5887cca01e97f7
6
+ metadata.gz: 1a7dbf1a5cf986f68e924c86ae9a3e17f87bf7ef3ab4e66f2b3edea262b23b132d9de35c5aa3bd0fb8d80bc48889ce4c512b96ee707b5693016b8dc24694b87f
7
+ data.tar.gz: 5ab3b6c5fd7ab573b31804e593f1059ed1bc5a13d20819fe368baf8b9a844ed7a823b251382c46df15bcb535def9483710dbb59abe1dc0fe7ff13a91824e0c76
data/README.md CHANGED
@@ -40,32 +40,7 @@ And use like so
40
40
 
41
41
  ```ruby
42
42
  client.absences.list
43
- #=> [
44
- # {
45
- # "employee"=>{"id"=>123, "email"=>"someone@somewhere.com", "first_name"=>"Jo", "last_name"=>"Bloggs"},
46
- # "approved_by"=>{"id"=>123, "first_name"=>"Jo", "last_name"=>"Bloggs"},
47
- # "leave_reason"=>nil,
48
- # "deducted"=>"4.0",
49
- # "work_units"=>"4.0",
50
- # "id"=>456,
51
- # "start_date"=>"2015-06-18",
52
- # "half_start"=>false,
53
- # "half_start_am_pm"=>nil,
54
- # "end_date"=>"2015-06-23",
55
- # "half_end"=>false,
56
- # "half_end_am_pm"=>nil,
57
- # "cancelled"=>true,
58
- # "notes"=>"",
59
- # "type"=>"Holiday",
60
- # "created_at"=>"2015-05-20T15:53:36+01:00",
61
- # "updated_at"=>"2015-06-11T13:58:27+01:00"
62
- # },
63
- # ...
64
- #]
65
- client.absences.list.next_page
66
- # 2
67
- client.absences.list.per_page
68
- # 100
43
+ #=> [...]
69
44
  ```
70
45
 
71
46
  You can also pass in arguments like so:
@@ -75,6 +50,27 @@ client.absences(per_page: 12, start_date: Date.today)
75
50
  #=> [...]
76
51
  ```
77
52
 
53
+ ### Pagination
54
+
55
+ You can also paginate through the data like so:
56
+
57
+ ```ruby
58
+ client.absences.list.next_page
59
+ #=> [...]
60
+ client.absences.list.previous_page
61
+ #=> [...]
62
+ client.absences.list.last_page
63
+ #=> [...]
64
+ client.absences.list.first_pages
65
+ #=> [..]
66
+ ```
67
+
68
+ If you don't want to paginate at all, you can initialize the client with the `auto_paginate` argument set to `true` like so:
69
+
70
+ ```ruby
71
+ client = Breathe::Client.new(api_key: YOUR_API_KEY, auto_paginate: true)
72
+ ```
73
+
78
74
  Only the absences endpoint is currently supported. PRs are accepted for more endpoints!
79
75
 
80
76
  ## Development
data/breathe.gemspec CHANGED
@@ -34,5 +34,5 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency "pry", "~> 0.12.2"
35
35
  spec.add_development_dependency "webmock", "~> 3.7.6"
36
36
 
37
- spec.add_dependency "faraday", "~> 0.17.0"
37
+ spec.add_dependency "sawyer", "~> 0.8.2"
38
38
  end
data/lib/breathe.rb CHANGED
@@ -1,4 +1,4 @@
1
- require "faraday"
1
+ require "sawyer"
2
2
 
3
3
  require "breathe/version"
4
4
  require "breathe/client"
@@ -9,5 +9,6 @@ require "breathe/absences"
9
9
  module Breathe
10
10
  class Error < StandardError; end
11
11
  class AuthenticationError < StandardError; end
12
+ class UnknownError < StandardError; end
12
13
  # Your code goes here...
13
14
  end
@@ -7,8 +7,11 @@ module Breathe
7
7
  end
8
8
 
9
9
  def list(args = {})
10
- response = client.get("absences", args)
11
- Response.new(response, "absences")
10
+ client.response(
11
+ method: :get,
12
+ path: "absences",
13
+ args: args
14
+ )
12
15
  end
13
16
  end
14
17
  end
@@ -1,43 +1,49 @@
1
1
  module Breathe
2
2
  class Client
3
+ attr_reader :api_key, :last_response
4
+
3
5
  BASE_URL = "https://api.breathehr.com/v1/"
4
6
 
5
- def initialize(api_key:)
7
+ def initialize(api_key:, auto_paginate: false)
6
8
  @api_key = api_key
9
+ @auto_paginate = auto_paginate
7
10
  end
8
11
 
9
12
  def absences
10
- @_absences ||= Absences.new(self)
13
+ @absences ||= Absences.new(self)
14
+ end
15
+
16
+ def response(method:, path:, args:)
17
+ response = request(method: method, path: path, options: {query: args})
18
+ parsed_response = Response.new(response: response, type: path)
19
+
20
+ if parsed_response.success?
21
+ @auto_paginate ? auto_paginated_response(parsed_response) : parsed_response
22
+ end
11
23
  end
12
24
 
13
- def get(url, url_opts = {})
14
- request(:get, url, url_opts)
25
+ def agent
26
+ Sawyer::Agent.new(BASE_URL, links_parser: Sawyer::LinkParsers::Simple.new) do |http|
27
+ http.headers["Content-Type"] = "application/json"
28
+ http.headers["X-Api-Key"] = api_key
29
+ end
30
+ end
31
+
32
+ def request(method:, path:, data: {}, options: {})
33
+ @last_response = agent.call(method, path, data, options)
34
+ @last_response
15
35
  end
16
36
 
17
37
  private
18
38
 
19
- attr_reader :api_key, :environment
39
+ def auto_paginated_response(parsed_response)
40
+ while (next_page = parsed_response.next_page)
41
+ break if next_page.nil?
20
42
 
21
- def connection
22
- Faraday.new(url: BASE_URL) do |faraday|
23
- faraday.use Faraday::Response::RaiseError
24
- faraday.adapter Faraday.default_adapter
43
+ parsed_response.concat(next_page)
25
44
  end
26
- end
27
45
 
28
- def request(method, url, url_opts = {})
29
- connection.send(method) do |req|
30
- req.url BASE_URL + url, url_opts
31
- req.headers["Content-Type"] = "application/json"
32
- req.headers["X-Api-Key"] = api_key
33
- end
34
- rescue Faraday::ClientError => e
35
- case e.message
36
- when /401/
37
- raise Breathe::AuthenticationError, "The BreatheHR API returned a 401 error - are you sure you've set the correct API key?"
38
- else
39
- raise e
40
- end
46
+ parsed_response
41
47
  end
42
48
  end
43
49
  end
@@ -1,53 +1,63 @@
1
1
  module Breathe
2
2
  class Response
3
3
  extend Forwardable
4
- attr_reader :data, :type, :response
4
+ attr_reader :response, :type
5
5
 
6
6
  delegate [:each, :find, :select, :count, :[]] => :body
7
7
 
8
- def initialize(response, type)
8
+ def initialize(response:, type:)
9
9
  @response = response
10
- @data = JSON.parse(response.body)
11
10
  @type = type
12
11
  end
13
12
 
13
+ def concat(response)
14
+ @response = response.response
15
+ body.concat(response.body)
16
+ end
17
+
18
+ def body
19
+ @body ||= response.data[type]
20
+ end
21
+
14
22
  def total
15
23
  response.headers["total"].to_i
16
24
  end
17
25
 
18
26
  def per_page
19
- response.headers.per_page
27
+ response.headers["per-page"].to_i
20
28
  end
21
29
 
22
- def next_page
23
- link_headers["next"].to_i unless link_headers.nil?
30
+ def first_page
31
+ get_page(:first)
24
32
  end
25
33
 
26
- def last_page
27
- link_headers["last"].to_i unless link_headers.nil?
34
+ def next_page
35
+ get_page(:next)
28
36
  end
29
37
 
30
- private
38
+ def previous_page
39
+ get_page(:prev)
40
+ end
31
41
 
32
- def body
33
- data[type]
42
+ def last_page
43
+ get_page(:last)
34
44
  end
35
45
 
36
- def link_headers
37
- @link_headers ||= begin
38
- return nil if response.headers["link"].nil?
46
+ def success?
47
+ return true if /^2+/.match?(response.status.to_s)
39
48
 
40
- parse_link_headers(response.headers["link"])
49
+ case response.status
50
+ when 401
51
+ raise Breathe::AuthenticationError, "The BreatheHR API returned a 401 error - are you sure you've set the correct API key?"
52
+ else
53
+ raise Breathe::UnknownError, "The BreatheHR API returned an unknown error"
41
54
  end
42
55
  end
43
56
 
44
- def parse_link_headers(header)
45
- header.split(",").map { |header|
46
- v, k = header.split(";")
47
- k = k.match("rel=\"(.+)\"")[1]
48
- v = v.match("page=([0-9]+)")[1]
49
- [k, v]
50
- }.to_h
57
+ private
58
+
59
+ def get_page(rel_type)
60
+ self.class.new(response: response.rels[rel_type].get, type: type) if response.rels[rel_type]
51
61
  end
52
62
  end
53
63
  end
@@ -1,3 +1,3 @@
1
1
  module Breathe
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: breathe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stuart Harrison
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-08 00:00:00.000000000 Z
11
+ date: 2019-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -123,19 +123,19 @@ dependencies:
123
123
  - !ruby/object:Gem::Version
124
124
  version: 3.7.6
125
125
  - !ruby/object:Gem::Dependency
126
- name: faraday
126
+ name: sawyer
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 0.17.0
131
+ version: 0.8.2
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: 0.17.0
138
+ version: 0.8.2
139
139
  description:
140
140
  email:
141
141
  - pezholio@gmail.com