patternrubyrailsMinor
Update record with CSV
Viewed 0 times
withrecordupdatecsv
Problem
I'm using Rails 4.2.5, and I'd like to update existing records with a csv file with two fields: id,category. Where if the category field is blank, it defaults to misc.
Here's an example csv file:
So, I've created some tasks,
I will definitely appreciate any advice on how this could be better written, and also whether this is even a good way to go about solving this problem.
Here's an example csv file:
id,category
123-123-123,0
123-123-124,1
123-123-125,
123-123-126,2So, I've created some tasks,
update_item_categories, and set_item_categories:# lib/tasks/update_item_categories.rake
require 'csv'
namespace :db do
task :update_item_categories => :environment do
categories = ['misc', 'food', 'drink']
CSV.foreach('public/update/item_categories.csv', headers: true) do |row|
row_hash = row.to_hash
category = categories[row_hash['category'].to_i]
unless Item.where(id: row_hash['id']).empty?
item = Item.find(row_hash['id'])
item.update_attributes(
:category => category
)
item.save!
end
end
task :set_item_categories => :environment do
Item.where(category: nil).each do |item|
item.update_attributes(category: 'misc')
item.save!
end
end
endI will definitely appreciate any advice on how this could be better written, and also whether this is even a good way to go about solving this problem.
Solution
Regarding the first task, you could save a couple of queries by modifying the code to look like this:
You can retrieve the
Regarding the second task, since you want to raise an exception in case of invalid record, you have to save each record individually but you can save some queries by finding records in batches. The code could look like this:
# ....
CSV.foreach('public/update/item_categories.csv', headers: true) do |row|
row_hash = row.to_hash
category = categories[row_hash['category'].to_i]
item = Item.where(id: row_hash['id'])
item.update_attributes!(category: category) unless item.nil?
end
# ....
You can retrieve the
item once and perform update_attributes! without save!. update_attributes! saves the changes to the db using save! internally. Here's the source code (update_attributes! it's an alias for update!):def update!(attributes)
with_transaction_returning_status do
assign_attributes(attributes)
save!
end
end
Regarding the second task, since you want to raise an exception in case of invalid record, you have to save each record individually but you can save some queries by finding records in batches. The code could look like this:
Item.find_each(category: nil) do |item|
item.update_attributes!(category: 'misc')
end
Context
StackExchange Code Review Q#125633, answer score: 2
Revisions (0)
No revisions yet.