granite 0.8.1 → 0.8.2
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 +4 -4
- data/lib/granite.rb +1 -0
- data/lib/granite/action/performing.rb +26 -6
- data/lib/granite/action/transaction.rb +24 -28
- data/lib/granite/represents/attribute.rb +3 -1
- data/lib/granite/typecasters.rb +10 -0
- data/lib/granite/version.rb +1 -1
- metadata +7 -8
- data/lib/granite/action/exceptions_handling.rb +0 -39
- data/lib/granite/action/transaction_manager.rb +0 -86
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3792e5a0bab26cb24becc52bb82e89198a74e84f
|
4
|
+
data.tar.gz: 1c085cd86ae0ca9379cfd8d6708a24dea36a6454
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1afd8ebb16b30ac0a5142369cb7bcb5ac62ab9c1d11a2c5ec84b0a525a70b43b0181e51aed50003384baa4303c0eb466440216acf345d66a7cde594e594e6de
|
7
|
+
data.tar.gz: 8bd7ef7aff11fa0f9aaa444993c637cffe2ff7f2c8dfc1b39ec1680d5766a32f5d0bd40a3bfc6fe17f9020a08df40d1777ffff942ea6507e3ed68d40e6edbb26
|
data/lib/granite.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'granite/action/exceptions_handling'
|
2
1
|
require 'granite/action/transaction'
|
3
2
|
require 'granite/action/error'
|
4
3
|
|
@@ -18,14 +17,28 @@ module Granite
|
|
18
17
|
module Performing
|
19
18
|
extend ActiveSupport::Concern
|
20
19
|
|
21
|
-
include ExceptionsHandling
|
22
20
|
include Transaction
|
23
21
|
|
24
22
|
included do
|
23
|
+
class_attribute :_exception_handlers, instance_writer: false
|
24
|
+
self._exception_handlers = {}
|
25
|
+
|
26
|
+
protected :_exception_handlers
|
27
|
+
|
25
28
|
define_callbacks :execute_perform
|
26
29
|
end
|
27
30
|
|
28
31
|
module ClassMethods
|
32
|
+
# Register default handler for exceptions thrown inside execute_perform! method.
|
33
|
+
# @param klass Exception class, could be parent class too [Class]
|
34
|
+
# @param block [Block<Exception>] with default behavior for handling specified
|
35
|
+
# type exceptions. First block argument is raised exception instance.
|
36
|
+
#
|
37
|
+
# @return [Hash<Class, Proc>] Registered handlers
|
38
|
+
def handle_exception(klass, &block)
|
39
|
+
self._exception_handlers = _exception_handlers.merge(klass => block)
|
40
|
+
end
|
41
|
+
|
29
42
|
def perform(*)
|
30
43
|
fail 'Perform block declaration was removed! Please declare `private def execute_perform!(*)` method'
|
31
44
|
end
|
@@ -41,7 +54,7 @@ module Granite
|
|
41
54
|
# using `:on`)
|
42
55
|
# @return [Object] result of execute_perform! method execution or false in case of errors
|
43
56
|
def perform(context: nil, **options)
|
44
|
-
|
57
|
+
transactional do
|
45
58
|
valid?(context) && perform_action(options)
|
46
59
|
end
|
47
60
|
end
|
@@ -59,7 +72,7 @@ module Granite
|
|
59
72
|
# @raise [Granite::Action::ValidationError] Action or associated objects are invalid
|
60
73
|
# @raise [NotImplementedError] execute_perform! method was not defined yet
|
61
74
|
def perform!(context: nil, **options)
|
62
|
-
|
75
|
+
transactional do
|
63
76
|
validate!(context)
|
64
77
|
perform_action!(**options)
|
65
78
|
end
|
@@ -75,7 +88,7 @@ module Granite
|
|
75
88
|
# @raise [NotImplementedError] execute_perform! method was not defined yet
|
76
89
|
def try_perform!(context: nil, **options)
|
77
90
|
return unless satisfy_preconditions?
|
78
|
-
|
91
|
+
transactional do
|
79
92
|
validate!(context)
|
80
93
|
perform_action!(**options)
|
81
94
|
end
|
@@ -95,7 +108,7 @@ module Granite
|
|
95
108
|
result = run_callbacks(:execute_perform) { execute_perform!(options) }
|
96
109
|
@_action_performed = true
|
97
110
|
result || true
|
98
|
-
rescue *
|
111
|
+
rescue *_exception_handlers.keys => e
|
99
112
|
handle_exception(e)
|
100
113
|
raise_validation_error(e) if raise_errors
|
101
114
|
raise Rollback
|
@@ -108,6 +121,13 @@ module Granite
|
|
108
121
|
def execute_perform!(**_options)
|
109
122
|
fail NotImplementedError, "BA perform body MUST be defined for #{self}"
|
110
123
|
end
|
124
|
+
|
125
|
+
def handle_exception(e)
|
126
|
+
klass = e.class.ancestors.detect do |ancestor|
|
127
|
+
ancestor <= Exception && _exception_handlers[ancestor]
|
128
|
+
end
|
129
|
+
instance_exec(e, &_exception_handlers[klass]) if klass
|
130
|
+
end
|
111
131
|
end
|
112
132
|
end
|
113
133
|
end
|
@@ -1,43 +1,39 @@
|
|
1
|
-
require 'granite/action/transaction_manager'
|
2
|
-
|
3
1
|
module Granite
|
4
2
|
class Action
|
3
|
+
class Rollback < defined?(ActiveRecord) ? ActiveRecord::Rollback : StandardError
|
4
|
+
end
|
5
|
+
|
5
6
|
module Transaction
|
6
7
|
extend ActiveSupport::Concern
|
7
8
|
|
8
|
-
|
9
|
-
define_callbacks :commit
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
delegate :transaction, to: :'Granite::Action::TransactionManager'
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
# Defines a callback which will be triggered right after transaction committed
|
18
|
-
# Uses the same arguments as `ActiveSupport::Callbacks.set_callback` except for the first two
|
19
|
-
#
|
20
|
-
def after_commit(*args, &block)
|
21
|
-
set_callback :commit, :after, *args, &block
|
22
|
-
end
|
23
|
-
end
|
9
|
+
private
|
24
10
|
|
25
|
-
def
|
26
|
-
if
|
27
|
-
|
28
|
-
super event
|
29
|
-
rescue *handled_exceptions => e
|
30
|
-
handle_exception(e)
|
31
|
-
end
|
11
|
+
def transactional(&block)
|
12
|
+
if transactional?
|
13
|
+
yield
|
32
14
|
else
|
33
|
-
|
15
|
+
@_transactional = true
|
16
|
+
result = transaction(&block) || false
|
17
|
+
@_transactional = nil
|
18
|
+
result
|
34
19
|
end
|
35
20
|
end
|
36
21
|
|
37
|
-
|
22
|
+
def transactional?
|
23
|
+
# Fuck the police!
|
24
|
+
!(!@_transactional)
|
25
|
+
end
|
38
26
|
|
39
27
|
def transaction(&block)
|
40
|
-
|
28
|
+
if defined?(ActiveRecord::Base)
|
29
|
+
ActiveRecord::Base.transaction(&block)
|
30
|
+
else
|
31
|
+
begin
|
32
|
+
yield
|
33
|
+
rescue Granite::Action::Rollback
|
34
|
+
false
|
35
|
+
end
|
36
|
+
end
|
41
37
|
end
|
42
38
|
end
|
43
39
|
end
|
@@ -43,7 +43,7 @@ module Granite
|
|
43
43
|
return unless reference.respond_to?(reader)
|
44
44
|
|
45
45
|
variable_cache(:value) do
|
46
|
-
normalize(enumerize(reference.public_send(reader)))
|
46
|
+
normalize(enumerize(typecast(defaultize(reference.public_send(reader)))))
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -60,6 +60,8 @@ module Granite
|
|
60
60
|
|
61
61
|
reference_attribute = reference.attribute(name)
|
62
62
|
|
63
|
+
return nil if reference_attribute.nil?
|
64
|
+
|
63
65
|
return Granite::Action::Types::Collection.new(reference_attribute.type) if [
|
64
66
|
ActiveData::Model::Attributes::ReferenceMany,
|
65
67
|
ActiveData::Model::Attributes::Collection,
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'active_data'
|
2
|
+
|
3
|
+
ActiveData.typecaster('Granite::Action::Types::Collection') do |value, attribute|
|
4
|
+
typecaster = ActiveData.typecaster(attribute.type.subtype)
|
5
|
+
if value.respond_to? :transform_values
|
6
|
+
value.transform_values { |v| typecaster.call(v, attribute) }
|
7
|
+
elsif value.respond_to?(:map)
|
8
|
+
value.map { |v| typecaster.call(v, attribute) }
|
9
|
+
end
|
10
|
+
end
|
data/lib/granite/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: granite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arkadiy Zabazhanov & friends
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: active_data
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.1.
|
33
|
+
version: 1.1.3
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.1.
|
40
|
+
version: 1.1.3
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: activesupport
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -280,7 +280,6 @@ files:
|
|
280
280
|
- lib/granite.rb
|
281
281
|
- lib/granite/action.rb
|
282
282
|
- lib/granite/action/error.rb
|
283
|
-
- lib/granite/action/exceptions_handling.rb
|
284
283
|
- lib/granite/action/performer.rb
|
285
284
|
- lib/granite/action/performing.rb
|
286
285
|
- lib/granite/action/policies.rb
|
@@ -293,7 +292,6 @@ files:
|
|
293
292
|
- lib/granite/action/projectors.rb
|
294
293
|
- lib/granite/action/subject.rb
|
295
294
|
- lib/granite/action/transaction.rb
|
296
|
-
- lib/granite/action/transaction_manager.rb
|
297
295
|
- lib/granite/action/types.rb
|
298
296
|
- lib/granite/action/types/collection.rb
|
299
297
|
- lib/granite/base.rb
|
@@ -328,6 +326,7 @@ files:
|
|
328
326
|
- lib/granite/rspec/raise_validation_error.rb
|
329
327
|
- lib/granite/rspec/satisfy_preconditions.rb
|
330
328
|
- lib/granite/translations.rb
|
329
|
+
- lib/granite/typecasters.rb
|
331
330
|
- lib/granite/version.rb
|
332
331
|
homepage: https://github.com/toptal/granite
|
333
332
|
licenses:
|
@@ -1,39 +0,0 @@
|
|
1
|
-
module Granite
|
2
|
-
class Action
|
3
|
-
module ExceptionsHandling
|
4
|
-
extend ActiveSupport::Concern
|
5
|
-
|
6
|
-
included do
|
7
|
-
class_attribute :_exception_handlers, instance_writer: false
|
8
|
-
self._exception_handlers = {}
|
9
|
-
|
10
|
-
protected :_exception_handlers
|
11
|
-
end
|
12
|
-
|
13
|
-
module ClassMethods
|
14
|
-
# Register default handler for exceptions thrown inside execute_perform! and after_commit methods.
|
15
|
-
# @param klass Exception class, could be parent class too [Class]
|
16
|
-
# @param block [Block<Exception>] with default behavior for handling specified
|
17
|
-
# type exceptions. First block argument is raised exception instance.
|
18
|
-
#
|
19
|
-
# @return [Hash<Class, Proc>] Registered handlers
|
20
|
-
def handle_exception(klass, &block)
|
21
|
-
self._exception_handlers = _exception_handlers.merge(klass => block)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def handled_exceptions
|
28
|
-
_exception_handlers.keys
|
29
|
-
end
|
30
|
-
|
31
|
-
def handle_exception(e)
|
32
|
-
klass = e.class.ancestors.detect do |ancestor|
|
33
|
-
ancestor <= Exception && _exception_handlers[ancestor]
|
34
|
-
end
|
35
|
-
instance_exec(e, &_exception_handlers[klass]) if klass
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
module Granite
|
2
|
-
class Action
|
3
|
-
class Rollback < defined?(ActiveRecord) ? ActiveRecord::Rollback : StandardError
|
4
|
-
end
|
5
|
-
|
6
|
-
module TransactionManager
|
7
|
-
class << self
|
8
|
-
# Runs a block in a transaction
|
9
|
-
# It will open a new transaction or append a block to the current one if it exists
|
10
|
-
#
|
11
|
-
# @param [Object] trigger_callbacks_for - object which will receive `run_callbacks(:commit)` after transaction commited
|
12
|
-
# @return [Object] result of a block
|
13
|
-
def transaction(trigger_callbacks_for: nil, &block)
|
14
|
-
(callback_listeners << trigger_callbacks_for) if trigger_callbacks_for
|
15
|
-
|
16
|
-
if in_a_transaction?
|
17
|
-
yield
|
18
|
-
else
|
19
|
-
wrap_in_transaction_with_callbacks(&block)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
IN_A_TRANSACTION_KEY = :granite_transaction_manager_in_a_transaction
|
26
|
-
CALLBACK_LISTENERS_KEY = :granite_transaction_manager_callback_listeners
|
27
|
-
|
28
|
-
def callback_listeners
|
29
|
-
Thread.current[CALLBACK_LISTENERS_KEY] ||= []
|
30
|
-
end
|
31
|
-
|
32
|
-
def in_a_transaction?
|
33
|
-
!!(Thread.current[IN_A_TRANSACTION_KEY])
|
34
|
-
end
|
35
|
-
|
36
|
-
def in_a_transaction=(value)
|
37
|
-
Thread.current[IN_A_TRANSACTION_KEY] = value
|
38
|
-
end
|
39
|
-
|
40
|
-
def wrap_in_transaction_with_callbacks(&block)
|
41
|
-
self.in_a_transaction = true
|
42
|
-
|
43
|
-
result = wrap_in_transaction(&block) || false
|
44
|
-
|
45
|
-
trigger_callbacks if result
|
46
|
-
|
47
|
-
result
|
48
|
-
ensure
|
49
|
-
callback_listeners.clear
|
50
|
-
self.in_a_transaction = nil
|
51
|
-
end
|
52
|
-
|
53
|
-
def wrap_in_transaction(&block)
|
54
|
-
if defined?(ActiveRecord::Base)
|
55
|
-
ActiveRecord::Base.transaction(&block)
|
56
|
-
else
|
57
|
-
begin
|
58
|
-
yield
|
59
|
-
rescue Granite::Action::Rollback
|
60
|
-
false
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def trigger_callbacks
|
66
|
-
collected_errors = []
|
67
|
-
|
68
|
-
callback_listeners.reverse.each do |listener|
|
69
|
-
begin
|
70
|
-
listener.run_callbacks :commit
|
71
|
-
rescue StandardError => e
|
72
|
-
collected_errors << e
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
if collected_errors.any?
|
77
|
-
collected_errors[1..-1].each do |error|
|
78
|
-
ActiveData.config.logger.error "Unhandled error in callback: #{error.inspect}\n#{error.backtrace.join("\n")}"
|
79
|
-
end
|
80
|
-
fail collected_errors.first
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|