activerecord_dumper 0.9.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/README.md +68 -0
- data/lib/activerecord_dumper/csv_db.rb +73 -0
- data/lib/activerecord_dumper/rake_tasks.rb +55 -0
- data/lib/activerecord_dumper/serialization_helper.rb +212 -0
- data/lib/activerecord_dumper/version.rb +3 -0
- data/lib/activerecord_dumper.rb +75 -0
- data/lib/tasks/activerecord_dumper_tasks.rake +29 -0
- data/spec/activerecord_dumper/dump_spec.rb +54 -0
- data/spec/activerecord_dumper/integration_spec.rb +49 -0
- data/spec/activerecord_dumper/load_spec.rb +42 -0
- data/spec/activerecord_dumper/rake_tasks_spec.rb +96 -0
- data/spec/activerecord_dumper/serialization_helper_base_spec.rb +54 -0
- data/spec/activerecord_dumper/serialization_helper_dump_spec.rb +100 -0
- data/spec/activerecord_dumper/serialization_helper_load_spec.rb +73 -0
- data/spec/activerecord_dumper/serialization_helper_utils_spec.rb +60 -0
- data/spec/activerecord_dumper/utils_spec.rb +23 -0
- data/spec/spec_helper.rb +77 -0
- data/spec/tasks/activerecord_dumper_tasks_spec.rb +66 -0
- metadata +130 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module ActiveRecordDumper
|
|
2
|
+
RSpec.describe RakeTasks do
|
|
3
|
+
before do
|
|
4
|
+
@serializer = instance_double(SerializationHelper::Base)
|
|
5
|
+
allow(SerializationHelper::Base).to receive(:new).and_return(@serializer)
|
|
6
|
+
allow(Rails).to receive(:root).and_return('/root')
|
|
7
|
+
allow(Time).to receive(:now).and_return(Time.parse('2007-08-09 12:34:56'))
|
|
8
|
+
stub_const('UserSpecifiedHelper', Class.new)
|
|
9
|
+
allow(UserSpecifiedHelper).to receive(:extension).and_return('ext')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe '.data_dump_task' do
|
|
13
|
+
it 'dumps to a file' do
|
|
14
|
+
expect(SerializationHelper::Base).to receive(:new).once.with(Helper)
|
|
15
|
+
expect(@serializer).to receive(:dump).once.with('/root/db/data.yml')
|
|
16
|
+
RakeTasks.data_dump_task
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'dumps to a file using a user-specified format class' do
|
|
20
|
+
stub_const('ENV', 'class' => 'UserSpecifiedHelper')
|
|
21
|
+
expect(SerializationHelper::Base).to receive(:new).once.with(UserSpecifiedHelper)
|
|
22
|
+
expect(@serializer).to receive(:dump).once.with('/root/db/data.ext')
|
|
23
|
+
RakeTasks.data_dump_task
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '.data_dump_dir_task' do
|
|
28
|
+
it 'dumps to a directory' do
|
|
29
|
+
expect(SerializationHelper::Base).to receive(:new).once.with(Helper)
|
|
30
|
+
expect(@serializer).to receive(:dump_to_dir).once.with('/root/db/2007-08-09T123456')
|
|
31
|
+
RakeTasks.data_dump_dir_task
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'dumps to a directory using a user-specified format class' do
|
|
35
|
+
stub_const('ENV', 'class' => 'UserSpecifiedHelper')
|
|
36
|
+
expect(SerializationHelper::Base).to(
|
|
37
|
+
receive(:new).once.with(UserSpecifiedHelper)
|
|
38
|
+
)
|
|
39
|
+
expect(@serializer).to(
|
|
40
|
+
receive(:dump_to_dir).once.with('/root/db/2007-08-09T123456')
|
|
41
|
+
)
|
|
42
|
+
RakeTasks.data_dump_dir_task
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'dumps to a user-specified directory' do
|
|
46
|
+
stub_const('ENV', 'dir' => 'user_dir')
|
|
47
|
+
expect(SerializationHelper::Base).to receive(:new).once.with(Helper)
|
|
48
|
+
expect(@serializer).to(
|
|
49
|
+
receive(:dump_to_dir).once.with('/root/db/user_dir')
|
|
50
|
+
)
|
|
51
|
+
RakeTasks.data_dump_dir_task
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe '.data_load_task' do
|
|
56
|
+
it 'loads a file' do
|
|
57
|
+
expect(SerializationHelper::Base).to receive(:new).once.with(Helper)
|
|
58
|
+
expect(@serializer).to receive(:load).once.with('/root/db/data.yml')
|
|
59
|
+
RakeTasks.data_load_task
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'loads a file using a user-specified format class' do
|
|
63
|
+
stub_const('ENV', 'class' => 'UserSpecifiedHelper')
|
|
64
|
+
expect(SerializationHelper::Base).to(
|
|
65
|
+
receive(:new).once.with(UserSpecifiedHelper)
|
|
66
|
+
)
|
|
67
|
+
expect(@serializer).to receive(:load).once.with('/root/db/data.ext')
|
|
68
|
+
RakeTasks.data_load_task
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe '.data_load_dir_task' do
|
|
73
|
+
it 'loads a directory' do
|
|
74
|
+
expect(SerializationHelper::Base).to receive(:new).once.with(Helper)
|
|
75
|
+
expect(@serializer).to receive(:load_from_dir).once.with('/root/db/base')
|
|
76
|
+
RakeTasks.data_load_dir_task
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'loads a directory using a user-specified format class' do
|
|
80
|
+
stub_const('ENV', 'class' => 'UserSpecifiedHelper')
|
|
81
|
+
expect(SerializationHelper::Base).to(
|
|
82
|
+
receive(:new).once.with(UserSpecifiedHelper)
|
|
83
|
+
)
|
|
84
|
+
expect(@serializer).to receive(:load_from_dir).once.with('/root/db/base')
|
|
85
|
+
RakeTasks.data_load_dir_task
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'loads a user-specified directory' do
|
|
89
|
+
stub_const('ENV', 'dir' => 'user_dir')
|
|
90
|
+
expect(SerializationHelper::Base).to receive(:new).once.with(Helper)
|
|
91
|
+
expect(@serializer).to receive(:load_from_dir).once.with('/root/db/user_dir')
|
|
92
|
+
RakeTasks.data_load_dir_task
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module ActiveRecordDumper
|
|
2
|
+
module SerializationHelper
|
|
3
|
+
RSpec.describe Base do
|
|
4
|
+
def prestub_active_record
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
before do
|
|
8
|
+
@io = StringIO.new
|
|
9
|
+
allow(ActiveRecord::Base).to receive(:connection).and_return(double('connection'))
|
|
10
|
+
allow(ActiveRecord::Base.connection).to receive(:tables).and_return([ 'mytable', 'schema_info', 'schema_migrations' ])
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def stub_helper!
|
|
14
|
+
@helper = double("MyHelper")
|
|
15
|
+
@dumper = double("MyDumper");
|
|
16
|
+
@loader = double("MyLoader");
|
|
17
|
+
allow(@helper).to receive(:dumper).and_return(@dumper)
|
|
18
|
+
allow(@helper).to receive(:loader).and_return(@loader)
|
|
19
|
+
allow(@helper).to receive(:extension).and_return("yml")
|
|
20
|
+
allow(@dumper).to receive(:tables).and_return([ActiveRecord::Base.connection.tables[0]])
|
|
21
|
+
allow(@dumper).to receive(:before_table).and_return(nil)
|
|
22
|
+
allow(@dumper).to receive(:after_table).and_return(nil)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context "for multi-file dumps" do
|
|
26
|
+
before do
|
|
27
|
+
expect(File).to receive(:open).once.with("dir_name/mytable.yml", "w").and_yield(@io)
|
|
28
|
+
expect(Dir).to receive(:mkdir).once.with("dir_name")
|
|
29
|
+
stub_helper!
|
|
30
|
+
expect(@dumper).to receive(:dump_table).once.with(@io, "mytable")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "creates the number of files that there are tables" do
|
|
34
|
+
Base.new(@helper).dump_to_dir "dir_name"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context "for multi-file loads" do
|
|
40
|
+
before do
|
|
41
|
+
stub_helper!
|
|
42
|
+
expect(@loader).to receive(:load).once.with(@io, true)
|
|
43
|
+
expect(File).to receive(:new).once.with("dir_name/mytable.yml", "r").and_return(@io)
|
|
44
|
+
allow(Dir).to receive(:entries).and_return(["mytable.yml"])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "inserts into the number of tables that there are files" do
|
|
48
|
+
Base.new(@helper).load_from_dir "dir_name"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
module ActiveRecordDumper
|
|
2
|
+
module SerializationHelper
|
|
3
|
+
RSpec.describe Dump do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
allow(ActiveRecord::Base).to receive(:connection).and_return(double('connection').as_null_object)
|
|
7
|
+
allow(ActiveRecord::Base.connection).to receive(:tables).and_return([ 'mytable', 'schema_info', 'schema_migrations' ])
|
|
8
|
+
allow(ActiveRecord::Base.connection).to receive(:columns).with('mytable').and_return([ double('a', :name => 'a', :type => :string), double('b', :name => 'b', :type => :string) ])
|
|
9
|
+
allow(ActiveRecord::Base.connection).to receive(:select_one).and_return({"count"=>"2"})
|
|
10
|
+
allow(ActiveRecord::Base.connection).to receive(:select_all).and_return([ { 'a' => 1, 'b' => 2 }, { 'a' => 3, 'b' => 4 } ])
|
|
11
|
+
allow(Utils).to receive(:quote_table).with('mytable').and_return('mytable')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
before(:each) do
|
|
15
|
+
allow(File).to receive(:open).with('dump.yml', 'w').and_yield(StringIO.new)
|
|
16
|
+
@io = StringIO.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "returns a list of column names" do
|
|
20
|
+
expect(Dump.table_column_names('mytable')).to eq([ 'a', 'b' ])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "returns the total number of records in a table" do
|
|
24
|
+
expect(Dump.table_record_count('mytable')).to eq(2)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe ".each_table_page" do
|
|
28
|
+
before do
|
|
29
|
+
allow(Dump).to receive(:sort_keys)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "returns all records from the database and returns them when there is only 1 page" do
|
|
33
|
+
Dump.each_table_page('mytable') do |records|
|
|
34
|
+
expect(records).to eq([ { 'a' => 1, 'b' => 2 }, { 'a' => 3, 'b' => 4 } ])
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "paginates records from the database and returns them" do
|
|
39
|
+
allow(ActiveRecord::Base.connection).to receive(:select_all).and_return([ { 'a' => 1, 'b' => 2 } ], [ { 'a' => 3, 'b' => 4 } ])
|
|
40
|
+
|
|
41
|
+
records = [ ]
|
|
42
|
+
Dump.each_table_page('mytable', 1) do |page|
|
|
43
|
+
expect(page.size).to eq(1)
|
|
44
|
+
records.concat(page)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
expect(records).to eq([ { 'a' => 1, 'b' => 2 }, { 'a' => 3, 'b' => 4 } ])
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "dumps a table's contents to yaml" do
|
|
52
|
+
expect(Dump).to receive(:dump_table_columns)
|
|
53
|
+
expect(Dump).to receive(:dump_table_records)
|
|
54
|
+
Dump.dump_table(@io, 'mytable')
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "does not dump a table's contents when the record count is zero" do
|
|
58
|
+
allow(Dump).to receive(:table_record_count).with('mytable').and_return(0)
|
|
59
|
+
expect(Dump).not_to receive(:dump_table_columns)
|
|
60
|
+
expect(Dump).not_to receive(:dump_table_records)
|
|
61
|
+
Dump.dump_table(@io, 'mytable')
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe ".tables" do
|
|
65
|
+
it "returns a list of tables without the rails schema table" do
|
|
66
|
+
expect(Dump.tables).to eq(['mytable'])
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "returns the list of tables in a consistent (sorted) order" do
|
|
70
|
+
allow(ActiveRecord::Base.connection).to receive(:tables).and_return(%w(z y x))
|
|
71
|
+
expect(Dump.tables).to eq(%w(x y z))
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
describe ".sort_keys" do
|
|
76
|
+
before do
|
|
77
|
+
allow(Utils).to receive(:quote_column) { |column| column }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "returns the first column as sort key" do
|
|
81
|
+
expect(Dump.sort_keys('mytable')).to eq(['a'])
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "returns the combined ids as sort key if the table looks like a HABTM" do
|
|
85
|
+
allow(ActiveRecord::Base.connection).to receive(:columns).with('mytable').and_return([
|
|
86
|
+
double('a_id', :name => 'a_id', :type => :string),
|
|
87
|
+
double('b_id', :name => 'b_id', :type => :string)
|
|
88
|
+
])
|
|
89
|
+
|
|
90
|
+
expect(Dump.sort_keys('mytable')).to eq(['a_id', 'b_id'])
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "quotes the column name" do
|
|
94
|
+
allow(Utils).to receive(:quote_column).with('a').and_return('`a`')
|
|
95
|
+
expect(Dump.sort_keys('mytable')).to eq(['`a`'])
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
module ActiveRecordDumper
|
|
2
|
+
module SerializationHelper
|
|
3
|
+
RSpec.describe Load do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
allow(Utils).to receive(:quote_table).with('mytable').and_return('mytable')
|
|
7
|
+
|
|
8
|
+
allow(ActiveRecord::Base).to receive(:connection).and_return(double('connection').as_null_object)
|
|
9
|
+
allow(ActiveRecord::Base.connection).to receive(:transaction).and_yield
|
|
10
|
+
@io = StringIO.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "truncates the table" do
|
|
14
|
+
allow(ActiveRecord::Base.connection).to receive(:execute).with("TRUNCATE mytable").and_return(true)
|
|
15
|
+
expect(ActiveRecord::Base.connection).not_to receive(:execute).with("DELETE FROM mytable")
|
|
16
|
+
Load.truncate_table('mytable')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "deletes the table if truncate throws an exception" do
|
|
20
|
+
expect(ActiveRecord::Base.connection).to receive(:execute).with("TRUNCATE mytable").and_raise()
|
|
21
|
+
expect(ActiveRecord::Base.connection).to receive(:execute).with("DELETE FROM mytable").and_return(true)
|
|
22
|
+
Load.truncate_table('mytable')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "calls reset pk sequence if the connection adapter is postgres" do
|
|
26
|
+
expect(ActiveRecord::Base.connection).to receive(:respond_to?).with(:reset_pk_sequence!).and_return(true)
|
|
27
|
+
expect(ActiveRecord::Base.connection).to receive(:reset_pk_sequence!).with('mytable')
|
|
28
|
+
Load.reset_pk_sequence!('mytable')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "does not call reset pk sequence for other adapters" do
|
|
32
|
+
expect(ActiveRecord::Base.connection).to receive(:respond_to?).with(:reset_pk_sequence!).and_return(false)
|
|
33
|
+
expect(ActiveRecord::Base.connection).not_to receive(:reset_pk_sequence!)
|
|
34
|
+
Load.reset_pk_sequence!('mytable')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "inserts records into a table" do
|
|
38
|
+
allow(ActiveRecord::Base.connection).to receive(:quote_column_name).with('a').and_return('a')
|
|
39
|
+
allow(ActiveRecord::Base.connection).to receive(:quote_column_name).with('b').and_return('b')
|
|
40
|
+
allow(ActiveRecord::Base.connection).to receive(:quote).with(1).and_return("'1'")
|
|
41
|
+
allow(ActiveRecord::Base.connection).to receive(:quote).with(2).and_return("'2'")
|
|
42
|
+
allow(ActiveRecord::Base.connection).to receive(:quote).with(3).and_return("'3'")
|
|
43
|
+
allow(ActiveRecord::Base.connection).to receive(:quote).with(4).and_return("'4'")
|
|
44
|
+
expect(ActiveRecord::Base.connection).to receive(:execute).with("INSERT INTO mytable (a,b) VALUES ('1','2')")
|
|
45
|
+
expect(ActiveRecord::Base.connection).to receive(:execute).with("INSERT INTO mytable (a,b) VALUES ('3','4')")
|
|
46
|
+
|
|
47
|
+
Load.load_records('mytable', ['a', 'b'], [[1, 2], [3, 4]])
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "quotes column names that correspond to sql keywords" do
|
|
51
|
+
allow(ActiveRecord::Base.connection).to receive(:quote_column_name).with('a').and_return('a')
|
|
52
|
+
allow(ActiveRecord::Base.connection).to receive(:quote_column_name).with('count').and_return('"count"')
|
|
53
|
+
allow(ActiveRecord::Base.connection).to receive(:quote).with(1).and_return("'1'")
|
|
54
|
+
allow(ActiveRecord::Base.connection).to receive(:quote).with(2).and_return("'2'")
|
|
55
|
+
allow(ActiveRecord::Base.connection).to receive(:quote).with(3).and_return("'3'")
|
|
56
|
+
allow(ActiveRecord::Base.connection).to receive(:quote).with(4).and_return("'4'")
|
|
57
|
+
expect(ActiveRecord::Base.connection).to receive(:execute).with("INSERT INTO mytable (a,\"count\") VALUES ('1','2')")
|
|
58
|
+
expect(ActiveRecord::Base.connection).to receive(:execute).with("INSERT INTO mytable (a,\"count\") VALUES ('3','4')")
|
|
59
|
+
|
|
60
|
+
Load.load_records('mytable', ['a', 'count'], [[1, 2], [3, 4]])
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "truncates the table and then loads the records into the table" do
|
|
64
|
+
expect(Load).to receive(:truncate_table).with('mytable')
|
|
65
|
+
expect(Load).to receive(:load_records).with('mytable', ['a', 'b'], [[1, 2], [3, 4]])
|
|
66
|
+
expect(Load).to receive(:reset_pk_sequence!).with('mytable')
|
|
67
|
+
|
|
68
|
+
Load.load_table('mytable', { 'columns' => [ 'a', 'b' ], 'records' => [[1, 2], [3, 4]] })
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module ActiveRecordDumper
|
|
2
|
+
module SerializationHelper
|
|
3
|
+
RSpec.describe Utils do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
allow(ActiveRecord::Base).to receive(:connection).and_return(double('connection').as_null_object)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "returns an array of hash values using an array of ordered keys" do
|
|
10
|
+
expect(Utils.unhash({ 'a' => 1, 'b' => 2 }, [ 'b', 'a' ])).to eq([ 2, 1 ])
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "unhashes each hash to an array using an array of ordered keys" do
|
|
14
|
+
expect(Utils.unhash_records([ { 'a' => 1, 'b' => 2 }, { 'a' => 3, 'b' => 4 } ], [ 'b', 'a' ])).to eq([ [ 2, 1 ], [ 4, 3 ] ])
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "returns true if it is a boolean type" do
|
|
18
|
+
expect(Utils.is_boolean(true)).to be true
|
|
19
|
+
expect(Utils.is_boolean('true')).to be false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "returns an array of boolean columns" do
|
|
23
|
+
allow(ActiveRecord::Base.connection).to receive(:columns).with('mytable').and_return([ double('a',:name => 'a',:type => :string), double('b', :name => 'b',:type => :boolean) ])
|
|
24
|
+
expect(Utils.boolean_columns('mytable')).to eq(['b'])
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "quotes the table name" do
|
|
28
|
+
expect(ActiveRecord::Base.connection).to receive(:quote_table_name).with('values').and_return('`values`')
|
|
29
|
+
expect(Utils.quote_table('values')).to eq('`values`')
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "converts ruby booleans to true and false" do
|
|
33
|
+
expect(Utils.convert_boolean(true)).to be true
|
|
34
|
+
expect(Utils.convert_boolean(false)).to be false
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "converts ruby strings t and f to true and false" do
|
|
38
|
+
expect(Utils.convert_boolean('t')).to be true
|
|
39
|
+
expect(Utils.convert_boolean('f')).to be false
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "converts ruby strings 1 and 0 to true and false" do
|
|
43
|
+
expect(Utils.convert_boolean('1')).to be true
|
|
44
|
+
expect(Utils.convert_boolean('0')).to be false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "converts ruby integers 1 and 0 to true and false" do
|
|
48
|
+
expect(Utils.convert_boolean(1)).to be true
|
|
49
|
+
expect(Utils.convert_boolean(0)).to be false
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe ".quote_column" do
|
|
53
|
+
it "quotes the column name" do
|
|
54
|
+
allow(ActiveRecord::Base.connection).to receive(:quote_column_name).with('id').and_return('`id`')
|
|
55
|
+
expect(Utils.quote_column('id')).to eq('`id`')
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module ActiveRecordDumper
|
|
2
|
+
RSpec.describe Utils do
|
|
3
|
+
|
|
4
|
+
it "turns an array with one record into a yaml chunk" do
|
|
5
|
+
expect(Utils.chunk_records([%w[a b]])).to eq(<<EOYAML
|
|
6
|
+
- - a
|
|
7
|
+
- b
|
|
8
|
+
EOYAML
|
|
9
|
+
)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "turns an array with two records into a yaml chunk" do
|
|
13
|
+
expect(Utils.chunk_records([%w[a b], %w[c d]])).to eq(<<EOYAML
|
|
14
|
+
- - a
|
|
15
|
+
- b
|
|
16
|
+
- - c
|
|
17
|
+
- d
|
|
18
|
+
EOYAML
|
|
19
|
+
)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'simplecov'
|
|
4
|
+
require 'simplecov-lcov'
|
|
5
|
+
|
|
6
|
+
SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
|
|
7
|
+
SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
|
|
8
|
+
SimpleCov.start
|
|
9
|
+
|
|
10
|
+
require 'logger'
|
|
11
|
+
require 'activerecord_dumper'
|
|
12
|
+
|
|
13
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
|
14
|
+
RSpec.configure do |config|
|
|
15
|
+
config.expect_with :rspec do |expectations|
|
|
16
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
|
17
|
+
# and `failure_message` of custom matchers include text for helper methods
|
|
18
|
+
# defined using `chain`, e.g.:
|
|
19
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
|
20
|
+
# # => "be bigger than 2 and smaller than 4"
|
|
21
|
+
# ...rather than:
|
|
22
|
+
# # => "be bigger than 2"
|
|
23
|
+
# expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
config.mock_with :rspec do |mocks|
|
|
27
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
|
28
|
+
# a real object. This is generally recommended, and will default to
|
|
29
|
+
# `true` in RSpec 4.
|
|
30
|
+
# mocks.verify_partial_doubles = true
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# These two settings work together to allow you to limit a spec run
|
|
34
|
+
# to individual examples or groups you care about by tagging them with
|
|
35
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
|
36
|
+
# get run.
|
|
37
|
+
config.filter_run :focus
|
|
38
|
+
config.run_all_when_everything_filtered = true
|
|
39
|
+
|
|
40
|
+
# Limits the available syntax to the non-monkey patched syntax that is recommended.
|
|
41
|
+
# For more details, see:
|
|
42
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
|
43
|
+
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
|
44
|
+
# - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
|
|
45
|
+
config.disable_monkey_patching!
|
|
46
|
+
|
|
47
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
|
48
|
+
# be too noisy due to issues in dependencies.
|
|
49
|
+
config.warnings = true
|
|
50
|
+
|
|
51
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
|
52
|
+
# file, and it's useful to allow more verbose output when running an
|
|
53
|
+
# individual spec file.
|
|
54
|
+
if config.files_to_run.one?
|
|
55
|
+
# Use the documentation formatter for detailed output,
|
|
56
|
+
# unless a formatter has already been configured
|
|
57
|
+
# (e.g. via a command-line flag).
|
|
58
|
+
config.default_formatter = 'doc'
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Print the 10 slowest examples and example groups at the
|
|
62
|
+
# end of the spec run, to help surface which specs are running
|
|
63
|
+
# particularly slow.
|
|
64
|
+
#config.profile_examples = 10
|
|
65
|
+
|
|
66
|
+
# Run specs in random order to surface order dependencies. If you find an
|
|
67
|
+
# order dependency and want to debug it, you can fix the order by providing
|
|
68
|
+
# the seed, which is printed after each run.
|
|
69
|
+
# --seed 1234
|
|
70
|
+
config.order = :random
|
|
71
|
+
|
|
72
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
|
73
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
|
74
|
+
# test failures related to randomization by passing the same `--seed` value
|
|
75
|
+
# as the one that triggered the failure.
|
|
76
|
+
Kernel.srand config.seed
|
|
77
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'rake'
|
|
2
|
+
|
|
3
|
+
RSpec.describe 'Rake tasks' do
|
|
4
|
+
before do
|
|
5
|
+
Rake::Application.new.rake_require('tasks/activerecord_dumper_tasks')
|
|
6
|
+
Rake::Task.define_task(:environment)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
subject { Rake::Task[self.class.description] }
|
|
10
|
+
|
|
11
|
+
describe 'db:dump' do
|
|
12
|
+
it 'depends on db:schema:dump and db:data:dump' do
|
|
13
|
+
expect(subject.prerequisites).to eq(['db:schema:dump', 'db:data:dump'])
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe 'db:load' do
|
|
18
|
+
it 'depends on db:schema:load and db:data:load' do
|
|
19
|
+
expect(subject.prerequisites).to eq(['db:schema:load', 'db:data:load'])
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe 'db:data:dump' do
|
|
24
|
+
it 'loads the environment' do
|
|
25
|
+
expect(subject.prerequisites).to eq(['environment'])
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'invokes the correct task' do
|
|
29
|
+
expect(ActiveRecordDumper::RakeTasks).to receive(:data_dump_task).once.with(no_args)
|
|
30
|
+
subject.invoke
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe 'db:data:dump_dir' do
|
|
35
|
+
it 'loads the environment' do
|
|
36
|
+
expect(subject.prerequisites).to eq(['environment'])
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'invokes the correct task' do
|
|
40
|
+
expect(ActiveRecordDumper::RakeTasks).to receive(:data_dump_dir_task).once.with(no_args)
|
|
41
|
+
subject.invoke
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe 'db:data:load' do
|
|
46
|
+
it 'loads the environment' do
|
|
47
|
+
expect(subject.prerequisites).to eq(['environment'])
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'invokes the correct task' do
|
|
51
|
+
expect(ActiveRecordDumper::RakeTasks).to receive(:data_load_task).once.with(no_args)
|
|
52
|
+
subject.invoke
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe 'db:data:load_dir' do
|
|
57
|
+
it 'loads the environment' do
|
|
58
|
+
expect(subject.prerequisites).to eq(['environment'])
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'invokes the correct task' do
|
|
62
|
+
expect(ActiveRecordDumper::RakeTasks).to receive(:data_load_dir_task).once.with(no_args)
|
|
63
|
+
subject.invoke
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: activerecord_dumper
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.9.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Adam Wiggins
|
|
8
|
+
- Orion Henry
|
|
9
|
+
- Serge Tkatchouk
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: activerecord
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
requirements:
|
|
18
|
+
- - ">="
|
|
19
|
+
- !ruby/object:Gem::Version
|
|
20
|
+
version: 3.2.22
|
|
21
|
+
- - "<"
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: '8.2'
|
|
24
|
+
type: :runtime
|
|
25
|
+
prerelease: false
|
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
27
|
+
requirements:
|
|
28
|
+
- - ">="
|
|
29
|
+
- !ruby/object:Gem::Version
|
|
30
|
+
version: 3.2.22
|
|
31
|
+
- - "<"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '8.2'
|
|
34
|
+
- !ruby/object:Gem::Dependency
|
|
35
|
+
name: bundler
|
|
36
|
+
requirement: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.14'
|
|
41
|
+
type: :development
|
|
42
|
+
prerelease: false
|
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '1.14'
|
|
48
|
+
- !ruby/object:Gem::Dependency
|
|
49
|
+
name: rspec
|
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '3.13'
|
|
55
|
+
type: :development
|
|
56
|
+
prerelease: false
|
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '3.13'
|
|
62
|
+
- !ruby/object:Gem::Dependency
|
|
63
|
+
name: sqlite3
|
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '2.1'
|
|
69
|
+
type: :development
|
|
70
|
+
prerelease: false
|
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '2.1'
|
|
76
|
+
description: |
|
|
77
|
+
ActiveRecordDumper is a fork of YamlDb gem without any explicit Rails dependencies.
|
|
78
|
+
This way it can be used by any AR-enabled app (e.g. Sinatra) without pulling whole Rails in.
|
|
79
|
+
YamlDB/ActiveRecordDumper is a database-independent format for dumping and restoring data.
|
|
80
|
+
It complements the database-independent schema format found in db/schema.rb.
|
|
81
|
+
The data is saved into db/data.yml. This can be used as a replacement for mysqldump or pg_dump,
|
|
82
|
+
but it only supports features found in ActiveRecord-based (Rails, etc.) apps.
|
|
83
|
+
Users, permissions, schemas, triggers, and other advanced database features are not supported by design.
|
|
84
|
+
Any database that has an ActiveRecord adapter should work.
|
|
85
|
+
executables: []
|
|
86
|
+
extensions: []
|
|
87
|
+
extra_rdoc_files:
|
|
88
|
+
- README.md
|
|
89
|
+
files:
|
|
90
|
+
- README.md
|
|
91
|
+
- lib/activerecord_dumper.rb
|
|
92
|
+
- lib/activerecord_dumper/csv_db.rb
|
|
93
|
+
- lib/activerecord_dumper/rake_tasks.rb
|
|
94
|
+
- lib/activerecord_dumper/serialization_helper.rb
|
|
95
|
+
- lib/activerecord_dumper/version.rb
|
|
96
|
+
- lib/tasks/activerecord_dumper_tasks.rake
|
|
97
|
+
- spec/activerecord_dumper/dump_spec.rb
|
|
98
|
+
- spec/activerecord_dumper/integration_spec.rb
|
|
99
|
+
- spec/activerecord_dumper/load_spec.rb
|
|
100
|
+
- spec/activerecord_dumper/rake_tasks_spec.rb
|
|
101
|
+
- spec/activerecord_dumper/serialization_helper_base_spec.rb
|
|
102
|
+
- spec/activerecord_dumper/serialization_helper_dump_spec.rb
|
|
103
|
+
- spec/activerecord_dumper/serialization_helper_load_spec.rb
|
|
104
|
+
- spec/activerecord_dumper/serialization_helper_utils_spec.rb
|
|
105
|
+
- spec/activerecord_dumper/utils_spec.rb
|
|
106
|
+
- spec/spec_helper.rb
|
|
107
|
+
- spec/tasks/activerecord_dumper_tasks_spec.rb
|
|
108
|
+
homepage: https://github.com/spijet/activerecord_dumper
|
|
109
|
+
licenses:
|
|
110
|
+
- MIT
|
|
111
|
+
metadata: {}
|
|
112
|
+
rdoc_options: []
|
|
113
|
+
require_paths:
|
|
114
|
+
- lib
|
|
115
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
116
|
+
requirements:
|
|
117
|
+
- - ">="
|
|
118
|
+
- !ruby/object:Gem::Version
|
|
119
|
+
version: '2.3'
|
|
120
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - ">="
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0'
|
|
125
|
+
requirements: []
|
|
126
|
+
rubygems_version: 4.0.5
|
|
127
|
+
specification_version: 4
|
|
128
|
+
summary: activerecord_dumper allows you to dump/restore any ActiveRecord database
|
|
129
|
+
to/from a YAML file.
|
|
130
|
+
test_files: []
|