storyblok 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 +7 -0
- data/.editorconfig +9 -0
- data/.gitignore +8 -0
- data/Gemfile +3 -0
- data/README.md +78 -0
- data/examples/example_queries.rb +15 -0
- data/examples/tree.rb +29 -0
- data/lib/storyblok.rb +3 -0
- data/lib/storyblok/cache.rb +26 -0
- data/lib/storyblok/client.rb +153 -0
- data/lib/storyblok/links.rb +42 -0
- data/lib/storyblok/request.rb +37 -0
- data/lib/storyblok/version.rb +4 -0
- data/storyblok.gemspec +22 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8dbb219ff3c07b2f526fa5c816276ae32126dd6b
|
4
|
+
data.tar.gz: f59d2ebfa84847b4b5bb94a580a8e06e0d2e4e4b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7e6dd72f70bfa84ec18bf5f130a08a68f6c74d14f4dd39fd22b4bf5219ec183e0f826a48d52ca15bc862580f47b2cef07078607860d5d97b63277fe1cd3ad179
|
7
|
+
data.tar.gz: 4429276f86a4cdf585ff47cfe5a1631a87a0abf800186ef1edc2b4efd9aef91a66bf12453e6c2eb06066eab024f9b7927a2801a78e963beb6ebdab468a396135
|
data/.editorconfig
ADDED
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# About
|
2
|
+
This is the Storyblok ruby client for easy access of the content delivery api.
|
3
|
+
|
4
|
+
## Install
|
5
|
+
|
6
|
+
```bash
|
7
|
+
gem 'storyblok'
|
8
|
+
```
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
### Load a Story
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
client = new Storyblok(token: 'YOUR_TOKEN')
|
16
|
+
|
17
|
+
# Optionally set a cache client
|
18
|
+
Storyblok::Cache.client = Redis.new(:url => 'redis://localhost:6379')
|
19
|
+
|
20
|
+
# Get a story
|
21
|
+
client.story('home')
|
22
|
+
```
|
23
|
+
|
24
|
+
### Load a list of Stories
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
# Get all Stories that start with news
|
28
|
+
client.stories({
|
29
|
+
:starts_with => 'news'
|
30
|
+
})
|
31
|
+
```
|
32
|
+
|
33
|
+
### Load a list of datasource entries
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
# Get all label datasource entries
|
37
|
+
client.datasource_entries({
|
38
|
+
:datasource => 'labels'
|
39
|
+
})
|
40
|
+
|
41
|
+
```
|
42
|
+
|
43
|
+
### Load a list of tags
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
# Get all Tags that within the folder news
|
47
|
+
client.tags({
|
48
|
+
:starts_with => 'news'
|
49
|
+
})
|
50
|
+
|
51
|
+
```
|
52
|
+
|
53
|
+
## Generate a navigation tree
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
links = client.links
|
57
|
+
tree = links.as_tree
|
58
|
+
|
59
|
+
puts '<ul>'
|
60
|
+
tree.each do |key, item|
|
61
|
+
puts '<li>' + item['item']['name']
|
62
|
+
|
63
|
+
if !item['children'].empty?
|
64
|
+
puts '<ul>'
|
65
|
+
item['children'].each do |key, inner_item|
|
66
|
+
puts '<li>' + inner_item['item']['name'] + '</li>'
|
67
|
+
end
|
68
|
+
puts '</ul>'
|
69
|
+
end
|
70
|
+
|
71
|
+
puts '</li>'
|
72
|
+
end
|
73
|
+
puts '</ul>'
|
74
|
+
```
|
75
|
+
|
76
|
+
### License
|
77
|
+
|
78
|
+
This project is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'storyblok'
|
2
|
+
|
3
|
+
logger = Logger.new(STDOUT)
|
4
|
+
|
5
|
+
client = Storyblok::Client.new(
|
6
|
+
token: 't618GfLe1YHICBioAHnMrwtt',
|
7
|
+
api_url: 'localhost:3001',
|
8
|
+
secure: false,
|
9
|
+
logger: logger
|
10
|
+
)
|
11
|
+
|
12
|
+
p client.stories(starts_with: 'en/news')
|
13
|
+
p client.story('demo1')
|
14
|
+
p client.datasource_entries(datasource: 'labels', per_page: 10)
|
15
|
+
p client.links
|
data/examples/tree.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'storyblok'
|
2
|
+
|
3
|
+
logger = Logger.new(STDOUT)
|
4
|
+
|
5
|
+
client = Storyblok::Client.new(
|
6
|
+
token: 't618GfLe1YHICBioAHnMrwtt',
|
7
|
+
api_url: 'localhost:3001',
|
8
|
+
secure: false,
|
9
|
+
logger: logger
|
10
|
+
)
|
11
|
+
|
12
|
+
links = client.links
|
13
|
+
tree = links.as_tree
|
14
|
+
|
15
|
+
puts '<ul>'
|
16
|
+
tree.each do |key, item|
|
17
|
+
puts '<li>' + item['item']['name']
|
18
|
+
|
19
|
+
if !item['children'].empty?
|
20
|
+
puts '<ul>'
|
21
|
+
item['children'].each do |key, inner_item|
|
22
|
+
puts '<li>' + inner_item['item']['name'] + '</li>'
|
23
|
+
end
|
24
|
+
puts '</ul>'
|
25
|
+
end
|
26
|
+
|
27
|
+
puts '</li>'
|
28
|
+
end
|
29
|
+
puts '</ul>'
|
data/lib/storyblok.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Storyblok
|
2
|
+
class Cache
|
3
|
+
def self.client=(client)
|
4
|
+
@client = client
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.client
|
8
|
+
@client
|
9
|
+
end
|
10
|
+
|
11
|
+
def cache(key, expire = nil)
|
12
|
+
if expire == 0
|
13
|
+
return yield(self)
|
14
|
+
end
|
15
|
+
|
16
|
+
if (value = @client.get(key)).nil?
|
17
|
+
value = yield(self)
|
18
|
+
@client.set(key, value)
|
19
|
+
@client.expire(key, expire) if expire
|
20
|
+
value
|
21
|
+
else
|
22
|
+
value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require_relative 'request'
|
2
|
+
require_relative 'links'
|
3
|
+
|
4
|
+
require 'rest-client'
|
5
|
+
require 'logger'
|
6
|
+
|
7
|
+
module Storyblok
|
8
|
+
class Client
|
9
|
+
DEFAULT_CONFIGURATION = {
|
10
|
+
secure: true,
|
11
|
+
api_url: 'api.storyblok.com',
|
12
|
+
api_version: 1,
|
13
|
+
logger: false,
|
14
|
+
log_level: Logger::INFO,
|
15
|
+
version: 'draft',
|
16
|
+
cache_version: Time.now.to_i
|
17
|
+
}
|
18
|
+
|
19
|
+
attr_reader :configuration, :logger
|
20
|
+
|
21
|
+
# @param [Hash] given_configuration
|
22
|
+
# @option given_configuration [String] :token Required
|
23
|
+
# @option given_configuration [String] :api_url
|
24
|
+
# @option given_configuration [Number] :api_version
|
25
|
+
# @option given_configuration [false, ::Logger] :logger
|
26
|
+
# @option given_configuration [::Logger::DEBUG, ::Logger::INFO, ::Logger::WARN, ::Logger::ERROR] :log_level
|
27
|
+
def initialize(given_configuration = {})
|
28
|
+
@configuration = default_configuration.merge(given_configuration)
|
29
|
+
validate_configuration!
|
30
|
+
setup_logger
|
31
|
+
end
|
32
|
+
|
33
|
+
# Gets a collection of stories
|
34
|
+
#
|
35
|
+
# @param [Hash] query
|
36
|
+
#
|
37
|
+
# @return [Hash]
|
38
|
+
def stories(query = {})
|
39
|
+
Request.new(self, '/cdn/stories', query).get
|
40
|
+
end
|
41
|
+
|
42
|
+
# Gets a specific story
|
43
|
+
#
|
44
|
+
# @param [String] id
|
45
|
+
# @param [Hash] query
|
46
|
+
#
|
47
|
+
# @return [Hash]
|
48
|
+
def story(id, query = {})
|
49
|
+
Request.new(self, '/cdn/stories', query, id).get
|
50
|
+
end
|
51
|
+
|
52
|
+
# Gets a collection of datasource entries
|
53
|
+
#
|
54
|
+
# @param [Hash] query
|
55
|
+
#
|
56
|
+
# @return [Hash]
|
57
|
+
def datasource_entries(query = {})
|
58
|
+
Request.new(self, '/cdn/datasource_entries', query).get
|
59
|
+
end
|
60
|
+
|
61
|
+
# Gets a collection of tags
|
62
|
+
#
|
63
|
+
# @param [Hash] query
|
64
|
+
#
|
65
|
+
# @return [Hash]
|
66
|
+
def tags(query = {})
|
67
|
+
Request.new(self, '/cdn/tags', query).get
|
68
|
+
end
|
69
|
+
|
70
|
+
# Gets a collection of links
|
71
|
+
#
|
72
|
+
# @param [Hash] query
|
73
|
+
#
|
74
|
+
# @return [Hash]
|
75
|
+
def links(query = {})
|
76
|
+
Links.new(Request.new(self, '/cdn/links', query).get)
|
77
|
+
end
|
78
|
+
|
79
|
+
def get(request)
|
80
|
+
endpoint = base_url + request.endpoint
|
81
|
+
query = request_query(request.query)
|
82
|
+
query_string = build_nested_query(query)
|
83
|
+
|
84
|
+
if Cache.client.nil?
|
85
|
+
result = run_request(endpoint, query_string)
|
86
|
+
else
|
87
|
+
cache_key = 'storyblok:' + configuration[:token] + ':' + request.endpoint + ':' + Base64.encode64(query_string)
|
88
|
+
cache_time = 60 * 60 * 2
|
89
|
+
|
90
|
+
result = Cache.client.cache(cache_key, cache_time) do
|
91
|
+
run_request(endpoint, query)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
JSON.parse(result)
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def run_request(endpoint, query_string)
|
101
|
+
logger.info(request: { endpoint: endpoint, query: query_string }) if logger
|
102
|
+
res = RestClient.get "#{endpoint}?#{query_string}"
|
103
|
+
|
104
|
+
{headers: res.headers, data: JSON.parse(res.body)}.to_json
|
105
|
+
end
|
106
|
+
|
107
|
+
# Patches a query hash with the client configurations for queries
|
108
|
+
def request_query(query)
|
109
|
+
query[:token] = configuration[:token]
|
110
|
+
query[:version] = configuration[:version] if query[:version].nil?
|
111
|
+
query[:cv] = configuration[:cache_version] if query[:cache_version].nil?
|
112
|
+
query
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns the base url for all of the client's requests
|
116
|
+
def base_url
|
117
|
+
"http#{configuration[:secure] ? 's' : ''}://#{configuration[:api_url]}/v#{configuration[:api_version]}"
|
118
|
+
end
|
119
|
+
|
120
|
+
def default_configuration
|
121
|
+
DEFAULT_CONFIGURATION.dup
|
122
|
+
end
|
123
|
+
|
124
|
+
def setup_logger
|
125
|
+
@logger = configuration[:logger]
|
126
|
+
logger.level = configuration[:log_level] if logger
|
127
|
+
end
|
128
|
+
|
129
|
+
def validate_configuration!
|
130
|
+
fail ArgumentError, 'You will need to initialize a client with an :token' if configuration[:token].empty?
|
131
|
+
fail ArgumentError, 'The client configuration needs to contain an :api_url' if configuration[:api_url].empty?
|
132
|
+
fail ArgumentError, 'The :api_version must be a positive number' unless configuration[:api_version].to_i >= 0
|
133
|
+
end
|
134
|
+
|
135
|
+
def build_nested_query(value, prefix = nil)
|
136
|
+
case value
|
137
|
+
when Array
|
138
|
+
value.map { |v|
|
139
|
+
build_nested_query(v, "#{prefix}[]")
|
140
|
+
}.join("&")
|
141
|
+
when Hash
|
142
|
+
value.map { |k, v|
|
143
|
+
build_nested_query(v, prefix ? "#{prefix}[#{URI.encode_www_form_component(k)}]" : URI.encode_www_form_component(k))
|
144
|
+
}.reject(&:empty?).join('&')
|
145
|
+
when nil
|
146
|
+
prefix
|
147
|
+
else
|
148
|
+
raise ArgumentError, "value must be a Hash" if prefix.nil?
|
149
|
+
"#{prefix}=#{URI.encode_www_form_component(value)}"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Storyblok
|
2
|
+
class Links
|
3
|
+
def initialize(response_obj)
|
4
|
+
@links = response_obj['data']['links']
|
5
|
+
end
|
6
|
+
|
7
|
+
def as_tree
|
8
|
+
tree = {}
|
9
|
+
|
10
|
+
@links.each do |key, item|
|
11
|
+
if tree[item['parent_id']].nil?
|
12
|
+
tree[item['parent_id']] = []
|
13
|
+
end
|
14
|
+
|
15
|
+
tree[item['parent_id']] << item
|
16
|
+
end
|
17
|
+
|
18
|
+
generate_tree(0, tree)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def generate_tree(parent_id = 0, items)
|
24
|
+
tree = {}
|
25
|
+
|
26
|
+
if !items[parent_id].nil?
|
27
|
+
result = items[parent_id]
|
28
|
+
|
29
|
+
result.each do |item|
|
30
|
+
if tree[item['id']].nil?
|
31
|
+
tree[item['id']] = {}
|
32
|
+
end
|
33
|
+
|
34
|
+
tree[item['id']]['item'] = item
|
35
|
+
tree[item['id']]['children'] = generate_tree(item['id'], items)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
tree
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Storyblok
|
2
|
+
# This object represents a request that is to be made. It gets initialized by the client
|
3
|
+
# with domain specific logic. The client later uses the Request's #url and #query methods
|
4
|
+
# to execute the HTTP request.
|
5
|
+
class Request
|
6
|
+
attr_reader :client, :type, :query, :id, :endpoint
|
7
|
+
|
8
|
+
def initialize(client, endpoint, query = {}, id = nil)
|
9
|
+
@client = client
|
10
|
+
@endpoint = endpoint
|
11
|
+
@query = query
|
12
|
+
|
13
|
+
if id
|
14
|
+
@type = :single
|
15
|
+
@id = URI.escape(id)
|
16
|
+
else
|
17
|
+
@type = :multi
|
18
|
+
@id = nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the final URL, relative to a storyblok space
|
23
|
+
def url
|
24
|
+
"#{@endpoint}#{@type == :single ? "/#{id}" : ''}"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Delegates the actual HTTP work to the client
|
28
|
+
def get
|
29
|
+
client.get(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns a new Request object with the same data
|
33
|
+
def copy
|
34
|
+
Marshal.load(Marshal.dump(self))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/storyblok.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
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 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') }
|
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'
|
19
|
+
|
20
|
+
gem.add_development_dependency 'bundler', '~> 1.5'
|
21
|
+
gem.add_development_dependency 'rspec', '~> 3'
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: storyblok
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Storyblok (Alexander Feiglstorfer)
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-02-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rest-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.8'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3'
|
55
|
+
description: Ruby client for the https://www.storyblok.com Content Delivery API
|
56
|
+
email: it@storyblok.com
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- ".editorconfig"
|
62
|
+
- ".gitignore"
|
63
|
+
- ".ruby-version"
|
64
|
+
- Gemfile
|
65
|
+
- Gemfile.lock
|
66
|
+
- README.md
|
67
|
+
- examples/example_queries.rb
|
68
|
+
- examples/tree.rb
|
69
|
+
- lib/storyblok.rb
|
70
|
+
- lib/storyblok/cache.rb
|
71
|
+
- lib/storyblok/client.rb
|
72
|
+
- lib/storyblok/links.rb
|
73
|
+
- lib/storyblok/request.rb
|
74
|
+
- lib/storyblok/version.rb
|
75
|
+
- storyblok.gemspec
|
76
|
+
homepage: https://github.com/storyblok/storyblok-ruby
|
77
|
+
licenses:
|
78
|
+
- MIT
|
79
|
+
metadata: {}
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 2.5.1
|
97
|
+
signing_key:
|
98
|
+
specification_version: 4
|
99
|
+
summary: storyblok
|
100
|
+
test_files: []
|