granite 0.12.0 → 0.14.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 +4 -4
- data/app/controllers/granite/controller.rb +6 -5
- data/lib/granite/action/exceptions_handling.rb +1 -1
- data/lib/granite/action/instrumentation.rb +23 -0
- data/lib/granite/action/performer.rb +5 -4
- data/lib/granite/action/preconditions.rb +2 -2
- data/lib/granite/action/projectors.rb +7 -7
- data/lib/granite/action/transaction_manager.rb +4 -6
- data/lib/granite/action/translations.rb +1 -1
- data/lib/granite/action.rb +2 -0
- data/lib/granite/assign_data.rb +2 -2
- data/lib/granite/context_proxy/data.rb +20 -0
- data/lib/granite/{performer_proxy → context_proxy}/proxy.rb +9 -8
- data/lib/granite/context_proxy.rb +34 -0
- data/lib/granite/projector/controller_actions.rb +7 -7
- data/lib/granite/projector/helpers.rb +1 -2
- data/lib/granite/projector.rb +3 -3
- data/lib/granite/represents/attribute.rb +4 -4
- data/lib/granite/rspec/perform_action.rb +89 -0
- data/lib/granite/rspec/projector_helpers.rb +4 -10
- data/lib/granite/rspec/raise_validation_error.rb +6 -8
- data/lib/granite/rspec.rb +1 -0
- data/lib/granite/ruby3_compatibility.rb +15 -0
- data/lib/granite/version.rb +1 -1
- data/lib/granite.rb +1 -0
- metadata +21 -17
- data/lib/granite/performer_proxy.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0524a0055b0ea48aeab0691a1063cf332455b87094e2a78dbb6b66cc24b168e
|
4
|
+
data.tar.gz: e07a9c6a636eed28916860e213beea548aa92943da442b7d39019b346079e3fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 217ac1d410c18e838f648af770c610b24ad4a28fc70e37514060509b5ac0a9303907912da5a2e7151162df2d842c78cdf3dd4c03e64ae464427bea9707923410
|
7
|
+
data.tar.gz: 2824f499e042ce4df4565d450367ccf3c33b711586c496c752fde675c4a1bd4d2a5810b92c84916603436981ef61c100583d89865e7f5c758c5033fbc3d97e20
|
@@ -14,11 +14,12 @@ module Granite
|
|
14
14
|
before_action :authorize_action!
|
15
15
|
|
16
16
|
def projector
|
17
|
-
@projector ||=
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
@projector ||=
|
18
|
+
begin
|
19
|
+
projector_class = action_class.public_send(projector_name)
|
20
|
+
projector_class = projector_class.with(projector_context) if respond_to?(:projector_context, true)
|
21
|
+
projector_class.new(projector_params)
|
22
|
+
end
|
22
23
|
end
|
23
24
|
helper_method :projector
|
24
25
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Granite
|
2
|
+
class Action
|
3
|
+
module Instrumentation
|
4
|
+
def perform!(*, **)
|
5
|
+
instrument_perform(:perform!) { super }
|
6
|
+
end
|
7
|
+
|
8
|
+
def perform(*, **)
|
9
|
+
instrument_perform(:perform) { super }
|
10
|
+
end
|
11
|
+
|
12
|
+
def try_perform!(*, **)
|
13
|
+
instrument_perform(:try_perform!) { super }
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def instrument_perform(using, &block)
|
19
|
+
ActiveSupport::Notifications.instrument('granite.perform_action', action: self, using: using, &block)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'granite/
|
1
|
+
require 'granite/context_proxy'
|
2
2
|
|
3
3
|
module Granite
|
4
4
|
class Action
|
@@ -8,15 +8,16 @@ module Granite
|
|
8
8
|
extend ActiveSupport::Concern
|
9
9
|
|
10
10
|
included do
|
11
|
-
include
|
12
|
-
attr_reader :
|
11
|
+
include ContextProxy
|
12
|
+
attr_reader :ctx
|
13
13
|
end
|
14
14
|
|
15
15
|
def initialize(*args)
|
16
|
-
@
|
16
|
+
@ctx = self.class.proxy_context
|
17
17
|
super
|
18
18
|
end
|
19
19
|
|
20
|
+
delegate :performer, to: :ctx, allow_nil: true
|
20
21
|
delegate :id, to: :performer, prefix: true, allow_nil: true
|
21
22
|
end
|
22
23
|
end
|
@@ -98,8 +98,8 @@ module Granite
|
|
98
98
|
end
|
99
99
|
|
100
100
|
# Adds passed error message and options to `errors` object
|
101
|
-
def decline_with(*args)
|
102
|
-
errors.add(:base, *args)
|
101
|
+
def decline_with(*args, **kwargs)
|
102
|
+
errors.add(:base, *args, **kwargs)
|
103
103
|
failed_preconditions << args.first
|
104
104
|
end
|
105
105
|
|
@@ -85,13 +85,13 @@ module Granite
|
|
85
85
|
_projectors.store(name, options, &block)
|
86
86
|
|
87
87
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
88
|
-
def self.#{name}
|
89
|
-
_projectors.fetch(:#{name})
|
90
|
-
end
|
91
|
-
|
92
|
-
def #{name}
|
93
|
-
@#{name} ||= self.class._projectors.fetch(:#{name}).new(self)
|
94
|
-
end
|
88
|
+
def self.#{name} # def self.foo
|
89
|
+
_projectors.fetch(:#{name}) # _projectors.fetch(:foo)
|
90
|
+
end # end
|
91
|
+
#
|
92
|
+
def #{name} # def foo
|
93
|
+
@#{name} ||= self.class._projectors.fetch(:#{name}).new(self) # @foo ||= self.class._projectors.fetch(:foo).new(self)
|
94
|
+
end # end
|
95
95
|
METHOD
|
96
96
|
end
|
97
97
|
end
|
@@ -62,16 +62,14 @@ module Granite
|
|
62
62
|
collected_errors = []
|
63
63
|
|
64
64
|
callbacks.reverse_each do |callback|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
collected_errors << e
|
69
|
-
end
|
65
|
+
callback.respond_to?(:run_callbacks) ? callback.run_callbacks(:commit) : callback.call
|
66
|
+
rescue StandardError => e
|
67
|
+
collected_errors << e
|
70
68
|
end
|
71
69
|
|
72
70
|
return unless collected_errors.any?
|
73
71
|
|
74
|
-
log_errors(collected_errors[1
|
72
|
+
log_errors(collected_errors[1..])
|
75
73
|
fail collected_errors.first
|
76
74
|
end
|
77
75
|
|
data/lib/granite/action.rb
CHANGED
@@ -5,6 +5,7 @@ require 'active_support/callbacks'
|
|
5
5
|
|
6
6
|
require 'granite/action/types'
|
7
7
|
require 'granite/action/error'
|
8
|
+
require 'granite/action/instrumentation'
|
8
9
|
require 'granite/action/performing'
|
9
10
|
require 'granite/action/performer'
|
10
11
|
require 'granite/action/precondition'
|
@@ -48,6 +49,7 @@ module Granite
|
|
48
49
|
include Policies
|
49
50
|
include Projectors
|
50
51
|
prepend AssignAttributes
|
52
|
+
prepend Instrumentation
|
51
53
|
|
52
54
|
handle_exception ActiveRecord::RecordInvalid do |e|
|
53
55
|
merge_errors(e.record.errors)
|
data/lib/granite/assign_data.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Granite
|
2
2
|
module AssignData
|
3
|
-
DataAssignment = Struct.new(:method, :options)
|
3
|
+
DataAssignment = Struct.new(:method, :options) # rubocop:disable Lint/StructNewOverride
|
4
4
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
@@ -9,7 +9,7 @@ module Granite
|
|
9
9
|
self.data_assignments = []
|
10
10
|
|
11
11
|
alias_method :only_run_validations!, :run_validations!
|
12
|
-
protected :only_run_validations!
|
12
|
+
protected :only_run_validations!
|
13
13
|
end
|
14
14
|
|
15
15
|
module ClassMethods
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Granite
|
2
|
+
module ContextProxy
|
3
|
+
# Contains all the arbitrary data that is passed to BA with `with`
|
4
|
+
class Data
|
5
|
+
attr_reader :performer
|
6
|
+
|
7
|
+
def self.wrap(data)
|
8
|
+
if data.is_a?(self)
|
9
|
+
data
|
10
|
+
else
|
11
|
+
new(**data || {})
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(performer: nil)
|
16
|
+
@performer = performer
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,21 +1,22 @@
|
|
1
1
|
module Granite
|
2
|
-
module
|
3
|
-
# Proxy
|
4
|
-
# performer-enabled context.
|
2
|
+
module ContextProxy
|
3
|
+
# Proxy which wraps the following method calls with BA context.
|
5
4
|
#
|
6
5
|
class Proxy
|
7
|
-
|
6
|
+
extend Granite::Ruby3Compatibility
|
7
|
+
|
8
|
+
def initialize(klass, context)
|
8
9
|
@klass = klass
|
9
|
-
@
|
10
|
+
@context = context
|
10
11
|
end
|
11
12
|
|
12
13
|
def inspect
|
13
|
-
"<#{@klass}
|
14
|
+
"<#{@klass}ContextProxy #{@context}>"
|
14
15
|
end
|
15
16
|
|
16
|
-
def method_missing(method, *args, &block)
|
17
|
+
ruby2_keywords def method_missing(method, *args, &block)
|
17
18
|
if @klass.respond_to?(method)
|
18
|
-
@klass.
|
19
|
+
@klass.with_context(@context) do
|
19
20
|
@klass.public_send(method, *args, &block)
|
20
21
|
end
|
21
22
|
else
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'granite/context_proxy/data'
|
2
|
+
require 'granite/context_proxy/proxy'
|
3
|
+
|
4
|
+
module Granite
|
5
|
+
# This concern contains class methods used for actions and projectors
|
6
|
+
#
|
7
|
+
module ContextProxy
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
PROXY_CONTEXT_KEY = :granite_proxy_context
|
12
|
+
|
13
|
+
def with(data)
|
14
|
+
Proxy.new(self, Data.wrap(data))
|
15
|
+
end
|
16
|
+
|
17
|
+
def as(performer)
|
18
|
+
with(performer: performer)
|
19
|
+
end
|
20
|
+
|
21
|
+
def with_context(context)
|
22
|
+
old_context = proxy_context
|
23
|
+
Thread.current[PROXY_CONTEXT_KEY] = context
|
24
|
+
yield
|
25
|
+
ensure
|
26
|
+
Thread.current[PROXY_CONTEXT_KEY] = old_context
|
27
|
+
end
|
28
|
+
|
29
|
+
def proxy_context
|
30
|
+
Thread.current[PROXY_CONTEXT_KEY]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -22,13 +22,13 @@ module Granite
|
|
22
22
|
self.controller_actions = controller_actions.merge(name.to_sym => options)
|
23
23
|
controller_class.__send__(:define_method, name, &block)
|
24
24
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
25
|
-
def #{name}_url(options = {})
|
26
|
-
action_url(:#{name}, **options.symbolize_keys)
|
27
|
-
end
|
28
|
-
|
29
|
-
def #{name}_path(options = {})
|
30
|
-
action_path(:#{name}, **options.symbolize_keys)
|
31
|
-
end
|
25
|
+
def #{name}_url(options = {}) # def foo_url(options = {}
|
26
|
+
action_url(:#{name}, **options.symbolize_keys) # action_url(:foo, **options.symbolize_keys)
|
27
|
+
end # end
|
28
|
+
#
|
29
|
+
def #{name}_path(options = {}) # def foo_path(options = {})
|
30
|
+
action_path(:#{name}, **options.symbolize_keys) # action_path(:foo, **options.symbolize_keys)
|
31
|
+
end # end
|
32
32
|
METHOD
|
33
33
|
else
|
34
34
|
controller_actions[name.to_sym]
|
@@ -35,8 +35,7 @@ Do you have #{projector.action_class.name.underscore}##{projector.projector_name
|
|
35
35
|
|
36
36
|
def required_params
|
37
37
|
corresponding_route.required_parts
|
38
|
-
.
|
39
|
-
.to_h
|
38
|
+
.to_h { |name| [name, action.public_send(name)] }
|
40
39
|
end
|
41
40
|
|
42
41
|
def corresponding_route
|
data/lib/granite/projector.rb
CHANGED
@@ -2,11 +2,11 @@ require 'granite/projector/controller_actions'
|
|
2
2
|
require 'granite/projector/error'
|
3
3
|
require 'granite/projector/helpers'
|
4
4
|
require 'granite/projector/translations'
|
5
|
-
require 'granite/
|
5
|
+
require 'granite/context_proxy'
|
6
6
|
|
7
7
|
module Granite
|
8
8
|
class Projector
|
9
|
-
include
|
9
|
+
include ContextProxy
|
10
10
|
include ControllerActions
|
11
11
|
include Helpers
|
12
12
|
include Translations
|
@@ -42,7 +42,7 @@ module Granite
|
|
42
42
|
private
|
43
43
|
|
44
44
|
def build_action(*args)
|
45
|
-
action_class.
|
45
|
+
action_class.with(self.class.proxy_context).new(*args)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -15,7 +15,7 @@ module Granite
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def typecast(value)
|
18
|
-
return value if value.class == type
|
18
|
+
return value if value.class == type # rubocop:disable Style/ClassEqualityComparison
|
19
19
|
|
20
20
|
typecaster.call(value, self) unless value.nil?
|
21
21
|
end
|
@@ -28,9 +28,9 @@ module Granite
|
|
28
28
|
|
29
29
|
def typecaster
|
30
30
|
@typecaster ||= begin
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
type_class = type.instance_of?(Class) ? type : type.class
|
32
|
+
@typecaster = ActiveData.typecaster(type_class.ancestors.grep(Class))
|
33
|
+
end
|
34
34
|
end
|
35
35
|
|
36
36
|
def changed?
|
@@ -0,0 +1,89 @@
|
|
1
|
+
RSpec::Matchers.define :perform_action do |klass|
|
2
|
+
chain :using do |using|
|
3
|
+
@using = using
|
4
|
+
end
|
5
|
+
|
6
|
+
chain :as do |performer|
|
7
|
+
@performer = performer
|
8
|
+
end
|
9
|
+
|
10
|
+
chain :with do |attributes|
|
11
|
+
@attributes = attributes
|
12
|
+
end
|
13
|
+
|
14
|
+
match do |block|
|
15
|
+
@klass = klass
|
16
|
+
@using ||= :perform!
|
17
|
+
|
18
|
+
@payloads = []
|
19
|
+
subscriber = ActiveSupport::Notifications.subscribe('granite.perform_action') do |_, _, _, _, payload|
|
20
|
+
@payloads << payload
|
21
|
+
end
|
22
|
+
|
23
|
+
block.call
|
24
|
+
|
25
|
+
ActiveSupport::Notifications.unsubscribe(subscriber)
|
26
|
+
|
27
|
+
@payloads.detect { |payload| action_matches?(payload[:action]) && payload[:using] == @using }
|
28
|
+
end
|
29
|
+
|
30
|
+
failure_message do
|
31
|
+
output = "expected to call #{performed_entity}"
|
32
|
+
add_performer_message(output, @performer) if defined?(@performer)
|
33
|
+
add_attributes_message(output, @attributes) if defined?(@attributes)
|
34
|
+
|
35
|
+
similar_payloads = @payloads.select { |payload| class_matches?(payload[:action]) && payload[:using] == @using }
|
36
|
+
if similar_payloads.present?
|
37
|
+
output << "\nreceived calls to #{performed_entity}:"
|
38
|
+
similar_payloads.each { |payload| add_message_from_payload(output, payload) }
|
39
|
+
end
|
40
|
+
|
41
|
+
output
|
42
|
+
end
|
43
|
+
|
44
|
+
failure_message_when_negated do
|
45
|
+
"expected not to call #{performed_entity}"
|
46
|
+
end
|
47
|
+
|
48
|
+
supports_block_expectations
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def add_message_from_payload(output, payload)
|
53
|
+
action = payload[:action]
|
54
|
+
add_performer_message(output, action.performer) if defined?(@performer)
|
55
|
+
add_attributes_message(output, actual_attributes(action)) if defined?(@attributes)
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_performer_message(output, performer)
|
59
|
+
output << "\n AS #{performer.inspect}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_attributes_message(output, attributes)
|
63
|
+
output << "\n WITH #{attributes.inspect}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def performed_entity
|
67
|
+
"#{@klass}##{@using}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def actual_attributes(action)
|
71
|
+
@attributes.keys.to_h { |attr| [attr, action.public_send(attr)] }
|
72
|
+
end
|
73
|
+
|
74
|
+
def action_matches?(action)
|
75
|
+
class_matches?(action) && performer_matches?(action) && attributes_match?(action)
|
76
|
+
end
|
77
|
+
|
78
|
+
def class_matches?(action)
|
79
|
+
action.is_a?(@klass)
|
80
|
+
end
|
81
|
+
|
82
|
+
def performer_matches?(action)
|
83
|
+
!defined?(@performer) || action.performer == @performer
|
84
|
+
end
|
85
|
+
|
86
|
+
def attributes_match?(action)
|
87
|
+
!defined?(@attributes) || match(@attributes).matches?(actual_attributes(action))
|
88
|
+
end
|
89
|
+
end
|
@@ -30,16 +30,10 @@ module Granite::ProjectorHelpers
|
|
30
30
|
|
31
31
|
private
|
32
32
|
|
33
|
-
def setup_controller
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
before do
|
40
|
-
@controller = yield.controller_class.new
|
41
|
-
@controller.class.instance_variable_set(:@controller_path, yield.projector_path)
|
42
|
-
@controller.request = @request
|
33
|
+
def setup_controller(&block)
|
34
|
+
define_method :setup_controller_request_and_response do
|
35
|
+
@controller ||= instance_eval(&block).controller_class.new
|
36
|
+
super()
|
43
37
|
end
|
44
38
|
end
|
45
39
|
|
@@ -23,14 +23,12 @@ RSpec::Matchers.define :raise_validation_error do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
match do |block|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
@result = @details_being_checked&.any? { |x| x[:error] == @error_type }
|
33
|
-
end
|
26
|
+
block.call
|
27
|
+
false
|
28
|
+
rescue Granite::Action::ValidationError => e
|
29
|
+
@details = e.errors.details
|
30
|
+
@details_being_checked = @details[@attribute || :base]
|
31
|
+
@result = @details_being_checked&.any? { |x| x[:error] == @error_type }
|
34
32
|
end
|
35
33
|
|
36
34
|
description do
|
data/lib/granite/rspec.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Granite
|
2
|
+
module Ruby3Compatibility
|
3
|
+
# Method definition aimed to provide compatibility between Ruby 2.6 and 3.0
|
4
|
+
# It's being recommended in this article
|
5
|
+
# https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
#
|
9
|
+
# ruby2_keywords def a_method(argument, *args, &block)
|
10
|
+
# delegating_to_method(argument, *args, &block)
|
11
|
+
# end
|
12
|
+
def ruby2_keywords(*)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/granite/version.rb
CHANGED
data/lib/granite.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.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Toptal Engineering
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-08-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -252,42 +252,42 @@ dependencies:
|
|
252
252
|
requirements:
|
253
253
|
- - "~>"
|
254
254
|
- !ruby/object:Gem::Version
|
255
|
-
version:
|
255
|
+
version: '1.0'
|
256
256
|
type: :development
|
257
257
|
prerelease: false
|
258
258
|
version_requirements: !ruby/object:Gem::Requirement
|
259
259
|
requirements:
|
260
260
|
- - "~>"
|
261
261
|
- !ruby/object:Gem::Version
|
262
|
-
version:
|
262
|
+
version: '1.0'
|
263
263
|
- !ruby/object:Gem::Dependency
|
264
264
|
name: rubocop-rails
|
265
265
|
requirement: !ruby/object:Gem::Requirement
|
266
266
|
requirements:
|
267
267
|
- - "~>"
|
268
268
|
- !ruby/object:Gem::Version
|
269
|
-
version: 2.
|
269
|
+
version: '2.13'
|
270
270
|
type: :development
|
271
271
|
prerelease: false
|
272
272
|
version_requirements: !ruby/object:Gem::Requirement
|
273
273
|
requirements:
|
274
274
|
- - "~>"
|
275
275
|
- !ruby/object:Gem::Version
|
276
|
-
version: 2.
|
276
|
+
version: '2.13'
|
277
277
|
- !ruby/object:Gem::Dependency
|
278
278
|
name: rubocop-rspec
|
279
279
|
requirement: !ruby/object:Gem::Requirement
|
280
280
|
requirements:
|
281
281
|
- - "~>"
|
282
282
|
- !ruby/object:Gem::Version
|
283
|
-
version:
|
283
|
+
version: '2.8'
|
284
284
|
type: :development
|
285
285
|
prerelease: false
|
286
286
|
version_requirements: !ruby/object:Gem::Requirement
|
287
287
|
requirements:
|
288
288
|
- - "~>"
|
289
289
|
- !ruby/object:Gem::Version
|
290
|
-
version:
|
290
|
+
version: '2.8'
|
291
291
|
- !ruby/object:Gem::Dependency
|
292
292
|
name: simplecov
|
293
293
|
requirement: !ruby/object:Gem::Requirement
|
@@ -302,8 +302,8 @@ dependencies:
|
|
302
302
|
- - "~>"
|
303
303
|
- !ruby/object:Gem::Version
|
304
304
|
version: '0.15'
|
305
|
-
description:
|
306
|
-
email:
|
305
|
+
description:
|
306
|
+
email:
|
307
307
|
executables: []
|
308
308
|
extensions: []
|
309
309
|
extra_rdoc_files: []
|
@@ -323,6 +323,7 @@ files:
|
|
323
323
|
- lib/granite/action.rb
|
324
324
|
- lib/granite/action/error.rb
|
325
325
|
- lib/granite/action/exceptions_handling.rb
|
326
|
+
- lib/granite/action/instrumentation.rb
|
326
327
|
- lib/granite/action/performer.rb
|
327
328
|
- lib/granite/action/performing.rb
|
328
329
|
- lib/granite/action/policies.rb
|
@@ -346,10 +347,11 @@ files:
|
|
346
347
|
- lib/granite/base.rb
|
347
348
|
- lib/granite/config.rb
|
348
349
|
- lib/granite/context.rb
|
350
|
+
- lib/granite/context_proxy.rb
|
351
|
+
- lib/granite/context_proxy/data.rb
|
352
|
+
- lib/granite/context_proxy/proxy.rb
|
349
353
|
- lib/granite/dispatcher.rb
|
350
354
|
- lib/granite/error.rb
|
351
|
-
- lib/granite/performer_proxy.rb
|
352
|
-
- lib/granite/performer_proxy/proxy.rb
|
353
355
|
- lib/granite/projector.rb
|
354
356
|
- lib/granite/projector/controller_actions.rb
|
355
357
|
- lib/granite/projector/error.rb
|
@@ -369,9 +371,11 @@ files:
|
|
369
371
|
- lib/granite/rspec.rb
|
370
372
|
- lib/granite/rspec/action_helpers.rb
|
371
373
|
- lib/granite/rspec/have_projector.rb
|
374
|
+
- lib/granite/rspec/perform_action.rb
|
372
375
|
- lib/granite/rspec/projector_helpers.rb
|
373
376
|
- lib/granite/rspec/raise_validation_error.rb
|
374
377
|
- lib/granite/rspec/satisfy_preconditions.rb
|
378
|
+
- lib/granite/ruby3_compatibility.rb
|
375
379
|
- lib/granite/translations.rb
|
376
380
|
- lib/granite/typecasters.rb
|
377
381
|
- lib/granite/util.rb
|
@@ -383,7 +387,7 @@ homepage: https://github.com/toptal/granite
|
|
383
387
|
licenses:
|
384
388
|
- MIT
|
385
389
|
metadata: {}
|
386
|
-
post_install_message:
|
390
|
+
post_install_message:
|
387
391
|
rdoc_options: []
|
388
392
|
require_paths:
|
389
393
|
- lib
|
@@ -391,15 +395,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
391
395
|
requirements:
|
392
396
|
- - ">="
|
393
397
|
- !ruby/object:Gem::Version
|
394
|
-
version: '
|
398
|
+
version: '2.5'
|
395
399
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
396
400
|
requirements:
|
397
401
|
- - ">="
|
398
402
|
- !ruby/object:Gem::Version
|
399
403
|
version: '0'
|
400
404
|
requirements: []
|
401
|
-
rubygems_version: 3.
|
402
|
-
signing_key:
|
405
|
+
rubygems_version: 3.3.9
|
406
|
+
signing_key:
|
403
407
|
specification_version: 4
|
404
408
|
summary: Another business actions architecture for Rails apps
|
405
409
|
test_files: []
|
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'granite/performer_proxy/proxy'
|
2
|
-
|
3
|
-
module Granite
|
4
|
-
# This concern contains class methods used for actions and projectors
|
5
|
-
#
|
6
|
-
module PerformerProxy
|
7
|
-
extend ActiveSupport::Concern
|
8
|
-
|
9
|
-
module ClassMethods
|
10
|
-
def as(performer)
|
11
|
-
Proxy.new(self, performer)
|
12
|
-
end
|
13
|
-
|
14
|
-
def with_proxy_performer(performer)
|
15
|
-
key = proxy_performer_key
|
16
|
-
old_performer = Thread.current[key]
|
17
|
-
Thread.current[key] = performer
|
18
|
-
yield
|
19
|
-
ensure
|
20
|
-
Thread.current[key] = old_performer
|
21
|
-
end
|
22
|
-
|
23
|
-
def proxy_performer
|
24
|
-
Thread.current[proxy_performer_key]
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def proxy_performer_key
|
30
|
-
:"granite_proxy_performer_#{hash}"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|