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
@@ -0,0 +1,95 @@
|
|
1
|
+
require "faraday"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module StrapiRuby
|
5
|
+
class Client
|
6
|
+
attr_reader :connection
|
7
|
+
|
8
|
+
def initialize(options = {}, &block)
|
9
|
+
@connection = set_connection(options, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def get(endpoint)
|
13
|
+
response = performs_request { @connection.get(endpoint) }
|
14
|
+
handle_response(response)
|
15
|
+
end
|
16
|
+
|
17
|
+
def post(endpoint, body)
|
18
|
+
response = performs_request { @connection.post(endpoint, build_data_payload(body)) }
|
19
|
+
handle_response(response)
|
20
|
+
end
|
21
|
+
|
22
|
+
def put(endpoint, body)
|
23
|
+
response = performs_request { @connection.put(endpoint, build_data_payload(body)) }
|
24
|
+
handle_response(response)
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete(endpoint)
|
28
|
+
response = performs_request { @connection.delete(endpoint) }
|
29
|
+
handle_response(response)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def set_connection(options, &block)
|
35
|
+
url = options[:strapi_server_uri]
|
36
|
+
strapi_token = options[:strapi_token]
|
37
|
+
|
38
|
+
default_headers = { "Content-Type" => "application/json",
|
39
|
+
"Authorization" => "Bearer #{strapi_token}",
|
40
|
+
"User-Agent" => "StrapiRuby/#{StrapiRuby::VERSION}" }
|
41
|
+
|
42
|
+
Faraday.new(url: url) do |faraday|
|
43
|
+
faraday.request :url_encoded
|
44
|
+
faraday.adapter Faraday.default_adapter
|
45
|
+
block&.call(faraday)
|
46
|
+
faraday.headers = default_headers.merge(faraday.headers)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def performs_request
|
51
|
+
begin
|
52
|
+
yield
|
53
|
+
rescue Faraday::ConnectionFailed => e
|
54
|
+
raise ConnectionError, "#{ErrorMessage.connection_failed} #{e.message}"
|
55
|
+
rescue Faraday::TimeoutError => e
|
56
|
+
raise ConnectionError, "#{ErrorMessage.timeout} #{e.message}"
|
57
|
+
rescue StandardError => e
|
58
|
+
raise ConnectionError, "#{ErrorMessage.unexpected} #{e.message}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def convert_json_to_open_struct(json)
|
63
|
+
JSON.parse(json, object_class: OpenStruct)
|
64
|
+
rescue JSON::ParserError => e
|
65
|
+
raise JSONParsingError, e.message
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_data_payload(body)
|
69
|
+
{ data: body }.to_json
|
70
|
+
end
|
71
|
+
|
72
|
+
# rubocop:disable Metrics/AbcSize
|
73
|
+
def handle_response(response)
|
74
|
+
body = convert_json_to_open_struct(response.body)
|
75
|
+
case response.status
|
76
|
+
when 200
|
77
|
+
body
|
78
|
+
when 400
|
79
|
+
raise BadRequestError.new(body.error.message, response.status)
|
80
|
+
when 401
|
81
|
+
raise UnauthorizedError.new(body.error.message, response.status)
|
82
|
+
when 403
|
83
|
+
raise ForbiddenError.new(body.error.message, response.status)
|
84
|
+
when 404
|
85
|
+
raise NotFoundError.new(body.error.message, response.status)
|
86
|
+
when 422
|
87
|
+
raise UnprocessableEntityError.new(body.error.message, response.status)
|
88
|
+
when 500..599
|
89
|
+
raise ServerError.new(body.error.message, response.status)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# rubocop:enable Metrics/AbcSize
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module StrapiRuby
|
2
|
+
class Config
|
3
|
+
include StrapiRuby::Validations
|
4
|
+
|
5
|
+
attr_accessor :strapi_server_uri,
|
6
|
+
:strapi_token,
|
7
|
+
:faraday,
|
8
|
+
:convert_to_html,
|
9
|
+
:convert_to_datetime,
|
10
|
+
:show_endpoint
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@strapi_server_uri = nil
|
14
|
+
@strapi_token = nil
|
15
|
+
@faraday = nil
|
16
|
+
@convert_to_datetime = true
|
17
|
+
@convert_to_html = []
|
18
|
+
@show_endpoint = false
|
19
|
+
end
|
20
|
+
|
21
|
+
def call
|
22
|
+
validate_config(self)
|
23
|
+
# We convert to symbols if user passed strings for convert_to_html options
|
24
|
+
@convert_to_html.map!(&:to_sym)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module StrapiRuby
|
2
|
+
module Configuration
|
3
|
+
def config
|
4
|
+
@config ||= Config.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def configure
|
8
|
+
yield(config)
|
9
|
+
config.call
|
10
|
+
client
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def client
|
16
|
+
@client ||= Client.new(
|
17
|
+
strapi_server_uri: @config.strapi_server_uri, strapi_token: @config.strapi_token, &@config.faraday
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module StrapiRuby
|
2
|
+
module Endpoint
|
3
|
+
class Builder
|
4
|
+
def initialize(options = {})
|
5
|
+
@resource = options[:resource]
|
6
|
+
@id = options[:id]
|
7
|
+
@query = Query.new(options).call
|
8
|
+
@result = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
build_endpoint
|
13
|
+
append_query
|
14
|
+
@result
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def build_endpoint
|
20
|
+
@result = if builds_collection?
|
21
|
+
"#{base_uri}/#{@resource}/#{@id}"
|
22
|
+
else
|
23
|
+
"#{base_uri}/#{@resource}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def append_query
|
28
|
+
@result += @query if @query
|
29
|
+
end
|
30
|
+
|
31
|
+
def builds_collection?
|
32
|
+
!@id.nil?
|
33
|
+
end
|
34
|
+
|
35
|
+
def base_uri
|
36
|
+
StrapiRuby.config.strapi_server_uri
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module StrapiRuby
|
2
|
+
module Endpoint
|
3
|
+
class Query
|
4
|
+
include StrapiParameters
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
@result = ""
|
8
|
+
@options = options
|
9
|
+
parse_query_params
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
if @options[:raw]
|
14
|
+
@result = @options[:raw]
|
15
|
+
else
|
16
|
+
@result
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def parse_query_params
|
23
|
+
return if @options[:raw]
|
24
|
+
|
25
|
+
@options.each do |key, value|
|
26
|
+
send(key, value) if @options[key] && respond_to?(key, true)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require "uri"
|
2
|
+
|
3
|
+
module StrapiRuby
|
4
|
+
module Endpoint
|
5
|
+
module StrapiParameters
|
6
|
+
private
|
7
|
+
|
8
|
+
def sort(args)
|
9
|
+
build_query_from_args(args, :sort)
|
10
|
+
end
|
11
|
+
|
12
|
+
def fields(args)
|
13
|
+
build_query_from_args(args, :fields)
|
14
|
+
end
|
15
|
+
|
16
|
+
def populate(args)
|
17
|
+
build_query_from_args(args, :populate)
|
18
|
+
end
|
19
|
+
|
20
|
+
def filters(args)
|
21
|
+
build_query_from_args(args, :filters)
|
22
|
+
end
|
23
|
+
|
24
|
+
def page_size(number)
|
25
|
+
raise TypeError, "#{ErrorMessage.expected_integer} Got #{number.class.name}" unless number.is_a?(Integer)
|
26
|
+
|
27
|
+
check_single_pagination
|
28
|
+
@result += "#{prefix}pagination[pageSize]=#{number}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Sets the page number for the query result.
|
32
|
+
#
|
33
|
+
# @param number [Integer] An Integer representing the page number.
|
34
|
+
#
|
35
|
+
# @return [String] The updated query string with the page number option added.
|
36
|
+
def page(number)
|
37
|
+
raise TypeError, "#{ErrorMessage.expected_integer} Got #{number.class.name}" unless number.is_a?(Integer)
|
38
|
+
|
39
|
+
check_single_pagination
|
40
|
+
@result += "#{prefix}pagination[page]=#{number}"
|
41
|
+
end
|
42
|
+
|
43
|
+
# Sets the offset for the query result.
|
44
|
+
#
|
45
|
+
# @param number [Integer] An Integer representing the offset.
|
46
|
+
#
|
47
|
+
# @return [String] The updated query string with the offset option added.
|
48
|
+
def start(number)
|
49
|
+
raise TypeError, "#{ErrorMessage.expected_integer} Got #{number.class.name}" unless number.is_a?(Integer)
|
50
|
+
|
51
|
+
check_single_pagination
|
52
|
+
@result += "#{prefix}pagination[start]=#{number}"
|
53
|
+
end
|
54
|
+
|
55
|
+
# Sets the limit for the query result.
|
56
|
+
#
|
57
|
+
# @param number [Integer] An Integer representing the limit.
|
58
|
+
#
|
59
|
+
# @return [String] The updated query string with the limit option added.
|
60
|
+
def limit(number)
|
61
|
+
raise TypeError unless number.is_a?(Integer)
|
62
|
+
|
63
|
+
check_single_pagination
|
64
|
+
@result += "#{prefix}pagination[limit]=#{number}"
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Sets the locale for the query result.
|
69
|
+
#
|
70
|
+
# @params arg [String, Symbol] A String or Symbol representing the locale.
|
71
|
+
#
|
72
|
+
# @return [String] The updated query string with the locale option added.
|
73
|
+
def locale(arg)
|
74
|
+
raise TypeError, "#{ErrorMessage.expected_string_symbol} Got #{arg.class.name}" unless arg.is_a?(String) || arg.is_a?(Symbol)
|
75
|
+
|
76
|
+
@result += "#{prefix}locale=#{arg}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def publication_state(arg)
|
80
|
+
raise TypeError, "#{ErrorMessage.expected_string_symbol} Got #{arg.class.name}" unless arg.is_a?(String) || arg.is_a?(Symbol)
|
81
|
+
raise ArgumentError, "#{ErrorMessage.publication_state} Got #{arg}" unless arg.to_sym == :live || arg.to_sym == :preview
|
82
|
+
|
83
|
+
@result += "#{prefix}publicationState=#{arg}"
|
84
|
+
end
|
85
|
+
|
86
|
+
# Checks params don't combine pagination methods.
|
87
|
+
#
|
88
|
+
def check_single_pagination
|
89
|
+
return unless (@options.key?(:page) && @options.key?(:start)) ||
|
90
|
+
(@options.key(:page) && @options.key?(:limit)) ||
|
91
|
+
(@options.key(:pagination) && options.key?(:start)) ||
|
92
|
+
(@options.key(:pagination) && options.key?(:limit))
|
93
|
+
|
94
|
+
raise ArgumentError, ErrorMessage.pagination
|
95
|
+
end
|
96
|
+
|
97
|
+
# builds the prefix for the query string (either "?" or "&" depending on whether the query string is empty or not).
|
98
|
+
#
|
99
|
+
# @return [String] A String representing the prefix.
|
100
|
+
def prefix
|
101
|
+
@result.empty? ? "?" : "&"
|
102
|
+
end
|
103
|
+
|
104
|
+
def build_query_from_args(args, method_name)
|
105
|
+
query = prefix
|
106
|
+
hash = {}
|
107
|
+
hash[method_name] = args
|
108
|
+
query += traverse_hash(hash)
|
109
|
+
@result += query
|
110
|
+
end
|
111
|
+
|
112
|
+
def traverse_hash(hash, parent_key = nil)
|
113
|
+
hash.map do |key, value|
|
114
|
+
current_key = parent_key ? "#{parent_key}[#{key}]" : key.to_s
|
115
|
+
|
116
|
+
if value.is_a?(Hash)
|
117
|
+
traverse_hash(value, current_key)
|
118
|
+
elsif value.is_a?(Array)
|
119
|
+
value.map.with_index do |item, index|
|
120
|
+
traverse_hash({ index => item }, current_key)
|
121
|
+
end
|
122
|
+
else
|
123
|
+
# We can pass values as symbols but we need to convert them to string
|
124
|
+
# to be able to escape them
|
125
|
+
value = value.to_s if value.is_a?(Symbol)
|
126
|
+
"#{current_key}=#{CGI.escape(value)}"
|
127
|
+
end
|
128
|
+
end.join("&")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module StrapiRuby
|
2
|
+
class ClientError < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class ConnectionError < ClientError
|
6
|
+
def initialize(message)
|
7
|
+
super("There is a problem while initializing the connection with Faraday: #{message}")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class UnauthorizedError < ClientError
|
12
|
+
def initialize(message, status)
|
13
|
+
super("There is an error from the Strapi server with status #{status}: #{message}. Make sure your strapi_token is valid.")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class ForbiddenError < ClientError
|
18
|
+
def initialize(message, status)
|
19
|
+
super("There is an error from the Strapi server with status #{status}: #{message}. Make sure your strapi_token has the correct permissions or allow public access.")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class NotFoundError < ClientError
|
24
|
+
def initialize(message, status)
|
25
|
+
super("There is an error from the Strapi server with status #{status}: #{message}.")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class UnprocessableEntityError < ClientError
|
30
|
+
def initialize(message, status)
|
31
|
+
super("There is an error from the Strapi server with status #{status}: #{message}.")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class ServerError < ClientError
|
36
|
+
def initialize(message, status)
|
37
|
+
super("There is an error from the Strapi server with status #{status}: #{message}. Please try again later.")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class BadRequestError < ClientError
|
42
|
+
def initialize(message, status)
|
43
|
+
super("There is an error from the Strapi server with status #{status}: #{message}. Check parameters")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class JSONParsingError < ClientError; end
|
48
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
missing_configuration: >
|
2
|
+
StrapiRuby.configure do |config|
|
3
|
+
config.strapi_server_uri = 'https://example.com'
|
4
|
+
config.strapi_token = '123'
|
5
|
+
end
|
6
|
+
missing_ressource: >
|
7
|
+
StrapiRuby.get(resource: :restaurants)
|
8
|
+
missing_data: >
|
9
|
+
StrapiRuby.post(resource: :restaurants, data: { name: 'My restaurant' })
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module StrapiRuby
|
4
|
+
class ErrorMessage
|
5
|
+
class << self
|
6
|
+
def method_missing(method_name, *_args)
|
7
|
+
define_singleton_method(method_name) do
|
8
|
+
text = text_yaml[method_name.to_s]
|
9
|
+
code = code_yaml[method_name.to_s]
|
10
|
+
|
11
|
+
build_error_message(text, code)
|
12
|
+
end
|
13
|
+
|
14
|
+
send(method_name)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def text_yaml
|
20
|
+
load_yaml("text")
|
21
|
+
end
|
22
|
+
|
23
|
+
def code_yaml
|
24
|
+
load_yaml("code")
|
25
|
+
end
|
26
|
+
|
27
|
+
def load_yaml(filename)
|
28
|
+
path = File.join(current_directory, "error_#{filename}.yml")
|
29
|
+
YAML.load_file(path)
|
30
|
+
end
|
31
|
+
|
32
|
+
def current_directory
|
33
|
+
File.dirname(__FILE__)
|
34
|
+
end
|
35
|
+
|
36
|
+
def build_error_message(text, code = nil)
|
37
|
+
"\n\n#{text}\n\n#{code ? "Example:\n\n#{code}\n\n" : ""}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
missing_configuration: Config block missing. Configure plugin in /config/strapi_ruby.rb.
|
2
|
+
missing_ressource: Ressource is missing.
|
3
|
+
missing_data: Data key is missing from parameters. You need to pass a body to perform this HTTP request (POST, PUT).
|
4
|
+
connection_failed: Connection failed!
|
5
|
+
timeout: Timeout reached!
|
6
|
+
unexpected: An unexpected error occured.
|
7
|
+
expected_array: Invalid argument type. Expected Array.
|
8
|
+
expected_hash: Invalid argument type. Expected Hash.
|
9
|
+
expected_string_symbol: Invalid argument type. Expected String or Symbol.
|
10
|
+
expected_integer: Invalid argument type. Expected Integer.
|
11
|
+
expected_proc: Invalid argument type. Expected Proc.
|
12
|
+
publication_state: Invalid argument. Expected :live or :preview.
|
13
|
+
pagination: Use a single pagination method, either by page or by offset
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module StrapiRuby
|
2
|
+
class Formatter
|
3
|
+
def initialize(options = {})
|
4
|
+
@keys_to_convert = options[:convert_to_html] || StrapiRuby.config.convert_to_html
|
5
|
+
end
|
6
|
+
|
7
|
+
def call(data)
|
8
|
+
# Check data for emptiness
|
9
|
+
check_emptiness(data)
|
10
|
+
|
11
|
+
converted_data = data.clone
|
12
|
+
convert_to_html!(converted_data)
|
13
|
+
convert_to_datetime!(converted_data)
|
14
|
+
converted_data
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def convert_to_datetime!(data)
|
20
|
+
return unless StrapiRuby.config.convert_to_datetime
|
21
|
+
|
22
|
+
if collection?(data)
|
23
|
+
data.each { |item| parse_into_datetime!(item.attributes) }
|
24
|
+
else
|
25
|
+
parse_into_datetime!(data.attributes)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse_into_datetime!(attributes)
|
30
|
+
traverse_struct_and_change_key!(attributes, "createdAt")
|
31
|
+
traverse_struct_and_change_key!(attributes, "publishedAt")
|
32
|
+
traverse_struct_and_change_key!(attributes, "updatedAt")
|
33
|
+
end
|
34
|
+
|
35
|
+
def traverse_struct_and_change_key!(struct, key_to_check, path = [])
|
36
|
+
struct.each_pair do |key, value|
|
37
|
+
current_path = path + [key]
|
38
|
+
|
39
|
+
struct.send("#{key}=", DateTime.parse(struct.send(key_to_check.to_sym))) if key.to_s == key_to_check && struct.respond_to?(key_to_check.to_sym)
|
40
|
+
|
41
|
+
if value.is_a?(OpenStruct)
|
42
|
+
traverse_struct_and_change_key!(value, key_to_check, current_path)
|
43
|
+
elsif value.is_a?(Array)
|
44
|
+
value.each_with_index do |item, index|
|
45
|
+
traverse_struct_and_change_key!(item, key_to_check, current_path + [index]) if item.is_a?(OpenStruct)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def check_emptiness(data)
|
52
|
+
if collection?(data)
|
53
|
+
data if data.all? { |item| item.to_h.empty? }
|
54
|
+
elsif data.to_h.empty?
|
55
|
+
data
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def collection?(data)
|
60
|
+
data.is_a?(Array)
|
61
|
+
end
|
62
|
+
|
63
|
+
def convert_to_html!(data)
|
64
|
+
if collection?(data)
|
65
|
+
data.each { |item| convert_attributes!(item.attributes) }
|
66
|
+
else
|
67
|
+
convert_attributes!(data.attributes)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def convert_attributes!(attributes)
|
72
|
+
# Loop through the methods of the attributes
|
73
|
+
attributes.methods.map do |method|
|
74
|
+
# Check if the method is in the keys to convert
|
75
|
+
next unless @keys_to_convert.include?(method)
|
76
|
+
|
77
|
+
# Get the value of the method
|
78
|
+
method_value = attributes.send(method)
|
79
|
+
# Convert and set the value of the method
|
80
|
+
attributes.send("#{method}=", convert_value_to_html(method_value))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def convert_value_to_html(value)
|
85
|
+
Markdown.instance.to_html(value)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module StrapiRuby
|
2
|
+
module Interface
|
3
|
+
include StrapiRuby::Validations
|
4
|
+
|
5
|
+
def get(options = {})
|
6
|
+
request(:get, options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def post(options = {})
|
10
|
+
request(:post, options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def put(options = {})
|
14
|
+
request(:put, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def delete(options = {})
|
18
|
+
request(:delete, options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def escape_empty_answer(answer)
|
22
|
+
return answer.error.message if answer.data.nil? && answer.error
|
23
|
+
yield
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def request(http_verb, options = {})
|
29
|
+
begin
|
30
|
+
validate_options(options)
|
31
|
+
@endpoint = build_endpoint(options)
|
32
|
+
answer = build_answer(http_verb, @endpoint, options)
|
33
|
+
data = format_data(answer.data, options)
|
34
|
+
meta = answer.meta
|
35
|
+
|
36
|
+
return_success_open_struct(data, meta, options)
|
37
|
+
rescue StrapiRuby::ClientError, StrapiRuby::ConfigError => e
|
38
|
+
return_error_open_struct(e, options)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def build_answer(http_verb, endpoint, options)
|
43
|
+
if %i[get delete].include?(http_verb)
|
44
|
+
@client.public_send(http_verb, endpoint)
|
45
|
+
else
|
46
|
+
validate_data_presence(options)
|
47
|
+
body = options[:data]
|
48
|
+
@client.public_send(http_verb, endpoint, body)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def show_endpoint?(options)
|
53
|
+
options[:show_endpoint] || StrapiRuby.config.show_endpoint
|
54
|
+
end
|
55
|
+
|
56
|
+
def return_success_open_struct(data, meta, error = nil, options = {})
|
57
|
+
if show_endpoint?(options)
|
58
|
+
OpenStruct.new(data: data,
|
59
|
+
meta: meta,
|
60
|
+
endpoint: @endpoint).freeze
|
61
|
+
else
|
62
|
+
OpenStruct.new(data: data, meta: meta).freeze
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def return_error_open_struct(error, options = {})
|
67
|
+
OpenStruct.new(error: OpenStruct.new(message: "#{error.class}: #{error.message}"),
|
68
|
+
endpoint: @endpoint,
|
69
|
+
data: nil,
|
70
|
+
meta: nil).freeze
|
71
|
+
end
|
72
|
+
|
73
|
+
def build_endpoint(options)
|
74
|
+
Endpoint::Builder.new(options).call
|
75
|
+
end
|
76
|
+
|
77
|
+
def format_data(data, options = {})
|
78
|
+
Formatter.new(options).call(data)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "singleton"
|
2
|
+
require "redcarpet"
|
3
|
+
|
4
|
+
# Use with Markdown.instance.to_html
|
5
|
+
|
6
|
+
module StrapiRuby
|
7
|
+
class Markdown
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
def to_html(markdown)
|
11
|
+
markdown_renderer.render(markdown)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def markdown_renderer
|
17
|
+
@markdown_renderer ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML, { autolink: true })
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|