# Before\_save returning false does not roll back transaction

**URL:** <https://www.ruby-forum.com/t/before-save-returning-false-does-not-roll-back-transaction/108835>\
**Category:** Rails\
**Created:** [July 7, 2007, 11:17pm UTC](https://www.ruby-forum.com/t/before-save-returning-false-does-not-roll-back-transaction/108835 "2007-07-07T23:17:56Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![pedz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/839c29/32.png) [@pedz](https://www.ruby-forum.com/u/pedz)\
**Post date:** [July 7, 2007, 11:17pm UTC](https://www.ruby-forum.com/t/before-save-returning-false-does-not-roll-back-transaction/108835/1 "2007-07-07T23:17:56Z")

</div>

I have models with has\_many and belongs\_to associations. I create a  
group of three interconnected records and do a save. The last record to  
be saved does not pass the before\_save criteria and so my before\_save  
function returns false. I was expecting everything to get rolled back.  
But it does not. Instead, the processing of the third record quits but  
the commit happens anyway – and the save returns true.

I have not pulled this out into a small stand alone example but I am  
doing roughly this:

class Relationship \< ActiveRecord::Base  
belongs\_to :link\_type  
belongs\_to :parent, :polymorphic =\> true  
belongs\_to :child, :polymorphic =\> true

before\_save :banana

protected

def banana  
errors.add(:parent, “bogus error”)  
logger.info(“returning false”)  
false  
end  
end

class Person \< ActiveRecord::Base  
has\_many :parents, :as =\> :parent, :class\_name =\> “Relationship”  
has\_many :children, :as =\> :child, :class\_name =\> “Relationship”  
end

class Company \< ActiveRecord::Base  
has\_many :parents, :as =\> :parent, :class\_name =\> “Relationship”  
has\_many :children, :as =\> :child, :class\_name =\> “Relationship”  
end

class PeopleController \< ApplicationController  
def create  
@person = Person.new(params[:person])

```
# Create optional new Company
if params[:company][:name] != "" then
  company =

```

Company.find\_or\_initialize\_by\_name(params[:company][:name])  
link\_type = LinkType.parent\_to\_child(“Company”, “Employee”,  
“Person”)  
relationship = Relationship.new(:link\_type =\> link\_type)  
@person.children \<\< relationship  
relationship.parent = company  
end  
logger.info(“about to save”)  
respond\_to do |format|  
if @person.save  
flash[:notice] = ‘Person was successfully created.’  
format.html { redirect\_to person\_url(@person) }  
format.xml { head :created, :location =\> person\_url(@person) }  
else  
format.html { render :action =\> “new” }  
format.xml { render :xml =\> @person.errors.to\_xml }  
end  
end  
end  
end

The log shows:

…  
Company Create (0.000210) INSERT INTO companies (“name”,  
“created\_at”) VALUES(‘c25’, ‘2007-07-07 16:01:07.577598’)  
SQL (0.000131) SELECT currval(‘companies\_id\_seq’)  
before\_save  
link\_type.child.name is Person  
child\_id is 23  
child\_type is Person  
link\_type.parent.name is Company  
parent\_id is 26  
parent\_type is Company  
returning false  
SQL (0.001573) COMMIT  
Redirected to [http://localhost:3000/rcm/people/23](http://localhost:3000/rcm/people/23)

First Person is saved, then Company is saved, then Relationship is in  
the process of being saved but the before\_save returns false. But, I  
would expect the whole transaction to be rolled back and the save return  
false. But instead it is committed and the save returns true. You can  
note that we are getting redirected to people/23 not people/new

I’m doing this in before\_save because at the time validate is called,  
the parent\_type is not filled in. It is the only place where everything  
is filled in so I can actually check to make sure everything is right.  
The other weird thing is validate for the relationship is being called  
twice during this process. Once early on and again after person and  
company has been saved. The second pass through validate has all the  
fields I need but I have not figured out how to determine if this is the  
first or second time through validate.

Can someone help?
