restforce-db 3.0.0 → 3.1.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.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/lib/restforce/db.rb +2 -0
  3. data/lib/restforce/db/associator.rb +2 -11
  4. data/lib/restforce/db/attacher.rb +91 -0
  5. data/lib/restforce/db/cleaner.rb +3 -13
  6. data/lib/restforce/db/collector.rb +1 -10
  7. data/lib/restforce/db/field_processor.rb +53 -17
  8. data/lib/restforce/db/initializer.rb +6 -14
  9. data/lib/restforce/db/instances/salesforce.rb +2 -1
  10. data/lib/restforce/db/record_types/salesforce.rb +47 -20
  11. data/lib/restforce/db/synchronizer.rb +1 -9
  12. data/lib/restforce/db/task.rb +32 -0
  13. data/lib/restforce/db/version.rb +1 -1
  14. data/lib/restforce/db/worker.rb +21 -59
  15. data/test/cassettes/Restforce_DB/accessing_Salesforce/uses_the_configured_credentials.yml +6 -6
  16. data/test/cassettes/Restforce_DB_Associations_BelongsTo/with_an_inverse_mapping/_build/returns_an_associated_record_populated_with_the_Salesforce_attributes.yml +203 -52
  17. data/test/cassettes/Restforce_DB_Associations_BelongsTo/with_an_inverse_mapping/_build/when_no_salesforce_record_is_found_for_the_association/proceeds_without_constructing_any_records.yml +185 -34
  18. data/test/cassettes/Restforce_DB_Associations_BelongsTo/with_an_inverse_mapping/_build/when_the_associated_record_has_already_been_persisted/assigns_the_existing_record.yml +203 -52
  19. data/test/cassettes/Restforce_DB_Associations_BelongsTo/with_an_inverse_mapping/_build/when_the_associated_record_has_been_cached/uses_the_cached_record.yml +203 -52
  20. data/test/cassettes/Restforce_DB_Associations_BelongsTo/with_an_inverse_mapping/_build/when_the_association_is_non-building/proceeds_without_constructing_any_records.yml +97 -44
  21. data/test/cassettes/Restforce_DB_Associations_BelongsTo/with_an_inverse_mapping/_build/with_an_unrelated_association_mapping/proceeds_without_raising_an_error.yml +203 -52
  22. data/test/cassettes/Restforce_DB_Associations_BelongsTo/with_an_inverse_mapping/_lookups/returns_a_hash_of_the_associated_records_lookup_IDs.yml +36 -36
  23. data/test/cassettes/Restforce_DB_Associations_BelongsTo/with_an_inverse_mapping/_lookups/when_there_is_currently_no_associated_record/and_the_underlying_association_is_one-to-many/still_returns_a_nil_lookup_value_in_the_hash.yml +20 -20
  24. data/test/cassettes/Restforce_DB_Associations_BelongsTo/with_an_inverse_mapping/_lookups/when_there_is_currently_no_associated_record/returns_a_nil_lookup_value_in_the_hash.yml +20 -20
  25. data/test/cassettes/Restforce_DB_Associations_BelongsTo/with_an_inverse_mapping/_synced_for_/when_a_matching_associated_record_has_been_synchronized/returns_true.yml +105 -52
  26. data/test/cassettes/Restforce_DB_Associations_BelongsTo/with_an_inverse_mapping/_synced_for_/when_no_matching_associated_record_has_been_synchronized/returns_false.yml +105 -52
  27. data/test/cassettes/Restforce_DB_Associations_HasMany/with_an_inverse_mapping/_build/builds_a_number_of_associated_records_from_the_data_in_Salesforce.yml +191 -87
  28. data/test/cassettes/Restforce_DB_Associations_HasMany/with_an_inverse_mapping/_build/when_no_salesforce_record_is_found_for_the_association/proceeds_without_constructing_any_records.yml +139 -35
  29. data/test/cassettes/Restforce_DB_Associations_HasMany/with_an_inverse_mapping/_build/when_the_associated_records_have_alrady_been_persisted/constructs_the_association_from_the_existing_records.yml +191 -87
  30. data/test/cassettes/Restforce_DB_Associations_HasMany/with_an_inverse_mapping/_build/when_the_associated_records_have_been_cached/uses_the_cached_records.yml +191 -87
  31. data/test/cassettes/Restforce_DB_Associations_HasMany/with_an_inverse_mapping/_build/when_the_association_is_non-building/proceeds_without_constructing_any_records.yml +81 -28
  32. data/test/cassettes/Restforce_DB_Associations_HasMany/with_an_inverse_mapping/_synced_for_/when_a_matching_associated_record_has_been_synchronized/returns_true.yml +191 -87
  33. data/test/cassettes/Restforce_DB_Associations_HasMany/with_an_inverse_mapping/_synced_for_/when_no_matching_associated_record_has_been_synchronized/returns_false.yml +139 -35
  34. data/test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_build/and_a_nested_association_on_the_associated_mapping/recursively_builds_all_associations.yml +278 -76
  35. data/test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_build/returns_an_associated_record_populated_with_the_Salesforce_attributes.yml +203 -52
  36. data/test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_build/when_no_salesforce_record_is_found_for_the_association/proceeds_without_constructing_any_records.yml +186 -35
  37. data/test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_build/when_the_associated_record_has_already_been_persisted/assigns_the_existing_record.yml +203 -52
  38. data/test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_build/when_the_associated_record_has_been_cached/uses_the_cached_record.yml +203 -52
  39. data/test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_build/when_the_association_is_non-building/proceeds_without_constructing_any_records.yml +142 -44
  40. data/test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_synced_for_/when_a_matching_associated_record_has_been_synchronized/returns_true.yml +203 -52
  41. data/test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_synced_for_/when_no_matching_associated_record_has_been_synchronized/returns_false.yml +203 -52
  42. data/test/cassettes/Restforce_DB_Associator/_run/given_a_BelongsTo_association/given_another_record_for_association/when_the_Salesforce_association_is_out_of_date/updates_the_association_ID_in_Salesforce.yml +124 -124
  43. data/test/cassettes/Restforce_DB_Associator/_run/given_a_BelongsTo_association/given_another_record_for_association/when_the_database_association_is_out_of_date/updates_the_associated_record_in_the_database.yml +224 -126
  44. data/test/cassettes/Restforce_DB_Attacher/_run/given_a_Salesforce_record_with_an_upsert_ID/for_a_Passive_strategy/does_nothing.yml +119 -0
  45. data/test/cassettes/Restforce_DB_Attacher/_run/given_a_Salesforce_record_with_an_upsert_ID/for_an_Always_strategy/links_the_Salesforce_record_to_the_matching_database_record.yml +246 -0
  46. data/test/cassettes/Restforce_DB_Attacher/_run/given_a_Salesforce_record_with_an_upsert_ID/for_an_Always_strategy/when_no_matching_database_record_can_be_found/wipes_the_SynchronizationID__c_on_the_Salesforce_record.yml +284 -0
  47. data/test/cassettes/Restforce_DB_Attacher/_run/given_a_Salesforce_record_with_an_upsert_ID/for_an_Always_strategy/when_the_matching_database_record_has_a_salesforce_id/does_not_change_the_current_Salesforce_ID.yml +246 -0
  48. data/test/cassettes/Restforce_DB_Attacher/_run/given_a_Salesforce_record_with_an_upsert_ID/for_an_Always_strategy/when_the_matching_database_record_has_a_salesforce_id/wipes_the_SynchronizationId__c.yml +284 -0
  49. data/test/cassettes/{Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/updates_the_salesforce_record.yml → Restforce_DB_Attacher/_run/given_a_Salesforce_record_with_an_upsert_ID/for_an_Always_strategy/when_the_upsert_ID_is_for_another_database_model/does_not_wipe_the_SynchronizationId__c.yml} +57 -95
  50. data/test/cassettes/{Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/updates_the_database_record.yml → Restforce_DB_Attacher/_run/given_a_Salesforce_record_with_an_upsert_ID/for_an_Always_strategy/wipes_the_SynchronizationId__c.yml} +77 -116
  51. data/test/cassettes/Restforce_DB_Cleaner/_run/given_a_synchronized_Salesforce_record/when_the_mapping_has_no_conditions/does_not_drop_the_synchronized_database_record.yml +20 -20
  52. data/test/cassettes/Restforce_DB_Cleaner/_run/given_a_synchronized_Salesforce_record/when_the_record_does_not_meet_the_mapping_conditions/but_meets_conditions_for_a_parallel_mapping/does_not_drop_the_synchronized_database_record.yml +98 -45
  53. data/test/cassettes/Restforce_DB_Cleaner/_run/given_a_synchronized_Salesforce_record/when_the_record_does_not_meet_the_mapping_conditions/drops_the_synchronized_database_record.yml +90 -37
  54. data/test/cassettes/Restforce_DB_Cleaner/_run/given_a_synchronized_Salesforce_record/when_the_record_has_been_deleted_in_Salesforce/drops_the_synchronized_database_record.yml +20 -20
  55. data/test/cassettes/Restforce_DB_Cleaner/_run/given_a_synchronized_Salesforce_record/when_the_record_meets_the_mapping_conditions/does_not_drop_the_synchronized_database_record.yml +89 -36
  56. data/test/cassettes/Restforce_DB_Collector/_run/given_a_Salesforce_record_with_an_associated_database_record/returns_the_attributes_from_both_records.yml +103 -50
  57. data/test/cassettes/Restforce_DB_Collector/_run/given_an_existing_Salesforce_record/which_has_been_synchronized/returns_the_attributes_from_the_Salesforce_record.yml +102 -73
  58. data/test/cassettes/Restforce_DB_Collector/_run/given_an_existing_Salesforce_record/which_has_not_been_synchronized/does_not_store_any_attributes.yml +81 -40
  59. data/test/cassettes/Restforce_DB_Collector/_run/given_an_existing_database_record/returns_the_attributes_from_the_database_record.yml +66 -13
  60. data/test/cassettes/Restforce_DB_Collector/_run/when_the_record_has_not_been_updated_outside_of_the_system/does_not_collect_any_changes.yml +82 -29
  61. data/test/cassettes/Restforce_DB_Initializer/_run/given_an_existing_Salesforce_record/for_a_Passive_strategy/does_not_create_a_database_record.yml +20 -20
  62. data/test/cassettes/Restforce_DB_Initializer/_run/given_an_existing_Salesforce_record/for_an_Always_strategy/creates_a_matching_database_record.yml +81 -28
  63. data/test/cassettes/Restforce_DB_Initializer/_run/given_an_existing_database_record/for_an_Always_strategy/populates_Salesforce_with_the_new_record.yml +103 -67
  64. data/test/cassettes/Restforce_DB_Instances_Salesforce/_synced_/when_a_matching_database_record_exists/returns_true.yml +81 -28
  65. data/test/cassettes/Restforce_DB_Instances_Salesforce/_synced_/when_no_matching_database_record_exists/returns_false.yml +81 -28
  66. data/test/cassettes/Restforce_DB_Instances_Salesforce/_update_/updates_the_local_record_with_the_passed_attributes.yml +59 -59
  67. data/test/cassettes/Restforce_DB_Instances_Salesforce/_update_/updates_the_record_in_Salesforce_with_the_passed_attributes.yml +67 -67
  68. data/test/cassettes/Restforce_DB_Instances_Salesforce/_updated_internally_/when_another_user_made_the_last_change/returns_false.yml +18 -18
  69. data/test/cassettes/Restforce_DB_Instances_Salesforce/_updated_internally_/when_our_client_made_the_last_change/returns_true.yml +101 -48
  70. data/test/cassettes/Restforce_DB_Model/given_a_database_model_which_includes_the_module/_force_sync_/given_a_previously-synchronized_record_for_a_mapped_model/force-updates_both_synchronized_records.yml +67 -67
  71. data/test/cassettes/Restforce_DB_Model/given_a_database_model_which_includes_the_module/_force_sync_/given_an_unsynchronized_record_for_a_mapped_model/creates_a_matching_record_in_Salesforce.yml +78 -42
  72. data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_all/returns_a_list_of_the_existing_records_in_Salesforce.yml +82 -29
  73. data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_create_/creates_a_record_in_Salesforce_from_the_passed_database_record_s_attributes.yml +70 -34
  74. data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_create_/updates_the_database_record_with_the_Salesforce_record_s_ID.yml +70 -34
  75. data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_create_/when_a_Salesforce_record_already_exists_for_the_database_instance/uses_the_existing_record.yml +76 -40
  76. data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_create_/wipes_the_temporary_SynchronizationId__c_value_used_for_upsert.yml +247 -0
  77. data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/finds_existing_records_in_Salesforce.yml +81 -28
  78. data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/given_a_set_of_mapping_conditions/when_a_record_does_not_meet_the_conditions/does_not_find_the_record.yml +80 -27
  79. data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/given_a_set_of_mapping_conditions/when_a_record_meets_the_conditions/finds_the_record.yml +81 -28
  80. data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/returns_nil_when_no_matching_record_exists.yml +65 -12
  81. data/test/cassettes/Restforce_DB_Strategies_Always/_build_/given_a_Salesforce_record/wants_to_build_a_new_matching_record.yml +81 -28
  82. data/test/cassettes/Restforce_DB_Strategies_Always/_build_/given_a_Salesforce_record/with_a_corresponding_database_record/does_not_want_to_build_a_new_record.yml +81 -28
  83. data/test/cassettes/Restforce_DB_Strategies_Associated/_build_/given_an_inverse_mapping/with_a_synchronized_association_record/wants_to_build_a_new_record.yml +103 -52
  84. data/test/cassettes/Restforce_DB_Strategies_Associated/_build_/given_an_inverse_mapping/with_an_existing_database_record/does_not_want_to_build_a_new_record.yml +95 -44
  85. data/test/cassettes/Restforce_DB_Strategies_Associated/_build_/given_an_inverse_mapping/with_no_synchronized_association_record/does_not_want_to_build_a_new_record.yml +103 -52
  86. data/test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/when_the_change_timestamp_is_stale/does_not_update_the_database_record.yml +60 -96
  87. data/test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/when_the_change_timestamp_is_stale/does_not_update_the_salesforce_record.yml +97 -44
  88. data/test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/when_the_changes_are_current/updates_the_database_record.yml +77 -77
  89. data/test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/when_the_changes_are_current/updates_the_salesforce_record.yml +85 -85
  90. data/test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_no_associated_database_record/does_nothing_for_this_specific_mapping.yml +89 -36
  91. data/test/cassettes/Restforce_DB_Worker/a_race_condition_during_synchronization/does_not_change_the_user-entered_name_on_the_database_record.yml +153 -116
  92. data/test/cassettes/Restforce_DB_Worker/a_race_condition_during_synchronization/overrides_the_stale-but-more-recent_name_on_the_Salesforce.yml +161 -124
  93. data/test/lib/restforce/db/attacher_test.rb +93 -0
  94. data/test/lib/restforce/db/field_processor_test.rb +62 -23
  95. data/test/lib/restforce/db/record_types/salesforce_test.rb +5 -0
  96. data/test/lib/restforce/db/worker_test.rb +4 -3
  97. metadata +13 -4
