storyblok 2.1.1 → 3.0.0

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: 33a4596358cf0ba305669f743c068507e4101df1ef108489220aea87ab080a10
4
- data.tar.gz: 39d281b937424cc102f5aed916e5b49ec139fa57991d0bdf033d2dcd3a7e6cce
3
+ metadata.gz: 5b52ba5dae9347e6869eff8ae51d53d3b569eef875132b569bcfd8c88c648650
4
+ data.tar.gz: b15b55e78b254420e70016a9258e4c31f9fcd855a97050ae64972b9ce16aeeeb
5
5
  SHA512:
6
- metadata.gz: 15b2d39171573e27f50353dfb643930b7c8cf2b8c57ed00576c5b58ffad967376b199635aacabfb37363580bcce5df9dc7e878f56a79182cfe4017ee7f606545
7
- data.tar.gz: 99271032e787a4d40270692800c95e8b7b2d2419ced123ea022d4e67436d0937d11477beac638449421cf1dbdde624cf771dd785a535b8c6c22d4709eab8337e
6
+ metadata.gz: 5265d40c02b920d73d783306810c0dffd1498574b607dd2af7ac658895efbf428f2812b04abdf56ca0e5107a050483f55f98e6c48a371da037bfcfa1fba9c01d
7
+ data.tar.gz: c7df3f398a7cffe56773d1c286b68ab9be0edcc3791fff45abdc504249b2ba70a0096aa43e6798e38b4b56f374008fc8007fdf9157835ba5a756c9e28a9d7c87
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
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
 
@@ -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,11 +12,14 @@ 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:
22
+ cache_version: Time.now.to_i,
20
23
  cache: nil
21
24
  }
22
25
 
@@ -185,9 +188,16 @@ module Storyblok
185
188
  end
186
189
  end
187
190
 
188
- 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
189
198
  end
190
199
 
200
+
191
201
  def flush
192
202
  unless cache.nil?
193
203
  cache.set('storyblok:' + configuration[:token] + ':version', space['data']['space']['version'])
@@ -301,5 +311,86 @@ module Storyblok
301
311
  "#{prefix}=#{URI.encode_www_form_component(value)}"
302
312
  end
303
313
  end
314
+
315
+ def resolve_stories(result, params)
316
+ data = result['data']
317
+ rels = data['rels']
318
+ links = data['links']
319
+
320
+ if data['stories'].nil?
321
+ find_and_fill_relations(data.dig('story', 'content'), params[:resolve_relations], rels)
322
+ find_and_fill_links(data.dig('story', 'content'), links)
323
+ else
324
+ data['stories'].each do |story|
325
+ find_and_fill_relations(story['content'], params[:resolve_relations], rels)
326
+ find_and_fill_links(story['content'], links)
327
+ end
328
+ end
329
+
330
+ result
331
+ end
332
+
333
+ def find_and_fill_links(content, links)
334
+ return if content.nil? || links.nil? || links.size.zero?
335
+
336
+ if content.is_a? Array
337
+ content.each do |item|
338
+ find_and_fill_links(item, links)
339
+ end
340
+ elsif content.is_a? Hash
341
+ content['story'] = nil
342
+ content.each do |_k, value|
343
+ if !content['fieldtype'].nil?
344
+ if content['fieldtype'] == 'multilink' && content['linktype'] == 'story'
345
+ id =
346
+ if content['id'].is_a? String
347
+ content['id']
348
+ elsif content['uuid'].is_a? String
349
+ content['uuid']
350
+ end
351
+
352
+ links.each do |link|
353
+ if link['uuid'] == id
354
+ content['story'] = link
355
+ break
356
+ end
357
+ end
358
+ end
359
+ end
360
+
361
+ find_and_fill_links(value, links)
362
+ end
363
+ content.delete('story') if content['story'].nil?
364
+ end
365
+ end
366
+
367
+ def find_and_fill_relations(content, relation_params, rels)
368
+ return if content.nil? || rels.nil? || rels.size.zero?
369
+
370
+ if content.is_a? Array
371
+ content.each do |item|
372
+ find_and_fill_relations(item, relation_params, rels)
373
+ end
374
+ elsif content.is_a? Hash
375
+ content.each do |_k, value|
376
+ if !content['component'].nil? && !content['_uid'].nil?
377
+ relation_params.split(',').each do |relation|
378
+ component, field_name = relation.split('.')
379
+
380
+ if (content['component'] == component) && !content[field_name].nil?
381
+ rels.each do |rel|
382
+ index = content[field_name].index(rel['uuid'])
383
+ if !index.nil?
384
+ content[field_name][index] = rel
385
+ end
386
+ end
387
+ end
388
+ end
389
+ end
390
+
391
+ find_and_fill_relations(value, relation_params, rels)
392
+ end
393
+ end
394
+ end
304
395
  end
