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