unione-ruby 0.0.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +90 -9
  3. data/Rakefile +49 -0
  4. data/config/response_schema/domain.yml +74 -0
  5. data/config/response_schema/email.yml +23 -0
  6. data/config/response_schema/event_dump.yml +75 -0
  7. data/config/response_schema/project.yml +59 -0
  8. data/config/response_schema/suppression.yml +71 -0
  9. data/config/response_schema/system.yml +33 -0
  10. data/config/response_schema/tag.yml +26 -0
  11. data/config/response_schema/template.yml +134 -0
  12. data/config/response_schema/unsubscribed.yml +45 -0
  13. data/config/response_schema/webhook.yml +141 -0
  14. data/examples/api/custom_api.rb +14 -0
  15. data/examples/api/domain.rb +14 -7
  16. data/examples/api/email/attachments.rb +28 -0
  17. data/examples/api/email/multiple_recipients.rb +24 -0
  18. data/examples/api/email/send.rb +25 -0
  19. data/examples/api/email/settings.rb +41 -0
  20. data/examples/api/email/subscribe.rb +14 -0
  21. data/examples/api/email/template.rb +26 -0
  22. data/examples/api/event_dump.rb +44 -0
  23. data/examples/api/project.rb +30 -23
  24. data/examples/api/suppression.rb +34 -0
  25. data/examples/api/system.rb +6 -6
  26. data/examples/api/tag.rb +15 -0
  27. data/examples/api/template.rb +40 -28
  28. data/examples/api/unsubscribed.rb +17 -11
  29. data/examples/api/webhook.rb +28 -25
  30. data/examples/helpers.rb +29 -0
  31. data/examples/send_mail.rb +44 -0
  32. data/examples/setup.rb +21 -14
  33. data/lib/unione/client/domain.rb +21 -45
  34. data/lib/unione/client/email.rb +16 -15
  35. data/lib/unione/client/event_dump.rb +37 -0
  36. data/lib/unione/client/project.rb +19 -61
  37. data/lib/unione/client/suppression.rb +38 -0
  38. data/lib/unione/client/system.rb +12 -17
  39. data/lib/unione/client/tag.rb +24 -0
  40. data/lib/unione/client/template.rb +19 -66
  41. data/lib/unione/client/unsubscribed.rb +18 -31
  42. data/lib/unione/client/webhook.rb +19 -65
  43. data/lib/unione/client.rb +33 -11
  44. data/lib/unione/connection.rb +7 -3
  45. data/lib/unione/helpers.rb +22 -0
  46. data/lib/unione/response/raise_error.rb +4 -5
  47. data/lib/unione/validation.rb +34 -9
  48. data/lib/unione/version.rb +1 -1
  49. data/lib/unione-ruby.rb +0 -3
  50. data/test/CONFIGFILE.yml +71 -0
  51. data/unione-ruby.gemspec +2 -2
  52. metadata +32 -10
  53. data/examples/api/email.rb +0 -51
  54. data/examples/sending_mail.rb +0 -32
  55. data/lib/unione/helpers/mail/mail.rb +0 -42
  56. data/lib/unione/helpers/template/template.rb +0 -32
  57. data/lib/unione/helpers/webhook/webhook.rb +0 -18
@@ -1,81 +1,34 @@
1
1
  module UniOne
2
2
  class Client
3
-
4
3
  module Template
4
+ extend UniOne::Validation::ClassMethods
5
+ include UniOne::Validation::InstanceMethods
5
6
 
6
- def set_template(template)
7
- post 'template/set.json', template
8
- validate_response({
9
- 'type' => 'object', 'required' => ['status', 'template'], 'properties' => {
10
- 'status' => {'type' => 'string'},
11
- 'template' => template_schema}
12
- })
13
- end
14
-
15
- def get_template(id)
16
- params = { id: id }
17
- post 'template/get.json', params
18
- validate_response({
19
- 'type' => 'object', 'required' => ['status', 'template'], 'properties' => {
20
- 'status' => {'type' => 'string'},
21
- 'template' => template_schema}
22
- })
23
- end
24
-
25
- def list_templates(limit, offset)
26
- params = { limit: limit, offset: offset }
27
- post 'template/list.json', params
28
- list_template_schema = remove_fields_from_schema(template_schema, ['from_name', 'headers'])
29
- validate_response({
30
- 'type' => 'object', 'required' => ['status', 'templates'], 'properties' => {
31
- 'status' => {'type' => 'string'},
32
- 'templates' => {'items' => list_template_schema}}
33
- })
34
- end
35
-
36
- def delete_template(id)
37
- params = { id: id }
38
- post 'template/delete.json', params
39
- validate_response({
40
- 'type' => 'object', 'required' => ['status'], 'properties' => {
41
- 'status' => {'type' => 'string'}}
42
- })
7
+ def set_template(params = {})
8
+ post('template/set.json', params)
43
9
  end
