Class: Salesforce::Sql::App

Inherits:
Object
  • Object
show all
Defined in:
lib/salesforce/sql/app.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(credentials) ⇒ App

Returns a new instance of App.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/salesforce/sql/app.rb', line 9

def initialize credentials

  # Login credentials
  @restforce_client =  credentials
  @salesforce_bulk_client =  credentials[:username], credentials[:password], credentials[:host]
  @username = credentials[:username]

  # Default variables:
  @bulk_api_step = 10000
  @debug = false
  @step = 100
  @default_ignore_fields = [
    'Id',
    'IsDeleted',
    'MasterRecordId',
    'ParentId',
    'OwnerId',
    'CreatedById',
    'SetupOwnerId',
    'CreatedDate',
    'LastModifiedDate',
    'LastModifiedById', 
    'SystemModstamp',
    'LastActivityDate',
  ]

end

Instance Attribute Details

#debugObject

Returns the value of attribute debug.



5
6
7
# File 'lib/salesforce/sql/app.rb', line 5

def debug
  @debug
end

#stepObject

Returns the value of attribute step.



7
8
9
# File 'lib/salesforce/sql/app.rb', line 7

def step
  @step
end

#usernameObject

Returns the value of attribute username.



6
7
8
# File 'lib/salesforce/sql/app.rb', line 6

def username
  @username
end

Instance Method Details

#copy_object(source:, object:, object_ids: [], ignore_fields: [], dependencies: []) ⇒ Object

Description: Copy an object from one source to target Parameters:

object: The object to copy
object_ids: An array of object ids to limit the query
ignore_fields: An array of fields to ignore
dependencies: When trying to copy a TABLE with DEPENDENCIES
  dependency_object: The DEPENDENCY object name
  dependency_object_pk: the DEPENENCY field to be used as primary key 
  object_fk_field: The foreign key field name in the TABLE


112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/salesforce/sql/app.rb', line 112

