Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix includes with has_one associations when no associated record #83

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lib/active_force/association/relation_model_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ def call

class BuildFromArray < AbstractBuildFrom
def call
value.map { |mash| association.build(mash, association_mapping) }
if association.is_a?(HasOneAssociation)
association.build(value.first, association_mapping)
else
value.map { |mash| association.build(mash, association_mapping) }
end
end
end

Expand Down
31 changes: 20 additions & 11 deletions lib/active_force/sobject.rb
Original file line number Diff line number Diff line change
Expand Up @@ -191,18 +191,12 @@ def reload
self
end

def write_value key, value, association_mapping = {}
if association = self.class.find_association(key.to_sym)
field = association.relation_name
value = Association::RelationModelBuilder.build(association, value, association_mapping)
elsif key.to_sym.in?(mappings.keys)
# key is a field name
field = key
def write_value(key, value, association_mapping = {})
if (association = self.class.find_association(key.to_sym))
write_association_value(association, value, association_mapping)
else
# Assume key is an SFDC column
field = mappings.key(key)
write_field_value(key, value)
end
send "#{field}=", value if field && respond_to?(field)
end

def [](name)
Expand All @@ -213,7 +207,7 @@ def []=(name,value)
send("#{name.to_sym}=", value)
end

private
private

def validate!
unless valid?
Expand All @@ -223,6 +217,21 @@ def validate!
end
end

def write_association_value(association, value, association_mapping)
association_cache[association.relation_name] = Association::RelationModelBuilder.build(association, value,
association_mapping)
end

def write_field_value(field_key, value)
field = if mappings.key?(field_key.to_sym)
field_key
else
mappings.key(field_key)
end

send("#{field}=", value) if field && respond_to?(field)
end

def handle_save_error error
return false if error.class == RecordInvalid
logger_output __method__, error, attributes
Expand Down
30 changes: 30 additions & 0 deletions spec/active_force/association/relation_model_builder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,36 @@ module Association
end
end

context 'with a restforce collection value' do
let(:value) do
build_restforce_collection([
build_restforce_sobject('Id' => 'first'),
build_restforce_sobject('Id' => 'second')
])
end

it 'returns a child for the first value' do
actual = instance.build_relation_model
expect(actual).to be_a(HasOneChild)
expect(actual.id).to eq('first')
end
end

context 'with an array value' do
let(:value) do
[
build_restforce_sobject('Id' => 'first'),
build_restforce_sobject('Id' => 'second')
]
end

it 'returns a child for the first value' do
actual = instance.build_relation_model
expect(actual).to be_a(HasOneChild)
expect(actual.id).to eq('first')
end
end

context 'without a value' do
let(:value){ nil }

Expand Down
39 changes: 39 additions & 0 deletions spec/active_force/sobject/includes_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,45 @@ module ActiveForce
end
end

context 'when query returns nil for associated record' do
let(:response) do
[build_restforce_sobject({ 'Id' => '123', 'Membership__r' => nil })]
end

before do
allow(client).to receive(:query).and_return(response)
end

it 'the association method returns nil without making another request' do
member = ClubMember.includes(:membership).where(id: '123').first
membership = member.membership
expect(membership).to be_nil
expect(client).to have_received(:query).once
end
end
end

context 'when query returns an associated record' do
let(:response) do
[
build_restforce_sobject(
{
'Id' => '123',
'Membership__r' => build_restforce_collection([build_restforce_sobject({ 'Id' => '33' })])
}
)
]
end

before do
allow(client).to receive(:query).and_return(response)
end

it 'the association method returns the record without making another request' do
member = ClubMember.includes(:membership).where(id: '123').first
expect(member.membership.id).to eq('33')
expect(client).to have_received(:query).once
end
end

context 'when invalid associations are passed' do
Expand Down