# HABTM join table not being updated

**URL:** <https://www.ruby-forum.com/t/habtm-join-table-not-being-updated/140125>\
**Category:** Rails\
**Created:** [June 11, 2008, 3:00am UTC](https://www.ruby-forum.com/t/habtm-join-table-not-being-updated/140125 "2008-06-11T03:00:39Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jeffrey\_Lee](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e36b37/32.png) [@Jeffrey\_Lee](https://www.ruby-forum.com/u/Jeffrey_Lee)\
**Post date:** [June 11, 2008, 3:00am UTC](https://www.ruby-forum.com/t/habtm-join-table-not-being-updated/140125/1 "2008-06-11T03:00:39Z")

</div>

I’ve been working with the Advanced Railes Recipies PDF tutorial but  
seem to have hit a snag. When adding a HABTM element, locations in  
place of tasks in my usage, the location (address) is added to the  
locations table; however, the join is not added to my  
locations\_profiles table (profile\_id,location\_id). Would I need to do  
something more than just @profile.save in the profiles controller for  
this to be saved properly?

I will post code when I get home but it is essentially the same as the  
tutorial (which doesn’t mention HABTM associations unfortunetally).

---

<div class="post-metadata">

**Author:** ![Jeffrey\_Lee](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e36b37/32.png) [@Jeffrey\_Lee](https://www.ruby-forum.com/u/Jeffrey_Lee)\
**Post date:** [June 11, 2008, 5:03am UTC](https://www.ruby-forum.com/t/habtm-join-table-not-being-updated/140125/2 "2008-06-11T05:03:28Z")

</div>

As I stated before, the location is added to the locations table and  
the profile is added to the profiles table (if new). The problem is  
that the join table is not updated to match the association.

Here is my profiles controller:

# GET /profiles/new

def new  
@devices = Device.find(:all)  
@profile = Profile.new  
@profile.websites.build # creates first website fieldset  
@profile.numbers.build # creates first number fieldset  
@profile.emails.build # creates first email fieldset  
@profile.locations.build # creates first location fieldset  
@profile.notes.build # creates first note fieldset  
end

# GET /profiles/1/edit

def edit  
@profile = Profile.find(params[:id])  
end

# POST /profiles

def create  
@profile = Profile.new(params[:profile])

```
if @profile.save
  flash[:notice] = "Successfully created profile!"
  redirect_to profile_path(@profile)
else
  render :action => 'new'
end

```

end

# PUT /profiles/1

def update  
params[:profile][:existing\_email\_attributes] ||= {}  
params[:profile][:existing\_website\_attributes] ||= {}  
params[:profile][:existing\_location\_attributes] ||= {}  
params[:profile][:existing\_number\_attributes] ||= {}  
params[:profile][:existing\_note\_attributes] ||= {}

```
@profile = Profile.find(params[:id])

if @profile.update_attributes(params[:profile])
  flash[:notice] = "Successfully updated profile!"
  redirect_to profile_path(@profile)
else
  render :action => 'edit'
end

```

end

profile.rb

class Profile \< ActiveRecord::Base

after\_update :save\_numbers  
after\_update :save\_emails  
after\_update :save\_locations  
after\_update :save\_websites  
after\_update :save\_notes

belongs\_to :user  
belongs\_to :type  
has\_many :numbers,  
:dependent =\> :delete\_all  
has\_many :emails,  
:dependent =\> :delete\_all  
has\_many :websites,  
:dependent =\> :delete\_all  
has\_many :notes,  
:dependent =\> :delete\_all  
has\_and\_belongs\_to\_many :locations

# Emails

def new\_email\_attributes=(email\_attributes)  
email\_attributes.each do |attributes|  
emails.build(attributes)  
end  
end  
def existing\_email\_attributes=(email\_attributes)  
emails.reject(&:new\_record?).each do |email|  
attributes = email\_attributes[email.id.to\_s]  
if attributes  
email.attributes = attributes  
else  
emails.delete(email)  
end  
end  
end  
def save\_emails  
emails.each do |email|  
email.save(false)  
end  
end

# Numbers

def new\_number\_attributes=(number\_attributes)  
number\_attributes.each do |attributes|  
numbers.build(attributes)  
end  
end  
def existing\_number\_attributes=(number\_attributes)  
numbers.reject(&:new\_record?).each do |number|  
attributes = number\_attributes[number.id.to\_s]  
if attributes  
number.attributes = attributes  
else  
numbers.delete(number)  
end  
end  
end  
def save\_numbers  
numbers.each do |number|  
number.save(false)  
end  
end

# Websites

def new\_website\_attributes=(website\_attributes)  
website\_attributes.each do |attributes|  
websites.build(attributes)  
end  
end  
def existing\_website\_attributes=(website\_attributes)  
websites.reject(&:new\_record?).each do |website|  
attributes = website\_attributes[website.id.to\_s]  
if attributes  
website.attributes = attributes  
else  
websites.delete(website)  
end  
end  
end  
def save\_websites  
websites.each do |website|  
website.save(false)  
end  
end

# Locations

def new\_location\_attributes=(location\_attributes)  
location\_attributes.each do |attributes|  
locations.build(attributes)  
end  
end  
def existing\_location\_attributes=(location\_attributes)  
locations.reject(&:new\_record?).each do |location|  
attributes = location\_attributes[location.id.to\_s]  
if attributes  
location.attributes = attributes  
else  
locations.delete(location)  
end  
end  
end  
def save\_locations  
locations.each do |location|  
location.save(false)  
end  
end

# Notes

def new\_note\_attributes=(note\_attributes)  
note\_attributes.each do |attributes|  
notes.build(attributes)  
end  
end  
def existing\_note\_attributes=(note\_attributes)  
notes.reject(&:new\_record?).each do |note|  
attributes = note\_attributes[note.id.to\_s]  
if attributes  
note.attributes = attributes  
else  
notes.delete(note)  
end  
end  
end  
def save\_notes  
notes.each do |note|  
note.save(false)  
end  
end

end

location.rb  
class Location \< ActiveRecord::Base

belongs\_to :state  
has\_and\_belongs\_to\_many :profiles

validates\_presence\_of :address\_line\_1,  
:message =\> “If you do not wish to add this  
location,  
please click remove.”  
validates\_presence\_of :city,  
:message =\> “If you do not wish to add this  
location,  
please click remove.”  
validates\_presence\_of :state\_id,  
:message =\> “If you do not wish to add this  
location,  
please click remove.”  
validates\_numericality\_of :zip,  
:allow\_nil =\> false,  
:message =\> “Please enter a zip code  
consisting of  
numbers only”  
end

\_location.html.erb

 \<% new\_or\_existing = location.new\_record? ? 'new' : 'existing' %\> \<% prefix = "profile[#{new\_or\_existing}\_location\_attributes][]" %\> \<% fields\_for prefix, location do |location\_form| -%\> 

Address Line 1: \<%= location\_form.text\_field :address\_line\_1 %\>  
 Address Line 2: \<%= location\_form.text\_field :address\_line\_2 %\>  
 City: \<%= location\_form.text\_field :city %\>  
 State: \<%= location\_form.select :state\_id, State.find(:all).collect {|p| [p.name, p.id] }, { :prompt =\> "Select a state" } %\> Zip Code: \<%= location\_form.text\_field :zip %\>  
 Description: \<%= location\_form.text\_field :description %\>  
 \<%= link\_to\_function "remove" , "$(this).up('.location').remove()" %\>

 \<% end -%\>

\_form.html.erb  
\<%= f.hidden\_field :id %\>

First name: \<%= f.text\_field :first\_name %\>

Last name: \<%= f.text\_field :last\_name %\>

Title: \<%= f.text\_field :title %\>

Company: \<%= f.text\_field :company %\>

User: \<%= f.text\_field :user\_id %\>

Type: \<%= f.text\_field :type\_id %\>

## Websites

 \<%= render :partial =\> 'website', :collection =\> @profile.websites %\>
\<%= add\_website\_link "Add a Website" %\>
## Numbers

 \<%= render :partial =\> 'number', :collection =\> @profile.numbers %\>
\<%= add\_number\_link "Add a Number" %\>
## Emails

 \<%= render :partial =\> 'email', :collection =\> @profile.emails %\>
\<%= add\_email\_link "Add an Email" %\>
## Locations

 \<%= render :partial =\> 'location', :collection =\> @profile.locations %\>
\<%= add\_location\_link "Add a Location" %\>
## Notes

 \<%= render :partial =\> 'note', :collection =\> @profile.notes %\>
\<%= add\_note\_link "Add a Note" %\>

profile helper  
module ProfilesHelper

def add\_website\_link(name)  
link\_to\_function name do |page|  
page.insert\_html :bottom, :websites, :partial =\>  
‘website’ , :object =\> Website.new  
end  
end

def add\_number\_link(name)  
link\_to\_function name do |page|  
page.insert\_html :bottom, :numbers, :partial =\> ‘number’ , :object  
=\> Number.new  
end  
end

def add\_email\_link(name)  
link\_to\_function name do |page|  
page.insert\_html :bottom, :emails, :partial =\> ‘email’ , :object  
=\>  
Email.new  
end  
end

def add\_location\_link(name)  
link\_to\_function name do |page|  
page.insert\_html :bottom, :locations, :partial =\>  
‘location’ , :object =\> Location.new  
end  
end

def add\_note\_link(name)  
link\_to\_function name do |page|  
page.insert\_html :bottom, :notes, :partial =\> ‘note’ , :object =\>  
Note.new  
end  
end

end
