luna_park 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.overcommit.yml +18 -0
- data/.rspec +3 -0
- data/.rubocop.yml +106 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +308 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +182 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +21 -0
- data/README.md +54 -0
- data/Rakefile +30 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/docs/.nojekyll +0 -0
- data/docs/CNAME +1 -0
- data/docs/README.md +190 -0
- data/docs/_coverpage.md +18 -0
- data/docs/_imgs/adapter.png +0 -0
- data/docs/_imgs/bender.jpeg +0 -0
- data/docs/_imgs/bender_header.jpeg +0 -0
- data/docs/_imgs/collecting.png +0 -0
- data/docs/_imgs/conductor_schema.png +0 -0
- data/docs/_imgs/ddd_header.jpeg +0 -0
- data/docs/_imgs/ddd_map.png +0 -0
- data/docs/_imgs/domain_context.jpeg +0 -0
- data/docs/_imgs/drunk_master.jpg +0 -0
- data/docs/_imgs/full_map.png +0 -0
- data/docs/_imgs/full_map_hight_res.png +0 -0
- data/docs/_imgs/graph_1.png +0 -0
- data/docs/_imgs/graph_2.jpg +0 -0
- data/docs/_imgs/graph_3.png +0 -0
- data/docs/_imgs/graph_4.jpg +0 -0
- data/docs/_imgs/graph_5.jpg +0 -0
- data/docs/_imgs/graph_5.png +0 -0
- data/docs/_imgs/processing.png +0 -0
- data/docs/_imgs/representation.png +0 -0
- data/docs/_imgs/storage.png +0 -0
- data/docs/_imgs/tourtle_context_map.png +0 -0
- data/docs/_imgs/tree.png +0 -0
- data/docs/_imgs/wm.jpeg +0 -0
- data/docs/_media/bender.jpg +0 -0
- data/docs/_media/black_cover.jpg +0 -0
- data/docs/_media/logo.svg +7 -0
- data/docs/_sidebar.md +9 -0
- data/docs/architecture.md +214 -0
- data/docs/google48f1e6f5c35eae5f.html +1 -0
- data/docs/index.html +32 -0
- data/docs/methodology.md +376 -0
- data/docs/patterns/entity.md +193 -0
- data/docs/patterns/sequence.md +332 -0
- data/docs/patterns/service.md +280 -0
- data/docs/patterns/value.md +197 -0
- data/docs/way.md +66 -0
- data/lib/luna_park.rb +72 -0
- data/lib/luna_park/callable.rb +7 -0
- data/lib/luna_park/entities/attributable.rb +18 -0
- data/lib/luna_park/entities/nested.rb +28 -0
- data/lib/luna_park/entities/simple.rb +39 -0
- data/lib/luna_park/errors.rb +16 -0
- data/lib/luna_park/errors/base.rb +244 -0
- data/lib/luna_park/errors/business.rb +9 -0
- data/lib/luna_park/errors/http.rb +90 -0
- data/lib/luna_park/errors/json_parse.rb +11 -0
- data/lib/luna_park/errors/system.rb +9 -0
- data/lib/luna_park/extensions/attributable.rb +26 -0
- data/lib/luna_park/extensions/callable.rb +44 -0
- data/lib/luna_park/extensions/comparable.rb +90 -0
- data/lib/luna_park/extensions/comparable_debug.rb +96 -0
- data/lib/luna_park/extensions/data_mapper.rb +195 -0
- data/lib/luna_park/extensions/dsl/attributes.rb +135 -0
- data/lib/luna_park/extensions/dsl/foreign_key.rb +97 -0
- data/lib/luna_park/extensions/exceptions/substitutive.rb +83 -0
- data/lib/luna_park/extensions/has_errors.rb +125 -0
- data/lib/luna_park/extensions/injector.rb +189 -0
- data/lib/luna_park/extensions/injector/dependencies.rb +74 -0
- data/lib/luna_park/extensions/predicate_attr_accessor.rb +23 -0
- data/lib/luna_park/extensions/repositories/postgres/create.rb +20 -0
- data/lib/luna_park/extensions/repositories/postgres/delete.rb +15 -0
- data/lib/luna_park/extensions/repositories/postgres/read.rb +63 -0
- data/lib/luna_park/extensions/repositories/postgres/update.rb +21 -0
- data/lib/luna_park/extensions/serializable.rb +99 -0
- data/lib/luna_park/extensions/severity_levels.rb +120 -0
- data/lib/luna_park/extensions/typed_attr_accessor.rb +26 -0
- data/lib/luna_park/extensions/validatable.rb +80 -0
- data/lib/luna_park/extensions/validatable/dry.rb +24 -0
- data/lib/luna_park/extensions/wrappable.rb +43 -0
- data/lib/luna_park/forms/simple.rb +63 -0
- data/lib/luna_park/forms/single_item.rb +74 -0
- data/lib/luna_park/handlers/simple.rb +17 -0
- data/lib/luna_park/http/client.rb +328 -0
- data/lib/luna_park/http/request.rb +225 -0
- data/lib/luna_park/http/response.rb +381 -0
- data/lib/luna_park/http/send.rb +103 -0
- data/lib/luna_park/mappers/simple.rb +92 -0
- data/lib/luna_park/notifiers/bugsnag.rb +48 -0
- data/lib/luna_park/notifiers/log.rb +174 -0
- data/lib/luna_park/notifiers/sentry.rb +50 -0
- data/lib/luna_park/repositories/postgres.rb +38 -0
- data/lib/luna_park/repositories/sequel.rb +11 -0
- data/lib/luna_park/repository.rb +9 -0
- data/lib/luna_park/serializers/simple.rb +28 -0
- data/lib/luna_park/tools.rb +19 -0
- data/lib/luna_park/use_cases/scenario.rb +325 -0
- data/lib/luna_park/use_cases/service.rb +13 -0
- data/lib/luna_park/validators/dry.rb +67 -0
- data/lib/luna_park/values/attributable.rb +21 -0
- data/lib/luna_park/values/compound.rb +26 -0
- data/lib/luna_park/values/single.rb +35 -0
- data/lib/luna_park/version.rb +5 -0
- data/luna_park.gemspec +54 -0
- data/node_modules/.yarn-integrity +12 -0
- data/package-lock.json +3 -0
- data/yarn.lock +4 -0
- metadata +414 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LunaPark
|
4
|
+
module Extensions
|
5
|
+
module TypedAttrAccessor
|
6
|
+
def typed_attr_accessor(*names, callable, is_array: false)
|
7
|
+
attr_reader(*names)
|
8
|
+
typed_attr_writer(*names, callable, is_array: is_array)
|
9
|
+
end
|
10
|
+
|
11
|
+
def typed_attr_writer(*names, callable, is_array: false)
|
12
|
+
return attr_writer(*names) if callable.nil?
|
13
|
+
|
14
|
+
names.each do |name|
|
15
|
+
setter = :"#{name}="
|
16
|
+
ivar = :"@#{name}"
|
17
|
+
if is_array
|
18
|
+
define_method(setter) { |input| instance_variable_set(ivar, input&.map { |elem| callable.call(elem) }) }
|
19
|
+
else
|
20
|
+
define_method(setter) { |input| instance_variable_set(ivar, callable.call(input)) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LunaPark
|
4
|
+
module Extensions
|
5
|
+
# @example
|
6
|
+
# class MyForm
|
7
|
+
# include LunaPark::Extensions::Validatable
|
8
|
+
#
|
9
|
+
# validator MyValidator # must respond_to #errors, #success?, #valid_params, .validate
|
10
|
+
#
|
11
|
+
# def initialize(params)
|
12
|
+
# @params = params
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# def data
|
16
|
+
# OpenStruct.new(valid_params) if valid?
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# private
|
20
|
+
#
|
21
|
+
# attr_reader :params # define abstract method
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# form = MyForm.new(foo: 'Foo')
|
25
|
+
# form.valid? # => false
|
26
|
+
# form.validation_errors # => { bar: ['is missing'] }
|
27
|
+
# form.data # => nil
|
28
|
+
#
|
29
|
+
# form = MyForm.new(foo: 'Foo', bar: 'Bar')
|
30
|
+
# form.valid? # => true
|
31
|
+
# form.data # => #<OpenStruct foo="Foo" bar="Bar" }
|
32
|
+
module Validatable
|
33
|
+
def self.included(klass)
|
34
|
+
klass.include InstanceMethods
|
35
|
+
klass.extend ClassMethods
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
39
|
+
module InstanceMethods
|
40
|
+
def validation_errors_array
|
41
|
+
validation ? validation.errors_array : {}
|
42
|
+
end
|
43
|
+
|
44
|
+
def validation_errors_tree
|
45
|
+
validation ? validation.errors_tree : []
|
46
|
+
end
|
47
|
+
|
48
|
+
def validation_errors
|
49
|
+
validation ? validation.errors : {}
|
50
|
+
end
|
51
|
+
|
52
|
+
def valid?
|
53
|
+
validation ? validation.success? : true
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def valid_params
|
59
|
+
validation ? validation.valid_params : params
|
60
|
+
end
|
61
|
+
|
62
|
+
def validation
|
63
|
+
@validation ||= self.class.validator.validate(params)
|
64
|
+
end
|
65
|
+
|
66
|
+
# :nocov:
|
67
|
+
def params
|
68
|
+
raise Errors::AbstractMethod
|
69
|
+
end
|
70
|
+
# :nocov:
|
71
|
+
end
|
72
|
+
|
73
|
+
module ClassMethods
|
74
|
+
def validator(klass = nil)
|
75
|
+
klass.nil? ? @validator : @validator = klass
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'luna_park/validators/dry'
|
4
|
+
|
5
|
+
module LunaPark
|
6
|
+
module Extensions
|
7
|
+
module Validatable
|
8
|
+
module Dry
|
9
|
+
def self.included(base)
|
10
|
+
base.include Validatable
|
11
|
+
base.extend self
|
12
|
+
end
|
13
|
+
|
14
|
+
def validator(klass = nil, &block)
|
15
|
+
return super unless block_given?
|
16
|
+
|
17
|
+
klass = Class.new(Validators::Dry)
|
18
|
+
klass.validation_schema(&block)
|
19
|
+
super(klass)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'luna_park/errors'
|
4
|
+
|
5
|
+
module LunaPark
|
6
|
+
module Extensions
|
7
|
+
##
|
8
|
+
# class-level mixin
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# class Account
|
12
|
+
# extend LunaPark::Extensions::Wrappable
|
13
|
+
#
|
14
|
+
# attr_reader :type, :id
|
15
|
+
#
|
16
|
+
# def initialize(type:, id:)
|
17
|
+
# @type, @id = type, id
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# hash = { type: 'user', id: 42 }
|
22
|
+
# acccount = Account.new(hash)
|
23
|
+
#
|
24
|
+
# Account.new(hash) # => #<Account type='user', id=42>
|
25
|
+
# Account.new(acccount) # => raise ArgumentError
|
26
|
+
# Account.wrap(hash) # => #<Account type='user', id=42>
|
27
|
+
# Account.wrap(acccount) # => #<Account type='user', id=42>
|
28
|
+
# Account.wrap(nil) # => nil
|
29
|
+
# Account.wrap(true) # => raise 'Account can not wrap TrueClass'
|
30
|
+
#
|
31
|
+
# Account.wrap(account).eql?(account) # => true
|
32
|
+
module Wrappable
|
33
|
+
def wrap(input)
|
34
|
+
case input
|
35
|
+
when self then input
|
36
|
+
when Hash then new(input)
|
37
|
+
when nil then nil
|
38
|
+
else raise Errors::Unwrapable, "#{self} can not wrap #{input.class}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'luna_park/extensions/validatable'
|
4
|
+
require 'luna_park/errors'
|
5
|
+
|
6
|
+
module LunaPark
|
7
|
+
module Forms
|
8
|
+
##
|
9
|
+
# Form object represents blank document, required to filled right, and can be performed
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# class MyForm < LunaPark::Forms::SingleItem
|
13
|
+
# validation MyValidator # respond to .validate, #valid?, #errors, #valid_params
|
14
|
+
#
|
15
|
+
# def perform(valid_params)
|
16
|
+
# "Performed #{valid_params[:foo_bar]}"
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# form = MyForm.new({ foo_bar: 'FooBar' })
|
21
|
+
#
|
22
|
+
# if form.submit
|
23
|
+
# form.result # => 'Performed FooBar'
|
24
|
+
# else
|
25
|
+
# form.errors # => { foo_bar: ['is wrong'] }
|
26
|
+
# end
|
27
|
+
class Simple
|
28
|
+
include Extensions::Validatable
|
29
|
+
|
30
|
+
attr_reader :result
|
31
|
+
|
32
|
+
def initialize(params = {})
|
33
|
+
@params = params
|
34
|
+
end
|
35
|
+
|
36
|
+
def submit
|
37
|
+
if valid?
|
38
|
+
perform!
|
39
|
+
true
|
40
|
+
else false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
alias errors validation_errors
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
attr_reader :params
|
49
|
+
|
50
|
+
def perform!
|
51
|
+
@result = perform(valid_params)
|
52
|
+
end
|
53
|
+
|
54
|
+
# :nocov:
|
55
|
+
|
56
|
+
# @abstract
|
57
|
+
def perform(_valid_params)
|
58
|
+
raise Errors::AbstractMethod
|
59
|
+
end
|
60
|
+
# :nocov:
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'luna_park/extensions/validatable'
|
4
|
+
require 'luna_park/extensions/attributable'
|
5
|
+
require 'luna_park/errors'
|
6
|
+
|
7
|
+
module LunaPark
|
8
|
+
module Forms
|
9
|
+
##
|
10
|
+
# Form object represents blank document, required to filled right, and can be performed
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# class MyForm < LunaPark::Forms::SingleItem
|
14
|
+
# validator MyValidator # respond to .validate, #valid?, #validation_errors, #valid_params
|
15
|
+
#
|
16
|
+
# def perform
|
17
|
+
# 'PerformResult'
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# def foo_bar=(foo_bar)
|
21
|
+
# @foo_bar = foo_bar
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# form = MyForm.new({ foo_bar: {} })
|
26
|
+
#
|
27
|
+
# if form.submit
|
28
|
+
# form.result # => 'PerformResult'
|
29
|
+
# else
|
30
|
+
# form.errors # => { foo_bar: ['is wrong'] }
|
31
|
+
# end
|
32
|
+
class SingleItem
|
33
|
+
include Extensions::Attributable
|
34
|
+
include Extensions::Validatable
|
35
|
+
|
36
|
+
attr_reader :result
|
37
|
+
|
38
|
+
def initialize(params = {})
|
39
|
+
@params = params
|
40
|
+
end
|
41
|
+
|
42
|
+
def submit
|
43
|
+
if valid?
|
44
|
+
fill!
|
45
|
+
perform!
|
46
|
+
true
|
47
|
+
else false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
alias errors validation_errors
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
attr_reader :params
|
56
|
+
|
57
|
+
def fill!
|
58
|
+
set_attributes valid_params
|
59
|
+
end
|
60
|
+
|
61
|
+
def perform!
|
62
|
+
@result = perform
|
63
|
+
end
|
64
|
+
|
65
|
+
# :nocov:
|
66
|
+
|
67
|
+
# @abstract
|
68
|
+
def perform
|
69
|
+
raise Errors::AbstractMethod
|
70
|
+
end
|
71
|
+
# :nocov:
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,328 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'luna_park/http/request'
|
4
|
+
require 'luna_park/http/response'
|
5
|
+
require 'luna_park/http/send'
|
6
|
+
|
7
|
+
module LunaPark
|
8
|
+
module Http
|
9
|
+
# Client are useful for organize a repository where the source of the date is the http-server,
|
10
|
+
# you should to inherit from this class. And interpret all the necessary endpoints as logical methods.
|
11
|
+
#
|
12
|
+
# <b>For example</b>:
|
13
|
+
# You have api endpoint, which get list of all users (GET http://api.example.com/users),
|
14
|
+
# as part of json api. Then you should define `Client` in your `Users` domain and
|
15
|
+
# define `all` method which get list of all users.
|
16
|
+
#
|
17
|
+
# module Users
|
18
|
+
# class Client < LunaPark::Http::Client
|
19
|
+
# def all
|
20
|
+
# response = get! json_request(
|
21
|
+
# title: 'Get users',
|
22
|
+
# url: 'http://api.example.com/users',
|
23
|
+
# )
|
24
|
+
# response.json_parse || []
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# == Handle errors in the simple way
|
30
|
+
#
|
31
|
+
# But how to handle http errors? You have two ways: simple and flexible. In first case
|
32
|
+
# you realize all request with bang-methods (get!, post!, put!, etc.). And if something
|
33
|
+
# went wrong client raise {LunaPark::Errors::Http} exception.
|
34
|
+
#
|
35
|
+
# # Server is unavailable
|
36
|
+
# client = Users::Clients.new
|
37
|
+
# client.all # => raise LunaPark::Errors::Http (Service Unavailable)
|
38
|
+
# # And your clients will see server error.
|
39
|
+
#
|
40
|
+
# == Handle errors in the flexible way
|
41
|
+
#
|
42
|
+
# But if you have different cases based on different HTTP codes, you should choose
|
43
|
+
# flexible way.
|
44
|
+
#
|
45
|
+
# <b>For example</b>:
|
46
|
+
# You develop application for a delivery service. And you should realize Orders domain.
|
47
|
+
# The Orders domain makes payment requests to the microservice responsible for transactions.
|
48
|
+
#
|
49
|
+
# Transactions microservice on payment endpoint has four uses cases, based on Http codes:
|
50
|
+
# - 201 - payment is successfully created.
|
51
|
+
# - 400 - request, has wrong structure, validation error.
|
52
|
+
# - 422 - business logic error (small balance for example).
|
53
|
+
# {"error":"Not enough funds in your account"}
|
54
|
+
# - 500 - server error
|
55
|
+
# Your transaction service client should process this code is:
|
56
|
+
# - 200 - return true
|
57
|
+
# - 422 - forward business logic error message to your customer
|
58
|
+
# - in others ways show server error to your client, and you your should notify developers about that.
|
59
|
+
#
|
60
|
+
# @example
|
61
|
+
# module Payments
|
62
|
+
# class Client < LunaPark::Http::Client
|
63
|
+
# def create(account:, money:)
|
64
|
+
# response = post json_request(
|
65
|
+
# title: 'Make payment for order',
|
66
|
+
# url: 'http://api.transactions.example.com/payments',
|
67
|
+
# data: {account: account, money: money}
|
68
|
+
# )
|
69
|
+
# case response.code
|
70
|
+
# when 200 then true
|
71
|
+
# when 422 then raise Error::Business.new(response.body.parse_json(payload_key: error), action: :catch)
|
72
|
+
# else raise Errors::Http.new(response.status, notify: true, response: response)
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
# end
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# # In your checkout scenario, payment is being made
|
79
|
+
# module Orders
|
80
|
+
# module Scenarios
|
81
|
+
# class Checkout < LunaPark::UseCases::Scenario
|
82
|
+
# def call!
|
83
|
+
# # ...
|
84
|
+
# payments.create(account: 42, money: Values::Money.new(100, :usd))
|
85
|
+
# # ...
|
86
|
+
# end
|
87
|
+
# end
|
88
|
+
# end
|
89
|
+
# end
|
90
|
+
#
|
91
|
+
# # In endpoint, if the client does not have enough money on his balance
|
92
|
+
# checkout.call
|
93
|
+
# checkout.success? # => false
|
94
|
+
# checkout.fail_message # => "Not enough funds in your account"
|
95
|
+
class Client
|
96
|
+
DEFAULT_OPEN_TIMEOUT = 60
|
97
|
+
DEFAULT_READ_TIMEOUT = 60
|
98
|
+
DEFAULT_DRIVER = LunaPark::Http::Send
|
99
|
+
DEFAULT_METHOD = :get
|
100
|
+
# Build plain request
|
101
|
+
#
|
102
|
+
# @param [String] title business description for request
|
103
|
+
# @param [String] url request url
|
104
|
+
# @param [String,Symbol] method http method (get, post, etc)
|
105
|
+
# @param [NilClass,String] body http request body
|
106
|
+
# @param [Hash] headers http headers
|
107
|
+
#
|
108
|
+
# @example
|
109
|
+
# request = form_request(
|
110
|
+
# title: 'get users list',
|
111
|
+
# url: 'http://api.example.com/users'
|
112
|
+
# )
|
113
|
+
#
|
114
|
+
# request # => <LunaPark::Http::Request @title="get users list"
|
115
|
+
# # @url="http://api.example.com/users" @method="get"
|
116
|
+
# # @headers={ 'Content-Type' => 'application/x-www-form-urlencoded' }
|
117
|
+
# # @body="" @sent_at="">
|
118
|
+
#
|
119
|
+
# @return [LunaPark::Http::Request]
|
120
|
+
# rubocop:disable Metrics/ParameterLists
|
121
|
+
def form_request(title:, url:, method: nil, body: nil, headers: nil, data: nil, **opts)
|
122
|
+
form_body = body || data # * we have no a good generator for `x-www-form-urlencoded` type, but Driver has
|
123
|
+
|
124
|
+
build_request(
|
125
|
+
title: title,
|
126
|
+
url: url,
|
127
|
+
method: method,
|
128
|
+
body: form_body,
|
129
|
+
headers: headers,
|
130
|
+
content_type: 'application/x-www-form-urlencoded',
|
131
|
+
**opts
|
132
|
+
)
|
133
|
+
end
|
134
|
+
# rubocop:enable Metrics/ParameterLists
|
135
|
+
|
136
|
+
# Build form request. Body will convert to json format automatically.
|
137
|
+
#
|
138
|
+
# @param [String] title business description for request
|
139
|
+
# @param [String] url request url
|
140
|
+
# @param [String,Symbol] method http method (get, post, etc)
|
141
|
+
# @param [NilClass,String,Hash] body http request body
|
142
|
+
# @param [Hash] headers http headers
|
143
|
+
#
|
144
|
+
# @example
|
145
|
+
# request = json_request(
|
146
|
+
# title: 'Ping pong',
|
147
|
+
# url: 'http://api.example.com/ping',
|
148
|
+
# data: { message: 'ping' }
|
149
|
+
# )
|
150
|
+
#
|
151
|
+
# request # => <LunaPark::Http::Request
|
152
|
+
# # @title="Ping pong"
|
153
|
+
# # @url="http://api.example.com/ping" @method="get"
|
154
|
+
# # @headers={ 'Content-Type' => 'application/json' }
|
155
|
+
# # @body="{"message":"ping"}" @sent_at=""
|
156
|
+
# # >
|
157
|
+
#
|
158
|
+
# @return [LunaPark::Http::Request]
|
159
|
+
# rubocop:disable Metrics/ParameterLists
|
160
|
+
def json_request(title:, url:, method: nil, body: nil, data: nil, headers: nil, **opts)
|
161
|
+
json_body = body || data && JSON.generate(data)
|
162
|
+
|
163
|
+
build_request(
|
164
|
+
title: title,
|
165
|
+
url: url,
|
166
|
+
method: method,
|
167
|
+
body: json_body,
|
168
|
+
headers: headers,
|
169
|
+
content_type: 'application/json',
|
170
|
+
**opts
|
171
|
+
)
|
172
|
+
end
|
173
|
+
# rubocop:enable Metrics/ParameterLists
|
174
|
+
|
175
|
+
# Send GET request. Always return response even if the response is not successful.
|
176
|
+
#
|
177
|
+
# @example success response
|
178
|
+
# get json_request(title: 'Hi world', url: 'http://example.com/hi')
|
179
|
+
# # => <LunaPark::Http::Response @code=200
|
180
|
+
# # @body="{"version":1,"data":"Hello World!"}" @headers={:content_type=>"application/json",
|
181
|
+
# # :connection=>"close", :server=>"thin"} @cookies={}>
|
182
|
+
#
|
183
|
+
# @example server is unavailable
|
184
|
+
# get json_request(title: 'Hi world', url: 'http://example.com/hi')
|
185
|
+
# # => <LunaPark::Http::Response @code=503
|
186
|
+
# # @body="" @headers={} @cookies={}>
|
187
|
+
#
|
188
|
+
# @return [LunaPark::Http::Response]
|
189
|
+
def get(request)
|
190
|
+
request.method = :get
|
191
|
+
request.call
|
192
|
+
end
|
193
|
+
|
194
|
+
# Send POST request. Always return response even if the response is not successful.
|
195
|
+
# @see #get
|
196
|
+
def post(request)
|
197
|
+
request.method = :post
|
198
|
+
request.call
|
199
|
+
end
|
200
|
+
|
201
|
+
# Send PUT request. Always return response even if the response is not successful.
|
202
|
+
# @see #get
|
203
|
+
def put(request)
|
204
|
+
request.method = :put
|
205
|
+
request.call
|
206
|
+
end
|
207
|
+
|
208
|
+
# Send PATCH request. Always return response even if the response is not successful.
|
209
|
+
# @see #get
|
210
|
+
def patch(request)
|
211
|
+
request.method = :patch
|
212
|
+
request.call
|
213
|
+
end
|
214
|
+
|
215
|
+
# Send DELETE request. Always return response even if the response is not successful.
|
216
|
+
# @see #get
|
217
|
+
def delete(request)
|
218
|
+
request.method = :delete
|
219
|
+
request.call
|
220
|
+
end
|
221
|
+
|
222
|
+
# Send GET request. Raise {LunaPark::Errors::Http} on bad response.
|
223
|
+
#
|
224
|
+
# @example success response
|
225
|
+
# get json_request(title: 'Hi world', url: 'http://example.com/hi')
|
226
|
+
# # => <LunaPark::Http::Response @code=200
|
227
|
+
# # @body="{"version":1,"data":"Hello World!"}" @headers={:content_type=>"application/json",
|
228
|
+
# # :connection=>"close", :server=>"thin"} @cookies={}>
|
229
|
+
#
|
230
|
+
# @example server is unavailable
|
231
|
+
# get json_request(title: 'Hi world', url: 'http://example.com/hi')
|
232
|
+
# # => raise LunaPark::Errors::Http
|
233
|
+
#
|
234
|
+
# @raise [LunaPark::Errors::Http] on bad response, timeout or server is unavailable
|
235
|
+
# @return [LunaPark::Http::Response]
|
236
|
+
def get!(request)
|
237
|
+
request.method = :get
|
238
|
+
request.call!
|
239
|
+
end
|
240
|
+
|
241
|
+
# Send POST request. Raise {LunaPark::Errors::Http} on bad response.
|
242
|
+
# @see #get!
|
243
|
+
def post!(request)
|
244
|
+
request.method = :post
|
245
|
+
request.call!
|
246
|
+
end
|
247
|
+
|
248
|
+
# Send PUT request. Raise {LunaPark::Errors::Http} on bad response.
|
249
|
+
# @see #get!
|
250
|
+
def put!(request)
|
251
|
+
request.method = :put
|
252
|
+
request.call!
|
253
|
+
end
|
254
|
+
|
255
|
+
# Send PATCh request. Raise {LunaPark::Errors::Http} on bad response.
|
256
|
+
# @see #get!
|
257
|
+
def patch!(request)
|
258
|
+
request.method = :patch
|
259
|
+
request.call!
|
260
|
+
end
|
261
|
+
|
262
|
+
# Send DELETE request. Raise {LunaPark::Errors::Http} on bad response.
|
263
|
+
# @see #get!
|
264
|
+
def delete!(request)
|
265
|
+
request.method = :delete
|
266
|
+
request.call!
|
267
|
+
end
|
268
|
+
|
269
|
+
private
|
270
|
+
|
271
|
+
def build_request(title:, url:, method: nil, body: nil, headers: nil, content_type: nil, open_timeout: nil, read_timeout: nil, driver: nil) # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
|
272
|
+
headers ||= {}
|
273
|
+
headers['Content-Type'] = content_type || 'text/plain'
|
274
|
+
|
275
|
+
# rubocop:disable Layout/HashAlignment
|
276
|
+
Request.new(
|
277
|
+
title: title,
|
278
|
+
url: url.to_s, # TODO: Use {LunaPark::Tools::URI} with @query
|
279
|
+
method: method || DEFAULT_METHOD,
|
280
|
+
body: body,
|
281
|
+
headers: headers,
|
282
|
+
open_timeout: open_timeout || self.class.open_timeout,
|
283
|
+
read_timeout: read_timeout || self.class.read_timeout,
|
284
|
+
driver: driver || self.class.driver
|
285
|
+
)
|
286
|
+
# rubocop:enable Layout/HashAlignment
|
287
|
+
end
|
288
|
+
|
289
|
+
class << self
|
290
|
+
# Set default diver for this Client
|
291
|
+
#
|
292
|
+
# @example set driver
|
293
|
+
# class Users < Client
|
294
|
+
# driver URI::Send
|
295
|
+
# end
|
296
|
+
#
|
297
|
+
# Foobar.driver # => URI::Send
|
298
|
+
def driver(driver = nil)
|
299
|
+
driver.nil? ? @driver || DEFAULT_DRIVER : @driver = driver
|
300
|
+
end
|
301
|
+
|
302
|
+
# Set default open_timeout for this Client
|
303
|
+
#
|
304
|
+
# @example set open_timeout
|
305
|
+
# class Users < Client
|
306
|
+
# open_timeout URI::Send
|
307
|
+
# end
|
308
|
+
#
|
309
|
+
# Foobar.open_timeout # => URI::Send
|
310
|
+
def open_timeout(timeout = nil)
|
311
|
+
timeout.nil? ? @open_timeout || DEFAULT_OPEN_TIMEOUT : @open_timeout = timeout
|
312
|
+
end
|
313
|
+
|
314
|
+
# Set default read_timeout for this Client
|
315
|
+
#
|
316
|
+
# @example set read_timeout
|
317
|
+
# class Users < Client
|
318
|
+
# read_timeout URI::Send
|
319
|
+
# end
|
320
|
+
#
|
321
|
+
# Foobar.read_timeout # => URI::Send
|
322
|
+
def read_timeout(timeout = nil)
|
323
|
+
timeout.nil? ? @read_timeout || DEFAULT_READ_TIMEOUT : @read_timeout = timeout
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|