squealer 2.1.1 → 2.2.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.
- data/.rvmrc +5 -5
- data/LICENSE +20 -0
- data/README.md +36 -12
- data/Rakefile +10 -1
- data/VERSION +1 -1
- data/bin/skewer +5 -9
- data/lib/example_squeal.rb +10 -3
- data/lib/squealer/database.rb +22 -4
- data/lib/squealer/hash.rb +1 -0
- data/lib/squealer/object.rb +2 -2
- data/lib/squealer/target.rb +32 -33
- data/lib/squealer.rb +0 -1
- data/spec/integration/export_a_record_spec.rb +148 -0
- data/spec/spec_helper.rb +34 -54
- data/spec/spec_helper_dbms_mysql.rb +56 -0
- data/spec/spec_helper_dbms_postgres.rb +55 -0
- data/spec/squealer/database_spec.rb +41 -11
- data/spec/squealer/object_spec.rb +4 -4
- data/spec/squealer/target_spec.rb +77 -108
- data/squealer.gemspec +31 -12
- metadata +109 -25
- data/lib/.example_squeal.rb.swp +0 -0
- data/lib/squealer/time.rb +0 -5
- data/spec/squealer/time_spec.rb +0 -10
data/spec/spec_helper.rb
CHANGED
@@ -6,37 +6,31 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
6
6
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
7
|
|
8
8
|
require 'squealer'
|
9
|
+
require "spec_helper_dbms_#{ENV['EXPORT_DBMS']||'mysql'}"
|
9
10
|
|
10
11
|
Spec::Runner.configure do |config|
|
11
12
|
config.before(:suite) do
|
12
13
|
$db_name = "test_export_#{object_id}"
|
13
|
-
|
14
|
+
create_export_db($db_name)
|
15
|
+
create_import_db($db_name)
|
14
16
|
end
|
15
17
|
|
16
18
|
config.after(:suite) do
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
def create_test_db(name)
|
21
|
-
@my = Mysql.connect('localhost', 'root')
|
22
|
-
@my.query("DROP DATABASE IF EXISTS #{name}")
|
23
|
-
@my.query("CREATE DATABASE #{name}")
|
24
|
-
@my.query("USE #{name}")
|
25
|
-
@my.query("SET sql_mode='ANSI_QUOTES'")
|
26
|
-
|
27
|
-
create_export_tables
|
19
|
+
Squealer::Database.instance.send(:dispose_all_connections)
|
20
|
+
drop_export_test_db($db_name)
|
28
21
|
|
29
|
-
Squealer::Database.instance.import_from('localhost', 27017, $db_name)
|
30
|
-
@mongo = Squealer::Database.instance.import.send(:instance_variable_get, '@dbc')
|
31
22
|
drop_mongo
|
32
|
-
seed_import
|
33
23
|
end
|
34
24
|
|
35
|
-
|
36
|
-
@
|
37
|
-
|
25
|
+
config.after(:each) do
|
26
|
+
@export_dbc.dispose if @export_dbc
|
27
|
+
end
|
38
28
|
|
29
|
+
def create_import_db(name)
|
30
|
+
Squealer::Database.instance.import_from('localhost', 27017, name)
|
31
|
+
@mongo = Squealer::Database.instance.import.instance_variable_get('@dbc')
|
39
32
|
drop_mongo
|
33
|
+
seed_import
|
40
34
|
end
|
41
35
|
|
42
36
|
def drop_mongo
|
@@ -51,24 +45,24 @@ Spec::Runner.configure do |config|
|
|
51
45
|
{ :name => 'Josh Graham', :dob => as_time(Date.parse('01-Jan-1971')), :gender => 'M',
|
52
46
|
:organization_id => hashrocket,
|
53
47
|
:activities => [
|
54
|
-
{ :name => 'Develop squealer', :due_date => as_time(Date.today + 1) },
|
55
|
-
{ :name => 'Organize speakerconf.com', :due_date => as_time(Date.today + 30) },
|
56
|
-
{ :name => 'Hashrocket party', :due_date => as_time(Date.today + 7) }
|
48
|
+
{ :_id => id, :name => 'Develop squealer', :due_date => as_time(Date.today + 1) },
|
49
|
+
{ :_id => id, :name => 'Organize speakerconf.com', :due_date => as_time(Date.today + 30) },
|
50
|
+
{ :_id => id, :name => 'Hashrocket party', :due_date => as_time(Date.today + 7) }
|
57
51
|
]
|
58
52
|
},
|
59
53
|
{ :name => 'Bernerd Schaefer', :dob => as_time(Date.parse('31-Dec-1985')), :gender => 'M',
|
60
54
|
:organization_id => hashrocket,
|
61
55
|
:activities => [
|
62
|
-
{ :name => 'Retype all of the code Josh wrote in squealer', :due_date => as_time(Date.today + 2) },
|
63
|
-
{ :name => 'Listen to rare Thelonius Monk EP', :due_date => as_time(Date.today) },
|
64
|
-
{ :name => 'Practice karaoke', :due_date => as_time(Date.today + 7) }
|
56
|
+
{ :_id => id, :name => 'Retype all of the code Josh wrote in squealer', :due_date => as_time(Date.today + 2) },
|
57
|
+
{ :_id => id, :name => 'Listen to rare Thelonius Monk EP', :due_date => as_time(Date.today) },
|
58
|
+
{ :_id => id, :name => 'Practice karaoke', :due_date => as_time(Date.today + 7) }
|
65
59
|
]
|
66
60
|
},
|
67
61
|
{ :name => 'Your momma', :dob => as_time(Date.parse('15-Jun-1955')), :gender => 'F',
|
68
62
|
:organization_id => zorganization,
|
69
63
|
:activities => [
|
70
|
-
{ :name => 'Cook me some pie', :due_date => as_time(Date.today) },
|
71
|
-
{ :name => 'Make me a sammich', :due_date => as_time(Date.today) }
|
64
|
+
{ :_id => id, :name => 'Cook me some pie', :due_date => as_time(Date.today) },
|
65
|
+
{ :_id => id, :name => 'Make me a sammich', :due_date => as_time(Date.today) }
|
72
66
|
]
|
73
67
|
}
|
74
68
|
]
|
@@ -76,37 +70,23 @@ Spec::Runner.configure do |config|
|
|
76
70
|
users.each { |user| @mongo.collection('users').save user }
|
77
71
|
end
|
78
72
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
"gender" CHAR(1) NULL ,
|
85
|
-
"dob" DATE NULL ,
|
86
|
-
PRIMARY KEY ("id") )
|
87
|
-
COMMAND
|
88
|
-
@my.query(command)
|
89
|
-
|
90
|
-
command = <<-COMMAND.gsub(/\n\s*/, " ")
|
91
|
-
CREATE TABLE "activity" (
|
92
|
-
"id" INT NOT NULL AUTO_INCREMENT ,
|
93
|
-
"user_id" INT NULL ,
|
94
|
-
"name" VARCHAR(255) NULL ,
|
95
|
-
"due_date" DATE NULL ,
|
96
|
-
PRIMARY KEY ("id") )
|
97
|
-
COMMAND
|
98
|
-
@my.query(command)
|
99
|
-
|
100
|
-
command = <<-COMMAND.gsub(/\n\s*/, " ")
|
101
|
-
CREATE TABLE "organizations" (
|
102
|
-
"id" INT NOT NULL AUTO_INCREMENT ,
|
103
|
-
"disabed_date" DATE NULL ,
|
104
|
-
PRIMARY KEY ("id") )
|
105
|
-
COMMAND
|
106
|
-
@my.query(command)
|
73
|
+
|
74
|
+
def truncate_export_tables
|
75
|
+
non_query('TRUNCATE TABLE "user"')
|
76
|
+
non_query('TRUNCATE TABLE "activity"')
|
77
|
+
non_query('TRUNCATE TABLE "organization"')
|
107
78
|
end
|
108
79
|
|
109
80
|
def as_time(date)
|
110
81
|
Time.parse(date.to_s)
|
111
82
|
end
|
83
|
+
|
84
|
+
def non_query(text)
|
85
|
+
export_dbc.create_command(text).execute_non_query
|
86
|
+
end
|
87
|
+
|
88
|
+
def id
|
89
|
+
require 'digest/sha1'
|
90
|
+
(Digest::SHA1.hexdigest rand.to_s)[0,24]
|
91
|
+
end
|
112
92
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
def create_export_db(name)
|
2
|
+
$db_adapter = 'mysql'
|
3
|
+
dbc = DataObjects::Connection.new("mysql://root@localhost/mysql")
|
4
|
+
dbc.create_command("DROP DATABASE IF EXISTS #{name}").execute_non_query
|
5
|
+
dbc.create_command("CREATE DATABASE #{name}").execute_non_query
|
6
|
+
dbc.create_command("SET sql_mode='ANSI_QUOTES'").execute_non_query
|
7
|
+
create_export_tables
|
8
|
+
dbc.dispose
|
9
|
+
end
|
10
|
+
|
11
|
+
def drop_export_test_db(name)
|
12
|
+
@export_dbc.dispose if @export_dbc
|
13
|
+
dbc = DataObjects::Connection.new("mysql://root@localhost/mysql")
|
14
|
+
dbc.create_command("DROP DATABASE IF EXISTS #{name}").execute_non_query
|
15
|
+
dbc.dispose
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_export_tables
|
19
|
+
command = <<-COMMAND.gsub(/\n\s*/, " ")
|
20
|
+
CREATE TABLE "user" (
|
21
|
+
"id" CHAR(24) NOT NULL ,
|
22
|
+
"organization_id" CHAR(24) NOT NULL ,
|
23
|
+
"name" VARCHAR(255) NULL ,
|
24
|
+
"gender" CHAR(1) NULL ,
|
25
|
+
"dob" DATETIME NULL ,
|
26
|
+
"foreign" BOOLEAN NULL ,
|
27
|
+
"dull" BOOLEAN NULL ,
|
28
|
+
"symbolic" VARCHAR(255) NULL ,
|
29
|
+
"interests" TEXT NULL ,
|
30
|
+
PRIMARY KEY ("id") )
|
31
|
+
COMMAND
|
32
|
+
non_query(command)
|
33
|
+
|
34
|
+
command = <<-COMMAND.gsub(/\n\s*/, " ")
|
35
|
+
CREATE TABLE "activity" (
|
36
|
+
"id" CHAR(24) NOT NULL ,
|
37
|
+
"user_id" CHAR(24) NULL ,
|
38
|
+
"name" VARCHAR(255) NULL ,
|
39
|
+
"due_date" DATETIME NULL ,
|
40
|
+
PRIMARY KEY ("id") )
|
41
|
+
COMMAND
|
42
|
+
non_query(command)
|
43
|
+
|
44
|
+
command = <<-COMMAND.gsub(/\n\s*/, " ")
|
45
|
+
CREATE TABLE "organization" (
|
46
|
+
"id" CHAR(24) NOT NULL ,
|
47
|
+
"disabled_date" DATETIME NULL ,
|
48
|
+
PRIMARY KEY ("id") )
|
49
|
+
COMMAND
|
50
|
+
non_query(command)
|
51
|
+
end
|
52
|
+
|
53
|
+
def export_dbc
|
54
|
+
$db_user ||= 'root'
|
55
|
+
@export_dbc ||= DataObjects::Connection.new("mysql://root@localhost/#{$db_name}")
|
56
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
def create_export_db(name)
|
2
|
+
$db_adapter = 'postgres'
|
3
|
+
dbc = DataObjects::Connection.new("postgres://localhost/postgres")
|
4
|
+
dbc.create_command("DROP DATABASE IF EXISTS #{name}").execute_non_query
|
5
|
+
dbc.create_command("CREATE DATABASE #{name}").execute_non_query
|
6
|
+
create_export_tables
|
7
|
+
dbc.dispose
|
8
|
+
end
|
9
|
+
|
10
|
+
def drop_export_test_db(name)
|
11
|
+
@export_dbc.dispose if @export_dbc
|
12
|
+
dbc = DataObjects::Connection.new("postgres://localhost/postgres")
|
13
|
+
dbc.create_command("DROP DATABASE IF EXISTS #{name}").execute_non_query
|
14
|
+
dbc.dispose
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_export_tables
|
18
|
+
command = <<-COMMAND.gsub(/\n\s*/, " ")
|
19
|
+
CREATE TABLE "user" (
|
20
|
+
"id" CHAR(24) NOT NULL ,
|
21
|
+
"organization_id" CHAR(24) NOT NULL ,
|
22
|
+
"name" VARCHAR(255) NULL ,
|
23
|
+
"gender" CHAR(1) NULL ,
|
24
|
+
"dob" TIMESTAMP NULL ,
|
25
|
+
"foreign" BOOLEAN NULL ,
|
26
|
+
"dull" BOOLEAN NULL ,
|
27
|
+
"symbolic" VARCHAR(255) NULL ,
|
28
|
+
"interests" TEXT NULL ,
|
29
|
+
PRIMARY KEY ("id") )
|
30
|
+
COMMAND
|
31
|
+
non_query(command)
|
32
|
+
|
33
|
+
command = <<-COMMAND.gsub(/\n\s*/, " ")
|
34
|
+
CREATE TABLE "activity" (
|
35
|
+
"id" CHAR(24) NOT NULL ,
|
36
|
+
"user_id" CHAR(24) NULL ,
|
37
|
+
"name" VARCHAR(255) NULL ,
|
38
|
+
"due_date" TIMESTAMP NULL ,
|
39
|
+
PRIMARY KEY ("id") )
|
40
|
+
COMMAND
|
41
|
+
non_query(command)
|
42
|
+
|
43
|
+
command = <<-COMMAND.gsub(/\n\s*/, " ")
|
44
|
+
CREATE TABLE "organization" (
|
45
|
+
"id" CHAR(24) NOT NULL ,
|
46
|
+
"disabled_date" TIMESTAMP NULL ,
|
47
|
+
PRIMARY KEY ("id") )
|
48
|
+
COMMAND
|
49
|
+
non_query(command)
|
50
|
+
end
|
51
|
+
|
52
|
+
def export_dbc
|
53
|
+
$db_user ||= ''
|
54
|
+
@export_dbc ||= DataObjects::Connection.new("postgres://localhost/#{$db_name}")
|
55
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'mysql'
|
3
2
|
require 'mongo'
|
4
3
|
|
5
4
|
describe Squealer::Database do
|
@@ -105,14 +104,25 @@ describe Squealer::Database do
|
|
105
104
|
end
|
106
105
|
|
107
106
|
context "real squeal" do
|
108
|
-
before { pending "interactive_view" }
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
107
|
+
# before { pending "interactive_view" }
|
108
|
+
it "exports that stuff to SQL" do
|
109
|
+
databases.export_to($db_adapter, 'localhost', $db_user, '', $db_name)
|
110
|
+
databases.import.source("users").each do |user|
|
111
|
+
target(:user) do |target|
|
112
|
+
target.instance_variable_get('@row_id').should == user['_id'].to_s
|
113
|
+
assign(:organization_id)
|
114
|
+
assign(:name)
|
115
|
+
|
116
|
+
#TODO: Update README to highlight that all embedded docs should have an _id
|
117
|
+
# as all Ruby mappers for MongoDB make one. (according to Durran)
|
118
|
+
user.activities.each do |activity|
|
119
|
+
target(:activity) do |target|
|
120
|
+
assign(:user_id)
|
121
|
+
assign(:name)
|
122
|
+
assign(:due_date)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
116
126
|
end
|
117
127
|
end
|
118
128
|
end
|
@@ -125,8 +135,28 @@ describe Squealer::Database do
|
|
125
135
|
let(:databases) { Squealer::Database.instance }
|
126
136
|
|
127
137
|
it "takes an export database" do
|
128
|
-
databases.export_to('localhost',
|
129
|
-
databases.
|
138
|
+
databases.export_to($db_adapter, 'localhost', $db_user, '', $db_name)
|
139
|
+
databases.instance_variable_get('@export_do').should_not be_nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "upsertable?" do
|
144
|
+
subject { Squealer::Database.instance }
|
145
|
+
|
146
|
+
context "mysql connection" do
|
147
|
+
before do
|
148
|
+
subject.export_to('mysql', 'localhost', 'root', '', 'mysql')
|
149
|
+
end
|
150
|
+
|
151
|
+
it { should be_upsertable }
|
152
|
+
end
|
153
|
+
|
154
|
+
context "postgres connection" do
|
155
|
+
before do
|
156
|
+
subject.export_to('postgres', 'localhost', '', '', 'postgres')
|
157
|
+
end
|
158
|
+
|
159
|
+
it { should_not be_upsertable }
|
130
160
|
end
|
131
161
|
end
|
132
162
|
|
@@ -112,11 +112,11 @@ describe Object do
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def mock_mysql
|
115
|
-
my = mock(
|
116
|
-
|
115
|
+
my = mock(DataObjects::Connection)
|
116
|
+
comm = mock(DataObjects::Command)
|
117
117
|
Squealer::Database.instance.should_receive(:export).at_least(:once).and_return(my)
|
118
|
-
my.should_receive(:
|
119
|
-
|
118
|
+
my.should_receive(:create_command).at_least(:once).and_return(comm)
|
119
|
+
comm.should_receive(:execute_non_query).at_least(:once)
|
120
120
|
end
|
121
121
|
|
122
122
|
end
|