restforce-db 0.3.5 → 0.4.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.
- checksums.yaml +4 -4
- data/README.md +5 -3
- data/lib/restforce/db/associations/active_record.rb +68 -0
- data/lib/restforce/db/instances/active_record.rb +2 -2
- data/lib/restforce/db/mapping.rb +37 -7
- data/lib/restforce/db/record_types/active_record.rb +19 -32
- data/lib/restforce/db/record_types/salesforce.rb +1 -1
- data/lib/restforce/db/version.rb +1 -1
- data/lib/restforce/db/worker.rb +4 -5
- data/lib/restforce/db.rb +2 -0
- data/test/lib/restforce/db/associations/active_record_test.rb +43 -0
- data/test/lib/restforce/db/mapping_test.rb +42 -2
- data/test/lib/restforce/db/model_test.rb +1 -2
- data/test/lib/restforce/db/record_types/active_record_test.rb +6 -1
- data/test/lib/restforce/db/synchronizer_test.rb +2 -1
- data/test/support/utilities.rb +2 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 98a9d9a418a15a7b4ca5ab954bc95d3e831e3bca
|
4
|
+
data.tar.gz: 26effab90549afaecad3d7883ef6f0881c4e96d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b8140eb2811c5fad0e94d82bf255219eb15d95105581eb32d84ce3cf0fd504495c5b39251d436581eee8f1955355311484491b26571b0041cb38c50f0a2e269
|
7
|
+
data.tar.gz: 170e5593fe2cf93d1e2500927baaec31747d5670fd7bb4113619d6ba65e35fdabcbc48201cdc7213a696ea565772218111f95575945c3ad62e7b5554dda852c9
|
data/README.md
CHANGED
@@ -24,11 +24,13 @@ This gem assumes that you're running Rails 4 or greater, therefore the `bin` fil
|
|
24
24
|
|
25
25
|
### Update your model schema
|
26
26
|
|
27
|
-
In order to keep your database records in sync with Salesforce, the table will need to store a reference to its associated Salesforce record. A generator is included to trivially add
|
27
|
+
In order to keep your database records in sync with Salesforce, the table will need to store a reference to its associated Salesforce record. A generator is included to trivially add a generic `salesforce_id` column to your tables:
|
28
28
|
|
29
29
|
$ bundle exec rails g restforce:migration MyModel
|
30
30
|
$ bundle exec rake db:migrate
|
31
31
|
|
32
|
+
If you need to activate multiple Salesforce mappings within a single model, you can do this with scoped column names. For example, if your Salesforce object types are named "Animal__c" and "Cat__c", `Restforce::DB` will look for columns named `animal_salesforce_id` and `cat_salesforce_id`.
|
33
|
+
|
32
34
|
### Register a mapping
|
33
35
|
|
34
36
|
To register a Salesforce mapping in an `ActiveRecord` model, you'll need to add a few lines of DSL-style code to the relevant class definitions:
|
@@ -48,7 +50,6 @@ class Restaurant < ActiveRecord::Base
|
|
48
50
|
associations: {
|
49
51
|
specialty: "Specialty__c",
|
50
52
|
},
|
51
|
-
root: true,
|
52
53
|
)
|
53
54
|
|
54
55
|
end
|
@@ -60,6 +61,7 @@ class Dish < ActiveRecord::Base
|
|
60
61
|
|
61
62
|
sync_with(
|
62
63
|
"Dish__c",
|
64
|
+
through: "Specialty__c",
|
63
65
|
fields: {
|
64
66
|
name: "Name",
|
65
67
|
ingredient: "Ingredient__c",
|
@@ -74,7 +76,7 @@ There are a few options to be aware of when describing a mapping:
|
|
74
76
|
|
75
77
|
- `fields`: These are direct field-to-field mappings. The keys should line up with your ActiveRecord attribute names, while the values should line up with the matching field names in Salesforce.
|
76
78
|
- `associations`: These are mappings of ActiveRecord associations to Salesforce lookups. Associations defined here will be built as part of the creation process for a newly-synced record.
|
77
|
-
- `
|
79
|
+
- `through`: This should be set for models which are created through an association. It references the lookup field on its parent's Salesforce object type.
|
78
80
|
|
79
81
|
### Run the daemon
|
80
82
|
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Restforce
|
2
|
+
|
3
|
+
module DB
|
4
|
+
|
5
|
+
module Associations
|
6
|
+
|
7
|
+
# Restforce::DB::Associations::ActiveRecord is a utility class which
|
8
|
+
# encapsulates the logic for creating/populating a one-to-one association
|
9
|
+
#
|
10
|
+
class ActiveRecord
|
11
|
+
|
12
|
+
attr_reader :associated
|
13
|
+
|
14
|
+
# Public: Initialize a new Restforce::DB::Associations::ActiveRecord.
|
15
|
+
#
|
16
|
+
# record - The base ActiveRecord::Base instance for which the
|
17
|
+
# association should be built.
|
18
|
+
# association - The name of the association which should be built.
|
19
|
+
def initialize(record, association)
|
20
|
+
@record = record
|
21
|
+
@associated = record.association(association).build
|
22
|
+
end
|
23
|
+
|
24
|
+
# Public: Build the associated record from the attributes found on the
|
25
|
+
# passed Salesforce record's lookups.
|
26
|
+
#
|
27
|
+
# from_record - A Hashie::Mash representing a base Salesforce record.
|
28
|
+
#
|
29
|
+
# Returns the constructed associated record.
|
30
|
+
def build(from_record)
|
31
|
+
Mapping[associated.class].each do |mapping|
|
32
|
+
lookup_id = from_record[mapping.through]
|
33
|
+
apply(mapping, lookup_id)
|
34
|
+
end
|
35
|
+
|
36
|
+
associated
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# Internal: Assemble the associated record, using the data from the
|
42
|
+
# Salesforce record corresponding to a specific lookup ID.
|
43
|
+
#
|
44
|
+
# TODO: With some refactoring, this should be possible to handle as a
|
45
|
+
# recursive call to the configured Mapping's database record type. Right
|
46
|
+
# now, nested associations are unhandled.
|
47
|
+
#
|
48
|
+
# mapping - A Restforce::DB::Mapping.
|
49
|
+
# lookup_id - A Salesforce ID corresponding to the record type in the
|
50
|
+
# passed Mapping.
|
51
|
+
#
|
52
|
+
# Returns nothing.
|
53
|
+
def apply(mapping, lookup_id)
|
54
|
+
return if lookup_id.nil?
|
55
|
+
|
56
|
+
salesforce_instance = mapping.salesforce_record_type.find(lookup_id)
|
57
|
+
attributes = mapping.convert(associated.class, salesforce_instance.attributes)
|
58
|
+
|
59
|
+
associated.assign_attributes(attributes.merge(mapping.lookup_column => lookup_id))
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -13,14 +13,14 @@ module Restforce
|
|
13
13
|
#
|
14
14
|
# Returns a String.
|
15
15
|
def id
|
16
|
-
@record.
|
16
|
+
@record.send(@mapping.lookup_column)
|
17
17
|
end
|
18
18
|
|
19
19
|
# Public: Has this record been synced to a Salesforce record?
|
20
20
|
#
|
21
21
|
# Returns a Boolean.
|
22
22
|
def synced?
|
23
|
-
@record.
|
23
|
+
@record.send(:"#{@mapping.lookup_column}?")
|
24
24
|
end
|
25
25
|
|
26
26
|
# Public: Get the time of the last update to this record.
|
data/lib/restforce/db/mapping.rb
CHANGED
@@ -7,6 +7,8 @@ module Restforce
|
|
7
7
|
# attributes from one to the other.
|
8
8
|
class Mapping
|
9
9
|
|
10
|
+
class InvalidMappingError < StandardError; end
|
11
|
+
|
10
12
|
class << self
|
11
13
|
|
12
14
|
include Enumerable
|
@@ -27,8 +29,10 @@ module Restforce
|
|
27
29
|
# Yields one Mapping for each database-to-Salesforce mapping.
|
28
30
|
# Returns nothing.
|
29
31
|
def each
|
30
|
-
collection.each do |
|
31
|
-
|
32
|
+
collection.each do |_, mappings|
|
33
|
+
mappings.each do |mapping|
|
34
|
+
yield mapping
|
35
|
+
end
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
@@ -37,12 +41,14 @@ module Restforce
|
|
37
41
|
self.collection ||= {}
|
38
42
|
|
39
43
|
attr_reader(
|
44
|
+
:database_model,
|
45
|
+
:salesforce_model,
|
40
46
|
:database_record_type,
|
41
47
|
:salesforce_record_type,
|
42
48
|
:associations,
|
43
49
|
:conditions,
|
50
|
+
:through,
|
44
51
|
)
|
45
|
-
attr_writer :root
|
46
52
|
|
47
53
|
# Public: Initialize a new Restforce::DB::Mapping.
|
48
54
|
#
|
@@ -61,20 +67,24 @@ module Restforce
|
|
61
67
|
# :root - A Boolean reflecting whether or not
|
62
68
|
# this is a root-level mapping.
|
63
69
|
def initialize(database_model, salesforce_model, options = {})
|
70
|
+
@database_model = database_model
|
71
|
+
@salesforce_model = salesforce_model
|
72
|
+
|
64
73
|
@database_record_type = RecordTypes::ActiveRecord.new(database_model, self)
|
65
74
|
@salesforce_record_type = RecordTypes::Salesforce.new(salesforce_model, self)
|
66
75
|
|
67
76
|
@fields = options.fetch(:fields) { {} }
|
68
77
|
@associations = options.fetch(:associations) { {} }
|
69
78
|
@conditions = options.fetch(:conditions) { [] }
|
70
|
-
@
|
79
|
+
@through = options.fetch(:through) { nil }
|
71
80
|
|
72
81
|
@types = {
|
73
82
|
database_model => :database,
|
74
83
|
salesforce_model => :salesforce,
|
75
84
|
}
|
76
85
|
|
77
|
-
self.class.collection[database_model]
|
86
|
+
self.class.collection[database_model] ||= []
|
87
|
+
self.class.collection[database_model] << self
|
78
88
|
end
|
79
89
|
|
80
90
|
# Public: Get a list of the relevant Salesforce field names for this
|
@@ -82,7 +92,7 @@ module Restforce
|
|
82
92
|
#
|
83
93
|
# Returns an Array.
|
84
94
|
def salesforce_fields
|
85
|
-
@fields.values + @associations.values
|
95
|
+
@fields.values + @associations.values.flatten
|
86
96
|
end
|
87
97
|
|
88
98
|
# Public: Get a list of the relevant database column names for this
|
@@ -93,12 +103,32 @@ module Restforce
|
|
93
103
|
@fields.keys
|
94
104
|
end
|
95
105
|
|
106
|
+
# Public: Get the name of the database column which should be used to
|
107
|
+
# store the Salesforce lookup ID.
|
108
|
+
#
|
109
|
+
# Raises an InvalidMappingError if no database column exists.
|
110
|
+
# Returns a Symbol.
|
111
|
+
def lookup_column
|
112
|
+
@lookup_column ||= begin
|
113
|
+
column_prefix = salesforce_model.underscore.chomp("__c")
|
114
|
+
column = :"#{column_prefix}_salesforce_id"
|
115
|
+
|
116
|
+
if database_record_type.column?(column)
|
117
|
+
column
|
118
|
+
elsif database_record_type.column?(:salesforce_id)
|
119
|
+
:salesforce_id
|
120
|
+
else
|
121
|
+
raise InvalidMappingError, "#{database_model} must define a Salesforce ID column"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
96
126
|
# Public: Is this a root-level mapping? Used to determine whether or not
|
97
127
|
# to trigger the creation of "missing" database records.
|
98
128
|
#
|
99
129
|
# Returns a Boolean.
|
100
130
|
def root?
|
101
|
-
@
|
131
|
+
@through.nil?
|
102
132
|
end
|
103
133
|
|
104
134
|
# Public: Build a normalized Hash of attributes from the appropriate set
|
@@ -19,11 +19,10 @@ module Restforce
|
|
19
19
|
def create!(from_record)
|
20
20
|
attributes = @mapping.convert(@record_type, from_record.attributes)
|
21
21
|
|
22
|
-
record = @record_type.new(attributes.merge(
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
build_association associated, lookup_id
|
22
|
+
record = @record_type.new(attributes.merge(@mapping.lookup_column => from_record.id))
|
23
|
+
|
24
|
+
associations = @mapping.associations.map do |association, _|
|
25
|
+
Associations::ActiveRecord.new(record, association).build(from_record.record)
|
27
26
|
end
|
28
27
|
|
29
28
|
record.transaction do
|
@@ -44,7 +43,7 @@ module Restforce
|
|
44
43
|
#
|
45
44
|
# Returns nil or a Restforce::DB::Instances::ActiveRecord instance.
|
46
45
|
def find(id)
|
47
|
-
record = @record_type.find_by(
|
46
|
+
record = @record_type.find_by(@mapping.lookup_column => id)
|
48
47
|
return nil unless record
|
49
48
|
|
50
49
|
Instances::ActiveRecord.new(@record_type, record, @mapping)
|
@@ -72,6 +71,19 @@ module Restforce
|
|
72
71
|
end
|
73
72
|
end
|
74
73
|
|
74
|
+
# Public: Does the model represented by this record type have a column
|
75
|
+
# with the requested name?
|
76
|
+
#
|
77
|
+
# column - A Symbol column name.
|
78
|
+
#
|
79
|
+
# Returns a Boolean.
|
80
|
+
def column?(column)
|
81
|
+
::ActiveRecord::Base.connection.column_exists?(
|
82
|
+
@record_type.table_name,
|
83
|
+
column,
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
75
87
|
private
|
76
88
|
|
77
89
|
# Internal: Has this Salesforce record already been linked to a database
|
@@ -81,32 +93,7 @@ module Restforce
|
|
81
93
|
#
|
82
94
|
# Returns a Boolean.
|
83
95
|
def synced?(record)
|
84
|
-
@record_type.exists?(
|
85
|
-
end
|
86
|
-
|
87
|
-
# Internal: Assemble an associated record, using the data from the
|
88
|
-
# Salesforce record corresponding to a specific lookup ID.
|
89
|
-
#
|
90
|
-
# TODO: With some refactoring using ActiveRecord inflections, this
|
91
|
-
# should be possible to handle as a recursive call to the configured
|
92
|
-
# Mapping's database record type. Right now, nested associations are
|
93
|
-
# ignored.
|
94
|
-
#
|
95
|
-
# associated - The associated database record.
|
96
|
-
# lookup_id - A Salesforce ID corresponding to the record type in the
|
97
|
-
# Mapping defined for the associated database model.
|
98
|
-
#
|
99
|
-
# Returns the associated ActiveRecord instance.
|
100
|
-
def build_association(associated, lookup_id)
|
101
|
-
return if lookup_id.nil?
|
102
|
-
|
103
|
-
mapping = Mapping[associated.class]
|
104
|
-
|
105
|
-
salesforce_instance = mapping.salesforce_record_type.find(lookup_id)
|
106
|
-
attributes = mapping.convert(associated.class, salesforce_instance.attributes)
|
107
|
-
|
108
|
-
associated.assign_attributes(attributes.merge(salesforce_id: lookup_id))
|
109
|
-
associated
|
96
|
+
@record_type.exists?(@mapping.lookup_column => record.id)
|
110
97
|
end
|
111
98
|
|
112
99
|
end
|
@@ -20,7 +20,7 @@ module Restforce
|
|
20
20
|
attributes = @mapping.convert(@record_type, from_record.attributes)
|
21
21
|
record_id = DB.client.create!(@record_type, attributes)
|
22
22
|
|
23
|
-
from_record.update!(
|
23
|
+
from_record.update!(@mapping.lookup_column => record_id).after_sync
|
24
24
|
|
25
25
|
find(record_id)
|
26
26
|
end
|
data/lib/restforce/db/version.rb
CHANGED
data/lib/restforce/db/worker.rb
CHANGED
@@ -99,8 +99,8 @@ module Restforce
|
|
99
99
|
# Returns nothing.
|
100
100
|
def perform
|
101
101
|
track do
|
102
|
-
Restforce::DB::Mapping.each do |
|
103
|
-
synchronize
|
102
|
+
Restforce::DB::Mapping.each do |mapping|
|
103
|
+
synchronize mapping
|
104
104
|
end
|
105
105
|
end
|
106
106
|
end
|
@@ -132,12 +132,11 @@ module Restforce
|
|
132
132
|
# Internal: Synchronize the objects in the database and Salesforce
|
133
133
|
# corresponding to the passed record type.
|
134
134
|
#
|
135
|
-
# name - The String name of the record type to synchronize.
|
136
135
|
# mapping - A Restforce::DB::Mapping.
|
137
136
|
#
|
138
137
|
# Returns a Boolean.
|
139
|
-
def synchronize(
|
140
|
-
log " SYNCHRONIZE #{name}"
|
138
|
+
def synchronize(mapping)
|
139
|
+
log " SYNCHRONIZE #{mapping.database_model.name} with #{mapping.salesforce_model}"
|
141
140
|
runtime = Benchmark.realtime { mapping.synchronizer.run(delay: @delay) }
|
142
141
|
log format(" COMPLETE after %.4f", runtime)
|
143
142
|
|
data/lib/restforce/db.rb
CHANGED
@@ -6,6 +6,8 @@ require "restforce/extensions"
|
|
6
6
|
require "restforce/db/version"
|
7
7
|
require "restforce/db/configuration"
|
8
8
|
|
9
|
+
require "restforce/db/associations/active_record"
|
10
|
+
|
9
11
|
require "restforce/db/instances/base"
|
10
12
|
require "restforce/db/instances/active_record"
|
11
13
|
require "restforce/db/instances/salesforce"
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative "../../../../test_helper"
|
2
|
+
|
3
|
+
describe Restforce::DB::Associations::ActiveRecord do
|
4
|
+
|
5
|
+
configure!
|
6
|
+
mappings!
|
7
|
+
|
8
|
+
let(:associations) { { user: "Friend__c" } }
|
9
|
+
let(:record) { CustomObject.new }
|
10
|
+
let(:association) { Restforce::DB::Associations::ActiveRecord.new(record, :user) }
|
11
|
+
|
12
|
+
describe "#build" do
|
13
|
+
let(:association_id) { "a001a000001EFRIEND" }
|
14
|
+
let(:salesforce_record) { Hashie::Mash.new("Friend__c" => association_id) }
|
15
|
+
let(:associated_record) { association.build(salesforce_record) }
|
16
|
+
|
17
|
+
before do
|
18
|
+
mapping = Restforce::DB::Mapping.new(
|
19
|
+
User,
|
20
|
+
"Contact",
|
21
|
+
through: "Friend__c",
|
22
|
+
fields: { email: "Email" },
|
23
|
+
)
|
24
|
+
salesforce_record_type = mapping.salesforce_record_type
|
25
|
+
|
26
|
+
# Stub out the `#find` method on the record type
|
27
|
+
def salesforce_record_type.find(id)
|
28
|
+
Struct.new(:id, :last_update, :attributes).new(
|
29
|
+
id,
|
30
|
+
Time.now,
|
31
|
+
email: "somebody@example.com",
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "creates the associated record from the related Salesforce record's attributes" do
|
37
|
+
expect(associated_record).to_not_be_nil
|
38
|
+
expect(associated_record.email).to_equal("somebody@example.com")
|
39
|
+
expect(associated_record.salesforce_id).to_equal(association_id)
|
40
|
+
expect(associated_record).to_equal record.user
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -27,14 +27,14 @@ describe Restforce::DB::Mapping do
|
|
27
27
|
# Restforce::DB::Mapping actually implements Enumerable, so we're just
|
28
28
|
# going with a trivially testable portion of the Enumerable API.
|
29
29
|
it "yields the registered record types" do
|
30
|
-
expect(Restforce::DB::Mapping.first).to_equal
|
30
|
+
expect(Restforce::DB::Mapping.first).to_equal mapping
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
describe "#initialize" do
|
35
35
|
|
36
36
|
it "adds the mapping to the global collection" do
|
37
|
-
expect(Restforce::DB::Mapping[database_model]).to_equal mapping
|
37
|
+
expect(Restforce::DB::Mapping[database_model]).to_equal [mapping]
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -56,6 +56,46 @@ describe Restforce::DB::Mapping do
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
+
describe "#lookup_column" do
|
60
|
+
let(:db) { mapping.database_record_type }
|
61
|
+
|
62
|
+
describe "when the database table has a column matching the Salesforce model" do
|
63
|
+
before do
|
64
|
+
def db.column?(_)
|
65
|
+
true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it "returns the explicit column name" do
|
70
|
+
expect(mapping.lookup_column).to_equal(:custom_object_salesforce_id)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "when the database table has a generic salesforce ID column" do
|
75
|
+
before do
|
76
|
+
def db.column?(column)
|
77
|
+
column == :salesforce_id
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it "returns the generic column name" do
|
82
|
+
expect(mapping.lookup_column).to_equal(:salesforce_id)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "when the database table has no salesforce ID column" do
|
87
|
+
before do
|
88
|
+
def db.column?(_)
|
89
|
+
false
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "raises an error" do
|
94
|
+
expect(-> { mapping.lookup_column }).to_raise Restforce::DB::Mapping::InvalidMappingError
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
59
99
|
describe "#attributes" do
|
60
100
|
|
61
101
|
it "builds a normalized Hash of database attribute values" do
|
@@ -23,8 +23,7 @@ describe Restforce::DB::Model do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
it "creates a mapping in Restforce::DB::Mapping" do
|
26
|
-
expect(Restforce::DB::Mapping[database_model])
|
27
|
-
.to_be_instance_of(Restforce::DB::Mapping)
|
26
|
+
expect(Restforce::DB::Mapping[database_model]).to_not_be :empty?
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
@@ -79,7 +79,12 @@ describe Restforce::DB::RecordTypes::ActiveRecord do
|
|
79
79
|
let(:associations) { { user: "Friend__c" } }
|
80
80
|
|
81
81
|
before do
|
82
|
-
mapping = Restforce::DB::Mapping.new(
|
82
|
+
mapping = Restforce::DB::Mapping.new(
|
83
|
+
User,
|
84
|
+
"Contact",
|
85
|
+
through: "Friend__c",
|
86
|
+
fields: { email: "Email" },
|
87
|
+
)
|
83
88
|
salesforce_record_type = mapping.salesforce_record_type
|
84
89
|
|
85
90
|
# Stub out the `#find` method on the record type
|
data/test/support/utilities.rb
CHANGED
@@ -18,11 +18,12 @@ def mappings!
|
|
18
18
|
let(:fields) { { name: "Name", example: "Example_Field__c" } }
|
19
19
|
let(:associations) { {} }
|
20
20
|
let(:conditions) { [] }
|
21
|
+
let(:through) { nil }
|
21
22
|
let!(:mapping) do
|
22
23
|
Restforce::DB::Mapping.new(
|
23
24
|
database_model,
|
24
25
|
salesforce_model,
|
25
|
-
|
26
|
+
through: through,
|
26
27
|
fields: fields,
|
27
28
|
associations: associations,
|
28
29
|
conditions: conditions,
|
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: 0.
|
4
|
+
version: 0.4.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-04-
|
11
|
+
date: 2015-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -220,6 +220,7 @@ files:
|
|
220
220
|
- lib/generators/templates/migration.rb.tt
|
221
221
|
- lib/generators/templates/script
|
222
222
|
- lib/restforce/db.rb
|
223
|
+
- lib/restforce/db/associations/active_record.rb
|
223
224
|
- lib/restforce/db/command.rb
|
224
225
|
- lib/restforce/db/configuration.rb
|
225
226
|
- lib/restforce/db/instances/active_record.rb
|
@@ -252,6 +253,7 @@ files:
|
|
252
253
|
- test/cassettes/Restforce_DB_Synchronizer/_run/given_an_existing_Salesforce_record/for_a_non-root_mapping/does_not_create_a_database_record.yml
|
253
254
|
- test/cassettes/Restforce_DB_Synchronizer/_run/given_an_existing_Salesforce_record/for_a_root_mapping/creates_a_matching_database_record.yml
|
254
255
|
- test/cassettes/Restforce_DB_Synchronizer/_run/given_an_existing_database_record/populates_Salesforce_with_the_new_record.yml
|
256
|
+
- test/lib/restforce/db/associations/active_record_test.rb
|
255
257
|
- test/lib/restforce/db/configuration_test.rb
|
256
258
|
- test/lib/restforce/db/instances/active_record_test.rb
|
257
259
|
- test/lib/restforce/db/instances/salesforce_test.rb
|