44
10
 
45
- private
46
-
47
- def template_schema
48
- {'type' => 'object', 'required' => ['id', 'name', 'editor_type', 'subject', 'from_name', 'body', 'headers', 'attachments',
49
- 'inline_attachments', 'created', 'user_id'], 'properties' => {
50
- 'id' => {'type' => 'string'},
51
- 'name' => {'type' => 'string'},
52
- 'editor_type' => {'type' => 'string'},
53
- 'subject' => {'type' => 'string'},
54
- 'from_name' => {'type' => 'string'},
55
- 'body' => template_body_schema,
56
- 'headers' => {'type' => 'object'},
57
- 'attachments' => {'items' => {'type' => 'object'}},
58
- 'inline_attachments' => {'items' => {'type' => 'object'}},
59
- 'options' => template_options_schema,
60
- 'created' => {'type' => 'string'},
61
- 'user_id' => {'type' => 'integer'},
62
- }}
11
+ def get_template(params = {})
12
+ post('template/get.json', params)
63
13
  end
64
14
 
65
- def template_body_schema
66
- {'type' => 'object', 'required' => ['html', 'plaintext', 'amp'], 'properties' => {
67
- 'html' => {'type' => 'string, null'},
68
- 'plaintext' => {'type' => 'string, null'},
69
- 'amp' => {'type' => 'string, null'}
70
- }}
15
+ def list_templates(params = {})
16
+ post('template/list.json', params)
71
17
  end
72
18
 
73
- def template_options_schema
74
- {'type' => 'object', 'required' => ['unsubscribe_url'], 'properties' => {
75
- 'unsubscribe_url' => {'type' => 'string'}
76
- }}
19
+ def delete_template(params = {})
20
+ post('template/delete.json', params)
77
21
  end
78
22
 
23
+ add_response_validations(
24
+ :template,
25
+ %w(
26
+ set_template
27
+ get_template
28
+ list_templates
29
+ delete_template
30
+ )
31
+ )
79
32
  end
80
33
  end
81
34
  end
@@ -1,44 +1,31 @@
1
1
  module UniOne
2
2
  class Client
3
-
4
3
  module Unsubscribed
4
+ extend UniOne::Validation::ClassMethods
5
+ include UniOne::Validation::InstanceMethods
5
6
 
6
- def unsubscribe(address)
7
- params = { address: address }
8
- post 'unsubscribed/set.json', params
9
- validate_response({
10
- 'type' => 'object', 'required' => ['status', 'address', 'message'], 'properties' => {
11
- 'status' => {'type' => 'string'},
12
- 'address' => {'type' => 'string'},
13
- 'message' => {'type' => 'string'}}
14
- })
7
+ def unsubscribe(params = {})
8
+ post('unsubscribed/set.json', params)
15
9
  end
16
10
 
17
- def check_unsubscribed(address)
18
- params = { address: address }
19
- post 'unsubscribed/check.json', params
20
- validate_response({
21
- 'type' => 'object', 'required' => ['status', 'address', 'is_unsubscribed'], 'properties' => {
22
- 'status' => {'type' => 'string'},
23
- 'address' => {'type' => 'string'},
24
- 'is_unsubscribed' => {'type' => 'boolean'}}
25
- })
11
+ def check_unsubscribed(params = {})
12
+ post('unsubscribed/check.json', params)
26
13
  end
27
14
 
