mongar 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +7 -1
- data/VERSION +1 -1
- data/lib/mongar/replica.rb +29 -3
- data/mongar.gemspec +2 -2
- data/spec/fixtures/sources.rb +10 -0
- data/spec/mongar/replica_spec.rb +97 -0
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -52,6 +52,10 @@ Run it with rails runner (rails 3.x) or script/runner (rails 2.x) script/mongar.
|
|
52
52
|
end
|
53
53
|
|
54
54
|
replicate Client do
|
55
|
+
db_time_selector do
|
56
|
+
current_time_on_db_server
|
57
|
+
end
|
58
|
+
|
55
59
|
column :id do
|
56
60
|
primary_index
|
57
61
|
end
|
@@ -84,7 +88,9 @@ Run it with rails runner (rails 3.x) or script/runner (rails 2.x) script/mongar.
|
|
84
88
|
end
|
85
89
|
|
86
90
|
== Contributing to mongar
|
87
|
-
|
91
|
+
|
92
|
+
Find this project on Pivotal Tracker here: https://www.pivotaltracker.com/projects/434475
|
93
|
+
|
88
94
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
89
95
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
90
96
|
* Fork the project
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.5
|
data/lib/mongar/replica.rb
CHANGED
@@ -4,7 +4,7 @@ class Mongar
|
|
4
4
|
|
5
5
|
attr_accessor :source, :destination, :log_level
|
6
6
|
attr_accessor :mongodb_name
|
7
|
-
attr_accessor :created_finder, :deleted_finder, :updated_finder
|
7
|
+
attr_accessor :created_finder, :deleted_finder, :updated_finder, :db_time_selector
|
8
8
|
attr_accessor :columns
|
9
9
|
|
10
10
|
def initialize(args = {})
|
@@ -24,11 +24,12 @@ class Mongar
|
|
24
24
|
end
|
25
25
|
self.updated_finder = Proc.new do |last_replicated_at|
|
26
26
|
find(:all, :conditions => ["updated_at > ? AND deleted_at IS NULL", last_replicated_at])
|
27
|
-
end
|
27
|
+
end
|
28
28
|
end
|
29
29
|
|
30
30
|
def run
|
31
|
-
time =
|
31
|
+
time = current_time_on_database_server
|
32
|
+
|
32
33
|
if do_full_refresh?
|
33
34
|
info "Running full refresh on Replica #{source.to_s} to #{destination.name}"
|
34
35
|
|
@@ -149,5 +150,30 @@ class Mongar
|
|
149
150
|
self.send("#{finder_type}_finder=".to_sym, nil)
|
150
151
|
end
|
151
152
|
end
|
153
|
+
|
154
|
+
def db_time_selector &block
|
155
|
+
return @db_time_selector unless block_given?
|
156
|
+
|
157
|
+
@db_time_selector = block
|
158
|
+
end
|
159
|
+
|
160
|
+
def default_time_selector(object)
|
161
|
+
adapter = object.connection.class.to_s
|
162
|
+
adapter = $1 if adapter =~ /::([^:]+)$/
|
163
|
+
|
164
|
+
time = if adapter == 'MysqlAdapter'
|
165
|
+
Time.parse(object.connection.execute("SELECT UTC_TIMESTAMP()").fetch_row.first)
|
166
|
+
elsif adapter == 'Mysql2Adapter'
|
167
|
+
object.connection.execute("SELECT UTC_TIMESTAMP()").first.first
|
168
|
+
elsif adapter == 'SQLServerAdapter'
|
169
|
+
object.connection.select_one("SELECT getutcdate() AS date")['date']
|
170
|
+
end
|
171
|
+
|
172
|
+
time.is_a?(Time) ? time : nil
|
173
|
+
end
|
174
|
+
|
175
|
+
def current_time_on_database_server
|
176
|
+
@db_time_selector.nil? ? default_time_selector(source) : source.instance_exec(&@db_time_selector)
|
177
|
+
end
|
152
178
|
end
|
153
179
|
end
|
data/mongar.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "mongar"
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.5"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Philippe Green"]
|
12
|
-
s.date = "2011-12-
|
12
|
+
s.date = "2011-12-15"
|
13
13
|
s.description = "Replicates data from ActiveRecord (or other Ruby data mapping class) to MongoDB"
|
14
14
|
s.email = "phil@greenviewdata.com"
|
15
15
|
s.extra_rdoc_files = [
|
data/spec/fixtures/sources.rb
CHANGED
@@ -1,7 +1,17 @@
|
|
1
|
+
class Mysql2Adapter
|
2
|
+
def execute(sql)
|
3
|
+
[[Time.now.utc]]
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
1
7
|
class Domain
|
2
8
|
attr_accessor :name, :client_id
|
3
9
|
attr_accessor :created_at, :updated_at, :deleted_at
|
4
10
|
|
11
|
+
def self.connection
|
12
|
+
return Mysql2Adapter.new
|
13
|
+
end
|
14
|
+
|
5
15
|
def initialize(args = {})
|
6
16
|
args.each do |key, value|
|
7
17
|
self.send(:"#{key}=", value)
|
data/spec/mongar/replica_spec.rb
CHANGED
@@ -26,6 +26,8 @@ describe "Mongar::Replica" do
|
|
26
26
|
@mongo = Mongar::Mongo.new
|
27
27
|
Mongar::Mongo.databases[:default] = @mongo
|
28
28
|
|
29
|
+
@replica.stub!(:default_time_selector).and_return(@time)
|
30
|
+
|
29
31
|
@last_replicated_time = Time.now - 86400
|
30
32
|
@collection.stub!(:last_replicated_at).and_return(@last_replicated_time)
|
31
33
|
|
@@ -60,6 +62,8 @@ describe "Mongar::Replica" do
|
|
60
62
|
before do
|
61
63
|
@time = Time.parse("1/1/2011 00:00:00")
|
62
64
|
Time.stub!(:now).and_return(@time)
|
65
|
+
@replica.stub!(:default_time_selector).and_return(@time)
|
66
|
+
|
63
67
|
@replica.stub!(:do_full_refresh?).and_return(false)
|
64
68
|
|
65
69
|
@deleted_client1 = Client.new(:name => "Widget Co", :employee_count => 500)
|
@@ -370,4 +374,97 @@ describe "Mongar::Replica" do
|
|
370
374
|
@replica.mongodb.should == @fake_db
|
371
375
|
end
|
372
376
|
end
|
377
|
+
|
378
|
+
describe "#db_time_selector" do
|
379
|
+
before do
|
380
|
+
@block = lambda {}
|
381
|
+
end
|
382
|
+
|
383
|
+
it "should default to nil" do
|
384
|
+
@replica.db_time_selector.should be_nil
|
385
|
+
end
|
386
|
+
|
387
|
+
it "should set the time sql to something else given an argument" do
|
388
|
+
@replica.db_time_selector &@block
|
389
|
+
@replica.db_time_selector.should == @block
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
describe "#current_time_on_database_server" do
|
394
|
+
before do
|
395
|
+
class Client; end
|
396
|
+
@replica.source = Client
|
397
|
+
@time = Time.now
|
398
|
+
end
|
399
|
+
context "default time selector" do
|
400
|
+
it "should call default_time_selector" do
|
401
|
+
@replica.should_receive(:default_time_selector).with(Client).and_return(@time)
|
402
|
+
@replica.current_time_on_database_server.should == @time
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
context "custom time selector" do
|
407
|
+
before do
|
408
|
+
@replica.db_time_selector do
|
409
|
+
current_db_time
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
it "should call the custom time selector function on the source class" do
|
414
|
+
Client.should_receive(:current_db_time).and_return(@time)
|
415
|
+
@replica.current_time_on_database_server.should == @time
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
describe "#default_time_selector" do
|
421
|
+
before do
|
422
|
+
class MockAdapters
|
423
|
+
class MysqlAdapter
|
424
|
+
end
|
425
|
+
|
426
|
+
class Mysql2Adapter
|
427
|
+
end
|
428
|
+
|
429
|
+
class SQLServerAdapter
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
@time = Time.now
|
434
|
+
end
|
435
|
+
|
436
|
+
context "mysql server backend" do
|
437
|
+
before do
|
438
|
+
@mock_connection = MockAdapters::MysqlAdapter.new
|
439
|
+
@mock_source = mock(Object, :connection => @mock_connection)
|
440
|
+
@mock_result = mock(Object, :fetch_row => [@time.to_s])
|
441
|
+
end
|
442
|
+
it "should run SELECT UTC_TIMESTAMP()" do
|
443
|
+
@mock_connection.should_receive(:execute).with("SELECT UTC_TIMESTAMP()").and_return(@mock_result)
|
444
|
+
@replica.default_time_selector(@mock_source).to_s.should == @time.to_s
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
context "mysql server backend with mysql2 adapter" do
|
449
|
+
before do
|
450
|
+
@mock_connection = MockAdapters::Mysql2Adapter.new
|
451
|
+
@mock_source = mock(Object, :connection => @mock_connection)
|
452
|
+
end
|
453
|
+
it "should run SELECT UTC_TIMESTAMP()" do
|
454
|
+
@mock_connection.should_receive(:execute).with("SELECT UTC_TIMESTAMP()").and_return([[@time]])
|
455
|
+
@replica.default_time_selector(@mock_source).should == @time
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
459
|
+
context "sql server backend" do
|
460
|
+
before do
|
461
|
+
@mock_connection = MockAdapters::SQLServerAdapter.new
|
462
|
+
@mock_source = mock(Object, :connection => @mock_connection)
|
463
|
+
end
|
464
|
+
it "should run SELECT getutcdate() as date" do
|
465
|
+
@mock_connection.should_receive(:select_one).with("SELECT getutcdate() AS date").and_return({"date" => @time})
|
466
|
+
@replica.default_time_selector(@mock_source).should == @time
|
467
|
+
end
|
468
|
+
end
|
469
|
+
end
|
373
470
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Philippe Green
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-12-
|
18
|
+
date: 2011-12-15 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
requirement: &id001 !ruby/object:Gem::Requirement
|