Shenanigator
Shenanigator

Reputation: 1066

Importing CSV and updating records if exists in rails 4

Model:

def self.import(csv_file)
    line = 2
    errors = []

    CSV.foreach(csv_file, headers: true) do |row|
      order = Order.find_or_initialize_by(projectid: row["projectid"], batch: row["batch"])
      order.assign_attributes(row.to_hash)
      if order.valid?
        order.save!
      else
        errors << line
      end

      line += 1
    end

    return errors
  end

here is the updated model code based on suggestions below; BIG thanks to Daiku and madcow thus far.

I think the reason that the record is not updating has to do with order.assign_attributes(row.to_hash) based on testing another and I did using the code above in the console, but with hard values.

I am trying to see what that code is doing now.

Upvotes: 0

Views: 1545

Answers (3)

Jake Kaad
Jake Kaad

Reputation: 103

This should work. Update will attempt to save the item before updating it so it works with new records as well as found records.

def self.import(csv_file)
  CSV.foreach(csv_file, headers: true) do |row|
    order = Order.find_or_initialize_by(projectid: row["projectid"], batch: row["batch"])
    if order.update(row.to_hash)
      true
    else
      false
    end
  end
end

Upvotes: 1

Shenanigator
Shenanigator

Reputation: 1066

The answer was multifaceted and Madcow, Daiku, and Jake to an extent all had a piece of it.

The updated code in the original post now works fantastically. I had put an id column in the csv file that I was uploading thinking it needed to be there to work. It did not need to be there, in fact it needed to not be there.

{"id"=>nil, "projectid"=>"IADTST1RWKP01", "batch"=>"1", "ppiho"=>"2015-11-02", "needby"=>"2015-10-02", "quantity"=>"192", "manufacturer"=>"Delta", "model"=>"US Cords", "CAR"=>nil, "cfnum"=>nil, "prnum"=>nil, "ponum"=>nil, "status"=>"Quote Completed", "contact"=>"Mike Salafia", "notes"=>nil}

when that hash was presented to the order it rejected it because id was trying to be set to nil and it cannot be nil. However, I don't need id in the csv file to find the order and update it or create a new order as the projectid and batch can be used for find and the id is auto assigned.

So I needed a return, Daiku made me look at the hash harder, and Jake's code would also likely work.

Upvotes: 0

madcow
madcow

Reputation: 2633

Ideas:

  1. Not sure exactly the context but if the use case includes updating the batch for an existing project_id, find_or_initialize_by is not finding the existing item because it is looking for a record that has both the same project_id and batch.

  2. Is projectid a typo? Should it be project_id?

Updated:

Also, you should have a return inside of the foreach loop or it will abort early.

Upvotes: 0

Related Questions