28
- def list_unsubscribed(date_from)
29
- params = { date_from: date_from }
30
- post 'unsubscribed/list.json', params
31
- validate_response({
32
- 'type' => 'object', 'required' => ['status', 'unsubscribed'], 'properties' => {
33
- 'status' => {'type' => 'string'},
34
- 'unsubscribed' => {
35
- 'items' => {'type' => 'object'}, 'required' => ['address', 'unsubscribed_on'], 'properties' => {
36
- 'address' => {'type' => 'string'},
37
- 'unsubscribed_on' => {'type' => 'string'}
38
- }}}
39
- })
15
+ def list_unsubscribed(params = {})
16
+ params[:date_from] = handle_date_param(params[:date_from]) if params[:date_from]
17
+
18
+ post('unsubscribed/list.json', params)
40
19
  end
41
20
 
21
+ add_response_validations(
22
+ :unsubscribed,
23
+ %w(
24
+ unsubscribe
25
+ check_unsubscribed
26
+ list_unsubscribed
27
+ )
28
+ )
42
29
  end
43
30
  end
44
31
  end
@@ -1,80 +1,34 @@
1
1
  module UniOne
2
2
  class Client
3
-
4
3
  module Webhook
4
+ extend UniOne::Validation::ClassMethods
5
+ include UniOne::Validation::InstanceMethods
5
6
 
6
- def set_webhook(webhook)
7
- post 'webhook/set.json', webhook
8
- validate_response({'type' => 'object', 'required' => ['status', 'object'], 'properties' => {
9
- 'status' => {'type' => 'string'},
10
- 'object' => webhook_schema
11
- }})
7
+ def set_webhook(params = {})
8
+ post('webhook/set.json', params)
12
9
  end
13
10
 
14
- def get_webhook(url)
15
- params = { url: url }
16
- post 'webhook/get.json', params
17
- get_webhook_schema = remove_fields_from_schema(webhook_schema, ['delivery_info', 'single_event'])
18
- validate_response({'type' => 'object', 'required' => ['status', 'object'], 'properties' => {
19
- 'status' => {'type' => 'string'},
20
- 'object' => get_webhook_schema
21
- }})
11
+ def get_webhook(params = {})
12
+ post('webhook/get.json', params)
22
13
  end
23
14
 
24
- def list_webhooks(limit, offset)
25
- params = { limit: limit, offset: offset }
26
- post 'webhook/list.json', params
27
- validate_response({
28
- 'type' => 'object', 'required' => ['status', 'objects'], 'properties' => {
29
- 'status' => {'type' => 'string'},
30
- 'objects' =>
31
- {'items' =>
32
- {'type' => 'object', 'required' => ['id', 'url', 'status', 'updated_at', 'events', 'event_format', 'delivery_info', 'single_event', 'max_parallel'], 'properties' => [
33
- 'id' => {'type' => 'integer'},
34
- 'url' => {'type' => 'string'},
35
- 'status' => {'type' => 'string'},
36
- 'updated_at' => {'type' => 'string'},
37
- 'events' =>
38
- {'type' => 'object', 'required' => ['email_status', 'spam_block'], 'properties' => [
39
- 'email_status' => {'items' => {'type' => 'string'}},
40
- 'spam_block' => {'items' => {'type' => 'string'}}]},
41
- 'event_format' => {'type' => 'string'},
42
- 'delivery_info' => {'type' => 'integer'},
43
- 'single_event' => {'type' => 'integer'},
44
- 'max_parallel' => {'type' => 'integer'}
45
- ]}}}
46
- })
15
+ def list_webhooks(params = {})
16
+ post('webhook/list.json', params)
47
17
  end
48
18
 
49
- def delete_webhook(url)
50
- params = { url: url }
51
- post 'webhook/delete.json', params
52
- validate_response({'type' => 'object', 'required' => ['status'], 'properties' => {
53
- 'status' => {'type' => 'string'}
54
- }})
19
+ def delete_webhook(params = {})
20
+ post('webhook/delete.json', params)
55
21
  end
56
22
 
57
- private
58
-
59
- def webhook_schema
60
- {'type' => 'object', 'required' => ['url', 'status', 'events', 'event_format', 'delivery_info', 'single_event', 'max_parallel'], 'properties' => {
61
- 'id' => {'type' => 'integer'},
62
- 'url' => {'type' => 'string'},
63
- 'status' => {'type' => 'string'},
64
- 'event_format' => {'type' => 'string'},
65
- 'delivery_info' => {'type' => 'integer'},
66
- 'single_event' => {'type' => 'integer'},
67
- 'max_parallel' => {'type' => 'integer'},
68
- 'events' => webhook_events_schema,
69
- }}
70
- end
71
-
72
- def webhook_events_schema
73
- {'type' => 'object', 'required' => ['email_status', 'spam_block'], 'properties' => {
74
- 'email_status' => {'items' => {'type' => 'string'}},
75
- 'spam_block' => {'items' => {'type' => 'string'}}
76
- }}
77
- end
23
+ add_response_validations(
24
+ :webhook,
25
+ %w(
26
+ set_webhook
27
+ get_webhook
28
+ list_webhooks
29
+ delete_webhook
30
+ )
31
+ )
78
32
  end
