active_git 0.0.7 → 0.0.8

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.
@@ -3,7 +3,16 @@ module ActiveGit
3
3
 
4
4
  module ClassMethods
5
5
 
6
- def git_versioned
6
+ def git_versioned(options={})
7
+
8
+ @options = options.merge root: false
9
+
10
+ def git_options
11
+ @options
12
+ end
13
+
14
+ include InstanceMethods
15
+
7
16
  ActiveGit.models << self
8
17
 
9
18
  after_save do |record|
@@ -14,22 +23,17 @@ module ActiveGit
14
23
  ActiveGit.synchronize FileDelete.new(record)
15
24
  end
16
25
 
17
- def from_json(json)
18
- record = self.new
19
- hash = json.is_a?(Hash) ? json : JSON.parse(json)
20
- hash.each do |attr, value|
21
- if record.respond_to? "#{attr}="
22
- if self.columns_hash[attr].type == :datetime
23
- record.send("#{attr}=", Time.parse(value).utc)
24
- else
25
- record.send("#{attr}=", value)
26
- end
27
- end
28
- end
29
- record
30
- end
31
26
  end
32
27
 
33
28
  end
29
+
30
+ module InstanceMethods
31
+
32
+ def git_dump
33
+ JSON.pretty_generate(as_json(self.class.git_options))
34
+ end
35
+
36
+ end
37
+
34
38
  end
35
39
  end
@@ -84,7 +84,7 @@ module ActiveGit
84
84
 
85
85
  model = File.dirname(file_name).split(/\/|\\/).pop.classify.constantize
86
86
 
87
- FileSave.new(model.from_json(merge))
87
+ FileSave.new(ModelParser.from_json(model, merge))
88
88
  end
89
89
 
90
90
  Synchronizer.synchronize events
@@ -6,10 +6,6 @@ module ActiveGit
6
6
  @working_path = working_path || ActiveGit.configuration.working_path
7
7
  end
8
8
 
9
- def synchronize(synchronizer)
10
- raise 'Must implement in subclass'
11
- end
12
-
13
9
  private
14
10
 
15
11
  def model
@@ -20,13 +16,11 @@ module ActiveGit
20
16
  Inflector.model_id @file_name
21
17
  end
22
18
 
23
- def data
24
- json = File.open(@file_name, 'r') { |f| f.read }
25
- model.from_json(json)
26
- end
27
-
28
19
  def create(synchronizer)
29
- synchronizer.bulk_insert data
20
+ json = File.read(@file_name)
21
+ ModelParser.instances(model, json).each do |instance|
22
+ synchronizer.bulk_insert instance
23
+ end
30
24
  end
31
25
 
32
26
  def delete(synchronizer)
@@ -1,32 +1,18 @@
1
1
  module ActiveGit
2
2
  class FileEvent
3
3
 
4
+ attr_reader :data
5
+
4
6
  def initialize(data, working_path=nil)
5
7
  @data = data
6
8
  @working_path = working_path || ActiveGit.configuration.working_path
7
9
  end
8
10
 
9
- def synchronize(synchronizer)
10
- raise 'Must implement in subclass'
11
- end
12
-
13
11
  protected
14
12
 
15
- def model
16
- @data.class
17
- end
18
-
19
- def model_path
20
- Inflector.dirname(model, @working_path)
21
- end
22
-
23
13
  def file_name
24
14
  Inflector.filename(@data, @working_path)
25
15
  end
26
16
 
27
- def json
28
- JSON.pretty_generate(@data.attributes)
29
- end
30
-
31
17
  end
32
18
  end
@@ -5,7 +5,7 @@ module ActiveGit
5
5
  synchronizer.define_job do
6
6
  ActiveGit.configuration.logger.debug "[ActiveGit] Writing file #{file_name}"
7
7
  FileUtils.mkpath(File.dirname(file_name)) unless Dir.exist?(File.dirname(file_name))
8
- File.open(file_name, 'w') { |f| f.puts json }
8
+ File.open(file_name, 'w') { |f| f.puts data.git_dump }
9
9
  end
10
10
 
11
11
  end
