Skip to content

Commit

Permalink
Merge pull request #30 from DNNX/support-update-only-in-collection-as…
Browse files Browse the repository at this point in the history
…sociations

Add support for `update_only` option to nested attributes of collections
  • Loading branch information
pyromaniac committed Nov 2, 2016
2 parents d5cb2c5 + b94766c commit ac7fdcf
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 9 deletions.
3 changes: 2 additions & 1 deletion lib/active_data.rb
Expand Up @@ -96,11 +96,12 @@ def self.config
end
end
typecaster('BigDecimal') do |value|
next unless value
begin
::BigDecimal.new Float(value).to_s
rescue
nil
end if value
end
end
typecaster('Float') do |value|
begin
Expand Down
10 changes: 5 additions & 5 deletions lib/active_data/model/associations/nested_attributes.rb
Expand Up @@ -52,7 +52,7 @@ def self.assign_nested_attributes_for_one_to_one_association(object, association
assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy]) unless call_reject_if(object, association_name, attributes)
elsif attributes[primary_attribute_name].present?
raise ActiveData::ObjectNotFound.new(object, association_name, attributes[primary_attribute_name])
elsif !reject_new_object?(object, association_name, attributes)
elsif !reject_new_object?(object, association_name, attributes, options)
assignable_attributes = attributes.except(*unassignable_keys(object))

if existing_record && !existing_record.persisted?
Expand Down Expand Up @@ -90,7 +90,7 @@ def self.assign_nested_attributes_for_collection_association(object, association
attributes = attributes.with_indifferent_access

if attributes[primary_attribute_name].blank?
unless reject_new_object?(object, association_name, attributes)
unless reject_new_object?(object, association_name, attributes, options)
association.build(attributes.except(*unassignable_keys(object)))
end
else
Expand All @@ -104,7 +104,7 @@ def self.assign_nested_attributes_for_collection_association(object, association
assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
end
elsif association.reflection.embedded?
unless reject_new_object?(object, association_name, attributes)
unless reject_new_object?(object, association_name, attributes, options)
association.reflection.klass.with_sanitize(false) do
association.build(attributes.except(DESTROY_ATTRIBUTE))
end
Expand Down Expand Up @@ -142,8 +142,8 @@ def self.destroy_flag?(hash)
ActiveData.typecaster(Boolean).call(hash[DESTROY_ATTRIBUTE])
end

def self.reject_new_object?(object, association_name, attributes)
destroy_flag?(attributes) || call_reject_if(object, association_name, attributes)
def self.reject_new_object?(object, association_name, attributes, options)
options[:update_only] || destroy_flag?(attributes) || call_reject_if(object, association_name, attributes)
end

def self.call_reject_if(object, association_name, attributes)
Expand Down
8 changes: 5 additions & 3 deletions lib/active_data/model/scopes.rb
Expand Up @@ -23,9 +23,11 @@ def self.for(model)
def initialize(source = nil, trust = false)
source ||= self.class.superclass.new

source.each do |entity|
raise AssociationTypeMismatch.new(self.class._scope_model, entity.class) unless entity.is_a?(self.class._scope_model)
end unless trust && source.is_a?(self.class)
unless trust && source.is_a?(self.class)
source.each do |entity|
raise AssociationTypeMismatch.new(self.class._scope_model, entity.class) unless entity.is_a?(self.class._scope_model)
end
end

super source
end
Expand Down
24 changes: 24 additions & 0 deletions spec/lib/active_data/model/nested_attributes.rb
Expand Up @@ -257,6 +257,30 @@
.to change { user.projects.map(&:title) }.to(['Project 2'])
end
end

context ':update_only' do
before { User.accepts_nested_attributes_for :projects, update_only: true }

specify do
expect do
user.projects_attributes = [
{ slug: projects.first.slug.to_i, title: 'Project 3' },
{ title: 'Project 4' }
]
end
.to change { user.projects.map(&:title) }.to(['Project 3', 'Project 2'])
end

specify do
expect do
user.projects_attributes = [
{ slug: projects.last.slug.to_i, title: 'Project 3' },
{ slug: projects.first.slug.to_i.pred, title: 'Project 0' }
]
end
.to change { user.projects.map(&:title) }.to(['Project 1', 'Project 3'])
end
end
end

context 'primary absence causes exception' do
Expand Down

0 comments on commit ac7fdcf

Please sign in to comment.