0

I'm trying to export and import two related models using FasterCSV. The first model is Task and the second model is PrecedingTask. Task has many preceding_tasks.

As you would expect, PrecedingTask references Task using the task_id field.

However, FasterCSV fails to load the task.id field from the .csv file data. Instead, task.id is populated using auto increment (as it normally would when running the rails application).

This breaks the relationship between Task and PrecedingTask.

Is there a way to suppress autoincrement when using FasterCSV? If not, what is the suggested workaround?

Here is the relevant Rake task:

def load_tasks
    csv.foreach("db/preceding_tasks.csv") do |row|
        PrecedingTask.create(
        :id                   => row[0],                
        :task_id              => row[1],        
        :predecessor_id       => row[2],
        :created_at           => row[3],      
        :updated_at           => row[4]  
        )
    end

    csv.foreach("db/tasks.csv") do |row|
        Task.create(
        :id                   => row[0],                
        :task_sequence        => row[1],        
        :name                 => row[2],
        :default_duration     => row[3],          
        :alert_code           => row[4],      
        :created_at           => row[5],      
        :updated_at           => row[6],    
        :optional             => row[7],    
        :start_trigger        => row[8],        
        :end_trigger          => row[9]     
        )
    end
end

________ UPDATE _________

Doh!

Turns out my Rake code was fine and I don't need to do anything special about auto increment.

The problem was that I did not include Task.id in the attr_accessible list, so it was being ignored. With that change, the ids are loaded as they appear in the task.csv file, and auto increment does not interfere.

Kevin
  • 744
  • 2
  • 7
  • 17

1 Answers1

1

I think what you want is this:

def load_tasks
    csv.foreach("db/tasks.csv") do |row|
        Task.create(
        :id                   => row[0],
        :task_sequence        => row[1],        
        :name                 => row[2],
        :default_duration     => row[3],          
        :alert_code           => row[4],      
        :created_at           => row[5],      
        :updated_at           => row[6],    
        :optional             => row[7],    
        :start_trigger        => row[8],        
        :end_trigger          => row[9]     
        )
    end

    csv.foreach("db/preceding_tasks.csv") do |row|
        t = Task.find(row[1])
        t.preceding_tasks.create(:predecessor_id => row[2], :created_at => row[3], :updated_at => row[4])
    end
end

The id of Task will be created on create, then all you want to do is create a preceding_task that belongs to a task. The task_id and id work for PrecedingTask will already be taken care of for you.

Chris Barretto
  • 9,379
  • 3
  • 42
  • 45
  • I think this is on the right track, but unless I'm overlooking something, it's not quite there. E.g. first record in task.csv has id of "3" (because id's "1" and "2" happened to be deleted). However, the first task record created will have an id of "1" because of autoincrement. When processing the related PrecedingTask, Task.find(row[1]) will translate to Task.find(3). It should be Task.find(1) because of the new id numbering. I think I need to create some sort of intermediate mapping. – Kevin Aug 30 '11 at 18:46
  • I see, just add id back into Task and that should solve your problems. In this context the preceding_task id doesn't really matter. Only task needs an explicit id to map to preceding_task.task_id – Chris Barretto Aug 30 '11 at 19:00