@@ -0,0 +1,36 @@
1
+ module ActiveGit
2
+ class ModelParser
3
+
4
+ def self.instances(model, json)
5
+ list = [from_json(model, json)]
6
+ attributes = json.is_a?(Hash) ? json : JSON.parse(json)
7
+ attributes.each do |attr, value|
8
+ if model.reflections.has_key?(attr.to_sym)
9
+ attr_model = attr.to_s.classify.constantize
10
+ if value.is_a? Array
11
+ value.each {|json| list = list + instances(attr_model, json)}
12
+ else
13
+ list = list + instances(attr_model, value)
14
+ end
15
+ end
16
+ end
17
+ list
18
+ end
19
+
20
+ def self.from_json(model, json)
21
+ record = model.new
22
+ attributes = json.is_a?(Hash) ? json : JSON.parse(json)
23
+ attributes.each do |attr, value|
24
+ if model.column_names.include?(attr.to_s)
25
+ if model.columns_hash[attr.to_s].type == :datetime && value.is_a?(String)
26
+ record.send("#{attr}=", Time.parse(value).utc)
27
+ else
28
+ record.send("#{attr}=", value)
29
+ end
30
+ end
31
+ end
32
+ record
33
+ end
34
+
35
+ end
36
+ end
@@ -1,3 +1,3 @@
1
1
  module ActiveGit
2
- VERSION = '0.0.7'
2
+ VERSION = '0.0.8'
3
3
  end
data/lib/active_git.rb CHANGED
@@ -21,6 +21,7 @@ require 'active_git/active_record_extension'
21
21
  require 'active_git/configuration'
22
22
  require 'active_git/commands'
23
23
  require 'active_git/inflector'
24
+ require 'active_git/model_parser'
24
25
 
25
26
  module ActiveGit
26
27
  extend Commands
@@ -54,18 +55,22 @@ module ActiveGit
54
55
  @batch_mode = true
55
56
  begin
56
57
  result = yield
57
- Synchronizer.synchronize @events
58
+ Synchronizer.synchronize queued_events
58
59
  result
59
60
  ensure
60
61
  @batch_mode = false
61
- @events.clear if @events
62
+ queued_events.clear
62
63
  end
63
64
  end
64
65
 
65
66
  private
66
67
 
67
68
  def self.enqueue(*events)
68
- @events = (@events || []) + events
69
+ events.each { |e| queued_events << e }
70
+ end
71
+
72
+ def self.queued_events
73
+ @events ||= []
69
74
  end
70
75
 
71
76
  end
@@ -48,14 +48,34 @@ describe ActiveGit::ActiveRecord do
48
48
  File.exist?(git_filename(language)).should be false
49
49
  end
50
50
 
51
- it 'Load from json' do
52
- attributes = {id: 1, name: 'Spanish', created_at: Time.now, updated_at: Time.now}
53
- language = Language.from_json attributes.to_json
54
-
55
- language.id.should eq attributes[:id]
56
- language.name.should eq attributes[:name]
57
- language.created_at.to_i.should eq attributes[:created_at].to_i
58
- language.updated_at.to_i.should eq attributes[:updated_at].to_i
51
+ it 'Dump' do
52
+ Time.zone = 'Buenos Aires'
53
+
54
+ brand = Brand.new name: 'Brand 1',
55
+ created_at: Time.zone.parse('2012-04-20T11:24:11'),
56
+ updated_at: Time.zone.parse('2012-04-20T11:24:11')
57
+
58
+ brand.git_dump.should eq File.read("#{File.dirname(__FILE__)}/json/dump.json")
59
+ end
60
+
61
+ it 'Nested dump' do
62
+ city = City.new name: 'Bs.As.'
63
+ country = Country.new name: 'Argentina'
64
+ country.cities << city
65
+ language = Language.new name: 'Spanish'
66
+ language.countries << country
67
+
68
+ language.git_dump.should eq File.read("#{File.dirname(__FILE__)}/json/nested_dump.json")
69
+ end
70
+
71
+ it 'Parent and child dump' do
72
+ language = Language.new name: 'Spanish'
73
+ city = City.new name: 'Bs.As.'
74
+ country = Country.new name: 'Argentina'
75
+ country.cities << city
76
+ country.language = language
77
+
78
+ country.git_dump.should eq File.read("#{File.dirname(__FILE__)}/json/parent_child_dump.json")
59
79
  end
