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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15b954d3cf0dc7ca6346d490dfe34ed0b676cbd3eef222d7091860d31c7103b4
4
- data.tar.gz: f5aaa23eac80dba3e1129c729c96aa3f57a4fcda746a6bdd14a6e914a25523fb
3
+ metadata.gz: a0a390c17a7c90bad28b7a799a7f151486d55d38977a98257cf67a1cd539e9dd
4
+ data.tar.gz: 54f9aaad47ad4d435cd40292fc969e9250c5f934c278475880f83a077e49b7cc
5
5
  SHA512:
6
- metadata.gz: 69cdd57edaab0f030cd3018a0e27caa4d28dde70ca6e4b75d00bd773d71838d3e8de9346e05b53c1b8885f273037787c09a08937de6564193bde954831e91941
7
- data.tar.gz: 4680ba3b6697ad2e25bd50cb0039dc3b3a4c3652df680045e862a80a8d9625d057a388d3d0b448bf5c17c042c2cea158672f2144fde359311b8ece9eb68dc58e
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.6)
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.0904)
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="welcome">#{data['welcome_text']}</div>"
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.story('article/article-1')
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']['story']['content']['intro']
23
- puts client.render(res['data']['story']['content']['intro'])
30
+ puts res['data']
31
+ #puts client.render(res['data']['story']['content']['intro'])
@@ -3,7 +3,9 @@ module Storyblok
3
3
  class Redis
4
4
  DEFAULT_CONFIGURATION = {
5
5
  ttl: 60 * 60 * 24
6
- }
6
+ }.freeze
7
+
8
+ attr_reader :redis
7
9
 
8
10
  def initialize(*args)
9
11
  options = args.last.is_a?(::Hash) ? args.pop : {}
@@ -12,16 +12,19 @@ module Storyblok
12
12
  DEFAULT_CONFIGURATION = {
13
13
  secure: true,
14
14
  api_url: 'api.storyblok.com',
15
- api_version: 1,
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
- version = cache.get('storyblok:' + configuration[:token] + ':version') || '0'
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', Time.now.to_i.to_s)
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
- {'headers' => res.headers, 'data' => JSON.parse(res.body)}.to_json
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
- query[:cv] = configuration[:cache_version] if query[:cache_version].nil?
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
@@ -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 = URI.escape(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
@@ -1,4 +1,4 @@
1
1
  module Storyblok
2
2
  # Gem Version
3
- VERSION = '2.0.8'
3
+ VERSION = '3.0.1'
4
4
  end
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: 2.0.8
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: 2020-04-17 00:00:00.000000000 Z
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