@@ -0,0 +1,93 @@
1
+ require_relative "../../../test_helper"
2
+
3
+ describe Restforce::DB::Attacher do
4
+
5
+ configure!
6
+ mappings!
7
+
8
+ let(:attacher) { Restforce::DB::Attacher.new(mapping) }
9
+
10
+ describe "#run", vcr: { match_requests_on: [:method, VCR.request_matchers.uri_without_param(:q)] } do
11
+ let(:attributes) do
12
+ {
13
+ "SynchronizationId__c" => "CustomObject::#{database_record.id}",
14
+ }
15
+ end
16
+ let(:database_record) { database_model.create! }
17
+ let(:salesforce_id) { Salesforce.create!(salesforce_model, attributes) }
18
+
19
+ describe "given a Salesforce record with an upsert ID" do
20
+ before do
21
+ salesforce_id
22
+ end
23
+
24
+ describe "for a Passive strategy" do
25
+ before do
26
+ mapping.strategy = Restforce::DB::Strategies::Passive.new
27
+ attacher.run
28
+ end
29
+
30
+ it "does nothing" do
31
+ expect(database_record.reload).to_not_be :salesforce_id?
32
+ end
33
+ end
34
+
35
+ describe "for an Always strategy" do
36
+ before do
37
+ mapping.strategy = Restforce::DB::Strategies::Always.new
38
+ attacher.run
39
+ end
40
+
41
+ it "links the Salesforce record to the matching database record" do
42
+ expect(database_record.reload).to_be :salesforce_id?
43
+ end
44
+
45
+ it "wipes the SynchronizationId__c" do
46
+ salesforce_record = mapping.salesforce_record_type.find(salesforce_id).record
47
+ expect(salesforce_record.SynchronizationId__c).to_be_nil
48
+ end
49
+
50
+ describe "when the matching database record has a salesforce_id" do
51
+ let(:old_id) { "a001a000001E1vFAKE" }
52
+ let(:database_record) { database_model.create!(salesforce_id: old_id) }
53
+
54
+ it "does not change the current Salesforce ID" do
55
+ expect(database_record.reload.salesforce_id).to_equal old_id
56
+ end
57
+
58
+ it "wipes the SynchronizationId__c" do
59
+ salesforce_record = mapping.salesforce_record_type.find(salesforce_id).record
60
+ expect(salesforce_record.SynchronizationId__c).to_be_nil
61
+ end
62
+ end
63
+
64
+ describe "when no matching database record can be found" do
65
+ let(:database_record) { nil }
66
+ let(:attributes) do
67
+ {
68
+ "SynchronizationId__c" => "CustomObject::1",
69
+ }
70
+ end
71
+
72
+ it "wipes the SynchronizationId__c" do
73
+ salesforce_record = mapping.salesforce_record_type.find(salesforce_id).record
74
+ expect(salesforce_record.SynchronizationId__c).to_be_nil
75
+ end
76
+ end
77
+
78
+ describe "when the upsert ID is for another database model" do
79
+ let(:attributes) do
80
+ {
81
+ "SynchronizationId__c" => "User::1",
82
+ }
83
+ end
84
+
85
+ it "does not wipe the SynchronizationId__c" do
86
+ salesforce_record = mapping.salesforce_record_type.find(salesforce_id).record
87
+ expect(salesforce_record.SynchronizationId__c).to_not_be_nil
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -5,42 +5,81 @@ describe Restforce::DB::FieldProcessor do
5
5
  configure!
