strapi_ruby 0.1.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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +40 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +582 -0
- data/Rakefile +12 -0
- data/assets/strapi_ruby_logo.png +0 -0
- data/features.md +7 -0
- data/lib/strapi_ruby/client.rb +95 -0
- data/lib/strapi_ruby/config.rb +27 -0
- data/lib/strapi_ruby/configuration.rb +21 -0
- data/lib/strapi_ruby/endpoint/builder.rb +40 -0
- data/lib/strapi_ruby/endpoint/query.rb +31 -0
- data/lib/strapi_ruby/endpoint/strapi_parameters.rb +132 -0
- data/lib/strapi_ruby/errors/client_error.rb +48 -0
- data/lib/strapi_ruby/errors/configuration_error.rb +7 -0
- data/lib/strapi_ruby/errors/error_code.yml +9 -0
- data/lib/strapi_ruby/errors/error_message.rb +41 -0
- data/lib/strapi_ruby/errors/error_text.yml +13 -0
- data/lib/strapi_ruby/formatter.rb +88 -0
- data/lib/strapi_ruby/interface.rb +81 -0
- data/lib/strapi_ruby/markdown.rb +20 -0
- data/lib/strapi_ruby/railtie.rb +12 -0
- data/lib/strapi_ruby/tasks/config.rake +28 -0
- data/lib/strapi_ruby/validations.rb +63 -0
- data/lib/strapi_ruby/version.rb +5 -0
- data/lib/strapi_ruby.rb +27 -0
- data/rubocop.txt +4 -0
- data/sig/strapi_ruby.rbs +4 -0
- data/strapi_ruby.gemspec +44 -0
- metadata +135 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9903f53042e56a2738031589080d7708a0286ac979d5f4f4aba8e71a914dc63f
|
4
|
+
data.tar.gz: 2108880a59532797595fad52bd7461c0cc4e3f12708f0d16213655f86ed1097f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 35b87fdf4069cbccf2fcf9988cf82fb0f46d2dbaedd73464a29cb8d95420608bcef064f77348ab7c8a9507405f1694161b6093eab3a56e671a4252284d29b70a
|
7
|
+
data.tar.gz: 4ca960cc893eeda6a890174f83036ab96f18aba94eca66b68febffa33330c713e361a56ece7db8c5a2401c0851caad7e126b842830d9d3824672d05e1598a1d2
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.6
|
3
|
+
Exclude:
|
4
|
+
- "spec/**/*"
|
5
|
+
|
6
|
+
|
7
|
+
Style/StringLiterals:
|
8
|
+
Enabled: true
|
9
|
+
EnforcedStyle: double_quotes
|
10
|
+
|
11
|
+
Style/StringLiteralsInInterpolation:
|
12
|
+
Enabled: true
|
13
|
+
EnforcedStyle: double_quotes
|
14
|
+
|
15
|
+
Layout/LineLength:
|
16
|
+
Max: 200
|
17
|
+
|
18
|
+
Style/Documentation:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
Style/FrozenStringLiteralComment:
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
Metrics/MethodLength:
|
25
|
+
Max: 18
|
26
|
+
|
27
|
+
Metrics/BlockLength:
|
28
|
+
Max: 50
|
29
|
+
|
30
|
+
Metrics/AbcSize:
|
31
|
+
Max: 23
|
32
|
+
|
33
|
+
Metrics/CyclomaticComplexity:
|
34
|
+
Max: 10
|
35
|
+
|
36
|
+
Metrics/PerceivedComplexity:
|
37
|
+
Max: 10
|
38
|
+
|
39
|
+
Style/MissingRespondToMissing:
|
40
|
+
Enabled: false
|
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2023 Maxence Robinet
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,582 @@
|
|
1
|
+
# StrapiRuby
|
2
|
+
|
3
|
+
<div align="center">
|
4
|
+
<img src="assets/strapi_ruby_logo.png" width="150px">
|
5
|
+
</div>
|
6
|
+
|
7
|
+
**StrapiRuby** is a Ruby wrapper around Strapi REST API, version 4. It has not been tested with previous versions.
|
8
|
+
|
9
|
+
**Strapi** is an open-source, Node.js based, Headless CMS to easily build customizable APIs.
|
10
|
+
|
11
|
+
I think it's one of the actual coolest solution for integrating a CMS into Rails for example, so let's dive in!
|
12
|
+
|
13
|
+
## Table of contents
|
14
|
+
|
15
|
+
- [Installation](#installation)
|
16
|
+
- Usage:
|
17
|
+
- [API](#api):
|
18
|
+
- [get](#get)
|
19
|
+
- [post](#post)
|
20
|
+
- [put](#put)
|
21
|
+
- [delete](#delete)
|
22
|
+
- [Basic Example: Rails](#basic-example-rails)
|
23
|
+
- [Strapi Parameters](#strapi-parameters):
|
24
|
+
- [populate](#populate)
|
25
|
+
- [fields](#fields)
|
26
|
+
- [sort](#sort)
|
27
|
+
- [filters](#filters)
|
28
|
+
- [page, page_size](#pagination-by-page-page--page_size)
|
29
|
+
- [start, limit](#pagination-by-offset-start--limit)
|
30
|
+
- [locale](#locale)
|
31
|
+
- [publication_state](#publication_state)
|
32
|
+
- [Use raw query](#use-raw-query)
|
33
|
+
- [Configuration](#configuration):
|
34
|
+
- [DateTime conversion](#datetime-conversion)
|
35
|
+
- [Markdown conversion](#markdown-conversion)
|
36
|
+
- [Faraday block](#faraday-block)
|
37
|
+
- [Contributing](#contributing)
|
38
|
+
- [Tests](#tests)
|
39
|
+
|
40
|
+
## Installation
|
41
|
+
|
42
|
+
Add this line to your application's Gemfile:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
# Gemfile
|
46
|
+
|
47
|
+
gem "strapi_ruby"
|
48
|
+
```
|
49
|
+
|
50
|
+
Then if you use Rails, run in your terminal to generate a config initializer. Otherwise copy paste and fill the config block.
|
51
|
+
|
52
|
+
```bash
|
53
|
+
rake strapi_ruby:config
|
54
|
+
```
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
# config/initializer/strapi_ruby.rb
|
58
|
+
|
59
|
+
# Don't
|
60
|
+
StrapiRuby.configure do |config|
|
61
|
+
config.strapi_server_uri = "http://localhost:1337/api"
|
62
|
+
config.strapi_token = "YOUR_TOKEN"
|
63
|
+
end
|
64
|
+
|
65
|
+
# Do
|
66
|
+
StrapiRuby.configure do |config|
|
67
|
+
config.strapi_server_uri = ENV["STRAPI_SERVER_URI"]
|
68
|
+
config.strapi_token = ENV["STRAPI_SERVER_TOKEN"]
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
##### IMPORTANT
|
73
|
+
|
74
|
+
- Always store sensible values in environment variables or Rails credentials
|
75
|
+
- Don't forget the trailing `/api` in your uri and don't finish it with a trailing slash.
|
76
|
+
|
77
|
+
And you're ready to fetch some data!
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
StrapiRuby.get(resource: :restaurants)
|
81
|
+
# => https://localhost:1337/api/restaurants
|
82
|
+
```
|
83
|
+
|
84
|
+
## Usage
|
85
|
+
|
86
|
+
### API
|
87
|
+
|
88
|
+
When passing most of the arguments and options, you can use either `Symbol` or `String` for single fields/items, and an `Array` of `Symbol` or `String`.
|
89
|
+
|
90
|
+
API methods will return an [OpenStruct](https://ruby-doc.org/stdlib-2.5.1/libdoc/ostruct/rdoc/OpenStruct.html) which is similar to a Hash but you can access keys with dot notation. All fields of the OpenStruct have been recursively converted to OpenStruct as well so it's easy to navigate, as seen below
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
# These are similar
|
94
|
+
answer = StrapiRuby.get(resource: :articles)
|
95
|
+
answer = StrapiRuby.get(resource: "articles")
|
96
|
+
|
97
|
+
# Grab data or meta
|
98
|
+
data = answer.data
|
99
|
+
meta = answer.meta
|
100
|
+
|
101
|
+
# Access a specific attribute
|
102
|
+
answer = StrapiRuby.get(resource: :articles, id: 2)
|
103
|
+
article = answer.data
|
104
|
+
title = article.attributes.title
|
105
|
+
|
106
|
+
# If an error occur, it will be raised to be rescued and displayed in the answer.
|
107
|
+
data = answer.data # => nil
|
108
|
+
meta = answer.meta # => nil
|
109
|
+
error = answer.error.message # => ErrorType:ErrorMessage
|
110
|
+
endpoint = answer.endpoint
|
111
|
+
# => "https://localhost:1337/api/restaurants?filters[title][$contains]=this+does+not+exists
|
112
|
+
```
|
113
|
+
|
114
|
+
#### .get
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
# Display all items of a collection as an array
|
118
|
+
answer = StrapiRuby.get(resource: :restaurants)
|
119
|
+
|
120
|
+
|
121
|
+
# Get a specific element
|
122
|
+
StrapiRuby.get(resource: :restaurants, id: 1)
|
123
|
+
```
|
124
|
+
|
125
|
+
#### .post
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
# Create an item of a collection, return item created
|
129
|
+
StrapiRuby.post(resource: :articles,
|
130
|
+
data: {title: "This is a brand article",
|
131
|
+
content: "created by a POST request"})
|
132
|
+
|
133
|
+
```
|
134
|
+
|
135
|
+
#### .put
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
# Update a specific item, return item updated
|
139
|
+
StrapiRuby.put(resource: :articles,
|
140
|
+
id: 23,
|
141
|
+
data: {content: "'I've edited this article via a PUT request'"})
|
142
|
+
```
|
143
|
+
|
144
|
+
#### .delete
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
# Delete an item, return item deleted
|
148
|
+
StrapiRuby.delete(resource: :articles, id: 12)
|
149
|
+
|
150
|
+
```
|
151
|
+
|
152
|
+
#### .escape_empty_answer
|
153
|
+
|
154
|
+
See [`.escape_empty_answer`](#gracefuly-degrade-errors-when-they-happen)
|
155
|
+
|
156
|
+
### Basic Example: Rails
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
# pages_controller.rb
|
160
|
+
|
161
|
+
def home
|
162
|
+
@articles = StrapiRuby.get(resource: :articles)
|
163
|
+
end
|
164
|
+
```
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
# home.html.erb
|
168
|
+
|
169
|
+
<% StrapiRuby.escape_empty_answer(@articles) do %>
|
170
|
+
<ul>
|
171
|
+
<% @articles.data.each do |article| %>
|
172
|
+
<li>
|
173
|
+
<%= article.attributes.title %>
|
174
|
+
</li>
|
175
|
+
<% end %>
|
176
|
+
</ul>
|
177
|
+
<% end %>
|
178
|
+
```
|
179
|
+
|
180
|
+
### Strapi Parameters
|
181
|
+
|
182
|
+
`strapi_ruby`` API functions wraps all parameters offered by the Strapi REST Api V4.
|
183
|
+
|
184
|
+
The query is built using a transverse hash function similar to Javascript `qs` library used by Strapi.
|
185
|
+
|
186
|
+
Instead parameters should be passed as a hash to their key and you can use symbols instead of strings.
|
187
|
+
|
188
|
+
Only exceptions are for the `operators` of the filters used as keys. Also, Integers, eg. for ID, must be passed as strings.
|
189
|
+
|
190
|
+
Full parameters documentation from Strapi is available [here](https://docs.strapi.io/dev-docs/api/rest/parameters).
|
191
|
+
|
192
|
+
You can also use their interactive query builder. Just remember to convert the result correctly the resulting JS object to a hash with correct keys and values.
|
193
|
+
|
194
|
+
#### populate
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
# Populate one level deep all relations
|
198
|
+
StrapiRuby.get(resource: :articles, populate: :*)
|
199
|
+
# => /articles?populate=*
|
200
|
+
|
201
|
+
# --------------------------------
|
202
|
+
|
203
|
+
# Populate one level deep a specific field
|
204
|
+
StrapiRuby.get(resource: :articles, populate: [:categories])
|
205
|
+
# => /articles?populate[0]=categories
|
206
|
+
|
207
|
+
# --------------------------------
|
208
|
+
|
209
|
+
# Populate two level deep
|
210
|
+
StrapiRuby.get(resource: :articles, populate: { author: { populate: [:company] } })
|
211
|
+
# => /articles??populate[author][populate][0]=company
|
212
|
+
|
213
|
+
# --------------------------------
|
214
|
+
|
215
|
+
# Populate a 2-level component and its media
|
216
|
+
StrapiRuby.get(resource: :articles, populate: [
|
217
|
+
"seoData",
|
218
|
+
"seoData.sharedImage",
|
219
|
+
"seoData.sharedImage.media",
|
220
|
+
])
|
221
|
+
# => articles?populate[0]=seoData&populate[1]=seoData.sharedImage&populate[2]=seoData.sharedImage.media
|
222
|
+
|
223
|
+
# --------------------------------
|
224
|
+
|
225
|
+
# Deeply populate a dynamic zone with 2 components
|
226
|
+
StrapiRuby.get(resource: :articles, populate: {
|
227
|
+
testDZ: {
|
228
|
+
populate: :*,
|
229
|
+
},
|
230
|
+
})
|
231
|
+
# => /articles?populate[testDZ][populate]=*
|
232
|
+
|
233
|
+
# Using detailed population strategy
|
234
|
+
StrapiRuby.get(resource: :articles, populate: {
|
235
|
+
testDz: {
|
236
|
+
on: {
|
237
|
+
"test.test-compo" => {
|
238
|
+
fields: [:testString],
|
239
|
+
populate: :*,
|
240
|
+
},
|
241
|
+
"test.test-compo2" => {
|
242
|
+
fields: [:testInt],
|
243
|
+
},
|
244
|
+
},
|
245
|
+
},
|
246
|
+
})
|
247
|
+
# => /articles?populate[testDz][on][test.test-compo][fields][0]=testString&populate[testDz][on][test.test-compo][populate]=*&populate[testDz][on][test.test-compo2][fields][0]=testInt
|
248
|
+
```
|
249
|
+
|
250
|
+
#### fields
|
251
|
+
|
252
|
+
```ruby
|
253
|
+
# Select one field
|
254
|
+
StrapiRuby.get(resource: :articles, fields: :title)
|
255
|
+
# => /articles?fields[0]=title
|
256
|
+
|
257
|
+
# --------------------------------
|
258
|
+
|
259
|
+
# Select multiple fields
|
260
|
+
StrapiRuby.get(resource: :articles, fields: [:title, :body])
|
261
|
+
# => /articles?fields[0]=title&fields[1]=body
|
262
|
+
```
|
263
|
+
|
264
|
+
#### sort
|
265
|
+
|
266
|
+
```ruby
|
267
|
+
# Sort by a single key
|
268
|
+
StrapiRuby.get(resource: :articles, sort: [])
|
269
|
+
# => articles?sort[0]=title&sort[1]=slug
|
270
|
+
|
271
|
+
# --------------------------------
|
272
|
+
|
273
|
+
# You can pass sort order and also sort by multiple keys
|
274
|
+
StrapiRuby.get(resource: :articles, sort: ["createdAt:desc", "title:asc"])
|
275
|
+
# => articles?sort[0]=created:desc&sort[1]=title:asc
|
276
|
+
```
|
277
|
+
|
278
|
+
#### filters
|
279
|
+
|
280
|
+
**Use a `String` and not a `Symbol` when using `operator`.**
|
281
|
+
|
282
|
+
| Operator | Description |
|
283
|
+
| --------------- | ----------------------------------- |
|
284
|
+
| `$eq` | Equal |
|
285
|
+
| `$eqi` | Equal (case-insensitive) |
|
286
|
+
| `$ne` | Not Equal |
|
287
|
+
| `$nei` | Not Equal (case-insensitive) |
|
288
|
+
| `$lt` | Less than |
|
289
|
+
| `$lte` | Less than (case-insensitive) |
|
290
|
+
| `$gt` | Greater than |
|
291
|
+
| `$gte` | Greater than (case-insensitive) |
|
292
|
+
| `$in` | In |
|
293
|
+
| `$notIn` | Not in |
|
294
|
+
| `$contains` | Contains |
|
295
|
+
| `$notContains` | Does not contain |
|
296
|
+
| `$containsi` | Contains (case-insensitive) |
|
297
|
+
| `$notContainsi` | Does not contain (case-insensitive) |
|
298
|
+
| `$null` | Is null |
|
299
|
+
| `$notNull` | Is not Null |
|
300
|
+
| `$between` | Is between |
|
301
|
+
| `$startsWith` | Starts with |
|
302
|
+
| `$startsWithi` | Starts with (case-insensitive) |
|
303
|
+
| `$endsWith` | Ends with |
|
304
|
+
| `$endsWithi` | Ends with (case-insensitive) |
|
305
|
+
| `$or` | Or |
|
306
|
+
| `$and` | And |
|
307
|
+
| `$not` | Not |
|
308
|
+
|
309
|
+
---
|
310
|
+
|
311
|
+
```ruby
|
312
|
+
# Simple usage
|
313
|
+
StrapiRuby.get(resource: :users, filters: { username: { "$eq" => "John" } })
|
314
|
+
# => /users?filters[username][$eq]=John
|
315
|
+
|
316
|
+
# --------------------------------
|
317
|
+
|
318
|
+
# Using $in operator to match multiples values
|
319
|
+
StrapiRuby.get(resource: :restaurants,
|
320
|
+
filters: {
|
321
|
+
id: {
|
322
|
+
"$in" => ["3", "6", "8"],
|
323
|
+
},
|
324
|
+
})
|
325
|
+
# => /restaurants?filters[id][$in][0]=3&filters[id][$in][1]=6&filters[id][$in][2]=8
|
326
|
+
|
327
|
+
# --------------------------------
|
328
|
+
|
329
|
+
# Complex filtering with $and and $or
|
330
|
+
RubyStrapi.get(resource: :books,
|
331
|
+
filters: {
|
332
|
+
"$or" => [
|
333
|
+
{
|
334
|
+
date: {
|
335
|
+
"$eq" => "2020-01-01",
|
336
|
+
},
|
337
|
+
},
|
338
|
+
{
|
339
|
+
date: {
|
340
|
+
"$eq" => "2020-01-02",
|
341
|
+
},
|
342
|
+
},
|
343
|
+
],
|
344
|
+
author: {
|
345
|
+
name: {
|
346
|
+
"$eq" => "Kai doe",
|
347
|
+
},
|
348
|
+
},
|
349
|
+
})
|
350
|
+
# => /books?filters[$or][0][date][$eq]=2020-01-01&filters[$or][1][date][$eq]=2020-01-02&filters[author][name][$eq]=Kai%20doe
|
351
|
+
|
352
|
+
# --------------------------------
|
353
|
+
|
354
|
+
# Deep filtering on relation's fields
|
355
|
+
StrapiRuby.get(resource: :restaurants,
|
356
|
+
filters: {
|
357
|
+
chef: {
|
358
|
+
restaurants: {
|
359
|
+
stars: {
|
360
|
+
"$eq" => 5,
|
361
|
+
},
|
362
|
+
},
|
363
|
+
},
|
364
|
+
})
|
365
|
+
# => /restaurants?filters[chef][restaurants][stars][$eq]=5
|
366
|
+
```
|
367
|
+
|
368
|
+
#### Pagination by page: page & page_size
|
369
|
+
|
370
|
+
Only one pagination method is possible.
|
371
|
+
|
372
|
+
```ruby
|
373
|
+
StrapiRuby.get(resource: :articles, page: 1, page_size: 10)
|
374
|
+
# => /articles?pagination[page]=1&pagination[pageSize]=10
|
375
|
+
```
|
376
|
+
|
377
|
+
#### Pagination by offset: start & limit
|
378
|
+
|
379
|
+
Only one pagination method is possible.
|
380
|
+
|
381
|
+
```ruby
|
382
|
+
StrapiRuby.get(resource: :articles, start: 0, limit: 10)
|
383
|
+
# => /articles?pagination[start]=0&pagination[limit]=10
|
384
|
+
```
|
385
|
+
|
386
|
+
#### locale
|
387
|
+
|
388
|
+
I18n plugin should be installed.
|
389
|
+
|
390
|
+
```ruby
|
391
|
+
StrapiRuby.get(resource: :articles, locale: :fr)
|
392
|
+
#=>?/articles?locale=fr
|
393
|
+
```
|
394
|
+
|
395
|
+
#### publication_state
|
396
|
+
|
397
|
+
Use `preview` or `live`
|
398
|
+
|
399
|
+
```ruby
|
400
|
+
StrapiRuby.get(resource: :articles, publication_state: :preview)
|
401
|
+
#=>?/articles?publicationState=preview
|
402
|
+
```
|
403
|
+
|
404
|
+
### Use raw query
|
405
|
+
|
406
|
+
If you wanna pass a raw query you decide to build, just use raw as an option.
|
407
|
+
It cannot be combined with any other Strapi parameters.
|
408
|
+
|
409
|
+
```ruby
|
410
|
+
StrapiRuby.get(resource: articles:, raw: "?fields=title&sort=createdAt:desc")
|
411
|
+
# => /articles?fields=title&sort=createdAt:desc"
|
412
|
+
```
|
413
|
+
|
414
|
+
## Configuration
|
415
|
+
|
416
|
+
You can pass more options via the config block.
|
417
|
+
|
418
|
+
### Show Endpoint
|
419
|
+
|
420
|
+
This option is for accessing the resulting endpoint in a **successful** error, ie. `strapi_server_uri` + its query.
|
421
|
+
|
422
|
+
It defaults to `false`.
|
423
|
+
|
424
|
+
```ruby
|
425
|
+
# Pass this as a parameter to the config block
|
426
|
+
StrapiRuby.configure do |config|
|
427
|
+
#...
|
428
|
+
config.show_endpoint = true
|
429
|
+
#...
|
430
|
+
end
|
431
|
+
|
432
|
+
# Or as an option to one of the API functions
|
433
|
+
StrapiRuby.get(resource: :articles, show_endpoint: true)
|
434
|
+
|
435
|
+
|
436
|
+
# You can access it in the answer
|
437
|
+
|
438
|
+
StrapiRuby.get(resource: :articles, show_endpoint: true).endpoint
|
439
|
+
# => https://localhost:1337/api/restaurants
|
440
|
+
```
|
441
|
+
|
442
|
+
Or directly in the options parameters
|
443
|
+
|
444
|
+
### DateTime Conversion
|
445
|
+
|
446
|
+
By default, any `createdAt`, `publishedAt` and `updatedAt` fields in the answer will be recursively converted to `DateTime` instances, making it easy to use [`#strftime`](https://ruby-doc.org/stdlib-2.6.1/libdoc/date/rdoc/DateTime.html#method-i-strftime) method.
|
447
|
+
|
448
|
+
But if you don't want this conversion, pass it to the configure block.
|
449
|
+
|
450
|
+
```ruby
|
451
|
+
StrapiRuby.configure do |config|
|
452
|
+
#...
|
453
|
+
config.convert_to_datetime = false
|
454
|
+
#...
|
455
|
+
end
|
456
|
+
```
|
457
|
+
|
458
|
+
### Markdown Conversion
|
459
|
+
|
460
|
+
Selected fields will automatically be converted to HTML using `redcarpet` gem. This is very useful to get data ready for the views.
|
461
|
+
|
462
|
+
```ruby
|
463
|
+
# You can pass this in your config file:
|
464
|
+
|
465
|
+
StrapiRuby.configure do |config|
|
466
|
+
#...
|
467
|
+
config.convert_to_html = [:body]
|
468
|
+
#...
|
469
|
+
end
|
470
|
+
|
471
|
+
# Or as an option to one of the API functions
|
472
|
+
StrapiRuby.get(resource: :articles, fields: :body, convert_to_html: [:body])
|
473
|
+
```
|
474
|
+
|
475
|
+
### Faraday Block
|
476
|
+
|
477
|
+
#### Passing a Proc
|
478
|
+
|
479
|
+
You can pass a proc when configuring Strapi Ruby just as you'd pass a block when creating a new instance of a Faraday.
|
480
|
+
Check [Faraday documentation](https://lostisland.github.io/faraday/#/customization/connection-options)
|
481
|
+
|
482
|
+
```ruby
|
483
|
+
StrapiRuby.configure do |config|
|
484
|
+
#...
|
485
|
+
config.faraday = Proc.new do |faraday|
|
486
|
+
faraday.headers['X-Custom-Header'] = 'Custom-Value'
|
487
|
+
end
|
488
|
+
#...
|
489
|
+
end
|
490
|
+
```
|
491
|
+
|
492
|
+
#### Default Faraday::Connection used by the gem
|
493
|
+
|
494
|
+
Default options used by this gem are `url_encode` and `Faraday.default_adapter`, but you can override them.
|
495
|
+
|
496
|
+
#### Default Faraday::Connection headers
|
497
|
+
|
498
|
+
Default headers cannot be overriden but will be merged with your added configuration.
|
499
|
+
|
500
|
+
```ruby
|
501
|
+
default_headers = { "Content-Type" => "application/json",
|
502
|
+
"Authorization" => "Bearer #{strapi_token}",
|
503
|
+
"User-Agent" => "StrapiRuby/#{StrapiRuby::VERSION}" }
|
504
|
+
```
|
505
|
+
|
506
|
+
### Handling Errors
|
507
|
+
|
508
|
+
Depending on your utilisation, there are multiple ways to handle errors.
|
509
|
+
|
510
|
+
#### Error Classes
|
511
|
+
|
512
|
+
```ruby
|
513
|
+
# Config Error
|
514
|
+
class ConfigurationError < StandardError
|
515
|
+
|
516
|
+
# Client Error
|
517
|
+
class ClientError < StandardError
|
518
|
+
|
519
|
+
# Client Error Specific Error
|
520
|
+
class ConnectionError < ClientError
|
521
|
+
class UnauthorizedError < ClientError
|
522
|
+
class ForbiddenError < ClientError
|
523
|
+
class NotFoundError < ClientError
|
524
|
+
class UnprocessableEntityError < ClientError
|
525
|
+
class ServerError < ClientError
|
526
|
+
class BadRequestError < ClientError
|
527
|
+
class JSONParsingError < ClientError
|
528
|
+
```
|
529
|
+
|
530
|
+
#### Gracefuly degrade errors when they happen
|
531
|
+
|
532
|
+
One way to handle errors and gracefuly degrade is using `.escape_empty_answer` and use a block to nest your data accessing code.
|
533
|
+
|
534
|
+
##### Definition
|
535
|
+
|
536
|
+
```ruby
|
537
|
+
# Definition
|
538
|
+
module StrapiRuby
|
539
|
+
def escape_empty_answer(answer)
|
540
|
+
return answer.error.message if answer.data.nil?
|
541
|
+
yield
|
542
|
+
end
|
543
|
+
end
|
544
|
+
```
|
545
|
+
|
546
|
+
##### Example : Usage in a Rails view
|
547
|
+
|
548
|
+
```erb
|
549
|
+
<% StrapiRuby.escape_empty_answer(answer) do %>
|
550
|
+
<%= answer.title %>
|
551
|
+
<%= answer.body %>
|
552
|
+
<% end %>
|
553
|
+
```
|
554
|
+
|
555
|
+
Or you may want to handle specific errors like this:
|
556
|
+
|
557
|
+
```ruby
|
558
|
+
# some_controller.rb
|
559
|
+
begin
|
560
|
+
answer = StrapiRuby.get(resource: "articles")
|
561
|
+
rescue NotFoundError e =>
|
562
|
+
# Do something to avoid an embarassing situation
|
563
|
+
rescue ClientError e =>
|
564
|
+
# Do something to avoid an embarassing situation
|
565
|
+
end
|
566
|
+
```
|
567
|
+
|
568
|
+
## Contributing
|
569
|
+
|
570
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/saint-james-fr/strapi_ruby](https://github.com/saint-james-fr/strapi_ruby). This project is intended to be a safe, welcoming space for collaboration.
|
571
|
+
|
572
|
+
## Tests
|
573
|
+
|
574
|
+
Run `bundle exec rspec` to run the tests.
|
575
|
+
|
576
|
+
Inside `spec/integration.rb` you'll have access to integration tests.
|
577
|
+
You'll need to configure environment variables within the repo and run a strapi server to run these tests sucessfully.
|
578
|
+
See Strapi documentation for more details about installing a Strapi Server [here](https://docs.strapi.io/dev-docs/quick-start)
|
579
|
+
|
580
|
+
## License
|
581
|
+
|
582
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
Binary file
|
data/features.md
ADDED