I was developing an app with Rails and implemented the process of creating data for multiple tables at the same time. In that process, I learned that there is a concept of transaction that makes both processes absent when either process fails, so I will write about transaction and the implemented contents as a memorandum and output.
Looking up the definition of the word "transaction" [Processing, handling, treatment, business, trading, buying and selling, newsletter, bulletin, minutes] It comes out like this.
In IT and programming "Indivisible things that combine multiple processes into one"
It seems that it can be defined as.
This article is a very easy-to-understand summary of the concept of transactions, and I used it as a reference.
What is a "transaction"? I tried to talk about it in a super easy way!
--Treat multiple processes as one set process --If even one process fails, the transaction as a whole will fail. --If it fails, it means that all the processing was not done.
The basic syntax is like this
model.transaction do
#Access processing to the table
#Access processing to the table
end
#Processing when transaction processing is successful
rescue => e
#Processing when transaction processing fails
As a caveat, "use a method that raises an exception when processing fails".
If a transaction fails in any one of the included processes, it determines that all the processes in the transaction have not been performed, but the condition for not doing so is "an exception occurs".
Let's actually implement it.
The app we were developing this time had a user grouping function. Therefore, it is assumed that the user who created the group automatically becomes the user who belongs to the group when creating a new group. Therefore, when creating a group, consider using a transaction to avoid unexpected behavior.
The table structure looks like this.
At the same time as creating the groups table instance, I wanted to create a group_users table (intermediate table between users table and groups table) with the id of the logged-in user as the user_id column.
If either process of 1 or 2 fails for some reason, transaction is used in the create action of the groups controller so that both processes have not been processed.
groups_controller.rb
#Excerpt from the create action part
#Variable current_user contains an instance of the logged-in user
def create
@group = Group.new(group_params)
#Apply transaction(Create group and create intermediate table at the same time)
# save!And create!When"!Please note that "" is attached!
@group.transaction do
@group.save!
current_user.group_users.create!(group_id: @group.id, permission: true)
end
#Processing when transaction is successful
flash[:success] = 'Created a new group'
redirect_to @group
rescue => e
#Processing when transaction fails
flash.now[:danger] = 'Group creation failed'
render :new
end
Note that both processes in this transaction are marked with a "!" And use a method that raises an exception when table data creation fails!
If the following is implemented without using transaction, there is a concern that an unmanned group will be created if the creation of the group_users table fails for some reason.
groups_controller.rb
#When not using transaction
def create
@group = Group.new(group_params)
if @group.save
current_user.group_users.create(group_id: @group.id, permission: true)
flash[:success] = 'Created a new group'
redirect_to @group
else
flash.now[:danger] = 'Group creation failed'
render :new:
end
end
Thank you for reading the article! I managed to implement it while investigating this time, but honestly I do not have a deep understanding of transactions. If you have any mistakes or better description methods, please feel free to comment. I used the following article as a reference. Thank you very much.
Recommended Posts