active_git 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
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(@file_name)
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
- ActiveGit.configuration.logger.debug "[ActiveGit] Deleting #{model.model_name} #{model_id}"
29
- record = model.find_by_id(model_id)
30
- record.delete if record
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
 
@@ -1,3 +1,3 @@
1
1
  module ActiveGit
2
- VERSION = '0.0.8'
2
+ VERSION = '0.0.9'
3
3
  end
@@ -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
@@ -4,6 +4,7 @@ describe ActiveGit 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
@@ -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
- languages = [
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
- languages.each do |language|
33
- File.exist?(git_filename(language)).should be true
34
- json = JSON.parse(@file_helper.read_file(git_filename(language)))
35
- json['id'].should eq language.id
36
- json['name'].should eq language.name
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
- country = Country.create! name: 'Argentina'
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}/countries").should be false
49
- File.exists?("#{ActiveGit.configuration.working_path}/countries/#{country.id}.json").should be false
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}/countries").should be false
56
- File.exists?("#{ActiveGit.configuration.working_path}/countries/#{country.id}.json").should be false
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
@@ -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::FATAL
11
+ logger.level = Logger::Severity::ERROR
12
12
 
13
13
  ActiveRecord::Base.logger = logger
14
14
  ActiveGit.configuration.logger = logger
@@ -1,3 +1,4 @@
1
1
  class City < ActiveRecord::Base
2
+ git_included_in :country
2
3
  belongs_to :country
3
4
  end
@@ -1,4 +1,4 @@
1
1
  class Language < ActiveRecord::Base
2
- git_versioned(include: {countries: {include: :cities}})
2
+ git_versioned include: {countries: {include: :cities}}
3
3
  has_many :countries
4
4
  end
@@ -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
- file_name = "#{working_path}/countries/#{country.id}.json"
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(file_name, working_path)
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
- file_name = "#{working_path}/countries/#{country.id}.json"
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, working_path)}
164
+ ActiveGit::Synchronizer.synchronize countries.map {|c| ActiveGit::FileSave.new(c)}
157
165
 
158
166
  events = countries.map do |country|
159
- ActiveGit::DbCreate.new(ActiveGit::Inflector.filename(country, working_path), working_path)
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.8
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-08-16 00:00:00.000000000 Z
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