active_git 0.0.8 → 0.0.9
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/active_git.gemspec +1 -0
- data/lib/active_git/active_record_extension.rb +35 -0
- data/lib/active_git/events/db_delete_all.rb +5 -0
- data/lib/active_git/events/db_event.rb +21 -4
- data/lib/active_git/version.rb +1 -1
- data/spec/active_record_extension_spec.rb +61 -0
- data/spec/batch_synchronization_spec.rb +1 -0
- data/spec/commands_spec.rb +32 -12
- data/spec/inflector_spec.rb +9 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/support/models/city.rb +1 -0
- data/spec/support/models/language.rb +1 -1
- data/spec/synchronization_spec.rb +24 -16
- metadata +10 -3
data/active_git.gemspec
CHANGED
@@ -9,6 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.description = 'DB and GIT synchronization via ActiveRecord and GitWrapper'
|
10
10
|
s.summary = 'DB and GIT synchronization via ActiveRecord and GitWrapper'
|
11
11
|
s.homepage = 'https://github.com/gabynaiman/active_git'
|
12
|
+
s.license = 'MIT'
|
12
13
|
|
13
14
|
s.files = `git ls-files`.split($\)
|
14
15
|
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -11,6 +11,26 @@ module ActiveGit
|
|
11
11
|
@options
|
12
12
|
end
|
13
13
|
|
14
|
+
def git_included_models
|
15
|
+
git_included_associations.map { |a| reflections[a] ? reflections[a].klass : a.to_s.classify.constantize }
|
16
|
+
end
|
17
|
+
|
18
|
+
def git_included_associations
|
19
|
+
git_deep_included_associations git_options[:include]
|
20
|
+
end
|
21
|
+
|
22
|
+
def git_deep_included_associations(arg)
|
23
|
+
return [] if arg.nil?
|
24
|
+
|
25
|
+
if arg.is_a? Array
|
26
|
+
arg
|
27
|
+
elsif arg.is_a? Hash
|
28
|
+
arg.keys + git_deep_included_associations(arg.map{|k,v| v[:include]})
|
29
|
+
else
|
30
|
+
[arg]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
14
34
|
include InstanceMethods
|
15
35
|
|
16
36
|
ActiveGit.models << self
|
@@ -25,6 +45,21 @@ module ActiveGit
|
|
25
45
|
|
26
46
|
end
|
27
47
|
|
48
|
+
def git_included_in(model)
|
49
|
+
|
50
|
+
after_save do
|
51
|
+
instance = send model
|
52
|
+
#TODO: Ver si se puede optimizar el reload para que no lo haga siempre
|
53
|
+
ActiveGit.synchronize FileSave.new(instance.reload) if instance
|
54
|
+
end
|
55
|
+
|
56
|
+
after_destroy do
|
57
|
+
instance = send model
|
58
|
+
ActiveGit.synchronize FileSave.new(instance.reload) if instance
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
28
63
|
end
|
29
64
|
|
30
65
|
module InstanceMethods
|
@@ -9,6 +9,11 @@ module ActiveGit
|
|
9
9
|
synchronizer.define_job do
|
10
10
|
ActiveGit.configuration.logger.debug "[ActiveGit] Deleting all #{@model.model_name} models"
|
11
11
|
@model.delete_all
|
12
|
+
|
13
|
+
@model.git_included_models.each do |nested_model|
|
14
|
+
ActiveGit.configuration.logger.debug "[ActiveGit] Deleting all #{nested_model.model_name} models (nested of #{@model.model_name})"
|
15
|
+
nested_model.delete_all
|
16
|
+
end
|
12
17
|
end
|
13
18
|
end
|
14
19
|
|
@@ -17,7 +17,7 @@ module ActiveGit
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def create(synchronizer)
|
20
|
-
json = File.read
|
20
|
+
json = File.read @file_name
|
21
21
|
ModelParser.instances(model, json).each do |instance|
|
22
22
|
synchronizer.bulk_insert instance
|
23
23
|
end
|
@@ -25,9 +25,26 @@ module ActiveGit
|
|
25
25
|
|
26
26
|
def delete(synchronizer)
|
27
27
|
synchronizer.define_job do
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
instance = model.find_by_id(model_id)
|
29
|
+
if instance
|
30
|
+
model.git_included_associations.each do |a|
|
31
|
+
if association = instance.reflections[a]
|
32
|
+
if association.collection?
|
33
|
+
instance.send(a).each do |e|
|
34
|
+
ActiveGit.configuration.logger.debug "[ActiveGit] Deleting #{e.class.model_name} #{e.id}"
|
35
|
+
e.delete
|
36
|
+
end
|
37
|
+
else
|
38
|
+
if i = instance.send(a)
|
39
|
+
ActiveGit.configuration.logger.debug "[ActiveGit] Deleting #{i.class.model_name} #{i.id}"
|
40
|
+
instance.send(a).delete
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
ActiveGit.configuration.logger.debug "[ActiveGit] Deleting #{model.model_name} #{model_id}"
|
46
|
+
instance.delete
|
47
|
+
end
|
31
48
|
end
|
32
49
|
end
|
33
50
|
|
data/lib/active_git/version.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe ActiveGit::ActiveRecord do
|
@@ -26,6 +28,17 @@ describe ActiveGit::ActiveRecord do
|
|
26
28
|
json['name'].should eq language.name
|
27
29
|
end
|
28
30
|
|
31
|
+
it 'Create included' do
|
32
|
+
country = Country.create! name: 'Argentina'
|
33
|
+
city = City.create! name: 'Bs.As.', country: country
|
34
|
+
|
35
|
+
JSON.parse(File.read(git_filename(country))).tap do |model|
|
36
|
+
model['cities'].should have(1).items
|
37
|
+
model['cities'][0]['id'].should eq city.id
|
38
|
+
model['cities'][0]['name'].should eq city.name
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
29
42
|
it 'Update' do
|
30
43
|
language = Language.create! name: 'Spanish'
|
31
44
|
|
@@ -38,6 +51,25 @@ describe ActiveGit::ActiveRecord do
|
|
38
51
|
json['name'].should eq 'English'
|
39
52
|
end
|
40
53
|
|
54
|
+
it 'Update included' do
|
55
|
+
country = Country.create! name: 'Argentina'
|
56
|
+
city = City.create! name: 'Bs.As.', country: country
|
57
|
+
|
58
|
+
JSON.parse(File.read(git_filename(country))).tap do |model|
|
59
|
+
model['cities'].should have(1).items
|
60
|
+
model['cities'][0]['id'].should eq city.id
|
61
|
+
model['cities'][0]['name'].should eq 'Bs.As.'
|
62
|
+
end
|
63
|
+
|
64
|
+
city.update_attributes name: 'Córdoba'
|
65
|
+
|
66
|
+
JSON.parse(File.read(git_filename(country))).tap do |model|
|
67
|
+
model['cities'].should have(1).items
|
68
|
+
model['cities'][0]['id'].should eq city.id
|
69
|
+
model['cities'][0]['name'].should eq 'Córdoba'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
41
73
|
it 'Destroy' do
|
42
74
|
language = Language.create! name: 'Spanish'
|
43
75
|
|
@@ -48,6 +80,23 @@ describe ActiveGit::ActiveRecord do
|
|
48
80
|
File.exist?(git_filename(language)).should be false
|
49
81
|
end
|
50
82
|
|
83
|
+
it 'Destroy included' do
|
84
|
+
country = Country.create! name: 'Argentina'
|
85
|
+
city = City.create! name: 'Bs.As.', country: country
|
86
|
+
|
87
|
+
JSON.parse(File.read(git_filename(country))).tap do |model|
|
88
|
+
model['cities'].should have(1).items
|
89
|
+
model['cities'][0]['id'].should eq city.id
|
90
|
+
model['cities'][0]['name'].should eq 'Bs.As.'
|
91
|
+
end
|
92
|
+
|
93
|
+
city.destroy
|
94
|
+
|
95
|
+
JSON.parse(File.read(git_filename(country))).tap do |model|
|
96
|
+
model['cities'].should have(:no).items
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
51
100
|
it 'Dump' do
|
52
101
|
Time.zone = 'Buenos Aires'
|
53
102
|
|
@@ -78,4 +127,16 @@ describe ActiveGit::ActiveRecord do
|
|
78
127
|
country.git_dump.should eq File.read("#{File.dirname(__FILE__)}/json/parent_child_dump.json")
|
79
128
|
end
|
80
129
|
|
130
|
+
it 'Included associations' do
|
131
|
+
Language.git_included_associations.should eq [:countries, :cities]
|
132
|
+
Country.git_included_associations.should eq [:language, :cities]
|
133
|
+
Brand.git_included_associations.should be_empty
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'Included models' do
|
137
|
+
Language.git_included_models.should eq [Country, City]
|
138
|
+
Country.git_included_models.should eq [Language, City]
|
139
|
+
Brand.git_included_models.should be_empty
|
140
|
+
end
|
141
|
+
|
81
142
|
end
|
data/spec/commands_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe ActiveGit::Commands do
|
@@ -15,45 +17,48 @@ describe ActiveGit::Commands do
|
|
15
17
|
context 'Dump and load' do
|
16
18
|
|
17
19
|
it 'Dump complete db to files' do
|
18
|
-
|
20
|
+
models = [
|
19
21
|
Language.create!(name: 'Spanish'),
|
20
|
-
Language.create!(name: 'English')
|
22
|
+
Language.create!(name: 'English'),
|
23
|
+
Brand.create!(name: 'Coca Cola')
|
21
24
|
]
|
22
25
|
|
23
26
|
@file_helper.write_file "#{ActiveGit.configuration.working_path}/test.txt", 'test'
|
24
27
|
@file_helper.write_file "#{git_dirname(Language)}/0.json", 'test'
|
28
|
+
@file_helper.write_file "#{git_dirname(Brand)}/0.json", 'test'
|
25
29
|
|
26
30
|
ActiveGit.dump_db
|
27
31
|
|
28
32
|
File.exist?("#{ActiveGit.configuration.working_path}/test.txt").should be false
|
29
33
|
|
30
34
|
Dir.glob("#{git_dirname(Language)}/*.json").should have(2).items
|
35
|
+
Dir.glob("#{git_dirname(Brand)}/*.json").should have(1).items
|
31
36
|
|
32
|
-
|
33
|
-
File.exist?(git_filename(
|
34
|
-
json = JSON.parse(@file_helper.read_file(git_filename(
|
35
|
-
json['id'].should eq
|
36
|
-
json['name'].should eq
|
37
|
+
models.each do |model|
|
38
|
+
File.exist?(git_filename(model)).should be true
|
39
|
+
json = JSON.parse(@file_helper.read_file(git_filename(model)))
|
40
|
+
json['id'].should eq model.id
|
41
|
+
json['name'].should eq model.name
|
37
42
|
end
|
38
43
|
end
|
39
44
|
|
40
45
|
it 'Dump single table to files' do
|
41
46
|
language = Language.create! name: 'Spanish'
|
42
|
-
|
47
|
+
brand = Brand.create! name: 'Coca Cola'
|
43
48
|
|
44
49
|
Dir["#{ActiveGit.configuration.working_path}/*"].each { |f| FileUtils.rm_rf f }
|
45
50
|
|
46
51
|
Dir.exists?("#{ActiveGit.configuration.working_path}/languages").should be false
|
47
52
|
File.exists?("#{ActiveGit.configuration.working_path}/languages/#{language.id}.json").should be false
|
48
|
-
Dir.exists?("#{ActiveGit.configuration.working_path}/
|
49
|
-
File.exists?("#{ActiveGit.configuration.working_path}/
|
53
|
+
Dir.exists?("#{ActiveGit.configuration.working_path}/brands").should be false
|
54
|
+
File.exists?("#{ActiveGit.configuration.working_path}/brands/#{brand.id}.json").should be false
|
50
55
|
|
51
56
|
ActiveGit.dump_db Language
|
52
57
|
|
53
58
|
Dir.exists?("#{ActiveGit.configuration.working_path}/languages").should be true
|
54
59
|
File.exists?("#{ActiveGit.configuration.working_path}/languages/#{language.id}.json").should be true
|
55
|
-
Dir.exists?("#{ActiveGit.configuration.working_path}/
|
56
|
-
File.exists?("#{ActiveGit.configuration.working_path}/
|
60
|
+
Dir.exists?("#{ActiveGit.configuration.working_path}/brands").should be false
|
61
|
+
File.exists?("#{ActiveGit.configuration.working_path}/brands/#{brand.id}.json").should be false
|
57
62
|
end
|
58
63
|
|
59
64
|
it 'Load all files to db' do
|
@@ -93,6 +98,21 @@ describe ActiveGit::Commands do
|
|
93
98
|
Brand.find_by_id(brand.id).should be_nil
|
94
99
|
end
|
95
100
|
|
101
|
+
it 'Load nested models' do
|
102
|
+
country = Country.create! name: 'Argentina'
|
103
|
+
country.cities << City.new(name: 'Bs.As.')
|
104
|
+
country.cities << City.new(name: 'Córdoba')
|
105
|
+
country.cities << City.new(name: 'Rosario')
|
106
|
+
|
107
|
+
country.cities[0].delete
|
108
|
+
country.delete
|
109
|
+
|
110
|
+
ActiveGit.load_files Country
|
111
|
+
|
112
|
+
country = Country.find(country.id)
|
113
|
+
country.should have(3).cities
|
114
|
+
end
|
115
|
+
|
96
116
|
end
|
97
117
|
|
98
118
|
context 'Git synchronization' do
|
data/spec/inflector_spec.rb
CHANGED
@@ -2,6 +2,15 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe ActiveGit::Inflector do
|
4
4
|
|
5
|
+
before :each do
|
6
|
+
@file_helper = FileHelper.new
|
7
|
+
ActiveGit.configuration.working_path = @file_helper.create_temp_folder
|
8
|
+
end
|
9
|
+
|
10
|
+
after :each do
|
11
|
+
@file_helper.remove_temp_folders
|
12
|
+
end
|
13
|
+
|
5
14
|
let(:working_path) { '/home/git' }
|
6
15
|
|
7
16
|
it 'Git path' do
|
data/spec/spec_helper.rb
CHANGED
@@ -8,7 +8,7 @@ ActiveRecord::Migrator.migrations_path = "#{File.dirname(__FILE__)}/migrations"
|
|
8
8
|
ActiveRecord::Migration.verbose = false
|
9
9
|
|
10
10
|
logger = Logger.new($stdout)
|
11
|
-
logger.level = Logger::Severity::
|
11
|
+
logger.level = Logger::Severity::ERROR
|
12
12
|
|
13
13
|
ActiveRecord::Base.logger = logger
|
14
14
|
ActiveGit.configuration.logger = logger
|
data/spec/support/models/city.rb
CHANGED
@@ -4,6 +4,7 @@ describe ActiveGit::Synchronizer do
|
|
4
4
|
|
5
5
|
before :each do
|
6
6
|
@file_helper = FileHelper.new
|
7
|
+
ActiveGit.configuration.working_path = @file_helper.create_temp_folder
|
7
8
|
end
|
8
9
|
|
9
10
|
after :each do
|
@@ -106,46 +107,53 @@ describe ActiveGit::Synchronizer do
|
|
106
107
|
argentina.cities.count.should eq 2
|
107
108
|
argentina.cities.should include(City.find_by_name 'Buenos Aires')
|
108
109
|
argentina.cities.should include(City.find_by_name 'Rosario')
|
109
|
-
argentina.cities.should_not include(City.find_by_name 'Montevideo')
|
110
110
|
|
111
111
|
uruguay = Country.find_by_name 'Uruguay'
|
112
112
|
|
113
113
|
uruguay.cities.count.should eq 2
|
114
114
|
uruguay.cities.should include(City.find_by_name 'Montevideo')
|
115
115
|
uruguay.cities.should include(City.find_by_name 'Colonia')
|
116
|
-
uruguay.cities.should_not include(City.find_by_name 'Buenos Aires')
|
117
116
|
end
|
118
117
|
|
119
118
|
it 'Update' do
|
120
|
-
working_path = @file_helper.create_temp_folder
|
121
|
-
|
122
119
|
country = Country.create! name: 'Argentina'
|
123
120
|
|
124
|
-
|
125
|
-
@file_helper.write_file file_name, country.attributes.merge('name' => 'Brasil').to_json
|
121
|
+
@file_helper.write_file git_filename(country), country.attributes.merge('name' => 'Brasil').to_json
|
126
122
|
|
127
|
-
ActiveGit::Synchronizer.synchronize ActiveGit::DbUpdate.new(
|
123
|
+
ActiveGit::Synchronizer.synchronize ActiveGit::DbUpdate.new(git_filename(country))
|
128
124
|
|
129
125
|
country.reload.name.should eq 'Brasil'
|
130
126
|
end
|
131
127
|
|
132
128
|
it 'Destroy' do
|
133
|
-
working_path = @file_helper.create_temp_folder
|
134
|
-
|
135
129
|
country = Country.create! name: 'Argentina'
|
136
130
|
|
137
|
-
|
138
|
-
|
139
|
-
ActiveGit::Synchronizer.synchronize ActiveGit::DbDelete.new(file_name, working_path)
|
131
|
+
ActiveGit::Synchronizer.synchronize ActiveGit::DbDelete.new(git_filename(country))
|
140
132
|
|
141
133
|
Country.find_by_id(country.id).should be_nil
|
142
134
|
end
|
143
135
|
|
136
|
+
it 'Destroy nested models' do
|
137
|
+
country1 = Country.create! name: 'Argentina'
|
138
|
+
country1.cities << City.new(name: 'Bs.As.')
|
139
|
+
country1.cities << City.new(name: 'Rosario')
|
140
|
+
|
141
|
+
country2 = Country.create! name: 'Uruguay'
|
142
|
+
country2.cities << City.new(name: 'Montevideo')
|
143
|
+
country2.cities << City.new(name: 'Colonia')
|
144
|
+
|
145
|
+
Country.count.should eq 2
|
146
|
+
City.count.should eq 4
|
147
|
+
|
148
|
+
ActiveGit::Synchronizer.synchronize ActiveGit::DbDelete.new(git_filename(country1))
|
149
|
+
|
150
|
+
Country.count.should eq 1
|
151
|
+
City.count.should eq 2
|
152
|
+
end
|
153
|
+
|
144
154
|
it 'Batch size' do
|
145
155
|
ActiveGit.configuration.sync_batch_size = 2
|
146
156
|
|
147
|
-
working_path = @file_helper.create_temp_folder
|
148
|
-
|
149
157
|
countries = 10.times.map do |i|
|
150
158
|
Country.new(name: "Country #{i}") do |country|
|
151
159
|
country.id = i.to_s
|
@@ -153,10 +161,10 @@ describe ActiveGit::Synchronizer do
|
|
153
161
|
country.updated_at = Time.now
|
154
162
|
end
|
155
163
|
end
|
156
|
-
ActiveGit::Synchronizer.synchronize countries.map {|c| ActiveGit::FileSave.new(c
|
164
|
+
ActiveGit::Synchronizer.synchronize countries.map {|c| ActiveGit::FileSave.new(c)}
|
157
165
|
|
158
166
|
events = countries.map do |country|
|
159
|
-
ActiveGit::DbCreate.new(
|
167
|
+
ActiveGit::DbCreate.new(git_filename(country))
|
160
168
|
end
|
161
169
|
|
162
170
|
Country.should_receive(:import).
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_git
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-09-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -228,7 +228,8 @@ files:
|
|
228
228
|
- spec/support/models/language.rb
|
229
229
|
- spec/synchronization_spec.rb
|
230
230
|
homepage: https://github.com/gabynaiman/active_git
|
231
|
-
licenses:
|
231
|
+
licenses:
|
232
|
+
- MIT
|
232
233
|
post_install_message:
|
233
234
|
rdoc_options: []
|
234
235
|
require_paths:
|
@@ -239,12 +240,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
239
240
|
- - ! '>='
|
240
241
|
- !ruby/object:Gem::Version
|
241
242
|
version: '0'
|
243
|
+
segments:
|
244
|
+
- 0
|
245
|
+
hash: 3436893494460006310
|
242
246
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
243
247
|
none: false
|
244
248
|
requirements:
|
245
249
|
- - ! '>='
|
246
250
|
- !ruby/object:Gem::Version
|
247
251
|
version: '0'
|
252
|
+
segments:
|
253
|
+
- 0
|
254
|
+
hash: 3436893494460006310
|
248
255
|
requirements: []
|
249
256
|
rubyforge_project:
|
250
257
|
rubygems_version: 1.8.25
|