transfer 0.0.1
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.
- data/Gemfile +4 -0
- data/README.md +172 -0
- data/Rakefile +1 -0
- data/lib/transfer/config.rb +34 -0
- data/lib/transfer/generators/active_record.rb +31 -0
- data/lib/transfer/generators/base.rb +26 -0
- data/lib/transfer/generators/mongoid.rb +28 -0
- data/lib/transfer/generators/sequel.rb +47 -0
- data/lib/transfer/transferer.rb +90 -0
- data/lib/transfer/version.rb +3 -0
- data/lib/transfer.rb +50 -0
- data/spec/fabricators/user_fabricator.rb +9 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/support/active_record.rb +42 -0
- data/spec/support/mongoid.rb +38 -0
- data/spec/support/sequel.rb +45 -0
- data/spec/support/shared_examples_for_generators.rb +64 -0
- data/spec/support/shared_examples_for_transfer.rb +154 -0
- data/spec/support/source.rb +26 -0
- data/spec/transfer/config_spec.rb +116 -0
- data/spec/transfer/generators/active_record_spec.rb +13 -0
- data/spec/transfer/generators/mongoid_spec.rb +13 -0
- data/spec/transfer/generators/sequel_spec.rb +13 -0
- data/spec/transfer/transferer_spec.rb +123 -0
- data/spec/transfer_spec.rb +174 -0
- data/transfer.gemspec +30 -0
- metadata +161 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
shared_examples "a generator" do
|
|
5
|
+
subject { generator.new klass }
|
|
6
|
+
|
|
7
|
+
it { should respond_to :create }
|
|
8
|
+
it { should respond_to :column_present? }
|
|
9
|
+
|
|
10
|
+
describe "#column_present?" do
|
|
11
|
+
it :first_name do
|
|
12
|
+
subject.column_present?(:first_name).should be_true
|
|
13
|
+
end
|
|
14
|
+
it :last_name do
|
|
15
|
+
subject.column_present?(:last_name).should be_true
|
|
16
|
+
end
|
|
17
|
+
it :full_name do
|
|
18
|
+
subject.column_present?(:full_name).should be_true
|
|
19
|
+
end
|
|
20
|
+
it :before_save_value do
|
|
21
|
+
subject.column_present?(:before_save_value).should be_true
|
|
22
|
+
end
|
|
23
|
+
it :dynamic_value do
|
|
24
|
+
subject.column_present?(:dynamic_value).should be_true
|
|
25
|
+
end
|
|
26
|
+
it :undefined do
|
|
27
|
+
subject.column_present?(:undefined).should be_false
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe "#create" do
|
|
32
|
+
let(:attributes) {{}}
|
|
33
|
+
let(:row) {{}}
|
|
34
|
+
let(:options) {{}}
|
|
35
|
+
let(:callbacks) {{}}
|
|
36
|
+
|
|
37
|
+
def do_action
|
|
38
|
+
subject.create attributes, row, options, callbacks
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should return correct type" do
|
|
42
|
+
do_action.should be_instance_of klass
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context "with #save throws an exception" do
|
|
46
|
+
before do
|
|
47
|
+
save_failure klass
|
|
48
|
+
end
|
|
49
|
+
context ":failure_startegy=>:ignore" do
|
|
50
|
+
let(:options) { {:failure_strategy => :ignore} }
|
|
51
|
+
it "not raise exception" do
|
|
52
|
+
expect{ do_action }.to_not raise_error
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
context ":failure_startegy=>:ignore" do
|
|
56
|
+
let(:options) { {:failure_strategy => :rollback} }
|
|
57
|
+
it "raise exception" do
|
|
58
|
+
expect{ do_action }.to raise_error
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
shared_examples "a transfer johnny hollow" do
|
|
4
|
+
let!(:user) { Fabricate :johnny_hollow }
|
|
5
|
+
|
|
6
|
+
it "should change count records from 0 to 1" do
|
|
7
|
+
expect{ do_action }.to change{ klass.count }.from(0).to(1)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe "first record" do
|
|
11
|
+
subject { klass.first }
|
|
12
|
+
|
|
13
|
+
before do
|
|
14
|
+
do_action do
|
|
15
|
+
first_name :fname
|
|
16
|
+
last_name :lname
|
|
17
|
+
full_name {|r| "#{r[:fname]} #{r[:lname]}" }
|
|
18
|
+
protected_value "flash"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it { should be }
|
|
23
|
+
its(:id) { should == user.id }
|
|
24
|
+
its(:first_name) { should == "Johnny" }
|
|
25
|
+
its(:last_name) { should == "Hollow" }
|
|
26
|
+
its(:full_name) { should == "Johnny Hollow" }
|
|
27
|
+
its(:protected_value) { should == "flash" }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe "callbacks" do
|
|
31
|
+
subject { klass.first }
|
|
32
|
+
|
|
33
|
+
it "should call before_save" do
|
|
34
|
+
do_action do
|
|
35
|
+
before_save do |row|
|
|
36
|
+
self.before_save_value = row[:fname]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
subject.before_save_value == "Johnny"
|
|
40
|
+
end
|
|
41
|
+
it "should call after_save" do
|
|
42
|
+
value = nil
|
|
43
|
+
do_action do
|
|
44
|
+
after_save do |row|
|
|
45
|
+
value = row[:fname]
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
value.should == "Johnny"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context "if #save throws an exception" do
|
|
52
|
+
include_context "stub klass model"
|
|
53
|
+
before do
|
|
54
|
+
save_failure klass
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "should call before_save" do
|
|
58
|
+
do_action do
|
|
59
|
+
before_save do |row|
|
|
60
|
+
self.dynamic_value = row[:fname]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
model.dynamic_value == "Johnny"
|
|
64
|
+
end
|
|
65
|
+
it "should not call after_save" do
|
|
66
|
+
do_action do
|
|
67
|
+
after_save do |row|
|
|
68
|
+
self.dynamic_value = row[:fname]
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
model.dynamic_value.should be_nil
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
shared_examples "a not transfer johnny hollow" do
|
|
79
|
+
let!(:user) { Fabricate :johnny_hollow }
|
|
80
|
+
it "should count not changed" do
|
|
81
|
+
expect{ do_action }.to_not change{ klass.count }
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
shared_examples "a transfer" do
|
|
86
|
+
context SequelUser do
|
|
87
|
+
let!(:klass) { SequelUser }
|
|
88
|
+
it_should_behave_like "a transfer johnny hollow"
|
|
89
|
+
end
|
|
90
|
+
context ActiveRecordUser do
|
|
91
|
+
let!(:klass) { ActiveRecordUser }
|
|
92
|
+
it_should_behave_like "a transfer johnny hollow"
|
|
93
|
+
end
|
|
94
|
+
context MongoidUser do
|
|
95
|
+
let!(:klass) { MongoidUser }
|
|
96
|
+
it_should_behave_like "a transfer johnny hollow"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
shared_examples "a not transfer" do
|
|
101
|
+
let!(:user) { Fabricate :johnny_hollow }
|
|
102
|
+
|
|
103
|
+
context SequelUser do
|
|
104
|
+
let!(:klass) { SequelUser }
|
|
105
|
+
it_should_behave_like "a not transfer johnny hollow"
|
|
106
|
+
end
|
|
107
|
+
context ActiveRecordUser do
|
|
108
|
+
let!(:klass) { ActiveRecordUser }
|
|
109
|
+
it_should_behave_like "a not transfer johnny hollow"
|
|
110
|
+
end
|
|
111
|
+
context MongoidUser do
|
|
112
|
+
let!(:klass) { MongoidUser }
|
|
113
|
+
it_should_behave_like "a not transfer johnny hollow"
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
shared_examples "a transfer with false validation" do
|
|
118
|
+
context SequelUserWithFalseValidation do
|
|
119
|
+
let!(:klass) { SequelUserWithFalseValidation }
|
|
120
|
+
it_should_behave_like "a transfer johnny hollow"
|
|
121
|
+
end
|
|
122
|
+
context ActiveRecordUserWithFalseValidation do
|
|
123
|
+
let!(:klass) { ActiveRecordUserWithFalseValidation }
|
|
124
|
+
it_should_behave_like "a transfer johnny hollow"
|
|
125
|
+
end
|
|
126
|
+
context MongoidUserWithFalseValidation do
|
|
127
|
+
let!(:klass) { MongoidUserWithFalseValidation }
|
|
128
|
+
it_should_behave_like "a transfer johnny hollow"
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
shared_examples "a not transfer with false validation" do
|
|
133
|
+
let!(:user) { Fabricate :johnny_hollow }
|
|
134
|
+
|
|
135
|
+
context SequelUserWithFalseValidation do
|
|
136
|
+
let!(:klass) { SequelUserWithFalseValidation }
|
|
137
|
+
it_should_behave_like "a not transfer johnny hollow"
|
|
138
|
+
end
|
|
139
|
+
context ActiveRecordUserWithFalseValidation do
|
|
140
|
+
let!(:klass) { ActiveRecordUserWithFalseValidation }
|
|
141
|
+
it_should_behave_like "a not transfer johnny hollow"
|
|
142
|
+
end
|
|
143
|
+
context MongoidUserWithFalseValidation do
|
|
144
|
+
let!(:klass) { MongoidUserWithFalseValidation }
|
|
145
|
+
it_should_behave_like "a not transfer johnny hollow"
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
shared_context "stub klass model" do
|
|
150
|
+
let!(:model) { klass.new }
|
|
151
|
+
before do
|
|
152
|
+
stub(klass).new { model }
|
|
153
|
+
end
|
|
154
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'sequel'
|
|
2
|
+
|
|
3
|
+
Sequel.extension :migration
|
|
4
|
+
|
|
5
|
+
SOURCE_DB = Sequel.sqlite
|
|
6
|
+
|
|
7
|
+
class SourceUserMigration < Sequel::Migration
|
|
8
|
+
def up
|
|
9
|
+
create_table! :source_users, :force => true do
|
|
10
|
+
primary_key :id
|
|
11
|
+
String :fname
|
|
12
|
+
String :lname
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
def down
|
|
16
|
+
drop_table :source_users
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class SourceUser < Sequel::Model
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
SourceUserMigration.apply SOURCE_DB, :up
|
|
26
|
+
SourceUser.db = SOURCE_DB
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
module Transfer
|
|
5
|
+
describe Config do
|
|
6
|
+
subject { Config.new options }
|
|
7
|
+
|
|
8
|
+
describe "#process_options" do
|
|
9
|
+
context "by default" do
|
|
10
|
+
let!(:options) { {} }
|
|
11
|
+
its(:process_options) { should == { :validate => true, :failure_strategy => :ignore } }
|
|
12
|
+
end
|
|
13
|
+
context "set options" do
|
|
14
|
+
let!(:options) { { :validate => false, :failure_strategy => :rollback, :failure => lambda{} } }
|
|
15
|
+
its(:process_options) { should == options }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe "#connection_options" do
|
|
20
|
+
context "by default" do
|
|
21
|
+
let!(:options) { {} }
|
|
22
|
+
its(:connection_options) { should be_empty }
|
|
23
|
+
end
|
|
24
|
+
context "set options" do
|
|
25
|
+
let!(:options) { { :adapter => "sqlite", :host => "localhost" } }
|
|
26
|
+
its(:connection_options) { should == options }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe "#connection" do
|
|
31
|
+
let!(:options) { { :adapter => "sqlite", :host => "localhost" } }
|
|
32
|
+
before do
|
|
33
|
+
stub(Sequel).connect(options) { :bingo }
|
|
34
|
+
end
|
|
35
|
+
its(:connection) { should be :bingo }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe "added new options" do
|
|
39
|
+
let!(:options) { {} }
|
|
40
|
+
|
|
41
|
+
describe "#validate" do
|
|
42
|
+
before do
|
|
43
|
+
subject.validate = false
|
|
44
|
+
end
|
|
45
|
+
its(:validate) { should be_false }
|
|
46
|
+
its(:process_options) { should include(:validate => false) }
|
|
47
|
+
its(:connection_options) { should_not include(:validate) }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe "#failure_strategy" do
|
|
51
|
+
before do
|
|
52
|
+
subject.failure_strategy = :rollback
|
|
53
|
+
end
|
|
54
|
+
its(:failure_strategy) { should == :rollback }
|
|
55
|
+
its(:process_options) { should include(:failure_strategy => :rollback) }
|
|
56
|
+
its(:connection_options) { should_not include(:failure_strategy) }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe "#failure" do
|
|
60
|
+
context "with block" do
|
|
61
|
+
before do
|
|
62
|
+
subject.failure {}
|
|
63
|
+
end
|
|
64
|
+
its(:failure) { should be_instance_of Proc }
|
|
65
|
+
its(:process_options) { should include(:failure) }
|
|
66
|
+
its(:connection_options) { should_not include(:failure) }
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe "#before" do
|
|
71
|
+
before do
|
|
72
|
+
subject.before {}
|
|
73
|
+
end
|
|
74
|
+
its(:before) { should be_instance_of Proc }
|
|
75
|
+
its(:process_options) { should include(:before) }
|
|
76
|
+
its(:connection_options) { should_not include(:before) }
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
describe "#after" do
|
|
80
|
+
before do
|
|
81
|
+
subject.after {}
|
|
82
|
+
end
|
|
83
|
+
its(:after) { should be_instance_of Proc }
|
|
84
|
+
its(:process_options) { should include(:after) }
|
|
85
|
+
its(:connection_options) { should_not include(:after) }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe "#success" do
|
|
89
|
+
before do
|
|
90
|
+
subject.success {}
|
|
91
|
+
end
|
|
92
|
+
its(:success) { should be_instance_of Proc }
|
|
93
|
+
its(:process_options) { should include(:success) }
|
|
94
|
+
its(:connection_options) { should_not include(:success) }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe "#other=" do
|
|
98
|
+
before do
|
|
99
|
+
subject.host = "localhost"
|
|
100
|
+
end
|
|
101
|
+
its(:host) { should == "localhost" }
|
|
102
|
+
its(:connection_options) { should include(:host => "localhost") }
|
|
103
|
+
its(:process_options) { should_not include(:host) }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
describe "#other &block" do
|
|
107
|
+
before do
|
|
108
|
+
subject.host {}
|
|
109
|
+
end
|
|
110
|
+
its(:host) { should be_instance_of Proc }
|
|
111
|
+
its(:connection_options) { should include(:host) }
|
|
112
|
+
its(:process_options) { should_not include(:host) }
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
module Transfer
|
|
5
|
+
describe Transferer do
|
|
6
|
+
let!(:dataset) { SOURCE_DB[:source_users] }
|
|
7
|
+
|
|
8
|
+
describe "#columns" do
|
|
9
|
+
def do_action klass, &block
|
|
10
|
+
Transferer.new(dataset, klass, &block).columns.keys
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
[SequelUser, ActiveRecordUser, MongoidUser].each do |klass|
|
|
14
|
+
context klass do
|
|
15
|
+
it "with block" do
|
|
16
|
+
do_action(klass) do
|
|
17
|
+
first_name :fname
|
|
18
|
+
last_name :lname
|
|
19
|
+
end.should == [:id, :first_name, :last_name]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "raise error if column not exists in source" do
|
|
23
|
+
expect{ do_action(klass) { first_name :undefined } }.to raise_error(ArgumentError, "source column #undefined not exists!")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "raise error if column not exists in destination class" do
|
|
27
|
+
expect{ do_action(klass) { undefined :fname } }.to raise_error(ArgumentError, "method #undefined in class #{klass} is not defined!")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "filter columns with #except" do
|
|
31
|
+
do_action(klass) do
|
|
32
|
+
except :id
|
|
33
|
+
end.should == []
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "filter columns with #only" do
|
|
37
|
+
do_action(klass) do
|
|
38
|
+
first_name :fname
|
|
39
|
+
last_name :lname
|
|
40
|
+
only :last_name
|
|
41
|
+
end.should == [:last_name]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe "#generator" do
|
|
48
|
+
subject { Transferer.new(dataset, @klass).generator }
|
|
49
|
+
|
|
50
|
+
it Generators::Sequel do
|
|
51
|
+
@klass = SequelUser
|
|
52
|
+
should be_instance_of Generators::Sequel
|
|
53
|
+
end
|
|
54
|
+
it Generators::ActiveRecord do
|
|
55
|
+
@klass = ActiveRecordUser
|
|
56
|
+
should be_instance_of Generators::ActiveRecord
|
|
57
|
+
end
|
|
58
|
+
it Generators::Mongoid do
|
|
59
|
+
@klass = MongoidUser
|
|
60
|
+
should be_instance_of Generators::Mongoid
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe "#callbacks" do
|
|
65
|
+
subject do
|
|
66
|
+
Transferer.new dataset, klass do
|
|
67
|
+
before_save do;end
|
|
68
|
+
after_save do;end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
[SequelUser, ActiveRecordUser, MongoidUser].each do |klass|
|
|
73
|
+
context klass do
|
|
74
|
+
let!(:klass) { klass }
|
|
75
|
+
its(:callbacks) { should be_include :before_save }
|
|
76
|
+
its(:callbacks) { should be_include :after_save }
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe "#process" do
|
|
82
|
+
def do_action o=options, &block
|
|
83
|
+
Transferer.new(dataset, klass, &block).process(o)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
context "with empty options" do
|
|
87
|
+
let!(:options) { {} }
|
|
88
|
+
it_should_behave_like "a transfer"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
context "with options :validate => true" do
|
|
92
|
+
let!(:options) { {:validate => true} }
|
|
93
|
+
it_should_behave_like "a transfer"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
context "with options :validate => false" do
|
|
97
|
+
let!(:options) { {:validate => false} }
|
|
98
|
+
it_should_behave_like "a transfer with false validation"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
context "if model#save throws an exception" do
|
|
102
|
+
let!(:olivia) { Fabricate :olivia_lufkin }
|
|
103
|
+
before do
|
|
104
|
+
stub.proxy(klass).new do |model|
|
|
105
|
+
save_failure(model) if model.id == olivia.id
|
|
106
|
+
model
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
context "with options :failure_strategy => :ignore" do
|
|
111
|
+
let!(:options) { {:failure_strategy => :ignore} }
|
|
112
|
+
it_should_behave_like "a transfer"
|
|
113
|
+
end
|
|
114
|
+
context "with options :failure_strategy => :rollback" do
|
|
115
|
+
let!(:options) { {:failure_strategy => :rollback} }
|
|
116
|
+
it_should_behave_like "a not transfer"
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
describe Transfer do
|
|
5
|
+
subject { Transfer }
|
|
6
|
+
|
|
7
|
+
it { should respond_to :configs }
|
|
8
|
+
it { should respond_to :configure }
|
|
9
|
+
|
|
10
|
+
before do
|
|
11
|
+
Transfer.configs.clear
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe ".configs" do
|
|
15
|
+
subject { Transfer.configs }
|
|
16
|
+
|
|
17
|
+
it { should be_instance_of Hash }
|
|
18
|
+
it "raise error if key not exists" do
|
|
19
|
+
expect{ subject[:anything] }.to raise_error
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe ".configure" do
|
|
24
|
+
context ":default" do
|
|
25
|
+
subject { Transfer.configs[:default] }
|
|
26
|
+
before do
|
|
27
|
+
Transfer.configure {|c| c.host = "default"}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it { should be_instance_of Transfer::Config }
|
|
31
|
+
its(:host) { should == "default" }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context ":named" do
|
|
35
|
+
subject { Transfer.configs[:named] }
|
|
36
|
+
before do
|
|
37
|
+
Transfer.configure(:named) {|c| c.host = "named" }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it { should be_instance_of Transfer::Config }
|
|
41
|
+
its(:host) { should == "named" }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe "transfer" do
|
|
46
|
+
def do_action &block
|
|
47
|
+
transfer :source_users => klass, &block
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
before do
|
|
51
|
+
instance_of(Transfer::Config).connection { SOURCE_DB }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context "with empty" do
|
|
55
|
+
before do
|
|
56
|
+
Transfer.configure
|
|
57
|
+
end
|
|
58
|
+
it_should_behave_like "a transfer"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context "with :validate => false" do
|
|
62
|
+
before do
|
|
63
|
+
Transfer.configure do |config|
|
|
64
|
+
config.validate = false
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
it_should_behave_like "a transfer with false validation"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context "olivia_lufkin and johnny_hollow" do
|
|
71
|
+
let!(:olivia) { Fabricate :olivia_lufkin }
|
|
72
|
+
before do
|
|
73
|
+
Transfer.configure do |config|
|
|
74
|
+
config.failure_strategy = failure_strategy
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
context "while olivia#save throws an exception" do
|
|
79
|
+
before do
|
|
80
|
+
stub.proxy(klass).new do |model|
|
|
81
|
+
save_failure(model) if model.id == olivia.id
|
|
82
|
+
model
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
context "with Transfer.failure_strategy = :ignore" do
|
|
87
|
+
let!(:failure_strategy) { :ignore }
|
|
88
|
+
it_should_behave_like "a transfer"
|
|
89
|
+
end
|
|
90
|
+
context "with Transfer.failure_strategy = :rollback" do
|
|
91
|
+
let!(:failure_strategy) { :rollback }
|
|
92
|
+
it_should_behave_like "a not transfer"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context "with callbacks" do
|
|
98
|
+
include_context "stub klass model"
|
|
99
|
+
let!(:user) { Fabricate :johnny_hollow }
|
|
100
|
+
before do
|
|
101
|
+
@config = Transfer.configure do |c|
|
|
102
|
+
c.before {}
|
|
103
|
+
c.success {}
|
|
104
|
+
c.failure {}
|
|
105
|
+
c.after {}
|
|
106
|
+
end
|
|
107
|
+
@dataset = @config.connection[:source_users]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
[SequelUser, ActiveRecordUser, MongoidUser].each do |klass|
|
|
111
|
+
context klass do
|
|
112
|
+
let!(:klass) { klass }
|
|
113
|
+
it "should call before" do
|
|
114
|
+
stub(@config.before).call(klass, @dataset).once
|
|
115
|
+
do_action
|
|
116
|
+
end
|
|
117
|
+
it "should call after" do
|
|
118
|
+
stub(@config.after).call(klass, @dataset).once
|
|
119
|
+
do_action
|
|
120
|
+
end
|
|
121
|
+
it "should call success" do
|
|
122
|
+
stub(@config.success).call(model, user.values).once
|
|
123
|
+
do_action
|
|
124
|
+
end
|
|
125
|
+
it "should not call failure" do
|
|
126
|
+
stub(@config.failure).call.never
|
|
127
|
+
do_action
|
|
128
|
+
end
|
|
129
|
+
context "if save failure" do
|
|
130
|
+
let!(:exception) { RuntimeError.new }
|
|
131
|
+
before do
|
|
132
|
+
save_failure klass
|
|
133
|
+
stub(RuntimeError).new { exception }
|
|
134
|
+
end
|
|
135
|
+
it "should call before" do
|
|
136
|
+
stub(@config.before).call(klass, @dataset).once
|
|
137
|
+
do_action
|
|
138
|
+
end
|
|
139
|
+
it "should call after" do
|
|
140
|
+
stub(@config.after).call(klass, @dataset).once
|
|
141
|
+
do_action
|
|
142
|
+
end
|
|
143
|
+
it "should not call success" do
|
|
144
|
+
stub(@config.success).call.never
|
|
145
|
+
do_action
|
|
146
|
+
end
|
|
147
|
+
it "should call failure" do
|
|
148
|
+
stub(@config.failure).call(model, user.values, exception).once
|
|
149
|
+
do_action
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
describe "override global options" do
|
|
157
|
+
before do
|
|
158
|
+
Transfer.configure do |c|
|
|
159
|
+
c.validate = true
|
|
160
|
+
c.failure_strategy = :ignore
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
[SequelUser, ActiveRecordUser, MongoidUser].each do |klass|
|
|
165
|
+
it "for #{klass}" do
|
|
166
|
+
instance_of(Transfer::Transferer).process(:validate => false, :failure_strategy => :rollback).once
|
|
167
|
+
transfer :source_users => klass, :validate => false, :failure_strategy => :rollback
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
end
|