I would like to use transactions when importing csv files in rails.(If an error occurs, cancel all line changes and return to the original screen to display the error.)

Asked 2 years ago, Updated 2 years ago, 27 views

Creating web applications in rails.Therefore, we are currently implementing the csv file capture function.I was able to import csv, but I would like to use transactions to import csv files.(If an error occurs, I would like to cancel all changes and return to the original screen to display the error.) However, I did not know how to implement it, so I asked you a question.

$rails-v 
5.0.0

controller/costs_controller.rb

def import
  if params[:csv_file].blank?
    redirect_to action: 'index', error: 'Please select CSV to load'
  elsif File.extname(params[:csv_file].original_filename)!=".csv"
    redirect_to action: 'index', notice: 'Only csv files can be loaded'
  else
    num = Cost.import_by_csv (params[:csv_file])
    redirect_to action: 'index', notice: "# {num.to_s} data information added/updated"
  end
end

model/cost.rb

require'csv'
class Cost<ActiveRecord::Base

  # Register the contents of the csv file in DB
  def self.import_by_csv(file)
    imported_num = 0
    open(file.path, 'r:cp932:utf-8', undef::replace) do | f |
      csv=CSV.new(f, :headers=>:first_row)
      caches = Cost.all.index_by (&:code)
      csv.each do | row |
        next if row.header_row?

  # Convert CSV Row Information to HASH
        table = Hash [[row.headers, row.fields].transpose]

  # Registered Data Information
  # Create if not registered
        cost=caches [table['code']]

        if cost.nil?
           cost=new
        end
  # data information update
        cost.attributes=table.slice(*table.except(:created_at,:updated_at).keys)

  # Save for validation ok
        if cost.valid?
          cost.save!
          imported_num+=1
        end
      end
    end

  # return the number of updates
    imported_num
  end
end

views/costs/index.html.slim

=form_tag import_costs_path, method::post, multipart:true do
  = file_field_tag —csv_file
  = submit_tag 'CSV Read'

route.rb

Rails.application.routes.drawdo
  resources —costs do
  post:import, on::collection
end

That's all the current code.When I looked into the transaction, I found out that

Cost.transaction do 
  ------ Code -----
end

There is a transaction implementation as shown in , but I don't know where and how to write it...
I apologize for the inconvenience, but I would appreciate it if you could let me know.
Thank you for your cooperation.

ruby-on-rails ruby

2022-09-29 21:42

1 Answers

A transaction summarizes a set of actions that you want to be consistent with.

In this case, csv.each to end should be included in Cost.transaction do to end.If there is an error in the middle (for example, validation failure) and you want to roll back, use raise ActiveRecord::Rollback.

In addition, if a database-side constraint fails, an exception will occur, so please handle it properly.


2022-09-29 21:42

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.