6
6
 
7
7
  let(:processor) { Restforce::DB::FieldProcessor.new }
8
+ let(:dummy_client) do
9
+ Object.new.tap do |client|
10
+
11
+ def client.describe(_)
12
+ raise "This has already been invoked!" if @already_run
13
+ @already_run = true
14
+
15
+ Struct.new(:fields).new([
16
+ { "name" => "Createable", "createable" => true, "updateable" => false },
17
+ { "name" => "Updateable", "createable" => false, "updateable" => true },
18
+ { "name" => "Both", "createable" => true, "updateable" => true },
19
+ { "name" => "Neither", "createable" => false, "updateable" => false },
20
+ ])
21
+ end
22
+
23
+ end
24
+ end
25
+
26
+ describe "#available_fields" do
27
+ let(:fields) do
28
+ %w(
29
+ Createable
30
+ Updateable
31
+ Both
32
+ Neither
33
+ Relationship__r.Relateable
34
+ )
35
+ end
36
+
37
+ it "filters the passed fields to only existing fields for an object" do
38
+ Restforce::DB.stub(:client, dummy_client) do
39
+ excessive_fields = fields + ["NonExistent"]
40
+ expect(processor.available_fields("CustomObject__c", excessive_fields)).to_equal(fields)
41
+ end
42
+ end
43
+
44
+ it "filters the passed fields to only createable fields" do
45
+ Restforce::DB.stub(:client, dummy_client) do
46
+ expect(processor.available_fields("CustomObject__c", fields, :create)).to_equal(%w(
47
+ Createable
48
+ Both
49
+ ))
50
+ end
51
+ end
52
+
53
+ it "filters the passed fields to only updateable fields" do
54
+ Restforce::DB.stub(:client, dummy_client) do
55
+ expect(processor.available_fields("CustomObject__c", fields, :update)).to_equal(%w(
56
+ Updateable
57
+ Both
58
+ ))
59
+ end
60
+ end
61
+ end
8
62
 