60
80
 
61
81
  end
@@ -113,6 +113,11 @@ describe ActiveGit do
113
113
  File.exist?(git_filename(english)).should be true
114
114
  end
115
115
 
116
+ it 'Batch process without events' do
117
+ Language.count.should eq 0
118
+ ActiveGit.batch {}
119
+ end
120
+
116
121
  it 'Handle exceptions' do
117
122
  spanish = nil
118
123
  english = nil
@@ -13,7 +13,7 @@ describe ActiveGit::Configuration do
13
13
  ActiveGit.configuration.bare_path = @bare_path
14
14
  ActiveGit.configuration.logger = @logger
15
15
  end
16
-
16
+
17
17
  it 'default sync_batch_size' do
18
18
  ActiveGit.configuration.sync_batch_size.should eq 10000
19
19
  end
@@ -59,5 +59,5 @@ describe ActiveGit::Configuration do
59
59
  ActiveGit.configuration.logger = logger
60
60
  ActiveGit.configuration.logger.should eq logger
61
61
  end
62
-
62
+
63
63
  end
@@ -0,0 +1,6 @@
1
+ {
2
+ "created_at": "2012-04-20T11:24:11-03:00",
3
+ "id": null,
4
+ "name": "Brand 1",
5
+ "updated_at": "2012-04-20T11:24:11-03:00"
6
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "created_at": null,
3
+ "id": null,
4
+ "name": "Spanish",
5
+ "updated_at": null,
6
+ "countries": [
7
+ {
8
+ "created_at": null,
9
+ "id": null,
10
+ "language_id": null,
11
+ "name": "Argentina",
12
+ "updated_at": null,
13
+ "cities": [
14
+ {
15
+ "country_id": null,
16
+ "created_at": null,
17
+ "id": null,
18
+ "name": "Bs.As.",
19
+ "updated_at": null
20
+ }
21
+ ]
22
+ }
23
+ ]
24
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "created_at": null,
3
+ "id": null,
4
+ "language_id": null,
5
+ "name": "Argentina",
6
+ "updated_at": null,
7
+ "language": {
8
+ "created_at": null,
9
+ "id": null,
10
+ "name": "Spanish",
11
+ "updated_at": null
12
+ },
13
+ "cities": [
14
+ {
15
+ "country_id": null,
16
+ "created_at": null,
17
+ "id": null,
18
+ "name": "Bs.As.",
19
+ "updated_at": null
20
+ }
21
+ ]
22
+ }
@@ -2,6 +2,7 @@ class CreateCountries < ActiveRecord::Migration
2
2
  def change
3
3
  create_table :countries do |t|
4
4
  t.string :name, null: false
5
+ t.references :language
5
6
 
6
7
  t.timestamps
7
8
  end
