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.
@@ -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,13 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ module Transfer
5
+ module Generators
6
+ describe ActiveRecord do
7
+ it_should_behave_like "a generator" do
8
+ let!(:generator) { ActiveRecord }
9
+ let!(:klass) { ActiveRecordUser }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ module Transfer
5
+ module Generators
6
+ describe Mongoid do
7
+ it_should_behave_like "a generator" do
8
+ let!(:generator) { Mongoid }
9
+ let!(:klass) { MongoidUser }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ module Transfer
5
+ module Generators
6
+ describe Sequel do
7
+ it_should_behave_like "a generator" do
8
+ let!(:generator) { Sequel }
9
+ let!(:klass) { SequelUser }
10
+ end
11
+ end
12
+ end
13
+ 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