fixably 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +18 -0
  3. data/.gitignore +14 -0
  4. data/.mutant.yml +23 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +145 -0
  7. data/CODE_OF_CONDUCT.md +84 -0
  8. data/Gemfile +12 -0
  9. data/Gemfile.lock +119 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +227 -0
  12. data/Rakefile +12 -0
  13. data/bin/console +15 -0
  14. data/bin/mutant +3 -0
  15. data/bin/setup +8 -0
  16. data/docs/customer/child.md +23 -0
  17. data/docs/customer.md +78 -0
  18. data/docs/device.md +56 -0
  19. data/docs/order/line.md +27 -0
  20. data/docs/order/note.md +34 -0
  21. data/docs/order/task.md +27 -0
  22. data/docs/order.md +121 -0
  23. data/docs/queue.md +36 -0
  24. data/docs/status.md +42 -0
  25. data/docs/user.md +23 -0
  26. data/fixably.gemspec +38 -0
  27. data/lib/fixably/action_policy.rb +94 -0
  28. data/lib/fixably/actions.rb +148 -0
  29. data/lib/fixably/active_resource/base.rb +53 -0
  30. data/lib/fixably/active_resource/paginated_collection.rb +91 -0
  31. data/lib/fixably/application_resource.rb +49 -0
  32. data/lib/fixably/argument_parameterisation.rb +77 -0
  33. data/lib/fixably/authorization.rb +17 -0
  34. data/lib/fixably/config.rb +39 -0
  35. data/lib/fixably/create_has_many_record.rb +90 -0
  36. data/lib/fixably/encoding.rb +38 -0
  37. data/lib/fixably/load_from_response.rb +116 -0
  38. data/lib/fixably/logger.rb +33 -0
  39. data/lib/fixably/resource_lazy_loader.rb +76 -0
  40. data/lib/fixably/resources/customer.rb +64 -0
  41. data/lib/fixably/resources/device.rb +27 -0
  42. data/lib/fixably/resources/order.rb +87 -0
  43. data/lib/fixably/resources/queue.rb +9 -0
  44. data/lib/fixably/resources/status.rb +12 -0
  45. data/lib/fixably/resources/user.rb +15 -0
  46. data/lib/fixably/version.rb +5 -0
  47. data/lib/fixably.rb +37 -0
  48. metadata +217 -0
