storyblok 2.0.8 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +36 -4
- data/examples/renderer.rb +16 -8
- data/lib/storyblok/cache/redis.rb +3 -1
- data/lib/storyblok/client.rb +117 -16
- data/lib/storyblok/request.rb +4 -3
- data/lib/storyblok/version.rb +1 -1
- metadata +58 -3
- data/storyblok.gemspec +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0a390c17a7c90bad28b7a799a7f151486d55d38977a98257cf67a1cd539e9dd
|
4
|
+
data.tar.gz: 54f9aaad47ad4d435cd40292fc969e9250c5f934c278475880f83a077e49b7cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 179c3cc2405a6370ab2cc924fa925df5df0a2737b18cd76ac6c6183e3c980889dd1782a4b3cb6f3f0e963124e138639864b6ed04fd293286c647fcf03a092424
|
7
|
+
data.tar.gz: aff00d8502c0816aac6078e68d4060db5a8041249c695f5e55c2c2ea8825ebf63efd788fd408acb9f9408ad57ce9f375eb098a5cb05253f8c820b1b3cd8c25aa
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
storyblok (2.0.
|
4
|
+
storyblok (2.0.8)
|
5
5
|
rest-client (>= 1.8.0, < 3)
|
6
6
|
storyblok-richtext-renderer (>= 0.0.4, < 1)
|
7
7
|
|
@@ -16,7 +16,7 @@ GEM
|
|
16
16
|
domain_name (~> 0.5)
|
17
17
|
mime-types (3.3)
|
18
18
|
mime-types-data (~> 3.2015)
|
19
|
-
mime-types-data (3.2019.
|
19
|
+
mime-types-data (3.2019.1009)
|
20
20
|
netrc (0.11.0)
|
21
21
|
redis (4.1.0)
|
22
22
|
rest-client (2.1.0)
|
data/README.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/76e7fcc8524d4fadeeee/test_coverage)](https://codeclimate.com/github/storyblok/storyblok-ruby/test_coverage)
|
2
|
+
![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/storyblok/storyblok-ruby/RSpec%20Tests/master)
|
3
|
+
[![Ruby Gems Downloads](https://img.shields.io/gem/dt/storyblok)](https://rubygems.org/gems/storyblok)
|
4
|
+
[![Inline docs](https://inch-ci.org/github/storyblok/storyblok-ruby.svg?branch=master)](https://www.rubydoc.info/gems/storyblok)
|
5
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/76e7fcc8524d4fadeeee/maintainability)](https://codeclimate.com/github/storyblok/storyblok-ruby/maintainability)
|
6
|
+
|
1
7
|
# About
|
2
|
-
This is the Storyblok ruby client for easy access of the management and content delivery api.
|
8
|
+
This is the official [Storyblok](https://www.storyblok.com/) ruby client for easy access of the management and content delivery api.
|
3
9
|
|
4
10
|
## Install
|
5
11
|
|
@@ -120,7 +126,7 @@ client.flush
|
|
120
126
|
client = Storyblok::Client.new(oauth_token: 'YOUR_OAUTH_TOKEN')
|
121
127
|
|
122
128
|
# Get your spaces
|
123
|
-
client.get('spaces')
|
129
|
+
client.get('spaces/')
|
124
130
|
```
|
125
131
|
|
126
132
|
### Create a story
|
@@ -158,12 +164,12 @@ Storyblok's richtext field also let's you insert content blocks. To render these
|
|
158
164
|
```ruby
|
159
165
|
# Option 1: Define the resolver when initializing
|
160
166
|
client = Storyblok::Client.new(
|
161
|
-
component_resolver: ->(component, data)
|
167
|
+
component_resolver: ->(component, data) {
|
162
168
|
case component
|
163
169
|
when 'button'
|
164
170
|
"<button>#{data['text']}</button>"
|
165
171
|
when 'your_custom_component'
|
166
|
-
"<div class=
|
172
|
+
"<div class='welcome'>#{data['welcome_text']}</div>"
|
167
173
|
end
|
168
174
|
}
|
169
175
|
)
|
@@ -183,6 +189,32 @@ gem build storyblok.gemspec
|
|
183
189
|
gem push storyblok-2.0.X.gem
|
184
190
|
~~~
|
185
191
|
|
192
|
+
### Running Tests
|
193
|
+
We use [RSpec](http://rspec.info/) for testing.
|
194
|
+
|
195
|
+
#### To run the whole test suite you will need export the environment variables, ATTENTION when running the test suit with the variable `REDIS_URL` exported, the test suite will remove the keys with this pattern `storyblok:*` from the redis database defined by `REDIS_URL`
|
196
|
+
|
197
|
+
```bash
|
198
|
+
export REDIS_URL="redis://localhost:6379"
|
199
|
+
```
|
200
|
+
|
201
|
+
Optionally you can generate the test report coverage by setting the environment variable
|
202
|
+
|
203
|
+
```bash
|
204
|
+
export COVERAGE=true
|
205
|
+
```
|
206
|
+
|
207
|
+
To run the whole test suite use the following command:
|
208
|
+
|
209
|
+
```bash
|
210
|
+
rspec
|
211
|
+
```
|
212
|
+
|
213
|
+
To run tests without redis cache tests (for when you don't have redis, or to avoid the test suite to remove the keys with this pattern `storyblok:*` ):
|
214
|
+
|
215
|
+
```bash
|
216
|
+
rspec --tag ~redis_cache:true
|
217
|
+
```
|
186
218
|
|
187
219
|
### License
|
188
220
|
|
data/examples/renderer.rb
CHANGED
@@ -1,23 +1,31 @@
|
|
1
1
|
# bundle exec ruby examples/renderer.rb
|
2
2
|
|
3
3
|
require_relative '../lib/storyblok'
|
4
|
+
require 'redis'
|
4
5
|
|
5
6
|
logger = Logger.new(STDOUT)
|
6
7
|
|
8
|
+
redis = Redis.new(url: 'redis://localhost:6379')
|
9
|
+
cache = Storyblok::Cache::Redis.new(redis: redis)
|
10
|
+
|
7
11
|
client = Storyblok::Client.new(
|
8
12
|
token: '6HMYdAjBoONyuS6GIf5PdAtt',
|
9
13
|
logger: logger,
|
10
14
|
component_resolver: ->(component, data) {
|
11
15
|
"Placeholder for #{component}: #{data['text']}"
|
12
|
-
}
|
16
|
+
},
|
17
|
+
api_url: 'api-testing.storyblok.com',
|
18
|
+
api_version: 2,
|
19
|
+
cache: cache
|
13
20
|
)
|
14
21
|
|
15
|
-
puts client.render({'type' => 'doc', 'content' => [
|
16
|
-
{'type' => 'paragraph', 'content' => [{'text' => 'Good', 'type' => 'text'}]},
|
17
|
-
{'type' => 'blok', 'attrs' => {'body' => [{'component' => 'button', 'text' => 'Click me'}]}}
|
18
|
-
]})
|
19
22
|
|
20
|
-
res = client.
|
23
|
+
res = client.flush
|
24
|
+
res = client.story('authors/page', {version: 'published'})
|
25
|
+
puts client.cache_version
|
26
|
+
res = client.story('authors/page', {version: 'published'})
|
27
|
+
res = client.story('authors/page', {version: 'published'})
|
28
|
+
res = client.story('authors/page', {version: 'published'})
|
21
29
|
|
22
|
-
puts res['data']
|
23
|
-
puts client.render(res['data']['story']['content']['intro'])
|
30
|
+
puts res['data']
|
31
|
+
#puts client.render(res['data']['story']['content']['intro'])
|
data/lib/storyblok/client.rb
CHANGED
@@ -12,16 +12,19 @@ module Storyblok
|
|
12
12
|
DEFAULT_CONFIGURATION = {
|
13
13
|
secure: true,
|
14
14
|
api_url: 'api.storyblok.com',
|
15
|
-
api_version:
|
15
|
+
api_version: 2,
|
16
16
|
logger: false,
|
17
17
|
log_level: Logger::INFO,
|
18
18
|
version: 'draft',
|
19
|
+
# :nocov:
|
19
20
|
component_resolver: ->(component, data) { '' },
|
21
|
+
# :nocov:
|
20
22
|
cache_version: Time.now.to_i,
|
21
23
|
cache: nil
|
22
24
|
}
|
23
25
|
|
24
26
|
attr_reader :configuration, :logger
|
27
|
+
attr_accessor :cache_version
|
25
28
|
|
26
29
|
# @param [Hash] given_configuration
|
27
30
|
# @option given_configuration [String] :token Required if oauth_token is not set
|
@@ -33,6 +36,7 @@ module Storyblok
|
|
33
36
|
# @option given_configuration [::Logger::DEBUG, ::Logger::INFO, ::Logger::WARN, ::Logger::ERROR] :log_level
|
34
37
|
def initialize(given_configuration = {})
|
35
38
|
@configuration = default_configuration.merge(given_configuration)
|
39
|
+
@cache_version = '0'
|
36
40
|
validate_configuration!
|
37
41
|
|
38
42
|
if configuration[:oauth_token]
|
@@ -62,7 +66,7 @@ module Storyblok
|
|
62
66
|
#
|
63
67
|
# @return [Hash]
|
64
68
|
def space(query = {})
|
65
|
-
Request.new(self, '/cdn/spaces/me', query).get
|
69
|
+
Request.new(self, '/cdn/spaces/me', query, nil, true).get
|
66
70
|
end
|
67
71
|
|
68
72
|
# Gets a collection of stories
|
@@ -169,32 +173,34 @@ module Storyblok
|
|
169
173
|
parse_result(res)
|
170
174
|
end
|
171
175
|
|
172
|
-
def cached_get(request)
|
176
|
+
def cached_get(request, bypass_cache = false)
|
173
177
|
endpoint = base_url + request.url
|
178
|
+
query = request_query(request.query)
|
179
|
+
query_string = build_nested_query(query)
|
174
180
|
|
175
|
-
if cache.nil?
|
176
|
-
query = request_query(request.query)
|
177
|
-
query_string = build_nested_query(query)
|
181
|
+
if cache.nil? || bypass_cache || query[:version] == 'draft'
|
178
182
|
result = run_request(endpoint, query_string)
|
179
183
|
else
|
180
|
-
|
181
|
-
|
182
|
-
query = query = request_query({ cache_version: version }.merge(request.query))
|
183
|
-
query_string = build_nested_query(query)
|
184
|
-
|
185
|
-
cache_key = 'storyblok:' + configuration[:token] + ':v:' + version + ':' + request.url + ':' + Base64.encode64(query_string)
|
184
|
+
cache_key = 'storyblok:' + configuration[:token] + ':v:' + query[:cv] + ':' + request.url + ':' + Base64.encode64(query_string)
|
186
185
|
|
187
186
|
result = cache.cache(cache_key) do
|
188
187
|
run_request(endpoint, query_string)
|
189
188
|
end
|
190
189
|
end
|
191
190
|
|
192
|
-
JSON.parse(result)
|
191
|
+
result = JSON.parse(result)
|
192
|
+
|
193
|
+
if !result.dig('data', 'story').nil? || !result.dig('data', 'stories').nil?
|
194
|
+
result = resolve_stories(result, query)
|
195
|
+
end
|
196
|
+
|
197
|
+
result
|
193
198
|
end
|
194
199
|
|
200
|
+
|
195
201
|
def flush
|
196
202
|
unless cache.nil?
|
197
|
-
cache.set('storyblok:' + configuration[:token] + ':version',
|
203
|
+
cache.set('storyblok:' + configuration[:token] + ':version', space['data']['space']['version'])
|
198
204
|
end
|
199
205
|
end
|
200
206
|
|
@@ -240,14 +246,27 @@ module Storyblok
|
|
240
246
|
raise
|
241
247
|
end
|
242
248
|
|
243
|
-
|
249
|
+
body = JSON.parse(res.body)
|
250
|
+
self.cache_version = body['cv'] if body['cv']
|
251
|
+
|
252
|
+
unless cache.nil?
|
253
|
+
cache.set('storyblok:' + configuration[:token] + ':version', cache_version)
|
254
|
+
end
|
255
|
+
|
256
|
+
{'headers' => res.headers, 'data' => body}.to_json
|
244
257
|
end
|
245
258
|
|
246
259
|
# Patches a query hash with the client configurations for queries
|
247
260
|
def request_query(query)
|
248
261
|
query[:token] = configuration[:token] if query[:token].nil?
|
249
262
|
query[:version] = configuration[:version] if query[:version].nil?
|
250
|
-
|
263
|
+
|
264
|
+
unless cache.nil?
|
265
|
+
query[:cv] = (cache.get('storyblok:' + configuration[:token] + ':version') or cache_version) if query[:cv].nil?
|
266
|
+
else
|
267
|
+
query[:cv] = cache_version if query[:cv].nil?
|
268
|
+
end
|
269
|
+
|
251
270
|
query
|
252
271
|
end
|
253
272
|
|
@@ -292,5 +311,87 @@ module Storyblok
|
|
292
311
|
"#{prefix}=#{URI.encode_www_form_component(value)}"
|
293
312
|
end
|
294
313
|
end
|
314
|
+
|
315
|
+
def resolve_stories(result, params)
|
316
|
+
data = result['data']
|
317
|
+
rels = data['rels']
|
318
|
+
links = data['links']
|
319
|
+
resolve_relations = params[:resolve_relations] || params["resolve_relations"]
|
320
|
+
|
321
|
+
if data['stories'].nil?
|
322
|
+
find_and_fill_relations(data.dig('story', 'content'), resolve_relations, rels)
|
323
|
+
find_and_fill_links(data.dig('story', 'content'), links)
|
324
|
+
else
|
325
|
+
data['stories'].each do |story|
|
326
|
+
find_and_fill_relations(story['content'], resolve_relations, rels)
|
327
|
+
find_and_fill_links(story['content'], links)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
result
|
332
|
+
end
|
333
|
+
|
334
|
+
def find_and_fill_links(content, links)
|
335
|
+
return if content.nil? || links.nil? || links.size.zero?
|
336
|
+
|
337
|
+
if content.is_a? Array
|
338
|
+
content.each do |item|
|
339
|
+
find_and_fill_links(item, links)
|
340
|
+
end
|
341
|
+
elsif content.is_a? Hash
|
342
|
+
content['story'] = nil
|
343
|
+
content.each do |_k, value|
|
344
|
+
if !content['fieldtype'].nil?
|
345
|
+
if content['fieldtype'] == 'multilink' && content['linktype'] == 'story'
|
346
|
+
id =
|
347
|
+
if content['id'].is_a? String
|
348
|
+
content['id']
|
349
|
+
elsif content['uuid'].is_a? String
|
350
|
+
content['uuid']
|
351
|
+
end
|
352
|
+
|
353
|
+
links.each do |link|
|
354
|
+
if link['uuid'] == id
|
355
|
+
content['story'] = link
|
356
|
+
break
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
find_and_fill_links(value, links)
|
363
|
+
end
|
364
|
+
content.delete('story') if content['story'].nil?
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
def find_and_fill_relations(content, relation_params, rels)
|
369
|
+
return if content.nil? || rels.nil? || rels.size.zero?
|
370
|
+
|
371
|
+
if content.is_a? Array
|
372
|
+
content.each do |item|
|
373
|
+
find_and_fill_relations(item, relation_params, rels)
|
374
|
+
end
|
375
|
+
elsif content.is_a? Hash
|
376
|
+
content.each do |_k, value|
|
377
|
+
if !content['component'].nil? && !content['_uid'].nil?
|
378
|
+
relation_params.split(',').each do |relation|
|
379
|
+
component, field_name = relation.split('.')
|
380
|
+
|
381
|
+
if (content['component'] == component) && !content[field_name].nil?
|
382
|
+
rels.each do |rel|
|
383
|
+
index = content[field_name].index(rel['uuid'])
|
384
|
+
if !index.nil?
|
385
|
+
content[field_name][index] = rel
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
find_and_fill_relations(value, relation_params, rels)
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
295
396
|
end
|
296
397
|
end
|
data/lib/storyblok/request.rb
CHANGED
@@ -5,14 +5,15 @@ module Storyblok
|
|
5
5
|
class Request
|
6
6
|
attr_reader :client, :type, :query, :id, :endpoint
|
7
7
|
|
8
|
-
def initialize(client, endpoint, query = {}, id = nil)
|
8
|
+
def initialize(client, endpoint, query = {}, id = nil, bypass_cache = false)
|
9
9
|
@client = client
|
10
10
|
@endpoint = endpoint
|
11
11
|
@query = query
|
12
|
+
@bypass_cache = bypass_cache
|
12
13
|
|
13
14
|
if id
|
14
15
|
@type = :single
|
15
|
-
@id =
|
16
|
+
@id = id
|
16
17
|
else
|
17
18
|
@type = :multi
|
18
19
|
@id = nil
|
@@ -26,7 +27,7 @@ module Storyblok
|
|
26
27
|
|
27
28
|
# Delegates the actual HTTP work to the client
|
28
29
|
def get
|
29
|
-
client.cached_get(self)
|
30
|
+
client.cached_get(self, @bypass_cache)
|
30
31
|
end
|
31
32
|
|
32
33
|
# Returns a new Request object with the same data
|
data/lib/storyblok/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: storyblok
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Storyblok (Alexander Feiglstorfer)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -64,6 +64,20 @@ dependencies:
|
|
64
64
|
- - "~>"
|
65
65
|
- !ruby/object:Gem::Version
|
66
66
|
version: '1.5'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: hashdiff
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 1.0.1
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 1.0.1
|
67
81
|
- !ruby/object:Gem::Dependency
|
68
82
|
name: rspec
|
69
83
|
requirement: !ruby/object:Gem::Requirement
|
@@ -78,6 +92,48 @@ dependencies:
|
|
78
92
|
- - "~>"
|
79
93
|
- !ruby/object:Gem::Version
|
80
94
|
version: '3'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: webmock
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - '='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 3.14.0
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - '='
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: 3.14.0
|
109
|
+
- !ruby/object:Gem::Dependency
|
110
|
+
name: vcr
|
111
|
+
requirement: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - '='
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: 6.0.0
|
116
|
+
type: :development
|
117
|
+
prerelease: false
|
118
|
+
version_requirements: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - '='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 6.0.0
|
123
|
+
- !ruby/object:Gem::Dependency
|
124
|
+
name: simplecov
|
125
|
+
requirement: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "<"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: 0.18.0
|
130
|
+
type: :development
|
131
|
+
prerelease: false
|
132
|
+
version_requirements: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - "<"
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: 0.18.0
|
81
137
|
description: Ruby client for the https://www.storyblok.com management and content
|
82
138
|
delivery API
|
83
139
|
email: it@storyblok.com
|
@@ -105,7 +161,6 @@ files:
|
|
105
161
|
- lib/storyblok/links.rb
|
106
162
|
- lib/storyblok/request.rb
|
107
163
|
- lib/storyblok/version.rb
|
108
|
-
- storyblok.gemspec
|
109
164
|
homepage: https://github.com/storyblok/storyblok-ruby
|
110
165
|
licenses:
|
111
166
|
- MIT
|
data/storyblok.gemspec
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require File.expand_path('../lib/storyblok/version', __FILE__)
|
2
|
-
|
3
|
-
Gem::Specification.new do |gem|
|
4
|
-
gem.name = 'storyblok'
|
5
|
-
gem.version = Storyblok::VERSION
|
6
|
-
gem.summary = 'storyblok'
|
7
|
-
gem.description = 'Ruby client for the https://www.storyblok.com management and content delivery API'
|
8
|
-
gem.license = 'MIT'
|
9
|
-
gem.authors = ['Storyblok (Alexander Feiglstorfer)']
|
10
|
-
gem.email = 'it@storyblok.com'
|
11
|
-
gem.homepage = 'https://github.com/storyblok/storyblok-ruby'
|
12
|
-
|
13
|
-
gem.files = Dir['{**/}{.*,*}'].select { |path| File.file?(path) && !path.start_with?('pkg') && !path.end_with?('.gem') }
|
14
|
-
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
15
|
-
gem.test_files = gem.files.grep(%r{^spec/})
|
16
|
-
gem.require_paths = ['lib']
|
17
|
-
|
18
|
-
gem.add_dependency 'rest-client', '>= 1.8.0', '< 3'
|
19
|
-
gem.add_dependency 'storyblok-richtext-renderer', '>= 0.0.4', '< 1'
|
20
|
-
|
21
|
-
gem.add_development_dependency 'bundler', '~> 1.5'
|
22
|
-
gem.add_development_dependency 'rspec', '~> 3'
|
23
|
-
end
|