DUI 0.9.0

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/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
data/.rvmrc ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
7
+ environment_id="ruby-1.8.7-p352@DUI"
8
+
9
+ #
10
+ # Uncomment following line if you want options to be set only for given project.
11
+ #
12
+ # PROJECT_JRUBY_OPTS=( --1.9 )
13
+
14
+ #
15
+ # First we attempt to load the desired environment directly from the environment
16
+ # file. This is very fast and efficient compared to running through the entire
17
+ # CLI and selector. If you want feedback on which environment was used then
18
+ # insert the word 'use' after --create as this triggers verbose mode.
19
+ #
20
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
21
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
22
+ then
23
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
24
+
25
+ if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
26
+ then
27
+ . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
28
+ fi
29
+ else
30
+ # If the environment file has not yet been created, use the RVM CLI to select.
31
+ if ! rvm --create "$environment_id"
32
+ then
33
+ echo "Failed to create RVM environment '${environment_id}'."
34
+ return 1
35
+ fi
36
+ fi
37
+
38
+ #
39
+ # If you use an RVM gemset file to install a list of gems (*.gems), you can have
40
+ # it be automatically loaded. Uncomment the following and adjust the filename if
41
+ # necessary.
42
+ #
43
+ # filename=".gems"
44
+ # if [[ -s "$filename" ]]
45
+ # then
46
+ # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
47
+ # fi
48
+
49
+ # If you use bundler, this might be useful to you:
50
+ # if command -v bundle && [[ -s Gemfile ]]
51
+ # then
52
+ # bundle install
53
+ # fi
54
+
55
+
data/DUI.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "DUI/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "DUI"
7
+ s.version = DUI::VERSION
8
+ s.authors = ["Darren Cauthon"]
9
+ s.email = ["darren@cauthon.com"]
10
+ s.homepage = "http://www.github.com/darrencauthon/DUI"
11
+ s.summary = %q{Easier syncing with Delete - Update - Insert}
12
+ s.description = %q{This gem provides a small API for comparing two datasets,
13
+ for determining what records should be deleted, updated, or inserted.}
14
+
15
+ s.rubyforge_project = "DUI"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ # specify any dependencies here; for example:
23
+ s.add_development_dependency "minitest"
24
+ s.add_runtime_dependency "hashie"
25
+ end
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in DUI.gemspec
4
+ gemspec
5
+
6
+ gem 'minitest'
7
+ gem 'hashie'
8
+
9
+ group :development do
10
+ gem 'guard'
11
+ gem 'guard-minitest', :git => 'git://github.com/aspiers/guard-minitest.git'
12
+ gem 'ruby_gntp'
13
+ end
data/Guardfile ADDED
@@ -0,0 +1,14 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+ guard 'minitest' do
4
+ watch(%r|^test/test_(.*)\.rb|)
5
+ watch(%r|^lib/(.*)([^/]+)\.rb|) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
6
+ watch(%r|^test/test_helper\.rb|) { "test" }
7
+ watch(%r|^lib/(.*)\.rb|) { |m| "test/test_#{m[1]}.rb" }
8
+
9
+ watch(%r{^spec/.+_spec\.rb$})
10
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
11
+ watch(%r{^lib/DUI/(.+)\.rb$}) { |m| "spec/DUI/#{m[1]}_spec.rb" }
12
+ watch(%r{^spec/models/.+\.rb$}) { ["spec/models", "spec/acceptance"] }
13
+ watch('spec/spec_helper.rb') { "spec" }
14
+ end
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,49 @@
1
+ module DUI
2
+
3
+ class Matcher
4
+
5
+ def initialize(&compare_method)
6
+ @compare_method = compare_method || Proc.new {|c, n| c.id == n.id }
7
+ end
8
+
9
+ def get_results(current_data, new_data)
10
+ results = get_the_results_of_the_delete_and_update_process(current_data, new_data)
11
+ results.records_to_insert = get_records_to_insert(results, new_data)
12
+ results
13
+ end
14
+
15
+ private
16
+
17
+ def get_the_results_of_the_delete_and_update_process(current_data, new_data)
18
+ results = an_object_with(:records_to_delete => [], :records_to_update => [])
19
+ all_current_data_with_possible_matches_in_new_data(current_data, new_data).each do |match|
20
+ if match.current_not_found_in_new
21
+ results.records_to_delete << match.current
22
+ else
23
+ results.records_to_update << match
24
+ end
25
+ end
26
+ results
27
+ end
28
+
29
+ def all_current_data_with_possible_matches_in_new_data(current_data, new_data)
30
+ current_data.map do |c|
31
+ an_object_with({:current => c}) do |result|
32
+ result.new = new_data.select {|n| @compare_method.call(c, n) }.first
33
+ result.current_not_found_in_new = result.new.nil?
34
+ end
35
+ end
36
+ end
37
+
38
+ def get_records_to_insert(results, new_data)
39
+ current_records = results.records_to_update.map{|u| u.current}
40
+ new_data.select {|n| current_records.select {|c| @compare_method.call(c, n) }.count == 0 }
41
+ end
42
+
43
+ def an_object_with(hash)
44
+ the_object = Hashie::Mash.new(hash)
45
+ yield the_object if block_given?
46
+ the_object
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module DUI
2
+ VERSION = "0.9.0"
3
+ end
data/lib/DUI.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'hashie'
2
+ require "DUI/version"
3
+ require "DUI/matcher"
4
+
5
+ module DUI
6
+ end
@@ -0,0 +1,256 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Matcher" do
4
+ before do
5
+ @matcher = DUI::Matcher.new
6
+ end
7
+
8
+ describe "when there is no existing data" do
9
+ before do
10
+ @current_data = []
11
+ end
12
+
13
+ describe "and it is given no data" do
14
+ before do
15
+ @new_data = []
16
+ @results = @matcher.get_results @current_data, @new_data
17
+ end
18
+
19
+ it "should have no records to delete" do
20
+ assert_equal 0, @results.records_to_delete.count
21
+ end
22
+
23
+ it "should have no records to update" do
24
+ assert_equal 0, @results.records_to_update.count
25
+ end
26
+
27
+ it "should have no records to insert" do
28
+ assert_equal 0, @results.records_to_insert.count
29
+ end
30
+ end
31
+
32
+ describe "and it is given one new record" do
33
+ before do
34
+ @new_data = [new_record_with_id(1)]
35
+ @results = @matcher.get_results @current_data, @new_data
36
+ end
37
+
38
+ it "should have no records to delete" do
39
+ assert_equal 0, @results.records_to_delete.count
40
+ end
41
+
42
+ it "should have no records to update" do
43
+ assert_equal 0, @results.records_to_update.count
44
+ end
45
+
46
+ it "should have one records to insert" do
47
+ assert_equal 1, @results.records_to_insert.count
48
+ end
49
+
50
+ it "should return the new record as a record to insert" do
51
+ @new_data.each do |x|
52
+ assert_equal true, @results.records_to_insert.include?(x)
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ describe "when there is one existing record" do
59
+ before do
60
+ @current_data = [new_record_with_id(3)]
61
+ end
62
+
63
+ describe "and it is given no new data" do
64
+ before do
65
+ @new_data = []
66
+ @results = @matcher.get_results @current_data, @new_data
67
+ end
68
+
69
+ it "should have one records to delete" do
70
+ assert_equal 1, @results.records_to_delete.count
71
+ end
72
+
73
+ it "should return the current record as a record to delete" do
74
+ @current_data.each do |x|
75
+ assert_equal true, @results.records_to_delete.include?(x)
76
+ end
77
+ end
78
+
79
+ it "should have no records to update" do
80
+ assert_equal 0, @results.records_to_update.count
81
+ end
82
+
83
+ it "should have no records to insert" do
84
+ assert_equal 0, @results.records_to_insert.count
85
+ end
86
+ end
87
+
88
+ describe "and it is given the same record" do
89
+ before do
90
+ @new_data = [new_record_with_id(3)]
91
+ @results = @matcher.get_results @current_data, @new_data
92
+ end
93
+
94
+ it "should have no records to delete" do
95
+ assert_equal 0, @results.records_to_delete.count
96
+ end
97
+
98
+ it "should have one records to update" do
99
+ assert_equal 1, @results.records_to_update.count
100
+ end
101
+
102
+ it "should return the existing record as a record to update" do
103
+ assert_equal 1, @results.records_to_update.select{|x| x.current.id == 3}.count
104
+ assert_equal 1, @results.records_to_update.select{|x| x.new.id == 3}.count
105
+ end
106
+
107
+ it "should have no records to insert" do
108
+ assert_equal 0, @results.records_to_insert.count
109
+ end
110
+ end
111
+
112
+ describe "and it is given a different record" do
113
+ before do
114
+ @new_data = [new_record_with_id(5)]
115
+ @results = @matcher.get_results @current_data, @new_data
116
+ end
117
+
118
+ it "should have no records to delete" do
119
+ assert_equal 1, @results.records_to_delete.count
120
+ end
121
+
122
+ it "should return the existing record as a record to delete" do
123
+ assert_equal 1, @results.records_to_delete.select{|x| x.id == 3}.count
124
+ end
125
+
126
+ it "should have no records to update" do
127
+ assert_equal 0, @results.records_to_update.count
128
+ end
129
+
130
+ it "should have one record to insert" do
131
+ assert_equal 1, @results.records_to_insert.count
132
+ end
133
+
134
+ it "should return the new record as a record to insert" do
135
+ assert_equal 1, @results.records_to_insert.select{|x| x.id == 5}.count
136
+ end
137
+ end
138
+
139
+ describe "and it is given the existing record and the same record" do
140
+ before do
141
+ @new_data = [new_record_with_id(3), new_record_with_id(5)]
142
+ @results = @matcher.get_results @current_data, @new_data
143
+ end
144
+
145
+ it "should have no records to delete" do
146
+ assert_equal 0, @results.records_to_delete.count
147
+ end
148
+
149
+ it "should have one records to update" do
150
+ assert_equal 1, @results.records_to_update.count
151
+ end
152
+
153
+ it "should return the existing record as a record to update" do
154
+ assert_equal 1, @results.records_to_update.select{|x| x.current.id == 3}.count
155
+ assert_equal 1, @results.records_to_update.select{|x| x.new.id == 3}.count
156
+ end
157
+
158
+ it "should have one records to insert" do
159
+ assert_equal 1, @results.records_to_insert.count
160
+ end
161
+
162
+ it "should return the new records as a record to insert" do
163
+ assert_equal 1, @results.records_to_insert.select{|x| x.id == 5}.count
164
+ end
165
+ end
166
+
167
+ describe "when there are two existing records" do
168
+ before do
169
+ @current_data = [new_record_with_id(7), new_record_with_id(8)]
170
+ end
171
+
172
+ describe "and no new data is passed" do
173
+ before do
174
+ @new_data = []
175
+ @results = @matcher.get_results @current_data, @new_data
176
+ end
177
+
178
+ it "should return 2 records to delete" do
179
+ assert_equal 2, @results.records_to_delete.count
180
+ end
181
+
182
+ it "should return 0 records to update" do
183
+ assert_equal 0, @results.records_to_update.count
184
+ end
185
+
186
+ it "should return 0 records to insert" do
187
+ assert_equal 0, @results.records_to_insert.count
188
+ end
189
+ end
190
+
191
+ describe "and both existing records are passed" do
192
+ before do
193
+ @new_data = [new_record_with_id(8), new_record_with_id(7)]
194
+ @results = @matcher.get_results @current_data, @new_data
195
+ end
196
+
197
+ it "should return 0 records to delete" do
198
+ assert_equal 0, @results.records_to_delete.count
199
+ end
200
+
201
+ it "should return 2 records to update" do
202
+ assert_equal 2, @results.records_to_update.count
203
+ end
204
+
205
+ it "should return both records as ready for update" do
206
+ assert_equal 1, @results.records_to_update.select{|x|x.current.id == 8}.count
207
+ assert_equal 1, @results.records_to_update.select{|x|x.current.id == 7}.count
208
+ assert_equal 1, @results.records_to_update.select{|x|x.new.id == 8}.count
209
+ assert_equal 1, @results.records_to_update.select{|x|x.new.id == 7}.count
210
+ end
211
+
212
+ it "should return no records for insertion" do
213
+ assert_equal 0, @results.records_to_insert.count
214
+ end
215
+ end
216
+ end
217
+ end
218
+ end
219
+
220
+ describe "Matcher, but with email instead of id" do
221
+ before do
222
+ @matcher = DUI::Matcher.new {|c, n| c.email == n.email}
223
+ end
224
+
225
+ describe "when there are two existing records" do
226
+ before do
227
+ @current_data = [new_record_with_id_and_email(7, "one@test.com"), new_record_with_id_and_email(8, "two@test.com")]
228
+ end
229
+
230
+ describe "and both existing records are passed" do
231
+ before do
232
+ @new_data = [new_record_with_id_and_email(88, "two@test.com"), new_record_with_id_and_email(77, "one@test.com")]
233
+ @results = @matcher.get_results @current_data, @new_data
234
+ end
235
+
236
+ it "should return 0 records to delete" do
237
+ assert_equal 0, @results.records_to_delete.count
238
+ end
239
+
240
+ it "should return 2 records to update" do
241
+ assert_equal 2, @results.records_to_update.count
242
+ end
243
+
244
+ it "should return both records as ready for update" do
245
+ assert_equal 1, @results.records_to_update.select{|x|x.current.email == "one@test.com"}.count
246
+ assert_equal 1, @results.records_to_update.select{|x|x.current.email == "two@test.com"}.count
247
+ assert_equal 1, @results.records_to_update.select{|x|x.new.email == "one@test.com"}.count
248
+ assert_equal 1, @results.records_to_update.select{|x|x.new.email == "two@test.com"}.count
249
+ end
250
+
251
+ it "should return no records for insertion" do
252
+ assert_equal 0, @results.records_to_insert.count
253
+ end
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,11 @@
1
+ require 'minitest/autorun'
2
+ require './lib/DUI.rb'
3
+ require 'hashie'
4
+
5
+ def new_record_with_id(id)
6
+ Hashie::Mash.new :id => id
7
+ end
8
+
9
+ def new_record_with_id_and_email(id, email)
10
+ Hashie::Mash.new :id => id, :email => email
11
+ end
@@ -0,0 +1,2 @@
1
+ require 'minitest/autorun'
2
+ require './lib/DUI.rb'
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: DUI
3
+ version: !ruby/object:Gem::Version
4
+ hash: 59
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 9
9
+ - 0
10
+ version: 0.9.0
11
+ platform: ruby
12
+ authors:
13
+ - Darren Cauthon
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-03-01 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: minitest
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: hashie
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ description: |-
49
+ This gem provides a small API for comparing two datasets,
50
+ for determining what records should be deleted, updated, or inserted.
51
+ email:
52
+ - darren@cauthon.com
53
+ executables: []
54
+
55
+ extensions: []
56
+
57
+ extra_rdoc_files: []
58
+
59
+ files:
60
+ - .gitignore
61
+ - .rvmrc
62
+ - DUI.gemspec
63
+ - Gemfile
64
+ - Guardfile
65
+ - Rakefile
66
+ - lib/DUI.rb
67
+ - lib/DUI/matcher.rb
68
+ - lib/DUI/version.rb
69
+ - spec/DUI/matcher_spec.rb
70
+ - spec/spec_helper.rb
71
+ - test/test_helper.rb
72
+ homepage: http://www.github.com/darrencauthon/DUI
73
+ licenses: []
74
+
75
+ post_install_message:
76
+ rdoc_options: []
77
+
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ hash: 3
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ requirements: []
99
+
100
+ rubyforge_project: DUI
101
+ rubygems_version: 1.8.10
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: Easier syncing with Delete - Update - Insert
105
+ test_files:
106
+ - spec/DUI/matcher_spec.rb
107
+ - spec/spec_helper.rb
108
+ - test/test_helper.rb