If you’re inserting records from R you may want to turn off the assignment rules or even bypass duplicate rules and alerts to save records. Beginning in Version 0.1.3 of the salesforcer package many functions have a control argument that will allow you to fine tune the behavior of calls to the Salesforce APIs. This vignette will introduce the different options you can control and how to pass them into the salesforcer functions you’re already familiar with.
+
+
+The new control argument
+
This new feature can be seen in the sf_create (and many other functions) as control=list(...). The dots mean that you can pass any number of controls directly into the function. For example, the following code will create a record, but prevent its creation from showing up in the Chatter feeds by setting the DisableFeedTrackingHeader.
You will notice that the argument DisableFeedTrackingHeader can be included right into the function without any documentation existing for it in the sf_create function. This is because the dots (...) allow you to pass over a dozen different control parameters and that documentation would be tedious to create and maintain over multiple functions in the package. However, you will notice in the documentation entry for the control argument there is a link to a function called sf_control which you can use to directly to pass into control or simply to review its documentation of all the possible control parameters and their defaults. This is where you can review the various control options in more detail before trying to set them.
+
You may have also noticed that the argument DisableFeedTrackingHeader was formatted as a list with an element inside called disableFeedTracking set to TRUE. This may seem redundant but there are two reasons for this. First, this is exactly how the Salesforce APIs documents these options, which are typically referred to as “headers” because they are passed as a named header of the HTTP request and then the header fields and values are provided for that header. Second, some headers have multiple fields and values so a list is the only way to provide multiple named fields and values under a single header entity. For example, the DuplicateRuleHeader, which controls whether the duplicate rules can be overridden when inserting records from the API, has three fields: allowSave, includeRecordDetails, and runAsCurrentUser. Supplying all three requires a list-like structure, which may seem redundant in other cases, but is necessary to follow.
Finally, you will notice in the example call that the api_type argument is set to “SOAP”. This is because the DisableFeedTrackingHeader is a control that is only available when making calls via the SOAP API. You will receive a warning when trying to set control parameters for APIs or operations that do not recognize that control. For example, the following code tries to set the BatchRetryHeader for a call to the SOAP API which does not acknowledge that control. That control is only used with the Bulk 1.0 API since its records as submitted in batches and automatic retry can be controlled.
If this type of control structure is new to you, take a look at the documentation for the glm and glm.control functions. The way these two functions behave is exactly how functions like sf_create and sf_control work with each other. As demonstrated above you can pass any number of arbitrary controls into the function and they are all gathered up into the control by control = list(...). However, you can specify the control directly like this:
+Backwards compatibility for all_or_none and other named arguments
+
You may already be taking advantage of the all_or_none or line_ending arguments which are control arguments that were explicity included in functions. These argument essentially hard coded values to pass the AllOrNoneHeader and LineEndingHeader control parameters. Starting with the 0.1.3 release it is no longer necessary and preferable not to have an argument like all_or_none listed explicity as an argument since it can be provided in the control argument. Note: the all_or_none argument and other explicit control arguments will still be available in salesforcer 0.1.3 but will provide a deprecated warning. They will be removed in the next CRAN release of the package so it will be important to update your code now if you are explicitly passing these arguments and see a deprecation warning.
+
+
+
+Reference Links
+
Below is a list of links that go directly to the control arguments (a.k.a headers) for the different APIs. I highly recommend reading this documentation before setting a control parameter in R so you know exactly what the behavior will be and how to specify it in R. You may notice that some controls are not included in the R package. Some may be added in the future if requested and some will not be added given the scope of the package. One final note is that some arguments in the REST API, like the “All or None” behavior is not a header, but a parameter in the API call. For this reason you will not see it listed in the REST API Headers section, but it is set in this R package using the AllOrNoneHeader argument in sf_control just to provide consistency between the SOAP and REST APIs. It would be confusing to have two arguments named differently, one for each API, but to do the exact same thing from R. For this reason, many of the control arguments match exactly as they are listed in the SOAP API, but can be used across other APIs even if not exactly written that way in the Salesforce documentation referenced below.
Note that we must set the API version here because calls to session will not create a new sessionId and then we are stuck with version 35.0 (the default from RForcecom::rforcecom.login). Some functions in salesforcer implement API calls that are only available after version 35.0.
There are some differences in the way each API returns response information; however, the end result is exactly the same for these two calls. Also, note that this package utilizes the Bulk 2.0 API for most bulk calls except for bulk queries since Salesforce has not yet implemented it in 2.0.
Here is a simple workflow of adding, querying, and deleting records using the Bulk 1.0 API.
If you prefer to be more precise about collecting and formatting the field data you can work directly with the nested lists that the APIs return. In this example we look at the picklist values of fields on the Account object.
Where the Metadata API really shines is when it comes to CRUD operations on metadata. In this example we will create an object, add fields to it, then delete that object.
Note that newly created custom fields are not editable by default, meaning that you will not be able to insert records into them until updating the field level security of your user profile. Run the following code to determine the user profiles in your org and updating the field permissions on an object that you may have created with the example code above.
The object_name argument, required for bulk queries, will be inferred if left blank, making it no longer a required argument
+
Almost all functions in the package now have a control argument and dots (...) which allows for more than a dozen different control parameters listed in sf_control() to be fed into existing function calls to tweak the default behavior. For example, if you would like to override duplicate rules then you can adjust the DuplicateRuleHeader. If you would like to have certain assignment rule run on newly created records, then pass in the AssignmentRuleHeader (#4, #5)
@@ -174,7 +180,9 @@
Fix bug where Username/Password authenticated sessions where not working with api_type = “Bulk 1.0”
Fix bug where Bulk 1.0 queries that timeout hit an error while trying to abort since that only supported aborting Bulk 2.0 jobs (#13)
Fix bug that had only production environment logins possible because of hard coding (@weckstm, #18)
Fix bug where four of the bulk operation options (content_type, concurrency_mode, line_ending, and column_delimiter) where not being passed down from the top level generic functions like sf_create(), sf_update(), etc. However, line_ending has now been moved into the sf_control function so it is no longer explicitly listed for bulk operations as an argument. (@mitch-niche, #23)
+
Ensure that for SOAP, REST, and Bulk 2.0 APIs the verbose argument prints out the XML or JSON along with the URL of the call so it can be replicated via cURL or some other programming language (#8)
character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request
-
-
-
...
-
other arguments passed on to sf_create_job_bulk such as
-content_type, concurrency_mode, line_ending or column_delimiter.
wait_for_results
@@ -211,6 +209,17 @@
Arg
max_attempts
integer; defines then max number attempts to check for job
completion before stopping
+
+
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
+
+
+
...
+
other arguments passed on to sf_control or sf_create_job_bulk
+such as content_type, concurrency_mode, or column_delimiter
Typically only used internally by functions when control parameters are passed
+through via dots (...), but it can be called directly to control the behavior
+of API calls. This function behaves exactly like glm.control
+for the glm function.
list; containing the allOrNone element with
+a value of TRUE or FALSE. This control specifies whether a call rolls back all changes
+unless all records are processed successfully. This control is available in
+SOAP, REST, and Metadata APIs for the following functions: sf_create,
+sf_delete, sf_update, sf_upsert, sf_create_metadata,
+sf_delete_metadata, sf_update_metadata, sf_upsert_metadata.
+For more information, read the Salesforce documentation
+here.
+
+
+
AllowFieldTruncationHeader
+
list; containing the allowFieldTruncation
+element with a value of TRUE or FALSE. This control specifies the truncation behavior
+for some field types in SOAP API version 15.0 and later for the following functions:
+sf_create, sf_update, sf_upsert. For
+more information, read the Salesforce documentation
+here.
+
+
+
AssignmentRuleHeader
+
list; containing the useDefaultRule
+element with a value of TRUE or FALSE or the assignmentRuleId element.
+This control specifies the assignment rule to use when creating or updating an
+Account, Case, or Lead for the following functions: sf_create,
+sf_update, sf_upsert. For more information, read the Salesforce documentation
+here.
+
+
+
DisableFeedTrackingHeader
+
list; containing the disableFeedTracking
+element with a value of TRUE or FALSE. This control specifies whether
+the changes made in the current call are tracked in feeds for SOAP API calls made
+with the following functions: sf_create, sf_delete,
+sf_update, sf_upsert. For more information, read the Salesforce documentation
+here.
+
+
+
DuplicateRuleHeader
+
list; containing the allowSave,
+includeRecordDetails, and runAsCurrentUser elements each with a
+value of TRUE or FALSE. This control specifies how duplicate rules should be applied
+when using the following functions: sf_create, sf_update,
+sf_upsert. For more information, read the Salesforce documentation
+here.
+
+
+
EmailHeader
+
list; containing the triggerAutoResponseEmail,
+triggerOtherEmail, and triggerUserEmail elements each with a
+value of TRUE or FALSE. This control determines if an email notification should be sent
+when a request is processed by SOAP API calls made with the following functions:
+sf_create, sf_delete, sf_update, sf_upsert,
+sf_reset_password. For more information, read the Salesforce documentation
+here.
+
+
+
LocaleOptions
+
list; containing the language element. This control
+specifies the language of the labels returned by the sf_describe_objects
+function using the SOAP API. The value must be a valid user locale (language and country), such as
+de_DE or en_GB. For more information, read the Salesforce documentation
+here.
+The list of valid user locales is available
+here.
+
+
+
MruHeader
+
list; containing the updateMru element with a value
+of TRUE or FALSE. This control indicates whether to update the list
+of most recently used items (TRUE) or not (FALSE) in the Recent Items
+section of the sidebar in the Salesforce user interface. This works for SOAP API calls
+made with the following functions: sf_create, sf_update,
+sf_upsert, sf_retrieve, sf_query. For more
+information, read the Salesforce documentation
+here.
+
+
+
OwnerChangeOptions
+
list; containing the options element.
+This control specifies the details of ownership of attachments and notes when a
+record’s owner is changed. This works for SOAP API calls made with the following functions:
+sf_update, sf_upsert. For more information, read the Salesforce documentation
+here.
+
+
+
QueryOptions
+
list; containing the batchSize element.
+This control specifies the batch size for query results . This works for SOAP or
+REST API calls made with the following functions: sf_query,
+sf_retrieve. For more information, read the Salesforce documentation
+here.
+
+
+
UserTerritoryDeleteHeader
+
list; containing the transferToUserId element.
+This control specifies a user to whom open opportunities are assigned when the current
+owner is removed from a territory. This works for the sf_delete function
+using the SOAP API. For more information, read the Salesforce documentation
+here.
+
+
+
BatchRetryHeader
+
list; containing the Sforce-Disable-Batch-Retry element.
+When you create a bulk job, the Batch Retry control lets you disable retries
+for unfinished batches included in the job. This works for most operations run through
+the Bulk 1.0 API (e.g. sf_create(., api_type = "Bulk 1.0")) or creating
+a Bulk 1.0 job with sf_create_job_bulk. For more information, read the Salesforce documentation
+here.
+
+
+
LineEndingHeader
+
list; containing the Sforce-Line-Ending element.
+When you’re creating a bulk upload job, the Line Ending control lets you
+specify whether line endings are read as line feeds (LFs) or as carriage returns
+and line feeds (CRLFs) for fields of type Text Area and Text Area (Long). This
+works for most operations run through the Bulk APIs or creating a Bulk 1.0
+job with sf_create_job_bulk. For more information, read the
+Salesforce documentation
+here.
+
+
+
PKChunkingHeader
+
list; containing the Sforce-Enable-PKChunking element.
+Use the PK Chunking control to enable automatic primary key (PK) chunking
+for a bulk query job. This works for queries run through the Bulk 1.0 API either via
+sf_query(., api_type = "Bulk 1.0")) or sf_query_bulk. For
+more information, read the Salesforce documentation
+here.
+
+
+
api_type
+
character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
+"Chatter" indicating which API to use when making the request
+
+
+
operation
+
character; a string defining the type of operation being
+performed (e.g. "insert", "update", "upsert", "delete")
+
+
+
+
+
Examples
+
# NOT RUN {
+this_control<-sf_control(DuplicateRuleHeader=list(allowSave=TRUE,
+ includeRecordDetails=FALSE,
+ runAsCurrentUser=TRUE))
+new_contact<-c(FirstName="Test", LastName="Contact-Create")
+new_record<-sf_create(new_contact, "Contact", control=this_control)
+
+# specifying the controls directly and are picked up by dots
+new_record<-sf_create(new_contact, "Contact",
+ DuplicateRuleHeader=list(allowSave=TRUE,
+ includeRecordDetails=FALSE,
+ runAsCurrentUser=TRUE))
+# }
character; the name of one Salesforce objects that the
function is operating against (e.g. "Account", "Contact", "CustomObject__c")
-
-
-
all_or_none
-
logical; allows a call to roll back all changes unless all
-records are processed successfully
api_type
character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request
+
+
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
Because the SOAP and REST calls chunk data into batches of 200 records
+the AllOrNoneHeader will only apply to the success or failure of every batch
+of records and not all records submitted to the function.
+
Examples
# NOT RUN {
-n<-3
+n<-2new_contacts<-tibble(FirstName=rep("Test", n),
LastName=paste0("Contact", 1:n))
new_contacts_result<-sf_create(new_contacts, object_name="Contact")
-new_contacts_result<-sf_create(new_contacts, object_name="Contact", api_type="REST")
+
+# add the control to allow the creation of records that might violate a duplicate rule
+new_contacts_result<-sf_create(new_contacts, object_name="Contact",
+ DuplicateRuleHeader=list(allowSave=TRUE,
+ includeRecordDetails=FALSE,
+ runAsCurrentUser=TRUE))
+
+# an example of how to specify using the Bulk 1.0 API to insert the records
+new_contacts_result<-sf_create(new_contacts, object_name="Contact", api_type="Bulk 1.0")
# }
character; being one of 'CSV', 'ZIP_CSV', 'ZIP_XML', or 'ZIP_JSON' to
-indicate the type of data being passed to the Bulk API.
+indicate the type of data being passed to the Bulk APIs. For the Bulk 2.0 API the only
+valid value (and the default) is 'CSV'.
concurrency_mode
@@ -200,14 +205,6 @@
Arg
whether batches should be completed sequentially or in parallel. Use "Serial"
only if lock contentions persist with in "Parallel" mode. Note: this argument is
only used in the Bulk 1.0 API and will be ignored in calls using the Bulk 2.0 API.
-
-
-
line_ending
-
character; indicating the line ending used for CSV job data,
-marking the end of a data row. The default is NULL meaing that the line ending
-is determined by the operating system using "CRLF" for Windows machines and
-"LF" for Unix machines. Note: this argument is only used in the Bulk 2.0 API
-and will be ignored in calls using the Bulk 1.0 API.
column_delimiter
@@ -217,6 +214,16 @@
Arg
note that this argument is only used in the Bulk 2.0 API and will be ignored
in calls using the Bulk 1.0 API.
+
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
logical; allows a call to roll back all changes unless all
-records are processed successfully
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
Examp
custom_metadata$deploymentStatus<-'Deployed'# make a description to identify this easily in the UI setup tabcustom_metadata$description<-'created by the Metadata API'
-new_custom_object<-sf_create_metadata(metadata_type='CustomObject',
- metadata=custom_metadata, verbose=TRUE)
+new_custom_object<-sf_create_metadata(metadata_type='CustomObject',
+ metadata=custom_metadata,
+ verbose=TRUE)
# adding custom fields to our object # input formatted as a list
diff --git a/docs/reference/sf_create_rest.html b/docs/reference/sf_create_rest.html
index 064558a1..62de446b 100644
--- a/docs/reference/sf_create_rest.html
+++ b/docs/reference/sf_create_rest.html
@@ -100,6 +100,9 @@
character; the name of one Salesforce objects that the
function is operating against (e.g. "Account", "Contact", "CustomObject__c")
-
-
-
all_or_none
-
logical; allows a call to roll back all changes unless all
-records are processed successfully
api_type
character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request
+
+
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
Because the SOAP and REST calls chunk data into batches of 200 records
+the AllOrNoneHeader will only apply to the success or failure of every batch
+of records and not all records submitted to the function.
+
Examples
# NOT RUN {n<-3new_contacts<-tibble(FirstName=rep("Test", n),
LastName=paste0("Contact", 1:n))
-new_contacts_result1<-sf_create(new_contacts, object_name="Contact")
-deleted_contacts_result1<-sf_delete(new_contacts_result1$id,
- object_name="Contact")
-
-new_contacts_result2<-sf_create(new_contacts, "Contact")
-deleted_contacts_result2<-sf_delete(new_contacts_result2$id,
- object_name="Contact",
- api_type="Bulk")
+new_records<-sf_create(new_contacts, object_name="Contact")
+deleted_first<-sf_delete(new_records$id[1], object_name="Contact")
+
+# add the control to do an "All or None" deletion of the remaining records
+deleted_rest<-sf_delete(new_records$id[2:3], object_name="Contact",
+ AllOrNoneHeader=list(allOrNone=TRUE))
# }
a character vector of names that we wish to read metadata for
-
all_or_none
-
logical; allows a call to roll back all changes unless all
-records are processed successfully
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request
+
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
character; the name of one Salesforce objects that the
function is operating against (e.g. "Account", "Contact", "CustomObject__c")
+
+
+
queryall
+
logical; indicating if the query recordset should include records
+that have been deleted because of a merge or delete. QueryAll will also return
+information about archived Task and Event records. QueryAll is available in API
+version 29.0 and later.
guess_types
@@ -183,30 +193,26 @@
Arg
and FALSE returns all values as character strings.
-
queryall
-
logical; indicating if the query recordset should include
-deleted and archived records (available only when querying Task and Event records)
+
api_type
+
character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
+"Chatter" indicating which API to use when making the request
-
page_size
-
numeric; a number between 200 and 2000 indicating the number of
-records per page that are returned. Speed benchmarks should be done to better
-understand the speed implications of choosing high or low values of this argument.
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
-
api_type
-
character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
-"Chatter" indicating which API to use when making the request
character; the name of one Salesforce objects that the
function is operating against (e.g. "Account", "Contact", "CustomObject__c")
+
+
+
queryall
+
logical; indicating if the query recordset should include records
+that have been deleted because of a merge or delete. QueryAll will also return
+information about archived Task and Event records. QueryAll is available in API
+version 29.0 and later.
guess_types
@@ -197,6 +207,16 @@
Arg
integer; defines then max number attempts to check for job
completion before stopping
+
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
# NOT RUN {
-# select all Ids from Account object
-ids<-sf_query_bulk(soql='SELECT Id FROM Account', object_name='Account')
+# select all Ids from Account object (up to 1000)
+ids<-sf_query_bulk(soql='SELECT Id FROM Account LIMIT 1000',
+ object_name='Account')
# }
character; the unique Salesforce Id assigned to the User
+
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
# NOT RUN {
-sf_reset_password(user_id="0056A000000ZZZaaBBB")
+# reset a user's password and ensure that an email is triggered to them
+sf_reset_password(user_id="0056A000000ZZZaaBBB",
+ EmailHeader=list(triggerAutoResponseEmail=FALSE,
+ triggerOtherEmail=FALSE,
+ triggerUserEmail=TRUE))
# }
character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request
+
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
# NOT RUN {
-my_query<-"SELECT Id, Name FROM Account LIMIT 10"
-job_info<-sf_create_job_bulk(operation='query', object='Account')
-query_info<-sf_submit_query_bulk(job_id=job_info$id, soql=my_query)
+my_query<-"SELECT Id, Name FROM Account LIMIT 1000"
+job_info<-sf_create_job_bulk(operation='query', object='Account')
+query_info<-sf_submit_query_bulk(job_id=job_info$id, soql=my_query)
# }
character; the name of one Salesforce objects that the
function is operating against (e.g. "Account", "Contact", "CustomObject__c")
-
-
-
all_or_none
-
logical; allows a call to roll back all changes unless all
-records are processed successfully
api_type
character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request
+
+
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
Because the SOAP and REST calls chunk data into batches of 200 records
+the AllOrNoneHeader will only apply to the success or failure of every batch
+of records and not all records submitted to the function.
+
Examples
# NOT RUN {
-n<-3
-new_contacts<-tibble(FirstName=rep("Test", n),
- LastName=paste0("Contact", 1:n))
-new_contacts_result<-sf_create(new_contacts, "Contact")
-
-update_contacts<-tibble(FirstName=rep("TestTest", n),
- LastName=paste0("Contact", 1:n),
- Id=new_contacts_result$id)
-updated_contacts_result1<-sf_update(update_contacts, "Contact")
-updated_contacts_result2<-sf_update(update_contacts, "Contact",
- api_type="Bulk")
+n<-2
+new_accts<-tibble(FirstName=rep("Test", n),
+ LastName=paste0("Account", 1:n))
+new_records<-sf_create(new_accts, "Account")
+
+updated_accts<-tibble(FirstName=rep("TestTest", n),
+ LastName=paste0("Account", 1:n),
+ Id=new_records$id)
+
+# update the accounts and ensure that all contacts and cases (open and closed)
+# owned by the previous account owner are transferred to the new owner
+update<-sf_update(updated_accts, "Account",
+ OwnerChangeOptions=list(options=
+ list(list(execute=TRUE,
+ type="TransferAllOwnedCases"),
+ list(execute=TRUE,
+ type="TransferOwnedOpenCases"),
+ list(execute=TRUE,
+ type="TransferContacts"))))
# }
logical; allows a call to roll back all changes unless all
-records are processed successfully
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
character; string identifying a custom field on the
object that has been set as an "External ID" field. This field is used to reference
objects during upserts to determine if the record already exists in Salesforce or not.
-
-
-
all_or_none
-
logical; allows a call to roll back all changes unless all
-records are processed successfully
api_type
character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request
+
+
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
logical; allows a call to roll back all changes unless all
-records are processed successfully
+
control
+
list; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for sf_control
diff --git a/docs/sitemap.xml b/docs/sitemap.xml
index 6478931d..269ed094 100644
--- a/docs/sitemap.xml
+++ b/docs/sitemap.xml
@@ -6,6 +6,12 @@
https://stevenmmortimer.github.io/salesforcer/reference/VERB_n.html
+
+ https://stevenmmortimer.github.io/salesforcer/reference/accepted_controls_by_api.html
+
+
+ https://stevenmmortimer.github.io/salesforcer/reference/accepted_controls_by_operation.html
+ https://stevenmmortimer.github.io/salesforcer/reference/build_metadata_xml_from_list.html
@@ -18,6 +24,9 @@
https://stevenmmortimer.github.io/salesforcer/reference/collapse_list_with_dupe_names.html
+
+ https://stevenmmortimer.github.io/salesforcer/reference/filter_valid_controls.html
+ https://stevenmmortimer.github.io/salesforcer/reference/get_os.html
@@ -117,6 +126,9 @@
https://stevenmmortimer.github.io/salesforcer/reference/remove_empty_linked_object_cols.html
+
+ https://stevenmmortimer.github.io/salesforcer/reference/return_matching_controls.html
+ https://stevenmmortimer.github.io/salesforcer/reference/rforcecom.bulkAction.html
@@ -189,6 +201,9 @@
https://stevenmmortimer.github.io/salesforcer/reference/sf_close_job_bulk.html
+
+ https://stevenmmortimer.github.io/salesforcer/reference/sf_control.html
+ https://stevenmmortimer.github.io/salesforcer/reference/sf_create.html
@@ -381,6 +396,9 @@
https://stevenmmortimer.github.io/salesforcer/articles/getting-started.html
+
+ https://stevenmmortimer.github.io/salesforcer/articles/passing-control-args.html
+ https://stevenmmortimer.github.io/salesforcer/articles/transitioning-from-RForcecom.html
diff --git a/index.Rmd b/index.Rmd
index 6f2b6aaa..d9fe3e53 100644
--- a/index.Rmd
+++ b/index.Rmd
@@ -14,7 +14,8 @@ knitr::opts_chunk$set(
[![Build Status](https://travis-ci.org/StevenMMortimer/salesforcer.svg?branch=master)](https://travis-ci.org/StevenMMortimer/salesforcer)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/StevenMMortimer/salesforcer?branch=master&svg=true)](https://ci.appveyor.com/project/StevenMMortimer/salesforcer)
-[![CRAN_Status_Badge](http://www.r-pkg.org/badges/version/salesforcer)](http://cran.r-project.org/package=salesforcer)
+[![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/salesforcer)](https://cran.r-project.org/package=salesforcer)
+[![Monthly Downloads](https://cranlogs.r-pkg.org/badges/last-month/salesforcer)](https://cran.r-project.org/package=salesforcer)
[![Coverage Status](https://codecov.io/gh/StevenMMortimer/salesforcer/branch/master/graph/badge.svg)](https://codecov.io/gh/StevenMMortimer/salesforcer?branch=master)
@@ -34,9 +35,12 @@ Package features include:
* Utilize backwards compatible functions for the **RForcecom** package, such as:
* `rforcecom.login()`, `rforcecom.getObjectDescription()`, `rforcecom.query()`, `rforcecom.create()`
* Basic utility calls (`sf_user_info()`, `sf_server_timestamp()`, `sf_list_objects()`)
+ * Passing API call control parameters such as, "All or None", "Duplicate Rule", "Assignment Rule"
+ execution and many more
## Table of Contents
* [Installation](#installation)
+ * [Vignettes](#vignettes)
* [Usage](#usage)
* [Authenticate](#authenticate)
* [Create](#create)
@@ -61,6 +65,16 @@ devtools::install_github("StevenMMortimer/salesforcer")
If you encounter a clear bug, please file a minimal reproducible example on [GitHub](https://github.com/StevenMMortimer/salesforcer/issues).
+## Vignettes
+
+The README below outlines the package functionality, but review the vignettes for
+more detailed examples on usage.
+
+ * [Getting Started](https://StevenMMortimer.github.io/salesforcer/articles/getting-started.html)
+ * [Working with Bulk API](https://StevenMMortimer.github.io/salesforcer/articles/working-with-bulk-api.html)
+ * [Transitioning from RForcecom](https://StevenMMortimer.github.io/salesforcer/articles/transitioning-from-RForcecom.html)
+ * [Passing Control Args](https://StevenMMortimer.github.io/salesforcer/articles/passing-control-args.html)
+
## Usage
### Authenticate
@@ -242,6 +256,11 @@ where we get a `tbl_df` with one row for each field on the Account object:
```{r soap-describe-object-fields}
acct_fields <- sf_describe_object_fields('Account')
acct_fields %>% select(name, label, length, soapType, type)
+
+# show the picklist selection options for the Account Type field
+acct_fields %>%
+ filter(label == "Account Type") %>%
+ .$picklistValues
```
If you prefer to be more precise about collecting and formatting the field data you
@@ -253,9 +272,10 @@ describe_obj_result <- sf_describe_objects(object_names=c('Account', 'Contact'))
# confirm that the Account object is queryable
describe_obj_result[[1]][c('label', 'queryable')]
# show the different picklist values for the Account Type field
-the_type_field <- describe_obj_result[[1]][[59]]
-the_type_field$label
-map_df(the_type_field[which(names(the_type_field) == "picklistValues")], as_tibble)
+all_fields <- describe_obj_result[[1]][names(describe_obj_result[[1]]) == "fields"]
+the_type_field_idx <- which(sapply(all_fields, FUN=function(x){x$label}) == "Account Type")
+acct_type_field <- all_fields[[the_type_field_idx]]
+map_df(acct_type_field[which(names(acct_type_field) == "picklistValues")], as_tibble)
```
It is recommended that you try out the various metadata functions `sf_read_metadata()`,
@@ -296,6 +316,30 @@ deleted_custom_object_result <- sf_delete_metadata(metadata_type = 'CustomObject
object_names = c('Custom_Account1__c'))
```
+Note that newly created custom fields are not editable by default, meaning that you
+will not be able to insert records into them until updating the field level security
+of your user profile. Run the following code to determine the user profiles in your
+org and updating the field permissions on an object that you may have created with the
+example code above.
+
+```{r metadata-crud-field-security, eval=FALSE}
+# get list of user proviles in order to get the "fullName" parameter correct in the next call
+my_queries <- list(list(type='Profile'))
+profiles_list <- sf_list_metadata(queries=my_queries)
+
+# update the field level security to "editable" for your fields
+prof_update <- sf_update_metadata(metadata_type='Profile',
+ metadata=list(fullName='Admin',
+ fieldPermissions=list(field=paste0(custom_object$fullName, '.CustomField3__c'),
+ editable='true'),
+ fieldPermissions=list(field=paste0(custom_object$fullName, '.CustomField4__c'),
+ editable='true')))
+
+# now try inserting values into that custom object's fields
+my_new_data = tibble(CustomField3__c = "Hello World", CustomField4__c = "Hello World")
+added_record <- sf_create(my_new_data, object_name = custom_object$fullName)
+```
+
```{r, include=FALSE, message = FALSE, eval=FALSE}
# There are methods as part of the REST API that will return metatdata.
#sf_describe_global()
diff --git a/man-roxygen/all_or_none.R b/man-roxygen/all_or_none.R
deleted file mode 100644
index 71579c83..00000000
--- a/man-roxygen/all_or_none.R
+++ /dev/null
@@ -1,2 +0,0 @@
-#' @param all_or_none logical; allows a call to roll back all changes unless all
-#' records are processed successfully
diff --git a/man-roxygen/control.R b/man-roxygen/control.R
new file mode 100644
index 00000000..2cc6a366
--- /dev/null
+++ b/man-roxygen/control.R
@@ -0,0 +1,3 @@
+#' @param control \code{list}; a list of parameters for controlling the behavior of
+#' the API call being used. For more information of what parameters are available
+#' look at the documentation for \code{\link{sf_control}}
diff --git a/man-roxygen/queryall.R b/man-roxygen/queryall.R
new file mode 100644
index 00000000..41148e1a
--- /dev/null
+++ b/man-roxygen/queryall.R
@@ -0,0 +1,4 @@
+#' @param queryall logical; indicating if the query recordset should include records
+#' that have been deleted because of a merge or delete. QueryAll will also return
+#' information about archived Task and Event records. QueryAll is available in API
+#' version 29.0 and later.
diff --git a/man/accepted_controls_by_api.Rd b/man/accepted_controls_by_api.Rd
new file mode 100644
index 00000000..7185ce36
--- /dev/null
+++ b/man/accepted_controls_by_api.Rd
@@ -0,0 +1,16 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils-control.R
+\name{accepted_controls_by_api}
+\alias{accepted_controls_by_api}
+\title{Return the Accepted Control Arguments by API Type}
+\usage{
+accepted_controls_by_api(api_type = c("SOAP", "REST", "Bulk 1.0",
+ "Bulk 2.0", "Metadata"))
+}
+\description{
+Return the Accepted Control Arguments by API Type
+}
+\note{
+This function is meant to be used internally. Only use when debugging.
+}
+\keyword{internal}
diff --git a/man/accepted_controls_by_operation.Rd b/man/accepted_controls_by_operation.Rd
new file mode 100644
index 00000000..04aa6b72
--- /dev/null
+++ b/man/accepted_controls_by_operation.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils-control.R
+\name{accepted_controls_by_operation}
+\alias{accepted_controls_by_operation}
+\title{Return the Accepted Control Arguments by Operation}
+\usage{
+accepted_controls_by_operation(operation = c("delete", "hardDelete",
+ "insert", "update", "upsert", "query", "queryall", "retrieve",
+ "resetPassword", "describeSObjects"))
+}
+\description{
+Return the Accepted Control Arguments by Operation
+}
+\note{
+This function is meant to be used internally. Only use when debugging.
+}
+\keyword{internal}
diff --git a/man/filter_valid_controls.Rd b/man/filter_valid_controls.Rd
new file mode 100644
index 00000000..bf0024a2
--- /dev/null
+++ b/man/filter_valid_controls.Rd
@@ -0,0 +1,15 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils-control.R
+\name{filter_valid_controls}
+\alias{filter_valid_controls}
+\title{Filter Out Control Arguments by API or Operation}
+\usage{
+filter_valid_controls(supplied, api_type = NULL, operation = NULL)
+}
+\description{
+Filter Out Control Arguments by API or Operation
+}
+\note{
+This function is meant to be used internally. Only use when debugging.
+}
+\keyword{internal}
diff --git a/man/return_matching_controls.Rd b/man/return_matching_controls.Rd
new file mode 100644
index 00000000..e93b68a1
--- /dev/null
+++ b/man/return_matching_controls.Rd
@@ -0,0 +1,15 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils-control.R
+\name{return_matching_controls}
+\alias{return_matching_controls}
+\title{Of All Args Return Ones Matching Control Arguments}
+\usage{
+return_matching_controls(args)
+}
+\description{
+Of All Args Return Ones Matching Control Arguments
+}
+\note{
+This function is meant to be used internally. Only use when debugging.
+}
+\keyword{internal}
diff --git a/man/sf_bulk_operation.Rd b/man/sf_bulk_operation.Rd
index 2f4ce6b7..50728830 100644
--- a/man/sf_bulk_operation.Rd
+++ b/man/sf_bulk_operation.Rd
@@ -7,8 +7,8 @@
sf_bulk_operation(input_data, object_name, operation = c("insert",
"delete", "upsert", "update", "hardDelete"),
external_id_fieldname = NULL, api_type = c("Bulk 1.0", "Bulk 2.0"),
- ..., wait_for_results = TRUE, interval_seconds = 3,
- max_attempts = 200, verbose = FALSE)
+ wait_for_results = TRUE, interval_seconds = 3, max_attempts = 200,
+ control = list(...), ..., verbose = FALSE)
}
\arguments{
\item{input_data}{\code{named vector}, \code{matrix}, \code{data.frame}, or
@@ -26,9 +26,6 @@ objects during upserts to determine if the record already exists in Salesforce o
\item{api_type}{character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request}
-\item{...}{other arguments passed on to \code{\link{sf_create_job_bulk}} such as
-\code{content_type}, \code{concurrency_mode}, \code{line_ending} or \code{column_delimiter}.}
-
\item{wait_for_results}{logical; indicating whether to wait for the operation to complete
so that the batch results of individual records can be obtained}
@@ -38,6 +35,13 @@ for job completion}
\item{max_attempts}{integer; defines then max number attempts to check for job
completion before stopping}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{other arguments passed on to \code{\link{sf_control}} or \code{\link{sf_create_job_bulk}}
+such as \code{content_type}, \code{concurrency_mode}, or \code{column_delimiter}}
+
\item{verbose}{logical; do you want informative messages?}
}
\value{
diff --git a/man/sf_control.Rd b/man/sf_control.Rd
new file mode 100644
index 00000000..281d41cd
--- /dev/null
+++ b/man/sf_control.Rd
@@ -0,0 +1,167 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils-control.R
+\name{sf_control}
+\alias{sf_control}
+\title{Auxiliary for Controlling Calls to Salesforce APIs}
+\usage{
+sf_control(AllOrNoneHeader = list(allOrNone = FALSE),
+ AllowFieldTruncationHeader = list(allowFieldTruncation = FALSE),
+ AssignmentRuleHeader = list(useDefaultRule = TRUE),
+ DisableFeedTrackingHeader = list(disableFeedTracking = FALSE),
+ DuplicateRuleHeader = list(allowSave = FALSE, includeRecordDetails =
+ FALSE, runAsCurrentUser = TRUE),
+ EmailHeader = list(triggerAutoResponseEmail = FALSE, triggerOtherEmail
+ = FALSE, triggerUserEmail = TRUE), LocaleOptions = list(language =
+ "en_US"), MruHeader = list(updateMru = FALSE),
+ OwnerChangeOptions = list(options = list(list(execute = TRUE, type =
+ "EnforceNewOwnerHasReadAccess"), list(execute = FALSE, type =
+ "KeepAccountTeam"), list(execute = FALSE, type = "KeepSalesTeam"),
+ list(execute = FALSE, type =
+ "KeepSalesTeamGrantCurrentOwnerReadWriteAccess"), list(execute = FALSE,
+ type = "SendEmail"), list(execute = FALSE, type =
+ "TransferAllOwnedCases"), list(execute = TRUE, type =
+ "TransferContacts"), list(execute = TRUE, type = "TransferContracts"),
+ list(execute = FALSE, type = "TransferNotesAndAttachments"),
+ list(execute = TRUE, type = "TransferOpenActivities"), list(execute =
+ TRUE, type = "TransferOrders"), list(execute = FALSE, type =
+ "TransferOtherOpenOpportunities"), list(execute = FALSE, type =
+ "TransferOwnedClosedOpportunities"), list(execute = FALSE, type =
+ "TransferOwnedOpenCases"), list(execute = FALSE, type =
+ "TransferOwnedOpenOpportunities"))), QueryOptions = list(batchSize =
+ 1000), UserTerritoryDeleteHeader = list(transferToUserId = NA),
+ BatchRetryHeader = list(`Sforce-Disable-Batch-Retry` = FALSE),
+ LineEndingHeader = list(`Sforce-Line-Ending` = NA),
+ PKChunkingHeader = list(`Sforce-Enable-PKChunking` = FALSE),
+ api_type = NULL, operation = NULL)
+}
+\arguments{
+\item{AllOrNoneHeader}{\code{list}; containing the \code{allOrNone} element with
+a value of \code{TRUE} or \code{FALSE}. This control specifies whether a call rolls back all changes
+unless all records are processed successfully. This control is available in
+SOAP, REST, and Metadata APIs for the following functions: \code{\link{sf_create}},
+\code{\link{sf_delete}}, \code{\link{sf_update}}, \code{\link{sf_upsert}}, \code{\link{sf_create_metadata}},
+\code{\link{sf_delete_metadata}}, \code{\link{sf_update_metadata}}, \code{\link{sf_upsert_metadata}}.
+For more information, read the Salesforce documentation
+\href{https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_header_allornoneheader.htm}{here}.}
+
+\item{AllowFieldTruncationHeader}{\code{list}; containing the \code{allowFieldTruncation}
+element with a value of \code{TRUE} or \code{FALSE}. This control specifies the truncation behavior
+for some field types in SOAP API version 15.0 and later for the following functions:
+\code{\link{sf_create}}, \code{\link{sf_update}}, \code{\link{sf_upsert}}. For
+more information, read the Salesforce documentation
+\href{https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_header_allowfieldtruncation.htm}{here}.}
+
+\item{AssignmentRuleHeader}{\code{list}; containing the \code{useDefaultRule}
+element with a value of \code{TRUE} or \code{FALSE} or the \code{assignmentRuleId} element.
+This control specifies the assignment rule to use when creating or updating an
+Account, Case, or Lead for the following functions: \code{\link{sf_create}},
+\code{\link{sf_update}}, \code{\link{sf_upsert}}. For more information, read the Salesforce documentation
+\href{https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_header_assignmentruleheader.htm}{here}.}
+
+\item{DisableFeedTrackingHeader}{\code{list}; containing the \code{disableFeedTracking}
+element with a value of \code{TRUE} or \code{FALSE}. This control specifies whether
+the changes made in the current call are tracked in feeds for SOAP API calls made
+with the following functions: \code{\link{sf_create}}, \code{\link{sf_delete}},
+\code{\link{sf_update}}, \code{\link{sf_upsert}}. For more information, read the Salesforce documentation
+\href{https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_header_disablefeedtracking.htm}{here}.}
+
+\item{DuplicateRuleHeader}{\code{list}; containing the \code{allowSave},
+\code{includeRecordDetails}, and \code{runAsCurrentUser} elements each with a
+value of \code{TRUE} or \code{FALSE}. This control specifies how duplicate rules should be applied
+when using the following functions: \code{\link{sf_create}}, \code{\link{sf_update}},
+\code{\link{sf_upsert}}. For more information, read the Salesforce documentation
+\href{https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_header_duplicateruleheader.htm}{here}.}
+
+\item{EmailHeader}{\code{list}; containing the \code{triggerAutoResponseEmail},
+\code{triggerOtherEmail}, and \code{triggerUserEmail} elements each with a
+value of \code{TRUE} or \code{FALSE}. This control determines if an email notification should be sent
+when a request is processed by SOAP API calls made with the following functions:
+\code{\link{sf_create}}, \code{\link{sf_delete}}, \code{\link{sf_update}}, \code{\link{sf_upsert}},
+\code{\link{sf_reset_password}}. For more information, read the Salesforce documentation
+\href{https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_header_emailheader.htm}{here}.}
+
+\item{LocaleOptions}{\code{list}; containing the \code{language} element. This control
+specifies the language of the labels returned by the \code{\link{sf_describe_objects}}
+function using the SOAP API. The value must be a valid user locale (language and country), such as
+\code{de_DE} or \code{en_GB}. For more information, read the Salesforce documentation
+\href{https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_header_localeheader.htm}{here}.
+The list of valid user locales is available
+\href{https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_categorynodelocalization.htm#languagelocalekey_desc}{here}.}
+
+\item{MruHeader}{\code{list}; containing the \code{updateMru} element with a value
+of \code{TRUE} or \code{FALSE}. This control indicates whether to update the list
+of most recently used items (\code{TRUE}) or not (\code{FALSE}) in the Recent Items
+section of the sidebar in the Salesforce user interface. This works for SOAP API calls
+made with the following functions: \code{\link{sf_create}}, \code{\link{sf_update}},
+\code{\link{sf_upsert}}, \code{\link{sf_retrieve}}, \code{\link{sf_query}}. For more
+information, read the Salesforce documentation
+\href{https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_header_mruheader.htm}{here}.}
+
+\item{OwnerChangeOptions}{\code{list}; containing the \code{options} element.
+This control specifies the details of ownership of attachments and notes when a
+record’s owner is changed. This works for SOAP API calls made with the following functions:
+\code{\link{sf_update}}, \code{\link{sf_upsert}}. For more information, read the Salesforce documentation
+\href{https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_header_ownerchangeoptions.htm}{here}.}
+
+\item{QueryOptions}{\code{list}; containing the \code{batchSize} element.
+This control specifies the batch size for query results . This works for SOAP or
+REST API calls made with the following functions: \code{\link{sf_query}},
+\code{\link{sf_retrieve}}. For more information, read the Salesforce documentation
+\href{https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_header_queryoptions.htm}{here}.}
+
+\item{UserTerritoryDeleteHeader}{\code{list}; containing the \code{transferToUserId} element.
+This control specifies a user to whom open opportunities are assigned when the current
+owner is removed from a territory. This works for the \code{\link{sf_delete}} function
+using the SOAP API. For more information, read the Salesforce documentation
+\href{https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_header_userterritorydeleteheader.htm}{here}.}
+
+\item{BatchRetryHeader}{\code{list}; containing the \code{Sforce-Disable-Batch-Retry} element.
+When you create a bulk job, the Batch Retry control lets you disable retries
+for unfinished batches included in the job. This works for most operations run through
+the Bulk 1.0 API (e.g. \code{sf_create(., api_type = "Bulk 1.0")}) or creating
+a Bulk 1.0 job with \code{\link{sf_create_job_bulk}}. For more information, read the Salesforce documentation
+\href{https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/async_api_headers_disable_batch_retry.htm}{here}.}
+
+\item{LineEndingHeader}{\code{list}; containing the \code{Sforce-Line-Ending} element.
+When you’re creating a bulk upload job, the Line Ending control lets you
+specify whether line endings are read as line feeds (LFs) or as carriage returns
+and line feeds (CRLFs) for fields of type Text Area and Text Area (Long). This
+works for most operations run through the Bulk APIs or creating a Bulk 1.0
+job with \code{\link{sf_create_job_bulk}}. For more information, read the
+Salesforce documentation
+\href{https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/async_api_headers_line_ending.htm}{here}.}
+
+\item{PKChunkingHeader}{\code{list}; containing the \code{Sforce-Enable-PKChunking} element.
+Use the PK Chunking control to enable automatic primary key (PK) chunking
+for a bulk query job. This works for queries run through the Bulk 1.0 API either via
+\code{sf_query(., api_type = "Bulk 1.0")}) or \code{\link{sf_query_bulk}}. For
+more information, read the Salesforce documentation
+\href{https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/async_api_headers_enable_pk_chunking.htm}{here}.}
+
+\item{api_type}{character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
+"Chatter" indicating which API to use when making the request}
+
+\item{operation}{character; a string defining the type of operation being
+performed (e.g. "insert", "update", "upsert", "delete")}
+}
+\description{
+Typically only used internally by functions when control parameters are passed
+through via dots (...), but it can be called directly to control the behavior
+of API calls. This function behaves exactly like \code{\link[stats:glm.control]{glm.control}}
+for the \code{\link[stats:glm]{glm}} function.
+}
+\examples{
+\dontrun{
+this_control <- sf_control(DuplicateRuleHeader=list(allowSave=TRUE,
+ includeRecordDetails=FALSE,
+ runAsCurrentUser=TRUE))
+new_contact <- c(FirstName = "Test", LastName = "Contact-Create")
+new_record <- sf_create(new_contact, "Contact", control = this_control)
+
+# specifying the controls directly and are picked up by dots
+new_record <- sf_create(new_contact, "Contact",
+ DuplicateRuleHeader = list(allowSave=TRUE,
+ includeRecordDetails=FALSE,
+ runAsCurrentUser=TRUE))
+}
+}
diff --git a/man/sf_create.Rd b/man/sf_create.Rd
index fd27d222..24211c3f 100644
--- a/man/sf_create.Rd
+++ b/man/sf_create.Rd
@@ -4,9 +4,8 @@
\alias{sf_create}
\title{Create Records}
\usage{
-sf_create(input_data, object_name, all_or_none = FALSE,
- api_type = c("SOAP", "REST", "Bulk 1.0", "Bulk 2.0"), ...,
- verbose = FALSE)
+sf_create(input_data, object_name, api_type = c("SOAP", "REST",
+ "Bulk 1.0", "Bulk 2.0"), control = list(...), ..., verbose = FALSE)
}
\arguments{
\item{input_data}{\code{named vector}, \code{matrix}, \code{data.frame}, or
@@ -15,13 +14,15 @@ sf_create(input_data, object_name, all_or_none = FALSE,
\item{object_name}{character; the name of one Salesforce objects that the
function is operating against (e.g. "Account", "Contact", "CustomObject__c")}
-\item{all_or_none}{logical; allows a call to roll back all changes unless all
-records are processed successfully}
-
\item{api_type}{character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request}
-\item{...}{other arguments passed on to \code{\link{sf_bulk_operation}}.}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{arguments passed to \code{\link{sf_control}} or further downstream
+to \code{\link{sf_bulk_operation}}}
\item{verbose}{logical; do you want informative messages?}
}
@@ -31,12 +32,25 @@ records are processed successfully}
\description{
Adds one or more new records to your organization’s data.
}
+\note{
+Because the SOAP and REST calls chunk data into batches of 200 records
+the AllOrNoneHeader will only apply to the success or failure of every batch
+of records and not all records submitted to the function.
+}
\examples{
\dontrun{
-n <- 3
+n <- 2
new_contacts <- tibble(FirstName = rep("Test", n),
LastName = paste0("Contact", 1:n))
new_contacts_result <- sf_create(new_contacts, object_name="Contact")
-new_contacts_result <- sf_create(new_contacts, object_name="Contact", api_type="REST")
+
+# add the control to allow the creation of records that might violate a duplicate rule
+new_contacts_result <- sf_create(new_contacts, object_name="Contact",
+ DuplicateRuleHeader = list(allowSave = TRUE,
+ includeRecordDetails = FALSE,
+ runAsCurrentUser = TRUE))
+
+# an example of how to specify using the Bulk 1.0 API to insert the records
+new_contacts_result <- sf_create(new_contacts, object_name="Contact", api_type="Bulk 1.0")
}
}
diff --git a/man/sf_create_bulk_v1.Rd b/man/sf_create_bulk_v1.Rd
index 05f942d5..be85804e 100644
--- a/man/sf_create_bulk_v1.Rd
+++ b/man/sf_create_bulk_v1.Rd
@@ -4,8 +4,7 @@
\alias{sf_create_bulk_v1}
\title{Create Records using Bulk 1.0 API}
\usage{
-sf_create_bulk_v1(input_data, object_name, all_or_none = FALSE, ...,
- verbose = FALSE)
+sf_create_bulk_v1(input_data, object_name, control, ..., verbose = FALSE)
}
\description{
Create Records using Bulk 1.0 API
diff --git a/man/sf_create_bulk_v2.Rd b/man/sf_create_bulk_v2.Rd
index f16169b2..67910b3b 100644
--- a/man/sf_create_bulk_v2.Rd
+++ b/man/sf_create_bulk_v2.Rd
@@ -4,8 +4,7 @@
\alias{sf_create_bulk_v2}
\title{Create Records using Bulk 2.0 API}
\usage{
-sf_create_bulk_v2(input_data, object_name, all_or_none = FALSE, ...,
- verbose = FALSE)
+sf_create_bulk_v2(input_data, object_name, control, ..., verbose = FALSE)
}
\description{
Create Records using Bulk 2.0 API
diff --git a/man/sf_create_job_bulk.Rd b/man/sf_create_job_bulk.Rd
index b8a4ce6f..165745c0 100644
--- a/man/sf_create_job_bulk.Rd
+++ b/man/sf_create_job_bulk.Rd
@@ -5,11 +5,12 @@
\title{Create Bulk API Job}
\usage{
sf_create_job_bulk(operation = c("insert", "delete", "upsert", "update",
- "hardDelete", "query"), object_name, external_id_fieldname = NULL,
- api_type = c("Bulk 1.0", "Bulk 2.0"), content_type = c("CSV",
- "ZIP_CSV", "ZIP_XML", "ZIP_JSON"), concurrency_mode = c("Parallel",
- "Serial"), line_ending = NULL, column_delimiter = c("COMMA", "TAB",
- "PIPE", "SEMICOLON", "CARET", "BACKQUOTE"), verbose = FALSE)
+ "hardDelete", "query", "queryall"), object_name,
+ external_id_fieldname = NULL, api_type = c("Bulk 1.0", "Bulk 2.0"),
+ content_type = c("CSV", "ZIP_CSV", "ZIP_XML", "ZIP_JSON"),
+ concurrency_mode = c("Parallel", "Serial"),
+ column_delimiter = c("COMMA", "TAB", "PIPE", "SEMICOLON", "CARET",
+ "BACKQUOTE"), control = list(...), ..., verbose = FALSE)
}
\arguments{
\item{operation}{character; a string defining the type of operation being
@@ -26,25 +27,26 @@ objects during upserts to determine if the record already exists in Salesforce o
"Chatter" indicating which API to use when making the request}
\item{content_type}{character; being one of 'CSV', 'ZIP_CSV', 'ZIP_XML', or 'ZIP_JSON' to
-indicate the type of data being passed to the Bulk API.}
+indicate the type of data being passed to the Bulk APIs. For the Bulk 2.0 API the only
+valid value (and the default) is 'CSV'.}
\item{concurrency_mode}{character; either "Parallel" or "Serial" that specifies
whether batches should be completed sequentially or in parallel. Use "Serial"
only if lock contentions persist with in "Parallel" mode. Note: this argument is
only used in the Bulk 1.0 API and will be ignored in calls using the Bulk 2.0 API.}
-\item{line_ending}{character; indicating the line ending used for CSV job data,
-marking the end of a data row. The default is NULL meaing that the line ending
-is determined by the operating system using "CRLF" for Windows machines and
-"LF" for Unix machines. Note: this argument is only used in the Bulk 2.0 API
-and will be ignored in calls using the Bulk 1.0 API.}
-
\item{column_delimiter}{character; indicating the column delimiter used for CSV job data.
The default value is COMMA. Valid values are: "BACKQUOTE", "CARET", "COMMA", "PIPE",
"SEMICOLON", and "TAB", but this package only accepts and uses "COMMA". Also,
note that this argument is only used in the Bulk 2.0 API and will be ignored
in calls using the Bulk 1.0 API.}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{arguments passed to \code{\link{sf_control}}}
+
\item{verbose}{logical; do you want informative messages?}
}
\value{
diff --git a/man/sf_create_job_bulk_v1.Rd b/man/sf_create_job_bulk_v1.Rd
index 267926b0..f2db95b5 100644
--- a/man/sf_create_job_bulk_v1.Rd
+++ b/man/sf_create_job_bulk_v1.Rd
@@ -5,10 +5,10 @@
\title{Create Job using Bulk 1.0 API}
\usage{
sf_create_job_bulk_v1(operation = c("insert", "delete", "upsert",
- "update", "hardDelete", "query"), object_name,
+ "update", "hardDelete", "query", "queryall"), object_name,
external_id_fieldname = NULL, content_type = c("CSV", "ZIP_CSV",
"ZIP_XML", "ZIP_JSON"), concurrency_mode = c("Parallel", "Serial"),
- verbose = FALSE)
+ control, ..., verbose = FALSE)
}
\description{
Create Job using Bulk 1.0 API
diff --git a/man/sf_create_job_bulk_v2.Rd b/man/sf_create_job_bulk_v2.Rd
index c4599706..bd2cc067 100644
--- a/man/sf_create_job_bulk_v2.Rd
+++ b/man/sf_create_job_bulk_v2.Rd
@@ -6,9 +6,8 @@
\usage{
sf_create_job_bulk_v2(operation = c("insert", "delete", "upsert",
"update"), object_name, external_id_fieldname = NULL,
- content_type = "CSV", line_ending = NULL,
- column_delimiter = c("COMMA", "TAB", "PIPE", "SEMICOLON", "CARET",
- "BACKQUOTE"), verbose = FALSE)
+ content_type = "CSV", column_delimiter = c("COMMA", "TAB", "PIPE",
+ "SEMICOLON", "CARET", "BACKQUOTE"), control, ..., verbose = FALSE)
}
\description{
Create Job using Bulk 2.0 API
diff --git a/man/sf_create_metadata.Rd b/man/sf_create_metadata.Rd
index fe51a2fd..e76b54cc 100644
--- a/man/sf_create_metadata.Rd
+++ b/man/sf_create_metadata.Rd
@@ -4,7 +4,7 @@
\alias{sf_create_metadata}
\title{Create Object or Field Metadata in Salesforce}
\usage{
-sf_create_metadata(metadata_type, metadata, all_or_none = FALSE,
+sf_create_metadata(metadata_type, metadata, control = list(...), ...,
verbose = FALSE)
}
\arguments{
@@ -13,8 +13,11 @@ sf_create_metadata(metadata_type, metadata, all_or_none = FALSE,
\item{metadata}{\code{list}; metadata components to be created formatted as
XML before being sent via API}
-\item{all_or_none}{logical; allows a call to roll back all changes unless all
-records are processed successfully}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{arguments passed to \code{\link{sf_control}}}
\item{verbose}{logical; do you want informative messages?}
}
@@ -55,8 +58,9 @@ custom_metadata$fields <- list(fullName="Phone__c",
custom_metadata$deploymentStatus <- 'Deployed'
# make a description to identify this easily in the UI setup tab
custom_metadata$description <- 'created by the Metadata API'
-new_custom_object <- sf_create_metadata(metadata_type='CustomObject',
- metadata=custom_metadata, verbose=TRUE)
+new_custom_object <- sf_create_metadata(metadata_type = 'CustomObject',
+ metadata = custom_metadata,
+ verbose = TRUE)
# adding custom fields to our object
# input formatted as a list
diff --git a/man/sf_create_rest.Rd b/man/sf_create_rest.Rd
index 4def4aca..86bfee68 100644
--- a/man/sf_create_rest.Rd
+++ b/man/sf_create_rest.Rd
@@ -4,8 +4,7 @@
\alias{sf_create_rest}
\title{Create Records using REST API}
\usage{
-sf_create_rest(input_data, object_name, all_or_none = FALSE,
- verbose = FALSE)
+sf_create_rest(input_data, object_name, control, ..., verbose = FALSE)
}
\description{
Create Records using REST API
diff --git a/man/sf_create_soap.Rd b/man/sf_create_soap.Rd
index 02fdcc49..69edc797 100644
--- a/man/sf_create_soap.Rd
+++ b/man/sf_create_soap.Rd
@@ -4,8 +4,7 @@
\alias{sf_create_soap}
\title{Create Records using SOAP API}
\usage{
-sf_create_soap(input_data, object_name, all_or_none = FALSE,
- verbose = FALSE)
+sf_create_soap(input_data, object_name, control, ..., verbose = FALSE)
}
\description{
Create Records using SOAP API
diff --git a/man/sf_delete.Rd b/man/sf_delete.Rd
index aac8e793..acaa4f87 100644
--- a/man/sf_delete.Rd
+++ b/man/sf_delete.Rd
@@ -4,8 +4,8 @@
\alias{sf_delete}
\title{Delete Records}
\usage{
-sf_delete(ids, object_name, all_or_none = FALSE, api_type = c("REST",
- "SOAP", "Bulk 1.0", "Bulk 2.0"), ..., verbose = FALSE)
+sf_delete(ids, object_name, api_type = c("REST", "SOAP", "Bulk 1.0",
+ "Bulk 2.0"), control = list(...), ..., verbose = FALSE)
}
\arguments{
\item{ids}{\code{vector}, \code{matrix}, \code{data.frame}, or
@@ -15,13 +15,15 @@ that can be passed in the request}
\item{object_name}{character; the name of one Salesforce objects that the
function is operating against (e.g. "Account", "Contact", "CustomObject__c")}
-\item{all_or_none}{logical; allows a call to roll back all changes unless all
-records are processed successfully}
-
\item{api_type}{character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request}
-\item{...}{other arguments passed on to \code{\link{sf_bulk_operation}}.}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{arguments passed to \code{\link{sf_control}} or further downstream
+to \code{\link{sf_bulk_operation}}}
\item{verbose}{logical; do you want informative messages?}
}
@@ -29,20 +31,23 @@ records are processed successfully}
\code{tbl_df} of records with success indicator
}
\description{
-Deletes one or more records to your organization’s data.
+Deletes one or more records from your organization’s data.
+}
+\note{
+Because the SOAP and REST calls chunk data into batches of 200 records
+the AllOrNoneHeader will only apply to the success or failure of every batch
+of records and not all records submitted to the function.
}
\examples{
\dontrun{
n <- 3
new_contacts <- tibble(FirstName = rep("Test", n),
LastName = paste0("Contact", 1:n))
-new_contacts_result1 <- sf_create(new_contacts, object_name="Contact")
-deleted_contacts_result1 <- sf_delete(new_contacts_result1$id,
- object_name="Contact")
+new_records <- sf_create(new_contacts, object_name="Contact")
+deleted_first <- sf_delete(new_records$id[1], object_name = "Contact")
-new_contacts_result2 <- sf_create(new_contacts, "Contact")
-deleted_contacts_result2 <- sf_delete(new_contacts_result2$id,
- object_name="Contact",
- api_type="Bulk")
+# add the control to do an "All or None" deletion of the remaining records
+deleted_rest <- sf_delete(new_records$id[2:3], object_name = "Contact",
+ AllOrNoneHeader = list(allOrNone = TRUE))
}
}
diff --git a/man/sf_delete_metadata.Rd b/man/sf_delete_metadata.Rd
index ad9c820b..8c6ee333 100644
--- a/man/sf_delete_metadata.Rd
+++ b/man/sf_delete_metadata.Rd
@@ -4,7 +4,7 @@
\alias{sf_delete_metadata}
\title{Delete Object or Field Metadata in Salesforce}
\usage{
-sf_delete_metadata(metadata_type, object_names, all_or_none = FALSE,
+sf_delete_metadata(metadata_type, object_names, control = list(...), ...,
verbose = FALSE)
}
\arguments{
@@ -12,8 +12,11 @@ sf_delete_metadata(metadata_type, object_names, all_or_none = FALSE,
\item{object_names}{a character vector of names that we wish to read metadata for}
-\item{all_or_none}{logical; allows a call to roll back all changes unless all
-records are processed successfully}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{arguments passed to \code{\link{sf_control}}}
\item{verbose}{logical; do you want informative messages?}
}
diff --git a/man/sf_describe_objects.Rd b/man/sf_describe_objects.Rd
index 669784b2..4a2de38e 100644
--- a/man/sf_describe_objects.Rd
+++ b/man/sf_describe_objects.Rd
@@ -4,8 +4,8 @@
\alias{sf_describe_objects}
\title{SObject Basic Information}
\usage{
-sf_describe_objects(object_names, api_type = c("SOAP", "REST", "Bulk"),
- verbose = FALSE)
+sf_describe_objects(object_names, api_type = c("SOAP", "REST"),
+ control = list(...), ..., verbose = FALSE)
}
\arguments{
\item{object_names}{character; the name of one or more Salesforce objects that the
@@ -14,6 +14,12 @@ function is operating against (e.g. "Account", "Contact", "CustomObject__c")}
\item{api_type}{character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{arguments passed to \code{\link{sf_control}}}
+
\item{verbose}{logical; do you want informative messages?}
}
\value{
diff --git a/man/sf_query.Rd b/man/sf_query.Rd
index d45cace1..05f5c49a 100644
--- a/man/sf_query.Rd
+++ b/man/sf_query.Rd
@@ -4,9 +4,9 @@
\alias{sf_query}
\title{Perform SOQL Query}
\usage{
-sf_query(soql, object_name, guess_types = TRUE, queryall = FALSE,
- page_size = 1000, api_type = c("REST", "SOAP", "Bulk 1.0"),
- next_records_url = NULL, ..., verbose = FALSE)
+sf_query(soql, object_name, queryall = FALSE, guess_types = TRUE,
+ api_type = c("REST", "SOAP", "Bulk 1.0"), control = list(...), ...,
+ next_records_url = NULL, verbose = FALSE)
}
\arguments{
\item{soql}{character; a string defining a SOQL query (e.g. "SELECT Id, Name FROM Account")}
@@ -14,25 +14,28 @@ sf_query(soql, object_name, guess_types = TRUE, queryall = FALSE,
\item{object_name}{character; the name of one Salesforce objects that the
function is operating against (e.g. "Account", "Contact", "CustomObject__c")}
+\item{queryall}{logical; indicating if the query recordset should include records
+that have been deleted because of a merge or delete. QueryAll will also return
+information about archived Task and Event records. QueryAll is available in API
+version 29.0 and later.}
+
\item{guess_types}{logical; indicating whether or not to use \code{col_guess()}
to try and cast the data returned in the query recordset. TRUE uses \code{col_guess()}
and FALSE returns all values as character strings.}
-\item{queryall}{logical; indicating if the query recordset should include
-deleted and archived records (available only when querying Task and Event records)}
-
-\item{page_size}{numeric; a number between 200 and 2000 indicating the number of
-records per page that are returned. Speed benchmarks should be done to better
-understand the speed implications of choosing high or low values of this argument.}
-
\item{api_type}{character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{arguments passed to \code{\link{sf_control}} or further downstream
+to \code{\link{sf_query_bulk}}.}
+
\item{next_records_url}{character (leave as NULL); a string used internally
by the function to paginate through to more records until complete}
-\item{...}{Other arguments passed on to \code{\link{sf_query_bulk}}.}
-
\item{verbose}{logical; do you want informative messages?}
}
\value{
@@ -57,7 +60,7 @@ Additionally, Bulk API can't access or query compound address or compound geoloc
}
\examples{
\dontrun{
-sf_query("SELECT Id, Account.Name, Email FROM Contact LIMIT 10", verbose = TRUE)
+sf_query("SELECT Id, Account.Name, Email FROM Contact LIMIT 10")
}
}
\references{
diff --git a/man/sf_query_bulk.Rd b/man/sf_query_bulk.Rd
index 5a677a47..1766a6f2 100644
--- a/man/sf_query_bulk.Rd
+++ b/man/sf_query_bulk.Rd
@@ -4,9 +4,9 @@
\alias{sf_query_bulk}
\title{Run Bulk Query}
\usage{
-sf_query_bulk(soql, object_name, guess_types = TRUE,
- api_type = c("Bulk 1.0"), interval_seconds = 5, max_attempts = 100,
- verbose = FALSE)
+sf_query_bulk(soql, object_name = NULL, queryall = FALSE,
+ guess_types = TRUE, api_type = c("Bulk 1.0"), interval_seconds = 5,
+ max_attempts = 100, control = list(...), ..., verbose = FALSE)
}
\arguments{
\item{soql}{character; a string defining a SOQL query (e.g. "SELECT Id, Name FROM Account")}
@@ -14,6 +14,11 @@ sf_query_bulk(soql, object_name, guess_types = TRUE,
\item{object_name}{character; the name of one Salesforce objects that the
function is operating against (e.g. "Account", "Contact", "CustomObject__c")}
+\item{queryall}{logical; indicating if the query recordset should include records
+that have been deleted because of a merge or delete. QueryAll will also return
+information about archived Task and Event records. QueryAll is available in API
+version 29.0 and later.}
+
\item{guess_types}{logical; indicating whether or not to use \code{col_guess()}
to try and cast the data returned in the query recordset. TRUE uses \code{col_guess()}
and FALSE returns all values as character strings.}
@@ -27,6 +32,12 @@ for job completion}
\item{max_attempts}{integer; defines then max number attempts to check for job
completion before stopping}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{arguments passed to \code{\link{sf_control}}}
+
\item{verbose}{logical; do you want informative messages?}
}
\value{
@@ -38,10 +49,11 @@ bulk query API jobs
}
\examples{
\dontrun{
-# select all Ids from Account object
-ids <- sf_query_bulk(soql='SELECT Id FROM Account', object_name='Account')
+# select all Ids from Account object (up to 1000)
+ids <- sf_query_bulk(soql = 'SELECT Id FROM Account LIMIT 1000',
+ object_name = 'Account')
}
}
\references{
-\url{https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/}
+\url{https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/asynch_api_bulk_query_intro.htm}
}
diff --git a/man/sf_query_result_bulk.Rd b/man/sf_query_result_bulk.Rd
index 2f8c518e..a9d394a4 100644
--- a/man/sf_query_result_bulk.Rd
+++ b/man/sf_query_result_bulk.Rd
@@ -34,9 +34,9 @@ which has already been submitted to Bulk API Job and has Completed state
}
\examples{
\dontrun{
-my_query <- "SELECT Id, Name FROM Account LIMIT 10"
-job_info <- sf_create_job_bulk(operation='query', object='Account')
-query_info <- sf_submit_query_bulk(job_id=job_info$id, soql=my_query)
+my_query <- "SELECT Id, Name FROM Account LIMIT 1000"
+job_info <- sf_create_job_bulk(operation = 'query', object = 'Account')
+query_info <- sf_submit_query_bulk(job_id = job_info$id, soql = my_query)
result <- sf_batch_details_bulk(job_id = query_info$jobId,
batch_id = query_info$id)
recordset <- sf_query_result_bulk(job_id = query_info$jobId,
diff --git a/man/sf_reset_password.Rd b/man/sf_reset_password.Rd
index 647081f7..71b2b991 100644
--- a/man/sf_reset_password.Rd
+++ b/man/sf_reset_password.Rd
@@ -4,11 +4,17 @@
\alias{sf_reset_password}
\title{Reset User Password}
\usage{
-sf_reset_password(user_id, verbose = FALSE)
+sf_reset_password(user_id, control = list(...), ..., verbose = FALSE)
}
\arguments{
\item{user_id}{character; the unique Salesforce Id assigned to the User}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{arguments passed to \code{\link{sf_control}}}
+
\item{verbose}{logical; do you want informative messages?}
}
\value{
@@ -19,6 +25,10 @@ Changes a user’s password to a temporary, system-generated value.
}
\examples{
\dontrun{
-sf_reset_password(user_id = "0056A000000ZZZaaBBB")
+# reset a user's password and ensure that an email is triggered to them
+sf_reset_password(user_id = "0056A000000ZZZaaBBB",
+ EmailHeader = list(triggerAutoResponseEmail = FALSE,
+ triggerOtherEmail = FALSE,
+ triggerUserEmail = TRUE))
}
}
diff --git a/man/sf_retrieve.Rd b/man/sf_retrieve.Rd
index fded45e8..86d8eb44 100644
--- a/man/sf_retrieve.Rd
+++ b/man/sf_retrieve.Rd
@@ -5,7 +5,7 @@
\title{Retrieve Records By Id}
\usage{
sf_retrieve(ids, fields, object_name, api_type = c("REST", "SOAP",
- "Bulk 1.0", "Bulk 2.0"), verbose = FALSE)
+ "Bulk 1.0", "Bulk 2.0"), control = list(...), ..., verbose = FALSE)
}
\arguments{
\item{ids}{\code{vector}, \code{matrix}, \code{data.frame}, or
@@ -21,6 +21,12 @@ function is operating against (e.g. "Account", "Contact", "CustomObject__c")}
\item{api_type}{character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{arguments passed to \code{\link{sf_control}}}
+
\item{verbose}{logical; do you want informative messages?}
}
\value{
diff --git a/man/sf_search.Rd b/man/sf_search.Rd
index fa58fe43..05ee2651 100644
--- a/man/sf_search.Rd
+++ b/man/sf_search.Rd
@@ -23,7 +23,7 @@ and FALSE returns all values as character strings.}
"Chatter" indicating which API to use when making the request}
\item{parameterized_search_options}{\code{list}; a list of parameters for
-controlling the search if not using SOSL. If using SOSL this is ignored.}
+controlling the search if not using SOSL. If using SOSL this argument is ignored.}
\item{verbose}{logical; do you want informative messages?}
diff --git a/man/sf_submit_query_bulk.Rd b/man/sf_submit_query_bulk.Rd
index a659ade6..a94a904c 100644
--- a/man/sf_submit_query_bulk.Rd
+++ b/man/sf_submit_query_bulk.Rd
@@ -40,9 +40,9 @@ Additionally, Bulk API can't access or query compound address or compound geoloc
}
\examples{
\dontrun{
-my_query <- "SELECT Id, Name FROM Account LIMIT 10"
-job_info <- sf_create_job_bulk(operation='query', object='Account')
-query_info <- sf_submit_query_bulk(job_id=job_info$id, soql=my_query)
+my_query <- "SELECT Id, Name FROM Account LIMIT 1000"
+job_info <- sf_create_job_bulk(operation = 'query', object = 'Account')
+query_info <- sf_submit_query_bulk(job_id = job_info$id, soql = my_query)
}
}
\references{
diff --git a/man/sf_update.Rd b/man/sf_update.Rd
index 72f8c6ce..ff6417d9 100644
--- a/man/sf_update.Rd
+++ b/man/sf_update.Rd
@@ -4,9 +4,8 @@
\alias{sf_update}
\title{Update Records}
\usage{
-sf_update(input_data, object_name, all_or_none = FALSE,
- api_type = c("SOAP", "REST", "Bulk 1.0", "Bulk 2.0"), ...,
- verbose = FALSE)
+sf_update(input_data, object_name, api_type = c("SOAP", "REST",
+ "Bulk 1.0", "Bulk 2.0"), control = list(...), ..., verbose = FALSE)
}
\arguments{
\item{input_data}{\code{named vector}, \code{matrix}, \code{data.frame}, or
@@ -15,13 +14,15 @@ sf_update(input_data, object_name, all_or_none = FALSE,
\item{object_name}{character; the name of one Salesforce objects that the
function is operating against (e.g. "Account", "Contact", "CustomObject__c")}
-\item{all_or_none}{logical; allows a call to roll back all changes unless all
-records are processed successfully}
-
\item{api_type}{character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request}
-\item{...}{other arguments passed on to \code{\link{sf_bulk_operation}}.}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{arguments passed to \code{\link{sf_control}} or further downstream
+to \code{\link{sf_bulk_operation}}}
\item{verbose}{logical; do you want informative messages?}
}
@@ -31,18 +32,31 @@ records are processed successfully}
\description{
Updates one or more records to your organization’s data.
}
+\note{
+Because the SOAP and REST calls chunk data into batches of 200 records
+the AllOrNoneHeader will only apply to the success or failure of every batch
+of records and not all records submitted to the function.
+}
\examples{
\dontrun{
-n <- 3
-new_contacts <- tibble(FirstName = rep("Test", n),
- LastName = paste0("Contact", 1:n))
-new_contacts_result <- sf_create(new_contacts, "Contact")
+n <- 2
+new_accts <- tibble(FirstName = rep("Test", n),
+ LastName = paste0("Account", 1:n))
+new_records <- sf_create(new_accts, "Account")
-update_contacts <- tibble(FirstName = rep("TestTest", n),
- LastName = paste0("Contact", 1:n),
- Id = new_contacts_result$id)
-updated_contacts_result1 <- sf_update(update_contacts, "Contact")
-updated_contacts_result2 <- sf_update(update_contacts, "Contact",
- api_type="Bulk")
+updated_accts <- tibble(FirstName = rep("TestTest", n),
+ LastName = paste0("Account", 1:n),
+ Id = new_records$id)
+
+# update the accounts and ensure that all contacts and cases (open and closed)
+# owned by the previous account owner are transferred to the new owner
+update <- sf_update(updated_accts, "Account",
+ OwnerChangeOptions=list(options=
+ list(list(execute=TRUE,
+ type="TransferAllOwnedCases"),
+ list(execute=TRUE,
+ type="TransferOwnedOpenCases"),
+ list(execute=TRUE,
+ type="TransferContacts"))))
}
}
diff --git a/man/sf_update_bulk_v1.Rd b/man/sf_update_bulk_v1.Rd
index 04eb321b..7676e3c9 100644
--- a/man/sf_update_bulk_v1.Rd
+++ b/man/sf_update_bulk_v1.Rd
@@ -4,8 +4,7 @@
\alias{sf_update_bulk_v1}
\title{Update Records using Bulk 1.0 API}
\usage{
-sf_update_bulk_v1(input_data, object_name, all_or_none = FALSE, ...,
- verbose = FALSE)
+sf_update_bulk_v1(input_data, object_name, control, ..., verbose = FALSE)
}
\description{
Update Records using Bulk 1.0 API
diff --git a/man/sf_update_bulk_v2.Rd b/man/sf_update_bulk_v2.Rd
index 19d82a57..28fc848a 100644
--- a/man/sf_update_bulk_v2.Rd
+++ b/man/sf_update_bulk_v2.Rd
@@ -4,8 +4,7 @@
\alias{sf_update_bulk_v2}
\title{Update Records using Bulk 2.0 API}
\usage{
-sf_update_bulk_v2(input_data, object_name, all_or_none = FALSE, ...,
- verbose = FALSE)
+sf_update_bulk_v2(input_data, object_name, control, ..., verbose = FALSE)
}
\description{
Update Records using Bulk 2.0 API
diff --git a/man/sf_update_metadata.Rd b/man/sf_update_metadata.Rd
index 54af55cb..824526a5 100644
--- a/man/sf_update_metadata.Rd
+++ b/man/sf_update_metadata.Rd
@@ -4,7 +4,7 @@
\alias{sf_update_metadata}
\title{Update Object or Field Metadata in Salesforce}
\usage{
-sf_update_metadata(metadata_type, metadata, all_or_none = FALSE,
+sf_update_metadata(metadata_type, metadata, control = list(...), ...,
verbose = FALSE)
}
\arguments{
@@ -13,8 +13,11 @@ sf_update_metadata(metadata_type, metadata, all_or_none = FALSE,
\item{metadata}{\code{list}; metadata components to be created formatted as
XML before being sent via API}
-\item{all_or_none}{logical; allows a call to roll back all changes unless all
-records are processed successfully}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{arguments passed to \code{\link{sf_control}}}
\item{verbose}{logical; do you want informative messages?}
}
diff --git a/man/sf_update_rest.Rd b/man/sf_update_rest.Rd
index 09928882..719abe7b 100644
--- a/man/sf_update_rest.Rd
+++ b/man/sf_update_rest.Rd
@@ -4,8 +4,7 @@
\alias{sf_update_rest}
\title{Update Records using REST API}
\usage{
-sf_update_rest(input_data, object_name, all_or_none = FALSE,
- verbose = FALSE)
+sf_update_rest(input_data, object_name, control, ..., verbose = FALSE)
}
\description{
Update Records using REST API
diff --git a/man/sf_update_soap.Rd b/man/sf_update_soap.Rd
index 02abad3c..4ca311ec 100644
--- a/man/sf_update_soap.Rd
+++ b/man/sf_update_soap.Rd
@@ -4,8 +4,7 @@
\alias{sf_update_soap}
\title{Update Records using SOAP API}
\usage{
-sf_update_soap(input_data, object_name, all_or_none = FALSE,
- verbose = FALSE)
+sf_update_soap(input_data, object_name, control, ..., verbose = FALSE)
}
\description{
Update Records using SOAP API
diff --git a/man/sf_upsert.Rd b/man/sf_upsert.Rd
index 5ba3fae8..1c322f80 100644
--- a/man/sf_upsert.Rd
+++ b/man/sf_upsert.Rd
@@ -5,8 +5,8 @@
\title{Upsert Records}
\usage{
sf_upsert(input_data, object_name, external_id_fieldname,
- all_or_none = FALSE, api_type = c("SOAP", "REST", "Bulk 1.0",
- "Bulk 2.0"), ..., verbose = FALSE)
+ api_type = c("SOAP", "REST", "Bulk 1.0", "Bulk 2.0"),
+ control = list(...), ..., verbose = FALSE)
}
\arguments{
\item{input_data}{\code{named vector}, \code{matrix}, \code{data.frame}, or
@@ -19,13 +19,15 @@ function is operating against (e.g. "Account", "Contact", "CustomObject__c")}
object that has been set as an "External ID" field. This field is used to reference
objects during upserts to determine if the record already exists in Salesforce or not.}
-\item{all_or_none}{logical; allows a call to roll back all changes unless all
-records are processed successfully}
-
\item{api_type}{character; one of "REST", "SOAP", "Bulk 1.0", "Bulk 2.0", or
"Chatter" indicating which API to use when making the request}
-\item{...}{other arguments passed on to \code{\link{sf_bulk_operation}}.}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{arguments passed to \code{\link{sf_control}} or further downstream
+to \code{\link{sf_bulk_operation}}}
\item{verbose}{logical; do you want informative messages?}
}
diff --git a/man/sf_upsert_bulk_v1.Rd b/man/sf_upsert_bulk_v1.Rd
index 588844d1..36b1122e 100644
--- a/man/sf_upsert_bulk_v1.Rd
+++ b/man/sf_upsert_bulk_v1.Rd
@@ -4,8 +4,8 @@
\alias{sf_upsert_bulk_v1}
\title{Upsert Records using Bulk 1.0 API}
\usage{
-sf_upsert_bulk_v1(input_data, object_name, external_id_fieldname,
- all_or_none = FALSE, ..., verbose = FALSE)
+sf_upsert_bulk_v1(input_data, object_name, external_id_fieldname, control,
+ ..., verbose = FALSE)
}
\description{
Upsert Records using Bulk 1.0 API
diff --git a/man/sf_upsert_bulk_v2.Rd b/man/sf_upsert_bulk_v2.Rd
index ddb1515d..50de5340 100644
--- a/man/sf_upsert_bulk_v2.Rd
+++ b/man/sf_upsert_bulk_v2.Rd
@@ -4,8 +4,8 @@
\alias{sf_upsert_bulk_v2}
\title{Upsert Records using Bulk 2.0 API}
\usage{
-sf_upsert_bulk_v2(input_data, object_name, external_id_fieldname,
- all_or_none = FALSE, ..., verbose = FALSE)
+sf_upsert_bulk_v2(input_data, object_name, external_id_fieldname, control,
+ ..., verbose = FALSE)
}
\description{
Upsert Records using Bulk 2.0 API
diff --git a/man/sf_upsert_metadata.Rd b/man/sf_upsert_metadata.Rd
index 7dc6f985..cafc6654 100644
--- a/man/sf_upsert_metadata.Rd
+++ b/man/sf_upsert_metadata.Rd
@@ -4,7 +4,7 @@
\alias{sf_upsert_metadata}
\title{Upsert Object or Field Metadata in Salesforce}
\usage{
-sf_upsert_metadata(metadata_type, metadata, all_or_none = FALSE,
+sf_upsert_metadata(metadata_type, metadata, control = list(...), ...,
verbose = FALSE)
}
\arguments{
@@ -13,8 +13,11 @@ sf_upsert_metadata(metadata_type, metadata, all_or_none = FALSE,
\item{metadata}{\code{list}; metadata components to be created formatted as
XML before being sent via API}
-\item{all_or_none}{logical; allows a call to roll back all changes unless all
-records are processed successfully}
+\item{control}{\code{list}; a list of parameters for controlling the behavior of
+the API call being used. For more information of what parameters are available
+look at the documentation for \code{\link{sf_control}}}
+
+\item{...}{arguments passed to \code{\link{sf_control}}}
\item{verbose}{logical; do you want informative messages?}
}
diff --git a/man/sf_upsert_rest.Rd b/man/sf_upsert_rest.Rd
index 760a3c04..b844e213 100644
--- a/man/sf_upsert_rest.Rd
+++ b/man/sf_upsert_rest.Rd
@@ -4,8 +4,8 @@
\alias{sf_upsert_rest}
\title{Upsert Records using REST API}
\usage{
-sf_upsert_rest(input_data, object_name, external_id_fieldname,
- all_or_none = FALSE, verbose = FALSE)
+sf_upsert_rest(input_data, object_name, external_id_fieldname, control,
+ ..., verbose = FALSE)
}
\description{
Upsert Records using REST API
diff --git a/man/sf_upsert_soap.Rd b/man/sf_upsert_soap.Rd
index 59be6df5..aa4f528b 100644
--- a/man/sf_upsert_soap.Rd
+++ b/man/sf_upsert_soap.Rd
@@ -4,8 +4,8 @@
\alias{sf_upsert_soap}
\title{Upsert Records using SOAP API}
\usage{
-sf_upsert_soap(input_data, object_name, external_id_fieldname,
- all_or_none = FALSE, verbose = FALSE)
+sf_upsert_soap(input_data, object_name, external_id_fieldname, control,
+ ..., verbose = FALSE)
}
\description{
Upsert Records using SOAP API
diff --git a/vignettes/getting-started.Rmd b/vignettes/getting-started.Rmd
index 3826de6a..e8029c04 100644
--- a/vignettes/getting-started.Rmd
+++ b/vignettes/getting-started.Rmd
@@ -70,6 +70,7 @@ sprintf("User Active?: %s", user_info$isActive)
```
### Create
+
Salesforce has objects and those objects contain records. One default object is the
"Contact" object. This example shows how to create two records in the Contact object.
@@ -82,6 +83,7 @@ created_records
```
### Retrieve
+
Retrieve pulls down a specific set of records and fields. It's very similar to
running a query, but doesn't use SOQL. Here is an example where we retrieve the
data we just created.
@@ -93,7 +95,6 @@ retrieved_records <- sf_retrieve(ids=created_records$id,
retrieved_records
```
-
### Query
Salesforce has proprietary form of SQL called SOQL (Salesforce Object Query
diff --git a/vignettes/getting-started.md b/vignettes/getting-started.md
index f35f3eea..9e4c7096 100644
--- a/vignettes/getting-started.md
+++ b/vignettes/getting-started.md
@@ -55,12 +55,13 @@ the information returned about the current user. It should be information about
# and confirm a connection to the APIs
user_info <- sf_user_info()
sprintf("User Id: %s", user_info$id)
-#> [1] "User Id: 0056A000000MPRjQAO"
+#> character(0)
sprintf("User Active?: %s", user_info$isActive)
-#> [1] "User Active?: TRUE"
+#> character(0)
```
### Create
+
Salesforce has objects and those objects contain records. One default object is the
"Contact" object. This example shows how to create two records in the Contact object.
@@ -73,12 +74,13 @@ created_records <- sf_create(new_contacts, "Contact")
created_records
#> # A tibble: 2 x 2
#> id success
-#>
-#> 1 0036A00000SncEJQAZ true
-#> 2 0036A00000SncEKQAZ true
+#>
+#> 1 0036A00000wzh4VQAQ TRUE
+#> 2 0036A00000wzh4WQAQ TRUE
```
### Retrieve
+
Retrieve pulls down a specific set of records and fields. It's very similar to
running a query, but doesn't use SOQL. Here is an example where we retrieve the
data we just created.
@@ -92,11 +94,10 @@ retrieved_records
#> # A tibble: 2 x 3
#> Id FirstName LastName
#>
-#> 1 0036A00000SncEJQAZ Test Contact-Create-1
-#> 2 0036A00000SncEKQAZ Test Contact-Create-2
+#> 1 0036A00000wzh4VQAQ Test Contact-Create-1
+#> 2 0036A00000wzh4WQAQ Test Contact-Create-2
```
-
### Query
Salesforce has proprietary form of SQL called SOQL (Salesforce Object Query
@@ -121,9 +122,9 @@ queried_records <- sf_query(my_soql)
queried_records
#> # A tibble: 2 x 4
#> Id Account FirstName LastName
-#> *
-#> 1 0036A00000SncEJQAZ NA Test Contact-Create-1
-#> 2 0036A00000SncEKQAZ NA Test Contact-Create-2
+#>
+#> 1 0036A00000wzh4VQAQ NA Test Contact-Create-1
+#> 2 0036A00000wzh4WQAQ NA Test Contact-Create-2
```
### Update
@@ -147,9 +148,9 @@ updated_records <- sf_update(queried_records, object_name="Contact")
updated_records
#> # A tibble: 2 x 2
#> id success
-#>
-#> 1 0036A00000SncEJQAZ true
-#> 2 0036A00000SncEKQAZ true
+#>
+#> 1 0036A00000wzh4VQAQ TRUE
+#> 2 0036A00000wzh4WQAQ TRUE
```
### Delete
@@ -164,8 +165,8 @@ deleted_records
#> # A tibble: 2 x 3
#> id success errors
#>
-#> 1 0036A00000SncEJQAZ TRUE
-#> 2 0036A00000SncEKQAZ TRUE
+#> 1 0036A00000wzh4VQAQ TRUE
+#> 2 0036A00000wzh4WQAQ TRUE
```
### Upsert
@@ -199,10 +200,10 @@ upserted_records <- sf_upsert(input_data=upserted_contacts,
upserted_records
#> # A tibble: 3 x 3
#> created id success
-#>
-#> 1 false 0036A00000SncEOQAZ true
-#> 2 false 0036A00000SncEPQAZ true
-#> 3 true 0036A00000SncETQAZ true
+#>
+#> 1 FALSE 0036A00000wzh4XQAQ TRUE
+#> 2 FALSE 0036A00000wzh4YQAQ TRUE
+#> 3 TRUE 0036A00000wzh4aQAA TRUE
```
diff --git a/vignettes/passing-control-args.R b/vignettes/passing-control-args.R
new file mode 100644
index 00000000..83eacec1
--- /dev/null
+++ b/vignettes/passing-control-args.R
@@ -0,0 +1,53 @@
+## ---- echo = FALSE-------------------------------------------------------
+NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true")
+knitr::opts_chunk$set(
+ collapse = TRUE,
+ comment = "#>",
+ purl = NOT_CRAN,
+ eval = NOT_CRAN
+)
+
+## ----auth, include = FALSE-----------------------------------------------
+suppressWarnings(suppressMessages(library(dplyr)))
+library(salesforcer)
+token_path <- here::here("tests", "testthat", "salesforcer_token.rds")
+suppressMessages(sf_auth(token = token_path, verbose = FALSE))
+
+## ----sample-create-------------------------------------------------------
+new_contact <- c(FirstName = "Test", LastName = "Contact-Create")
+record <- sf_create(new_contact,
+ object_name = "Contact",
+ DisableFeedTrackingHeader = list(disableFeedTracking = TRUE),
+ api_type = "SOAP")
+
+## ---- include = FALSE----------------------------------------------------
+deleted_records <- sf_delete(record$id)
+
+## ----sample-create-w-duplicate-------------------------------------------
+new_contact <- c(FirstName = "Test", LastName = "Contact-Create")
+record <- sf_create(new_contact,
+ object_name = "Contact",
+ DuplicateRuleHeader = list(allowSave = TRUE,
+ includeRecordDetails = FALSE,
+ runAsCurrentUser = TRUE))
+
+## ---- include = FALSE----------------------------------------------------
+deleted_records <- sf_delete(record$id)
+
+## ----sample-create-w-warning---------------------------------------------
+new_contact <- c(FirstName = "Test", LastName = "Contact-Create")
+record <- sf_create(new_contact,
+ object_name = "Contact",
+ BatchRetryHeader = list(`Sforce-Disable-Batch-Retry` = FALSE),
+ api_type = "SOAP")
+
+## ---- include = FALSE----------------------------------------------------
+deleted_records <- sf_delete(record$id)
+
+## ----sample-query--------------------------------------------------------
+new_contact <- c(FirstName = "Test", LastName = "Contact-Create")
+records <- sf_query("SELECT Id, Name FROM Account LIMIT 1000",
+ object_name = "Account",
+ control = sf_control(QueryOptions = list(batchSize = 100)),
+ api_type = "SOAP")
+
diff --git a/vignettes/passing-control-args.Rmd b/vignettes/passing-control-args.Rmd
new file mode 100644
index 00000000..05a194e1
--- /dev/null
+++ b/vignettes/passing-control-args.Rmd
@@ -0,0 +1,166 @@
+---
+title: "Passing Control Args"
+author: "Steven M. Mortimer"
+date: "2019-06-08"
+output:
+ rmarkdown::html_vignette:
+ toc: true
+ toc_depth: 4
+ keep_md: true
+vignette: >
+ %\VignetteIndexEntry{Passing Control Args}
+ %\VignetteEngine{knitr::rmarkdown}
+ %\VignetteEncoding{UTF-8}
+---
+
+```{r, echo = FALSE}
+NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true")
+knitr::opts_chunk$set(
+ collapse = TRUE,
+ comment = "#>",
+ purl = NOT_CRAN,
+ eval = NOT_CRAN
+)
+```
+
+If you're inserting records from R you may want to turn off the assignment rules
+or even bypass duplicate rules and alerts to save records. Beginning in Version 0.1.3 of
+the **salesforcer** package many functions have a `control` argument that will allow
+you to fine tune the behavior of calls to the Salesforce APIs. This vignette will
+introduce the different options you can control and how to pass them into the **salesforcer**
+functions you're already familiar with.
+
+### The new control argument
+
+This new feature can be seen in the `sf_create` (and many other functions) as
+`control=list(...)`. The dots mean that you can pass any number of controls directly
+into the function. For example, the following code will create a record, but prevent
+its creation from showing up in the Chatter feeds by setting the `DisableFeedTrackingHeader`.
+
+```{r auth, include = FALSE}
+suppressWarnings(suppressMessages(library(dplyr)))
+library(salesforcer)
+token_path <- here::here("tests", "testthat", "salesforcer_token.rds")
+suppressMessages(sf_auth(token = token_path, verbose = FALSE))
+```
+
+```{r sample-create}
+new_contact <- c(FirstName = "Test", LastName = "Contact-Create")
+record <- sf_create(new_contact,
+ object_name = "Contact",
+ DisableFeedTrackingHeader = list(disableFeedTracking = TRUE),
+ api_type = "SOAP")
+```
+
+```{r, include = FALSE}
+deleted_records <- sf_delete(record$id)
+```
+
+You will notice that the argument `DisableFeedTrackingHeader` can be included right into
+the function without any documentation existing for it in the `sf_create` function.
+This is because the dots (`...`) allow you to pass over a dozen different control
+parameters and that documentation would be tedious to create and maintain over multiple
+functions in the package. However, you will notice in the documentation entry for
+the `control` argument there is a link to a function called `sf_control` which you
+can use to directly to pass into `control` or simply to review its documentation of all the
+possible control parameters and their defaults. This is where you can review the various
+control options in more detail before trying to set them.
+
+You may have also noticed that the argument DisableFeedTrackingHeader was formatted
+as a list with an element inside called `disableFeedTracking` set to `TRUE`. This may
+seem redundant but there are two reasons for this. First, this is exactly how the
+Salesforce APIs documents these options, which are typically referred to as "headers"
+because they are passed as a named header of the HTTP request and then the header fields
+and values are provided for that header. Second, some headers have multiple fields and values
+so a list is the only way to provide multiple named fields and values under a single header entity.
+For example, the DuplicateRuleHeader, which controls whether
+the duplicate rules can be overridden when inserting records from the API, has three
+fields: `allowSave`, `includeRecordDetails`, and `runAsCurrentUser`. Supplying all
+three requires a list-like structure, which may seem redundant in other cases, but is
+necessary to follow.
+
+```{r sample-create-w-duplicate}
+new_contact <- c(FirstName = "Test", LastName = "Contact-Create")
+record <- sf_create(new_contact,
+ object_name = "Contact",
+ DuplicateRuleHeader = list(allowSave = TRUE,
+ includeRecordDetails = FALSE,
+ runAsCurrentUser = TRUE))
+```
+
+```{r, include = FALSE}
+deleted_records <- sf_delete(record$id)
+```
+
+Finally, you will notice in the example call that the `api_type` argument is set to "SOAP".
+This is because the `DisableFeedTrackingHeader` is a control that is only available when
+making calls via the SOAP API. You will receive a warning when trying to set control
+parameters for APIs or operations that do not recognize that control. For example,
+the following code tries to set the `BatchRetryHeader` for a call to the SOAP
+API which does not acknowledge that control. That control is only used with the Bulk
+1.0 API since its records as submitted in batches and automatic retry can be controlled.
+
+```{r sample-create-w-warning}
+new_contact <- c(FirstName = "Test", LastName = "Contact-Create")
+record <- sf_create(new_contact,
+ object_name = "Contact",
+ BatchRetryHeader = list(`Sforce-Disable-Batch-Retry` = FALSE),
+ api_type = "SOAP")
+```
+
+```{r, include = FALSE}
+deleted_records <- sf_delete(record$id)
+```
+
+### Creating the control argument with sf_control
+
+If this type of control structure is new to you, take a look at the documentation for
+the `glm` and `glm.control` functions. The way these two functions behave is exactly how
+functions like `sf_create` and `sf_control` work with each other. As demonstrated above
+you can pass any number of arbitrary controls into the function and they are all
+gathered up into the control by `control = list(...)`. However, you can specify the
+control directly like this:
+
+```{r sample-query}
+new_contact <- c(FirstName = "Test", LastName = "Contact-Create")
+records <- sf_query("SELECT Id, Name FROM Account LIMIT 1000",
+ object_name = "Account",
+ control = sf_control(QueryOptions = list(batchSize = 100)),
+ api_type = "SOAP")
+```
+
+### Backwards compatibility for all_or_none and other named arguments
+
+You may already be taking advantage of the `all_or_none` or `line_ending` arguments
+which are control arguments that were explicity included in functions. These argument
+essentially hard coded values to pass the `AllOrNoneHeader` and `LineEndingHeader`
+control parameters. Starting with the 0.1.3 release it is no longer necessary and
+preferable not to have an argument like `all_or_none` listed explicity as an argument
+since it can be provided in the `control` argument. Note: the `all_or_none` argument
+and other explicit control arguments will still be available in **salesforcer 0.1.3**
+but will provide a deprecated warning. They will be removed in the next CRAN release
+of the package so it will be important to update your code now if you are explicitly
+passing these arguments and see a deprecation warning.
+
+### Reference Links
+
+Below is a list of links that go directly to the control arguments (a.k.a headers)
+for the different APIs. I highly recommend reading this documentation before setting
+a control parameter in R so you know exactly what the behavior will be and how to
+specify it in R. You may notice that some controls are not included in the R package.
+Some may be added in the future if requested and some will not be added given the
+scope of the package. One final note is that some arguments in the REST API, like the
+"All or None" behavior is not a header, but a parameter in the API call. For this reason
+you will not see it listed in the REST API Headers section, but it is set in this R package
+using the `AllOrNoneHeader` argument in `sf_control` just to provide consistency between
+the SOAP and REST APIs. It would be confusing to have two arguments named differently,
+one for each API, but to do the exact same thing from R. For this reason, many of the
+control arguments match exactly as they are listed in the SOAP API, but can be used
+across other APIs even if not exactly written that way in the Salesforce documentation
+referenced below.
+
+ * **SOAP API Headers**: https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/soap_headers.htm
+ * **REST API Headers**: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/headers.htm
+ * **Bulk 1.0 API Headers**: https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/async_api_headers.htm
+ * **Bulk 2.0 API Headers**: None
+ * **Metadata API Headers**: https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_headers.htm
diff --git a/vignettes/passing-control-args.md b/vignettes/passing-control-args.md
new file mode 100644
index 00000000..0e3541ec
--- /dev/null
+++ b/vignettes/passing-control-args.md
@@ -0,0 +1,154 @@
+---
+title: "Passing Control Args"
+author: "Steven M. Mortimer"
+date: "2019-06-08"
+output:
+ rmarkdown::html_vignette:
+ toc: true
+ toc_depth: 4
+ keep_md: true
+vignette: >
+ %\VignetteIndexEntry{Passing Control Args}
+ %\VignetteEngine{knitr::rmarkdown}
+ %\VignetteEncoding{UTF-8}
+---
+
+
+
+If you're inserting records from R you may want to turn off the assignment rules
+or even bypass duplicate rules and alerts to save records. Beginning in Version 0.1.3 of
+the **salesforcer** package many functions have a `control` argument that will allow
+you to fine tune the behavior of calls to the Salesforce APIs. This vignette will
+introduce the different options you can control and how to pass them into the **salesforcer**
+functions you're already familiar with.
+
+### The new control argument
+
+This new feature can be seen in the `sf_create` (and many other functions) as
+`control=list(...)`. The dots mean that you can pass any number of controls directly
+into the function. For example, the following code will create a record, but prevent
+its creation from showing up in the Chatter feeds by setting the `DisableFeedTrackingHeader`.
+
+
+
+
+```r
+new_contact <- c(FirstName = "Test", LastName = "Contact-Create")
+record <- sf_create(new_contact,
+ object_name = "Contact",
+ DisableFeedTrackingHeader = list(disableFeedTracking = TRUE),
+ api_type = "SOAP")
+```
+
+
+
+You will notice that the argument `DisableFeedTrackingHeader` can be included right into
+the function without any documentation existing for it in the `sf_create` function.
+This is because the dots (`...`) allow you to pass over a dozen different control
+parameters and that documentation would be tedious to create and maintain over multiple
+functions in the package. However, you will notice in the documentation entry for
+the `control` argument there is a link to a function called `sf_control` which you
+can use to directly to pass into `control` or simply to review its documentation of all the
+possible control parameters and their defaults. This is where you can review the various
+control options in more detail before trying to set them.
+
+You may have also noticed that the argument `DisableFeedTrackingHeader` was formatted
+as a list with an element inside called `disableFeedTracking` set to `TRUE`. This may
+seem redundant but there are two reasons for this. First, this is exactly how the
+Salesforce APIs documents these options, which are typically referred to as "headers"
+because they are passed as a named header of the HTTP request and then the header fields
+and values are provided for that header. Second, some headers have multiple fields and values
+so a list is the only way to provide multiple named fields and values under a single header entity.
+For example, the `DuplicateRuleHeader`, which controls whether
+the duplicate rules can be overridden when inserting records from the API, has three
+fields: `allowSave`, `includeRecordDetails`, and `runAsCurrentUser`. Supplying all
+three requires a list-like structure, which may seem redundant in other cases, but is
+necessary to follow.
+
+
+```r
+new_contact <- c(FirstName = "Test", LastName = "Contact-Create")
+record <- sf_create(new_contact,
+ object_name = "Contact",
+ DuplicateRuleHeader = list(allowSave = TRUE,
+ includeRecordDetails = FALSE,
+ runAsCurrentUser = TRUE))
+```
+
+
+
+Finally, you will notice in the example call that the `api_type` argument is set to "SOAP".
+This is because the `DisableFeedTrackingHeader` is a control that is only available when
+making calls via the SOAP API. You will receive a warning when trying to set control
+parameters for APIs or operations that do not recognize that control. For example,
+the following code tries to set the `BatchRetryHeader` for a call to the SOAP
+API which does not acknowledge that control. That control is only used with the Bulk
+1.0 API since its records as submitted in batches and automatic retry can be controlled.
+
+
+```r
+new_contact <- c(FirstName = "Test", LastName = "Contact-Create")
+record <- sf_create(new_contact,
+ object_name = "Contact",
+ BatchRetryHeader = list(`Sforce-Disable-Batch-Retry` = FALSE),
+ api_type = "SOAP")
+#> Warning in filter_valid_controls(supplied_arguments, api_type = api_type):
+#> Ignoring the following controls which are not used in the SOAP API:
+#> BatchRetryHeader
+```
+
+
+
+### Creating the control argument with sf_control
+
+If this type of control structure is new to you, take a look at the documentation for
+the `glm` and `glm.control` functions. The way these two functions behave is exactly how
+functions like `sf_create` and `sf_control` work with each other. As demonstrated above
+you can pass any number of arbitrary controls into the function and they are all
+gathered up into the control by `control = list(...)`. However, you can specify the
+control directly like this:
+
+
+```r
+new_contact <- c(FirstName = "Test", LastName = "Contact-Create")
+records <- sf_query("SELECT Id, Name FROM Account LIMIT 1000",
+ object_name = "Account",
+ control = sf_control(QueryOptions = list(batchSize = 100)),
+ api_type = "SOAP")
+```
+
+### Backwards compatibility for all_or_none and other named arguments
+
+You may already be taking advantage of the `all_or_none` or `line_ending` arguments
+which are control arguments that were explicity included in functions. These argument
+essentially hard coded values to pass the `AllOrNoneHeader` and `LineEndingHeader`
+control parameters. Starting with the 0.1.3 release it is no longer necessary and
+preferable not to have an argument like `all_or_none` listed explicity as an argument
+since it can be provided in the `control` argument. Note: the `all_or_none` argument
+and other explicit control arguments will still be available in **salesforcer 0.1.3**
+but will provide a deprecated warning. They will be removed in the next CRAN release
+of the package so it will be important to update your code now if you are explicitly
+passing these arguments and see a deprecation warning.
+
+### Reference Links
+
+Below is a list of links that go directly to the control arguments (a.k.a headers)
+for the different APIs. I highly recommend reading this documentation before setting
+a control parameter in R so you know exactly what the behavior will be and how to
+specify it in R. You may notice that some controls are not included in the R package.
+Some may be added in the future if requested and some will not be added given the
+scope of the package. One final note is that some arguments in the REST API, like the
+"All or None" behavior is not a header, but a parameter in the API call. For this reason
+you will not see it listed in the REST API Headers section, but it is set in this R package
+using the `AllOrNoneHeader` argument in `sf_control` just to provide consistency between
+the SOAP and REST APIs. It would be confusing to have two arguments named differently,
+one for each API, but to do the exact same thing from R. For this reason, many of the
+control arguments match exactly as they are listed in the SOAP API, but can be used
+across other APIs even if not exactly written that way in the Salesforce documentation
+referenced below.
+
+ * **SOAP API Headers**: https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/soap_headers.htm
+ * **REST API Headers**: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/headers.htm
+ * **Bulk 1.0 API Headers**: https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/async_api_headers.htm
+ * **Bulk 2.0 API Headers**: None
+ * **Metadata API Headers**: https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_headers.htm