railsのcsvファイルの読み込みについての質問です。(読み込む際にファイルデータをDBに新規登録するか、更新するか判別させたいです)
codeカラムをキーとしてcodeがDBとcsvファイルで照らし合わせ、数字が一致すればupdate, しなければcreateを実行して欲しいのですが、現状、updateが実行されず、createしかされません。
お手数おかけしますが、updateを行うには何が足りないのかご教示いただけましたら嬉しいです....
以下が現在のコードです。
model/cost.rb
require 'csv' class Cost < ActiveRecord::Base validates :code, presence: true, uniqueness: true validates :name, presence: true, uniqueness: true validates :cost_class, presence: true validates :budget_class, presence: true 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) Cost.transaction do #トランザクションの開始 csv.each do |row| next if row.header_row? table = Hash[[row.headers, row.fields].transpose] cost = caches[table['code']] || new #この辺りが怪しいと感じています cost.attributes = table.slice(*table.except(:id, :created_at, :updated_at).keys) # ここのコードもよくわかっていません... cost.save! #失敗したら例外発生 imported_num += 1 end end end imported_num end end
controllers/costs_controller.rb
class CostsController < ApplicationController def import if params[:csv_file].blank? redirect_to costs_path, alert: '読み込むCSVを選択してください' elsif File.extname(params[:csv_file].original_filename) != ".csv" redirect_to master_costs_path, alert: 'csvファイルのみ読み込み可能です' else imported_row_count = Cost.import_by_csv(params[:csv_file]) redirect_to costs_path, alert: "#{ imported_row_count }件のデータ情報を追加/更新しました" end rescue ActiveRecord::RecordInvalid => e redirect_to costs_path, alert: "不正なデータが含まれています:#{ e.record.errors.full_messages }" rescue ActiveModel::UnknownAttributeError redirect_to costs_path, alert: '適切なファイルを選択してください' end end
index.html.slim
= form_tag import_costs_path, method: :post, multipart: true do = file_field_tag :csv_file = submit_tag 'CSV読み込み'
現状このコードでcsvファイルを読み込むとcodeがない場合にはデータがDBに新規作成されますが、codeがすでにある場合は
""不正なデータが含まれています:["Codeはすでに存在します", "Nameはすでに存在します"]"" と表示され、更新されません。=> 新規登録を前提とする警告が出てしまっている気がします...
ログ
ActiveRecord::SchemaMigration Load (0.6ms) SELECT "schema_migrations".* FROM "schema_migrations" Processing by CostsController#import as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"*******", "csv_file"=>#<ActionDispatch::Http::UploadedFile:0x007fe88db51800 @tempfile=#<Tempfile:/var/folders/dm/******/T/*****.csv>, @original_filename="costs.csv", @content_type="text/csv", @headers="Content-Disposition: form-data; name=\"csv_file\"; filename=\"costs.csv\"\r\nContent-Type: text/csv\r\n">, "commit"=>"CSV読み込み"} Cost Load (1.2ms) SELECT "costs".* FROM "costs" (3.7ms) BEGIN Cost Exists (0.5ms) SELECT 1 AS one FROM "costs" WHERE "costs"."code" = $1 LIMIT $2 [["code", 1], ["LIMIT", 1]] Cost Exists (1.2ms) SELECT 1 AS one FROM "costs" WHERE "costs"."name" = $1 LIMIT $2 [["name", "あ,\"\\え"], ["LIMIT", 1]] (0.3ms) ROLLBACK Redirected to http://localhost:3000/costs Completed 302 Found in 413ms (ActiveRecord: 13.3ms) Started GET "/costs" for ::1 at 2016-07-14 16:16:19 +0900 Processing by CostsController#index as HTML Rendering costs/index.html.slim within layouts/application Cost Load (1.3ms) SELECT "costs".* FROM "costs" ORDER BY "costs"."code" ASC LIMIT $1 OFFSET $2 [["LIMIT", 10], ["OFFSET", 0]] (0.5ms) SELECT COUNT(*) FROM "costs" Rendered costs/index.html.slim within layouts/application (177.9ms) Completed 200 OK in 1564ms (Views: 1477.7ms | ActiveRecord: 1.8ms)
コントローラーで何かが足りない気はしますが、わかりません。
長くなってしまいすみませんが、回答いただけましたら大変幸いです。
よろしくお願い致します。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/07/19 02:37