itiel 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.autotest +17 -0
- data/.gitignore +13 -0
- data/.gitlab-ci.yml +36 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/Gemfile.rails.4.0 +7 -0
- data/Gemfile.rails.4.1 +7 -0
- data/Gemfile.rails.4.2 +7 -0
- data/README.markdown +106 -0
- data/Rakefile +13 -0
- data/build.sh +10 -0
- data/features/extract/database_table.feature +16 -0
- data/features/extract/sql_script.feature +17 -0
- data/features/load/database_table_loader.feature +21 -0
- data/features/lookup/csv_file.feature +41 -0
- data/features/lookup/database_table.feature +43 -0
- data/features/script/ruby_script.feature +19 -0
- data/features/step_definitions/csv_steps.rb +15 -0
- data/features/step_definitions/extractor/csv_file_steps.rb +3 -0
- data/features/step_definitions/extractor/custom_sql_steps.rb +6 -0
- data/features/step_definitions/extractor/database_steps.rb +27 -0
- data/features/step_definitions/extractor/database_table_steps.rb +8 -0
- data/features/step_definitions/extractor/extraction_steps.rb +3 -0
- data/features/step_definitions/flow_steps.rb +9 -0
- data/features/step_definitions/loader/csv_file_steps.rb +4 -0
- data/features/step_definitions/loader/database_table_steps.rb +14 -0
- data/features/step_definitions/lookup/lookup_steps.rb +35 -0
- data/features/step_definitions/scripting/ruby_script_steps.rb +5 -0
- data/features/step_definitions/stream_steps.rb +8 -0
- data/features/step_definitions/transformation/calculated_column_steps.rb +5 -0
- data/features/step_definitions/transformation/calculated_columns_steps.rb +7 -0
- data/features/step_definitions/transformation/constant_column_steps.rb +3 -0
- data/features/step_definitions/transformation/map_values_step.rb +4 -0
- data/features/step_definitions/transformation/rename_column_steps.rb +3 -0
- data/features/step_definitions/transformation/select_column_steps.rb +3 -0
- data/features/step_definitions/transformation/single_column_sort_steps.rb +3 -0
- data/features/support/database.yml +1 -0
- data/features/support/env.rb +13 -0
- data/features/transform/transformations.feature +123 -0
- data/itiel.gemspec +34 -0
- data/lib/itiel.rb +45 -0
- data/lib/itiel/db/connection.rb +24 -0
- data/lib/itiel/db/sql_connectable.rb +33 -0
- data/lib/itiel/db/truncator.rb +30 -0
- data/lib/itiel/extract/chained_step.rb +22 -0
- data/lib/itiel/extract/csv_file.rb +31 -0
- data/lib/itiel/extract/custom_sql.rb +38 -0
- data/lib/itiel/extract/database_table.rb +23 -0
- data/lib/itiel/job.rb +116 -0
- data/lib/itiel/load/chained_step.rb +37 -0
- data/lib/itiel/load/csv_file.rb +45 -0
- data/lib/itiel/load/database_table.rb +34 -0
- data/lib/itiel/load/input_output_behavior.rb +36 -0
- data/lib/itiel/logger.rb +47 -0
- data/lib/itiel/lookup/chained_step.rb +35 -0
- data/lib/itiel/lookup/csv_file.rb +16 -0
- data/lib/itiel/lookup/database_table.rb +36 -0
- data/lib/itiel/lookup/hash_lookup.rb +35 -0
- data/lib/itiel/nameable.rb +6 -0
- data/lib/itiel/script/chained_step.rb +18 -0
- data/lib/itiel/script/ruby_script.rb +31 -0
- data/lib/itiel/script/sql_script.rb +29 -0
- data/lib/itiel/transform/calculated_columns.rb +47 -0
- data/lib/itiel/transform/chained_step.rb +27 -0
- data/lib/itiel/transform/constant_column.rb +35 -0
- data/lib/itiel/transform/input_output_behavior.rb +44 -0
- data/lib/itiel/transform/map_values.rb +43 -0
- data/lib/itiel/transform/remove_column.rb +33 -0
- data/lib/itiel/transform/rename_column.rb +43 -0
- data/lib/itiel/transform/select_column.rb +37 -0
- data/lib/itiel/version.rb +3 -0
- data/spec/db/sql_connectable_spec.rb +20 -0
- data/spec/extract/chained_step_spec.rb +31 -0
- data/spec/extract/csv_file_spec.rb +22 -0
- data/spec/extract/custom_sql_spec.rb +19 -0
- data/spec/extract/database_table_spec.rb +22 -0
- data/spec/job_spec.rb +80 -0
- data/spec/loader/chained_step_spec.rb +39 -0
- data/spec/loader/csv_file_spec.rb +69 -0
- data/spec/loader/database_table_spec.rb +29 -0
- data/spec/lookup/hash_lookup_spec.rb +108 -0
- data/spec/nameable_spec.rb +17 -0
- data/spec/script/chained_step_spec.rb +24 -0
- data/spec/script/ruby_script_spec.rb +18 -0
- data/spec/script/sql_script_spec.rb +41 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/config/database.yml +1 -0
- data/spec/support/config/sources.yml +9 -0
- data/spec/transform/calculated_columns_spec.rb +36 -0
- data/spec/transform/chained_step_spec.rb +36 -0
- data/spec/transform/constant_column_spec.rb +22 -0
- data/spec/transform/map_values_spec.rb +26 -0
- data/spec/transform/rename_column_spec.rb +25 -0
- data/spec/transform/select_column_spec.rb +21 -0
- metadata +344 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
module Itiel
|
2
|
+
module Transform
|
3
|
+
#
|
4
|
+
# Renames a column in the data stream
|
5
|
+
#
|
6
|
+
# Usage:
|
7
|
+
#
|
8
|
+
# @transformer = Itiel::Transform::RenameColumn.new("order_id" => "id")
|
9
|
+
#
|
10
|
+
# This would rename the order_id column in the input stream to id
|
11
|
+
#
|
12
|
+
class RenameColumn
|
13
|
+
include ChainedStep
|
14
|
+
include Itiel::Nameable
|
15
|
+
|
16
|
+
attr_accessor :mappings
|
17
|
+
|
18
|
+
def initialize(*args)
|
19
|
+
self.mappings = args
|
20
|
+
end
|
21
|
+
|
22
|
+
def transform!(input_stream)
|
23
|
+
old_keys = self.mappings.first.keys
|
24
|
+
all_keys = input_stream.first.keys
|
25
|
+
|
26
|
+
transformed_output = []
|
27
|
+
input_stream.each do |object|
|
28
|
+
element = {}
|
29
|
+
all_keys.each do |k|
|
30
|
+
if old_keys.include?(k)
|
31
|
+
element[self.mappings.first[k]] = object[k]
|
32
|
+
else
|
33
|
+
element[k] = object[k]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
transformed_output << element
|
37
|
+
end
|
38
|
+
|
39
|
+
transformed_output
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Itiel
|
2
|
+
module Transform
|
3
|
+
#
|
4
|
+
# This transformation only selects specific columns on the data stream
|
5
|
+
#
|
6
|
+
# Usage:
|
7
|
+
#
|
8
|
+
# @transformer = Itiel::Transform::SelectColumn.new("order_id", "name")
|
9
|
+
#
|
10
|
+
# In the example, the output stream would only have the order_id and the name column
|
11
|
+
# All other columns will be ignored
|
12
|
+
#
|
13
|
+
class SelectColumn
|
14
|
+
include ChainedStep
|
15
|
+
include Itiel::Nameable
|
16
|
+
|
17
|
+
attr_accessor :mappings
|
18
|
+
|
19
|
+
def input=(stream)
|
20
|
+
next_step.input = transform!(stream)
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(*args)
|
24
|
+
self.mappings = args
|
25
|
+
end
|
26
|
+
|
27
|
+
def transform!(input_stream)
|
28
|
+
selected_output = []
|
29
|
+
input_stream.each do |object|
|
30
|
+
selected_output << object.select {|key, value| self.mappings.include? key }
|
31
|
+
end
|
32
|
+
|
33
|
+
selected_output
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Itiel::DB::SQLConnectable do
|
4
|
+
before :each do
|
5
|
+
class Step
|
6
|
+
include Itiel::DB::SQLConnectable
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
it "sets and gets connection_file_path" do
|
11
|
+
expect(Step).to respond_to :connection_file_path
|
12
|
+
expect(Step).to respond_to :connection_file_path=
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns a sequel_connection object based on the connection file" do
|
16
|
+
Step.connection_file_path = File.dirname(__FILE__) + '/../support/config/database.yml'
|
17
|
+
expect(Step.sequel_connection(:test)).to_not be_nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Itiel::Extract::ChainedStep do
|
4
|
+
before :each do
|
5
|
+
klass = Class.new
|
6
|
+
klass.send(:include, Itiel::Extract::ChainedStep)
|
7
|
+
@step = klass.new
|
8
|
+
|
9
|
+
@stream = double
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#start" do
|
13
|
+
before :each do
|
14
|
+
@next_step = double
|
15
|
+
@step.next_step = @next_step
|
16
|
+
end
|
17
|
+
|
18
|
+
it "extracts and sends the stream to the next step" do
|
19
|
+
allow(@step).to receive(:extract).and_return(@stream)
|
20
|
+
allow(@next_step).to receive(:input=).and_return(@stream)
|
21
|
+
|
22
|
+
@step.start
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#extract" do
|
27
|
+
it "raises an exception" do
|
28
|
+
expect { @step.extract }.to raise_error Itiel::MethodNotImplementedException
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Itiel::Extract::CSVFile do
|
4
|
+
before :each do
|
5
|
+
@step = Itiel::Extract::CSVFile.new 'FILENAME'
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#extract" do
|
9
|
+
it "reads a csv file and returns it as a hash to the stream" do
|
10
|
+
row = double
|
11
|
+
allow(row).to receive(:to_hash).and_return({data: true})
|
12
|
+
|
13
|
+
@stream = [ row ]
|
14
|
+
allow(CSV).to receive(:read).
|
15
|
+
with('FILENAME', headers: true).
|
16
|
+
and_return(@stream)
|
17
|
+
|
18
|
+
expect(@step.extract).to eq [{ data: true }]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Itiel::Extract::CustomSQL do
|
4
|
+
describe "#extract" do
|
5
|
+
before :each do
|
6
|
+
@step = Itiel::Extract::CustomSQL.new 'SCRIPT'
|
7
|
+
@step.connection = :test
|
8
|
+
end
|
9
|
+
|
10
|
+
it "Runs a script on the database and returns its results to the stream" do
|
11
|
+
result = double
|
12
|
+
allow(result).to receive(:all).and_return double
|
13
|
+
db = { 'SCRIPT' => result }
|
14
|
+
allow(Itiel::Extract::CustomSQL).to receive(:sequel_connection).with(:test).and_return db
|
15
|
+
|
16
|
+
expect(@step.extract).to eq result.all
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Itiel::Extract::DatabaseTable do
|
4
|
+
before :each do
|
5
|
+
@step = Itiel::Extract::DatabaseTable.new
|
6
|
+
@step.connection = :test
|
7
|
+
@step.table_name = 'table_name'
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#extract" do
|
11
|
+
it "returns all the rows in the specified database table" do
|
12
|
+
result = double
|
13
|
+
db = { table_name: result }
|
14
|
+
allow(result).to receive(:all).and_return double
|
15
|
+
expect(Itiel::Extract::DatabaseTable).
|
16
|
+
to receive(:sequel_connection).
|
17
|
+
with(:test).and_return db
|
18
|
+
|
19
|
+
expect(@step.extract).to eq result.all
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/spec/job_spec.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Itiel::Job do
|
4
|
+
describe "#run" do
|
5
|
+
it "yields a new instance of Itiel::Job" do
|
6
|
+
Itiel::Job.run { |object| expect(object).to be_instance_of(Itiel::Job) }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#define" do
|
11
|
+
it "returns an instance of Itiel::Job" do
|
12
|
+
expect(Itiel::Job.define).to be_instance_of(Itiel::Job)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "yields a new instance of Itiel::Job" do
|
16
|
+
Itiel::Job.define {|object| assert_instance_of(Itiel::Job, object)}
|
17
|
+
end
|
18
|
+
|
19
|
+
it "sets given block as the block attribute of the instance it returns" do
|
20
|
+
block = Proc.new {}
|
21
|
+
job = Itiel::Job.define(&block)
|
22
|
+
expect(block).to eq job.block
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#run!" do
|
27
|
+
it "calls the block on self.block" do
|
28
|
+
block = Proc.new {}
|
29
|
+
expect(block).to receive(:call)
|
30
|
+
job = Itiel::Job.define(&block)
|
31
|
+
job.run!
|
32
|
+
end
|
33
|
+
|
34
|
+
it "responds to step inside the block" do
|
35
|
+
@object = double
|
36
|
+
instanced_job = Itiel::Job.define do |job|
|
37
|
+
job.step @object
|
38
|
+
end
|
39
|
+
|
40
|
+
expect(instanced_job).to receive(:step).with(@object)
|
41
|
+
instanced_job.run!
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#step" do
|
46
|
+
before :each do
|
47
|
+
@job = Itiel::Job.new
|
48
|
+
@source = double
|
49
|
+
@destination = double
|
50
|
+
@stream = double
|
51
|
+
|
52
|
+
allow(@source).to receive(:output).and_return @stream
|
53
|
+
expect(@destination).to receive(:input=).and_return @stream
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "@source => @destination" do
|
57
|
+
it "hardwires the @destination's input with the @source output" do
|
58
|
+
@job.step @source => @destination
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "step @source; step @destination" do
|
63
|
+
it "hardwires the @destination's input with the @source output" do
|
64
|
+
expect(@destination).to receive(:output)
|
65
|
+
@job.step @source
|
66
|
+
@job.step @destination
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "step @source => [ @destination, @second_destination ]" do
|
71
|
+
it "hardwires both destination's inputs with the @source output" do
|
72
|
+
@second_destination = double
|
73
|
+
expect(@second_destination).to receive(:input=).and_return @stream
|
74
|
+
|
75
|
+
@job.step @source => [@destination, @second_destination]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Itiel::Load::ChainedStep do
|
4
|
+
before :each do
|
5
|
+
klass = Class.new
|
6
|
+
klass.send :include, Itiel::Load::ChainedStep
|
7
|
+
|
8
|
+
@step = klass.new
|
9
|
+
end
|
10
|
+
|
11
|
+
it "defines next_step" do
|
12
|
+
expect(@step).to respond_to(:next_step)
|
13
|
+
expect(@step).to respond_to(:next_step=)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe :persist do
|
17
|
+
it "raises an error if undefined" do
|
18
|
+
expect { @step.persist([]) }.to raise_error Itiel::MethodNotImplementedException
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe :input= do
|
23
|
+
before :each do
|
24
|
+
@next_step = double
|
25
|
+
@input = [ double ]
|
26
|
+
@step.next_step = @next_step
|
27
|
+
|
28
|
+
expect(Itiel::Logger).to receive(:log_received).with(@step, @input.size)
|
29
|
+
expect(Itiel::Logger).to receive(:log_processed).with(@step, @input.size)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "calls persist with the stream received through input= and sends it to next_step" do
|
33
|
+
expect(@step).to receive(:persist).with @input
|
34
|
+
expect(@next_step).to receive(:input=).with @input
|
35
|
+
@step.input = @input
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Itiel::Load::CSVFile do
|
4
|
+
before :each do
|
5
|
+
@filename = File.expand_path("#{File.dirname(__FILE__)}/../../tmp/output.csv")
|
6
|
+
File.unlink(@filename) if File.exist?(@filename)
|
7
|
+
|
8
|
+
@input = [
|
9
|
+
{
|
10
|
+
"id" => 1,
|
11
|
+
"name" => "Subject Name"
|
12
|
+
},
|
13
|
+
{
|
14
|
+
"id" => 2,
|
15
|
+
"name" => "Subject Name"
|
16
|
+
}
|
17
|
+
]
|
18
|
+
|
19
|
+
@expected_result = [
|
20
|
+
[ "id" , "name" ] ,
|
21
|
+
[ "1" , "Subject Name" ] ,
|
22
|
+
[ "2" , "Subject Name" ]
|
23
|
+
]
|
24
|
+
|
25
|
+
@csv_output = Itiel::Load::CSVFile.new(@filename)
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "the file does not exist" do
|
29
|
+
before :each do
|
30
|
+
@csv_output.persist(@input)
|
31
|
+
@result = CSV.read(@filename, :headers => true)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "generates a CSV file with the input data" do
|
35
|
+
expect(@expected_result).to eq @result.to_a
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "the file already exists" do
|
40
|
+
before :each do
|
41
|
+
FileUtils.touch(@filename)
|
42
|
+
@csv_output.persist(@input)
|
43
|
+
@result = CSV.read(@filename)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "appends to the existing data" do
|
47
|
+
expect(@expected_result - [[ "id", "name" ]]).to eq @result
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "use append = false" do
|
52
|
+
before do
|
53
|
+
@csv_output = Itiel::Load::CSVFile.new(@filename, false)
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "the file already exists" do
|
57
|
+
before :each do
|
58
|
+
FileUtils.touch(@filename)
|
59
|
+
@csv_output.persist(@input)
|
60
|
+
@result = CSV.read(@filename)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "replaces the existing file with the input data" do
|
64
|
+
expect(@expected_result).to eq @result
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Itiel::Load::DatabaseTable do
|
4
|
+
before(:each) do
|
5
|
+
@output = Itiel::Load::DatabaseTable.new :test, "users"
|
6
|
+
@input = [
|
7
|
+
{
|
8
|
+
"id" => "1",
|
9
|
+
"name" => "Some Name"
|
10
|
+
},
|
11
|
+
{
|
12
|
+
"id" => "2",
|
13
|
+
"name" => "Some Other Name"
|
14
|
+
},
|
15
|
+
]
|
16
|
+
end
|
17
|
+
|
18
|
+
it "inserts a record for each row" do
|
19
|
+
table = double
|
20
|
+
allow(@output).to receive(:table).and_return table
|
21
|
+
|
22
|
+
@input.each do |row|
|
23
|
+
expect(table).to receive(:insert).and_return row
|
24
|
+
end
|
25
|
+
|
26
|
+
@output.persist(@input)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Itiel::Lookup::HashLookup do
|
4
|
+
before(:each) do
|
5
|
+
@input = [
|
6
|
+
{
|
7
|
+
:id => 1,
|
8
|
+
:author => "Isaac"
|
9
|
+
},
|
10
|
+
{
|
11
|
+
:id => 2,
|
12
|
+
:author => "Carver"
|
13
|
+
}
|
14
|
+
]
|
15
|
+
|
16
|
+
@lookup_source = [
|
17
|
+
{
|
18
|
+
:id => 1,
|
19
|
+
:name => "Isaac",
|
20
|
+
:active => "t"
|
21
|
+
},
|
22
|
+
{
|
23
|
+
:id => 2,
|
24
|
+
:name => "Carver",
|
25
|
+
:active => "f"
|
26
|
+
}
|
27
|
+
]
|
28
|
+
|
29
|
+
@lookup_stream = {
|
30
|
+
"Isaac" => {
|
31
|
+
:author_id => 1,
|
32
|
+
:active => "t"
|
33
|
+
},
|
34
|
+
|
35
|
+
"Carver" => {
|
36
|
+
:author_id => 2,
|
37
|
+
:active => "f"
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
@expected_output = [
|
42
|
+
{
|
43
|
+
:id => 1,
|
44
|
+
:author => "Isaac",
|
45
|
+
:author_id => 1,
|
46
|
+
:active => "t"
|
47
|
+
},
|
48
|
+
{
|
49
|
+
:id => 2,
|
50
|
+
:author => "Carver",
|
51
|
+
:author_id => 2,
|
52
|
+
:active => "f"
|
53
|
+
}
|
54
|
+
]
|
55
|
+
|
56
|
+
class FooLookup
|
57
|
+
include Itiel::Lookup::HashLookup
|
58
|
+
end
|
59
|
+
|
60
|
+
@lookup = FooLookup.new
|
61
|
+
@lookup.lookup_columns = { "author" => "name" }
|
62
|
+
@lookup.joined_columns = { "id" => "author_id", "active" => "active" }
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "#lookup!" do
|
66
|
+
it "joins the data using the specified column" do
|
67
|
+
allow(@lookup).to receive(:lookup_stream).and_return @lookup_stream
|
68
|
+
expect(@expected_output).to eq @lookup.lookup!(@input)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#lookup_stream" do
|
73
|
+
it do
|
74
|
+
allow(@lookup).to receive(:lookup_source).and_return @lookup_source
|
75
|
+
expect(@lookup_stream).to eq @lookup.lookup_stream
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe 'with nil values in the lookup column' do
|
80
|
+
before do
|
81
|
+
@input.append({ id: 3, author: nil })
|
82
|
+
@expected_output.append({ id: 3, author: nil, author_id: nil, active: nil })
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#lookup!" do
|
86
|
+
it 'joins the data setting the value to nil' do
|
87
|
+
allow(@lookup).to receive(:lookup_stream).and_return @lookup_stream
|
88
|
+
expect(@expected_output).to eq @lookup.lookup!(@input)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "When the lookup column doesn't exist in the input_stream" do
|
94
|
+
before do
|
95
|
+
@input.append({ id: 3 })
|
96
|
+
@expected_output.append({ id: 3, author_id: nil, active: nil })
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#lookup!" do
|
100
|
+
it 'joins the data setting the value to nil' do
|
101
|
+
allow(@lookup).to receive(:lookup_stream).and_return @lookup_stream
|
102
|
+
|
103
|
+
expect(@expected_output).to eq @lookup.lookup!(@input)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|