granite 0.17.1 → 0.17.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/granite/controller/translations.rb +1 -1
- data/app/controllers/granite/controller.rb +1 -1
- data/lib/generators/granite/install_controller_generator.rb +1 -1
- data/lib/generators/granite_generator.rb +5 -2
- data/lib/granite/action/error.rb +1 -1
- data/lib/granite/action/exceptions_handling.rb +5 -5
- data/lib/granite/action/instrumentation.rb +1 -1
- data/lib/granite/action/performing.rb +7 -4
- data/lib/granite/action/policies.rb +3 -3
- data/lib/granite/action/precondition.rb +2 -2
- data/lib/granite/action/preconditions/base_precondition.rb +1 -1
- data/lib/granite/action/preconditions/object_precondition.rb +1 -1
- data/lib/granite/action/preconditions.rb +3 -3
- data/lib/granite/action/projectors.rb +4 -6
- data/lib/granite/action/subject.rb +5 -5
- data/lib/granite/action/transaction.rb +1 -1
- data/lib/granite/action/transaction_manager/transactions_stack.rb +2 -3
- data/lib/granite/action/transaction_manager.rb +5 -4
- data/lib/granite/action/translations.rb +2 -2
- data/lib/granite/action.rb +7 -4
- data/lib/granite/assign_data.rb +2 -2
- data/lib/granite/config.rb +1 -1
- data/lib/granite/context.rb +1 -1
- data/lib/granite/context_proxy.rb +1 -1
- data/lib/granite/dispatcher.rb +49 -46
- data/lib/granite/projector/controller_actions.rb +3 -3
- data/lib/granite/projector/error.rb +1 -1
- data/lib/granite/projector/helpers.rb +4 -4
- data/lib/granite/projector/translations.rb +1 -1
- data/lib/granite/projector.rb +1 -1
- data/lib/granite/routing/cache.rb +1 -1
- data/lib/granite/routing/caching.rb +1 -1
- data/lib/granite/routing/declarer.rb +1 -1
- data/lib/granite/routing/mapper.rb +1 -1
- data/lib/granite/routing/mapping.rb +1 -1
- data/lib/granite/routing/route.rb +1 -1
- data/lib/granite/rspec/action_helpers.rb +8 -4
- data/lib/granite/rspec/perform_action.rb +1 -1
- data/lib/granite/rspec/projector_helpers.rb +43 -38
- data/lib/granite/rspec/raise_validation_error.rb +2 -6
- data/lib/granite/rspec/satisfy_preconditions.rb +6 -6
- data/lib/granite/translations.rb +1 -1
- data/lib/granite/version.rb +1 -1
- data/lib/granite.rb +5 -1
- data/lib/rubocop/granite/inject.rb +1 -3
- data/lib/rubocop/granite.rb +1 -1
- data/lib/rubocop-granite.rb +0 -2
- metadata +30 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3e1ba1452b79b7af5130326fb9fd4b11399bf8c23d2bdcbb3cf7a3d54a81c6f
|
4
|
+
data.tar.gz: dbc6e24fa6d5e22710bed7a24f0ff9bde67d91bc6672bb0af89477601ec1b199
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cfff687bb585d2ddff0fc504e08a849e3f148c13cfb9bb6d48a016dca0a83a57008cdce581753ccacb18005a5c9cac46ad49ebcacc3e615f14c9a7af4fc7aa90
|
7
|
+
data.tar.gz: 77fa6fd1b0c27b045cca42ec681ae51e3042fa89c45c602bdd509f78126920da694d85582089805cf753ce9792aef21177ee9cfe745e268bd36e6be62b0094b5
|
@@ -2,7 +2,7 @@ require 'rails/generators/base'
|
|
2
2
|
|
3
3
|
module Granite
|
4
4
|
module Generators
|
5
|
-
class InstallControllerGenerator < Rails::Generators::Base
|
5
|
+
class InstallControllerGenerator < Rails::Generators::Base # :nodoc:
|
6
6
|
source_root File.expand_path('../../..', __dir__)
|
7
7
|
|
8
8
|
desc 'Creates a Granite::Controller for further customization'
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class GraniteGenerator < Rails::Generators::NamedBase
|
1
|
+
class GraniteGenerator < Rails::Generators::NamedBase # :nodoc:
|
2
2
|
source_root File.expand_path('templates', __dir__)
|
3
3
|
|
4
4
|
argument :projector, type: :string, required: false
|
@@ -6,7 +6,10 @@ class GraniteGenerator < Rails::Generators::NamedBase
|
|
6
6
|
|
7
7
|
def create_action
|
8
8
|
template 'granite_action.rb.erb', "apq/actions/#{file_path}.rb"
|
9
|
-
|
9
|
+
unless options.collection?
|
10
|
+
template 'granite_business_action.rb.erb',
|
11
|
+
"apq/actions/#{class_path.join('/')}/business_action.rb"
|
12
|
+
end
|
10
13
|
template 'granite_base_action.rb.erb', 'apq/actions/base_action.rb', skip: true
|
11
14
|
template 'granite_action_spec.rb.erb', "spec/apq/actions/#{file_path}_spec.rb"
|
12
15
|
empty_directory "apq/actions/#{file_path}/#{projector}" if projector
|
data/lib/granite/action/error.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Granite
|
2
2
|
class Action
|
3
|
-
module ExceptionsHandling
|
3
|
+
module ExceptionsHandling # :nodoc:
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
@@ -10,7 +10,7 @@ module Granite
|
|
10
10
|
protected :_exception_handlers
|
11
11
|
end
|
12
12
|
|
13
|
-
module ClassMethods
|
13
|
+
module ClassMethods # :nodoc:
|
14
14
|
# Register default handler for exceptions thrown inside execute_perform! and after_commit methods.
|
15
15
|
# @param klass Exception class, could be parent class too [Class]
|
16
16
|
# @param block [Block<Exception>] with default behavior for handling specified
|
@@ -28,11 +28,11 @@ module Granite
|
|
28
28
|
_exception_handlers.keys
|
29
29
|
end
|
30
30
|
|
31
|
-
def handle_exception(
|
32
|
-
klass =
|
31
|
+
def handle_exception(exception)
|
32
|
+
klass = exception.class.ancestors.detect do |ancestor|
|
33
33
|
ancestor <= Exception && _exception_handlers[ancestor]
|
34
34
|
end
|
35
|
-
instance_exec(
|
35
|
+
instance_exec(exception, &_exception_handlers[klass]) if klass
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -25,9 +25,9 @@ module Granite
|
|
25
25
|
define_callbacks :execute_perform
|
26
26
|
end
|
27
27
|
|
28
|
-
module ClassMethods
|
28
|
+
module ClassMethods # :nodoc:
|
29
29
|
def perform(*)
|
30
|
-
|
30
|
+
raise 'Perform block declaration was removed! Please declare `private def execute_perform!(*)` method'
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -36,13 +36,16 @@ module Granite
|
|
36
36
|
# database transaction. Returns the result of execute_perform! method execution
|
37
37
|
# or true if method execution returned false or nil
|
38
38
|
#
|
39
|
+
# @deprecated Use {#perform!} or {#try_perform!} instead
|
39
40
|
# @param context [Symbol] can be optionally provided to define which
|
40
41
|
# validations to test against (the context is defined on validations
|
41
42
|
# using `:on`)
|
42
43
|
# @return [Object] result of execute_perform! method execution or false in case of errors
|
43
44
|
def perform(context: nil, **options)
|
45
|
+
Granite.deprecator.warn('Granite::Action#perform is deprecated, use #perform! or #try_perform! instead')
|
46
|
+
|
44
47
|
transaction do
|
45
|
-
|
48
|
+
raise Rollback unless valid?(context)
|
46
49
|
|
47
50
|
perform_action(**options)
|
48
51
|
end
|
@@ -110,7 +113,7 @@ module Granite
|
|
110
113
|
end
|
111
114
|
|
112
115
|
def execute_perform!(**_options)
|
113
|
-
|
116
|
+
raise NotImplementedError, "BA perform body MUST be defined for #{self}"
|
114
117
|
end
|
115
118
|
end
|
116
119
|
end
|
@@ -5,7 +5,7 @@ require 'granite/action/policies/required_performer_strategy'
|
|
5
5
|
|
6
6
|
module Granite
|
7
7
|
class Action
|
8
|
-
class NotAllowedError < Error
|
8
|
+
class NotAllowedError < Error # :nodoc:
|
9
9
|
def initialize(action)
|
10
10
|
performer_id = "##{action.performer.id}" if action.performer.respond_to?(:id) && action.performer.id.present?
|
11
11
|
|
@@ -30,7 +30,7 @@ module Granite
|
|
30
30
|
self._policies_strategy = AnyStrategy
|
31
31
|
end
|
32
32
|
|
33
|
-
module ClassMethods
|
33
|
+
module ClassMethods # :nodoc:
|
34
34
|
# The simplies policy. Takes block and executes it returning
|
35
35
|
# boolean result. Multiple policies are reduced with ||
|
36
36
|
#
|
@@ -80,7 +80,7 @@ module Granite
|
|
80
80
|
# Raises Granite::Action::NotAllowedError if action is not allowed
|
81
81
|
#
|
82
82
|
def authorize!
|
83
|
-
|
83
|
+
raise Granite::Action::NotAllowedError, self unless allowed?
|
84
84
|
|
85
85
|
self
|
86
86
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Granite
|
2
2
|
class Action
|
3
|
-
class Precondition < BasicObject
|
3
|
+
class Precondition < BasicObject # :nodoc:
|
4
4
|
UNDEFINED = ::Object.new.freeze
|
5
5
|
|
6
6
|
def self.description(text = UNDEFINED)
|
@@ -17,7 +17,7 @@ module Granite
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def call(*)
|
20
|
-
|
20
|
+
raise NotImplementedError, "#call method must be implemented for #{self.class}"
|
21
21
|
end
|
22
22
|
|
23
23
|
def method_missing(method_name, *args, &blk)
|
@@ -13,7 +13,7 @@ module Granite
|
|
13
13
|
module Preconditions
|
14
14
|
extend ActiveSupport::Concern
|
15
15
|
|
16
|
-
class PreconditionsCollection
|
16
|
+
class PreconditionsCollection # :nodoc:
|
17
17
|
include Enumerable
|
18
18
|
|
19
19
|
delegate :each, to: :@preconditions
|
@@ -36,7 +36,7 @@ module Granite
|
|
36
36
|
self._preconditions = PreconditionsCollection.new
|
37
37
|
end
|
38
38
|
|
39
|
-
module ClassMethods
|
39
|
+
module ClassMethods # :nodoc:
|
40
40
|
# Define preconditions for current action.
|
41
41
|
#
|
42
42
|
# @param options [Hash] hash with
|
@@ -61,7 +61,7 @@ module Granite
|
|
61
61
|
key = key.to_s.camelize
|
62
62
|
Granite.precondition_namespaces.reduce(nil) do |memo, ns|
|
63
63
|
memo || "#{ns.to_s.camelize}::#{key}Precondition".safe_constantize
|
64
|
-
end ||
|
64
|
+
end || raise(NameError, "No precondition class for #{key}Precondition")
|
65
65
|
end
|
66
66
|
|
67
67
|
def add_preconditions_hash(*args, **options)
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module Granite
|
2
2
|
class Action
|
3
|
-
module Projectors
|
3
|
+
module Projectors # :nodoc:
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
class ProjectorsCollection
|
6
|
+
class ProjectorsCollection # :nodoc:
|
7
7
|
def initialize(action_class)
|
8
8
|
@action_class = action_class
|
9
9
|
@storage = {}
|
@@ -40,9 +40,7 @@ module Granite
|
|
40
40
|
redefine_const(projector_name, projector)
|
41
41
|
redefine_const(controller_name, projector.controller_class)
|
42
42
|
|
43
|
-
blocks.each
|
44
|
-
projector.class_eval(&block)
|
45
|
-
end
|
43
|
+
blocks.each { |block| projector.class_eval(&block) }
|
46
44
|
|
47
45
|
projector
|
48
46
|
end
|
@@ -72,7 +70,7 @@ module Granite
|
|
72
70
|
end
|
73
71
|
end
|
74
72
|
|
75
|
-
module ClassMethods
|
73
|
+
module ClassMethods # :nodoc:
|
76
74
|
def _projectors
|
77
75
|
@_projectors ||= ProjectorsCollection.new(self)
|
78
76
|
end
|
@@ -1,25 +1,25 @@
|
|
1
1
|
module Granite
|
2
2
|
class Action
|
3
|
-
class SubjectNotFoundError < ArgumentError
|
3
|
+
class SubjectNotFoundError < ArgumentError # :nodoc:
|
4
4
|
def initialize(action_class)
|
5
5
|
super("Unable to initialize #{action_class} without subject provided")
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
-
class SubjectTypeMismatchError < ArgumentError
|
9
|
+
class SubjectTypeMismatchError < ArgumentError # :nodoc:
|
10
10
|
def initialize(action_class, candidate, expected)
|
11
11
|
super("Unable to initialize #{action_class} with #{candidate} as subject, expecting instance of #{expected}")
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
module Subject
|
15
|
+
module Subject # :nodoc:
|
16
16
|
extend ActiveSupport::Concern
|
17
17
|
|
18
18
|
included do
|
19
19
|
class_attribute :_subject
|
20
20
|
end
|
21
21
|
|
22
|
-
module ClassMethods
|
22
|
+
module ClassMethods # :nodoc:
|
23
23
|
def subject(name, *args, &block)
|
24
24
|
reflection = reflect_on_association(name)
|
25
25
|
reflection ||= references_one name, *args, &block
|
@@ -65,7 +65,7 @@ module Granite
|
|
65
65
|
assign_attributes(attributes)
|
66
66
|
|
67
67
|
self.subject = args.first unless args.empty?
|
68
|
-
|
68
|
+
raise SubjectNotFoundError, self.class unless subject
|
69
69
|
rescue Granite::Form::AssociationTypeMismatch
|
70
70
|
raise SubjectTypeMismatchError.new(self.class, args.first.class.name, reflection.klass)
|
71
71
|
end
|
@@ -21,7 +21,7 @@ module Granite
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def add_callback(callback)
|
24
|
-
|
24
|
+
raise 'Start a transaction before you add callbacks on it' if depth.zero?
|
25
25
|
|
26
26
|
@callbacks.last << callback
|
27
27
|
end
|
@@ -46,7 +46,7 @@ module Granite
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def finish_current(result)
|
49
|
-
|
49
|
+
raise ArgumentError, 'No current transaction' if @depth.zero?
|
50
50
|
|
51
51
|
@depth -= 1
|
52
52
|
|
@@ -58,7 +58,6 @@ module Granite
|
|
58
58
|
@callbacks.pop
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
62
61
|
end
|
63
62
|
end
|
64
63
|
end
|
@@ -5,7 +5,7 @@ module Granite
|
|
5
5
|
class Rollback < defined?(ActiveRecord) ? ActiveRecord::Rollback : StandardError
|
6
6
|
end
|
7
7
|
|
8
|
-
module TransactionManager
|
8
|
+
module TransactionManager # :nodoc:
|
9
9
|
class << self
|
10
10
|
# Runs a block in a transaction
|
11
11
|
# It will open a new transaction or append a block to the current one if it exists
|
@@ -23,7 +23,7 @@ module Granite
|
|
23
23
|
def after_commit(listener = nil, &block)
|
24
24
|
callback = listener || block
|
25
25
|
|
26
|
-
|
26
|
+
raise 'Block or object is required to register after_commit hook!' unless callback
|
27
27
|
|
28
28
|
transactions_stack.add_callback callback
|
29
29
|
end
|
@@ -70,12 +70,13 @@ module Granite
|
|
70
70
|
return unless collected_errors.any?
|
71
71
|
|
72
72
|
log_errors(collected_errors[1..])
|
73
|
-
|
73
|
+
raise collected_errors.first
|
74
74
|
end
|
75
75
|
|
76
76
|
def log_errors(errors)
|
77
77
|
errors.each do |error|
|
78
|
-
|
78
|
+
message = "Unhandled error in after_commit callback: #{error.inspect}\n#{error.backtrace.join("\n")}"
|
79
|
+
Granite::Form.config.logger.error message
|
79
80
|
end
|
80
81
|
end
|
81
82
|
end
|
data/lib/granite/action.rb
CHANGED
@@ -15,13 +15,16 @@ require 'granite/action/subject'
|
|
15
15
|
require 'granite/action/translations'
|
16
16
|
|
17
17
|
module Granite
|
18
|
-
class Action
|
19
|
-
class ValidationError < Error
|
18
|
+
class Action # :nodoc:
|
19
|
+
class ValidationError < Error # :nodoc:
|
20
20
|
delegate :errors, to: :action
|
21
21
|
|
22
22
|
def initialize(action)
|
23
23
|
errors = action.errors.full_messages.join(', ')
|
24
|
-
super(I18n.t(:"#{action.class.i18n_scope}.errors.messages.action_invalid",
|
24
|
+
super(I18n.t(:"#{action.class.i18n_scope}.errors.messages.action_invalid",
|
25
|
+
action: action.class,
|
26
|
+
errors: errors,
|
27
|
+
default: :'errors.messages.action_invalid'), action)
|
25
28
|
end
|
26
29
|
end
|
27
30
|
|
@@ -102,7 +105,7 @@ module Granite
|
|
102
105
|
protected
|
103
106
|
|
104
107
|
def raise_validation_error(original_error = nil)
|
105
|
-
|
108
|
+
raise ValidationError, self, original_error&.backtrace
|
106
109
|
end
|
107
110
|
end
|
108
111
|
end
|
data/lib/granite/assign_data.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Granite
|
2
|
-
module AssignData
|
2
|
+
module AssignData # :nodoc:
|
3
3
|
DataAssignment = Struct.new(:method, :options) # rubocop:disable Lint/StructNewOverride
|
4
4
|
|
5
5
|
extend ActiveSupport::Concern
|
@@ -14,7 +14,7 @@ module Granite
|
|
14
14
|
assign_data :sync_attributes
|
15
15
|
end
|
16
16
|
|
17
|
-
module ClassMethods
|
17
|
+
module ClassMethods # :nodoc:
|
18
18
|
# Defines a callback to call when assigning data from business action to model.
|
19
19
|
# @param methods [Array<Symbol>] list of methods to call
|
20
20
|
# @param block [Proc] a block to call
|
data/lib/granite/config.rb
CHANGED
data/lib/granite/context.rb
CHANGED
data/lib/granite/dispatcher.rb
CHANGED
@@ -1,64 +1,67 @@
|
|
1
1
|
require 'memoist'
|
2
2
|
require 'action_controller/metal/exceptions'
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
module Granite
|
5
|
+
class Dispatcher # :nodoc:
|
6
|
+
extend Memoist
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
# Make dispatcher object pristine, clean memoist cache.
|
9
|
+
def reset!
|
10
|
+
unmemoize_all
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
def call(*)
|
14
|
+
# Pretend to be a Rack app, however we are still dispatcher, so this method should never be called
|
15
|
+
# see lib/granite/routing/mapping.rb for more info.
|
16
|
+
raise 'Dispatcher can\'t be used as a Rack app.'
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
def serve(req)
|
20
|
+
controller, action = detect_controller_class_and_action_name(req)
|
21
|
+
controller.action(action).call(req.env)
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
def constraints
|
25
|
+
[->(req) { detect_controller_class_and_action_name(req).all?(&:present?) }]
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
def controller(params, *_args)
|
29
|
+
projector(*params.values_at(:granite_action, :granite_projector))&.controller_class
|
30
|
+
end
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
def prepare_params!(params, *_args)
|
33
|
+
params
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
+
private
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
38
|
+
def detect_controller_class_and_action_name(req)
|
39
|
+
[
|
40
|
+
controller(req.params),
|
41
|
+
action_name(
|
42
|
+
req.request_method_symbol,
|
43
|
+
*req.params.values_at(:granite_action, :granite_projector, :projector_action)
|
44
|
+
)
|
45
|
+
]
|
46
|
+
end
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
48
|
+
memoize def action_name(request_method_symbol, granite_action, granite_projector, projector_action)
|
49
|
+
projector = projector(granite_action, granite_projector)
|
50
|
+
return unless projector
|
50
51
|
|
51
|
-
|
52
|
-
|
52
|
+
projector.action_for(request_method_symbol, projector_action.to_s)
|
53
|
+
end
|
53
54
|
|
54
|
-
|
55
|
-
|
55
|
+
memoize def projector(granite_action, granite_projector)
|
56
|
+
action = business_action(granite_action)
|
56
57
|
|
57
|
-
|
58
|
-
|
58
|
+
action.public_send(granite_projector) if action.respond_to?(granite_projector)
|
59
|
+
end
|
59
60
|
|
60
|
-
|
61
|
-
|
62
|
-
|
61
|
+
memoize def business_action(granite_action)
|
62
|
+
granite_action.camelize.safe_constantize ||
|
63
|
+
raise(ActionController::RoutingError,
|
64
|
+
"Granite action '#{granite_action}' is mounted but class '#{granite_action.camelize}' can't be found")
|
65
|
+
end
|
63
66
|
end
|
64
67
|
end
|
@@ -2,7 +2,7 @@ require 'action_dispatch/routing'
|
|
2
2
|
|
3
3
|
module Granite
|
4
4
|
class Projector
|
5
|
-
module ControllerActions
|
5
|
+
module ControllerActions # :nodoc:
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
included do
|
@@ -16,8 +16,8 @@ module Granite
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
module ClassMethods
|
20
|
-
def action(name, options = {}, &block)
|
19
|
+
module ClassMethods # :nodoc:
|
20
|
+
def action(name, options = {}, &block) # rubocop:disable Metrics/MethodLength
|
21
21
|
if block
|
22
22
|
self.controller_actions = controller_actions.merge(name.to_sym => options)
|
23
23
|
controller_class.__send__(:define_method, name, &block)
|
@@ -2,14 +2,14 @@ require 'granite/projector/error'
|
|
2
2
|
|
3
3
|
module Granite
|
4
4
|
class Projector
|
5
|
-
class ActionNotMountedError < Error
|
5
|
+
class ActionNotMountedError < Error # :nodoc:
|
6
6
|
def initialize(projector)
|
7
7
|
super("Seems like #{projector.class} was not mounted. \
|
8
8
|
Do you have #{projector.action_name}##{projector.projector_name} declared in routes?", projector)
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
module Helpers
|
12
|
+
module Helpers # :nodoc:
|
13
13
|
extend ActiveSupport::Concern
|
14
14
|
|
15
15
|
def view_context
|
@@ -35,7 +35,7 @@ Do you have #{projector.action_name}##{projector.projector_name} declared in rou
|
|
35
35
|
|
36
36
|
def required_params
|
37
37
|
corresponding_route.required_parts
|
38
|
-
|
38
|
+
.to_h { |name| [name, action.public_send(name)] }
|
39
39
|
end
|
40
40
|
|
41
41
|
def corresponding_route
|
@@ -51,7 +51,7 @@ Do you have #{projector.action_name}##{projector.projector_name} declared in rou
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def fetch_corresponding_route
|
54
|
-
Rails.application.routes.routes.granite_cache[*route_id] ||
|
54
|
+
Rails.application.routes.routes.granite_cache[*route_id] || raise(ActionNotMountedError, self)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
data/lib/granite/projector.rb
CHANGED
@@ -3,7 +3,7 @@ require 'granite/routing/route'
|
|
3
3
|
|
4
4
|
module Granite
|
5
5
|
module Routing
|
6
|
-
module Mapper
|
6
|
+
module Mapper # :nodoc:
|
7
7
|
def granite(projector_path, **options)
|
8
8
|
route = Route.new(projector_path, **options.extract!(:path, :as, :projector_prefix))
|
9
9
|
Declarer.declare(self, route, **options)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Granite
|
2
2
|
module Routing
|
3
|
-
module Mapping
|
3
|
+
module Mapping # :nodoc:
|
4
4
|
# Override the `ActionDispatch::Routing::Mapper::Mapping#app` method to
|
5
5
|
# be able to mount custom Dispatcher objects. Otherwise, the only way to
|
6
6
|
# point a dispatcher to business actions is to mount it as a Rack app
|
@@ -1,8 +1,12 @@
|
|
1
|
-
module Granite
|
2
|
-
|
1
|
+
module Granite
|
2
|
+
module ActionHelpers # :nodoc:
|
3
|
+
extend ActiveSupport::Concern
|
3
4
|
|
4
|
-
|
5
|
+
delegate :perform!, to: :subject
|
6
|
+
end
|
5
7
|
end
|
6
8
|
|
7
|
-
RSpec.configuration.define_derived_metadata(file_path: %r{spec/apq/actions/})
|
9
|
+
RSpec.configuration.define_derived_metadata(file_path: %r{spec/apq/actions/}) do |metadata|
|
10
|
+
metadata[:type] ||= :granite_action
|
11
|
+
end
|
8
12
|
RSpec.configuration.include Granite::ActionHelpers, type: :granite_action
|
@@ -1,54 +1,59 @@
|
|
1
|
-
module Granite
|
2
|
-
|
3
|
-
|
1
|
+
module Granite
|
2
|
+
module ProjectorHelpers # :nodoc:
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
include RSpec::Rails::ControllerExampleGroup
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
included do
|
7
|
+
before { Granite::Routing::Declarer.dispatcher.unmemoize_all }
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
module ClassMethods # :nodoc:
|
11
|
+
def draw_routes(&block)
|
12
|
+
before(:all) do
|
13
|
+
routes = Rails.application.routes
|
14
|
+
routes.disable_clear_and_finalize = true
|
15
|
+
routes.draw(&block)
|
16
|
+
end
|
17
|
+
|
18
|
+
after(:all) do
|
19
|
+
Rails.application.routes.disable_clear_and_finalize = false
|
20
|
+
Rails.application.reload_routes!
|
21
|
+
Rails.application.routes.routes.clear_cache!
|
22
|
+
end
|
15
23
|
end
|
16
24
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
25
|
+
def projector(&block)
|
26
|
+
setup_controller
|
27
|
+
setup_view_context
|
28
|
+
let(:projector_class, &block)
|
29
|
+
let(:projector) { controller.projector }
|
21
30
|
end
|
22
|
-
end
|
23
31
|
|
24
|
-
|
25
|
-
setup_controller
|
26
|
-
setup_view_context
|
27
|
-
let(:projector_class, &block)
|
28
|
-
let(:projector) { controller.projector }
|
29
|
-
end
|
32
|
+
private
|
30
33
|
|
31
|
-
|
34
|
+
def setup_controller
|
35
|
+
define_method :setup_controller_request_and_response do
|
36
|
+
@controller ||= projector_class.controller_class.new
|
37
|
+
super()
|
38
|
+
end
|
39
|
+
end
|
32
40
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
super()
|
41
|
+
def setup_view_context
|
42
|
+
before { Granite.view_context = controller.view_context }
|
43
|
+
after { Granite.view_context = nil }
|
37
44
|
end
|
38
45
|
end
|
39
46
|
|
40
|
-
|
41
|
-
|
42
|
-
|
47
|
+
# Overrides ActionController::TestCase::Behavior#process to include granite_action and granite_projector
|
48
|
+
def process(action, **options)
|
49
|
+
projector_params = { granite_action: projector_class.action_name,
|
50
|
+
granite_projector: projector_class.projector_name }
|
51
|
+
super(action, **options, params: projector_params.reverse_merge(options[:params] || {}))
|
43
52
|
end
|
44
53
|
end
|
45
|
-
|
46
|
-
# Overrides ActionController::TestCase::Behavior#process to include granite_action and granite_projector
|
47
|
-
def process(action, **options)
|
48
|
-
projector_params = {granite_action: projector_class.action_name, granite_projector: projector_class.projector_name}
|
49
|
-
super(action, **options, params: projector_params.reverse_merge(options[:params] || {}))
|
50
|
-
end
|
51
54
|
end
|
52
55
|
|
53
|
-
RSpec.configuration.define_derived_metadata(file_path: %r{spec/apq/projectors/})
|
56
|
+
RSpec.configuration.define_derived_metadata(file_path: %r{spec/apq/projectors/}) do |metadata|
|
57
|
+
metadata[:type] ||= :granite_projector
|
58
|
+
end
|
54
59
|
RSpec.configuration.include Granite::ProjectorHelpers, type: :granite_projector
|
@@ -38,13 +38,9 @@ RSpec::Matchers.define :raise_validation_error do
|
|
38
38
|
expected
|
39
39
|
end
|
40
40
|
|
41
|
-
failure_message
|
42
|
-
"expected to #{description}"
|
43
|
-
end
|
41
|
+
failure_message { "expected to #{description}" }
|
44
42
|
|
45
|
-
failure_message_when_negated
|
46
|
-
"expected not to #{description}"
|
47
|
-
end
|
43
|
+
failure_message_when_negated { "expected not to #{description}" }
|
48
44
|
|
49
45
|
supports_block_expectations
|
50
46
|
end
|
@@ -16,13 +16,13 @@
|
|
16
16
|
# ```ruby
|
17
17
|
# # assuming subject is business action
|
18
18
|
# it { is_expected.to satisfy_preconditions }
|
19
|
-
# it { is_expected.not_to satisfy_preconditions.with_message('
|
20
|
-
# it { is_expected.not_to satisfy_preconditions.with_messages(/^
|
21
|
-
# it { is_expected.not_to satisfy_preconditions.with_message_of_kind(:
|
22
|
-
# it { is_expected.not_to satisfy_preconditions.with_messages_of_kinds(:
|
19
|
+
# it { is_expected.not_to satisfy_preconditions.with_message('Form has not been signed') }
|
20
|
+
# it { is_expected.not_to satisfy_preconditions.with_messages(/^Form has not been signed by/', 'Signature required') }
|
21
|
+
# it { is_expected.not_to satisfy_preconditions.with_message_of_kind(:portfolio_needed) }
|
22
|
+
# it { is_expected.not_to satisfy_preconditions.with_messages_of_kinds(:portfolio_needed, :relevant_education_needed) }
|
23
23
|
# ```
|
24
24
|
#
|
25
|
-
RSpec::Matchers.define :satisfy_preconditions do
|
25
|
+
RSpec::Matchers.define :satisfy_preconditions do # rubocop:disable Metrics/BlockLength
|
26
26
|
chain(:with_message) do |message|
|
27
27
|
@expected_messages = [message]
|
28
28
|
end
|
@@ -44,7 +44,7 @@ RSpec::Matchers.define :satisfy_preconditions do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
match do |object|
|
47
|
-
|
47
|
+
raise '"with_messages" method chain is not supported for positive matcher' if @expected_messages
|
48
48
|
|
49
49
|
object.satisfy_preconditions?
|
50
50
|
end
|
data/lib/granite/translations.rb
CHANGED
data/lib/granite/version.rb
CHANGED
data/lib/granite.rb
CHANGED
@@ -6,7 +6,7 @@ require 'granite/version'
|
|
6
6
|
require 'granite/config'
|
7
7
|
require 'granite/context'
|
8
8
|
|
9
|
-
module Granite
|
9
|
+
module Granite # :nodoc:
|
10
10
|
def self.config
|
11
11
|
Granite::Config.instance
|
12
12
|
end
|
@@ -15,6 +15,10 @@ module Granite
|
|
15
15
|
Granite::Context.instance
|
16
16
|
end
|
17
17
|
|
18
|
+
def self.deprecator
|
19
|
+
@deprecator ||= ActiveSupport::Deprecation.new('1.0.0', 'Granite')
|
20
|
+
end
|
21
|
+
|
18
22
|
singleton_class.delegate(*Granite::Config.delegated, to: :config)
|
19
23
|
singleton_class.delegate(*Granite::Context.delegated, to: :context)
|
20
24
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
# The original code is from https://github.com/rubocop-hq/rubocop-rspec/blob/master/lib/rubocop/rspec/inject.rb
|
4
2
|
# See https://github.com/rubocop-hq/rubocop-rspec/blob/master/MIT-LICENSE.md
|
5
3
|
module RuboCop
|
@@ -11,7 +9,7 @@ module RuboCop
|
|
11
9
|
path = CONFIG_DEFAULT.to_s
|
12
10
|
hash = ConfigLoader.load_file(path)
|
13
11
|
config = Config.new(hash, path).tap(&:make_excludes_absolute)
|
14
|
-
|
12
|
+
Rails.logger.debug { "configuration from #{path}" } if ConfigLoader.debug?
|
15
13
|
config = ConfigLoader.merge_with_default(config, path)
|
16
14
|
ConfigLoader.instance_variable_set(:@default_configuration, config)
|
17
15
|
end
|
data/lib/rubocop/granite.rb
CHANGED
data/lib/rubocop-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.17.
|
4
|
+
version: 0.17.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Toptal Engineering
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -31,39 +31,39 @@ dependencies:
|
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '7.2'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
|
-
name:
|
34
|
+
name: activesupport
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
39
|
+
version: '6.0'
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '7.2'
|
40
43
|
type: :runtime
|
41
44
|
prerelease: false
|
42
45
|
version_requirements: !ruby/object:Gem::Requirement
|
43
46
|
requirements:
|
44
47
|
- - ">="
|
45
48
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
49
|
+
version: '6.0'
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '7.2'
|
47
53
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
54
|
+
name: granite-form
|
49
55
|
requirement: !ruby/object:Gem::Requirement
|
50
56
|
requirements:
|
51
57
|
- - ">="
|
52
58
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
54
|
-
- - "<"
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version: '7.2'
|
59
|
+
version: 0.3.0
|
57
60
|
type: :runtime
|
58
61
|
prerelease: false
|
59
62
|
version_requirements: !ruby/object:Gem::Requirement
|
60
63
|
requirements:
|
61
64
|
- - ">="
|
62
65
|
- !ruby/object:Gem::Version
|
63
|
-
version:
|
64
|
-
- - "<"
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version: '7.2'
|
66
|
+
version: 0.3.0
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
68
|
name: memoist
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -233,75 +233,75 @@ dependencies:
|
|
233
233
|
- !ruby/object:Gem::Version
|
234
234
|
version: '1.2'
|
235
235
|
- !ruby/object:Gem::Dependency
|
236
|
-
name:
|
236
|
+
name: rspec_junit_formatter
|
237
237
|
requirement: !ruby/object:Gem::Requirement
|
238
238
|
requirements:
|
239
239
|
- - "~>"
|
240
240
|
- !ruby/object:Gem::Version
|
241
|
-
version: '
|
241
|
+
version: '0.2'
|
242
242
|
type: :development
|
243
243
|
prerelease: false
|
244
244
|
version_requirements: !ruby/object:Gem::Requirement
|
245
245
|
requirements:
|
246
246
|
- - "~>"
|
247
247
|
- !ruby/object:Gem::Version
|
248
|
-
version: '
|
248
|
+
version: '0.2'
|
249
249
|
- !ruby/object:Gem::Dependency
|
250
|
-
name:
|
250
|
+
name: rspec-rails
|
251
251
|
requirement: !ruby/object:Gem::Requirement
|
252
252
|
requirements:
|
253
253
|
- - "~>"
|
254
254
|
- !ruby/object:Gem::Version
|
255
|
-
version: '0
|
255
|
+
version: '6.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: '0
|
262
|
+
version: '6.0'
|
263
263
|
- !ruby/object:Gem::Dependency
|
264
264
|
name: rubocop
|
265
265
|
requirement: !ruby/object:Gem::Requirement
|
266
266
|
requirements:
|
267
267
|
- - "~>"
|
268
268
|
- !ruby/object:Gem::Version
|
269
|
-
version:
|
269
|
+
version: 1.63.5
|
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:
|
276
|
+
version: 1.63.5
|
277
277
|
- !ruby/object:Gem::Dependency
|
278
278
|
name: rubocop-rails
|
279
279
|
requirement: !ruby/object:Gem::Requirement
|
280
280
|
requirements:
|
281
281
|
- - "~>"
|
282
282
|
- !ruby/object:Gem::Version
|
283
|
-
version:
|
283
|
+
version: 2.25.0
|
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.25.0
|
291
291
|
- !ruby/object:Gem::Dependency
|
292
292
|
name: rubocop-rspec
|
293
293
|
requirement: !ruby/object:Gem::Requirement
|
294
294
|
requirements:
|
295
295
|
- - "~>"
|
296
296
|
- !ruby/object:Gem::Version
|
297
|
-
version:
|
297
|
+
version: 2.29.2
|
298
298
|
type: :development
|
299
299
|
prerelease: false
|
300
300
|
version_requirements: !ruby/object:Gem::Requirement
|
301
301
|
requirements:
|
302
302
|
- - "~>"
|
303
303
|
- !ruby/object:Gem::Version
|
304
|
-
version:
|
304
|
+
version: 2.29.2
|
305
305
|
- !ruby/object:Gem::Dependency
|
306
306
|
name: simplecov
|
307
307
|
requirement: !ruby/object:Gem::Requirement
|
@@ -392,7 +392,8 @@ files:
|
|
392
392
|
homepage: https://github.com/toptal/granite
|
393
393
|
licenses:
|
394
394
|
- MIT
|
395
|
-
metadata:
|
395
|
+
metadata:
|
396
|
+
rubygems_mfa_required: 'true'
|
396
397
|
post_install_message:
|
397
398
|
rdoc_options: []
|
398
399
|
require_paths:
|
@@ -401,14 +402,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
401
402
|
requirements:
|
402
403
|
- - ">="
|
403
404
|
- !ruby/object:Gem::Version
|
404
|
-
version: '2.
|
405
|
+
version: '2.6'
|
405
406
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
406
407
|
requirements:
|
407
408
|
- - ">="
|
408
409
|
- !ruby/object:Gem::Version
|
409
410
|
version: '0'
|
410
411
|
requirements: []
|
411
|
-
rubygems_version: 3.
|
412
|
+
rubygems_version: 3.5.10
|
412
413
|
signing_key:
|
413
414
|
specification_version: 4
|
414
415
|
summary: Another business actions architecture for Rails apps
|