Skip to content

Commit

Permalink
WIP: use association manipulation iff external associations
Browse files Browse the repository at this point in the history
For #121
  • Loading branch information
chrisandreae committed Jul 8, 2019
1 parent 44cb3f9 commit ec62454
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 12 deletions.
15 changes: 11 additions & 4 deletions lib/view_model/active_record/association_manipulation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,9 @@ def load_associated(association_name, scope: nil, eager_include: true, serialize
def replace_associated(association_name, update_hash, references: {}, deserialize_context: self.class.new_deserialize_context)
association_data = self.class._association_data(association_name)

# TODO: do we need this to be a hard constraint? Is it useful?
# unless association_data.external?
# raise Viewmodel::DeserializationError::InternalAssociationWrite.new(association_name)
# end
unless association_data.external?
raise ViewModel::DeserializationError::InternalAssociationWrite.new(association_name, self.to_reference)
end

if association_data.referenced?
is_fupdate =
Expand Down Expand Up @@ -110,6 +109,10 @@ def append_associated(association_name, subtree_hash_or_hashes, references: {},
direct_reflection = association_data.direct_reflection
raise ArgumentError.new("Cannot append to single association '#{association_name}'") unless association_data.collection?

unless association_data.external?
raise ViewModel::DeserializationError::InternalAssociationWrite.new(association_name, self.to_reference)
end

ViewModel::Utils.wrap_one_or_many(subtree_hash_or_hashes) do |subtree_hashes|
model_class.transaction do
ViewModel::Callbacks.wrap_deserialize(self, deserialize_context: deserialize_context) do |hook_control|
Expand Down Expand Up @@ -223,6 +226,10 @@ def delete_associated(association_name, associated_id, type: nil, deserialize_co
association_data = self.class._association_data(association_name)
direct_reflection = association_data.direct_reflection

unless association_data.external?
raise ViewModel::DeserializationError::InternalAssociationWrite.new(association_name, self.to_reference)
end

unless association_data.collection?
raise ArgumentError.new("Cannot remove element from single association '#{association_name}'")
end
Expand Down
10 changes: 5 additions & 5 deletions lib/view_model/active_record/update_data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -680,11 +680,11 @@ def parse(hash_data, valid_reference_keys)
when AssociationData
association_data = member_data

# TODO: is this a desirable constraint? If so, this implementation
# won't work, because replace_associated uses this update machinery
# if association_data.external?
# raise ViewModel::DeserializationError::ExternalAssociationWrite.new(name)
# end
# FIXME: replace_associated uses this update machinery, this won't work
# until we mark it.
if association_data.external?
raise ViewModel::DeserializationError::ExternalAssociationWrite.new(name)
end

case
when value.nil?
Expand Down
3 changes: 0 additions & 3 deletions lib/view_model/deserialization_error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,6 @@ def meta
end
end

# FIXME: these two errors aren't used, because we haven't decided if it's a
# useful constraint. Use or remove before merging.

# Attempted to write to an external association during a deserialization
class ExternalAssociationWrite < InvalidRequest
attr_reader :association
Expand Down
4 changes: 4 additions & 0 deletions test/unit/view_model/active_record/has_many_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,10 @@ def new_model
end

describe 'with association manipulation' do
def subject_association_features
super.merge(external: true)
end

it 'appends a child' do
view = create_viewmodel!

Expand Down

0 comments on commit ec62454

Please sign in to comment.