pdfmonkey 0.9.0 → 1.0.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 +4 -4
- data/CHANGELOG.md +36 -1
- data/README.md +420 -78
- data/lib/pdfmonkey/adapter.rb +155 -32
- data/lib/pdfmonkey/collection.rb +37 -0
- data/lib/pdfmonkey/configuration.rb +15 -6
- data/lib/pdfmonkey/current_user.rb +36 -0
- data/lib/pdfmonkey/document.rb +77 -49
- data/lib/pdfmonkey/document_card.rb +46 -0
- data/lib/pdfmonkey/engine.rb +19 -0
- data/lib/pdfmonkey/resource.rb +197 -0
- data/lib/pdfmonkey/snippet.rb +28 -0
- data/lib/pdfmonkey/template.rb +80 -0
- data/lib/pdfmonkey/template_card.rb +43 -0
- data/lib/pdfmonkey/template_folder.rb +25 -0
- data/lib/pdfmonkey/version.rb +1 -1
- data/lib/pdfmonkey/webhook.rb +26 -0
- data/lib/pdfmonkey/workspace.rb +24 -0
- data/lib/pdfmonkey.rb +49 -3
- metadata +20 -32
- data/.github/dependabot.yml +0 -20
- data/.github/workflows/ci.yml +0 -43
- data/.gitignore +0 -8
- data/.rspec +0 -2
- data/.rubocop.yml +0 -209
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -8
- data/Gemfile.lock +0 -58
- data/Rakefile +0 -20
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/pdfmonkey.gemspec +0 -31
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b9b2578ff539c12892c1f12d30dfd3ff64bcf57380f9143cb29cfb5d3ab2c39b
|
|
4
|
+
data.tar.gz: 807b5ec97e55da7a6d19adcf1c50e3d7436a4830bfd05148c6529bea7c1b87f0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ddc09a6c959f07fd8d8ec54035d646ae529f0fdf5ff4b5ac14e181bf75992feffa77738d6e6bb0aa234f2a029ba352ab7d21870ab04955e1b8fcee8440d6539c
|
|
7
|
+
data.tar.gz: b7be90236f0a8791c7d09d3189dc177f37cf8229a7b961c793f946664ec8ec98cdc6d4cbfee564e7e5f32fc657a7fd3f9e5f2bfcc1ff5ee34026098bdc07192d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 1.0.0 - 2026-02-18
|
|
4
|
+
|
|
5
|
+
### Breaking changes
|
|
6
|
+
|
|
7
|
+
* **Requiring Ruby >= 3.2** — The gem now requires Ruby 3.2 or later.
|
|
8
|
+
* **Exception-based error handling** — API errors now raise `Pdfmonkey::ApiError` (with `errors` and `status_code` attributes) and network errors raise `Pdfmonkey::ConnectionError` instead of returning error hashes. Rescue `Pdfmonkey::Error` for a catch-all.
|
|
9
|
+
* **`Document.generate!` / `Document.generate` signature change** — These methods now use keyword arguments (`document_template_id:`, `payload:`, `meta:`). Positional arguments still work but emit a deprecation warning.
|
|
10
|
+
* **`Document.generate!` raises on failure** — `Document.generate!` now raises `Pdfmonkey::GenerationError` when the document ends with `error` or `failure` status, instead of returning the failed document.
|
|
11
|
+
* **`Document.generate!` polling** — `Document.generate!` now sleeps `poll_interval` seconds (default 0.5s) between status polls instead of busy-looping.
|
|
12
|
+
* **`document_template_id` validation** — `Document.generate!`, `Document.generate`, and `Document.create_draft` now raise `ArgumentError` when `document_template_id` is missing or blank.
|
|
13
|
+
* **Removing `ostruct` dependency** — Attributes are now backed by `Struct` instead of `OpenStruct`. This removes the runtime dependency on the `ostruct` gem.
|
|
14
|
+
* **`Document#attributes` is no longer public** — Access individual attributes through their accessor methods instead.
|
|
15
|
+
* **`User-Agent` is no longer configurable** — The `user_agent` configuration option has been removed. The header is now always `pdfmonkey-ruby/<version>`.
|
|
16
|
+
* **`to_json` omits nil attributes** — `Resource#to_json` now compacts nil values and strips the `errors` attribute from the serialized output.
|
|
17
|
+
* **Resource base class** — All resource classes now inherit from `Pdfmonkey::Resource` which provides shared CRUD operations, attribute management and JSON serialization.
|
|
18
|
+
|
|
19
|
+
### New features
|
|
20
|
+
|
|
21
|
+
* Adding `Document#generate` and `Document#generate!` instance methods for triggering generation on draft documents
|
|
22
|
+
* Adding `Document#save` as a public method (was private in 0.9.0)
|
|
23
|
+
* Adding `Document.create_draft` for creating draft documents with preview support
|
|
24
|
+
* Adding `Document#update!` for updating document attributes via PUT
|
|
25
|
+
* Adding `Document.list_cards`, `Document.fetch_card`, and `Document.fetch_full` for accessing documents through the `Document` class
|
|
26
|
+
* Adding `output_type` to `Document` attributes
|
|
27
|
+
* Adding resources for:
|
|
28
|
+
* `Engine`
|
|
29
|
+
* `Snippet`
|
|
30
|
+
* `TemplateCard`
|
|
31
|
+
* `TemplateFolder`
|
|
32
|
+
* `Template`
|
|
33
|
+
* `Webhook`
|
|
34
|
+
* `Workspace` (read-only)
|
|
35
|
+
* Adding `CurrentUser.fetch` for retrieving authenticated user info
|
|
36
|
+
* Adding `Pdfmonkey.with_adapter` for per-request adapter scoping (e.g. multi-tenant credentials)
|
|
37
|
+
* Adding persistent HTTP connections with configurable timeouts (`open_timeout`, `read_timeout`, `keep_alive_timeout`)
|
|
38
|
+
* Adding API key validation at request time (raises `Pdfmonkey::Error` if unconfigured)
|
|
4
39
|
|
|
5
40
|
## 0.9.0
|
|
6
41
|
|
data/README.md
CHANGED
|
@@ -6,7 +6,7 @@ This gem is the quickest way to use the [PDFMonkey](https://www.pdfmonkey.io) AP
|
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
9
|
-
Add this line to your application
|
|
9
|
+
Add this line to your application's Gemfile:
|
|
10
10
|
|
|
11
11
|
```ruby
|
|
12
12
|
gem 'pdfmonkey'
|
|
@@ -32,7 +32,7 @@ PDFMonkey will look for the `PDFMONKEY_PRIVATE_KEY` environment variable. This v
|
|
|
32
32
|
|
|
33
33
|
#### Setting credentials manually
|
|
34
34
|
|
|
35
|
-
You can choose to set up your credentials
|
|
35
|
+
You can choose to set up your credentials explicitly in your application:
|
|
36
36
|
|
|
37
37
|
```ruby
|
|
38
38
|
Pdfmonkey.configure do |config|
|
|
@@ -40,25 +40,41 @@ Pdfmonkey.configure do |config|
|
|
|
40
40
|
end
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
**Note:** Configuration is global. If you need per-request credentials (e.g. multi-tenant), use `with_adapter`:
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
```ruby
|
|
46
|
+
config = Pdfmonkey::Configuration.new
|
|
47
|
+
config.private_key = 'tenant-specific-key'
|
|
48
|
+
|
|
49
|
+
adapter = Pdfmonkey::Adapter.new(config: config)
|
|
50
|
+
|
|
51
|
+
Pdfmonkey.with_adapter(adapter) do
|
|
52
|
+
Pdfmonkey::Document.generate!(
|
|
53
|
+
document_template_id: 'b13ebd75-…',
|
|
54
|
+
payload: { name: 'John Doe' }
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
All operations inside the block use the given adapter. Calls outside the block continue using the global configuration.
|
|
60
|
+
|
|
61
|
+
### Documents
|
|
46
62
|
|
|
47
63
|
#### Synchronous generation
|
|
48
64
|
|
|
49
|
-
If
|
|
65
|
+
If you want to wait for a Document's generation before continuing with your workflow, use the `generate!` method, it will request a document generation and wait for it to succeed or fail before giving you any answer.
|
|
50
66
|
|
|
51
67
|
```ruby
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
68
|
+
document = Pdfmonkey::Document.generate!(
|
|
69
|
+
document_template_id: 'b13ebd75-d290-409b-9cac-8f597ae3e785',
|
|
70
|
+
payload: { name: 'John Doe' }
|
|
71
|
+
)
|
|
56
72
|
|
|
57
73
|
document.status # => 'success'
|
|
58
74
|
document.download_url # => 'https://…'
|
|
59
75
|
```
|
|
60
76
|
|
|
61
|
-
|
|
77
|
+
**Warning:** The download URL of a document is only valid **for 1 hour**. Past this delay, reload the document to obtain a new one:
|
|
62
78
|
|
|
63
79
|
```ruby
|
|
64
80
|
document.reload!
|
|
@@ -66,49 +82,79 @@ document.reload!
|
|
|
66
82
|
|
|
67
83
|
#### Asynchronous generation
|
|
68
84
|
|
|
69
|
-
PDFMonkey was created with an asynchronous workflow in mind. It provides webhooks to inform you of a Document
|
|
85
|
+
PDFMonkey was created with an asynchronous workflow in mind. It provides webhooks to inform you of a Document's generation success or failure.
|
|
70
86
|
|
|
71
|
-
To leverage this behavior and continue working while your Document is generated, use the `generate` method:
|
|
87
|
+
To leverage this behavior and continue working while your Document is being generated, use the `generate` method:
|
|
72
88
|
|
|
73
89
|
```ruby
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
90
|
+
document = Pdfmonkey::Document.generate(
|
|
91
|
+
document_template_id: 'b13ebd75-d290-409b-9cac-8f597ae3e785',
|
|
92
|
+
payload: { name: 'John Doe' }
|
|
93
|
+
)
|
|
78
94
|
|
|
79
95
|
document.status # => 'pending'
|
|
80
96
|
document.download_url # => nil
|
|
81
97
|
```
|
|
82
98
|
|
|
83
|
-
If you have a webhook URL set up it will be called with
|
|
99
|
+
If you have a webhook URL set up it will be called with your document once the generation is complete. You can simulate it for testing with the following cURL command:
|
|
84
100
|
|
|
85
|
-
```
|
|
101
|
+
```bash
|
|
86
102
|
curl <url of your app> \
|
|
87
103
|
-X POST \
|
|
88
104
|
-H 'Content-Type: application/json' \
|
|
89
105
|
-d '{
|
|
90
106
|
"document": {
|
|
107
|
+
"id": "76bebeb9-9eb1-481a-bc3c-faf43dc3ac81",
|
|
91
108
|
"app_id": "d9ec8249-65ae-4d50-8aee-7c12c1f9683a",
|
|
92
|
-
"checksum": "ac0c2b6bcc77e2b01dc6ca6a9f656b2d",
|
|
93
109
|
"created_at": "2020-01-02T03:04:05.000+01:00",
|
|
94
110
|
"document_template_id": "f7fbe2b4-a57c-46ee-8422-5ae8cc37daac",
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"id": "76bebeb9-9eb1-481a-bc3c-faf43dc3ac81",
|
|
98
|
-
"meta": null,
|
|
99
|
-
"payload": "{\"name\": \"John Doe\"}",
|
|
100
|
-
"preview_url": null,
|
|
111
|
+
"meta": "{\"_filename\":\"my-doc.pdf\"}",
|
|
112
|
+
"output_type": "pdf",
|
|
101
113
|
"status": "success",
|
|
102
|
-
"updated_at": "2020-01-02T03:04:15.000+01:00"
|
|
114
|
+
"updated_at": "2020-01-02T03:04:15.000+01:00",
|
|
115
|
+
"xml_data": null,
|
|
116
|
+
"payload": "{\"name\": \"John Doe\"}",
|
|
117
|
+
"download_url": "https://example.com/76bebeb9-9eb1-481a-bc3c-faf43dc3ac81.pdf",
|
|
118
|
+
"checksum": "ac0c2b6bcc77e2b01dc6ca6a9f656b2d",
|
|
119
|
+
"failure_cause": null,
|
|
120
|
+
"filename": "my-doc.pdf",
|
|
121
|
+
"generation_logs": [],
|
|
122
|
+
"preview_url": "https://preview.pdfmonkey.io/pdf/web/viewer.html?file=https%3A%2F%2Fpreview.pdfmonkey.io%2Fdocument-render%2F76bebeb9-9eb1-481a-bc3c-faf43dc3ac81%2Fac0c2b6bcc77e2b01dc6ca6a9f656b2d",
|
|
123
|
+
"public_share_link": "https://example.com/76bebeb9-9eb1-481a-bc3c-faf43dc3ac81.pdf"
|
|
103
124
|
}
|
|
104
125
|
}'
|
|
105
126
|
```
|
|
106
127
|
|
|
128
|
+
#### Draft documents
|
|
129
|
+
|
|
130
|
+
You can create a draft document that won't be queued for generation.
|
|
131
|
+
|
|
132
|
+
> [!TIP]
|
|
133
|
+
> This is useful for embedding a preview via `preview_url` before triggering generation. That what we do in the PDFMonkey dashboard to show you a preview of your document before generating it, using an `iframe`.
|
|
134
|
+
|
|
135
|
+
```ruby
|
|
136
|
+
draft = Pdfmonkey::Document.create_draft(
|
|
137
|
+
document_template_id: 'b13ebd75-d290-409b-9cac-8f597ae3e785',
|
|
138
|
+
payload: { name: 'John Doe' }
|
|
139
|
+
)
|
|
140
|
+
draft.status # => 'draft'
|
|
141
|
+
draft.preview_url # => 'https://…'
|
|
142
|
+
|
|
143
|
+
# When ready, trigger generation and wait for completion:
|
|
144
|
+
draft.generate!
|
|
145
|
+
draft.status # => 'success'
|
|
146
|
+
draft.download_url # => 'https://…'
|
|
147
|
+
|
|
148
|
+
# Or trigger generation without waiting:
|
|
149
|
+
draft.generate
|
|
150
|
+
draft.status # => 'pending'
|
|
151
|
+
```
|
|
152
|
+
|
|
107
153
|
#### Attaching meta data to the document
|
|
108
154
|
|
|
109
|
-
In addition to the Document
|
|
155
|
+
In addition to the Document's payload you can add meta data when generating a Document.
|
|
110
156
|
|
|
111
|
-
This can be done by passing
|
|
157
|
+
This can be done by passing the `meta:` keyword argument to the `generate!` and `generate` methods:
|
|
112
158
|
|
|
113
159
|
```ruby
|
|
114
160
|
meta = {
|
|
@@ -116,69 +162,85 @@ meta = {
|
|
|
116
162
|
client_id: '123xxx123'
|
|
117
163
|
}
|
|
118
164
|
|
|
119
|
-
document = Pdfmonkey::Document.generate!(
|
|
165
|
+
document = Pdfmonkey::Document.generate!(
|
|
166
|
+
document_template_id: template_id,
|
|
167
|
+
payload: payload,
|
|
168
|
+
meta: meta
|
|
169
|
+
)
|
|
120
170
|
document.meta
|
|
121
171
|
# => '{"_filename":"john-doe-contract.pdf","client_id":"123xxx123"}'
|
|
122
172
|
|
|
123
|
-
document = Pdfmonkey::Document.generate(
|
|
173
|
+
document = Pdfmonkey::Document.generate(
|
|
174
|
+
document_template_id: template_id,
|
|
175
|
+
payload: payload,
|
|
176
|
+
meta: meta
|
|
177
|
+
)
|
|
124
178
|
document.meta
|
|
125
179
|
# => '{"_filename":"john-doe-contract.pdf","client_id":"123xxx123"}'
|
|
126
180
|
```
|
|
127
181
|
|
|
128
|
-
####
|
|
182
|
+
#### Image generation
|
|
129
183
|
|
|
130
|
-
|
|
184
|
+
Image generation uses the same API flow as PDF generation. The template's `output_type` attribute indicates whether it produces `'pdf'` or `'image'` output. Image-specific options are passed through the `meta` parameter:
|
|
131
185
|
|
|
132
186
|
```ruby
|
|
133
|
-
|
|
187
|
+
doc = Pdfmonkey::Document.generate!(
|
|
188
|
+
document_template_id: template_id,
|
|
189
|
+
payload: payload,
|
|
190
|
+
meta: {
|
|
191
|
+
_type: 'png', # webp (default), png, or jpg
|
|
192
|
+
_width: 800, # pixels
|
|
193
|
+
_height: 600, # pixels
|
|
194
|
+
_quality: 80 # webp only, default 100
|
|
195
|
+
}
|
|
196
|
+
)
|
|
197
|
+
doc.download_url # => URL to the generated image
|
|
198
|
+
```
|
|
134
199
|
|
|
135
|
-
|
|
136
|
-
data = { name: 'John Doe' }
|
|
200
|
+
#### Updating a document
|
|
137
201
|
|
|
138
|
-
|
|
202
|
+
```ruby
|
|
203
|
+
document.update!(status: 'pending')
|
|
204
|
+
```
|
|
139
205
|
|
|
140
|
-
|
|
141
|
-
document.errors # => ["Document template must exist"]
|
|
206
|
+
#### Listing documents
|
|
142
207
|
|
|
143
|
-
|
|
144
|
-
|
|
208
|
+
```ruby
|
|
209
|
+
cards = Pdfmonkey::Document.list_cards(page: 1, status: 'success')
|
|
145
210
|
|
|
146
|
-
|
|
147
|
-
|
|
211
|
+
cards.each do |card|
|
|
212
|
+
puts card.id
|
|
213
|
+
puts card.status
|
|
214
|
+
end
|
|
148
215
|
|
|
149
|
-
#
|
|
150
|
-
|
|
216
|
+
cards.current_page # => 1
|
|
217
|
+
cards.total_pages # => 5
|
|
151
218
|
|
|
152
|
-
|
|
153
|
-
|
|
219
|
+
# Navigate pages
|
|
220
|
+
next_cards = cards.next_page
|
|
221
|
+
prev_cards = cards.prev_page
|
|
154
222
|
```
|
|
155
223
|
|
|
156
|
-
|
|
224
|
+
You can filter by `document_template_id:`, `status:`, `workspace_id:`, and `updated_since:`.
|
|
225
|
+
|
|
226
|
+
#### Fetching a document
|
|
227
|
+
|
|
228
|
+
> [!CAUTION]
|
|
229
|
+
> Fetching a full document includes its payload, meaning it could be large depending on the data you provided. We **strongly** recommend using only `fetch_card` unless you have a specific reason to fetch the full document.
|
|
157
230
|
|
|
158
|
-
You can fetch an existing document using
|
|
231
|
+
You can fetch an existing document using `.fetch` (or its explicit alias `.fetch_full`):
|
|
159
232
|
|
|
160
233
|
```ruby
|
|
161
234
|
document = Pdfmonkey::Document.fetch('76bebeb9-9eb1-481a-bc3c-faf43dc3ac81')
|
|
162
235
|
```
|
|
163
236
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
In case of error, be it an HTTP layer error or an API error, `document.status` will be set to `'error'` and `document.error` will contain the error message.
|
|
237
|
+
To fetch just the lightweight card representation (recommended):
|
|
167
238
|
|
|
168
239
|
```ruby
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
document.status # => 'error'
|
|
172
|
-
document.errors # => ["We couldn't find any Document with ID \"unknown\"..."]
|
|
173
|
-
|
|
174
|
-
# If the network is down
|
|
175
|
-
document = Pdfmonkey::Document.fetch('95eb0b6e-090b-4195-9b7c-cc3d50099867')
|
|
176
|
-
|
|
177
|
-
document.status # => 'error'
|
|
178
|
-
document.errors # => ["Failed to open TCP connection to api.pdfmonkey.io:443 (getaddrinfo: nodename nor servname provided, or not known)"]
|
|
240
|
+
card = Pdfmonkey::Document.fetch_card('76bebeb9-9eb1-481a-bc3c-faf43dc3ac81')
|
|
179
241
|
```
|
|
180
242
|
|
|
181
|
-
|
|
243
|
+
#### Deleting a document
|
|
182
244
|
|
|
183
245
|
You can delete an existing document using the `.delete` method:
|
|
184
246
|
|
|
@@ -196,26 +258,306 @@ document.delete!
|
|
|
196
258
|
|
|
197
259
|
#### Error handling
|
|
198
260
|
|
|
199
|
-
|
|
261
|
+
API errors and network errors raise exceptions:
|
|
200
262
|
|
|
201
263
|
```ruby
|
|
202
|
-
|
|
203
|
-
|
|
264
|
+
begin
|
|
265
|
+
document = Pdfmonkey::Document.generate(
|
|
266
|
+
document_template_id: template_id,
|
|
267
|
+
payload: data
|
|
268
|
+
)
|
|
269
|
+
rescue Pdfmonkey::ApiError => e
|
|
270
|
+
e.message # => "Document template must exist"
|
|
271
|
+
e.errors # => ["Document template must exist"]
|
|
272
|
+
e.status_code # => 422
|
|
273
|
+
rescue Pdfmonkey::ConnectionError => e
|
|
274
|
+
e.message # => "Failed to open TCP connection to api.pdfmonkey.io:443 ..."
|
|
275
|
+
end
|
|
276
|
+
```
|
|
204
277
|
|
|
205
|
-
document
|
|
206
|
-
# {
|
|
207
|
-
# errors: ["We couldn't find any Document with ID \"11111111-2222-3333-4444-555555555555\". If ..."],
|
|
208
|
-
# status: "error"
|
|
209
|
-
# }
|
|
278
|
+
When using `generate!`, an additional exception may be raised if the document's status is `'error'` or `'failure'`:
|
|
210
279
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
280
|
+
```ruby
|
|
281
|
+
begin
|
|
282
|
+
document = Pdfmonkey::Document.generate!(
|
|
283
|
+
document_template_id: template_id,
|
|
284
|
+
payload: data
|
|
285
|
+
)
|
|
286
|
+
rescue Pdfmonkey::GenerationError => e
|
|
287
|
+
e.message # => "Document generation failed: Template error"
|
|
288
|
+
e.document # => #<Pdfmonkey::Document …> (the failed document)
|
|
289
|
+
end
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
All exception classes inherit from `Pdfmonkey::Error`, so you can rescue broadly:
|
|
293
|
+
|
|
294
|
+
```ruby
|
|
295
|
+
begin
|
|
296
|
+
document = Pdfmonkey::Document.generate!(
|
|
297
|
+
document_template_id: template_id,
|
|
298
|
+
payload: data
|
|
299
|
+
)
|
|
300
|
+
rescue Pdfmonkey::Error => e
|
|
301
|
+
puts "Something went wrong: #{e.message}"
|
|
302
|
+
end
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Templates
|
|
306
|
+
|
|
307
|
+
#### Fetching a template
|
|
308
|
+
|
|
309
|
+
> [!CAUTION]
|
|
310
|
+
> Fetching a full template includes its body and settings, which can be large. Use `list_cards` when you only need metadata.
|
|
311
|
+
|
|
312
|
+
```ruby
|
|
313
|
+
template = Pdfmonkey::Template.fetch('b13ebd75-d290-409b-9cac-8f597ae3e785')
|
|
314
|
+
template.identifier # => 'my-invoice'
|
|
315
|
+
template.body # => '<h1>Invoice</h1>…' (published version)
|
|
316
|
+
template.body_draft # => '<h1>Invoice v2</h1>…' (draft version)
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
You can also use the explicit alias `.fetch_full`:
|
|
320
|
+
|
|
321
|
+
```ruby
|
|
322
|
+
template = Pdfmonkey::Template.fetch_full('b13ebd75-d290-409b-9cac-8f597ae3e785')
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
#### Creating a template
|
|
326
|
+
|
|
327
|
+
When creating a template, attributes like `body`, `scss_style`, `settings`, `sample_data`, and `pdf_engine_id` are automatically written to their draft counterparts (`body_draft`, `scss_style_draft`, etc.):
|
|
328
|
+
|
|
329
|
+
```ruby
|
|
330
|
+
template = Pdfmonkey::Template.create(
|
|
331
|
+
identifier: 'my-invoice',
|
|
332
|
+
body: '<h1>Invoice</h1>'
|
|
333
|
+
)
|
|
334
|
+
template.body_draft # => '<h1>Invoice</h1>'
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
#### Updating a template
|
|
338
|
+
|
|
339
|
+
Like `create`, `update!` writes to the draft fields:
|
|
340
|
+
|
|
341
|
+
```ruby
|
|
342
|
+
template.update!(body: '<h1>Updated Invoice</h1>')
|
|
343
|
+
template.body_draft # => '<h1>Updated Invoice</h1>'
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
#### Publishing a template
|
|
347
|
+
|
|
348
|
+
Once you're happy with the draft, publish it to copy all draft fields to their published counterparts:
|
|
349
|
+
|
|
350
|
+
```ruby
|
|
351
|
+
template.publish!
|
|
352
|
+
template.body # => '<h1>Updated Invoice</h1>'
|
|
217
353
|
```
|
|
218
354
|
|
|
355
|
+
#### Listing templates
|
|
356
|
+
|
|
357
|
+
```ruby
|
|
358
|
+
cards = Pdfmonkey::Template.list_cards(workspace_id: 'f4ab650c-…')
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
#### Deleting a template
|
|
362
|
+
|
|
363
|
+
```ruby
|
|
364
|
+
Pdfmonkey::Template.delete('b13ebd75-…')
|
|
365
|
+
# or
|
|
366
|
+
template.delete!
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Template Folders
|
|
370
|
+
|
|
371
|
+
```ruby
|
|
372
|
+
# List folders
|
|
373
|
+
folders = Pdfmonkey::TemplateFolder.list
|
|
374
|
+
|
|
375
|
+
# Create a folder
|
|
376
|
+
folder = Pdfmonkey::TemplateFolder.create(identifier: 'invoices')
|
|
377
|
+
|
|
378
|
+
# Fetch a folder
|
|
379
|
+
folder = Pdfmonkey::TemplateFolder.fetch('folder-id')
|
|
380
|
+
|
|
381
|
+
# Update a folder
|
|
382
|
+
folder.update!(identifier: 'receipts')
|
|
383
|
+
|
|
384
|
+
# Delete a folder
|
|
385
|
+
Pdfmonkey::TemplateFolder.delete('folder-id')
|
|
386
|
+
# or
|
|
387
|
+
folder.delete!
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
To create a template inside a specific folder, pass the `template_folder_id`:
|
|
391
|
+
|
|
392
|
+
```ruby
|
|
393
|
+
folder = Pdfmonkey::TemplateFolder.create(identifier: 'invoices')
|
|
394
|
+
|
|
395
|
+
template = Pdfmonkey::Template.create(
|
|
396
|
+
identifier: 'monthly-invoice',
|
|
397
|
+
body: '<h1>Invoice</h1>',
|
|
398
|
+
template_folder_id: folder.id
|
|
399
|
+
)
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### Snippets
|
|
403
|
+
|
|
404
|
+
Snippets are reusable HTML components that can be included in templates.
|
|
405
|
+
|
|
406
|
+
```ruby
|
|
407
|
+
# List snippets
|
|
408
|
+
snippets = Pdfmonkey::Snippet.list
|
|
409
|
+
|
|
410
|
+
# Create a snippet
|
|
411
|
+
snippet = Pdfmonkey::Snippet.create(
|
|
412
|
+
identifier: 'header',
|
|
413
|
+
code: '<div class="header">…</div>',
|
|
414
|
+
workspace_id: 'f4ab650c-…'
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
# Fetch a snippet
|
|
418
|
+
snippet = Pdfmonkey::Snippet.fetch('snippet-id')
|
|
419
|
+
|
|
420
|
+
# Update a snippet
|
|
421
|
+
snippet.update!(code: '<div class="header">Updated</div>')
|
|
422
|
+
|
|
423
|
+
# Delete a snippet
|
|
424
|
+
Pdfmonkey::Snippet.delete('snippet-id')
|
|
425
|
+
# or
|
|
426
|
+
snippet.delete!
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Workspaces
|
|
430
|
+
|
|
431
|
+
Workspaces are read-only resources. They can be listed and fetched but not created, updated, or deleted through the API.
|
|
432
|
+
|
|
433
|
+
```ruby
|
|
434
|
+
# List workspaces
|
|
435
|
+
workspaces = Pdfmonkey::Workspace.list_cards
|
|
436
|
+
|
|
437
|
+
workspaces.each do |workspace|
|
|
438
|
+
puts workspace.identifier
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
# Fetch a workspace
|
|
442
|
+
workspace = Pdfmonkey::Workspace.fetch('workspace-id')
|
|
443
|
+
workspace.identifier # => 'my-app'
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### Webhooks
|
|
447
|
+
|
|
448
|
+
Webhooks allow you to receive notifications when documents are generated.
|
|
449
|
+
|
|
450
|
+
```ruby
|
|
451
|
+
# Create a webhook for all templates in a workspace
|
|
452
|
+
webhook = Pdfmonkey::Webhook.create(
|
|
453
|
+
url: 'https://example.com/webhooks/pdfmonkey',
|
|
454
|
+
event: 'document.generation.completed',
|
|
455
|
+
workspace_id: 'f4ab650c-…'
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
# Optionally restrict to specific templates
|
|
459
|
+
webhook = Pdfmonkey::Webhook.create(
|
|
460
|
+
url: 'https://example.com/webhooks/pdfmonkey',
|
|
461
|
+
event: 'document.generation.completed',
|
|
462
|
+
workspace_id: 'f4ab650c-…',
|
|
463
|
+
document_template_ids: ['tpl-1', 'tpl-2']
|
|
464
|
+
)
|
|
465
|
+
|
|
466
|
+
# You can also specify a custom channel for routing
|
|
467
|
+
webhook = Pdfmonkey::Webhook.create(
|
|
468
|
+
url: 'https://example.com/webhooks/pdfmonkey',
|
|
469
|
+
event: 'document.generation.completed',
|
|
470
|
+
workspace_id: 'f4ab650c-…',
|
|
471
|
+
custom_channel: 'invoices'
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
# Delete a webhook
|
|
475
|
+
Pdfmonkey::Webhook.delete('webhook-id')
|
|
476
|
+
# or
|
|
477
|
+
webhook.delete!
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### Engines
|
|
481
|
+
|
|
482
|
+
List available PDF rendering engines:
|
|
483
|
+
|
|
484
|
+
```ruby
|
|
485
|
+
engines = Pdfmonkey::Engine.list
|
|
486
|
+
|
|
487
|
+
engines.each do |engine|
|
|
488
|
+
puts "#{engine.name} (deprecated: #{engine.deprecated_on || 'no'})"
|
|
489
|
+
end
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
You can use an engine when creating a template:
|
|
493
|
+
|
|
494
|
+
```ruby
|
|
495
|
+
engines = Pdfmonkey::Engine.list
|
|
496
|
+
v4 = engines.find { |e| e.name == 'v4' }
|
|
497
|
+
|
|
498
|
+
template = Pdfmonkey::Template.create(
|
|
499
|
+
identifier: 'my-template',
|
|
500
|
+
body: '<h1>Hello</h1>',
|
|
501
|
+
pdf_engine_id: v4.id
|
|
502
|
+
)
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### Current User
|
|
506
|
+
|
|
507
|
+
Retrieve information about the authenticated user:
|
|
508
|
+
|
|
509
|
+
```ruby
|
|
510
|
+
user = Pdfmonkey::CurrentUser.fetch
|
|
511
|
+
|
|
512
|
+
user.email # => 'user@example.com'
|
|
513
|
+
user.current_plan # => 'pro'
|
|
514
|
+
user.available_documents # => 1000
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Pagination
|
|
518
|
+
|
|
519
|
+
All list methods return `Pdfmonkey::Collection` objects that support pagination:
|
|
520
|
+
|
|
521
|
+
```ruby
|
|
522
|
+
collection = Pdfmonkey::Document.list_cards(page: 1)
|
|
523
|
+
|
|
524
|
+
collection.current_page # => 1
|
|
525
|
+
collection.total_pages # => 5
|
|
526
|
+
collection.next_page_number # => 2
|
|
527
|
+
collection.prev_page_number # => nil
|
|
528
|
+
|
|
529
|
+
# Navigate to next/previous pages
|
|
530
|
+
next_page = collection.next_page # => Collection or nil
|
|
531
|
+
prev_page = collection.prev_page # => Collection or nil
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
Collections are `Enumerable`. Methods like `.each`, `.map`, and `.select` operate on the items **of the current page only** — they do not automatically fetch subsequent pages:
|
|
535
|
+
|
|
536
|
+
```ruby
|
|
537
|
+
# These all act on the current page's items
|
|
538
|
+
collection.each { |item| puts item.id }
|
|
539
|
+
collection.map(&:status)
|
|
540
|
+
collection.select { |item| item.status == 'success' }
|
|
541
|
+
|
|
542
|
+
# To process all pages, navigate manually
|
|
543
|
+
page = Pdfmonkey::Template.list_cards(page: 1)
|
|
544
|
+
while page
|
|
545
|
+
page.each { |item| process(item) }
|
|
546
|
+
page = page.next_page
|
|
547
|
+
end
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
### Serialization
|
|
551
|
+
|
|
552
|
+
All resources support `to_json` and `to_h`:
|
|
553
|
+
|
|
554
|
+
```ruby
|
|
555
|
+
document.to_json # => '{"document":{"id":"…","status":"success",…}}'
|
|
556
|
+
document.to_h # => {id: "…", status: "success", errors: nil, …}
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
`to_json` wraps attributes under the resource's API member key, omits `nil` values and strips the `errors` attribute (it is intended for API requests). Use `to_h` when you need the full attribute hash for logging or caching.
|
|
560
|
+
|
|
219
561
|
## Development
|
|
220
562
|
|
|
221
563
|
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
@@ -224,7 +566,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
|
224
566
|
|
|
225
567
|
## Contributing
|
|
226
568
|
|
|
227
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
|
569
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/pdfmonkeyio/pdfmonkey-ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
|
228
570
|
|
|
229
571
|
## License
|
|
230
572
|
|
|
@@ -232,4 +574,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
|
232
574
|
|
|
233
575
|
## Code of Conduct
|
|
234
576
|
|
|
235
|
-
Everyone interacting in the Pdfmonkey project
|
|
577
|
+
Everyone interacting in the Pdfmonkey project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/pdfmonkeyio/pdfmonkey-ruby/blob/master/CODE_OF_CONDUCT.md).
|