data/README.md ADDED
@@ -0,0 +1,227 @@
1
+ # Fixably
2
+
3
+ The Fixably Ruby library provides access to the Fixably API for Ruby
4
+ applications with automatic integration into Ruby on Rails.
5
+
6
+ Support is only provided for Ruby >= 3.0
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem "fixably"
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle install
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install fixably
23
+
24
+ ## Configuration
25
+
26
+ Before you begin, you will need to setup API credentials in Fixably at
27
+ https://[your-domain].fixably.com/en/settings/integrations
28
+
29
+ You need to set your API key and subdomain in the Fixably configuration. The
30
+ subdomain is the part before .fixably.com when you are using Fixable. For
31
+ example, if you accessed Fixably via https://demo.fixably.com/, then your
32
+ subdomain is "demo".
33
+
34
+ ```ruby
35
+ require "fixably"
36
+
37
+ Fixably.configure do |config|
38
+ config.api_key = ENV["fixably_api_key"]
39
+ config.subdomain = "demo"
40
+ end
41
+ ```
42
+
43
+ In a Rails application, this is best done in an initializer. For example,
44
+ `config/initializers/fixably.rb`:
45
+ ```ruby
46
+ Fixably.configure do |config|
47
+ config.api_key = Rails.application.credentials.fixably["api_key"]
48
+ config.subdomain = Rails.application.credentials.fixably["subdomain"]
49
+ end
50
+ ```
51
+
52
+ ## Usage
53
+
54
+ This gem utilises Active Resource under the hood to provide a Rails-like
55
+ interface.
56
+
57
+ ```ruby
58
+ customers = Fixably::Customer.all
59
+ customer = Fixably::Customer.find(1_000)
60
+ customer = Fixably::Customer.first
61
+ customer = Fixably::Customer.last
62
+
63
+ customers = Fixably::Customer.where(first_name: "HashNotAdam")
64
+ customer = customers.first
65
+ customer.first_name = "Adam"
66
+ customer.save!
67
+
68
+ customer = Fixably::Customer.create!(
69
+ first_name: "Adam",
70
+ last_name: "Rice",
71
+ email: "development@hashnotadam.com"
72
+ )
73
+ ```
74
+
75
+ Where there are known required fields, you can test validity or catch errors if
76
+ using the bang functions.
77
+
78
+ ```ruby
79
+ customer = Fixably::Customer.new(first_name: "HashNotAdam")
80
+ customer.valid? # => false
81
+ customer.errors.full_messages.to_sentence # => Either email or phone must be present
82
+
83
+ customer.save # => false
84
+ customer.save! # Exception: Failed. (ActiveResource::ResourceInvalid)
85
+
86
+ customer = Fixably::Customer.create(first_name: "HashNotAdam")
87
+ customer.persisted? # => false
88
+
89
+ customer = Fixably::Customer.create!(first_name: "HashNotAdam") # Exception: Failed. (ActiveResource::ResourceInvalid)
90
+ ```
91
+
92
+ If you need to know the attributes of a model, you can request the schema. It
93
+ should be noted that the schema only includes fields that Fixably accept when
94
+ creating or updating record. For example, if you load a customer, the API will
95
+ include an ID and tags but Fixably does not support modifying either attribute.
96
+
97
+ ```ruby
98
+ Fixably::Customer.schema
99
+ # =>
100
+ # {"first_name"=>"string",
101
+ # "last_name"=>"string",
102
+ # "company"=>"string",
103
+ # "phone"=>"string",
104
+ # "email"=>"string",
105
+ # "business_id"=>"string",
106
+ # "language"=>"string",
107
+ # "provider"=>"string",
108
+ # "identifier"=>"string"}
109
+ ```
110
+
111
+ We only use a small subset of the available resources so not all of the API is
112
+ implemented, however, this gem is designed in such a way to make it easy to add
113
+ new endpoints. If you need access to another resource, let's chat.
114
+
115
+ Currently supported resources:
116
+ - Fixably::Customer ([documentation](docs/customer.md))
117
+ - Fixably::Customer::Child ([documentation](docs/customer/child.md))
118
+ - Fixably::Device ([documentation](docs/device.md))
119
+ - Fixably::Order ([documentation](docs/order.md))
120
+ - Fixably::Order::Line ([documentation](docs/order/line.md))
121
+ - Fixably::Order::Note ([documentation](docs/order/note.md))
122
+ - Fixably::Order::Task ([documentation](docs/order/task.md))
123
+ - Fixably::Queue ([documentation](docs/queue.md))
124
+ - Fixably::Status ([documentation](docs/status.md))
125
+ - Fixably::User ([documentation](docs/user.md))
126
+
127
+ ## Link expansion
128
+
129
+ Fixably actively avoid sending information about associations or even the data
130
+ for a collection ([Fixably docs](https://docs.fixably.com/?http#link-expansion)).
131
+ For example, if you were to send a request for a collection of customers, you
132
+ would receive something like:
133
+ ```ruby
134
+ {
135
+ "limit": 25,
136
+ "offset": 0,
137
+ "totalItems": 100,
138
+ "items": [
139
+ { "href": "https://subdomain.fixably.com/api/v3/customers/1001" },
140
+ { "href": "https://subdomain.fixably.com/api/v3/customers/1002" },
141
+ { "href": "https://subdomain.fixably.com/api/v3/customers/1003" },
142
+ ...
143
+ ]
144
+ }
145
+ ```
146
+
147
+ This gem will always pass "expand=items" with requests which expands the first
148
+ layer of information. If you would also like to load associations, you can
149
+ use the `includes` method with the name of the association. For example:
150
+
151
+ ```ruby
152
+ customers = Fixably::Customer.includes(:children).all
153
+ # expand=items,children(items)
154
+ ```
155
+
156
+ ## Pagination
157
+
158
+ When making a request that could return multiple results, you will receive a
159
+ paginated collection. You can pass `limit` and `offset` parameters to manually
160
+ manage pagination or use the helper methods:
161
+ ```ruby
162
+ customers = Fixably::Customer.where(company: "Education Advantage") # PaginatedCollection
163
+ customers.limit # => 25
164
+ customers.offset # => 0
165
+
166
+ customers.each.count # => 25
167
+
168
+ all_customers = []
169
+ customers.paginated_each { all_customers << _1 }
170
+ all_customers.count # => 100
171
+
172
+ all_customers = customers.paginated_map
173
+ all_customers.count # => 100
174
+ ```
175
+
176
+ Remember to be respectful when using this feature; requesting all records has
177
+ the potential to send a lot of requests. If you need to download a lot of data,
178
+ it is probably worth your time to tweak the limit to pull in bigger batches:
179
+ ```ruby
180
+ customers = Fixably::Customer.all(limit: 100)
181
+ customers.limit # => 100
182
+ customers.offset # => 0
183
+
184
+ customers.each.count # => 25
185
+ ```
186
+
187
+ ## Contributing
188
+
189
+ Bug reports and pull requests are welcome on
190
+ [GitHub](https://github.com/HashNotAdam/fixably-ruby).
191
+ This project is intended to be a safe, welcoming space for collaboration, and
192
+ contributors are expected to adhere to the
193
+ [code of conduct](https://github.com/HashNotAdam/fixably-ruby/blob/master/CODE_OF_CONDUCT.md).
194
+
195
+ If you would like to add a feature or fix a bug:
196
+ - create an issue so we can discuss your thoughts;
197
+ - fork the project;
198
+ - start a feature/bugfix branch;
199
+ - commit your changes (be sure to include tests); and
200
+ - create a pull request to merge your branch into main.
201
+
202
+ Be aware that this gem monkey patches Active Resource. As such, you may need to
203
+ familiarise yourself with `lib/fixably/active_resource/base.rb`.
204
+
205
+ ## Testing
206
+
207
+ The test suite does not make any requests, however, it does test up to the point
208
+ that the request would be made. This means that many tests will fail unless
209
+ a subdomain and API key are configured.
210
+
211
+ The dotenv gem is loaded when tests are run and will look for a .env file in the
212
+ root directory. A .env.example file has been supplied so you copy it to .env and
213
+ replace the example values:
214
+
215
+ ```sh
216
+ cp .env.example .env
217
+ ```
218
+
219
+ ## License
220
+
221
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
222
+
223
+ ## Code of Conduct
224
+
225
+ Everyone interacting in the Fixably project's codebases, issue trackers, chat
226
+ rooms and mailing lists is expected to follow the
227
+ [code of conduct](https://github.com/HashNotAdam/fixably-ruby/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "fixably"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/mutant ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/zsh
2
+
3
+ MUTATION_TESTING=true bundle exec mutant run $@
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,23 @@
1
+ # Fixably::Customer::Child
2
+
3
+ ## List children
4
+
5
+ The Fixably API does not allow children to be searched
6
+
7
+ ## Get a child
8
+
9
+ ```ruby
10
+ Fixably::Customer::Child.find(1000, customer_id: 1000)
11
+ ```
12
+
13
+ ## Create a child
14
+
15
+ The Fixably API does not allow children to be created
16
+
17
+ ## Update a child
18
+
19
+ The Fixably API does not allow children to be updated
20
+
21
+ ## Destroy a child
22
+
23
+ The Fixably API does not allow children to be destroyed
data/docs/customer.md ADDED
@@ -0,0 +1,78 @@
1
+ # Fixably::Customer
2
+
3
+ ## List customers
4
+
5
+ ```ruby
6
+ Fixably::Customer.all
7
+ Fixably::Customer.where(first_name: "Adam")
8
+ ```
9
+
10
+ ### Include associations in a list
11
+
12
+ **Children**
13
+ ```ruby
14
+ Fixably::Customer.includes(:children).all
15
+ Fixably::Customer.includes(:children).where(first_name: "Adam")
16
+ ```
17
+
18
+ ## Get a customer
19
+
20
+ ```ruby
21
+ Fixably::Customer.find(1_000)
22
+ Fixably::Customer.first
23
+ Fixably::Customer.last
24
+ ```
25
+
26
+ ## Create a customer
27
+
28
+ ```ruby
29
+ customer = Fixably::Customer.create(
30
+ first_name: "Adam",
31
+ last_name: "Rice",
32
+ email: "development@hashnotadam.com"
33
+ )
34
+ customer.valid? # => true
35
+ customer.persisted? # => true
36
+
37
+ # Raises an error on failure
38
+ Fixably::Customer.create!(
39
+ first_name: "Adam",
40
+ last_name: "Rice",
41
+ email: "development@hashnotadam.com"
42
+ )
43
+
44
+ customer = Fixably::Customer.new(
45
+ first_name: "Adam",
46
+ last_name: "Rice",
47
+ email: "development@hashnotadam.com"
48
+ )
49
+ customer.save
50
+ customer.valid? # => true
51
+ customer.persisted? # => true
52
+
53
+ customer = Fixably::Customer.new(
54
+ first_name: "Adam",
55
+ last_name: "Rice",
56
+ email: "development@hashnotadam.com"
57
+ )
58
+ # Raises an error on failure
59
+ customer.save!
60
+ ```
61
+
62
+ ## Update a customer
63
+
64
+ ```ruby
65
+ customer = Fixably::Customer.find(1_000)
66
+ customer.first_name = "Adam"
67
+
68
+ customer.save
69
+ customer.valid? # => true
70
+ customer.persisted? # => true
71
+
72
+ # Raises an error on failure
73
+ customer.save!
74
+ ```
75
+
76
+ ## Destroy a customer
77
+
78
+ The Fixably API does not allow customers to be destroyed
data/docs/device.md ADDED
@@ -0,0 +1,56 @@
1
+ # Fixably::Device
2
+
3
+ ## List devices
4
+
5
+ ```ruby
6
+ Fixably::Device.all
7
+ Fixably::Device.where(serialNumber: "ABCDE123FGHI")
8
+ ```
9
+
10
+ ## Get a device
11
+
12
+ ```ruby
13
+ Fixably::Device.find(1_000)
14
+ Fixably::Device.first
15
+ Fixably::Device.last
16
+ ```
17
+
18
+ ## Create a device
19
+
20
+ ```ruby
21
+ device = Fixably::Device.create(
22
+ name: "My device",
23
+ serial_number: "ABCDE123FGHI"
24
+ )
25
+ device.valid? # => true
26
+ device.persisted? # => true
27
+
28
+ # Raises an error on failure
29
+ Fixably::Device.create!(
30
+ name: "My device",
31
+ serial_number: "ABCDE123FGHI"
32
+ )
33
+
34
+ device = Fixably::Device.new(
35
+ name: "My device",
36
+ serial_number: "ABCDE123FGHI"
37
+ )
38
+ device.save
39
+ device.valid? # => true
40
+ device.persisted? # => true
41
+
42
+ device = Fixably::Device.new(
43
+ name: "My device",
44
+ serial_number: "ABCDE123FGHI"
45
+ )
46
+ # Raises an error on failure
47
+ device.save!
48
+ ```
49
+
50
+ ## Update a device
51
+
52
+ The Fixably API does not allow devices to be updated
53
+
54
+ ## Destroy a device
55
+
56
+ The Fixably API does not allow devices to be destroyed
@@ -0,0 +1,27 @@
1
+ # Fixably::Order::Line
2
+
3
+ ## List order lines
4
+
5
+ ```ruby
6
+ Fixably::Order::Line.all(order_id: 1000)
7
+ ```
8
+
9
+ ## Get an order line
10
+
11
+ ```ruby
12
+ Fixably::Order::Line.find(1000, order_id: 1000)
13
+ Fixably::Order::Line.first(order_id: 1000)
14
+ Fixably::Order::Line.last(order_id: 1000)
15
+ ```
16
+
17
+ ## Create an order line
18
+
19
+ The Fixably API does not allow order lines to be created
20
+
21
+ ## Update an order line
22
+
23
+ While supported by Fixably, this feature has not yet been implemented
24
+
25
+ ## Destroy an order line
26
+
27
+ The Fixably API does not allow notes to be destroyed