harmonize 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +22 -6
- data/README.md +10 -10
- data/Rakefile +10 -16
- data/lib/harmonize.rb +3 -1
- data/lib/harmonize/base.rb +10 -4
- data/lib/harmonize/engine.rb +6 -0
- data/lib/harmonize/gemdata.rb +1 -1
- data/lib/harmonize/models.rb +34 -0
- data/lib/harmonize/models/active_record/log.rb +21 -0
- data/lib/harmonize/models/active_record/modification.rb +22 -0
- data/lib/harmonize/models/mongoid/log.rb +29 -0
- data/lib/harmonize/models/mongoid/modification.rb +27 -0
- data/lib/harmonize/strategies/basic_crud_strategy.rb +92 -58
- metadata +43 -47
- data/app/models/harmonize/log.rb +0 -16
- data/app/models/harmonize/modification.rb +0 -18
data/Gemfile
CHANGED
@@ -1,13 +1,29 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
|
-
|
3
|
-
gem 'rails', '3.0.9'
|
4
|
-
gem 'hashie'
|
2
|
+
gemspec
|
5
3
|
|
6
4
|
group :development, :test, :console do
|
7
|
-
gem '
|
5
|
+
#gem 'rails', '3.0.10'
|
6
|
+
#gem 'rails', '3.1.1'
|
7
|
+
#gem 'activerecord', '3.1.1', :require => 'active_record'
|
8
|
+
#gem 'activerecord', '3.0.10', :require => 'active_record'
|
9
|
+
#gem 'sqlite3'
|
10
|
+
gem 'mongoid'
|
11
|
+
gem 'bson_ext'
|
8
12
|
gem 'rspec-rails', '~> 2'
|
9
|
-
gem 'ruby-debug19', :require => 'ruby-debug'
|
10
13
|
gem 'capybara', '~> 1'
|
11
14
|
gem 'database_cleaner'
|
12
|
-
gem '
|
15
|
+
gem 'factory_girl'
|
16
|
+
gem 'rake'
|
17
|
+
end
|
18
|
+
|
19
|
+
platform :mri_18 do
|
20
|
+
group :development do
|
21
|
+
gem 'ruby-debug'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
platform :mri_19 do
|
26
|
+
group :development do
|
27
|
+
gem 'ruby-debug19', :require => 'ruby-debug' unless RUBY_VERSION == '1.9.3'
|
28
|
+
end
|
13
29
|
end
|
data/README.md
CHANGED
@@ -32,7 +32,7 @@ Lets pretend we work for a company that has a large list of stores. This list of
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
With our Store model wired up as above, we will get a new class method on our model called "harmonize\_default!". When we call harmonize\_default! harmonize will use the default strategy to harmonize the source records with the target records. In order to understand what actions are taken to bring the targets into harmony, we need to understand Harmonize::Strategies
|
35
|
+
With our Store model wired up as above, we will get a new class method on our model called "harmonize\_default!". When we call harmonize\_default! harmonize will use the default strategy to harmonize the source records with the target records. In order to understand what actions are taken to bring the targets into harmony, we need to understand Harmonize::Strategies -- but we're getting ahead of ourselves. First, let's look at how to configure harmonize.
|
36
36
|
|
37
37
|
## Harmonize::Configuration
|
38
38
|
|
@@ -49,9 +49,9 @@ Each call to harmonize creates a Harmonize::Configuration instance that defines
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
###
|
52
|
+
### Harmonize::Configuration.harmonizer\_name
|
53
53
|
|
54
|
-
harmonize uses the configured
|
54
|
+
harmonize uses the configured harmonizer\_name as the name of the harmonizer being configured. Each harmonizer\_name may only be used once. This allows the harmonize method to be called more than once per model. This option is used to name special methods used by harmonize. The harmonization method is named with the following convention: "harmonize\_#{harmonizer\_name}!".
|
55
55
|
|
56
56
|
The default setting is:
|
57
57
|
|
@@ -59,7 +59,7 @@ The default setting is:
|
|
59
59
|
|
60
60
|
This setting can be any symbol.
|
61
61
|
|
62
|
-
###
|
62
|
+
### Harmonize::Configuration.key
|
63
63
|
|
64
64
|
harmonize uses the configured key to determine what attribute in the source data feed to use to find existing target records.
|
65
65
|
|
@@ -69,7 +69,7 @@ The default setting is:
|
|
69
69
|
|
70
70
|
This setting can be any attribute that will be found in source records.
|
71
71
|
|
72
|
-
###
|
72
|
+
### Harmonize::Configuration.source
|
73
73
|
|
74
74
|
harmonize uses the configured source to gather the latest set of source records. This can be set to a lambda or any other callable object. The only requirement is that it returns a collection of hash like objects. By default this setting calls a method name with the following convention: "harmonize\_source\_#{harmonizer\_name}".
|
75
75
|
|
@@ -79,7 +79,7 @@ The default setting is:
|
|
79
79
|
|
80
80
|
This setting can be any class method defined in the model that returns properly structured data.
|
81
81
|
|
82
|
-
###
|
82
|
+
### Harmonize::Configuration.target
|
83
83
|
|
84
84
|
harmonize uses the configured target to gather the latest set of target records. This can be set to a lambda or any other callable object. The only requirement is that it returns an ActiveRecord::Relation. Hint, all (named) scopes return ActiveRecord::Relation instances.
|
85
85
|
|
@@ -89,7 +89,7 @@ The default setting is:
|
|
89
89
|
|
90
90
|
This setting can be any class method defined in the model that returns an ActiveRecord::Relation.
|
91
91
|
|
92
|
-
###
|
92
|
+
### Harmonize::Configuration.strategy
|
93
93
|
|
94
94
|
harmonize uses the configured strategy to determine which Harmonize::Strategies::Strategy subclass to use when harmonizing. harmonize uses this setting as well as the strategy\_arguments setting to create an instance of the Strategy subclass.
|
95
95
|
|
@@ -99,7 +99,7 @@ The default setting is:
|
|
99
99
|
|
100
100
|
This setting can be any class that returns complies with the Strategy api.
|
101
101
|
|
102
|
-
###
|
102
|
+
### Harmonize::Configuration.target
|
103
103
|
|
104
104
|
harmonize uses the configured strategy\_arguments to determine which arguments to use when initializing the set Harmonize::Strategies::Strategy subclass.
|
105
105
|
|
@@ -158,11 +158,11 @@ Use, report bugs, fix them, and send pull requests!
|
|
158
158
|
|
159
159
|
## TODO
|
160
160
|
|
161
|
-
* Maybe move key from Configuration to a strategy\_argument as it is not a configuration option really, but a way to change
|
161
|
+
* Maybe move key from Configuration to a strategy\_argument as it is not a configuration option really, but a way to change strategy behaviour.
|
162
162
|
|
163
163
|
## Contributors
|
164
164
|
|
165
|
-
* Bram Swenson <bram@
|
165
|
+
* Bram Swenson <bram@craniumisajar.com>
|
166
166
|
|
167
167
|
## Notes
|
168
168
|
|
data/Rakefile
CHANGED
@@ -7,25 +7,19 @@ rescue LoadError
|
|
7
7
|
end
|
8
8
|
|
9
9
|
require 'rake'
|
10
|
+
if defined?(Rails)
|
11
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
12
|
+
load 'rails/tasks/engine.rake'
|
13
|
+
end
|
14
|
+
|
10
15
|
require 'rspec/core'
|
11
16
|
require 'rspec/core/rake_task'
|
12
17
|
require 'bundler/gem_tasks'
|
13
18
|
|
14
|
-
|
15
|
-
RSpec::Core::RakeTask.new(:spec)
|
16
|
-
desc 'Setup the test database'
|
17
|
-
task :dbsetup do
|
18
|
-
results = %x(
|
19
|
-
cd spec/dummy &&
|
20
|
-
rm db/*.sqlite3 &&
|
21
|
-
RAILS_ENV=test rake db:migrate
|
22
|
-
)
|
23
|
-
puts "dbsetup: #{results}" unless results == ''
|
24
|
-
end
|
19
|
+
RSpec::Core::RakeTask.new(:spec)
|
25
20
|
|
26
|
-
|
27
|
-
task :
|
21
|
+
if defined?(ActiveRecord)
|
22
|
+
task :default => [ 'app:db:create', 'app:db:migrate', 'spec' ]
|
23
|
+
else
|
24
|
+
task :default => [ 'spec' ]
|
28
25
|
end
|
29
|
-
|
30
|
-
task :default => 'test:run'
|
31
|
-
|
data/lib/harmonize.rb
CHANGED
@@ -2,8 +2,10 @@ require 'hashie/dash'
|
|
2
2
|
require 'harmonize/errors'
|
3
3
|
module Harmonize
|
4
4
|
require 'harmonize/engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
|
5
|
+
require 'harmonize/models'
|
5
6
|
autoload :Base, 'harmonize/base'
|
6
7
|
autoload :Strategies, 'harmonize/strategies'
|
7
8
|
autoload :Configuration, 'harmonize/configuration'
|
8
9
|
end
|
9
|
-
ActiveRecord::Base.send :include, Harmonize::Base if defined?(ActiveRecord::Base)
|
10
|
+
::ActiveRecord::Base.send :include, ::Harmonize::Base if defined?(::ActiveRecord::Base)
|
11
|
+
::Mongoid::Document.send :include, ::Harmonize::Base if defined?(::Mongoid::Document)
|
data/lib/harmonize/base.rb
CHANGED
@@ -43,14 +43,14 @@ module Harmonize
|
|
43
43
|
|
44
44
|
def create_harmonize_log(harmonizer_name)
|
45
45
|
harmonizer = harmonizers[harmonizer_name]
|
46
|
-
Harmonize::Log.create!(
|
46
|
+
Harmonize::Log.create!({
|
47
47
|
:start => DateTime.now,
|
48
48
|
:class_name => self.class.name,
|
49
49
|
:harmonizer_name => harmonizer_name,
|
50
50
|
:key => harmonizer.key,
|
51
51
|
:strategy => harmonizer.strategy.inspect,
|
52
|
-
:strategy_arguments => harmonizer.strategy_arguments.inspect
|
53
|
-
)
|
52
|
+
:strategy_arguments => harmonizer.strategy_arguments.inspect
|
53
|
+
})
|
54
54
|
end
|
55
55
|
|
56
56
|
def harmonize_source_method(harmonizer_name, method_name = nil)
|
@@ -63,7 +63,13 @@ module Harmonize
|
|
63
63
|
method_name ||= :scoped
|
64
64
|
raise HarmonizerTargetUndefined.new(harmonizer_name.to_s) unless respond_to?(method_name)
|
65
65
|
target_scope = send(method_name)
|
66
|
-
|
66
|
+
if defined?(::ActiveRecord)
|
67
|
+
scope_base = ::ActiveRecord::Relation
|
68
|
+
end
|
69
|
+
if defined?(::Mongoid)
|
70
|
+
scope_base = ::Mongoid::Criteria
|
71
|
+
end
|
72
|
+
raise HarmonizerTargetInvalid.new(harmonizer_name.to_s) unless target_scope.is_a?(scope_base)
|
67
73
|
target_scope
|
68
74
|
end
|
69
75
|
|
data/lib/harmonize/engine.rb
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
module Harmonize
|
2
2
|
class Engine < ::Rails::Engine
|
3
|
+
load_path = File.expand_path("../..", __FILE__)
|
4
|
+
puts "LOAD PATH: #{load_path}"
|
5
|
+
config.autoload_paths << load_path
|
6
|
+
model_path = File.expand_path("../../models/active_record", __FILE__)
|
7
|
+
puts "MODEL PATH: #{model_path}"
|
8
|
+
paths["app/models"] << model_path
|
3
9
|
end
|
4
10
|
end
|
data/lib/harmonize/gemdata.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Harmonize
|
2
|
+
puts "MODELS LOADING"
|
3
|
+
module Models
|
4
|
+
begin
|
5
|
+
require 'mongoid'
|
6
|
+
Harmonize::Models::Orm = ::Mongoid
|
7
|
+
rescue LoadError
|
8
|
+
end
|
9
|
+
begin
|
10
|
+
require 'active_record'
|
11
|
+
Harmonize::Models::Orm = ::ActiveRecord
|
12
|
+
rescue LoadError
|
13
|
+
end unless defined?(Harmonize::Models::Orm)
|
14
|
+
module ActiveRecord
|
15
|
+
autoload :Log, 'harmonize/models/active_record/log'
|
16
|
+
autoload :Modification, 'harmonize/models/active_record/modification'
|
17
|
+
end
|
18
|
+
module Mongoid
|
19
|
+
autoload :Log, 'harmonize/models/mongoid/log'
|
20
|
+
autoload :Modification, 'harmonize/models/mongoid/modification'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
case Harmonize::Models::Orm.to_s
|
24
|
+
when 'ActiveRecord'
|
25
|
+
puts "LOADING ACTIVE RECORD MODELS"
|
26
|
+
Modification = Harmonize::Models::ActiveRecord::Modification unless defined?(Modification)
|
27
|
+
Log = Harmonize::Models::ActiveRecord::Log unless defined?(Log)
|
28
|
+
when 'Mongoid'
|
29
|
+
puts "LOADING MONGOID MODELS"
|
30
|
+
Modification = Harmonize::Models::Mongoid::Modification unless defined?(Modification)
|
31
|
+
Log = Harmonize::Models::Mongoid::Log unless defined?(Log)
|
32
|
+
end
|
33
|
+
puts "MODELS LOADED"
|
34
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Harmonize
|
2
|
+
module Models
|
3
|
+
module ActiveRecord
|
4
|
+
class Log < ::ActiveRecord::Base
|
5
|
+
set_table_name :harmonize_logs
|
6
|
+
|
7
|
+
validates :key, :class_name, :harmonizer_name, :strategy, :strategy_arguments, :presence => true
|
8
|
+
|
9
|
+
ModificationOptions = { :class_name => "Harmonize::Models::ActiveRecord::Modification",
|
10
|
+
:foreign_key => :harmonize_log_id }
|
11
|
+
|
12
|
+
has_many :modifications, ModificationOptions.merge(:inverse_of => :log, :dependent => :destroy)
|
13
|
+
has_many :created, ModificationOptions.merge(:conditions => { :modification_type => 'create' })
|
14
|
+
has_many :updated, ModificationOptions.merge(:conditions => { :modification_type => 'update' })
|
15
|
+
has_many :destroyed, ModificationOptions.merge(:conditions => { :modification_type => 'destroy'})
|
16
|
+
has_many :errored, ModificationOptions.merge(:conditions => { :modification_type => 'error' })
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Harmonize
|
2
|
+
module Models
|
3
|
+
module ActiveRecord
|
4
|
+
class Modification < ::ActiveRecord::Base
|
5
|
+
set_table_name :harmonize_modifications
|
6
|
+
|
7
|
+
validates :harmonize_log_id, :modification_type, :presence => true
|
8
|
+
validates :modification_type, :inclusion => %w( create update destroy error )
|
9
|
+
|
10
|
+
serialize :instance_errors
|
11
|
+
|
12
|
+
belongs_to :log, :class_name => "Harmonize::Models::ActiveRecord::Log",
|
13
|
+
:foreign_key => :harmonize_log_id, :inverse_of => :modifications
|
14
|
+
|
15
|
+
scope :created, lambda { where(:modification_type => 'create') }
|
16
|
+
scope :updated, lambda { where(:modification_type => 'update') }
|
17
|
+
scope :destroyed, lambda { where(:modification_type => 'destroy') }
|
18
|
+
scope :errored, lambda { where(:modification_type => 'error') }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Harmonize
|
2
|
+
module Models
|
3
|
+
module Mongoid
|
4
|
+
class Log
|
5
|
+
include ::Mongoid::Document
|
6
|
+
include ::Mongoid::Timestamps
|
7
|
+
store_in :harmonize_logs
|
8
|
+
|
9
|
+
field :key, :type => String
|
10
|
+
field :class_name, :type => String
|
11
|
+
field :harmonizer_name, :type => String
|
12
|
+
field :strategy, :type => String
|
13
|
+
field :strategy_arguments, :type => String
|
14
|
+
field :start, :type => DateTime
|
15
|
+
field :end, :type => DateTime
|
16
|
+
|
17
|
+
validates :key, :class_name, :harmonizer_name, :strategy, :strategy_arguments, :presence => true
|
18
|
+
|
19
|
+
ModificationOptions = { :class_name => "Harmonize::Models::Mongoid::Modification" }
|
20
|
+
|
21
|
+
has_many :modifications, ModificationOptions.merge(:inverse_of => :log, :dependent => :destroy)
|
22
|
+
def created; modifications.created; end
|
23
|
+
def updated; modifications.updated; end
|
24
|
+
def destroyed; modifications.destroyed; end
|
25
|
+
def errored; modifications.errored; end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Harmonize
|
2
|
+
module Models
|
3
|
+
module Mongoid
|
4
|
+
class Modification
|
5
|
+
include ::Mongoid::Document
|
6
|
+
include ::Mongoid::Timestamps
|
7
|
+
|
8
|
+
field :instance_id, :type => String
|
9
|
+
field :modification_type, :type => String
|
10
|
+
field :before_time, :type => DateTime
|
11
|
+
field :after_time, :type => DateTime
|
12
|
+
field :instance_errors, :type => String
|
13
|
+
|
14
|
+
validates :modification_type, :presence => true, :inclusion => %w( create update destroy error )
|
15
|
+
|
16
|
+
#serialize :instance_errors
|
17
|
+
|
18
|
+
belongs_to :log, :class_name => "Harmonize::Models::Mongoid::Log", :inverse_of => :modifications
|
19
|
+
|
20
|
+
scope :created, lambda { where(:modification_type => 'create') }
|
21
|
+
scope :updated, lambda { where(:modification_type => 'update') }
|
22
|
+
scope :destroyed, lambda { where(:modification_type => 'destroy') }
|
23
|
+
scope :errored, lambda { where(:modification_type => 'error') }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -2,84 +2,118 @@ module Harmonize
|
|
2
2
|
module Strategies
|
3
3
|
|
4
4
|
class BasicCrudStrategy < Strategy
|
5
|
-
|
6
5
|
def harmonize!
|
7
|
-
|
8
|
-
destroy_targets_not_found_in_source
|
6
|
+
create_and_update_targets
|
7
|
+
destroy_targets_not_found_in_source
|
9
8
|
end
|
10
9
|
|
11
10
|
private
|
12
|
-
|
13
11
|
def create_and_update_targets
|
14
|
-
sources.each
|
15
|
-
target_instance = find_target_instance(harmonizer.key, source[harmonizer.key])
|
16
|
-
modification = initialize_modification(target_instance)
|
17
|
-
modification = harmonize_target_instance!(target_instance, source, modification)
|
18
|
-
modification.save! if modification
|
19
|
-
keys << source[harmonizer.key]
|
20
|
-
end
|
12
|
+
sources.each { |source| modify_target(source) }
|
21
13
|
end
|
22
14
|
|
23
|
-
def
|
24
|
-
|
25
|
-
destroy_scope = touched_keys.empty? ? targets : targets.where("#{harmonizer.key} NOT IN (?)", touched_keys)
|
26
|
-
destroy_scope.find_each do |instance|
|
27
|
-
modification = harmonize_log.modifications.build(
|
28
|
-
:modification_type => 'destroy', :before_time => DateTime.now,
|
29
|
-
:instance_id => instance.id
|
30
|
-
)
|
31
|
-
instance.destroy
|
32
|
-
modification.update_attributes!(:after_time => DateTime.now)
|
33
|
-
end
|
15
|
+
def modify_target(source)
|
16
|
+
Modifier.modify(source, self)
|
34
17
|
end
|
35
18
|
|
36
|
-
def
|
37
|
-
|
38
|
-
instance = target_relation.first rescue nil
|
39
|
-
instance ||= target_relation.build
|
40
|
-
instance
|
19
|
+
def destroy_targets_not_found_in_source
|
20
|
+
destroy_scope.all.each { |target| destroy_target(target) }
|
41
21
|
end
|
42
22
|
|
43
|
-
def
|
44
|
-
|
45
|
-
harmonize_log.modifications.new(:modification_type => 'update', :before_time => DateTime.now)
|
46
|
-
else
|
47
|
-
harmonize_log.modifications.new(:modification_type => 'create', :before_time => DateTime.now)
|
48
|
-
end
|
23
|
+
def destroy_target(target)
|
24
|
+
Modifier.destroy(target, self)
|
49
25
|
end
|
50
26
|
|
51
|
-
|
52
|
-
|
53
|
-
return
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
27
|
+
# if we didn't get any touched_keys, destroy everything in targets scope
|
28
|
+
def destroy_scope
|
29
|
+
return targets if source_keys.empty?
|
30
|
+
case Harmonize::Models::Orm.to_s
|
31
|
+
when 'ActiveRecord'
|
32
|
+
targets.where("#{harmonizer.key} NOT IN (?)", source_keys)
|
33
|
+
when 'Mongoid'
|
34
|
+
targets.not_in(harmonizer.key => source_keys)
|
59
35
|
end
|
60
|
-
modification
|
61
36
|
end
|
62
37
|
|
63
|
-
def
|
64
|
-
|
65
|
-
begin
|
66
|
-
target_instance.attributes = source
|
67
|
-
rescue ActiveRecord::UnknownAttributeError => e
|
68
|
-
error_message = e.message
|
69
|
-
end
|
70
|
-
return target_instance, error_message
|
38
|
+
def source_keys
|
39
|
+
@source_keys ||= sources.map { |s| s[harmonizer.key] }
|
71
40
|
end
|
72
41
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
42
|
+
class Modifier
|
43
|
+
def self.modify(source, strategy)
|
44
|
+
new(source, nil, strategy).modify
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.destroy(target, strategy)
|
48
|
+
new(nil, target, strategy).destroy
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize(source, target, strategy)
|
52
|
+
@source = source
|
53
|
+
@target = target
|
54
|
+
@error = nil # any error that occured during modification
|
55
|
+
@type = nil # [ create, update, destroy ]
|
56
|
+
@targets = strategy.targets
|
57
|
+
@log = strategy.harmonize_log
|
58
|
+
@key = strategy.harmonizer.key
|
59
|
+
end
|
60
|
+
|
61
|
+
def modify
|
62
|
+
log do
|
63
|
+
find_or_initialize_target
|
64
|
+
update_target_attributes
|
65
|
+
save_target
|
78
66
|
end
|
79
|
-
rescue ActiveRecord::ActiveRecordError => e
|
80
|
-
error_message = e.message
|
81
67
|
end
|
82
|
-
|
68
|
+
|
69
|
+
def destroy
|
70
|
+
log do
|
71
|
+
@type = 'destroy'
|
72
|
+
@target.destroy
|
73
|
+
@modified = true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def find_or_initialize_target
|
78
|
+
target_relation = @targets.where( @key => @source[@key] )
|
79
|
+
@target = target_relation.first || target_relation.build
|
80
|
+
@type = @target.new_record? ? 'create' : 'update'
|
81
|
+
end
|
82
|
+
|
83
|
+
def update_target_attributes
|
84
|
+
@target.attributes = @source
|
85
|
+
@modified = @target.changed?
|
86
|
+
end
|
87
|
+
|
88
|
+
def save_target
|
89
|
+
unless @target.save
|
90
|
+
@error = @target.errors.full_messages
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def log
|
95
|
+
@before = DateTime.now
|
96
|
+
yield
|
97
|
+
@after = DateTime.now
|
98
|
+
rescue ActiveRecord::UnknownAttributeError, ActiveRecord::ActiveRecordError => e
|
99
|
+
@error = e.message
|
100
|
+
ensure
|
101
|
+
if @error
|
102
|
+
@type = 'error'
|
103
|
+
@after = nil
|
104
|
+
end
|
105
|
+
create_log_entry if @modified || @error
|
106
|
+
end
|
107
|
+
|
108
|
+
def create_log_entry
|
109
|
+
@log.modifications.create(
|
110
|
+
:instance_id => @target.id,
|
111
|
+
:modification_type => @type,
|
112
|
+
:instance_errors => @error,
|
113
|
+
:before_time => @before,
|
114
|
+
:after_time => @after
|
115
|
+
)
|
116
|
+
end
|
83
117
|
end
|
84
118
|
|
85
119
|
end
|
metadata
CHANGED
@@ -1,88 +1,84 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: harmonize
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
4
5
|
prerelease:
|
5
|
-
version: 0.0.2
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Bram Swenson
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-11-17 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
17
15
|
name: hashie
|
18
|
-
requirement: &
|
16
|
+
requirement: &11797080 !ruby/object:Gem::Requirement
|
19
17
|
none: false
|
20
|
-
requirements:
|
21
|
-
- -
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version:
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
24
22
|
type: :runtime
|
25
23
|
prerelease: false
|
26
|
-
version_requirements: *
|
27
|
-
description:
|
28
|
-
Bring entire sets of models into harmony with external sources.
|
24
|
+
version_requirements: *11797080
|
25
|
+
description: ! 'Bring entire sets of models into harmony with external sources.
|
29
26
|
|
30
|
-
|
27
|
+
'
|
28
|
+
email:
|
31
29
|
- bram@craniumisajar.com
|
32
30
|
executables: []
|
33
|
-
|
34
31
|
extensions: []
|
35
|
-
|
36
32
|
extra_rdoc_files: []
|
37
|
-
|
38
|
-
|
39
|
-
- app/models/harmonize/log.rb
|
40
|
-
- app/models/harmonize/modification.rb
|
41
|
-
- lib/harmonize/base.rb
|
33
|
+
files:
|
34
|
+
- lib/harmonize/models.rb
|
42
35
|
- lib/harmonize/configuration.rb
|
43
|
-
- lib/harmonize/engine.rb
|
44
36
|
- lib/harmonize/errors.rb
|
45
37
|
- lib/harmonize/gemdata.rb
|
46
|
-
- lib/harmonize/strategies/basic_crud_strategy.rb
|
47
38
|
- lib/harmonize/strategies/strategy.rb
|
39
|
+
- lib/harmonize/strategies/basic_crud_strategy.rb
|
40
|
+
- lib/harmonize/engine.rb
|
41
|
+
- lib/harmonize/base.rb
|
42
|
+
- lib/harmonize/models/active_record/modification.rb
|
43
|
+
- lib/harmonize/models/active_record/log.rb
|
44
|
+
- lib/harmonize/models/mongoid/modification.rb
|
45
|
+
- lib/harmonize/models/mongoid/log.rb
|
48
46
|
- lib/harmonize/strategies.rb
|
49
47
|
- lib/harmonize.rb
|
50
|
-
- lib/rails/generators/harmonize/migration_generator.rb
|
51
48
|
- lib/rails/generators/harmonize/templates/migration.rb
|
49
|
+
- lib/rails/generators/harmonize/migration_generator.rb
|
52
50
|
- MIT-LICENSE
|
53
51
|
- Rakefile
|
54
52
|
- Gemfile
|
55
53
|
- README.md
|
56
|
-
has_rdoc: true
|
57
54
|
homepage: http://github.com/bramswenson/harmonize
|
58
55
|
licenses: []
|
59
|
-
|
60
56
|
post_install_message:
|
61
57
|
rdoc_options: []
|
62
|
-
|
63
|
-
require_paths:
|
58
|
+
require_paths:
|
64
59
|
- lib
|
65
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
61
|
none: false
|
67
|
-
requirements:
|
68
|
-
- -
|
69
|
-
- !ruby/object:Gem::Version
|
70
|
-
|
71
|
-
segments:
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
segments:
|
72
67
|
- 0
|
73
|
-
|
74
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
hash: 4193351527517161227
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
70
|
none: false
|
76
|
-
requirements:
|
77
|
-
- -
|
78
|
-
- !ruby/object:Gem::Version
|
79
|
-
version:
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
hash: 4193351527517161227
|
80
78
|
requirements: []
|
81
|
-
|
82
79
|
rubyforge_project:
|
83
|
-
rubygems_version: 1.
|
80
|
+
rubygems_version: 1.8.10
|
84
81
|
signing_key:
|
85
82
|
specification_version: 3
|
86
83
|
summary: Bring entire sets of models into harmony with external sources.
|
87
84
|
test_files: []
|
88
|
-
|
data/app/models/harmonize/log.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
module Harmonize
|
2
|
-
class Log < ActiveRecord::Base
|
3
|
-
set_table_name :harmonize_logs
|
4
|
-
|
5
|
-
validates :key, :class_name, :harmonizer_name, :strategy, :strategy_arguments, :presence => true
|
6
|
-
|
7
|
-
ModificationOptions = { :class_name => "Harmonize::Modification", :foreign_key => :harmonize_log_id }
|
8
|
-
|
9
|
-
has_many :modifications, ModificationOptions.merge(:inverse_of => :log, :dependent => :destroy)
|
10
|
-
has_many :created, ModificationOptions.merge(:conditions => { :modification_type => 'create' })
|
11
|
-
has_many :updated, ModificationOptions.merge(:conditions => { :modification_type => 'update' })
|
12
|
-
has_many :destroyed, ModificationOptions.merge(:conditions => { :modification_type => 'destroy'})
|
13
|
-
has_many :errored, ModificationOptions.merge(:conditions => { :modification_type => 'error' })
|
14
|
-
|
15
|
-
end
|
16
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module Harmonize
|
2
|
-
class Modification < ActiveRecord::Base
|
3
|
-
set_table_name :harmonize_modifications
|
4
|
-
|
5
|
-
validates :harmonize_log_id, :modification_type, :presence => true
|
6
|
-
validates :modification_type, :inclusion => %w( create update destroy error )
|
7
|
-
|
8
|
-
serialize :instance_errors
|
9
|
-
|
10
|
-
belongs_to :log, :class_name => "Harmonize::Log",
|
11
|
-
:foreign_key => :harmonize_log_id, :inverse_of => :modifications
|
12
|
-
|
13
|
-
scope :created, where(:modification_type => 'create')
|
14
|
-
scope :updated, where(:modification_type => 'update')
|
15
|
-
scope :destroyed, where(:modification_type => 'destroy')
|
16
|
-
scope :errored, where(:modification_type => 'error')
|
17
|
-
end
|
18
|
-
end
|