# Question about setting field values for a belongs\_to model

**URL:** <https://www.ruby-forum.com/t/question-about-setting-field-values-for-a-belongs-to-model/96814>\
**Category:** Rails\
**Created:** [July 2, 2006, 8:38am UTC](https://www.ruby-forum.com/t/question-about-setting-field-values-for-a-belongs-to-model/96814 "2006-07-02T08:38:09Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![stephanwehner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/0ea827/32.png) [@stephanwehner](https://www.ruby-forum.com/u/stephanwehner)\
**Post date:** [July 2, 2006, 8:38am UTC](https://www.ruby-forum.com/t/question-about-setting-field-values-for-a-belongs-to-model/96814/1 "2006-07-02T08:38:09Z")

</div>

I have two tables, applicants, and skills where each applicant  
“has\_many” skills, and each skill “belongs\_to” an applicant.

When I have a reference to an applicant and a (skill) id for one of  
their skills, I thought to update their skills by using

@applicant.skills.find(id\_of\_skill).description = ‘new description’

# even adding @applicant.skills.find(id\_of\_skill).save here doesn’t help

…other processing  
@applicant.save

This sounds to me like it should lead to the description of the skill  
being updated in the database, and indeed an update statement is in the  
log, but with the original value. The description of the skill is not  
updated in the database.

Instead, this works

@applicant.skills.find(id\_of\_skill).update\_attributes(:description =\>  
‘new description’)  
…other processing  
@applicant.save

So somewhere my intuition is wrong. How should I think about this? Why  
does the straightforward statement not work?

Code to pour over is below. This is on ruby 1.8.4 (2005-12-24)  
[i386-linux] / Rails 1.1.2

Thanks,

Stephan

* * *

Following are

1. mysql table definitions
2. method update in ApplicantController
3. rhtml file, app/views/applicant/edit.rhtml
4. Applicant and Skill models

create table if not exists applicants (  
id int not null auto\_increment,  
name varchar(20) not null,  
primary key(id),  
unique index uniq\_index(id)  
);

create table if not exists skills (  
id int not null auto\_increment,  
applicant\_id int not null,  
description varchar(30) not null,  
primary key(id),  
unique index uniq\_index(id)  
);

class ApplicantController \< ApplicationController  
:  
: methods generated by scaffold  
:

def update  
@applicant = Applicant.find(params[:id])  
@applicant.attributes=params[:applicant]

```
if !params[:newskill][:description].blank?
  @applicant.skills << Skill.new(params[:newskill])
end
if params[:skill]
  params[:skill].each do |skillid, newdescription|
  @applicant.skills.find(skillid.to_i).update_attributes(

```

:description=\> newdescription )  
#  
# The following two lines do not work, but they don’t crash either  
# The log file shows update statements to the skill table  
# but with the original values, not the new values  
#  
# @applicant.skills.find(skillid.to\_i).description =  
newdescription  
# @applicant.skills.find(skillid.to\_i).save  
end  
end  
if params[:deleteskill]  
params[:deleteskill].each do |id, todelete|  
if todelete == “1”  
@applicant.skills.find(id).destroy  
end  
end  
end  
if (@applicant.save)  
flash[:notice] = ‘Applicant was successfully updated.’  
redirect\_to :action =\> ‘show’, :id =\> @applicant  
else  
render :action =\> ‘edit’  
end  
end

:  
: other ApplicantController methods defined by scaffold  
:

File app/views/applicant/edit.rhtml

# Editing applicant

\<%= start\_form\_tag :action =\> ‘update’, :id =\> @applicant %\>  
\<%= render :partial =\> ‘form’ %\>

\<% if @applicant.skills.length \> 0 %\>

Skills:  
\<% for skill in @applicant.skills %\>  
Delete? \<%= check\_box :deleteskill, skill.id %\>  
Change? \<%= text\_field :skill, skill.id.to\_s, :size=\>20,  
:value=\>skill.description %\>   
  
\<% end %\>  
\<% end %\>  
Add skill? \<%= text\_field :newskill, :description, :size=\>20 %\>  
  
\<%= submit\_tag ‘Edit’ %\>  
\<%= end\_form\_tag %\>

\<%= link\_to ‘Show’, :action =\> ‘show’, :id =\> @applicant %\> |  
\<%= link\_to ‘Back’, :action =\> ‘list’ %\>

The two models:

class Applicant \< ActiveRecord::Base  
has\_many :skills, :dependent =\> :destroy

end  
class Skill \< ActiveRecord::Base  
belongs\_to :applicant  
end

---

<div class="post-metadata">

**Author:** ![stephanwehner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/0ea827/32.png) [@stephanwehner](https://www.ruby-forum.com/u/stephanwehner)\
**Post date:** [July 2, 2006, 8:49am UTC](https://www.ruby-forum.com/t/question-about-setting-field-values-for-a-belongs-to-model/96814/2 "2006-07-02T08:49:28Z")

</div>

If you directly manipulate the associated object, the parent object will  
become stale since the data it tracks is recorded inside the @applicant  
object.

Try “@applicant.reload” after updating an associated record.

Also, why are you doing this?

@applicant.skills.find(id\_of\_skill).update\_attributes(…)

As long as you have the id of the skill why not call it on the Skill  
clas directly?

Skill.find(id\_of\_skill).update\_attributes(…)

If you do this before creating the @applicant object you wont need ot  
call reload at all.

---

<div class="post-metadata">

**Author:** ![stephanwehner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/0ea827/32.png) [@stephanwehner](https://www.ruby-forum.com/u/stephanwehner)\
**Post date:** [July 2, 2006, 6:17pm UTC](https://www.ruby-forum.com/t/question-about-setting-field-values-for-a-belongs-to-model/96814/3 "2006-07-02T18:17:13Z")

</div>

Ok, thanks a lot, Alex. Why does the database get updated  
when using “update\_attributes” ? As far as I can see the  
source code is

```
  def update_attributes(attributes)
    self.attributes = attributes
    save
  end

```

which looks a lot like my

```
@applicant.skills.find(skillid.to_i).description = newdescription
@applicant.skills.find(skillid.to_i).save

```

Stephan

Alex W. wrote:

> If you directly manipulate the associated object, the parent object will  
> become stale since the data it tracks is recorded inside the @applicant  
> object.
> 
> Try “@applicant.reload” after updating an associated record.
> 
> Also, why are you doing this?
> 
> @applicant.skills.find(id\_of\_skill).update\_attributes(…)
> 
> As long as you have the id of the skill why not call it on the Skill  
> clas directly?
> 
> Skill.find(id\_of\_skill).update\_attributes(…)
> 
> If you do this before creating the @applicant object you wont need ot  
> call reload at all.

---

<div class="post-metadata">

**Author:** ![stephanwehner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/0ea827/32.png) [@stephanwehner](https://www.ruby-forum.com/u/stephanwehner)\
**Post date:** [July 2, 2006, 6:49pm UTC](https://www.ruby-forum.com/t/question-about-setting-field-values-for-a-belongs-to-model/96814/4 "2006-07-02T18:49:04Z")

</div>

Stephan W. wrote:

> Ok, thanks a lot, Alex. Why does the database get updated  
> when using “update\_attributes” ? As far as I can see the  
> source code is
> 
> ```
> def update_attributes(attributes)
> self.attributes = attributes
> save
> end
> 
> ```
> 
> which looks a lot like my
> 
> ```
> @applicant.skills.find(skillid.to_i).description = newdescription
> @applicant.skills.find(skillid.to_i).save
> 
> ```
> 
> Stephan

The problem is that each ActiveRecord object caches it’s fetched  
associations to reduce database load.

@applicant.skills #fetches form database  
@applicant.skills #same result but from the object’s cache

skill = Skill.find(1)  
skill.foo = ‘bar’  
skill.save

@applicant.skills #same result as above because this object  
#doesn’t know anything changed so doesnt  
#talk to db

@applicant.reload.skills #cache is cleared and reloaded giving  
#us correct results.

Think of the internal working of association fetches like this:

def skills  
@skills ||= find\_by\_sql(“SELECT FROM `skills` WHERE `applicant_id` =  
?”, id)  
end

This means it will only execute the query if @skills is nil.

There are operations which do work without reloading however. Such as:

@applicant.skills \<\< Skill.new(:foo =\> ‘bar’)

lastly

> Why does the database get updated when using “update\_attributes”?

Because the update\_attributes method calls save. But this saves the  
skill, not the applicant because you are invoking the method that does  
the saving on the skill, not on the applicant.

---

<div class="post-metadata">

**Author:** ![stephanwehner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/0ea827/32.png) [@stephanwehner](https://www.ruby-forum.com/u/stephanwehner)\
**Post date:** [July 2, 2006, 8:27pm UTC](https://www.ruby-forum.com/t/question-about-setting-field-values-for-a-belongs-to-model/96814/5 "2006-07-02T20:27:59Z")

</div>

Ok, I found that

skill = @applicant.skills.find(skillid.to\_i)  
skill.description = newdescription  
skill.save

does “work” (the database gets updated).

In this sequence

@applicant.skills.find(skillid.to\_i).description = newdescription  
@applicant.skills.find(skillid.to\_i).save

the second call to

@applicant.skills.find(skillid.to\_i)

does not return the object that was manipulated in the first line.

Thanks again. This mailing list is great!

Stephan

Alex W. wrote:

> Stephan W. wrote:
> 
> > Ok, thanks a lot, Alex. Why does the database get updated  
> > when using “update\_attributes” ? As far as I can see the  
> > source code is
> > 
> > ```
> > def update_attributes(attributes)
> > self.attributes = attributes
> > save
> > end
> > 
> > ```
> > 
> > which looks a lot like my
> > 
> > ```
> > @applicant.skills.find(skillid.to_i).description = newdescription
> > @applicant.skills.find(skillid.to_i).save
> > 
> > ```
> > 
> > Stephan
> 
> The problem is that each ActiveRecord object caches it’s fetched  
> associations to reduce database load.
> 
> @applicant.skills #fetches form database  
> @applicant.skills #same result but from the object’s cache
> 
> skill = Skill.find(1)  
> skill.foo = ‘bar’  
> skill.save
> 
> @applicant.skills #same result as above because this object  
> #doesn’t know anything changed so doesnt  
> #talk to db
> 
> @applicant.reload.skills #cache is cleared and reloaded giving  
> #us correct results.
> 
> Think of the internal working of association fetches like this:
> 
> def skills  
> @skills ||= find\_by\_sql(“SELECT FROM `skills` WHERE `applicant_id` =  
> ?”, id)  
> end
> 
> This means it will only execute the query if @skills is nil.
> 
> There are operations which do work without reloading however. Such as:
> 
> @applicant.skills \<\< Skill.new(:foo =\> ‘bar’)
> 
> lastly
> 
> > Why does the database get updated when using “update\_attributes”?
> 
> Because the update\_attributes method calls save. But this saves the  
> skill, not the applicant because you are invoking the method that does  
> the saving on the skill, not on the applicant.
