maestrano-connector-rails 2.0.2.pre.RC5 → 2.0.2.pre.RC6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +4 -0
- data/Gemfile +2 -2
- data/VERSION +1 -1
- data/app/models/maestrano/connector/rails/concerns/entity.rb +3 -125
- data/app/models/maestrano/connector/rails/concerns/sub_entity_base.rb +0 -8
- data/app/models/maestrano/connector/rails/organization.rb +2 -2
- data/app/models/maestrano/connector/rails/services/data_consolidator.rb +157 -0
- data/maestrano-connector-rails.gemspec +10 -12
- data/spec/models/complex_entity_spec.rb +3 -5
- data/spec/spec_helper.rb +1 -1
- metadata +20 -23
- data/bin/rails +0 -17
- data/bin/rake +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44c8a03cd21fe3a99e6db9afaef6859ec8f7a7bf
|
4
|
+
data.tar.gz: fc34a1cec7f51613576f15631b0a1b2f99e3f0e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44d8478e4cd319ffa2dd858849b6382d8204f8047071139c817a0cfd0742e95cc4c29b4dba413228eae1eb3a881525924ee5c3b1ee408e6fc2629395c6229348
|
7
|
+
data.tar.gz: 9b77f64bce1e3f2b74b69e7653e36cd2a9aed844992cb6a019847fc657337f0fde563ed4bba96761cb5a241dfa2c0ce0017c55dd11890e8ceb2fc61ff0eaf97b
|
data/.rubocop_todo.yml
CHANGED
data/Gemfile
CHANGED
@@ -3,7 +3,7 @@ source 'http://rubygems.org'
|
|
3
3
|
# Add dependencies required to use your gem here.
|
4
4
|
gem 'rails', '~> 4.2'
|
5
5
|
|
6
|
-
gem 'maestrano-rails', '~> 1.0.
|
6
|
+
gem 'maestrano-rails', '~> 1.0.3'
|
7
7
|
|
8
8
|
gem 'attr_encrypted', '~> 1.4.0'
|
9
9
|
gem 'autoprefixer-rails'
|
@@ -22,7 +22,6 @@ gem 'slim'
|
|
22
22
|
|
23
23
|
# Add dependencies to develop your gem here.
|
24
24
|
group :development do
|
25
|
-
gem 'webmock', '~> 1.24.1'
|
26
25
|
gem 'activerecord-jdbcsqlite3-adapter', platforms: :jruby
|
27
26
|
gem 'bundler'
|
28
27
|
gem 'factory_girl_rails'
|
@@ -36,4 +35,5 @@ group :development do
|
|
36
35
|
gem 'simplecov', '>= 0'
|
37
36
|
gem 'sqlite3', platforms: :ruby
|
38
37
|
gem 'timecop'
|
38
|
+
gem 'webmock', '~> 1.24.1'
|
39
39
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0.2.pre.
|
1
|
+
2.0.2.pre.RC6
|
@@ -422,84 +422,15 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
422
422
|
end
|
423
423
|
|
424
424
|
def consolidate_and_map_connec_entities(connec_entities, external_entities, references, external_entity_name)
|
425
|
-
|
426
|
-
# Entity has been created before date filtering limit
|
427
|
-
next nil if before_date_filtering_limit?(entity, false) && !@opts[:full_sync]
|
428
|
-
|
429
|
-
# Unfold the id arrays
|
430
|
-
# From that point on, the connec_entity contains only string of external ids
|
431
|
-
unfold_hash = Maestrano::Connector::Rails::ConnecHelper.unfold_references(entity, references, @organization)
|
432
|
-
entity = unfold_hash[:entity]
|
433
|
-
next nil unless entity # discard if at least one record reference is missing
|
434
|
-
connec_id = unfold_hash[:connec_id]
|
435
|
-
id_refs_only_connec_entity = unfold_hash[:id_refs_only_connec_entity]
|
436
|
-
|
437
|
-
if entity['id'].blank?
|
438
|
-
# Expecting find_or_create to be mostly a create
|
439
|
-
idmap = self.class.find_or_create_idmap(organization_id: @organization.id, name: self.class.object_name_from_connec_entity_hash(entity), external_entity: external_entity_name.downcase, connec_id: connec_id)
|
440
|
-
next map_connec_entity_with_idmap(entity, external_entity_name, idmap, id_refs_only_connec_entity)
|
441
|
-
end
|
442
|
-
|
443
|
-
# Expecting find_or_create to be mostly a find
|
444
|
-
idmap = self.class.find_or_create_idmap(external_id: entity['id'], organization_id: @organization.id, external_entity: external_entity_name.downcase, connec_id: connec_id)
|
445
|
-
idmap.update(name: self.class.object_name_from_connec_entity_hash(entity))
|
446
|
-
|
447
|
-
next nil if idmap.external_inactive || !idmap.to_external || (!@opts[:full_sync] && not_modified_since_last_push_to_external?(idmap, entity))
|
448
|
-
|
449
|
-
# Check for conflict with entities from external
|
450
|
-
solve_conflict(entity, external_entities, external_entity_name, idmap, id_refs_only_connec_entity)
|
451
|
-
}.compact
|
425
|
+
Maestrano::Connector::Rails::Services::DataConsolidator.new(@organization, self, @opts).consolidate_connec_entities(connec_entities, external_entities, references, external_entity_name)
|
452
426
|
end
|
453
427
|
|
454
428
|
def consolidate_and_map_external_entities(external_entities, connec_entity_name)
|
455
|
-
|
456
|
-
# Entity has been created before date filtering limit
|
457
|
-
next nil if before_date_filtering_limit?(entity) && !@opts[:full_sync]
|
458
|
-
|
459
|
-
entity_id = self.class.id_from_external_entity_hash(entity)
|
460
|
-
idmap = self.class.find_or_create_idmap(external_id: entity_id, organization_id: @organization.id, connec_entity: connec_entity_name.downcase)
|
461
|
-
|
462
|
-
# Not pushing entity to Connec!
|
463
|
-
next nil unless idmap.to_connec
|
464
|
-
|
465
|
-
# Not pushing to Connec! and flagging as inactive if inactive in external application
|
466
|
-
inactive = self.class.inactive_from_external_entity_hash?(entity)
|
467
|
-
idmap.update(external_inactive: inactive, name: self.class.object_name_from_external_entity_hash(entity))
|
468
|
-
next nil if inactive
|
469
|
-
|
470
|
-
# Entity has not been modified since its last push to connec!
|
471
|
-
next nil if !@opts[:full_sync] && not_modified_since_last_push_to_connec?(idmap, entity)
|
472
|
-
|
473
|
-
map_external_entity_with_idmap(entity, connec_entity_name, idmap)
|
474
|
-
}.compact
|
429
|
+
Maestrano::Connector::Rails::Services::DataConsolidator.new(@organization, self, @opts).consolidate_external_entities(external_entities, connec_entity_name)
|
475
430
|
end
|
476
431
|
|
477
432
|
def consolidate_and_map_singleton(connec_entities, external_entities)
|
478
|
-
|
479
|
-
|
480
|
-
idmap = self.class.find_or_create_idmap(organization_id: @organization.id)
|
481
|
-
# No to_connec, to_external and inactive consideration here as we don't expect those workflow for singleton
|
482
|
-
|
483
|
-
keep_external = if external_entities.empty?
|
484
|
-
false
|
485
|
-
elsif connec_entities.empty?
|
486
|
-
true
|
487
|
-
elsif @opts.key?(:connec_preemption)
|
488
|
-
!@opts[:connec_preemption]
|
489
|
-
else
|
490
|
-
!is_connec_more_recent?(connec_entities.first, external_entities.first)
|
491
|
-
end
|
492
|
-
|
493
|
-
if keep_external
|
494
|
-
idmap.update(external_id: self.class.id_from_external_entity_hash(external_entities.first), name: self.class.object_name_from_external_entity_hash(external_entities.first))
|
495
|
-
return {connec_entities: [], external_entities: [{entity: map_to_connec(external_entities.first), idmap: idmap}]}
|
496
|
-
else
|
497
|
-
unfold_hash = Maestrano::Connector::Rails::ConnecHelper.unfold_references(connec_entities.first, self.class.references, @organization)
|
498
|
-
entity = unfold_hash[:entity]
|
499
|
-
idmap.update(name: self.class.object_name_from_connec_entity_hash(entity), connec_id: unfold_hash[:connec_id])
|
500
|
-
idmap.update(external_id: self.class.id_from_external_entity_hash(external_entities.first)) unless external_entities.empty?
|
501
|
-
return {connec_entities: [{entity: map_to_external(entity), idmap: idmap, id_refs_only_connec_entity: {}}], external_entities: []}
|
502
|
-
end
|
433
|
+
Maestrano::Connector::Rails::Services::DataConsolidator.new(@organization, self, @opts).consolidate_singleton(connec_entities, external_entities)
|
503
434
|
end
|
504
435
|
|
505
436
|
# ----------------------------------------------
|
@@ -548,59 +479,6 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
548
479
|
end
|
549
480
|
end
|
550
481
|
|
551
|
-
def not_modified_since_last_push_to_connec?(idmap, entity)
|
552
|
-
not_modified = idmap.last_push_to_connec && idmap.last_push_to_connec > self.class.last_update_date_from_external_entity_hash(entity)
|
553
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', @organization, "Discard #{Maestrano::Connector::Rails::External.external_name} #{self.class.external_entity_name} : #{entity}") if not_modified
|
554
|
-
not_modified
|
555
|
-
end
|
556
|
-
|
557
|
-
def not_modified_since_last_push_to_external?(idmap, entity)
|
558
|
-
not_modified = idmap.last_push_to_external && idmap.last_push_to_external > entity['updated_at']
|
559
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', @organization, "Discard Connec! #{self.class.connec_entity_name} : #{entity}") if not_modified
|
560
|
-
not_modified
|
561
|
-
end
|
562
|
-
|
563
|
-
def before_date_filtering_limit?(entity, external = true)
|
564
|
-
@organization.date_filtering_limit && @organization.date_filtering_limit > (external ? self.class.creation_date_from_external_entity_hash(entity) : entity['created_at'])
|
565
|
-
end
|
566
|
-
|
567
|
-
def is_connec_more_recent?(connec_entity, external_entity)
|
568
|
-
connec_entity['updated_at'] > self.class.last_update_date_from_external_entity_hash(external_entity)
|
569
|
-
end
|
570
|
-
|
571
|
-
# This methods try to find a external entity among all the external entities matching the connec (mapped) one (same id)
|
572
|
-
# If it does not find any, there is no conflict, and it returns the mapped connec entity
|
573
|
-
# If it finds one, the conflict is solved either with options or using the entities timestamps
|
574
|
-
# If the connec entity is kept, it is returned mapped and the matching external entity is discarded (deleted from the array)
|
575
|
-
# Else the method returns nil, meaning the connec entity is discarded
|
576
|
-
def solve_conflict(connec_entity, external_entities, external_entity_name, idmap, id_refs_only_connec_entity)
|
577
|
-
# Here the connec_entity['id'] is an external id (String) because the entity has been unfolded.
|
578
|
-
external_entity = external_entities.find { |entity| connec_entity['id'] == self.class.id_from_external_entity_hash(entity) }
|
579
|
-
# No conflict
|
580
|
-
return map_connec_entity_with_idmap(connec_entity, external_entity_name, idmap, id_refs_only_connec_entity) unless external_entity
|
581
|
-
|
582
|
-
# Conflict
|
583
|
-
# We keep the most recently updated entity
|
584
|
-
keep_connec = @opts.key?(:connec_preemption) ? @opts[:connec_preemption] : is_connec_more_recent?(connec_entity, external_entity)
|
585
|
-
|
586
|
-
if keep_connec
|
587
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', @organization, "Conflict between #{Maestrano::Connector::Rails::External.external_name} #{external_entity_name} #{external_entity} and Connec! #{self.class.connec_entity_name} #{connec_entity}. Entity from Connec! kept")
|
588
|
-
external_entities.delete(external_entity)
|
589
|
-
map_connec_entity_with_idmap(connec_entity, external_entity_name, idmap, id_refs_only_connec_entity)
|
590
|
-
else
|
591
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', @organization, "Conflict between #{Maestrano::Connector::Rails::External.external_name} #{external_entity_name} #{external_entity} and Connec! #{self.class.connec_entity_name} #{connec_entity}. Entity from external kept")
|
592
|
-
nil
|
593
|
-
end
|
594
|
-
end
|
595
|
-
|
596
|
-
def map_connec_entity_with_idmap(connec_entity, external_entity_name, idmap, id_refs_only_connec_entity)
|
597
|
-
{entity: map_to_external(connec_entity, idmap.last_push_to_external.nil?), idmap: idmap, id_refs_only_connec_entity: id_refs_only_connec_entity}
|
598
|
-
end
|
599
|
-
|
600
|
-
def map_external_entity_with_idmap(external_entity, connec_entity_name, idmap)
|
601
|
-
{entity: map_to_connec(external_entity, idmap.last_push_to_connec.nil?), idmap: idmap}
|
602
|
-
end
|
603
|
-
|
604
482
|
def fetch_connec(uri)
|
605
483
|
Maestrano::Connector::Rails::ConnectorLogger.log('debug', @organization, "Fetching data from connec entity=#{self.class.connec_entity_name}, url=#{uri}")
|
606
484
|
response = @connec_client.get(uri)
|
@@ -60,14 +60,6 @@ module Maestrano::Connector::Rails::Concerns::SubEntityBase
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
def map_connec_entity_with_idmap(connec_entity, external_entity_name, idmap, id_refs_only_connec_entity)
|
64
|
-
{entity: map_to(external_entity_name, connec_entity, idmap.last_push_to_external.nil?), idmap: idmap, id_refs_only_connec_entity: id_refs_only_connec_entity}
|
65
|
-
end
|
66
|
-
|
67
|
-
def map_external_entity_with_idmap(external_entity, connec_entity_name, idmap)
|
68
|
-
{entity: map_to(connec_entity_name, external_entity, idmap.last_push_to_connec.nil?), idmap: idmap}
|
69
|
-
end
|
70
|
-
|
71
63
|
# Maps the entity received from external after a creation or an update and complete the received ids with the connec ones
|
72
64
|
def map_and_complete_hash_with_connec_ids(external_hash, external_entity_name, connec_hash)
|
73
65
|
return nil if connec_hash.empty?
|
@@ -134,11 +134,11 @@ module Maestrano::Connector::Rails
|
|
134
134
|
end
|
135
135
|
|
136
136
|
def push_to_connec_enabled?(entity)
|
137
|
-
synchronized_entities.dig(EntityHelper.snake_name(entity), :can_push_to_connec) && entity&.class
|
137
|
+
synchronized_entities.dig(EntityHelper.snake_name(entity), :can_push_to_connec) && entity&.class&.can_write_connec?
|
138
138
|
end
|
139
139
|
|
140
140
|
def push_to_external_enabled?(entity)
|
141
|
-
synchronized_entities.dig(EntityHelper.snake_name(entity), :can_push_to_external) && entity&.class
|
141
|
+
synchronized_entities.dig(EntityHelper.snake_name(entity), :can_push_to_external) && entity&.class&.can_write_external?
|
142
142
|
end
|
143
143
|
|
144
144
|
def set_instance_metadata
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module Maestrano::Connector::Rails::Services
|
2
|
+
class DataConsolidator
|
3
|
+
def initialize(organization, entity_self, options)
|
4
|
+
@is_a_subentity = entity_self.is_a?(Maestrano::Connector::Rails::Concerns::SubEntityBase)
|
5
|
+
@organization = organization
|
6
|
+
@current_entity = entity_self
|
7
|
+
@opts = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def consolidate_singleton(connec_entities, external_entities)
|
11
|
+
return {connec_entities: [], external_entities: []} if external_entities.empty? && connec_entities.empty?
|
12
|
+
|
13
|
+
idmap = @current_entity.class.find_or_create_idmap(organization_id: @organization.id)
|
14
|
+
# No to_connec, to_external and inactive consideration here as we don't expect those workflow for singleton
|
15
|
+
|
16
|
+
external_id = @current_entity.class.id_from_external_entity_hash(external_entities.first) if external_entities.first
|
17
|
+
# A singleton will be either valid (updated/created) in the external app or in Connec!
|
18
|
+
# if keep_external is true we are keeping the external entity
|
19
|
+
keep_external = if external_entities.empty?
|
20
|
+
false
|
21
|
+
elsif connec_entities.empty?
|
22
|
+
true
|
23
|
+
elsif @opts.key?(:connec_preemption)
|
24
|
+
!@opts[:connec_preemption]
|
25
|
+
else
|
26
|
+
!connec_more_recent?(connec_entities.first, external_entities.first)
|
27
|
+
end
|
28
|
+
|
29
|
+
if keep_external
|
30
|
+
idmap.update(external_id: external_id, name: @current_entity.class.object_name_from_external_entity_hash(external_entities.first))
|
31
|
+
return {connec_entities: [], external_entities: [{entity: @current_entity.map_to_connec(external_entities.first), idmap: idmap}]}
|
32
|
+
else
|
33
|
+
unfold_hash = Maestrano::Connector::Rails::ConnecHelper.unfold_references(connec_entities.first, @current_entity.class.references, @organization)
|
34
|
+
entity = unfold_hash[:entity]
|
35
|
+
idmap.update(name: @current_entity.class.object_name_from_connec_entity_hash(entity), connec_id: unfold_hash[:connec_id])
|
36
|
+
idmap.update(external_id: @current_entity.class.id_from_external_entity_hash(external_entities.first)) unless external_entities.empty?
|
37
|
+
return {connec_entities: [{entity: @current_entity.map_to_external(entity), idmap: idmap, id_refs_only_connec_entity: {}}], external_entities: []}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def consolidate_connec_entities(connec_entities, external_entities, references, external_entity_name)
|
42
|
+
connec_entities.map do |entity|
|
43
|
+
# Entity has been created before date filtering limit
|
44
|
+
next if before_date_filtering_limit?(entity, false) && !@opts[:full_sync]
|
45
|
+
|
46
|
+
# Unfold the id arrays
|
47
|
+
# From that point on, the connec_entity contains only string of external ids
|
48
|
+
unfold_hash = Maestrano::Connector::Rails::ConnecHelper.unfold_references(entity, references, @organization)
|
49
|
+
entity = unfold_hash[:entity]
|
50
|
+
next unless entity # discard if at least one record reference is missing
|
51
|
+
connec_id = unfold_hash[:connec_id]
|
52
|
+
id_refs_only_connec_entity = unfold_hash[:id_refs_only_connec_entity]
|
53
|
+
|
54
|
+
if entity['id'].blank?
|
55
|
+
# Expecting find_or_create to be mostly a create
|
56
|
+
idmap = @current_entity.class.find_or_create_idmap(organization_id: @organization.id, name: @current_entity.class.object_name_from_connec_entity_hash(entity), external_entity: external_entity_name.downcase, connec_id: connec_id)
|
57
|
+
next map_connec_entity_with_idmap(entity, external_entity_name, idmap, id_refs_only_connec_entity)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Expecting find_or_create to be mostly a find
|
61
|
+
idmap = @current_entity.class.find_or_create_idmap(external_id: entity['id'], organization_id: @organization.id, external_entity: external_entity_name.downcase, connec_id: connec_id)
|
62
|
+
idmap.update(name: @current_entity.class.object_name_from_connec_entity_hash(entity))
|
63
|
+
|
64
|
+
next if idmap.external_inactive || !idmap.to_external || (!@opts[:full_sync] && not_modified_since_last_push_to_external?(idmap, entity))
|
65
|
+
|
66
|
+
# Check for conflict with entities from external
|
67
|
+
solve_conflict(entity, external_entities, external_entity_name, idmap, id_refs_only_connec_entity)
|
68
|
+
end.compact
|
69
|
+
end
|
70
|
+
|
71
|
+
def consolidate_external_entities(external_entities, connec_entity_name)
|
72
|
+
external_entities.map do |entity|
|
73
|
+
# Entity has been created before date filtering limit
|
74
|
+
next if before_date_filtering_limit?(entity) && !@opts[:full_sync]
|
75
|
+
|
76
|
+
entity_id = @current_entity.class.id_from_external_entity_hash(entity)
|
77
|
+
idmap = @current_entity.class.find_or_create_idmap(external_id: entity_id, organization_id: @organization.id, connec_entity: connec_entity_name.downcase)
|
78
|
+
|
79
|
+
# Not pushing entity to Connec!
|
80
|
+
next unless idmap.to_connec
|
81
|
+
|
82
|
+
# Not pushing to Connec! and flagging as inactive if inactive in external application
|
83
|
+
inactive = @current_entity.class.inactive_from_external_entity_hash?(entity)
|
84
|
+
idmap.update(external_inactive: inactive, name: @current_entity.class.object_name_from_external_entity_hash(entity))
|
85
|
+
next if inactive
|
86
|
+
|
87
|
+
# Entity has not been modified since its last push to connec!
|
88
|
+
next if !@opts[:full_sync] && not_modified_since_last_push_to_connec?(idmap, entity)
|
89
|
+
|
90
|
+
map_external_entity_with_idmap(entity, connec_entity_name, idmap)
|
91
|
+
end.compact
|
92
|
+
end
|
93
|
+
|
94
|
+
def before_date_filtering_limit?(entity, external = true)
|
95
|
+
@organization.date_filtering_limit && @organization.date_filtering_limit > (external ? @current_entity.class.creation_date_from_external_entity_hash(entity) : entity['created_at'])
|
96
|
+
end
|
97
|
+
|
98
|
+
def not_modified_since_last_push_to_connec?(idmap, entity)
|
99
|
+
not_modified = idmap.last_push_to_connec && idmap.last_push_to_connec > @current_entity.class.last_update_date_from_external_entity_hash(entity)
|
100
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', @organization, "Discard #{Maestrano::Connector::Rails::External.external_name} #{@current_entity.class.external_entity_name} : #{entity}") if not_modified
|
101
|
+
not_modified
|
102
|
+
end
|
103
|
+
|
104
|
+
def not_modified_since_last_push_to_external?(idmap, entity)
|
105
|
+
not_modified = idmap.last_push_to_external && idmap.last_push_to_external > entity['updated_at']
|
106
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', @organization, "Discard Connec! #{@current_entity.class.connec_entity_name} : #{entity}") if not_modified
|
107
|
+
not_modified
|
108
|
+
end
|
109
|
+
|
110
|
+
def map_external_entity_with_idmap(external_entity, connec_entity_name, idmap)
|
111
|
+
entity = if @is_a_subentity
|
112
|
+
@current_entity.map_to(connec_entity_name, external_entity, idmap.last_push_to_connec.nil?)
|
113
|
+
else
|
114
|
+
@current_entity.map_to_connec(external_entity, idmap.last_push_to_connec.nil?)
|
115
|
+
end
|
116
|
+
{entity: entity, idmap: idmap}
|
117
|
+
end
|
118
|
+
|
119
|
+
def map_connec_entity_with_idmap(connec_entity, external_entity_name, idmap, id_refs_only_connec_entity)
|
120
|
+
entity = if @is_a_subentity
|
121
|
+
@current_entity.map_to(external_entity_name, connec_entity, idmap.last_push_to_external.nil?)
|
122
|
+
else
|
123
|
+
@current_entity.map_to_external(connec_entity, idmap.last_push_to_external.nil?)
|
124
|
+
end
|
125
|
+
{entity: entity, idmap: idmap, id_refs_only_connec_entity: id_refs_only_connec_entity}
|
126
|
+
end
|
127
|
+
|
128
|
+
# This methods try to find a external entity among all the external entities matching the connec (mapped) one (same id)
|
129
|
+
# If it does not find any, there is no conflict, and it returns the mapped connec entity
|
130
|
+
# If it finds one, the conflict is solved either with options or using the entities timestamps
|
131
|
+
# If the connec entity is kept, it is returned mapped and the matching external entity is discarded (deleted from the array)
|
132
|
+
# Else the method returns nil, meaning the connec entity is discarded
|
133
|
+
def solve_conflict(connec_entity, external_entities, external_entity_name, idmap, id_refs_only_connec_entity)
|
134
|
+
# Here the connec_entity['id'] is an external id (String) because the entity has been unfolded.
|
135
|
+
external_entity = external_entities.find { |entity| connec_entity['id'] == @current_entity.class.id_from_external_entity_hash(entity) }
|
136
|
+
# No conflict
|
137
|
+
return map_connec_entity_with_idmap(connec_entity, external_entity_name, idmap, id_refs_only_connec_entity) unless external_entity
|
138
|
+
|
139
|
+
# Conflict
|
140
|
+
# We keep the most recently updated entity
|
141
|
+
keep_connec = @opts.key?(:connec_preemption) ? @opts[:connec_preemption] : connec_more_recent?(connec_entity, external_entity)
|
142
|
+
|
143
|
+
if keep_connec
|
144
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', @organization, "Conflict between #{Maestrano::Connector::Rails::External.external_name} #{external_entity_name} #{external_entity} and Connec! #{@current_entity.class.connec_entity_name} #{connec_entity}. Entity from Connec! kept")
|
145
|
+
external_entities.delete(external_entity)
|
146
|
+
map_connec_entity_with_idmap(connec_entity, external_entity_name, idmap, id_refs_only_connec_entity)
|
147
|
+
else
|
148
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', @organization, "Conflict between #{Maestrano::Connector::Rails::External.external_name} #{external_entity_name} #{external_entity} and Connec! #{@current_entity.class.connec_entity_name} #{connec_entity}. Entity from external kept")
|
149
|
+
nil
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def connec_more_recent?(connec_entity, external_entity)
|
154
|
+
connec_entity['updated_at'] > @current_entity.class.last_update_date_from_external_entity_hash(external_entity)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -2,19 +2,18 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: maestrano-connector-rails 2.0.2.pre.
|
5
|
+
# stub: maestrano-connector-rails 2.0.2.pre.RC6 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "maestrano-connector-rails".freeze
|
9
|
-
s.version = "2.0.2.pre.
|
9
|
+
s.version = "2.0.2.pre.RC6"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["Maestrano".freeze]
|
14
|
-
s.date = "2017-02-
|
14
|
+
s.date = "2017-02-16"
|
15
15
|
s.description = "Maestrano is the next generation marketplace for SME applications. See https://sme.maestrano.com for details.".freeze
|
16
16
|
s.email = "developers@maestrano.com".freeze
|
17
|
-
s.executables = ["rails".freeze, "rake".freeze]
|
18
17
|
s.extra_rdoc_files = [
|
19
18
|
"LICENSE",
|
20
19
|
"README.md"
|
@@ -64,12 +63,11 @@ Gem::Specification.new do |s|
|
|
64
63
|
"app/models/maestrano/connector/rails/external.rb",
|
65
64
|
"app/models/maestrano/connector/rails/id_map.rb",
|
66
65
|
"app/models/maestrano/connector/rails/organization.rb",
|
66
|
+
"app/models/maestrano/connector/rails/services/data_consolidator.rb",
|
67
67
|
"app/models/maestrano/connector/rails/sub_entity_base.rb",
|
68
68
|
"app/models/maestrano/connector/rails/synchronization.rb",
|
69
69
|
"app/models/maestrano/connector/rails/user.rb",
|
70
70
|
"app/models/maestrano/connector/rails/user_organization_rel.rb",
|
71
|
-
"bin/rails",
|
72
|
-
"bin/rake",
|
73
71
|
"config/routes.rb",
|
74
72
|
"db/migrate/20151122162100_create_users.rb",
|
75
73
|
"db/migrate/20151122162414_create_organizations.rb",
|
@@ -229,7 +227,7 @@ Gem::Specification.new do |s|
|
|
229
227
|
|
230
228
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
231
229
|
s.add_runtime_dependency(%q<rails>.freeze, ["~> 4.2"])
|
232
|
-
s.add_runtime_dependency(%q<maestrano-rails>.freeze, ["~> 1.0.
|
230
|
+
s.add_runtime_dependency(%q<maestrano-rails>.freeze, ["~> 1.0.3"])
|
233
231
|
s.add_runtime_dependency(%q<attr_encrypted>.freeze, ["~> 1.4.0"])
|
234
232
|
s.add_runtime_dependency(%q<autoprefixer-rails>.freeze, [">= 0"])
|
235
233
|
s.add_runtime_dependency(%q<bootstrap-sass>.freeze, [">= 0"])
|
@@ -242,7 +240,6 @@ Gem::Specification.new do |s|
|
|
242
240
|
s.add_runtime_dependency(%q<sidekiq-unique-jobs>.freeze, [">= 0"])
|
243
241
|
s.add_runtime_dependency(%q<sinatra>.freeze, [">= 0"])
|
244
242
|
s.add_runtime_dependency(%q<slim>.freeze, [">= 0"])
|
245
|
-
s.add_development_dependency(%q<webmock>.freeze, ["~> 1.24.1"])
|
246
243
|
s.add_development_dependency(%q<activerecord-jdbcsqlite3-adapter>.freeze, [">= 0"])
|
247
244
|
s.add_development_dependency(%q<bundler>.freeze, [">= 0"])
|
248
245
|
s.add_development_dependency(%q<factory_girl_rails>.freeze, [">= 0"])
|
@@ -256,9 +253,10 @@ Gem::Specification.new do |s|
|
|
256
253
|
s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
|
257
254
|
s.add_development_dependency(%q<sqlite3>.freeze, [">= 0"])
|
258
255
|
s.add_development_dependency(%q<timecop>.freeze, [">= 0"])
|
256
|
+
s.add_development_dependency(%q<webmock>.freeze, ["~> 1.24.1"])
|
259
257
|
else
|
260
258
|
s.add_dependency(%q<rails>.freeze, ["~> 4.2"])
|
261
|
-
s.add_dependency(%q<maestrano-rails>.freeze, ["~> 1.0.
|
259
|
+
s.add_dependency(%q<maestrano-rails>.freeze, ["~> 1.0.3"])
|
262
260
|
s.add_dependency(%q<attr_encrypted>.freeze, ["~> 1.4.0"])
|
263
261
|
s.add_dependency(%q<autoprefixer-rails>.freeze, [">= 0"])
|
264
262
|
s.add_dependency(%q<bootstrap-sass>.freeze, [">= 0"])
|
@@ -271,7 +269,6 @@ Gem::Specification.new do |s|
|
|
271
269
|
s.add_dependency(%q<sidekiq-unique-jobs>.freeze, [">= 0"])
|
272
270
|
s.add_dependency(%q<sinatra>.freeze, [">= 0"])
|
273
271
|
s.add_dependency(%q<slim>.freeze, [">= 0"])
|
274
|
-
s.add_dependency(%q<webmock>.freeze, ["~> 1.24.1"])
|
275
272
|
s.add_dependency(%q<activerecord-jdbcsqlite3-adapter>.freeze, [">= 0"])
|
276
273
|
s.add_dependency(%q<bundler>.freeze, [">= 0"])
|
277
274
|
s.add_dependency(%q<factory_girl_rails>.freeze, [">= 0"])
|
@@ -285,10 +282,11 @@ Gem::Specification.new do |s|
|
|
285
282
|
s.add_dependency(%q<simplecov>.freeze, [">= 0"])
|
286
283
|
s.add_dependency(%q<sqlite3>.freeze, [">= 0"])
|
287
284
|
s.add_dependency(%q<timecop>.freeze, [">= 0"])
|
285
|
+
s.add_dependency(%q<webmock>.freeze, ["~> 1.24.1"])
|
288
286
|
end
|
289
287
|
else
|
290
288
|
s.add_dependency(%q<rails>.freeze, ["~> 4.2"])
|
291
|
-
s.add_dependency(%q<maestrano-rails>.freeze, ["~> 1.0.
|
289
|
+
s.add_dependency(%q<maestrano-rails>.freeze, ["~> 1.0.3"])
|
292
290
|
s.add_dependency(%q<attr_encrypted>.freeze, ["~> 1.4.0"])
|
293
291
|
s.add_dependency(%q<autoprefixer-rails>.freeze, [">= 0"])
|
294
292
|
s.add_dependency(%q<bootstrap-sass>.freeze, [">= 0"])
|
@@ -301,7 +299,6 @@ Gem::Specification.new do |s|
|
|
301
299
|
s.add_dependency(%q<sidekiq-unique-jobs>.freeze, [">= 0"])
|
302
300
|
s.add_dependency(%q<sinatra>.freeze, [">= 0"])
|
303
301
|
s.add_dependency(%q<slim>.freeze, [">= 0"])
|
304
|
-
s.add_dependency(%q<webmock>.freeze, ["~> 1.24.1"])
|
305
302
|
s.add_dependency(%q<activerecord-jdbcsqlite3-adapter>.freeze, [">= 0"])
|
306
303
|
s.add_dependency(%q<bundler>.freeze, [">= 0"])
|
307
304
|
s.add_dependency(%q<factory_girl_rails>.freeze, [">= 0"])
|
@@ -315,6 +312,7 @@ Gem::Specification.new do |s|
|
|
315
312
|
s.add_dependency(%q<simplecov>.freeze, [">= 0"])
|
316
313
|
s.add_dependency(%q<sqlite3>.freeze, [">= 0"])
|
317
314
|
s.add_dependency(%q<timecop>.freeze, [">= 0"])
|
315
|
+
s.add_dependency(%q<webmock>.freeze, ["~> 1.24.1"])
|
318
316
|
end
|
319
317
|
end
|
320
318
|
|
@@ -166,7 +166,7 @@ describe Maestrano::Connector::Rails::ComplexEntity do
|
|
166
166
|
let(:external_name) { 'sc_e1' }
|
167
167
|
let(:connec_name) { 'connec1' }
|
168
168
|
let(:modelled_external_entities) { {external_name => {connec_name => [entity]}} }
|
169
|
-
before
|
169
|
+
before do
|
170
170
|
allow(subject.class).to receive(:connec_entities_names).and_return(['connec1'])
|
171
171
|
allow(subject.class).to receive(:external_entities_names).and_return(['sc_e1'])
|
172
172
|
allow(Entities::SubEntities::ScE1).to receive(:external?).and_return(true)
|
@@ -175,7 +175,7 @@ describe Maestrano::Connector::Rails::ComplexEntity do
|
|
175
175
|
allow(Entities::SubEntities::ScE1).to receive(:object_name_from_external_entity_hash).and_return(human_name)
|
176
176
|
allow(Entities::SubEntities::ScE1).to receive(:last_update_date_from_external_entity_hash).and_return(date)
|
177
177
|
allow_any_instance_of(Entities::SubEntities::ScE1).to receive(:map_to).and_return(mapped_entity)
|
178
|
-
|
178
|
+
end
|
179
179
|
|
180
180
|
context 'when idmap exists' do
|
181
181
|
let!(:idmap) { create(:idmap, organization: organization, connec_entity: connec_name.downcase, external_entity: external_name.downcase, external_id: id) }
|
@@ -199,9 +199,7 @@ describe Maestrano::Connector::Rails::ComplexEntity do
|
|
199
199
|
end
|
200
200
|
|
201
201
|
context 'when entity is inactive' do
|
202
|
-
before {
|
203
|
-
allow(Entities::SubEntities::ScE1).to receive(:inactive_from_external_entity_hash?).and_return(true)
|
204
|
-
}
|
202
|
+
before { allow(Entities::SubEntities::ScE1).to receive(:inactive_from_external_entity_hash?).and_return(true)}
|
205
203
|
|
206
204
|
it 'discards the entity' do
|
207
205
|
expect(subject.consolidate_and_map_external_entities(modelled_external_entities)).to eql({external_name => {connec_name => []}})
|
data/spec/spec_helper.rb
CHANGED
@@ -27,7 +27,7 @@ RSpec.configure do |config|
|
|
27
27
|
allow(Maestrano::Connector::Rails::External).to receive(:external_name).and_return('External app')
|
28
28
|
allow(Maestrano::Connector::Rails::External).to receive(:get_client).and_return(Object.new)
|
29
29
|
allow(Maestrano::Connector::Rails::External).to receive(:entities_list).and_return(%w(entity1 entity2))
|
30
|
-
stub_request(:get,
|
30
|
+
stub_request(:get, %r(#{Maestrano['default'].param('api.host')}/api/v1/account/groups/[\w-]*)).
|
31
31
|
to_return({status: 200, body: "{}", headers: {}})
|
32
32
|
Rails.cache.clear
|
33
33
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: maestrano-connector-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.2.pre.
|
4
|
+
version: 2.0.2.pre.RC6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maestrano
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-02-
|
11
|
+
date: 2017-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.0.
|
33
|
+
version: 1.0.3
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.0.
|
40
|
+
version: 1.0.3
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: attr_encrypted
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -206,20 +206,6 @@ dependencies:
|
|
206
206
|
- - ">="
|
207
207
|
- !ruby/object:Gem::Version
|
208
208
|
version: '0'
|
209
|
-
- !ruby/object:Gem::Dependency
|
210
|
-
name: webmock
|
211
|
-
requirement: !ruby/object:Gem::Requirement
|
212
|
-
requirements:
|
213
|
-
- - "~>"
|
214
|
-
- !ruby/object:Gem::Version
|
215
|
-
version: 1.24.1
|
216
|
-
type: :development
|
217
|
-
prerelease: false
|
218
|
-
version_requirements: !ruby/object:Gem::Requirement
|
219
|
-
requirements:
|
220
|
-
- - "~>"
|
221
|
-
- !ruby/object:Gem::Version
|
222
|
-
version: 1.24.1
|
223
209
|
- !ruby/object:Gem::Dependency
|
224
210
|
name: activerecord-jdbcsqlite3-adapter
|
225
211
|
requirement: !ruby/object:Gem::Requirement
|
@@ -402,12 +388,24 @@ dependencies:
|
|
402
388
|
- - ">="
|
403
389
|
- !ruby/object:Gem::Version
|
404
390
|
version: '0'
|
391
|
+
- !ruby/object:Gem::Dependency
|
392
|
+
name: webmock
|
393
|
+
requirement: !ruby/object:Gem::Requirement
|
394
|
+
requirements:
|
395
|
+
- - "~>"
|
396
|
+
- !ruby/object:Gem::Version
|
397
|
+
version: 1.24.1
|
398
|
+
type: :development
|
399
|
+
prerelease: false
|
400
|
+
version_requirements: !ruby/object:Gem::Requirement
|
401
|
+
requirements:
|
402
|
+
- - "~>"
|
403
|
+
- !ruby/object:Gem::Version
|
404
|
+
version: 1.24.1
|
405
405
|
description: Maestrano is the next generation marketplace for SME applications. See
|
406
406
|
https://sme.maestrano.com for details.
|
407
407
|
email: developers@maestrano.com
|
408
|
-
executables:
|
409
|
-
- rails
|
410
|
-
- rake
|
408
|
+
executables: []
|
411
409
|
extensions: []
|
412
410
|
extra_rdoc_files:
|
413
411
|
- LICENSE
|
@@ -457,12 +455,11 @@ files:
|
|
457
455
|
- app/models/maestrano/connector/rails/external.rb
|
458
456
|
- app/models/maestrano/connector/rails/id_map.rb
|
459
457
|
- app/models/maestrano/connector/rails/organization.rb
|
458
|
+
- app/models/maestrano/connector/rails/services/data_consolidator.rb
|
460
459
|
- app/models/maestrano/connector/rails/sub_entity_base.rb
|
461
460
|
- app/models/maestrano/connector/rails/synchronization.rb
|
462
461
|
- app/models/maestrano/connector/rails/user.rb
|
463
462
|
- app/models/maestrano/connector/rails/user_organization_rel.rb
|
464
|
-
- bin/rails
|
465
|
-
- bin/rake
|
466
463
|
- config/routes.rb
|
467
464
|
- db/migrate/20151122162100_create_users.rb
|
468
465
|
- db/migrate/20151122162414_create_organizations.rb
|
data/bin/rails
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
#
|
4
|
-
# This file was generated by Bundler.
|
5
|
-
#
|
6
|
-
# The application 'rails' is installed as part of a gem, and
|
7
|
-
# this file is here to facilitate running it.
|
8
|
-
#
|
9
|
-
|
10
|
-
require "pathname"
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
12
|
-
Pathname.new(__FILE__).realpath)
|
13
|
-
|
14
|
-
require "rubygems"
|
15
|
-
require "bundler/setup"
|
16
|
-
|
17
|
-
load Gem.bin_path("railties", "rails")
|
data/bin/rake
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
#
|
4
|
-
# This file was generated by Bundler.
|
5
|
-
#
|
6
|
-
# The application 'rake' is installed as part of a gem, and
|
7
|
-
# this file is here to facilitate running it.
|
8
|
-
#
|
9
|
-
|
10
|
-
require "pathname"
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
12
|
-
Pathname.new(__FILE__).realpath)
|
13
|
-
|
14
|
-
require "rubygems"
|
15
|
-
require "bundler/setup"
|
16
|
-
|
17
|
-
load Gem.bin_path("rake", "rake")
|