granite 0.9.9 → 0.12.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/translations.rb +2 -1
- data/lib/granite/action/performing.rb +2 -2
- data/lib/granite/action/policies.rb +3 -3
- data/lib/granite/action/preconditions/base_precondition.rb +1 -1
- data/lib/granite/action/preconditions.rb +13 -9
- data/lib/granite/action/translations.rb +2 -1
- data/lib/granite/action.rb +16 -8
- data/lib/granite/assign_data.rb +40 -0
- data/lib/granite/base.rb +4 -0
- data/lib/granite/dispatcher.rb +6 -6
- data/lib/granite/projector/controller_actions.rb +2 -2
- data/lib/granite/projector/translations.rb +2 -1
- data/lib/granite/represents/attribute.rb +1 -1
- data/lib/granite/represents.rb +1 -4
- data/lib/granite/util.rb +1 -1
- data/lib/granite/version.rb +1 -1
- metadata +31 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f01fbcec194a3031c22582899a7ff0210d2b621aa149a5ccf7814a3a70540ea
|
4
|
+
data.tar.gz: c763544b18d4feb43a5502df2e661dce313c304f47543978be095e4e72afc863
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '099c76956322fe11a1118dc25a1fffbc0553018d1abf660d7c6270256f40505a3d93be01e57df0d7502c767c09d961fcf3361a7281315296e6abb9c512a38a9f'
|
7
|
+
data.tar.gz: 9b1b66eca75f4ff623319d1828cbec2b987c36050fb70598a8a14ea7edd760da38eb61c89f0a4de3b706875b68a16dccefe22333c3ac8edbe5b80864e04f4aca
|
@@ -6,7 +6,8 @@ module Granite
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def translate(*args, **options)
|
9
|
-
|
9
|
+
key, options = Granite::Translations.scope_translation_args(i18n_scopes, *args, **options)
|
10
|
+
super(key, **options)
|
10
11
|
end
|
11
12
|
|
12
13
|
alias t translate
|
@@ -42,7 +42,7 @@ module Granite
|
|
42
42
|
# @return [Object] result of execute_perform! method execution or false in case of errors
|
43
43
|
def perform(context: nil, **options)
|
44
44
|
transaction do
|
45
|
-
valid?(context) && perform_action(options)
|
45
|
+
valid?(context) && perform_action(**options)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -94,7 +94,7 @@ module Granite
|
|
94
94
|
def perform_action(raise_errors: false, **options)
|
95
95
|
result = run_callbacks(:execute_perform) do
|
96
96
|
apply_association_changes!
|
97
|
-
execute_perform!(options)
|
97
|
+
execute_perform!(**options)
|
98
98
|
end
|
99
99
|
@_action_performed = true
|
100
100
|
result || true
|
@@ -55,17 +55,17 @@ module Granite
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
def try_perform!(
|
58
|
+
def try_perform!(*, **)
|
59
59
|
authorize!
|
60
60
|
super
|
61
61
|
end
|
62
62
|
|
63
|
-
def perform(
|
63
|
+
def perform(*, **)
|
64
64
|
authorize!
|
65
65
|
super
|
66
66
|
end
|
67
67
|
|
68
|
-
def perform!(
|
68
|
+
def perform!(*, **)
|
69
69
|
authorize!
|
70
70
|
super
|
71
71
|
end
|
@@ -51,15 +51,7 @@ module Granite
|
|
51
51
|
elsif args.first.is_a?(Class)
|
52
52
|
add_precondition(ObjectPrecondition, *args, options)
|
53
53
|
else
|
54
|
-
|
55
|
-
args.each do |type|
|
56
|
-
precondition common_options.merge(type => {})
|
57
|
-
end
|
58
|
-
options.each do |key, value|
|
59
|
-
value = Array.wrap(value)
|
60
|
-
precondition_options = value.extract_options!
|
61
|
-
add_precondition(klass(key), *value, precondition_options.merge!(common_options))
|
62
|
-
end
|
54
|
+
add_preconditions_hash(*args, **options)
|
63
55
|
end
|
64
56
|
end
|
65
57
|
|
@@ -72,6 +64,18 @@ module Granite
|
|
72
64
|
end || fail(NameError, "No precondition class for #{key}Precondition")
|
73
65
|
end
|
74
66
|
|
67
|
+
def add_preconditions_hash(*args, **options)
|
68
|
+
common_options = options.extract!(:if, :unless, :desc, :description)
|
69
|
+
args.each do |type|
|
70
|
+
precondition common_options.merge(type => {})
|
71
|
+
end
|
72
|
+
options.each do |key, value|
|
73
|
+
value = Array.wrap(value)
|
74
|
+
precondition_options = value.extract_options!
|
75
|
+
add_precondition(klass(key), *value, precondition_options.merge!(common_options))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
75
79
|
def add_precondition(klass, *args, &block)
|
76
80
|
self._preconditions += klass.new(*args, &block)
|
77
81
|
end
|
@@ -16,7 +16,8 @@ module Granite
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def translate(*args, **options)
|
19
|
-
|
19
|
+
key, options = Granite::Translations.scope_translation_args(self.class.i18n_scopes, *args, **options)
|
20
|
+
I18n.translate(key, **options)
|
20
21
|
end
|
21
22
|
alias t translate
|
22
23
|
end
|
data/lib/granite/action.rb
CHANGED
@@ -50,20 +50,28 @@ module Granite
|
|
50
50
|
prepend AssignAttributes
|
51
51
|
|
52
52
|
handle_exception ActiveRecord::RecordInvalid do |e|
|
53
|
-
|
54
|
-
(this + other).uniq
|
55
|
-
end
|
53
|
+
merge_errors(e.record.errors)
|
56
54
|
end
|
57
55
|
|
58
56
|
handle_exception ActiveData::ValidationError do |e|
|
59
|
-
|
60
|
-
(this + other).uniq
|
61
|
-
end
|
57
|
+
merge_errors(e.model.errors)
|
62
58
|
end
|
63
59
|
|
64
60
|
handle_exception Granite::Action::ValidationError do |e|
|
65
|
-
|
66
|
-
|
61
|
+
merge_errors(e.action.errors)
|
62
|
+
end
|
63
|
+
|
64
|
+
if ActiveModel.version < Gem::Version.new('6.1.0')
|
65
|
+
def merge_errors(other_errors)
|
66
|
+
errors.messages.deep_merge!(other_errors.messages) do |_, this, other|
|
67
|
+
(this + other).uniq
|
68
|
+
end
|
69
|
+
end
|
70
|
+
else
|
71
|
+
def merge_errors(other_errors)
|
72
|
+
other_errors.each do |error|
|
73
|
+
errors.import(error) unless errors.added?(error.attribute, error)
|
74
|
+
end
|
67
75
|
end
|
68
76
|
end
|
69
77
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Granite
|
2
|
+
module AssignData
|
3
|
+
DataAssignment = Struct.new(:method, :options)
|
4
|
+
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_attribute :data_assignments
|
9
|
+
self.data_assignments = []
|
10
|
+
|
11
|
+
alias_method :only_run_validations!, :run_validations!
|
12
|
+
protected :only_run_validations! # rubocop:disable Style/AccessModifierDeclarations
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
# Defines a callback to call when assigning data from business action to model.
|
17
|
+
# @param methods [Array<Symbol>] list of methods to call
|
18
|
+
# @param block [Proc] a block to call
|
19
|
+
# @option options [Symbol, Proc, Object] :if call methods/block if this condition evaluates to true
|
20
|
+
# @option options [Symbol, Proc, Object] :unless call method/block unless this condition evaluates to true
|
21
|
+
def assign_data(*methods, **options, &block)
|
22
|
+
self.data_assignments += methods.map { |method| DataAssignment.new(method, options) }
|
23
|
+
self.data_assignments += [DataAssignment.new(block, options)] if block
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def assign_data
|
30
|
+
data_assignments.each { |assignment| evaluate(assignment.method) if conditions_satisfied?(**assignment.options) }
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def run_validations!
|
36
|
+
assign_data
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/granite/base.rb
CHANGED
@@ -5,8 +5,11 @@ require 'active_data/model/associations'
|
|
5
5
|
|
6
6
|
require 'granite/translations'
|
7
7
|
require 'granite/represents'
|
8
|
+
require 'granite/assign_data'
|
8
9
|
|
9
10
|
module Granite
|
11
|
+
# Base included in Granite::Action, but also used by ActiveData when building data objects (e.g. when using
|
12
|
+
# embeds_many)
|
10
13
|
module Base
|
11
14
|
extend ActiveSupport::Concern
|
12
15
|
|
@@ -19,6 +22,7 @@ module Granite
|
|
19
22
|
include ActiveModel::Validations::Callbacks
|
20
23
|
|
21
24
|
include Granite::Util
|
25
|
+
include Granite::AssignData
|
22
26
|
include Granite::Represents
|
23
27
|
end
|
24
28
|
end
|
data/lib/granite/dispatcher.rb
CHANGED
@@ -25,7 +25,7 @@ class Granite::Dispatcher
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def controller(params, *_args)
|
28
|
-
projector(params.
|
28
|
+
projector(*params.values_at(:granite_action, :granite_projector))&.controller_class
|
29
29
|
end
|
30
30
|
|
31
31
|
def prepare_params!(params, *_args)
|
@@ -39,19 +39,19 @@ class Granite::Dispatcher
|
|
39
39
|
controller(req.params),
|
40
40
|
action_name(
|
41
41
|
req.request_method_symbol,
|
42
|
-
req.params.
|
42
|
+
*req.params.values_at(:granite_action, :granite_projector, :projector_action)
|
43
43
|
)
|
44
44
|
]
|
45
45
|
end
|
46
46
|
|
47
|
-
memoize def action_name(request_method_symbol, granite_action
|
48
|
-
projector = projector(granite_action
|
47
|
+
memoize def action_name(request_method_symbol, granite_action, granite_projector, projector_action)
|
48
|
+
projector = projector(granite_action, granite_projector)
|
49
49
|
return unless projector
|
50
50
|
|
51
|
-
projector.action_for(request_method_symbol, projector_action)
|
51
|
+
projector.action_for(request_method_symbol, projector_action.to_s)
|
52
52
|
end
|
53
53
|
|
54
|
-
memoize def projector(granite_action
|
54
|
+
memoize def projector(granite_action, granite_projector)
|
55
55
|
action = business_action(granite_action)
|
56
56
|
|
57
57
|
action.public_send(granite_projector) if action.respond_to?(granite_projector)
|
@@ -23,11 +23,11 @@ module Granite
|
|
23
23
|
controller_class.__send__(:define_method, name, &block)
|
24
24
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
25
25
|
def #{name}_url(options = {})
|
26
|
-
action_url(:#{name}, options.symbolize_keys)
|
26
|
+
action_url(:#{name}, **options.symbolize_keys)
|
27
27
|
end
|
28
28
|
|
29
29
|
def #{name}_path(options = {})
|
30
|
-
action_path(:#{name}, options.symbolize_keys)
|
30
|
+
action_path(:#{name}, **options.symbolize_keys)
|
31
31
|
end
|
32
32
|
METHOD
|
33
33
|
else
|
@@ -8,7 +8,8 @@ module Granite
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def translate(*args, **options)
|
11
|
-
|
11
|
+
key, options = Granite::Translations.scope_translation_args(i18n_scopes, *args, **options)
|
12
|
+
super(key, **options)
|
12
13
|
end
|
13
14
|
|
14
15
|
alias t translate
|
data/lib/granite/represents.rb
CHANGED
@@ -13,10 +13,7 @@ module Granite
|
|
13
13
|
fields.each do |field|
|
14
14
|
add_attribute Granite::Represents::Reflection, field, options, &block
|
15
15
|
|
16
|
-
|
17
|
-
attribute(field).sync if attribute(field).changed?
|
18
|
-
true
|
19
|
-
end
|
16
|
+
assign_data { attribute(field).sync if attribute(field).changed? }
|
20
17
|
end
|
21
18
|
end
|
22
19
|
end
|
data/lib/granite/util.rb
CHANGED
@@ -26,7 +26,7 @@ module Granite
|
|
26
26
|
# @option options :if method name or callable
|
27
27
|
# @option options :unless method name or callable
|
28
28
|
# @return [Boolean] whether conditions are satisfied
|
29
|
-
def conditions_satisfied?(options)
|
29
|
+
def conditions_satisfied?(**options)
|
30
30
|
fail ArgumentError, 'You cannot specify both if and unless' if options.key?(:if) && options.key?(:unless)
|
31
31
|
|
32
32
|
if options.key?(:if)
|
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.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
autorequire:
|
7
|
+
- Toptal Engineering
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: '5.1'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '7.1'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,21 +29,21 @@ dependencies:
|
|
29
29
|
version: '5.1'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '7.1'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: active_data
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 1.
|
39
|
+
version: 1.2.0
|
40
40
|
type: :runtime
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: 1.
|
46
|
+
version: 1.2.0
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: activesupport
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
version: '5.1'
|
54
54
|
- - "<"
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: '
|
56
|
+
version: '7.1'
|
57
57
|
type: :runtime
|
58
58
|
prerelease: false
|
59
59
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -63,7 +63,7 @@ dependencies:
|
|
63
63
|
version: '5.1'
|
64
64
|
- - "<"
|
65
65
|
- !ruby/object:Gem::Version
|
66
|
-
version: '
|
66
|
+
version: '7.1'
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
68
|
name: memoist
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,20 +84,28 @@ dependencies:
|
|
84
84
|
requirements:
|
85
85
|
- - ">="
|
86
86
|
- !ruby/object:Gem::Version
|
87
|
-
version: '
|
88
|
-
- - "<"
|
89
|
-
- !ruby/object:Gem::Version
|
90
|
-
version: '6.1'
|
87
|
+
version: '0'
|
91
88
|
type: :development
|
92
89
|
prerelease: false
|
93
90
|
version_requirements: !ruby/object:Gem::Requirement
|
94
91
|
requirements:
|
95
92
|
- - ">="
|
96
93
|
- !ruby/object:Gem::Version
|
97
|
-
version: '
|
98
|
-
|
94
|
+
version: '0'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: appraisal
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
99
100
|
- !ruby/object:Gem::Version
|
100
|
-
version: '
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
101
109
|
- !ruby/object:Gem::Dependency
|
102
110
|
name: capybara
|
103
111
|
requirement: !ruby/object:Gem::Requirement
|
@@ -294,8 +302,8 @@ dependencies:
|
|
294
302
|
- - "~>"
|
295
303
|
- !ruby/object:Gem::Version
|
296
304
|
version: '0.15'
|
297
|
-
description:
|
298
|
-
email:
|
305
|
+
description:
|
306
|
+
email:
|
299
307
|
executables: []
|
300
308
|
extensions: []
|
301
309
|
extra_rdoc_files: []
|
@@ -334,6 +342,7 @@ files:
|
|
334
342
|
- lib/granite/action/translations.rb
|
335
343
|
- lib/granite/action/types.rb
|
336
344
|
- lib/granite/action/types/collection.rb
|
345
|
+
- lib/granite/assign_data.rb
|
337
346
|
- lib/granite/base.rb
|
338
347
|
- lib/granite/config.rb
|
339
348
|
- lib/granite/context.rb
|
@@ -374,7 +383,7 @@ homepage: https://github.com/toptal/granite
|
|
374
383
|
licenses:
|
375
384
|
- MIT
|
376
385
|
metadata: {}
|
377
|
-
post_install_message:
|
386
|
+
post_install_message:
|
378
387
|
rdoc_options: []
|
379
388
|
require_paths:
|
380
389
|
- lib
|
@@ -389,8 +398,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
389
398
|
- !ruby/object:Gem::Version
|
390
399
|
version: '0'
|
391
400
|
requirements: []
|
392
|
-
rubygems_version: 3.
|
393
|
-
signing_key:
|
401
|
+
rubygems_version: 3.2.29
|
402
|
+
signing_key:
|
394
403
|
specification_version: 4
|
395
404
|
summary: Another business actions architecture for Rails apps
|
396
405
|
test_files: []
|