Skip to content

Commit

Permalink
Merge pull request #197 from iknow/visit-children-in-declaration-order
Browse files Browse the repository at this point in the history
Visit children in declaration order
  • Loading branch information
chrisandreae authored Dec 1, 2023
2 parents 49d72d9 + 3e349d8 commit 65edd06
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 10 deletions.
2 changes: 1 addition & 1 deletion lib/iknow_view_models/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module IknowViewModels
VERSION = '3.7.5'
VERSION = '3.7.6'
end
29 changes: 20 additions & 9 deletions lib/view_model/active_record/update_operation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,15 @@ def run!(deserialize_context:)
viewmodel._list_attribute = reposition_to
end

# Visit attributes and associations as much as possible in the order
# that they're declared in the view.
member_ordering = viewmodel.class._members.keys.each_with_index.to_h

# update user-specified attributes
valid_members = viewmodel.class._members.keys.map(&:to_s).to_set
bad_keys = attributes.keys.reject { |k| valid_members.include?(k) }
if bad_keys.present?
causes = bad_keys.map { |k| ViewModel::DeserializationError::UnknownAttribute.new(k, blame_reference) }
raise ViewModel::DeserializationError::Collection.for_errors(causes)
end
attribute_keys = attributes.keys.sort_by { |k| member_ordering[k] }
attribute_keys.each do |attr_name|
serialized_value = attributes[attr_name]

attributes.each do |attr_name, serialized_value|
# Note that the VM::AR deserialization tree asserts ownership over any
# references it's provided, and so they're intentionally not passed on
# to attribute deserialization for use by their `using:` viewmodels. A
Expand All @@ -101,7 +101,13 @@ def run!(deserialize_context:)
end

# Update points-to associations before save
points_to.each do |association_data, child_operation|
points_to_keys = points_to.keys.sort_by do |association_data|
member_ordering[association_data.association_name]
end

points_to_keys.each do |association_data|
child_operation = points_to[association_data]

reflection = association_data.direct_reflection
debug "-> #{debug_name}: Updating points-to association '#{reflection.name}'"

Expand Down Expand Up @@ -138,7 +144,12 @@ def run!(deserialize_context:)

# Update association cache of pointed-from associations after save: the
# child update will have saved the pointer.
pointed_to.each do |association_data, child_operation|
pointed_to_keys = pointed_to.keys.sort_by do |association_data|
member_ordering[association_data.association_name]
end

pointed_to_keys.each do |association_data|
child_operation = pointed_to[association_data]
reflection = association_data.direct_reflection

debug "-> #{debug_name}: Updating pointed-to association '#{reflection.name}'"
Expand Down

0 comments on commit 65edd06

Please sign in to comment.