@@ -0,0 +1,10 @@
1
+ class CreateCities < ActiveRecord::Migration
2
+ def change
3
+ create_table :cities do |t|
4
+ t.string :name, null: false
5
+ t.references :country
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveGit::ModelParser do
4
+
5
+ LANGUAGE = {
6
+ id: 1,
7
+ name: 'Spanish',
8
+ created_at: Time.now,
9
+ updated_at: Time.now,
10
+ countries: [
11
+ {
12
+ id: 1,
13
+ name: 'Argentina',
14
+ LANGUAGE_id: 1,
15
+ cities: [
16
+ {id: 1, name: 'Buenos Aires', country_id: 1},
17
+ {id: 2, name: 'Rosario', country_id: 1}
18
+ ]
19
+ }
20
+ ]
21
+ }
22
+
23
+ [LANGUAGE, LANGUAGE.to_json].each do |source|
24
+ it "Load from #{source.class.to_s.downcase}" do
25
+ instance = ActiveGit::ModelParser.from_json(Language, source)
26
+
27
+ instance.id.should eq LANGUAGE[:id]
28
+ instance.name.should eq LANGUAGE[:name]
29
+ instance.created_at.to_i.should eq LANGUAGE[:created_at].to_i
30
+ instance.updated_at.to_i.should eq LANGUAGE[:updated_at].to_i
31
+ end
32
+
33
+ it "Instances from #{source.class.to_s.downcase}" do
34
+ instances = ActiveGit::ModelParser.instances(Language, source)
35
+
36
+ instances.count.should eq 4
37
+ instances[0].class.should eq Language
38
+ instances[0].name.should eq 'Spanish'
39
+ instances[1].class.should eq Country
40
+ instances[1].name.should eq 'Argentina'
41
+ instances[2].class.should eq City
42
+ instances[2].name.should eq 'Buenos Aires'
43
+ instances[3].class.should eq City
44
+ instances[3].name.should eq 'Rosario'
45
+ end
46
+ end
47
+
48
+ it "instances from a hash with different associations" do
49
+ country = {
50
+ id: 1,
51
+ name: 'Argentina',
52
+ language: {id: 1, name: 'Spanish'},
53
+ cities: [
54
+ {id: 1, name: 'Buenos Aires', country_id: 1},
55
+ {id: 2, name: 'Rosario', country_id: 1}
56
+ ]
57
+ }
58
+
59
+ instances = ActiveGit::ModelParser.instances(Country, country)
60
+ instances.count.should eq 4
61
+ instances[0].class.should eq Country
62
+ instances[0].name.should eq 'Argentina'
63
+ instances[1].class.should eq Language
64
+ instances[1].name.should eq 'Spanish'
65
+ instances[2].class.should eq City
66
+ instances[2].name.should eq 'Buenos Aires'
67
+ instances[3].class.should eq City
68
+ instances[3].name.should eq 'Rosario'
69
+ end
70
+
71
+ end
@@ -0,0 +1,3 @@
1
+ class City < ActiveRecord::Base
2
+ belongs_to :country
3
+ end
@@ -1,2 +1,5 @@
1
1
  class Country < ActiveRecord::Base
2
+ git_versioned include: [:language, :cities]
3
+ belongs_to :language
4
+ has_many :cities
2
5
  end
@@ -1,3 +1,4 @@
1
1
  class Language < ActiveRecord::Base
2
- git_versioned
2
+ git_versioned(include: {countries: {include: :cities}})
3
+ has_many :countries
3
4
  end
@@ -62,7 +62,7 @@ describe ActiveGit::Synchronizer do
62
62
  working_path = @file_helper.create_temp_folder
63
63
 
64
64
  file_name = "#{working_path}/countries/1.json"
65
- @file_helper.write_file file_name, {id: 1, name: 'Argentina', created_at: '2012-04-20T11:24:11-03:00', updated_at: '2012-04-20T11:24:11-03:00'}.to_json
65
+ @file_helper.write_file file_name, {id: 1, name: 'Argentina', created_at: Time.now, updated_at: Time.now}.to_json
66
66
 
67
67
  Country.count.should eq 0
68
68
 
@@ -71,6 +71,51 @@ describe ActiveGit::Synchronizer do
71
71
  Country.find(1).name.should eq 'Argentina'
72
72
  end
73
73
 
