Search code examples
ruby-on-railscsvtaskrakeupdate-all

Rails 4 rake task to update records. Find by ts_code and update with CSV


bit of a messy one I'm having here trying to get this to work. I have a store with a database of products. What I have been given is a CSV file with 3 columns and over 500 entries, ts_code cost_price and sell_price.

So I need a task that i can run that finds all the products that match the ts_code, then update the cost_price and sell_price of those products.

I've tried to edit the task that I used to import the products in the first place like the following.

Original Task

require 'csv'
desc "Imports a CSV file into an ActiveRecord table"
task :import, [:filename] => :environment do
CSV.foreach('csv/vow.csv', :headers => true) do |row|
Spree::Product.create!(row.to_hash)
end
end

I was hoping something like this would work but I'm stuck now.

require 'csv'
desc "Imports a CSV file into an ActiveRecord table"
task :update, [:filename] => :environment do
CSV.foreach('csv/vow.csv', :headers => true) do |row|
a = Spree::Product.find_by(:ts_code)
Spree::Product.update_all!(a, row.to_hash)
end
end

I also know I need to tell it what columns to update but I'm not sure where to put them like cost & sell_price. If anyone could help that would be great.

Still trying to get this working somehow, next thing i tried was this but getting an error undefined method find_by. Syntax is wrong somehow, not sure how close I am.

require 'csv'
desc "Imports a CSV file into an ActiveRecord table"
task :update, [:filename] => :environment do
CSV.foreach('csv/recharge_pricing.csv', :headers => true) do |row|
product = find_by(ts_code: row["ts_code"]) || new
parameters = ActionController::Parameters.new(row.to_hash)
product.update(parameters.permit(:cost_price,:price))
product.save!
end
end

Solution

  • Your second example had the find_by 1 syntax correct - you need to call it on your Spree::Product object. You could also call Spree::Product.find_by_ts_code(row["ts_code"]) as a shortcut.

    Also, instead of your || new syntax, you might look at find_or_create_by 2 - something like this:

    product = Spree.Product.find_or_create_by(ts_code: row["ts_code"])
    

    Lastly, update calls save for you, so your save! call is redundant.