Multiple saves within one controller method issues

I am having a little problem with relations between models when more than one is created within one action.

I have a Member, User and Address class as defined by the schemas below:

create_table "addresses", :force => true do |t|   t.column "location_id", :integer   t.column "location_type", :string   t.column "city", :string   t.column "region_code", :string   t.column "address_1", :string   t.column "address_2", :string   t.column "address_3", :string   t.column "address_4", :string   t.column "country_id", :integer   t.column "province_id", :integer   t.column "longitude", :string   t.column "latitude", :string end

create_table "members", :force => true do |t|   t.column "first_name", :string   t.column "last_name", :string   t.column "primary_phone", :string   t.column "activated", :boolean, :default => false end

create_table "users", :force => true do |t|   t.column "login", :string   t.column "email", :string   t.column "crypted_password", :string, :limit => 40   t.column "salt", :string, :limit => 40   t.column "created_at", :datetime   t.column "updated_at", :datetime   t.column "remember_token", :string   t.column "remember_token_expires_at", :datetime   t.column "member_id", :integer end

And here are the corresponding models (or at least part of them):

class Member < ActiveRecord::Base   has_one :user   has_one :address, :as => :location

class Address < ActiveRecord::Base   belongs_to :province   belongs_to :country

validates_presence_of :location_type, :location_id, :address_1, :city, :country_id   validates_presence_of :province_id, :if => [1, 2].include? (:country_id)

class User < ActiveRecord::Base   belongs_to :member

  validates_presence_of :member_id   validates_presence_of :login, :email   validates_presence_of :password, :if => :password_required?   validates_presence_of :password_confirmation, :if => :password_required?   validates_uniqueness_of :login, :email, :case_sensitive => false

Here is the Member controller code for the create method:

def create   @member = Member.new(params[:member])   @address = Address.new(params[:address])   @user = User.new(params[:user])

  @member.address = @address   @member.user = @user

  respond_to do |format|     if @member.address.valid? and @member.user.valid? and @member.save       ...     end   end end

The above controller code will not ever be able to save seeing as address will fail validation due to it missing the location_type and location_id column values for the polymorphic relationship. If I remove the validates_presence_of for the location_id and location_type I then get the error "Member can't be blank", which is caused by the belong_to :member statement within the User class.

Now I could remove the validation check on the address and user models and simply call the save, and that will work if all the models are valid. All inserts will be performed in the proper order and all relations will be created, BUT if there are any validation errors within either the address or user model it will not thrown an error on the member.save! or return a false on member.save.

When member.save is called the Member model will be inserted, but neither the address or user will be inserted as was confirmed when performing through the console.

I have tried to enclose the save within a transaction, but since an error is not raised the transaction if committed and once again the address and user models are not inserted.

Below is some of the console output with ap, mp and up being some predefined address, member and user hashed params:

peter = Member.new(mp)

=> #<Member:0x2400dc4 @new_record=true, @attributes={"activated"=>false, "first_name"=>"john", "last_name"=>"doe", "primary_phone"=>"555-2323"}>

peter.address = Address.new(ap)

=> #<Address:0x23f80c0 @new_record=true, @attributes={"city"=>"Edmonton", "latitude"=>nil, "region_code"=>"T5Z3J4", "province_id"=>1, "country_id"=>1, "location_type"=>"Member", "location_id"=>nil, "address_1"=>"16436-81st", "address_2"=>nil, "longitude"=>nil, "address_3"=>nil, "address_4"=>nil}>

peter.user = User.new(up)

=> #<User:0x23e5aec @password_confirmation="123123", @new_record=true, @password="123123", @attributes={"salt"=>nil, "updated_at"=>nil, "crypted_password"=>nil, "member_id"=>nil, "remember_token_expires_at"=>nil, "remember_token"=>nil, "login"=>"chris1", "created_at"=>nil, "email"=>"chris1@gmail.com"}>

peter.save!

=> true

peter

=> #<Member:0x2400dc4 @errors=#<ActiveRecord::Errors:0x23e01c8 @errors={}, @base=#<Member:0x2400dc4 ...>>, @new_record=false, @address=#<Address:0x23f80c0 @new_record=true, @attributes={"city"=>"Edmonton", "latitude"=>nil, "region_code"=>"T5Z3J4", "province_id"=>1, "country_id"=>1, "location_type"=>"Member", "location_id"=>nil, "address_1"=>"16436-81st", "address_2"=>nil, "longitude"=>nil, "address_3"=>nil, "address_4"=>nil}>, @attributes={"id"=>29, "activated"=>false, "first_name"=>"john", "last_name"=>"doe", "primary_phone"=>"555-2323"}, @user=#<User:0x23e5aec @errors=#<ActiveRecord::Errors:0x23d9c9c @errors={"login"=>["has already been taken"], "email"=>["has already been taken"]}, @base=#<User:0x23e5aec ...>>, @password_confirmation="123123", @new_record=true, @password="123123", @attributes={"salt"=>nil, "updated_at"=>nil, "crypted_password"=>nil, "member_id"=>29, "remember_token_expires_at"=>nil, "remember_token"=>nil, "login"=>"chris1", "created_at"=>nil, "email"=>"chris1@gmail.com"}>>

It can be seen that the user and address were not inserted while the member was.

So why is Rails allowing this to happen and what is the best way to get around this, or am I way off in left field and I am doing things totally wrong?

Thanks for the help.

(I posted a question like this about a week or so ago and got zero responses. I am not sure if this is such a common question that it is now ignored or if no one has an answer. Could someone please let me know either way?)