Skip to content

Commit

Permalink
Allow myltiple hydrators on form
Browse files Browse the repository at this point in the history
  • Loading branch information
pyromaniac committed Aug 6, 2024
1 parent 4f501c6 commit 848209e
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 14 deletions.
8 changes: 4 additions & 4 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2024-05-05 08:51:48 UTC using RuboCop version 1.59.0.
# on 2024-08-06 04:56:51 UTC using RuboCop version 1.65.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
Expand All @@ -22,14 +22,14 @@ Metrics/AbcSize:
# Offense count: 1
# Configuration parameters: CountComments, CountAsOne.
Metrics/ClassLength:
Max: 145
Max: 149

# Offense count: 1
# Configuration parameters: CountComments, CountAsOne.
Metrics/ModuleLength:
Max: 142
Max: 140

# Offense count: 2
# Offense count: 3
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
Metrics/ParameterLists:
Max: 7
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## [0.7.1](https://github.com/BookingSync/operations/tree/main)

### Added

- Allow passing multiple `hydrators:` to Operations::Form [\#49](https://github.com/BookingSync/operations/pull/49) ([pyromaniac](https://github.com/pyromaniac))

## [0.7.1](https://github.com/BookingSync/operations/tree/v0.7.1)

### Added
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -904,7 +904,7 @@ class Post::Update
def self.default_form
@default_form ||= Operations::Form.new(
default,
hydrator: Post::Update::Hydrator.new
hydrators: [Post::Update::Hydrator.new]
)
end
end
Expand All @@ -929,7 +929,7 @@ class Post::Update
@default_form ||= Operations::Form.new(
default,
model_map: Post::Update::ModelMap.new,
hydrator: Post::Update::Hydrator.new
hydrators: [Post::Update::Hydrator.new]
)
end
end
Expand Down
2 changes: 1 addition & 1 deletion UPGRADING_FORMS.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Post::Update
def self.default_form
@default_form ||= Operations::Form.new(
default,
hydrator: Post::Update::Hydrator.new,
hydrators: [Post::Update::Hydrator.new],
model_map: Post::Update::ModelMap.new,
params_transformations: [
ParamsMap.new(id: :post_id)
Expand Down
5 changes: 5 additions & 0 deletions lib/operations/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ def initialize(
result_policies = policies_sum - [Undefined] unless policies_sum == [Undefined, Undefined]
options[:policies] = result_policies if result_policies

if after.present?
ActiveSupport::Deprecation.new.warn("Operations::Command `after:` option is deprecated and will be " \
"removed in 1.0.0. Please use `on_success:` instead")
end

preconditions.push(precondition) if precondition.present?
super(operation, preconditions: preconditions, on_success: after, **options)
end
Expand Down
25 changes: 21 additions & 4 deletions lib/operations/form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
#
class Operations::Form
include Dry::Core::Constants
include Dry::Equalizer(:command, :model_map, :persisted, :params_transformations, :hydrator, :form_class)
include Operations::Inspect.new(:model_name, :model_map, :persisted, :params_transformations, :hydrator, :form_class)
include Dry::Equalizer(:command, :model_map, :persisted,
:params_transformations, :hydrators, :hydration_merge_params, :form_class)
include Operations::Inspect.new(:model_name, :model_map, :persisted,
:params_transformations, :hydrators, :hydration_merge_params, :form_class)

# We need to make deprecated inheritance from Operations::Form act exactly the
# same way as from Operations::Form::Base. In order to do this, we are encapsulating all the
Expand Down Expand Up @@ -51,10 +53,17 @@ def self.inherited(subclass)
option :persisted, type: Operations::Types::Bool, default: proc { true }
option :params_transformations, type: Operations::Types::Coercible::Array.of(Operations::Types.Interface(:call)),
default: proc { [] }
option :hydrator, type: Operations::Types.Interface(:call).optional, default: proc {}
option :hydrators, type: Operations::Types::Array.of(Operations::Types.Interface(:call)), default: proc { [] }
option :hydration_merge_params, type: Operations::Types::Bool, default: proc { true }
option :base_class, type: Operations::Types::Class, default: proc { ::Operations::Form::Base }
end)

def initialize(command, hydrator: nil, hydrators: [], **options)
hydrators.push(hydrator) if hydrator.present?

super(command, hydrators: hydrators, **options)
end

def build(params = EMPTY_HASH, **context)
instantiate_form(command.callable(transform_params(params, **context), **context))
end
Expand All @@ -81,12 +90,20 @@ def transform_params(params, **context)

def instantiate_form(operation_result)
form_class.new(
hydrator&.call(form_class, operation_result.params, **operation_result.context) || {},
hydrate_params(form_class, operation_result.params, **operation_result.context),
messages: operation_result.errors.to_h,
operation_result: operation_result
)
end

def hydrate_params(form_class, params, **context)
hydrated_params = hydrators.inject({}) do |value, hydrator|
value.merge(hydrator.call(form_class, params, context).deep_symbolize_keys)
end
hydrated_params.deep_merge!(params) if hydration_merge_params
hydrated_params
end

def key_map
@key_map ||= command.contract.schema.key_map
end
Expand Down
8 changes: 7 additions & 1 deletion lib/operations/form/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,13 @@ def self.extended(base)
base.class_attribute :persisted, instance_accessor: false, default: nil

base.define_method :initialize do |*args, **kwargs|
args.empty? && kwargs.present? ? super(kwargs, **{}) : super(*args, **kwargs)
if args.empty?
# Initializing Operations::Form::Base instance
super(kwargs, **{})
else
# Initializing Operations::Form instance as form object (deprecated)
super(*args, **kwargs)
end
end
end

Expand Down
5 changes: 3 additions & 2 deletions spec/operations/form_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def call(_, **)
let(:default_options) do
{
model_map: proc { |_path| "DummyModel" },
hydrator: proc { |_form_class, params, **_context| { ignored: 42, name: "Batman" }.merge(params) }
hydrators: [proc { |_form_class, _params, **_context| { ignored: 42, name: "Batman" } }]
}
end
let(:options) { default_options }
Expand Down Expand Up @@ -171,7 +171,8 @@ def call(_, **)
model_map=#<Proc:0x>,
persisted=true,
params_transformations=[],
hydrator=#<Proc:0x>,
hydrators=[#<Proc:0x>],
hydration_merge_params=true,
form_class=#<Class
attributes={:entities=>
#<Operations::Form::Attribute
Expand Down

0 comments on commit 848209e

Please sign in to comment.