Skip to content

Commit

Permalink
Dedupe and simplify logic for merging pass-through update expression …
Browse files Browse the repository at this point in the history
…opts
  • Loading branch information
lsglick committed Oct 17, 2023
1 parent 82f6951 commit 888e5bf
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 69 deletions.
67 changes: 24 additions & 43 deletions lib/aws-record/record/item_operations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -274,28 +274,15 @@ def _perform_save(opts)
key: key_values
}
update_pairs = _dirty_changes_for_update
update_tuple = self.class.send(
update_expression_opts = self.class.send(
:_build_update_expression,
update_pairs
)
if update_tuple
if opts.include?(:update_expression)
raise Errors::UpdateExpressionCollision,
'Attributes need to be saved before custom update expression can be used.'
end
uex, exp_attr_names, exp_attr_values = update_tuple
update_opts[:update_expression] = uex
# need to combine expression attribute names and values
update_opts[:expression_attribute_names] = [
exp_attr_names,
opts[:expression_attribute_names]
].compact.reduce(&:merge)

update_opts[:expression_attribute_values] = [
exp_attr_values,
opts[:expression_attribute_values]
].compact.reduce(&:merge)
end
opts = self.class.send(
:_merge_update_expression_opts,
update_expression_opts,
opts
)
resp = dynamodb_client.update_item(opts.merge(update_opts))
assign_attributes(resp[:attributes]) if resp[:attributes]
end
Expand Down Expand Up @@ -613,25 +600,8 @@ def update(new_params, opts = {})
table_name: table_name,
key: key
}
update_tuple = _build_update_expression(new_params)
unless update_tuple.nil?
if opts.include?(:update_expression)
raise Errors::UpdateExpressionCollision,
'Using custom update expression with attribute updates is not currently supported.'
end
uex, exp_attr_names, exp_attr_values = update_tuple
update_opts[:update_expression] = uex
# need to combine expression attribute names and values
update_opts[:expression_attribute_names] = [
exp_attr_names,
opts[:expression_attribute_names]
].compact.reduce(&:merge)

update_opts[:expression_attribute_values] = [
exp_attr_values,
opts[:expression_attribute_values]
].compact.reduce(&:merge)
end
update_expression_opts = _build_update_expression(new_params)
opts = _merge_update_expression_opts(update_expression_opts, opts)
dynamodb_client.update_item(opts.merge(update_opts))
end

Expand Down Expand Up @@ -663,11 +633,22 @@ def _build_update_expression(attr_value_pairs)
update_expressions = []
update_expressions << ("SET #{set_expressions.join(', ')}") unless set_expressions.empty?
update_expressions << ("REMOVE #{remove_expressions.join(', ')}") unless remove_expressions.empty?
if update_expressions.empty?
nil
else
exp_attr_values = nil if exp_attr_values.empty?
[update_expressions.join(' '), exp_attr_names, exp_attr_values]
{
update_expression: update_expressions.join(' '),
expression_attribute_names: exp_attr_names,
expression_attribute_values: exp_attr_values
}.reject { |_, value| value.nil? || value.empty? }
end

def _merge_update_expression_opts(update_expression_opts, pass_through_opts)
update_expression_opts.merge(pass_through_opts) do |key, expression_value, pass_through_value|
case key
when :update_expression
msg = 'Using pass-through update expression with attribute updates is not currently supported.'
raise Errors::UpdateExpressionCollision, msg
else
expression_value.merge(pass_through_value)
end
end
end

Expand Down
31 changes: 6 additions & 25 deletions lib/aws-record/record/transactions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -286,34 +286,15 @@ def _transform_update_record(update_record, opts)
opts[:table_name] = update_record.class.table_name
opts[:key] = update_record.send(:key_values)
dirty_changes = update_record.send(:_dirty_changes_for_update)
update_tuple = update_record.class.send(
update_expression_opts = update_record.class.send(
:_build_update_expression,
dirty_changes
)
if update_tuple
if opts.include?(:update_expression)
raise Errors::UpdateExpressionCollision,
'Transactional write includes updated attributes, yet an' \
'update expression was also provided. This is not ' \
'currently supported. You should rewrite this case to ' \
'add any attribute updates to your own update ' \
"expression if desired.\n" \
"\tItem: #{JSON.pretty_unparse(update_record.to_h)}\n" \
"\tExtra Options: #{JSON.pretty_unparse(opts)}"
end
uex, exp_attr_names, exp_attr_values = update_tuple
opts[:update_expression] = uex
# need to combine expression attribute names and values
opts[:expression_attribute_names] = [
exp_attr_names,
opts[:expression_attribute_names]
].compact.reduce(&:merge)

opts[:expression_attribute_values] = [
exp_attr_values,
opts[:expression_attribute_values]
].compact.reduce(&:merge)
end
opts = update_record.class.send(
:_merge_update_expression_opts,
update_expression_opts,
opts
)
{ update: opts }
end

Expand Down
1 change: 0 additions & 1 deletion spec/aws-record/record/item_operations_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,6 @@ module Record
expression_attribute_names: {
'#UE_A' => 'body'
},
expression_attribute_values: nil
}
]
)
Expand Down

0 comments on commit 888e5bf

Please sign in to comment.