Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,23 @@ end

data-import provides a clean dsl to define your mappings from the legacy schema to the new one.

### Providing options ###

You may want to make your mappings configurable. Any options you pass into DataImport.run_config! will be passed through to the evaluation context of the provided mappings.

```ruby
import 'Things' do
if options[:validate_rows]
validate do ... end
end

seeds options[:seeds]
end

DataImport.run_config! 'path/to/mapping.rb', { :validate_rows => true, :seeds => { :key => value } }
```


### Before Filter ###

data-import allows you to definie a global filter. This filter can be used to make global transformations like encoding fixes. You can define a filter, which downcases every string like so:
Expand Down
2 changes: 1 addition & 1 deletion lib/data-import.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
module DataImport
class << self
def run_config!(config_paths, options = {})
plan = DataImport::Dsl.evaluate_import_config(config_paths)
plan = DataImport::Dsl.evaluate_import_config(config_paths, options)
run_plan!(plan, options)
end

Expand Down
19 changes: 11 additions & 8 deletions lib/data-import/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ module DataImport
class Dsl
class << self

def evaluate_import_config(files)
def evaluate_import_config(files, options = {})
plan = DataImport::ExecutionPlan.new
Array(files).each do |file|
context = new(plan)
context = new(plan, options)
context.instance_eval read_import_config(file), file
end
plan
end

def define(&block)
plan = DataImport::ExecutionPlan.new
context = new(plan)
def define(options = {}, &block)
plan = DataImport::ExecutionPlan.new([], options)
context = new(plan, options)
context.instance_eval &block
plan
end
Expand All @@ -28,8 +28,11 @@ def read_import_config(file)

end

def initialize(plan)
attr_reader :options

def initialize(plan, options = {})
@plan = plan
@options = options
end

def source_database
Expand All @@ -52,14 +55,14 @@ def import(name, &block)
definition = DataImport::Definition::Simple.new(name, source_database, target_database)
@plan.add_definition(definition)

Import.new(definition).instance_eval &block
Import.new(definition, options).instance_eval &block
end

def script(name, &block)
definition = DataImport::Definition::Script.new(name, source_database, target_database)
@plan.add_definition(definition)

Script.new(definition).instance_eval &block
Script.new(definition, options).instance_eval &block
end

def before_filter(&block)
Expand Down
5 changes: 3 additions & 2 deletions lib/data-import/dsl/import.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ class Dsl
class Import
include Dependencies

attr_reader :definition
attr_reader :definition, :options

def initialize(definition)
def initialize(definition, options = {})
@options = options
@definition = definition
end

Expand Down
5 changes: 3 additions & 2 deletions lib/data-import/dsl/script.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ class Dsl
class Script
include Dependencies

attr_reader :definition
attr_reader :definition, :options

def initialize(definition)
def initialize(definition, options = {})
@options = options
@definition = definition
end

Expand Down
7 changes: 4 additions & 3 deletions lib/data-import/execution_context.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
class ExecutionContext

attr_reader :progress_reporter
attr_reader :progress_reporter, :options

def initialize(execution_plan, definition, progress_reporter)
def initialize(execution_plan, definition, progress_reporter, options = nil)
@execution_plan = execution_plan
@options = options || execution_plan.options
@definition = definition
@progress_reporter = progress_reporter
end
Expand Down Expand Up @@ -33,7 +34,7 @@ def initialize(context)
@context = context
end

[:logger, :definition, :name, :source_database, :target_database].each do |method_symbol|
[:logger, :definition, :name, :source_database, :target_database, :options].each do |method_symbol|
define_method method_symbol do |*args|
@context.send(method_symbol, *args)
end
Expand Down
5 changes: 4 additions & 1 deletion lib/data-import/execution_plan.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
module DataImport
class ExecutionPlan
def initialize(definitions = [])
attr_reader :options

def initialize(definitions = [], options = {})
@options = options
@definitions = Hash[definitions.map do |definition|
[definition.name, definition]
end]
Expand Down
2 changes: 1 addition & 1 deletion lib/data-import/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def run(options = {})
bar = @progress_reporter.new(definition.name, definition.total_steps_required)

