Saturday, February 16, 2008

Rake Script to Load Seed Data or Update Existing Data

In the previous blog we descussed loading of seed data using rake/active record.
What was missing was examples.

So First a example of our "rake" file.

namespace :project do
desc 'parts_master_load'
task :parts_master_load => :environment do
PartsMaster.uoc :pn => '11-1111-11',
:description => 'Part description for part 11-111-11',
:application_code => ApplicationCode.foc('appcode1'),
:pn_type_code => PnTypeCode.foc('REF')
PartsMaster.uoc :pn => '22-2222-22',
:description => 'Part Description for part 22-222-22',
:application_code => ApplicationCode.foc('apcode2'),
:pn_type_code => PnTypeCode.foc('REF')
end
end

Rake has the advantage in that it runs with all of rails environment, and for us that means activerecord, so we can use our "models". Another advantage is if there is a error, if you have the rake trace option, you get exactly the line of "data" that caused the issue.


In the above example, there are "three" models that are directly mentioned.
One is the PartsMaster, Two is the ApplicationCode, and the Third is the PnTypeCode.

The "method" foc is one of my own, that means "find" or "create". Very handly for those "simple" tables that are used for "catagories".

So as a example of "foc" as used in the "application" code module.

class ApplicationCode < ActiveRecord::Base
set_table_name "APPLICATION_CODES"

defaults :application_code => "",
:cannot_modify => "F",
:converted => "F",

public


def self.foc(thevalue) #find_or_create
if thevalue.nil?
thevalue = "_"
end
if thevalue == ""
thevalue = "_"
end
therecord = find(:first,:conditions => "application_code = '#{thevalue}'")
if therecord
return therecord
end
therecord = self.new
therecord.application_code = thevalue
therecord.description = thevalue
therecord.save
return therecord
end

end

Here you can see the power of "foc". We actually use the "application" key to do a "lookup", on existing data. We can "also" cleanup any "issues" with the "incoming" data, to make it more "consistent". If the record "does" not exist, then the record is created. This also is good illustration of "default" values to make usage of the model "easier".

Now lets look at a "stippet" of the "update or create" or uoc method. For the main
table in the application, we need to update existing records, since the file has constraints, so we cannot "truncate" the table, and aways do a "create".

def self.uoc(options = {}) # update or create
thevalue = options[:pn] #fixme - Need to also look at manufactuer
record = find(:first,:conditions => "pn = '#{thevalue}'")
if record.nil?
record = new
end
record.attributes = options
record.save!

record
end

This illustrates a lovely "concept" in ruby of allowing us to use a hash, allowing us to take variable arguments in, and pass those variable arguments down. Code looks simple. I could code the same in "C" and it would be rather ugly.

In this code, the "new" will create a record, and establish defaults (The record has a couple hundred fields, so defaults is "not" small.) and then "update" it with what we pass. That allows the "create" rake script to be very small.

So there you have it. From now own, I'm going to use active record to do my data load and migration. It works very nice.

1 comment:

Leane said...

This is great info to know.