305
396
  end
@@ -1,4 +1,4 @@
1
1
  module Storyblok
2
2
  # Gem Version
3
- VERSION = '2.1.1'
3
+ VERSION = '3.0.0'
4
4
  end
@@ -0,0 +1,91 @@
1
+ require 'redis'
2
+ require_relative '../../lib/storyblok/cache/redis'
3
+ require 'spec_helper'
4
+
5
+ describe Storyblok::Cache::Redis, redis_cache: true do
6
+ let(:redis_client) {
7
+ raise StandardError, "Environment variable 'REDIS_URL' is not defined" if ENV['REDIS_URL'].nil?
8
+ Redis.new(url: ENV['REDIS_URL'])
9
+ }
10
+
11
+ context "When '::Redis' from redis-rb gem is not available" do
12
+ let!(:redis_constant_copy) { ::Redis }
13
+ before { Object.send(:remove_const, :Redis) }
14
+ after { ::Redis = redis_constant_copy }
15
+ it "raises Redis.current could not be found" do
16
+ expect{ subject }.to raise_error(RuntimeError, 'Redis.current could not be found. Supply :redis option or make sure Redis.current is available.')
17
+ end
18
+ end
19
+
20
+ context "When Storyblok::Cache::Redis is initialized without 'redis' arg" do
21
+ it "asks the redis to '::Redis.current'" do
22
+ redis_current = nil
23
+ expect{ redis_current = subject.redis }.not_to raise_error
24
+ expect(redis_current.object_id).to eq(::Redis.current.object_id)
25
+ end
26
+ end
27
+
28
+ describe "#cache" do
29
+ before { redis_client.keys("storyblok:*").each { |e| redis_client.del(e) } }
30
+
31
+ let(:key) { "storyblok:my_cache_key" }
32
+ context "When is passed an block" do
33
+ context "When the result it's not cached" do
34
+ it "caches the block result and returns the block call result" do
35
+ expect{
36
+ subject.cache(key){ "my_value" }
37
+ }.to change { redis_client.keys("#{key}*").size }.from(0).to(1)
38
+
39
+ expect(redis_client.get(key)).to eq("my_value")
40
+ end
41
+ end
42
+
43
+ context "When the arg expire as '0' is passed" do
44
+ let(:expire) { 0 }
45
+ it "returns the result of the block" do
46
+ expect(subject.cache(key, expire){ "my_value" } ).to eq("my_value")
47
+ end
48
+
49
+ it "doesn't cache anything" do
50
+ expect{ subject.cache(key, expire){ "my_value" } }.not_to change { redis_client.keys.size }
51
+ end
52
+ end
53
+
54
+ context "When the key has value on cache" do
55
+ before { subject.cache(key){ "my_value_cached" } }
56
+ it "the block it's no called and the cache stays untouched and the cached value is returned" do
57
+ expect{
58
+ subject.cache(key){ "my_new_value" }
59
+ }.not_to change { redis_client.keys("#{key}*").size }
60
+
61
+ expect(redis_client.get(key)).to eq("my_value_cached")
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ describe "#set" do
68
+ subject { super().set(key, value, expire) }
69
+ before { redis_client.keys("storyblok:*").each { |e| redis_client.del(e) } }
70
+ let(:key) {'storyblok:my_key'}
71
+ let(:value) {'my_value'}
72
+
73
+ context "When arg 'expire' is false" do
74
+ let(:expire) { false }
75
+ it "store the key value at Redis database WITHOUT expiration" do
76
+ expect{ subject }.to change { redis_client.keys("#{key}*").size }.from(0).to(1)
77
+ expect(redis_client.get(key)).to eq(value)
78
+ expect(redis_client.ttl(key)).to eq(-1) # -1 means no expiration for redis key
79
+ end
80
+ end
81
+
82
+ context "When args 'expire' is valid integer" do
83
+ let(:expire) { 60 * 60 }
84
+ it "store the key value at Redis database WITH expiration" do
85
+ expect{ subject }.to change { redis_client.keys("#{key}*").size }.from(0).to(1)
86
+ expect(redis_client.get(key)).to eq(value)
87
+ expect(redis_client.ttl(key)).to be > 1
88
+ end
89
+ end
90
+ end
91
+ end