74
+ it 'Create multiple models from a file with 3 nested levels' do
75
+ working_path = @file_helper.create_temp_folder
76
+
77
+ city1_json = {id: 1, name: "Buenos Aires", country_id: 1, created_at: Time.now, updated_at: Time.now}
78
+ city2_json = {id: 2, name: "Rosario", country_id: 1, created_at: Time.now, updated_at: Time.now}
79
+ country1_json = {id: 1, name: 'Argentina', language_id: 1, created_at: Time.now, updated_at: Time.now, cities:[city1_json,city2_json]}
80
+
81
+ city1_json = {id: 3, name: "Montevideo", country_id: 2, created_at: Time.now, updated_at: Time.now}
82
+ city2_json = {id: 4, name: "Colonia", country_id: 2, created_at: Time.now, updated_at: Time.now}
83
+ country2_json = {id: 2, name: 'Uruguay', language_id: 1, created_at: Time.now, updated_at: Time.now, cities:[city1_json,city2_json]}
84
+
85
+ file_name = "#{working_path}/languages/1.json"
86
+ @file_helper.write_file file_name, {id: 1, name: 'Spanish', created_at: Time.now, updated_at: Time.now, countries:[country1_json,country2_json] }.to_json
87
+
88
+ Language.count.should eq 0
89
+ Country.count.should eq 0
90
+ City.count.should eq 0
91
+
92
+ ActiveGit::Synchronizer.synchronize ActiveGit::DbCreate.new(file_name, working_path)
93
+
94
+ Language.count.should eq 1
95
+ Country.count.should eq 2
96
+ City.count.should eq 4
97
+
98
+ spanish = Language.find_by_name 'Spanish'
99
+
100
+ spanish.countries.count.should eq 2
101
+ spanish.countries.should include(Country.find_by_name 'Argentina')
102
+ spanish.countries.should include(Country.find_by_name 'Uruguay')
103
+
104
+ argentina = Country.find_by_name 'Argentina'
105
+
106
+ argentina.cities.count.should eq 2
107
+ argentina.cities.should include(City.find_by_name 'Buenos Aires')
108
+ argentina.cities.should include(City.find_by_name 'Rosario')
109
+ argentina.cities.should_not include(City.find_by_name 'Montevideo')
110
+
111
+ uruguay = Country.find_by_name 'Uruguay'
112
+
113
+ uruguay.cities.count.should eq 2
114
+ uruguay.cities.should include(City.find_by_name 'Montevideo')
115
+ uruguay.cities.should include(City.find_by_name 'Colonia')
116
+ uruguay.cities.should_not include(City.find_by_name 'Buenos Aires')
117
+ end
118
+
74
119
  it 'Update' do
75
120
  working_path = @file_helper.create_temp_folder
76
121
 
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.7
4
+ version: 0.0.8
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-09 00:00:00.000000000 Z
12
+ date: 2013-08-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -200,6 +200,7 @@ files:
200
200
  - lib/active_git/events/file_save.rb
201
201
  - lib/active_git/events/folder_remove.rb
202
202
  - lib/active_git/inflector.rb
203
+ - lib/active_git/model_parser.rb
203
204
  - lib/active_git/synchronization_error.rb
204
205
  - lib/active_git/synchronizer.rb
205
206
  - lib/active_git/version.rb
@@ -209,13 +210,19 @@ files:
209
210
  - spec/configuration_spec.rb
210
211
  - spec/coverage_helper.rb
211
212
  - spec/inflector_spec.rb
213
+ - spec/json/dump.json
214
+ - spec/json/nested_dump.json
215
+ - spec/json/parent_child_dump.json
212
216
  - spec/migrations/20121004135939_create_countries.rb
213
217
  - spec/migrations/20121004135940_create_languages.rb
214
218
  - spec/migrations/20121030163114_create_brands.rb
215
219
  - spec/migrations/20130315192821_create_customers.rb
220
+ - spec/migrations/20130812112000_create_cities.rb
221
+ - spec/model_parser_spec.rb
216
222
  - spec/spec_helper.rb
217
223
  - spec/support/helpers/file_helper.rb
218
224
  - spec/support/models/brand.rb
225
+ - spec/support/models/city.rb
219
226
  - spec/support/models/country.rb
220
227
  - spec/support/models/customer.rb
221
228
  - spec/support/models/language.rb
@@ -251,13 +258,19 @@ test_files:
251
258
  - spec/configuration_spec.rb
252
259
  - spec/coverage_helper.rb
253
260
  - spec/inflector_spec.rb
261
+ - spec/json/dump.json
262
+ - spec/json/nested_dump.json
263
+ - spec/json/parent_child_dump.json
254
264
  - spec/migrations/20121004135939_create_countries.rb
255
265
  - spec/migrations/20121004135940_create_languages.rb
256
266
  - spec/migrations/20121030163114_create_brands.rb
257
267
  - spec/migrations/20130315192821_create_customers.rb
268
+ - spec/migrations/20130812112000_create_cities.rb
269
+ - spec/model_parser_spec.rb
258
270
  - spec/spec_helper.rb
259
271
  - spec/support/helpers/file_helper.rb
260
272
  - spec/support/models/brand.rb
273
+ - spec/support/models/city.rb
261
274
  - spec/support/models/country.rb
262
275
  - spec/support/models/customer.rb
263
276
  - spec/support/models/language.rb