79
33
  end
80
34
  end
data/lib/unione/client.rb CHANGED
@@ -1,47 +1,69 @@
1
1
  require_relative 'connection'
2
2
  require_relative 'validation'
3
+ require_relative 'helpers'
3
4
  require_relative 'client/domain'
4
5
  require_relative 'client/email'
6
+ require_relative 'client/event_dump'
5
7
  require_relative 'client/project'
8
+ require_relative 'client/suppression'
6
9
  require_relative 'client/system'
10
+ require_relative 'client/tag'
7
11
  require_relative 'client/template'
8
12
  require_relative 'client/unsubscribed'
9
13
  require_relative 'client/webhook'
10
14
 
11
15
  module UniOne
12
-
13
16
  class Client
14
-
15
17
  include UniOne::Connection
16
- include UniOne::Validation
18
+ extend UniOne::Validation::ClassMethods
19
+ include UniOne::Validation::InstanceMethods
20
+ include UniOne::Client::Helpers
17
21
  include UniOne::Client::Domain
18
22
  include UniOne::Client::Email
23
+ include UniOne::Client::EventDump
19
24
  include UniOne::Client::Project
25
+ include UniOne::Client::Suppression
20
26
  include UniOne::Client::System
27
+ include UniOne::Client::Tag
21
28
  include UniOne::Client::Template
22
29
  include UniOne::Client::Unsubscribed
23
30
  include UniOne::Client::Webhook
24
31
 
32
+ class BaseException < StandardError; end
33
+ class InvalidCallbackAuth < BaseException; end
34
+
25
35
  API_ENDPOINT =
26
- 'https://%{data_center}.unione.io/%{lang}/transactional/api/v1/'
36
+ 'https://%{hostname}/%{lang}/transactional/api/v1/'
27
37
 
28
38
  # * *Args* :
29
- # - +data_center+ -> data center: ['eu1', 'us1']
30
- # - +lang+ -> Two-letter ISO 639-1 language abbreviation, e.g. 'en'
31
- # - +api_key+ -> your UniOne API key
32
- # - +api_key_in_params+ -> boolean, pass API key inside form, otherwise pass in headers (default in headers)
39
+ # - +hostname+ -> string, API hostname, for example 'eu1.unione.io'
40
+ # - +lang+ -> string, two-letter ISO 639-1 language abbreviation, e.g. 'en'
41
+ # - +api_key+ -> string, your UniOne API key
42
+ # - +timeout+ -> integer, timeout in seconds, 5 by default
43
+ # - +api_key_in_params+ -> boolean, pass API key in parameters, otherwise pass in headers (default)
44
+ # - +enable_logging+ -> boolean, enable logging
33
45
  def initialize(params = {})
34
- @data_center = params[:data_center]
46
+ @hostname = params[:hostname]
35
47
  @lang = params[:lang]
36
48
  @api_key = params[:api_key]
37
- @api_key_in_params = !!params[:api_key_in_params]
49
+ @timeout = params[:timeout] || 5
50
+ @api_key_in_params = params[:api_key_in_params]
51
+ @enable_logging = params[:enable_logging] || ENV['ENABLE_LOGGING']
38
52
  end
39
53
 
40
54
  private
41
55
 
42
56
  def api_endpoint
43
57
  @api_endpoint ||=
44
- API_ENDPOINT % { data_center: @data_center, lang: @lang }
58
+ API_ENDPOINT % { hostname: @hostname, lang: @lang }
59
+ end
60
+
61
+ def handle_time_param(param)
62
+ param.respond_to?(:strftime) ? param.strftime('%Y-%m-%d %H:%M:%S') : param
63
+ end
64
+
65
+ def handle_date_param(param)
66
+ param.respond_to?(:strftime) ? param.strftime('%Y-%m-%d') : param
45
67
  end
46
68
  end