def copy_object source:, object:, object_ids: [], ignore_fields: [], dependencies: []

  count_before = self.query("Select count(Id) from #{object}").first['expr0']

  # Remove well known problematic fields and merge them with user requirements:
  ignore_fields = (ignore_fields + @default_ignore_fields).uniq
  
  # Get all the fields from source and destination removing __pc and calculated ones
  source_object_fields = source.get_fields object
  target_object_fields = self.get_fields object

  # Get common fields
  object_fields = source_object_fields & target_object_fields

  # Get all the records from the source sandbox and store them in bulk_import_records
  bulk_import_records = source.query "Select #{object_fields.join(',')} FROM #{object}", object_ids

  # Dependencies ID Matching:
  dependencies.each do |dep|

    # Export the dependency object ids from the source sandbox
    dependency_ids = bulk_import_records.map{|row| row[dep[:object_fk_field]]}.compact.sort.uniq

    # Use those Ids to get the object records from source including the dependency_object_pk
    source_object = source.query "Select Id,#{dep[:dependency_object_pk]} FROM #{dep[:dependency_object]}", dependency_ids

    # Get the dependency_object_pk values and export the IDs from the target object
    dependency_object_pk_values = source_object.map {|row| row[dep[:dependency_object_pk]].gsub("'", %q(\\\'))}
    target_object = self.query_select_in "Select Id,#{dep[:dependency_object_pk]} FROM #{dep[:dependency_object]} WHERE #{dep[:dependency_object_pk]}", dependency_object_pk_values

    # Now we have source_object and target_object ids and values, we can do the mapping on bulk_import_records
    bulk_import_records.map! do |record|

      # If the :object_fk_field is nil, then there is no reference to map and we import the record as itis
      next record if record[dep[:object_fk_field]].nil?

      # Grab the source dependency item for this record using the :object_fk_field id, if the source item doesn't exist, don't insert the record
      source_item = source_object.select {|row| row['Id'] == record[dep[:object_fk_field]] }
      next if source_item.empty?

      # Grab the target dependency item for this record using the :dependency_object_pk, if the target item doesnt exist, don't insert the record
      target_item = target_object.select {|row| row[dep[:dependency_object_pk]] == source_item.first[dep[:dependency_object_pk]]}
      next if target_item.empty?

      # The actual mapping
      record[dep[:object_fk_field]] = target_item.first['Id']
      record
    end

    bulk_import_records.compact!
  end

  # If the object is an attachment, then we can't use bulk api:w
  if object == "Attachment"

    attachment_ignore_fields = ignore_fields.clone
    attachment_ignore_fields.delete 'isPrivate'
    attachment_ignore_fields.delete 'ParentId'
    attachment_ignore_fields << 'BodyLength'

    print_debug "Importing #{bulk_import_records.size} attachments"

    bulk_import_records.each do |att|
      att['Body'] = Base64::encode64(att.Body)
      attachment_ignore_fields.each {|f| att.delete f}
      @restforce_client.create('Attachment',att)
    end
    count_after = self.query("Select count(Id) from #{object}").first['expr0']

    return count_after - count_before

  end

  # Remove ignored fields
  bulk_import_records.each do |row|
    ignore_fields.each {|f| row.delete f}
  end

  print_debug "#{bulk_import_records.size} #{object} records added to import on #{self.username}"

  # Import the data using salesforce_bulk
  if !bulk_import_records.empty?
    bulk_insert object, bulk_import_records
  end
  count_after = self.query("Select count(Id) from #{object}").first['expr0']

  count_after - count_before

end

#delete(object) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/salesforce/sql/app.rb', line 86

def delete object

  count_before = self.query("Select count(Id) from #{object}").first['expr0']

  query = "Select Id FROM #{object}" 
  bulk_delete_records = normalize_query @restforce_client.query(query)

  print_debug "#{bulk_delete_records.size} #{object} records added to delete on #{self.username}"

  bulk_delete object, bulk_delete_records if !bulk_delete_records.empty?
  count_after = self.query("Select count(Id) from #{object}").first['expr0']

  count_before - count_after

end

#get_fields(object) ⇒ Object



37
38
39
40
41
42
43
44
# File 'lib/salesforce/sql/app.rb', line 37

def get_fields object

  fields = @restforce_client.describe(object)['fields'].select do |field| 
    field['name'][-4..-1] != '__pc' && field['calculated'] != true  
  end
  fields.map {|f| f['name']}

end

#insert(object, records) ⇒ Object



202
203
204
205
206
207
# File 'lib/salesforce/sql/app.rb', line 202

def insert object, records
  count_before = self.query("Select count(Id) from #{object}").first['expr0']
  bulk_insert object, records
  count_after = self.query("Select count(Id) from #{object}").first['expr0']
  count_after - count_before
end

#query(query, ids = []) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/salesforce/sql/app.rb', line 65

def query query, ids = []

  retval = []
  if ids.empty?
    retval = normalize_query @restforce_client.query(query)
  else
    (0..(ids.size-1)).step(@step).each do |n|

      # Create the query
      ids_string = ids[n..(n+@step-1)].map {|i| "'#{i}'"}.join ','
      stepped_query =  query + " WHERE Id IN (#{ids_string})" 

      # run it and add it to the result
      retval += normalize_query @restforce_client.query(stepped_query)
    end
  end

  retval

end

#query_select_in(query, ids = []) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/salesforce/sql/app.rb', line 46

def query_select_in query, ids = []
  retval = []
  if ids.empty?
    retval = normalize_query @restforce_client.query(query)
  else
    (0..(ids.size-1)).step(@step).each do |n|

      # Create the query
      ids_string = ids[n..(n+@step-1)].map {|i| "'#{i}'"}.join ','
      stepped_query =  query + " IN (#{ids_string})" 

      # run it and add it to the result
      retval += normalize_query @restforce_client.query(stepped_query)
    end
  end

  retval
end