granite 0.9.8 → 0.11.1
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 +16 -0
- data/app/controllers/granite/controller.rb +2 -2
- 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 +25 -0
- data/lib/granite/action.rb +2 -4
- data/lib/granite/assign_data.rb +40 -0
- data/lib/granite/base.rb +4 -1
- data/lib/granite/dispatcher.rb +6 -6
- data/lib/granite/projector/controller_actions.rb +2 -2
- data/lib/granite/projector/translations.rb +7 -41
- data/lib/granite/represents.rb +1 -4
- data/lib/granite/routing/mapper.rb +2 -2
- data/lib/granite/translations.rb +11 -20
- data/lib/granite/util.rb +1 -1
- data/lib/granite/version.rb +1 -1
- metadata +7 -6
- data/lib/granite/projector/translations/helper.rb +0 -22
- data/lib/granite/projector/translations/view_helper.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a6546b162c712c95bf1c954a99143418186c5392548e7a6f767755d7715854c
|
4
|
+
data.tar.gz: 2cd60295ca235be9d5a561f92777a8a7db2920481f33309c93b6730587df14e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89dbff44372428da1723b72f28181880a69428845fd6e0665b981fbb9f13e4323176f1b888f93986f15da104618f2674b01f445f21ca13ce6472595bf26009be
|
7
|
+
data.tar.gz: df01fdaec830de6c86fe291a608e7e32df1feefcfe2e92964b435e95505ffd027705e531f912bc5e7ee2a779a88485c7a9a1c439366a01de1bec6a88eda5a3b8
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Granite
|
2
|
+
class Controller
|
3
|
+
module Translations
|
4
|
+
def i18n_scopes
|
5
|
+
Granite::Translations.combine_paths(projector.i18n_scopes, [*action_name, nil])
|
6
|
+
end
|
7
|
+
|
8
|
+
def translate(*args, **options)
|
9
|
+
key, options = Granite::Translations.scope_translation_args(i18n_scopes, *args, **options)
|
10
|
+
super(key, **options)
|
11
|
+
end
|
12
|
+
|
13
|
+
alias t translate
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'granite/projector/translations/helper'
|
2
1
|
require 'action_controller'
|
3
2
|
|
4
3
|
module Granite
|
5
4
|
class Controller < Granite.base_controller_class
|
6
|
-
include
|
5
|
+
include Controller::Translations
|
6
|
+
helper Controller::Translations
|
7
7
|
|
8
8
|
singleton_class.__send__(:attr_accessor, :projector_class)
|
9
9
|
singleton_class.delegate :projector_path, :projector_name, :action_class, to: :projector_class
|
@@ -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
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Granite
|
2
|
+
class Action
|
3
|
+
module Translations
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def i18n_scope
|
8
|
+
:granite_action
|
9
|
+
end
|
10
|
+
|
11
|
+
def i18n_scopes
|
12
|
+
lookup_ancestors.flat_map do |klass|
|
13
|
+
:"#{klass.i18n_scope}.#{klass.model_name.i18n_key}"
|
14
|
+
end + [nil]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def translate(*args, **options)
|
19
|
+
key, options = Granite::Translations.scope_translation_args(self.class.i18n_scopes, *args, **options)
|
20
|
+
I18n.translate(key, **options)
|
21
|
+
end
|
22
|
+
alias t translate
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/granite/action.rb
CHANGED
@@ -12,6 +12,7 @@ require 'granite/action/preconditions'
|
|
12
12
|
require 'granite/action/policies'
|
13
13
|
require 'granite/action/projectors'
|
14
14
|
require 'granite/action/subject'
|
15
|
+
require 'granite/action/translations'
|
15
16
|
|
16
17
|
module Granite
|
17
18
|
class Action
|
@@ -39,6 +40,7 @@ module Granite
|
|
39
40
|
end
|
40
41
|
|
41
42
|
include Base
|
43
|
+
include Translations
|
42
44
|
include Performing
|
43
45
|
include Subject
|
44
46
|
include Performer
|
@@ -65,10 +67,6 @@ module Granite
|
|
65
67
|
end
|
66
68
|
end
|
67
69
|
|
68
|
-
def self.i18n_scope
|
69
|
-
:granite_action
|
70
|
-
end
|
71
|
-
|
72
70
|
# Almost the same as Dirty `#changed?` method, but
|
73
71
|
# doesn't check subject reference key
|
74
72
|
def attributes_changed?(except: [])
|
@@ -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,7 +22,7 @@ module Granite
|
|
19
22
|
include ActiveModel::Validations::Callbacks
|
20
23
|
|
21
24
|
include Granite::Util
|
22
|
-
include Granite::
|
25
|
+
include Granite::AssignData
|
23
26
|
include Granite::Represents
|
24
27
|
end
|
25
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
|
@@ -1,52 +1,18 @@
|
|
1
1
|
module Granite
|
2
2
|
class Projector
|
3
3
|
module Translations
|
4
|
-
|
4
|
+
include ActionView::Helpers::TranslationHelper
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
def i18n_scopes
|
7
|
+
Granite::Translations.combine_paths(action_class.i18n_scopes, [:"#{projector_name}"])
|
8
8
|
end
|
9
9
|
|
10
|
-
def translate(*args)
|
11
|
-
|
10
|
+
def translate(*args, **options)
|
11
|
+
key, options = Granite::Translations.scope_translation_args(i18n_scopes, *args, **options)
|
12
|
+
super(key, **options)
|
12
13
|
end
|
13
|
-
alias t translate
|
14
|
-
|
15
|
-
module ClassMethods
|
16
|
-
def scope_translation_args_by_projector(args, action_name: nil)
|
17
|
-
options = args.extract_options!
|
18
|
-
|
19
|
-
lookups = expand_relative_key(args.first, action_name).map(&:to_sym)
|
20
|
-
lookups += [options[:default]]
|
21
|
-
lookups = lookups.flatten.compact
|
22
|
-
|
23
|
-
key = lookups.shift
|
24
|
-
options[:default] = lookups
|
25
|
-
|
26
|
-
[key, options]
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
14
|
|
31
|
-
|
32
|
-
return [key] unless key.is_a?(String) && key.start_with?('.')
|
33
|
-
|
34
|
-
base_keys = extract_base_keys(key, action_name)
|
35
|
-
|
36
|
-
action_class.lookup_ancestors.map do |klass|
|
37
|
-
base_keys.map do |base_key|
|
38
|
-
:"#{klass.i18n_scope}.#{klass.model_name.i18n_key}.#{base_key}"
|
39
|
-
end
|
40
|
-
end.flatten + base_keys
|
41
|
-
end
|
42
|
-
|
43
|
-
def extract_base_keys(key, action_name)
|
44
|
-
undotted_key = key.sub(/^\./, '')
|
45
|
-
base_keys = [:"#{projector_name}.#{undotted_key}"]
|
46
|
-
base_keys.unshift :"#{projector_name}.#{action_name}.#{undotted_key}" if action_name
|
47
|
-
base_keys
|
48
|
-
end
|
49
|
-
end
|
15
|
+
alias t translate
|
50
16
|
end
|
51
17
|
end
|
52
18
|
end
|
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
|
@@ -5,8 +5,8 @@ module Granite
|
|
5
5
|
module Routing
|
6
6
|
module Mapper
|
7
7
|
def granite(projector_path, **options)
|
8
|
-
route = Route.new(projector_path, options.extract!(:path, :as, :projector_prefix))
|
9
|
-
Declarer.declare(self, route, options)
|
8
|
+
route = Route.new(projector_path, **options.extract!(:path, :as, :projector_prefix))
|
9
|
+
Declarer.declare(self, route, **options)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
data/lib/granite/translations.rb
CHANGED
@@ -1,19 +1,14 @@
|
|
1
1
|
module Granite
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
module ClassMethods
|
11
|
-
def scope_translation_args(args)
|
12
|
-
options = args.extract_options!
|
2
|
+
class Translations
|
3
|
+
class << self
|
4
|
+
def combine_paths(paths1, paths2)
|
5
|
+
paths1.flat_map do |path1|
|
6
|
+
paths2.map { |path2| [*path1, *path2].join('.') }
|
7
|
+
end
|
8
|
+
end
|
13
9
|
|
14
|
-
|
15
|
-
lookups
|
16
|
-
lookups = lookups.flatten.compact
|
10
|
+
def scope_translation_args(scopes, key, *, **options)
|
11
|
+
lookups = expand_relative_key(scopes, key) + Array(options[:default])
|
17
12
|
|
18
13
|
key = lookups.shift
|
19
14
|
options[:default] = lookups
|
@@ -23,14 +18,10 @@ module Granite
|
|
23
18
|
|
24
19
|
private
|
25
20
|
|
26
|
-
def expand_relative_key(key)
|
21
|
+
def expand_relative_key(scopes, key)
|
27
22
|
return [key] unless key.is_a?(String) && key.start_with?('.')
|
28
23
|
|
29
|
-
|
30
|
-
|
31
|
-
lookup_ancestors.map do |klass|
|
32
|
-
:"#{klass.i18n_scope}.#{klass.model_name.i18n_key}.#{base_key}"
|
33
|
-
end.flatten + [base_key]
|
24
|
+
combine_paths(scopes, [key.sub(/^\./, '')]).map(&:to_sym)
|
34
25
|
end
|
35
26
|
end
|
36
27
|
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.11.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Toptal Engineering
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -302,6 +302,7 @@ extra_rdoc_files: []
|
|
302
302
|
files:
|
303
303
|
- LICENSE
|
304
304
|
- app/controllers/granite/controller.rb
|
305
|
+
- app/controllers/granite/controller/translations.rb
|
305
306
|
- config/rubocop-default.yml
|
306
307
|
- lib/generators/USAGE
|
307
308
|
- lib/generators/granite/install_controller_generator.rb
|
@@ -330,8 +331,10 @@ files:
|
|
330
331
|
- lib/granite/action/transaction.rb
|
331
332
|
- lib/granite/action/transaction_manager.rb
|
332
333
|
- lib/granite/action/transaction_manager/transactions_stack.rb
|
334
|
+
- lib/granite/action/translations.rb
|
333
335
|
- lib/granite/action/types.rb
|
334
336
|
- lib/granite/action/types/collection.rb
|
337
|
+
- lib/granite/assign_data.rb
|
335
338
|
- lib/granite/base.rb
|
336
339
|
- lib/granite/config.rb
|
337
340
|
- lib/granite/context.rb
|
@@ -344,8 +347,6 @@ files:
|
|
344
347
|
- lib/granite/projector/error.rb
|
345
348
|
- lib/granite/projector/helpers.rb
|
346
349
|
- lib/granite/projector/translations.rb
|
347
|
-
- lib/granite/projector/translations/helper.rb
|
348
|
-
- lib/granite/projector/translations/view_helper.rb
|
349
350
|
- lib/granite/rails.rb
|
350
351
|
- lib/granite/represents.rb
|
351
352
|
- lib/granite/represents/attribute.rb
|
@@ -389,7 +390,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
389
390
|
- !ruby/object:Gem::Version
|
390
391
|
version: '0'
|
391
392
|
requirements: []
|
392
|
-
rubygems_version: 3.0.
|
393
|
+
rubygems_version: 3.0.9
|
393
394
|
signing_key:
|
394
395
|
specification_version: 4
|
395
396
|
summary: Another business actions architecture for Rails apps
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'granite/projector/translations/view_helper'
|
2
|
-
|
3
|
-
module Granite
|
4
|
-
class Projector
|
5
|
-
module Translations
|
6
|
-
module Helper
|
7
|
-
extend ActiveSupport::Concern
|
8
|
-
|
9
|
-
included do
|
10
|
-
delegate :scope_translation_args_by_projector, to: :projector_class
|
11
|
-
helper_method :scope_translation_args_by_projector
|
12
|
-
helper ViewHelper
|
13
|
-
end
|
14
|
-
|
15
|
-
def translate(*args)
|
16
|
-
super(*scope_translation_args_by_projector(args, action_name: action_name))
|
17
|
-
end
|
18
|
-
alias t translate
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|