47
69
  end
@@ -6,14 +6,14 @@ require 'hashie'
6
6
  module UniOne
7
7
  module Connection
8
8
 
9
- def get(url, params)
9
+ def get(url, params = {})
10
10
  prepare_params!(params)
11
11
 
12
12
  # Assume HTTP library receives params as Hash
13
13
  request(:get, url, params)
14
14
  end
15
15
 
16
- def post(url, params)
16
+ def post(url, params = {})
17
17
  prepare_params!(params)
18
18
 
19
19
  # Assume HTTP library receives payload body as String
@@ -34,12 +34,16 @@ module UniOne
34
34
  @conn ||= Faraday.new(
35
35
  url: api_endpoint,
36
36
  headers: headers,
37
- request: { timeout: 30 }
37
+ request: { timeout: @timeout }
38
38
  ) do |conn|
39
39
  conn.response :mashify, content_type: /\bjson$/
40
40
  conn.response :json, content_type: /\bjson$/
41
41
  conn.response :raise_error
42
42
  conn.adapter :net_http_persistent
43
+
44
+ if @enable_logging
45
+ conn.response(:logger, nil, { headers: true, bodies: true, errors: true })
46
+ end
43
47
  end
44
48
  end
45
49
 
@@ -0,0 +1,22 @@
1
+ require 'digest'
2
+
3
+ module UniOne
4
+ class Client
5
+ module Helpers
6
+ # Helper function for webhooks callback. It is checking auth field
7
+ # and if it is invalid, raises Unione::Client::InvalidCallbackAuth exception
8
+ def verify_callback_auth!(params)
9
+ params = params.transform_keys(&:to_sym)
10
+ auth = params[:auth]
11
+ unless auth == Digest::MD5.hexdigest(params.merge(auth: @api_key).to_json)
12
+ raise InvalidCallbackAuth
13
+ end
14
+ end
15
+
16
+ def callback_helper(params)
17
+ verify_callback_auth!(params)
18
+ yield params.dig('events_by_user', 0, 'events')
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,14 +1,13 @@
1
+ # UniOne response middleware
2
+
1
3
  require 'faraday'
2
4
  require 'unione/error'
3
5
 
4
6
  module UniOne
5
- # UniOne response middleware
6
7
  module Response
7
-
8
- # This class raises an UniOne-flavored exception based
9
- # HTTP status codes returned by the API
8
+ # This class raises an UniOne-flavored exception based on HTTP
9
+ # status codes returned by the API
10
10
  class RaiseError < Faraday::Response::Middleware
11
-
12
11
  private
13
12
 
14
13
  def on_complete(response)
@@ -1,19 +1,44 @@
1
1
  require 'json-schema'
2
+ require 'yaml'
2
3
 
3
4
  module UniOne
4
5
  module Validation
6
+ module ClassMethods
7
+ def add_response_validations(klass, methods)
8
+ methods.each do |method|
9
+ orig = "#{method}_without_hook"
10
+ alias_method orig, method
5
11
 
6
- private
7
-
8
- def validate_response(schema)
9
- JSON::Validator.validate!(schema, @last_response.body)
10
- @last_response
12
+ define_method method do |*args|
13
+ send(orig, *args)
14
+ schema = get_response_schema(klass, method)
15
+ validate_response(schema)
16
+ end
17
+ end
18
+ end
11
19
  end
12
20
 
13
- def remove_fields_from_schema(schema, fields)
14
- schema.dup.tap do |s|
15
- s['required'] = s['required'].reject { |f| fields.include?(f) }
16
- s['properties'] = s['properties'].reject { |f| fields.include?(f) }
21
+ module InstanceMethods
22
+ private
23
+
24
+ def validate_response(schema)
25
+ JSON::Validator.validate!(schema, @last_response.body)
26
+ @last_response
27
+ end
28
+
29
+ def get_response_schema(klass, method)
30
+ @response_schemas ||= {}
31
+ @response_schemas[klass] ||= begin
32
+ directory = File.join(File.dirname(__FILE__), '..', '..', 'config', 'response_schema')
33
+ filename = "#{klass}.yml"
34
+ YAML.load_file(File.join(directory, filename))
35
+ end
36
+
37
+ @response_schemas[klass][method]
38
+ end
39
+
40
+ def undescore_class_name(class_name)
41
+ class_name.gsub(/([^\^])([A-Z])/,'\1_\2').downcase
17
42
  end
