# Atomic transactions in rails controllers

**URL:** <https://www.ruby-forum.com/t/atomic-transactions-in-rails-controllers/107859>\
**Category:** Rails\
**Created:** [June 26, 2007, 10:48pm UTC](https://www.ruby-forum.com/t/atomic-transactions-in-rails-controllers/107859 "2007-06-26T22:48:35Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![halfgaar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/ea666f/32.png) [@halfgaar](https://www.ruby-forum.com/u/halfgaar)\
**Post date:** [June 26, 2007, 10:48pm UTC](https://www.ruby-forum.com/t/atomic-transactions-in-rails-controllers/107859/1 "2007-06-26T22:48:35Z")

</div>

Hi,

When I have a transaction block like this:

ActiveRecord::Base.Transaction do  
cars.each do | car |  
car.dosomething  
car.save!  
end  
end

When the last car in the collection fails, all the others will have  
gotten an ID. That means that if the fault results in a validation  
error, and I correct the form and resubmit, rails say it can’t find a  
car with that id.

It’s not very atomic this way.

I can solve it partly by setting the id’s to nil in a rescue clause,  
but that has a drawback. In my form, I want certain fields to be  
disabled when editing an existing record (as opposed to creating a new  
one). I use car.new\_record? for that. But, when the validation fails  
and I submit, and submit again, because of the loss of ID, rails  
doesn’t know anymore that it was an existing record, and new\_record?  
will return true.

So, my question: is there a way to unset the id and still let rails  
think the record already exists in the DB? Is it dangerous to make a  
method in AR::Base, which sets @new\_record to true and id to nil?

Or, even better, is it possible to have true atomic transactions in  
rails models? (probably not, because there is no uncomitted state of  
variables in ruby, but I thought I’d ask…)

---

<div class="post-metadata">

**Author:** ![halfgaar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/ea666f/32.png) [@halfgaar](https://www.ruby-forum.com/u/halfgaar)\
**Post date:** [June 26, 2007, 11:42pm UTC](https://www.ruby-forum.com/t/atomic-transactions-in-rails-controllers/107859/2 "2007-06-26T23:42:42Z")

</div>

> When I have a transaction block like this:
> 
> ActiveRecord::Base.Transaction do  
> cars.each do | car |  
> car.dosomething  
> car.save!  
> end  
> end

Rails seems to fall down a bit when you want to edit multiple child  
records on one form. I’ve solved this problem by tying each child  
record to it’s parent, and then I save! the parent, which also seems to  
validate and save it’s children if necessary. I assign ID numbers before  
I create the records so that I can manipulate the correct div via ajax  
calls. Each child is in a div like

, so without  
an id, the div doesn’t work right.

Because the child records are tied to the parent, the parent is saved  
first, and then it’s ID is applied via the has\_many relationship to the  
children records. So, the unique number that I temporarily assign for  
handling the div is correctly replaced by rails. Rails seems smart  
enough to run the validations before attempting to save, so no records  
wind up in the database until they all test as valid.

def signup  
unless request.post?  
# initialize the view, set temporary id numbers  
@user = User.new  
@user.emails \<\< Email.new do |o|  
o.id = Time.now.to\_i  
o.emailtype\_id = 1 # business  
end  
@user.phones \<\< Phone.new do |o|  
o.id = Time.now.to\_i  
o.phonetype\_id = 1 # business  
end  
@user.addresses \<\< Address.new do |o|  
o.id = Time.now.to\_i  
o.addresstype\_id = 1 # business  
end  
else  
# post, so assign fields to objects  
@user = User.new(params[:user])

```
  # the model protects the user name, password and admin flag from

```

mass assignment  
# so set them here  
@user.login = params[:user][:login]  
@user.password = params[:user][:password]

```
  # attach sub-models to model
  params[:email].each {|e| @user.emails << Email.new(e)} if

```

params[:email]  
params[:phone].each {|t| @user.phones \<\< Phone.new(t)} if  
params[:phone]  
params[:address].each {|a| @user.addresses \<\< Address.new(a)} if  
params[:address]

```
  # validate and save the whole shebang
  @user.save!
  redirect_back_or_default(:controller => '/account', :action =>

```

‘thankyou’)  
flash[:notice] = “Thanks for signing up!”  
end  
rescue ActiveRecord::RecordInvalid  
# hack, assign id numbers to the sub-models so that the view will  
render correctly  
# things will get very weird if the id’s in the user table  
approach that of the current  
# time in seconds. It’s quite unlikely, however.  
count = 0  
[@user.emails, @user.addresses, @user.phones].flatten!.each do  
|obj|  
obj.id = Time.now.to\_i + count unless obj.id  
count = count + 100 # try to make sure we won’t get the same id  
for multiple objects  
end  
end

In order for this to work, the fields for, example, the phone partial  
need to look something like:

\<% @phone = phone %\>

"\> \<%= hidden\_field\_tag 'phone[][id]', phone.id %\> Telephone Number:  
 \<%= text\_field\_tag 'phone[][number]', phone.number, :size =\> 15 %\>  
 \<%= error\_message\_on 'phone', 'number', 'Telephone Number ', '', 'errorMessage' %\>

HTH

Regards,  
Rich

---

<div class="post-metadata">

**Author:** ![halfgaar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/ea666f/32.png) [@halfgaar](https://www.ruby-forum.com/u/halfgaar)\
**Post date:** [June 27, 2007, 10:19am UTC](https://www.ruby-forum.com/t/atomic-transactions-in-rails-controllers/107859/3 "2007-06-27T10:19:30Z")

</div>

On Jun 26, 2007, at 11:41 PM, Duzenbury, Rich wrote:

> Rails seems to fall down a bit when you want to edit multiple child  
> records on one form. I’ve solved this problem by tying each child  
> record to it’s parent, and then I save! the parent, which also  
> seems to  
> validate and save it’s children if necessary.

If validates\_associated.

– fxn

---

<div class="post-metadata">

**Author:** ![halfgaar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/ea666f/32.png) [@halfgaar](https://www.ruby-forum.com/u/halfgaar)\
**Post date:** [June 27, 2007, 7:45pm UTC](https://www.ruby-forum.com/t/atomic-transactions-in-rails-controllers/107859/4 "2007-06-27T19:45:35Z")

</div>

On Jun 27, 10:16 am, Xavier N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> If validates\_associated.

Hey, now this may be very convenient. I was about to reply to Rich  
that in my controllers, rails was very unpredictable when it comes to  
validating has\_many collections (it sometimes would and sometimes  
wouldn’t), and I have some very klunky code to work around that, but  
this may just solve all of that.

---

<div class="post-metadata">

**Author:** ![halfgaar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/ea666f/32.png) [@halfgaar](https://www.ruby-forum.com/u/halfgaar)\
**Post date:** [June 27, 2007, 7:57pm UTC](https://www.ruby-forum.com/t/atomic-transactions-in-rails-controllers/107859/5 "2007-06-27T19:57:37Z")

</div>

On Jun 26, 11:41 pm, “Duzenbury, Rich” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> children records. So, the unique number that I temporarily assign for  
> o.emailtype\_id = 1 # business  
> # post, so assign fields to objects  
> params[:email]  
> end  
> count = count + 100 # try to make sure we won’t get the same id  
> Telephone Number:  
>   
> \<%= text\_field\_tag ‘phone[][number]’, phone.number, :size =\> 15  
> %\>  
>   
> \<%= error\_message\_on ‘phone’, ‘number’, 'Telephone Number ', ‘’,  
> ‘errorMessage’ %\>
> 
> HTH
> 
> Regards,  
> Rich

First, see my reply to Xavier’s message.

While it doesn’t solve my new\_record issue, you did help me with  
another issue, but I do have a question. When you assign ID’s to new  
objects, doesn’t it complain about trying to save records which don’t  
exists, because the ID’s are not present in the DB? Or, does it only  
do that when new\_record? == false?

BTW, I always solved the id of the div issue by assigning id’s based  
on Time.now.to\_s when the partial in question was rendered for an  
object that didn’t exist in the DB yet. I will be exploring your  
method, since it looks cleaner.

Another thing: why aren’t you using text\_field(model, method) as  
opposed to using text\_field\_tag, and then implementing what text\_field  
already does for you, including marking it red on validation failures.