9
63
  describe "#process" do
10
64
  let(:attributes) do
11
65
  {
12
- "Creatable" => "This field is create-only!",
66
+ "Createable" => "This field is create-only!",
13
67
  "Updateable" => "And... this field is update-only!",
14
68
  "Both" => "But... this field allows both!",
69
+ "Neither" => "Unfortunately, this field allows neither.",
15
70
  }
16
71
  end
17
- let(:dummy_client) do
18
- Object.new.tap do |client|
19
72
 
20
- def client.describe(_)
21
- raise "This has already been invoked!" if @already_run
22
- @already_run = true
23
-
24
- Struct.new(:fields).new([
25
- { "name" => "Creatable", "createable" => true, "updateable" => false },
26
- { "name" => "Updateable", "createable" => false, "updateable" => true },
27
- { "name" => "Both", "createable" => true, "updateable" => true },
28
- ])
29
- end
30
-
31
- end
32
- end
33
-
34
- it "removes the read-only fields from the passed attribute Hash on :create" do
73
+ it "removes the non-creatable fields from the passed attribute Hash on :create" do
35
74
  Restforce::DB.stub(:client, dummy_client) do
36
75
  expect(processor.process("CustomObject__c", attributes, :create)).to_equal(
37
- "Creatable" => attributes["Creatable"],
38
- "Both" => attributes["Both"],
76
+ "Createable" => attributes["Createable"],
77
+ "Both" => attributes["Both"],
39
78
  )