18
43
  end
19
44
  end
@@ -1,3 +1,3 @@
1
1
  module UniOne
2
- VERSION = '0.0.2'
2
+ VERSION = '1.0.0'
3
3
  end
data/lib/unione-ruby.rb CHANGED
@@ -1,5 +1,2 @@
1
1
  require_relative 'unione/client'
2
2
  require_relative 'unione/version'
3
- require_relative 'unione/helpers/mail/mail'
4
- require_relative 'unione/helpers/template/template'
5
- require_relative 'unione/helpers/webhook/webhook'
@@ -0,0 +1,71 @@
1
+ - method: send_email
2
+ params:
3
+ message:
4
+ recipients:
5
+ - email: test@qadns.net
6
+ substitutions:
7
+ CustomerId: 12452
8
+ to_name: John Smith
9
+ metadata:
10
+ campaign_id: c77f4f4e-3561-49f7-9f07-c35be01b4f43
11
+ customer_hash: b253ac7
12
+ tags:
13
+ - string1
14
+ skip_unsubscribe: 0
15
+ global_language: en
16
+ template_engine: simple
17
+ global_substitutions:
18
+ property1: string
19
+ property2: string
20
+ global_metadata:
21
+ property1: string
22
+ property2: string
23
+ body:
24
+ html: "<b>Hello, {{to_name}}</b>"
25
+ plaintext: Hello, {{to_name}}
26
+ amp: <!doctype html><html amp4email><head> <meta charset="utf-8"><script async
27
+ src="https://cdn.ampproject.org/v0.js"></script> <style amp4email-boilerplate>body{visibility:hidden}</style></head><body>
28
+ Hello, AMP4EMAIL world.</body></html>
29
+ subject: string
30
+ from_email: test@qadns.net
31
+ from_name: John Smith
32
+ reply_to: test@qadns.net
33
+ track_links: 0
34
+ track_read: 0
35
+ bypass_global: 0
36
+ bypass_unavailable: 0
37
+ bypass_unsubscribed: 0
38
+ bypass_complained: 0
39
+ headers:
40
+ X-MyHeader: some data
41
+ List-Unsubscribe: "<mailto: unsubscribe@example.com?subject=unsubscribe>, <http://www.example.com/unsubscribe/{{CustomerId}}>"
42
+ attachments:
43
+ - type: text/plain
44
+ name: readme.txt
45
+ content: SGVsbG8sIHdvcmxkIQ==
46
+ inline_attachments:
47
+ - type: image/gif
48
+ name: IMAGECID1
49
+ content: R0lGODdhAwADAIABAP+rAP///ywAAAAAAwADAAACBIQRBwUAOw==
50
+ options:
51
+ unsubscribe_url: https://example.org/unsubscribe/{{CustomerId}}
52
+ - method: set_webhook
53
+ params:
54
+ url: http://example.com
55
+ status: active
56
+ event_format: json_post
57
+ delivery_info: 1
58
+ single_event: 0
59
+ max_parallel: 10
60
+ events:
61
+ email_status:
62
+ - sent
63
+ - delivered
64
+ - opened
65
+ - hard_bounced
66
+ - soft_bounced
67
+ - spam
68
+ - clicked
69
+ - unsubscribed
70
+ spam_block:
71
+ - '*'
data/unione-ruby.gemspec CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.add_dependency 'json', '~> 2.0'
8
8
  spec.add_dependency 'faraday', '~> 1.0'
9
9
  spec.add_dependency 'faraday_middleware', '~> 1.0'
10
- spec.add_dependency 'net-http-persistent', '~> 3.0'
10
+ spec.add_dependency 'net-http-persistent', '~> 4.0'
11
11
  spec.add_dependency 'hashie', '~> 4.0'
12
12
  spec.add_dependency 'json-schema', '~> 2.0'
13
13
  spec.authors = ['UniOne developer']
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.licenses = ['MIT']
19
19
  spec.name = 'unione-ruby'
20
20
  spec.require_paths = ['lib']
21
- spec.required_ruby_version = '>= 2.4'
21
+ spec.required_ruby_version = '>= 2.5'
22
22
  spec.summary = 'Official UniOne Gem'
23
23
  spec.version = UniOne::VERSION
24
24
  end