operations 0.7.1 → 0.7.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/.rubocop_todo.yml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +12 -8
- data/UPGRADING_FORMS.md +1 -1
- data/lib/operations/command.rb +5 -0
- data/lib/operations/form/attribute.rb +16 -20
- data/lib/operations/form/base.rb +12 -5
- data/lib/operations/form.rb +21 -4
- data/lib/operations/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: affb68a66ecbc1ee0e687ab13efb202037d10054adb114e684e775224957b65e
|
4
|
+
data.tar.gz: 255180d0be3704a73c0bf6e148658df8b662e33a4508dff3ae3fee819e73caba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f639386ccb6d003909737a4606b44f21cf49dc90b36fe0c854ea1e8c824049b2de7a70c480b44b2f4713558f21417c755361b6fccad4ed2f2af1068bc7cd135
|
7
|
+
data.tar.gz: a24d378627511c1198728a9aebe38c7f39cb057756e957906df29bf059804eef94d1188146b845842be42d94c559ebccd84b3d4d6a613b95a2a31d427771fe09
|
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2024-
|
3
|
+
# on 2024-08-07 02:24:58 UTC using RuboCop version 1.65.0.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
@@ -22,14 +22,14 @@ Metrics/AbcSize:
|
|
22
22
|
# Offense count: 1
|
23
23
|
# Configuration parameters: CountComments, CountAsOne.
|
24
24
|
Metrics/ClassLength:
|
25
|
-
Max:
|
25
|
+
Max: 149
|
26
26
|
|
27
27
|
# Offense count: 1
|
28
28
|
# Configuration parameters: CountComments, CountAsOne.
|
29
29
|
Metrics/ModuleLength:
|
30
|
-
Max:
|
30
|
+
Max: 141
|
31
31
|
|
32
|
-
# Offense count:
|
32
|
+
# Offense count: 3
|
33
33
|
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
|
34
34
|
Metrics/ParameterLists:
|
35
35
|
Max: 7
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [0.7.2](https://github.com/BookingSync/operations/tree/v0.7.2)
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Allow referencing and arbitrary model attrbiute from form object attribute with `model_name: "Post#title"` [\#50](https://github.com/BookingSync/operations/pull/50) ([pyromaniac](https://github.com/pyromaniac))
|
8
|
+
- Allow passing multiple `hydrators:` to Operations::Form [\#49](https://github.com/BookingSync/operations/pull/49) ([pyromaniac](https://github.com/pyromaniac))
|
9
|
+
|
10
|
+
### Improvements
|
11
|
+
|
12
|
+
- Change default form hydration behavior - it is now deep merging params after hydration, so no need to do it in the hydrator. Controlled with `hydration_merge_params:` option. [\#49](https://github.com/BookingSync/operations/pull/49) ([pyromaniac](https://github.com/pyromaniac))
|
13
|
+
|
3
14
|
## [0.7.1](https://github.com/BookingSync/operations/tree/v0.7.1)
|
4
15
|
|
5
16
|
### Added
|
data/README.md
CHANGED
@@ -312,7 +312,7 @@ class ActiveRecordRepository
|
|
312
312
|
include Dry::Monads[:result]
|
313
313
|
extend Dry::Initializer
|
314
314
|
|
315
|
-
param :model, type: Types
|
315
|
+
param :model, type: Types::Class.constrained(lt: ActiveRecord::Base)
|
316
316
|
|
317
317
|
def create(**attributes)
|
318
318
|
record = model.new(**attributes)
|
@@ -904,7 +904,7 @@ class Post::Update
|
|
904
904
|
def self.default_form
|
905
905
|
@default_form ||= Operations::Form.new(
|
906
906
|
default,
|
907
|
-
|
907
|
+
hydrators: [Post::Update::Hydrator.new]
|
908
908
|
)
|
909
909
|
end
|
910
910
|
end
|
@@ -912,9 +912,7 @@ end
|
|
912
912
|
class Post::Update::Hydrator
|
913
913
|
def call(form_class, params, post:, **_context)
|
914
914
|
value_attributes = form_class.attributes.keys - %i[post_id]
|
915
|
-
|
916
|
-
|
917
|
-
data.merge!(params)
|
915
|
+
value_attributes.index_with { |name| post.public_send(name) }
|
918
916
|
end
|
919
917
|
end
|
920
918
|
```
|
@@ -929,14 +927,20 @@ class Post::Update
|
|
929
927
|
@default_form ||= Operations::Form.new(
|
930
928
|
default,
|
931
929
|
model_map: Post::Update::ModelMap.new,
|
932
|
-
|
930
|
+
hydrators: [Post::Update::Hydrator.new]
|
933
931
|
)
|
934
932
|
end
|
935
933
|
end
|
936
934
|
|
937
935
|
class Post::Update::ModelMap
|
938
|
-
|
939
|
-
Post
|
936
|
+
MAPPING = {
|
937
|
+
%w[published_at] => Post, # a model can be passed but beware of circular dependencies, better use strings
|
938
|
+
%w[title] => "Post", # or a model name - safer option
|
939
|
+
%w[content] => "Post#body" # referencing different attribute is possible, useful for naming migration or translations
|
940
|
+
}.freeze
|
941
|
+
|
942
|
+
def call(path)
|
943
|
+
MAPPING[path] # returns the mapping for a single path
|
940
944
|
end
|
941
945
|
end
|
942
946
|
```
|
data/UPGRADING_FORMS.md
CHANGED
@@ -31,7 +31,7 @@ class Post::Update
|
|
31
31
|
def self.default_form
|
32
32
|
@default_form ||= Operations::Form.new(
|
33
33
|
default,
|
34
|
-
|
34
|
+
hydrators: [Post::Update::Hydrator.new],
|
35
35
|
model_map: Post::Update::ModelMap.new,
|
36
36
|
params_transformations: [
|
37
37
|
ParamsMap.new(id: :post_id)
|
data/lib/operations/command.rb
CHANGED
@@ -197,6 +197,11 @@ class Operations::Command
|
|
197
197
|
result_policies = policies_sum - [Undefined] unless policies_sum == [Undefined, Undefined]
|
198
198
|
options[:policies] = result_policies if result_policies
|
199
199
|
|
200
|
+
if after.present?
|
201
|
+
ActiveSupport::Deprecation.new.warn("Operations::Command `after:` option is deprecated and will be " \
|
202
|
+
"removed in 1.0.0. Please use `on_success:` instead")
|
203
|
+
end
|
204
|
+
|
200
205
|
preconditions.push(precondition) if precondition.present?
|
201
206
|
super(operation, preconditions: preconditions, on_success: after, **options)
|
202
207
|
end
|
@@ -5,39 +5,35 @@
|
|
5
5
|
# legacy UI.
|
6
6
|
class Operations::Form::Attribute
|
7
7
|
extend Dry::Initializer
|
8
|
-
include Dry::Equalizer(:name, :collection, :
|
9
|
-
include Operations::Inspect.new(:name, :collection, :
|
8
|
+
include Dry::Equalizer(:name, :collection, :model_class, :model_attribute, :form)
|
9
|
+
include Operations::Inspect.new(:name, :collection, :model_class, :model_attribute, :form)
|
10
10
|
|
11
11
|
param :name, type: Operations::Types::Coercible::Symbol
|
12
12
|
option :collection, type: Operations::Types::Bool, default: proc { false }
|
13
|
-
option :model_name,
|
14
|
-
type: (Operations::Types::String | Operations::Types.Instance(Class).constrained(lt: ActiveRecord::Base)).optional,
|
15
|
-
default: proc {}
|
13
|
+
option :model_name, type: (Operations::Types::String | Operations::Types::Class).optional, default: proc {}
|
16
14
|
option :form, type: Operations::Types::Class.optional, default: proc {}
|
17
15
|
|
18
|
-
def
|
19
|
-
@
|
20
|
-
end
|
16
|
+
def model_class
|
17
|
+
return @model_class if defined?(@model_class)
|
21
18
|
|
22
|
-
|
23
|
-
owning_model.human_attribute_name(string_name, options) if model_name
|
19
|
+
@model_class = model_name.is_a?(String) ? model_name.split("#").first.constantize : model_name
|
24
20
|
end
|
25
21
|
|
26
|
-
def
|
27
|
-
@
|
28
|
-
end
|
22
|
+
def model_attribute
|
23
|
+
return @model_attribute if defined?(@model_attribute)
|
29
24
|
|
30
|
-
|
31
|
-
owning_model.localized_attr_name_for(string_name, locale) if model_name
|
25
|
+
@model_attribute = model_class && (model_name.to_s.split("#").second.presence || name.to_s)
|
32
26
|
end
|
33
27
|
|
34
|
-
|
28
|
+
def model_type
|
29
|
+
model_class.type_for_attribute(model_attribute) if model_name
|
30
|
+
end
|
35
31
|
|
36
|
-
def
|
37
|
-
|
32
|
+
def model_human_name(options = {})
|
33
|
+
model_class.human_attribute_name(model_attribute, options) if model_name
|
38
34
|
end
|
39
35
|
|
40
|
-
def
|
41
|
-
|
36
|
+
def model_validators
|
37
|
+
model_name ? model_class.validators_on(model_attribute) : []
|
42
38
|
end
|
43
39
|
end
|
data/lib/operations/form/base.rb
CHANGED
@@ -50,7 +50,13 @@ class Operations::Form::Base
|
|
50
50
|
base.class_attribute :persisted, instance_accessor: false, default: nil
|
51
51
|
|
52
52
|
base.define_method :initialize do |*args, **kwargs|
|
53
|
-
args.empty?
|
53
|
+
if args.empty?
|
54
|
+
# Initializing Operations::Form::Base instance
|
55
|
+
super(kwargs, **{})
|
56
|
+
else
|
57
|
+
# Initializing Operations::Form instance as form object (deprecated)
|
58
|
+
super(*args, **kwargs)
|
59
|
+
end
|
54
60
|
end
|
55
61
|
end
|
56
62
|
|
@@ -83,12 +89,13 @@ class Operations::Form::Base
|
|
83
89
|
|
84
90
|
# :nodoc:
|
85
91
|
module InstanceMethods
|
86
|
-
|
87
|
-
|
92
|
+
# Copied from globalize-accessors, should be deprecated and removed as it is not a core method
|
93
|
+
def localized_attr_name_for(attr_name, locale)
|
94
|
+
"#{attr_name}_#{locale.to_s.underscore}"
|
88
95
|
end
|
89
96
|
|
90
|
-
def
|
91
|
-
self.class.attributes[name.to_sym].
|
97
|
+
def type_for_attribute(name)
|
98
|
+
self.class.attributes[name.to_sym].model_type
|
92
99
|
end
|
93
100
|
|
94
101
|
def has_attribute?(name) # rubocop:disable Naming/PredicateName
|
data/lib/operations/form.rb
CHANGED
@@ -21,8 +21,10 @@
|
|
21
21
|
#
|
22
22
|
class Operations::Form
|
23
23
|
include Dry::Core::Constants
|
24
|
-
include Dry::Equalizer(:command, :model_map, :persisted,
|
25
|
-
|
24
|
+
include Dry::Equalizer(:command, :model_map, :persisted,
|
25
|
+
:params_transformations, :hydrators, :hydration_merge_params, :form_class)
|
26
|
+
include Operations::Inspect.new(:model_name, :model_map, :persisted,
|
27
|
+
:params_transformations, :hydrators, :hydration_merge_params, :form_class)
|
26
28
|
|
27
29
|
# We need to make deprecated inheritance from Operations::Form act exactly the
|
28
30
|
# same way as from Operations::Form::Base. In order to do this, we are encapsulating all the
|
@@ -51,10 +53,17 @@ class Operations::Form
|
|
51
53
|
option :persisted, type: Operations::Types::Bool, default: proc { true }
|
52
54
|
option :params_transformations, type: Operations::Types::Coercible::Array.of(Operations::Types.Interface(:call)),
|
53
55
|
default: proc { [] }
|
54
|
-
option :
|
56
|
+
option :hydrators, type: Operations::Types::Array.of(Operations::Types.Interface(:call)), default: proc { [] }
|
57
|
+
option :hydration_merge_params, type: Operations::Types::Bool, default: proc { true }
|
55
58
|
option :base_class, type: Operations::Types::Class, default: proc { ::Operations::Form::Base }
|
56
59
|
end)
|
57
60
|
|
61
|
+
def initialize(command, hydrator: nil, hydrators: [], **options)
|
62
|
+
hydrators.push(hydrator) if hydrator.present?
|
63
|
+
|
64
|
+
super(command, hydrators: hydrators, **options)
|
65
|
+
end
|
66
|
+
|
58
67
|
def build(params = EMPTY_HASH, **context)
|
59
68
|
instantiate_form(command.callable(transform_params(params, **context), **context))
|
60
69
|
end
|
@@ -81,12 +90,20 @@ class Operations::Form
|
|
81
90
|
|
82
91
|
def instantiate_form(operation_result)
|
83
92
|
form_class.new(
|
84
|
-
|
93
|
+
hydrate_params(form_class, operation_result.params, **operation_result.context),
|
85
94
|
messages: operation_result.errors.to_h,
|
86
95
|
operation_result: operation_result
|
87
96
|
)
|
88
97
|
end
|
89
98
|
|
99
|
+
def hydrate_params(form_class, params, **context)
|
100
|
+
hydrated_params = hydrators.inject({}) do |value, hydrator|
|
101
|
+
value.merge(hydrator.call(form_class, params, **context).deep_symbolize_keys)
|
102
|
+
end
|
103
|
+
hydrated_params.deep_merge!(params) if hydration_merge_params
|
104
|
+
hydrated_params
|
105
|
+
end
|
106
|
+
|
90
107
|
def key_map
|
91
108
|
@key_map ||= command.contract.schema.key_map
|
92
109
|
end
|
data/lib/operations/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: operations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arkadiy Zabazhanov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-08-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: appraisal
|