# Multiple saves within one controller method issues

**URL:** <https://www.ruby-forum.com/t/multiple-saves-within-one-controller-method-issues/120334>\
**Category:** Rails\
**Created:** [November 15, 2007, 10:02pm UTC](https://www.ruby-forum.com/t/multiple-saves-within-one-controller-method-issues/120334 "2007-11-15T22:02:17Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![chrisolsen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/c6cbf5/32.png) [@chrisolsen](https://www.ruby-forum.com/u/chrisolsen)\
**Post date:** [November 15, 2007, 10:02pm UTC](https://www.ruby-forum.com/t/multiple-saves-within-one-controller-method-issues/120334/1 "2007-11-15T22:02:17Z")

</div>

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”=\>“removed\_email\_address@domain.invalid”}\>

> > 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”=\>“removed\_email\_address@domain.invalid”}\>\>

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?)
