In Michael Hartl's rails tutorial chapter 13.3.1, we create a twitter-style micropost like this:
Micropost.create
My question is why use Micropost.create
and not Micropost.create!
?
It seems that you would always want to raise exceptions in active record if there's a problem so that you can address the exceptions.
Why would want to ever use Micropost.create
? He explains that both are options with this table:
But he doesn't really explain why you would choose one or the other. So, why would you choose one over the other?
Well, it depends where you are using the method.
create
If it's a simple create in your controller, generally you will use create
to be able to control the flow logic, take this example:
if Micropost.create(micropost_params)
# handle success save, e.g.:
redirect_to :index
else
# handle failure in save, e.g.:
render :new
end
With the above code you control the flow without using exceptions, and that's what you want when you create a record: Handle errors that you know that will be likely to happen without raising exceptions.
So, i prefer to ask it the other way around: why use create!
and raise an exception (and get the related overhead) if you could just get a false
and handle the error? And why do it if i need more code to handle that exception?
While this is a valid use create
, it's not that common, since save
and update
are more likely to be used (in most cases you will create using new
and then saving with save
).
create!
If you want to update multiple records within the same action (read transactions), then create!
will serve you better; consider the following example:
ActiveRecord::Base.transaction do
user1.update!(balance: user1.balance + 100)
user2.update!(balance: user2.balance - 100)
transfer.create!(amount: 100, receiver: user1, sender: user2)
end
Here you update 2 records and create 1 within the same transaction, but if one of them fails you need to do a rollback to keep you data integrity intact. So, if you use create
you will need to handle the rollback yourself to undo the transaction; on the other hand, using create!
will raise an exception that triggers the rollback automatically.
Another good use for create!
is testing (as in Hartl's tutorial) and debugging, i found them more convenient since they help catch errors a lot faster.