40
79
  end
41
80
  end
42
81
 
43
- it "removes the read-only fields from the passed attribute Hash on :update" do
82
+ it "removes the non-updateable fields from the passed attribute Hash on :update" do
44
83
  Restforce::DB.stub(:client, dummy_client) do
45
84
  expect(processor.process("CustomObject__c", attributes, :update)).to_equal(
46
85
  "Updateable" => attributes["Updateable"],
@@ -51,11 +90,11 @@ describe Restforce::DB::FieldProcessor do
51
90
 
52
91
  it "invokes the client only once for a single SObject Type" do
53
92
  Restforce::DB.stub(:client, dummy_client) do
54
- processor.process("CustomObject__c", attributes)
93
+ processor.process("CustomObject__c", attributes, :update)
55
94
 
56
95
  # Our dummy client is configured to raise an error if `#describe` is
57
96
  # invoked more than once. There is no "wont_raise" in Minitest.
58
- processor.process("CustomObject__c", attributes)
97
+ processor.process("CustomObject__c", attributes, :create)
59
98
  end
60
99
  end
61
100
  end
@@ -28,6 +28,11 @@ describe Restforce::DB::RecordTypes::Salesforce do
28
28
  expect(sync_from.synced?).to_equal(true)
29
29
  end
30
30
 
31
+ it "wipes the temporary SynchronizationId__c value used for upsert" do
32
+ Salesforce.records << [salesforce_model, instance.Id]
33
+ expect(instance.SynchronizationId__c).to_be_nil
34
+ end
35
+
31
36
  describe "when a Salesforce record already exists for the database instance" do
32
37
 
33
38
  it "uses the existing record" do
@@ -20,7 +20,8 @@ describe Restforce::DB::Worker do
20
20
 
21
21
  ## 1b. The record is synced to Salesforce.
22
22
  worker.send :reset!
23
- worker.send :propagate, mapping
23
+ worker.send :task, Restforce::DB::Initializer, mapping
24
+
24
25
  expect(database_record.reload).to_be :salesforce_id?
25
26
  Salesforce.records << [salesforce_model, database_record.salesforce_id]
26
27
 
@@ -43,8 +44,8 @@ describe Restforce::DB::Worker do
43
44
  # We sleep here to ensure we pick up our manual changes.
44
45
  sleep 1 if VCR.current_cassette.recording?
45
46
  worker.send :reset!
46
- worker.send :collect, mapping
47
- worker.send :synchronize, mapping
47
+ worker.send :task, Restforce::DB::Collector, mapping
48
+ worker.send :task, Restforce::DB::Synchronizer, mapping
48
49
  end
49
50
  end
50
51
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restforce-db
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Horner
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-06-25 00:00:00.000000000 Z
11
+ date: 2015-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -216,6 +216,7 @@ files:
216
216
  - lib/restforce/db/associations/has_many.rb
217
217
  - lib/restforce/db/associations/has_one.rb
218
218
  - lib/restforce/db/associator.rb
219
+ - lib/restforce/db/attacher.rb
219
220
  - lib/restforce/db/attribute_map.rb
220
221
  - lib/restforce/db/cleaner.rb
221
222
  - lib/restforce/db/client.rb
@@ -243,6 +244,7 @@ files:
243
244
  - lib/restforce/db/strategy.rb
244
245
  - lib/restforce/db/synchronization_error.rb
245
246
  - lib/restforce/db/synchronizer.rb
247
+ - lib/restforce/db/task.rb
246
248
  - lib/restforce/db/timestamp_cache.rb
247
249
  - lib/restforce/db/tracker.rb
248
250
  - lib/restforce/db/version.rb
@@ -279,6 +281,13 @@ files:
279
281
  - test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_synced_for_/when_no_matching_associated_record_has_been_synchronized/returns_false.yml
280
282
  - test/cassettes/Restforce_DB_Associator/_run/given_a_BelongsTo_association/given_another_record_for_association/when_the_Salesforce_association_is_out_of_date/updates_the_association_ID_in_Salesforce.yml
281
283
  - test/cassettes/Restforce_DB_Associator/_run/given_a_BelongsTo_association/given_another_record_for_association/when_the_database_association_is_out_of_date/updates_the_associated_record_in_the_database.yml
284
+ - test/cassettes/Restforce_DB_Attacher/_run/given_a_Salesforce_record_with_an_upsert_ID/for_a_Passive_strategy/does_nothing.yml
285
+ - test/cassettes/Restforce_DB_Attacher/_run/given_a_Salesforce_record_with_an_upsert_ID/for_an_Always_strategy/links_the_Salesforce_record_to_the_matching_database_record.yml
286
+ - test/cassettes/Restforce_DB_Attacher/_run/given_a_Salesforce_record_with_an_upsert_ID/for_an_Always_strategy/when_no_matching_database_record_can_be_found/wipes_the_SynchronizationID__c_on_the_Salesforce_record.yml
287
+ - test/cassettes/Restforce_DB_Attacher/_run/given_a_Salesforce_record_with_an_upsert_ID/for_an_Always_strategy/when_the_matching_database_record_has_a_salesforce_id/does_not_change_the_current_Salesforce_ID.yml
288
+ - test/cassettes/Restforce_DB_Attacher/_run/given_a_Salesforce_record_with_an_upsert_ID/for_an_Always_strategy/when_the_matching_database_record_has_a_salesforce_id/wipes_the_SynchronizationId__c.yml
289
+ - test/cassettes/Restforce_DB_Attacher/_run/given_a_Salesforce_record_with_an_upsert_ID/for_an_Always_strategy/when_the_upsert_ID_is_for_another_database_model/does_not_wipe_the_SynchronizationId__c.yml
290
+ - test/cassettes/Restforce_DB_Attacher/_run/given_a_Salesforce_record_with_an_upsert_ID/for_an_Always_strategy/wipes_the_SynchronizationId__c.yml
282
291
  - test/cassettes/Restforce_DB_Cleaner/_run/given_a_synchronized_Salesforce_record/when_the_mapping_has_no_conditions/does_not_drop_the_synchronized_database_record.yml
283
292
  - test/cassettes/Restforce_DB_Cleaner/_run/given_a_synchronized_Salesforce_record/when_the_record_does_not_meet_the_mapping_conditions/but_meets_conditions_for_a_parallel_mapping/does_not_drop_the_synchronized_database_record.yml
284
293
  - test/cassettes/Restforce_DB_Cleaner/_run/given_a_synchronized_Salesforce_record/when_the_record_does_not_meet_the_mapping_conditions/drops_the_synchronized_database_record.yml
@@ -304,6 +313,7 @@ files:
304
313
  - test/cassettes/Restforce_DB_RecordTypes_Salesforce/_create_/creates_a_record_in_Salesforce_from_the_passed_database_record_s_attributes.yml
305
314
  - test/cassettes/Restforce_DB_RecordTypes_Salesforce/_create_/updates_the_database_record_with_the_Salesforce_record_s_ID.yml
306
315
  - test/cassettes/Restforce_DB_RecordTypes_Salesforce/_create_/when_a_Salesforce_record_already_exists_for_the_database_instance/uses_the_existing_record.yml
316
+ - test/cassettes/Restforce_DB_RecordTypes_Salesforce/_create_/wipes_the_temporary_SynchronizationId__c_value_used_for_upsert.yml
307
317
  - test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/finds_existing_records_in_Salesforce.yml
308
318
  - test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/given_a_set_of_mapping_conditions/when_a_record_does_not_meet_the_conditions/does_not_find_the_record.yml
309
319
  - test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/given_a_set_of_mapping_conditions/when_a_record_meets_the_conditions/finds_the_record.yml
@@ -313,8 +323,6 @@ files:
313
323
  - test/cassettes/Restforce_DB_Strategies_Associated/_build_/given_an_inverse_mapping/with_a_synchronized_association_record/wants_to_build_a_new_record.yml
314
324
  - test/cassettes/Restforce_DB_Strategies_Associated/_build_/given_an_inverse_mapping/with_an_existing_database_record/does_not_want_to_build_a_new_record.yml
315
325
  - test/cassettes/Restforce_DB_Strategies_Associated/_build_/given_an_inverse_mapping/with_no_synchronized_association_record/does_not_want_to_build_a_new_record.yml
316
- - test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/updates_the_database_record.yml
317
- - test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/updates_the_salesforce_record.yml
318
326
  - test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/when_the_change_timestamp_is_stale/does_not_update_the_database_record.yml
319
327
  - test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/when_the_change_timestamp_is_stale/does_not_update_the_salesforce_record.yml
320
328
  - test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/when_the_changes_are_current/updates_the_database_record.yml
@@ -329,6 +337,7 @@ files:
329
337
  - test/lib/restforce/db/associations/has_many_test.rb
330
338
  - test/lib/restforce/db/associations/has_one_test.rb
331
339
  - test/lib/restforce/db/associator_test.rb
340
+ - test/lib/restforce/db/attacher_test.rb
332
341
  - test/lib/restforce/db/attribute_map_test.rb
333
342
  - test/lib/restforce/db/cleaner_test.rb
334
343
  - test/lib/restforce/db/collector_test.rb