DataImport.logger.info "Starting to import \"#{definition.name}\""
context = ExecutionContext.new(resolved_plan, definition, bar)
context = ExecutionContext.new(resolved_plan, definition, bar, @plan.options)
definition.run context

bar.finish
Expand Down
69 changes: 69 additions & 0 deletions spec/acceptance/options_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
require 'acceptance/spec_helper'

describe 'logger' do

SEEDS = { :planet => 'Earth' }

OPTIONS = { :name_mapping => :name, :map_gender? => false, :validate => false, :seeds => SEEDS }

in_memory_mapping(OPTIONS) do
import 'with options' do
from 'Person'
to 'females'

mapping 'Name' => options[:name_mapping]

mapping 'options in a block mapping' do
if options[:map_gender?]
{ :gender => :gender }
end
end

if options[:validate]
validate_row do
if mapped_row[:gender] == 'f'
true
else
false
end
end
end

seed options[:seeds]
end

script 'Options test' do
body do
target_database.db[:females].insert(options[:seeds].merge(:name => 'Andy', :gender => 'm' ))
end
end
end

database_setup do
source.create_table :Person do
String :Name
String :Gender
end

target.create_table :females do
String :name
String :gender
String :planet
end

source[:Person].insert('Name' => 'Tina', 'Gender' => 'f')
source[:Person].insert('Name' => 'Jack', 'Gender' => 'm')
end

it 'provides options to the DSL' do
plan.options.should eq OPTIONS

DataImport.run_plan!(plan)

target_database[:females].count.should == 3
target_database[:females].first[:gender].should be nil
target_database[:females].first[:planet].should eq SEEDS[:planet]
target_database[:females].first(:name => 'Andy')[:planet].should eq SEEDS[:planet]
end

end
4 changes: 2 additions & 2 deletions spec/acceptance/support/macros.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

module TestingMacros

def in_memory_mapping(&block)
plan = DataImport::Dsl.define do
def in_memory_mapping(options = {}, &block)
plan = DataImport::Dsl.define(options) do
source 'sqlite:/'
target 'sqlite:/'

Expand Down
10 changes: 6 additions & 4 deletions spec/unit/data-import/dsl_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,17 @@
subject.import('a') {}
end

it "executes the block in an import context" do
it "executes the block in an import context with options" do
subject.stub(:source_database).and_return { nil }
subject.stub(:target_database).and_return { nil }
subject.stub(:options).and_return({})

my_block = lambda {}
import_dsl = stub
definition = stub
DataImport::Definition::Simple.should_receive(:new).with(any_args).and_return(definition)
plan.should_receive(:add_definition).with(definition)
DataImport::Dsl::Import.should_receive(:new).with(definition).and_return(import_dsl)
DataImport::Dsl::Import.should_receive(:new).with(definition, {}).and_return(import_dsl)

import_dsl.should_receive(:instance_eval).with(&my_block)
subject.import 'name', &my_block
Expand Down Expand Up @@ -123,15 +124,16 @@
subject.script('a') {}
end

it "executes the block in an script conext" do
it "executes the block in a script context with options" do
subject.stub(:source_database).and_return { nil }
subject.stub(:target_database).and_return { nil }
subject.stub(:options).and_return({})

my_block = lambda {}
script_dsl = stub
DataImport::Definition::Script.should_receive(:new).with(any_args).and_return(definition)
plan.should_receive(:add_definition).with(definition)
DataImport::Dsl::Script.should_receive(:new).with(definition).and_return(script_dsl)
DataImport::Dsl::Script.should_receive(:new).with(definition, {}).and_return(script_dsl)

script_dsl.should_receive(:instance_eval).with(&my_block)
subject.script 'name', &my_block
Expand Down
2 changes: 1 addition & 1 deletion spec/unit/data-import_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
let(:definitions) { [stub(:name => 'Artists'), stub(:name => 'Paints')] }

it "can execute a configuration file" do
DataImport::Dsl.should_receive(:evaluate_import_config).with('my_file').and_return(plan)
DataImport::Dsl.should_receive(:evaluate_import_config).with('my_file', :only => ['C']).and_return(plan)
DataImport::Runner.should_receive(:new).with(plan).and_return(runner)
runner.should_receive(:run).with(:only => ['C'])

Expand Down