nd_sync 0.0.1 → 0.0.3
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 +4 -4
- data/.rspec +1 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +54 -0
- data/README.md +3 -0
- data/lib/nd_sync/local.rb +50 -0
- data/lib/nd_sync/remote.rb +38 -0
- data/nd_sync.gemspec +21 -0
- data/spec/lib/nd_sync/local_spec.rb +119 -0
- data/spec/lib/nd_sync/remote_spec.rb +42 -0
- data/spec/lib/nd_sync_spec.rb +74 -0
- data/spec/spec_helper.rb +12 -0
- metadata +19 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d0aed4d787144688f5724075f552fb90d6ea48e
|
4
|
+
data.tar.gz: 2b3f8eda58da146fa9430948f37319c67ab41942
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce0c50d0c5fef26e25a8ca16115cb000991425b7c87197714561eeebe7cef451fa7cc38061c1b80e48d59ad815d52e01123fcc608cee9ae97ce4c84b27584aa2
|
7
|
+
data.tar.gz: 31bb939ebbf10114342493b1d71a73894e8a885a4084c03f0f2127aecfef4807b93d0be071004b3d197dbe917cfaf676b8a384d54d7955aa3c10e6377942ec7d
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
nd_sync (0.0.1)
|
5
|
+
activerecord (~> 3)
|
6
|
+
activeresource (~> 3)
|
7
|
+
activesupport (~> 3)
|
8
|
+
jbuilder (~> 2.0)
|
9
|
+
nd_transcriber (~> 0.0)
|
10
|
+
nd_transmission (~> 0.0)
|
11
|
+
|
12
|
+
GEM
|
13
|
+
remote: https://rubygems.org/
|
14
|
+
specs:
|
15
|
+
activemodel (3.2.17)
|
16
|
+
activesupport (= 3.2.17)
|
17
|
+
builder (~> 3.0.0)
|
18
|
+
activerecord (3.2.17)
|
19
|
+
activemodel (= 3.2.17)
|
20
|
+
activesupport (= 3.2.17)
|
21
|
+
arel (~> 3.0.2)
|
22
|
+
tzinfo (~> 0.3.29)
|
23
|
+
activeresource (3.2.17)
|
24
|
+
activemodel (= 3.2.17)
|
25
|
+
activesupport (= 3.2.17)
|
26
|
+
activesupport (3.2.17)
|
27
|
+
i18n (~> 0.6, >= 0.6.4)
|
28
|
+
multi_json (~> 1.0)
|
29
|
+
addressable (2.3.6)
|
30
|
+
arel (3.0.3)
|
31
|
+
builder (3.0.4)
|
32
|
+
crack (0.4.2)
|
33
|
+
safe_yaml (~> 1.0.0)
|
34
|
+
i18n (0.6.11)
|
35
|
+
jbuilder (2.0.6)
|
36
|
+
activesupport (>= 3.0.0, < 5)
|
37
|
+
multi_json (~> 1.2)
|
38
|
+
multi_json (1.10.1)
|
39
|
+
nd_transcriber (0.0.1)
|
40
|
+
nd_transmission (0.0.1)
|
41
|
+
safe_yaml (1.0.3)
|
42
|
+
sqlite3 (1.3.9)
|
43
|
+
tzinfo (0.3.41)
|
44
|
+
webmock (1.18.0)
|
45
|
+
addressable (>= 2.3.6)
|
46
|
+
crack (>= 0.3.2)
|
47
|
+
|
48
|
+
PLATFORMS
|
49
|
+
ruby
|
50
|
+
|
51
|
+
DEPENDENCIES
|
52
|
+
nd_sync!
|
53
|
+
sqlite3
|
54
|
+
webmock
|
data/README.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
module NdSync
|
2
|
+
module Local
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
include NdTranscriber
|
7
|
+
|
8
|
+
scope :pending, -> { where('step = desired_step - 1') }
|
9
|
+
scope :synched, -> { where('step = desired_step') }
|
10
|
+
|
11
|
+
def model_object
|
12
|
+
model_class.find(origin_id)
|
13
|
+
end
|
14
|
+
|
15
|
+
def model_class
|
16
|
+
@model_class ||= Class.new(ActiveRecord::Base)
|
17
|
+
@model_class.table_name = origin_table
|
18
|
+
@model_class.primary_key = origin_id_field
|
19
|
+
@model_class
|
20
|
+
end
|
21
|
+
|
22
|
+
def transmitted_to web
|
23
|
+
updates = {}
|
24
|
+
|
25
|
+
if web.try(:errors).try(:any?)
|
26
|
+
updates[origin_step_field] = -1
|
27
|
+
else
|
28
|
+
updates[origin_step_field] = desired_step
|
29
|
+
updates[:web_id] = web.id if web.id && respond_to?(:web_id)
|
30
|
+
end
|
31
|
+
|
32
|
+
model_class.where(origin_id_field => origin_id).update_all(updates)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module ClassMethods
|
37
|
+
def to_transmit
|
38
|
+
pending.to_a
|
39
|
+
end
|
40
|
+
|
41
|
+
def receive(collection)
|
42
|
+
collection.each do |remote|
|
43
|
+
local = transcribe(remote)
|
44
|
+
local.save
|
45
|
+
remote.transmitted_to(local)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module NdSync
|
2
|
+
module Remote
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
include NdTranscriber
|
7
|
+
|
8
|
+
def transmitted_to(local)
|
9
|
+
put("synched/#{local.id}")
|
10
|
+
end
|
11
|
+
|
12
|
+
self.site = NdSync.remote_site
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
def to_transmit
|
17
|
+
find(:all, params: { sync_pending: true }).to_a
|
18
|
+
end
|
19
|
+
|
20
|
+
def receive(locals)
|
21
|
+
response = post(:batch, {}, to_batch(transcribe_all(locals)))
|
22
|
+
JSON.parse(response.body).each_with_index do |remote_hash, idx|
|
23
|
+
locals[idx].transmitted_to new(remote_hash)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_batch(collection)
|
28
|
+
Jbuilder.encode do |json|
|
29
|
+
json.set! collection_name do
|
30
|
+
json.array! collection do |item|
|
31
|
+
item.to_batch json
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/nd_sync.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'nd_sync'
|
3
|
+
s.version = '0.0.3'
|
4
|
+
s.date = '2014-09-01'
|
5
|
+
s.summary = "Synchronizing local and remote objects."
|
6
|
+
s.description = "Synchronizes database with RESTful web service."
|
7
|
+
s.authors = ["Diego Aguir Selzlein"]
|
8
|
+
s.email = 'diegoselzlein@gmail.com'
|
9
|
+
s.homepage = 'https://github.com/nerde/nd_sync'
|
10
|
+
s.license = 'MIT'
|
11
|
+
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.require_paths = ["lib"]
|
14
|
+
|
15
|
+
s.add_dependency("jbuilder" , '~> 2.0')
|
16
|
+
s.add_dependency("activesupport" , '~> 3')
|
17
|
+
s.add_dependency("activerecord" , '~> 3')
|
18
|
+
s.add_dependency("activeresource" , '~> 3')
|
19
|
+
s.add_dependency("nd_transcriber" , '~> 0.0')
|
20
|
+
s.add_dependency("nd_transmission", '~> 0.0')
|
21
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe NdSync::Local do
|
4
|
+
before(:all) do
|
5
|
+
class Model < ActiveRecord::Base
|
6
|
+
end
|
7
|
+
|
8
|
+
class View < ActiveRecord::Base
|
9
|
+
include NdSync::Local
|
10
|
+
attr_accessor :transcribed
|
11
|
+
|
12
|
+
alias :transcribed? :transcribed
|
13
|
+
end
|
14
|
+
|
15
|
+
Model.connection.create_table :models do |t|
|
16
|
+
t.integer :paso
|
17
|
+
t.integer :web_id
|
18
|
+
end
|
19
|
+
Model.connection.create_table :views do |t|
|
20
|
+
t.integer :step
|
21
|
+
t.integer :desired_step
|
22
|
+
t.string :origin_table
|
23
|
+
t.string :origin_id_field
|
24
|
+
t.string :origin_step_field
|
25
|
+
t.integer :origin_id
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
before do
|
30
|
+
Model.delete_all
|
31
|
+
View.delete_all
|
32
|
+
end
|
33
|
+
|
34
|
+
it "makes transcriber available" do
|
35
|
+
View.transcriber do
|
36
|
+
self.transcribed = true
|
37
|
+
end
|
38
|
+
|
39
|
+
expect(View.transcribe(nil)).to be_transcribed
|
40
|
+
end
|
41
|
+
|
42
|
+
it "transmits objects where step is desired_step - 1" do
|
43
|
+
vi1 = View.create! step: 0, desired_step: 2
|
44
|
+
vi2 = View.create! step: 1, desired_step: 2
|
45
|
+
vi3 = View.create! step: 2, desired_step: 2
|
46
|
+
|
47
|
+
pendings = View.to_transmit
|
48
|
+
|
49
|
+
expect(pendings ).to be_kind_of Array
|
50
|
+
expect(pendings.size).to eq 1
|
51
|
+
expect(pendings ).not_to include vi1
|
52
|
+
expect(pendings ).to include vi2
|
53
|
+
expect(pendings ).not_to include vi3
|
54
|
+
end
|
55
|
+
|
56
|
+
it "generates model class dinamically" do
|
57
|
+
vi = View.new(origin_table: 'models', origin_id_field: 'code')
|
58
|
+
|
59
|
+
expect(vi.model_class.superclass ).to be ActiveRecord::Base
|
60
|
+
expect(vi.model_class.table_name ).to eq 'models'
|
61
|
+
expect(vi.model_class.primary_key).to eq 'code'
|
62
|
+
end
|
63
|
+
|
64
|
+
it "loads it's model's object" do
|
65
|
+
vi = View.new(origin_table: 'models', origin_id_field: 'id', origin_id: 3)
|
66
|
+
Model.create!(id: 1)
|
67
|
+
mo = Model.create!(id: 3)
|
68
|
+
|
69
|
+
expect(vi.model_object.id).to eq mo.id
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'transmitted_to' do
|
73
|
+
it "marks model as synched" do
|
74
|
+
vi = View.new(origin_table: 'models', origin_id_field: 'id', origin_id: 3,
|
75
|
+
origin_step_field: 'paso', step: 1, desired_step: 2)
|
76
|
+
mo1 = Model.create!(id: 3, paso: 1)
|
77
|
+
mo2 = Model.create!(id: 1, paso: 1)
|
78
|
+
|
79
|
+
vi.transmitted_to double(id: 5)
|
80
|
+
|
81
|
+
mo1.reload
|
82
|
+
mo2.reload
|
83
|
+
expect(mo1.paso).to eq 2
|
84
|
+
expect(mo2.paso).to eq 1
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'view responds to web_id' do
|
88
|
+
it "updates its model's web_id" do
|
89
|
+
vi = View.new(origin_table: 'models', origin_id_field: 'id', origin_id: 3,
|
90
|
+
origin_step_field: 'paso', step: 1, desired_step: 2)
|
91
|
+
def vi.web_id
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
mo1 = Model.create!(id: 3, paso: 1)
|
95
|
+
|
96
|
+
vi.transmitted_to double(id: 5)
|
97
|
+
|
98
|
+
mo1.reload
|
99
|
+
expect(mo1.web_id).to eq 5
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'received object contains errors' do
|
104
|
+
it "marks object as problematic" do
|
105
|
+
vi = View.new(origin_table: 'models', origin_id_field: 'id', origin_id: 3,
|
106
|
+
origin_step_field: 'paso', step: 1, desired_step: 2)
|
107
|
+
mo1 = Model.create!(id: 3, paso: 1)
|
108
|
+
mo2 = Model.create!(id: 1, paso: 1)
|
109
|
+
|
110
|
+
vi.transmitted_to double(id: 5, errors: ['error'])
|
111
|
+
|
112
|
+
mo1.reload
|
113
|
+
mo2.reload
|
114
|
+
expect(mo1.paso).to eq -1
|
115
|
+
expect(mo2.paso).to eq 1
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe NdSync::Remote do
|
4
|
+
NdSync.remote_site = 'http://localhost:3210'
|
5
|
+
|
6
|
+
class RemoteModel < ActiveResource::Base
|
7
|
+
include NdSync::Remote
|
8
|
+
|
9
|
+
def to_batch json
|
10
|
+
json.(self, :name)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "loads site from NdSync" do
|
15
|
+
expect(RemoteModel.site).to eq URI('http://localhost:3210')
|
16
|
+
end
|
17
|
+
|
18
|
+
it "transmits objects requesting by sync_pending" do
|
19
|
+
stub_request(:get, "localhost:3210/remote_models.json").with(query: {sync_pending: 'true'}).
|
20
|
+
to_return(body: [{id: 5}].to_json, :status => 200)
|
21
|
+
|
22
|
+
webs = RemoteModel.to_transmit
|
23
|
+
expect(webs.size ).to eq 1
|
24
|
+
expect(webs.first.id).to eq 5
|
25
|
+
end
|
26
|
+
|
27
|
+
it "generates objects in JSON to be uploaded" do
|
28
|
+
rm = RemoteModel.new(name: 'test')
|
29
|
+
|
30
|
+
expect(RemoteModel.to_batch([rm])).to eq({remote_models: [{name: 'test'}]}.to_json)
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "transmitted_to" do
|
34
|
+
it "updates remote object with local ID" do
|
35
|
+
req = stub_request(:put, "localhost:3210/remote_models/3/synched/5.json")
|
36
|
+
|
37
|
+
RemoteModel.new(id: 3).transmitted_to double(id: 5)
|
38
|
+
|
39
|
+
expect(req).to have_been_requested
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe NdSync do
|
4
|
+
NdSync.remote_site = 'http://localhost:3210'
|
5
|
+
|
6
|
+
class Local < ActiveRecord::Base
|
7
|
+
include NdSync::Local
|
8
|
+
|
9
|
+
transcriber do
|
10
|
+
copy_fields :id => :web_id
|
11
|
+
end
|
12
|
+
|
13
|
+
def origin_step_field
|
14
|
+
:step
|
15
|
+
end
|
16
|
+
|
17
|
+
def origin_table
|
18
|
+
self.class.table_name
|
19
|
+
end
|
20
|
+
|
21
|
+
def origin_id_field
|
22
|
+
self.class.primary_key
|
23
|
+
end
|
24
|
+
|
25
|
+
alias :origin_id :id
|
26
|
+
end
|
27
|
+
|
28
|
+
class Remote < ActiveResource::Base
|
29
|
+
include NdSync::Remote
|
30
|
+
|
31
|
+
def to_batch(json)
|
32
|
+
json.(self, :id)
|
33
|
+
end
|
34
|
+
|
35
|
+
transcriber do
|
36
|
+
copy_fields :web_id => :id
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
before(:all) do
|
41
|
+
Local.connection.create_table :locals do |t|
|
42
|
+
t.integer :web_id
|
43
|
+
t.integer :step
|
44
|
+
t.integer :desired_step
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
before do
|
49
|
+
Local.delete_all
|
50
|
+
end
|
51
|
+
|
52
|
+
it "allows to download data" do
|
53
|
+
stub_request(:get, "localhost:3210/remotes.json").with(query: {sync_pending: 'true'}).
|
54
|
+
to_return(body: [{id: 5}].to_json, :status => 200)
|
55
|
+
req = stub_request(:put, /localhost:3210\/remotes\/5\/synched\/\d\.json/)
|
56
|
+
|
57
|
+
expect do
|
58
|
+
NdTransmission::Base.new(Remote => Local).transmit
|
59
|
+
end.to change(Local, :count).by(1)
|
60
|
+
expect(req).to have_been_requested
|
61
|
+
end
|
62
|
+
|
63
|
+
it "allows to upload data" do
|
64
|
+
Local.create!(web_id: 5, step: 1, desired_step: 2)
|
65
|
+
req = stub_request(:post, "localhost:3210/remotes/batch.json").
|
66
|
+
with(body: {remotes: [{id: 5}]}).
|
67
|
+
to_return(body: [{id: 5}].to_json, :status => 200)
|
68
|
+
|
69
|
+
expect do
|
70
|
+
NdTransmission::Base.new(Local => Remote).transmit
|
71
|
+
end.to change(Local.pending, :count).by(-1)
|
72
|
+
expect(req).to have_been_requested
|
73
|
+
end
|
74
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.expand_path('../../lib/nd_sync', __FILE__)
|
2
|
+
require 'sqlite3'
|
3
|
+
require 'webmock/rspec'
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.order = "random"
|
7
|
+
config.before { GC.disable }
|
8
|
+
config.after { GC.enable }
|
9
|
+
config.before(:all) do
|
10
|
+
ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
|
11
|
+
end
|
12
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nd_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Diego Aguir Selzlein
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jbuilder
|
@@ -30,42 +30,42 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '3'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: activerecord
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '3'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '3'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: activeresource
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '3'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '3'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: nd_transcriber
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,7 +100,18 @@ executables: []
|
|
100
100
|
extensions: []
|
101
101
|
extra_rdoc_files: []
|
102
102
|
files:
|
103
|
+
- ".rspec"
|
104
|
+
- Gemfile
|
105
|
+
- Gemfile.lock
|
106
|
+
- README.md
|
103
107
|
- lib/nd_sync.rb
|
108
|
+
- lib/nd_sync/local.rb
|
109
|
+
- lib/nd_sync/remote.rb
|
110
|
+
- nd_sync.gemspec
|
111
|
+
- spec/lib/nd_sync/local_spec.rb
|
112
|
+
- spec/lib/nd_sync/remote_spec.rb
|
113
|
+
- spec/lib/nd_sync_spec.rb
|
114
|
+
- spec/spec_helper.rb
|
104
115
|
homepage: https://github.com/nerde/nd_sync
|
105
116
|
licenses:
|
106
117
|
- MIT
|