# Inconsistency between association and send(method)

**URL:** <https://www.ruby-forum.com/t/inconsistency-between-association-and-send-method/145612>\
**Category:** Rails\
**Created:** [August 12, 2008, 3:43am UTC](https://www.ruby-forum.com/t/inconsistency-between-association-and-send-method/145612 "2008-08-12T03:43:43Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![pkoebbe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ec9cab/32.png) [@pkoebbe](https://www.ruby-forum.com/u/pkoebbe)\
**Post date:** [August 12, 2008, 3:43am UTC](https://www.ruby-forum.com/t/inconsistency-between-association-and-send-method/145612/1 "2008-08-12T03:43:43Z")

</div>

I’m working on a generic method to display conflicting values when there  
is a concurrency violation using the optimistic locking mechanism in  
Rails (lock\_version and StaleObjectError). When a user submits a form  
and there is a concurrency clash, I want to display the “new”,  
conflicting values next to the values in the form. In my model’s persist  
method, I trap the StaleObjectError and populate what I call the  
conflicting object. As a simple example, consider a Person model:

def Person.persist(params)  
conflicting\_person = nil

person = Person.find\_by\_id(params[:person][:id])

begin  
person.save  
rescue ActiveRecord::StaleObjectError  
conflicting\_person = Person.find\_by\_id(person.id)  
end

return person, conflicting\_person  
end

In the controller, I test the return value of conflicting\_person and  
decide what to do. If not nil, it gets assigned to an instance variable  
and I render the form again. The partial includes code such as:

div.label do  
\_ ‘First Name:’  
end

div.data do  
f.text\_field :first\_name  
end

\_! conflicting\_data(@person, @conflicting\_person, :first\_name)

div.clearer

and conflicting\_data is a helper defined as

def conflicting\_data(current\_obj, conflicting\_obj, attribute)  
if conflicting\_obj  
if conflicting[attribute] != current[attribute]  
conflicting\_value = conflicting[attribute] # abbreviated for  
simplicity  
“

#{conflicting\_value}
”  
end  
end  
end

Suppose users A and B both query person John D… User A changes the  
first name to ‘Johnathon’ and saves. User B changes first name to ‘Jack’  
and tries to save. A message about concurrency will be displayed to User  
B and next to the first name field ‘Johnathon’ will be display so the  
user can see what values are different.

When working with an object’s immediate attributes, this is working out  
very well. But I am having some difficulty when comparing nested  
attributes. When there are concurrency clashes on Person attributes  
(first\_name, last\_name, date\_of\_birth, etc), I am having no problems.  
But a Person belongs to a ZipCode, and I am having problems with  
conficting data in the ZipCodes. I made the following changes in an  
attempt to get down one more level.

In the Person.persist method, I figured I should include the ZipCode  
when finding the conflicting\_person:

begin  
person.save  
rescue ActiveRecord::StaleObjectError  
conflicting\_person = Person.find\_by\_id(person.id, :include =\>  
:zip\_code)  
end

I also changed the finder earlier in Person.persist that finds the  
person object that is going to be updated. The result is when person and  
conflicting\_person are returned at the end of Person.persist, both  
should have associated zip\_code data with them and not need to query the  
database. I then changed conflicting\_data to be

def conflicting\_data(current\_obj, conflicting\_obj, attribute, nested\_obj  
= nil)  
if conflicting\_obj  
current = nested\_obj ? current\_obj.send(nested\_obj) : current\_obj  
conflicting = nested\_obj ? conflicting\_obj.send(nested\_obj) :  
conflicting\_obj

```
if conflicting[attribute] != current[attribute]
  conflicting_value = conflicting[attribute] # abbreviated for

```

simplicity  
“

#{conflicting\_value}
”  
end  
end  
end

and it gets called like

conflicting\_data(@person, @conflicting\_person, :code, :zip\_code)

This way, if there is no nested object, the immediate attribute of the  
object is used, but when I pass in a nested object, the attribute of the  
nested object is used. Functionally, the code works. The problem I’m  
having is that when I do the two sends to get the nested objects of  
current\_obj and conflicting\_obj, they are the same thing because the  
current one ends up getting the zip code of the conflicting one. Using  
the debugger, I have inspected current\_obj and conflicting\_obj and  
verified that they have different values for zip\_code\_id, but when the  
send methods complete, current and conflicting represent the same  
ZipCode.

p current\_obj.zip\_code\_id  
=\> 27754  
p current\_obj.send(:zip\_code).id  
=\> 27805  
p conflicting\_obj.zip\_code\_id  
=\> 27805  
p conflicting\_obj.send(:zip\_code).id  
=\> 27805

I would very much appreciate some insight into why this is happening.  
Thanks.

Peace,  
Phillip

---

<div class="post-metadata">

**Author:** ![pkoebbe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ec9cab/32.png) [@pkoebbe](https://www.ruby-forum.com/u/pkoebbe)\
**Post date:** [August 12, 2008, 6:26pm UTC](https://www.ruby-forum.com/t/inconsistency-between-association-and-send-method/145612/2 "2008-08-12T18:26:39Z")

</div>

Phillip K. wrote:

> In the Person.persist method, I figured I should include the ZipCode  
> when finding the conflicting\_person:

I guess I figured wrong. I did a little experimenting in script/console  
and discovered that if you load an association, then change the  
foreign\_key, the association is not refreshed until you save and reload  
the object. For instance:

p = Person.find(2)  
=\>   
p.zip\_code\_id  
=\> 27805  
p.zip\_code.city  
=\> ‘Springfield’  
p.zip\_code\_id = 27754  
=\> 27754  
p.zip\_code.city  
=\> ‘Springfield’  
p.save  
=\> true  
p.zip\_code\_city  
=\> ‘Springfield’  
p.reload  
=\>   
p.zip\_code.city  
=\> ‘Carlinville’

The first reference to an attribute of the zip\_code object  
(zip\_code.city) loads the association into memory. On the other hand, if  
I were to change the foreign\_key first, it would be okay:

p = Person.find(2)  
=\>   
p.zip\_code\_id  
=\> 27805  
p.zip\_code\_id = 27754  
=\> 27754  
p.zip\_code.city  
=\> ‘Carlinville’

The end result is that I fixed my original problem by _not_ including  
zip\_code when finding person and conflicting\_person in Person.persist.  
I do, however, have another problem, but I will put that in another  
thread.

Peace,  
Phillip
