diff --git a/NAMESPACE b/NAMESPACE
index f517d6ba..77cebe81 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -37,6 +37,7 @@ export(rforcecom.bulkAction)
export(rforcecom.bulkQuery)
export(rforcecom.create)
export(rforcecom.delete)
+export(rforcecom.getObjectDescription)
export(rforcecom.getServerTimestamp)
export(rforcecom.login)
export(rforcecom.query)
@@ -63,6 +64,7 @@ export(sf_delete)
export(sf_delete_job_bulk)
export(sf_delete_metadata)
export(sf_describe_metadata)
+export(sf_describe_object_fields)
export(sf_describe_objects)
export(sf_end_job_bulk)
export(sf_get_job_bulk)
diff --git a/NEWS.md b/NEWS.md
index 329d7dab..d1f6034a 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -2,11 +2,12 @@
### Features
- * Nothing Yet!
+ * Add **RForcecom** backward compatibile version of `rforcecom.getObjectDescription()`
+ * Add `sf_describe_object_fields()` which is a tidyier version of `rforcecom.getObjectDescription()`
### Bug Fixes
- * Nothing Yet!
+ * Fix bug where Username/Password authenticated sessions where not working with api_type = "Bulk 1.0"
---
diff --git a/R/compatibility.R b/R/compatibility.R
index 2f0ceccc..863bb380 100644
--- a/R/compatibility.R
+++ b/R/compatibility.R
@@ -269,6 +269,27 @@ rforcecom.retrieve <- function(session, objectName,
return(resultSet)
}
+#' salesforcer's backwards compatible version of rforcecom.getObjectDescription
+#'
+#' @importFrom purrr map_df
+#' @template session
+#' @template objectName
+#' @return Object descriptions
+#' @note This function returns a data.frame with one row per field for an object.
+#' @export
+rforcecom.getObjectDescription <- function(session, objectName){
+
+ .Deprecated("sf_describe_objects")
+
+ obj_dat <- sf_describe_objects(object_names = objectName,
+ api_type="SOAP")[[1]]
+
+ obj_fields <- map_df(obj_dat[names(obj_dat) == "fields"],
+ as.data.frame,
+ stringsAsFactors=FALSE)
+ return(obj_fields)
+}
+
#' Run Bulk Action
#'
#' This function is a convenience wrapper for submitting bulk API jobs
diff --git a/R/read-metadata.R b/R/read-metadata.R
index 5e4c0782..b4a3f67e 100644
--- a/R/read-metadata.R
+++ b/R/read-metadata.R
@@ -1,6 +1,6 @@
#' Read Object or Field Metadata from Salesforce
#'
-#' This function takes a a request of named elements in Salesforce and
+#' This function takes a request of named elements in Salesforce and
#' returns their metadata
#'
#' @importFrom XML newXMLNode addChildren xmlParse xmlToList
@@ -66,3 +66,32 @@ sf_read_metadata <- function(metadata_type, object_names, verbose=FALSE){
return(resultset)
}
+
+#' Describe Object Fields
+#'
+#' This function takes the name of an object in Salesforce and returns a description
+#' of the fields on that object by returning a tibble with one row per field.
+#'
+#' @importFrom readr type_convert cols
+#' @importFrom dplyr as_tibble
+#' @template object_name
+#' @note The tibble only contains the fields that the user can view, as defined by
+#' the user's field-level security settings.
+#' @return A \code{tbl_df} containing one row per field for the requested object.
+#' @examples
+#' \dontrun{
+#' acct_fields <- sf_describe_object_fields('Account')
+#' }
+#' @export
+sf_describe_object_fields <- function(object_name){
+
+ stopifnot(length(object_name) == 1)
+
+ # suppress deprecation warnings
+ suppressWarnings(obj_fields_dat <- rforcecom.getObjectDescription(objectName=object_name))
+ obj_fields_dat <- obj_fields_dat %>%
+ as_tibble() %>%
+ type_convert(col_types=cols())
+
+ return(obj_fields_dat)
+}
\ No newline at end of file
diff --git a/README.Rmd b/README.Rmd
index 3a69e771..2cfaa75b 100644
--- a/README.Rmd
+++ b/README.Rmd
@@ -29,7 +29,7 @@ Bulk 2.0, and Metadata APIs. Package features include:
* Retrieve and modify metadata (Custom Objects, Fields, etc.) using the Metadata API with:
* `sf_describe_objects()`, `sf_create_metadata()`, `sf_update_metadata()`
* Utilize backwards compatible functions for the **RForcecom** package, such as:
- * `rforcecom.login()`, `rforcecom.query()`, `rforcecom.create()`, `rforcecom.update()`
+ * `rforcecom.login()`, `rforcecom.getObjectDescription()`, `rforcecom.query()`, `rforcecom.create()`
* Basic utility calls (`sf_user_info()`, `sf_server_timestamp()`, `sf_list_objects()`)
## Table of Contents
@@ -232,21 +232,34 @@ read_obj_result[[1]][first_two_fields_idx]
The data is returned as a list because object definitions are highly nested representations.
You may notice that we are missing some really specific details, such as, the picklist
-values of a field with type "Picklist". You can get that information using the function
-`sf_describe_object()` function which is actually part of the REST and SOAP APIs.
-It is recommended that you try out the various metadata functions `sf_read_metadata()`,
-`sf_list_metadata()`, `sf_describe_metadata()`, and `sf_describe_objects()` in order
-to see which information best suits your use case.
+values of a field with type "Picklist". You can get that information using the
+`sf_describe_object_fields()` or `sf_describe_objects()` functions which are based
+on calls from REST and SOAP APIs. Here is an example using `sf_describe_object_fields()`
+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)
+```
+
+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.
```{r rest-describe-objects}
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 first two returned fields of the Account object
-the_type_field <- describe_obj_result[[1]][[58]]
-the_type_field$name
+# 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)
```
+It is recommended that you try out the various metadata functions `sf_read_metadata()`,
+`sf_list_metadata()`, `sf_describe_metadata()`, and `sf_describe_objects()` in order
+to see which information best suits your use case.
+
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.
diff --git a/_pkgdown.yml b/_pkgdown.yml
index a9525226..e74b8916 100644
--- a/_pkgdown.yml
+++ b/_pkgdown.yml
@@ -65,6 +65,7 @@ reference:
- '`sf_retrieve_metadata`'
- '`sf_describe_metadata`'
- '`sf_describe_objects`'
+ - '`sf_describe_object_fields`'
- title: Salesforce Org Utility Functions
desc: Functions used for basic calls to understand the org.
contents:
@@ -74,3 +75,17 @@ reference:
- '`sf_list_resources`'
- '`sf_list_api_limits`'
- '`sf_list_objects`'
+ - title: Backward Compatibility with RForcecom
+ desc: Functions that mirror RForcecom to ease code transitions between salesforcer and RForcecom
+ contents:
+ - '`rforcecom.login`'
+ - '`rforcecom.getServerTimestamp`'
+ - '`rforcecom.getObjectDescription`'
+ - '`rforcecom.create`'
+ - '`rforcecom.update`'
+ - '`rforcecom.upsert`'
+ - '`rforcecom.delete`'
+ - '`rforcecom.retrieve`'
+ - '`rforcecom.search`'
+ - '`rforcecom.query`'
+ - '`rforcecom.bulkQuery`'
diff --git a/docs/CONDUCT.html b/docs/CONDUCT.html
index f764040f..b91de2d7 100644
--- a/docs/CONDUCT.html
+++ b/docs/CONDUCT.html
@@ -21,16 +21,28 @@
+
+
+
-
+
+
+
+
+
+
+
+
+
+
@@ -40,23 +52,16 @@
-
+
+
-
-
-
-
-
#> # A tibble: 2 x 2#> id success#> <chr> <chr>
-#> 1 0036A00000Sp4e9QAB true
-#> 2 0036A00000Sp4eAQAR true
+#> 1 0036A00000cIQYKQA4 true
+#> 2 0036A00000cIQYLQA4 true
@@ -161,8 +161,8 @@
#> # A tibble: 2 x 3#> Id FirstName LastName #> <chr> <chr> <chr>
-#> 1 0036A00000Sp4e9QAB Test Contact-Create-1
-#> 2 0036A00000Sp4eAQAR Test Contact-Create-2
+#> 1 0036A00000cIQYKQA4 Test Contact-Create-1
+#> 2 0036A00000cIQYLQA4 Test Contact-Create-2
@@ -181,8 +181,8 @@
#> # A tibble: 2 x 4#> Id Account FirstName LastName #> * <chr> <lgl> <chr> <chr>
-#> 1 0036A00000Sp4e9QAB NA Test Contact-Create-1
-#> 2 0036A00000Sp4eAQAR NA Test Contact-Create-2
+#> 1 0036A00000cIQYKQA4 NA Test Contact-Create-1
+#> 2 0036A00000cIQYLQA4 NA Test Contact-Create-2
@@ -198,8 +198,8 @@
#> # A tibble: 2 x 2#> id success#> <chr> <chr>
-#> 1 0036A00000Sp4e9QAB true
-#> 2 0036A00000Sp4eAQAR true
#> 3 0036A00000RUqb0QAD NA #> 4 0036A00000RUqedQAD NA #> 5 0036A00000RUqeeQAD NA
+
+
+
+Describe
+
The RForcecom package has the function rforcecom.getObjectDescription() which returns a data.frame with one row per field on an object. The same function in salesforcer is named sf_describe_object_fields() and also has better printing and datatype casting by using tibbles.
#> # A tibble: 2 x 3#> id success errors #> <chr> <lgl> <list>
-#> 1 0036A00000Sp4eiQAB TRUE <list [0]>
-#> 2 0036A00000Sp4ejQAB TRUE <list [0]>
+#> 1 0036A00000cIQZ3QAO TRUE <list [0]>
+#> 2 0036A00000cIQZ4QAO TRUE <list [0]># Bulk
bulk_created_records <-sf_create(new_contacts, object_name="Contact", api_type="Bulk 1.0")
bulk_created_records
#> # A tibble: 2 x 4#> Id Success Created Error#> <chr> <chr> <chr> <lgl>
-#> 1 0036A00000Sp4enQAB true true NA
-#> 2 0036A00000Sp4eoQAB true true NA
+#> 1 0036A00000cIQZ8QAO true true NA
+#> 2 0036A00000cIQZ9QAO true true NA
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 API.
-
# just add api_type="Bulk" to most calls!
+
Here is a simple workflow of adding, querying, and deleting records using the Bulk 1.0 API.
+
# just add api_type="Bulk 1.0" or api_type="Bulk 2.0" to most calls!# create bulk
object <- "Contact"
n <-2
@@ -157,8 +157,8 @@
#> # A tibble: 2 x 4#> Id Success Created Error#> <chr> <chr> <chr> <lgl>
-#> 1 0036A00000Sp4esQAB true true NA
-#> 2 0036A00000Sp4etQAB true true NA
+#> 1 0036A00000cIQZIQA4 true true NA
+#> 2 0036A00000cIQZJQA4 true true NA# query bulk
my_soql <-sprintf("SELECT Id,
@@ -173,8 +173,8 @@
#> # A tibble: 2 x 3#> Id FirstName LastName #> <chr> <chr> <chr>
-#> 1 0036A00000Sp4esQAB Test Contact-Create-1
-#> 2 0036A00000Sp4etQAB Test Contact-Create-2
+#> 1 0036A00000cIQZIQA4 Test Contact-Create-1
+#> 2 0036A00000cIQZJQA4 Test Contact-Create-2# delete bulk
deleted_records <-sf_delete(queried_records$Id, object_name=object, api_type="Bulk 1.0")
@@ -182,8 +182,8 @@
#> # A tibble: 2 x 4#> Id Success Created Error#> <chr> <chr> <chr> <lgl>
-#> 1 0036A00000Sp4esQAB true false NA
-#> 2 0036A00000Sp4etQAB true false NA
+#> 1 0036A00000cIQZIQA4 true false NA
+#> 2 0036A00000cIQZJQA4 true false NA
#> # A tibble: 2 x 4#> Id Account FirstName LastName #> * <chr> <lgl> <chr> <chr>
-#> 1 0036A00000Sp4duQAB NA Test Contact-Create-1
-#> 2 0036A00000Sp4dvQAB NA Test Contact-Create-2
+#> 1 0036A00000cIQXRQA4 NA Test Contact-Create-1
+#> 2 0036A00000cIQXSQA4 NA Test Contact-Create-2
@@ -253,8 +252,8 @@
#> # A tibble: 2 x 2#> id success#> <chr> <chr>
-#> 1 0036A00000Sp4duQAB true
-#> 2 0036A00000Sp4dvQAB true
The data is returned as a list because object definitions are highly nested representations. You may notice that we are missing some really specific details, such as, the picklist values of a field with type “Picklist”. You can get that information using the function sf_describe_object() function which is actually part of the REST and SOAP APIs. It is recommended that you try out the various metadata functions sf_read_metadata(), sf_list_metadata(), sf_describe_metadata(), and sf_describe_objects() in order to see which information best suits your use case.
+
The data is returned as a list because object definitions are highly nested representations. You may notice that we are missing some really specific details, such as, the picklist values of a field with type “Picklist”. You can get that information using the sf_describe_object_fields() or sf_describe_objects() functions which are based on calls from REST and SOAP APIs. Here is an example using sf_describe_object_fields() where we get a tbl_df with one row for each field on the Account object:
+
acct_fields <-sf_describe_object_fields('Account')
+acct_fields %>%select(name, label, length, soapType, type)
+#> # A tibble: 67 x 5
+#> name label length soapType type
+#> <chr> <chr> <dbl> <chr> <chr>
+#> 1 Id Account ID 18. tns:ID id
+#> 2 IsDeleted Deleted 0. xsd:boolean boolean
+#> 3 MasterRecordId Master Record ID 18. tns:ID reference
+#> 4 Name Account Name 255. xsd:string string
+#> 5 Type Account Type 40. xsd:string picklist
+#> 6 ParentId Parent Account ID 18. tns:ID reference
+#> 7 BillingStreet Billing Street 255. xsd:string textarea
+#> 8 BillingCity Billing City 40. xsd:string string
+#> 9 BillingState Billing State/Province 80. xsd:string string
+#> 10 BillingPostalCode Billing Zip/Postal Code 20. xsd:string string
+#> # ... with 57 more rows
+
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.
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')]
#> $label#> [1] "Account"#> #> $queryable#> [1] "true"
-# show the first two returned fields of the Account object
-the_type_field <-describe_obj_result[[1]][[58]]
-the_type_field$name
-#> [1] "Type"
+# show the different picklist values for the Account Type field
+the_type_field <-describe_obj_result[[1]][[59]]
+the_type_field$label
+#> [1] "Account Type"map_df(the_type_field[which(names(the_type_field) == "picklistValues")], as_tibble)
#> # A tibble: 7 x 4#> active defaultValue label value
@@ -341,6 +358,7 @@
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.
A function to create a variety of objects that are part of the Metadata API service
Below is a list of objects and their required components to be created with this function:
list; a list containing "sessionID", "instanceURL", and "
+apiVersion" as returned by RForcecom::rforcecom.login(). This argument is
+ignored in all backward compatible calls because the authorization credentials
+are stored in an environment internal to the salesforcer package, so it is no longer
+necessary to pass the session in each function call.
+
+
+
objectName
+
character; the name of the Salesforce object that the
+function is operating against (e.g. "Account", "Contact", "CustomObject__c")
+
+
+
+
Value
+
+
Object descriptions
+
+
Note
+
+
This function returns a data.frame with one row per field for an object.
Log in using Basic (Username-Password) or OAuth 2.0 authenticaion. OAuth does
not require sharing passwords, but will require authorizing salesforcer
@@ -159,6 +166,7 @@
Log in to Salesforce
permission to operate on your behalf. By default, these user credentials are
cached in a file named .httr-oauth-salesforcer in the current working directory.
+
Examp
# log in using basic authentication (username-password)sf_auth(username="test@gmail.com",
password="test_password",
- security_token= )
+ security_token="test_token")
# log in using OAuth 2.0# Via brower or refresh of .httr-oauth-salesforcer
@@ -255,10 +263,16 @@
Before the user makes any calls requiring an authorized session, check if an
OAuth token or session is not already available, call sf_auth to
@@ -159,6 +166,7 @@
Check that an Authorized Salesforce Session Exists
access_token() to reveal the actual access token, suitable for use
with curl.
+
Force the current OAuth to refresh. This is only needed for times when you
load the token from outside the current working directory, it is expired, and
you're running in non-interactive mode.
This function takes the name of an object in Salesforce and returns a description
+of the fields on that object by returning a tibble with one row per field.
+
+
+
+
sf_describe_object_fields(object_name)
+
+
Arguments
+
+
+
+
object_name
+
character; the name of one Salesforce objects that the
+function is operating against (e.g. "Account", "Contact", "CustomObject__c")
+
+
+
+
Value
+
+
A tbl_df containing one row per field for the requested object.
+
+
Note
+
+
The tibble only contains the fields that the user can view, as defined by
+the user's field-level security settings.
+
+
+
Examples
+
# NOT RUN {
+acct_fields<-sf_describe_object_fields('Account')
+# }
This function is an early and simple approach to converting an
XML node or document into a more typical R list containing the data values.
It differs from xmlToList by not including attributes at all in the output.
A function specifically for parsing an XML node into a data.frame
+
xml_nodeset_to_df(this_node)
@@ -201,10 +209,16 @@
Contents
diff --git a/docs/sitemap.xml b/docs/sitemap.xml
index 4de2a8f6..d567df67 100644
--- a/docs/sitemap.xml
+++ b/docs/sitemap.xml
@@ -1,5 +1,8 @@
+
+ https://stevenmmortimer.github.io/salesforcer/index.html
+ https://stevenmmortimer.github.io/salesforcer/reference/VERB_n.html
@@ -117,6 +120,9 @@
https://stevenmmortimer.github.io/salesforcer/reference/rforcecom.delete.html
+
+ https://stevenmmortimer.github.io/salesforcer/reference/rforcecom.getObjectDescription.html
+ https://stevenmmortimer.github.io/salesforcer/reference/rforcecom.getServerTimestamp.html
@@ -216,6 +222,9 @@
https://stevenmmortimer.github.io/salesforcer/reference/sf_describe_metadata.html
+
+ https://stevenmmortimer.github.io/salesforcer/reference/sf_describe_object_fields.html
+ https://stevenmmortimer.github.io/salesforcer/reference/sf_describe_objects.html
diff --git a/index.Rmd b/index.Rmd
index 376b4a52..c69634b5 100644
--- a/index.Rmd
+++ b/index.Rmd
@@ -30,7 +30,7 @@ Bulk 2.0, and Metadata APIs. Package features include:
* Retrieve and modify metadata (Custom Objects, Fields, etc.) using the Metadata API with:
* `sf_describe_objects()`, `sf_create_metadata()`, `sf_update_metadata()`
* Utilize backwards compatible functions for the **RForcecom** package, such as:
- * `rforcecom.login()`, `rforcecom.query()`, `rforcecom.create()`, `rforcecom.update()`
+ * `rforcecom.login()`, `rforcecom.getObjectDescription()`, `rforcecom.query()`, `rforcecom.create()`
* Basic utility calls (`sf_user_info()`, `sf_server_timestamp()`, `sf_list_objects()`)
## Table of Contents
@@ -233,21 +233,34 @@ read_obj_result[[1]][first_two_fields_idx]
The data is returned as a list because object definitions are highly nested representations.
You may notice that we are missing some really specific details, such as, the picklist
-values of a field with type "Picklist". You can get that information using the function
-`sf_describe_object()` function which is actually part of the REST and SOAP APIs.
-It is recommended that you try out the various metadata functions `sf_read_metadata()`,
-`sf_list_metadata()`, `sf_describe_metadata()`, and `sf_describe_objects()` in order
-to see which information best suits your use case.
+values of a field with type "Picklist". You can get that information using the
+`sf_describe_object_fields()` or `sf_describe_objects()` functions which are based
+on calls from REST and SOAP APIs. Here is an example using `sf_describe_object_fields()`
+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)
+```
+
+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.
```{r rest-describe-objects}
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 first two returned fields of the Account object
-the_type_field <- describe_obj_result[[1]][[58]]
-the_type_field$name
+# 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)
```
+It is recommended that you try out the various metadata functions `sf_read_metadata()`,
+`sf_list_metadata()`, `sf_describe_metadata()`, and `sf_describe_objects()` in order
+to see which information best suits your use case.
+
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.
diff --git a/man/rforcecom.getObjectDescription.Rd b/man/rforcecom.getObjectDescription.Rd
new file mode 100644
index 00000000..c05da771
--- /dev/null
+++ b/man/rforcecom.getObjectDescription.Rd
@@ -0,0 +1,27 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/compatibility.R
+\name{rforcecom.getObjectDescription}
+\alias{rforcecom.getObjectDescription}
+\title{salesforcer's backwards compatible version of rforcecom.getObjectDescription}
+\usage{
+rforcecom.getObjectDescription(session, objectName)
+}
+\arguments{
+\item{session}{\code{list}; a list containing "sessionID", "instanceURL", and "
+apiVersion" as returned by \code{RForcecom::rforcecom.login()}. This argument is
+ignored in all backward compatible calls because the authorization credentials
+are stored in an environment internal to the salesforcer package, so it is no longer
+necessary to pass the session in each function call.}
+
+\item{objectName}{character; the name of the Salesforce object that the
+function is operating against (e.g. "Account", "Contact", "CustomObject__c")}
+}
+\value{
+Object descriptions
+}
+\description{
+salesforcer's backwards compatible version of rforcecom.getObjectDescription
+}
+\note{
+This function returns a data.frame with one row per field for an object.
+}
diff --git a/man/sf_describe_object_fields.Rd b/man/sf_describe_object_fields.Rd
new file mode 100644
index 00000000..c1f061eb
--- /dev/null
+++ b/man/sf_describe_object_fields.Rd
@@ -0,0 +1,28 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/read-metadata.R
+\name{sf_describe_object_fields}
+\alias{sf_describe_object_fields}
+\title{Describe Object Fields}
+\usage{
+sf_describe_object_fields(object_name)
+}
+\arguments{
+\item{object_name}{character; the name of one Salesforce objects that the
+function is operating against (e.g. "Account", "Contact", "CustomObject__c")}
+}
+\value{
+A \code{tbl_df} containing one row per field for the requested object.
+}
+\description{
+This function takes the name of an object in Salesforce and returns a description
+of the fields on that object by returning a tibble with one row per field.
+}
+\note{
+The tibble only contains the fields that the user can view, as defined by
+the user's field-level security settings.
+}
+\examples{
+\dontrun{
+acct_fields <- sf_describe_object_fields('Account')
+}
+}
diff --git a/man/sf_read_metadata.Rd b/man/sf_read_metadata.Rd
index ede4a9b1..baae6825 100644
--- a/man/sf_read_metadata.Rd
+++ b/man/sf_read_metadata.Rd
@@ -17,7 +17,7 @@ sf_read_metadata(metadata_type, object_names, verbose = FALSE)
A \code{list} containing a response for each requested object
}
\description{
-This function takes a a request of named elements in Salesforce and
+This function takes a request of named elements in Salesforce and
returns their metadata
}
\examples{
diff --git a/tests/testthat/test-compatibility.R b/tests/testthat/test-compatibility.R
index 12e9990b..4fc107e9 100644
--- a/tests/testthat/test-compatibility.R
+++ b/tests/testthat/test-compatibility.R
@@ -173,6 +173,19 @@ test_that("testing rforcecom.search compatibility", {
expect_is(result2, "data.frame")
})
+test_that("testing rforcecom.getObjectDescription compatibility", {
+
+ result1 <- RForcecom::rforcecom.getObjectDescription(session, objectName="Account")
+ result2 <- salesforcer::rforcecom.getObjectDescription(session, objectName="Account")
+
+ expect_is(result1, "data.frame")
+ expect_is(result2, "data.frame")
+ # same number of fields
+ expect_equal(nrow(result1), nrow(result2))
+ # same names of the fields
+ expect_equal(sort(as.character(result1$name)), sort(result2$name))
+})
+
# not exported?
# test_that("testing rforcecom.bulkAction compatibility", {
# n <- 2
diff --git a/tests/testthat/test-metadata.R b/tests/testthat/test-metadata.R
index 3f070a55..38217662 100644
--- a/tests/testthat/test-metadata.R
+++ b/tests/testthat/test-metadata.R
@@ -69,6 +69,7 @@ describe_obj_result <- sf_describe_metadata()
list_obj_result <- sf_list_metadata(queries=list(list(type='CustomObject')))
read_obj_result <- sf_read_metadata(metadata_type='CustomObject',
object_names=paste0("Custom_Account_", rand_int+1, "__c"))
+desc_obj_fields_result <- sf_describe_object_fields(paste0("Custom_Account_", rand_int+1, "__c"))
retrieve_request <- list(unpackaged=list(types=list(members='*', name='CustomObject')))
retrieve_info <- sf_retrieve_metadata(retrieve_request)
@@ -137,6 +138,13 @@ test_that("sf_read_metadata", {
names(read_obj_result[[1]])))
})
+test_that("sf_describe_object_fields", {
+ expect_is(desc_obj_fields_result, "tbl_df")
+ expect_true(all(c('Id', 'OwnerId', 'IsDeleted', 'Name', 'CreatedDate', 'CreatedById',
+ 'LastModifiedDate', 'LastModifiedById', 'SystemModstamp', 'LastActivityDate') %in%
+ desc_obj_fields_result$name))
+})
+
test_that("sf_retrieve_metadata", {
expect_is(retrieve_info, "tbl_df")
expect_true(all(c('done', 'id', 'status', 'success', 'fileProperties') %in%
diff --git a/vignettes/transitioning-from-RForcecom.R b/vignettes/transitioning-from-RForcecom.R
index a966e4b4..9429f4d5 100644
--- a/vignettes/transitioning-from-RForcecom.R
+++ b/vignettes/transitioning-from-RForcecom.R
@@ -81,3 +81,14 @@ result2
salesforcer_results <- sf_query(this_soql)
salesforcer_results
+## ---- warning=FALSE------------------------------------------------------
+# the RForcecom way
+result1 <- RForcecom::rforcecom.getObjectDescription(session, objectName='Account')
+
+# backwards compatible in the salesforcer package
+result2 <- salesforcer::rforcecom.getObjectDescription(session, objectName='Account')
+
+# the better way in salesforcer to get object fields
+result3 <- salesforcer::sf_describe_object_fields('Account')
+result3
+
diff --git a/vignettes/transitioning-from-RForcecom.Rmd b/vignettes/transitioning-from-RForcecom.Rmd
index 59cbc4ef..74f80fe7 100644
--- a/vignettes/transitioning-from-RForcecom.Rmd
+++ b/vignettes/transitioning-from-RForcecom.Rmd
@@ -138,5 +138,24 @@ salesforcer_results <- sf_query(this_soql)
salesforcer_results
```
+### Describe
+
+The **RForcecom** package has the function `rforcecom.getObjectDescription()` which returns
+a `data.frame` with one row per field on an object. The same function in **salesforcer**
+is named `sf_describe_object_fields()` and also has better printing and datatype
+casting by using tibbles.
+
+```{r, warning=FALSE}
+# the RForcecom way
+result1 <- RForcecom::rforcecom.getObjectDescription(session, objectName='Account')
+
+# backwards compatible in the salesforcer package
+result2 <- salesforcer::rforcecom.getObjectDescription(session, objectName='Account')
+
+# the better way in salesforcer to get object fields
+result3 <- salesforcer::sf_describe_object_fields('Account')
+result3
+```
+
In the future more features will be migrated from **RForcecom** to make the
transition as seamless as possible.
diff --git a/vignettes/transitioning-from-RForcecom.md b/vignettes/transitioning-from-RForcecom.md
index adf94c49..3d968200 100644
--- a/vignettes/transitioning-from-RForcecom.md
+++ b/vignettes/transitioning-from-RForcecom.md
@@ -78,13 +78,13 @@ fields <- c(FirstName="Test", LastName="Contact-Create-Compatibility")
result1 <- RForcecom::rforcecom.create(session, objectName=object, fields)
result1
#> id success
-#> 1 0036A00000SncEYQAZ true
+#> 1 0036A00000cIQKmQAO true
# replicated in salesforcer package
result2 <- salesforcer::rforcecom.create(session, objectName=object, fields)
result2
#> id success
-#> 1 0036A00000SncEdQAJ true
+#> 1 0036A00000cIQKrQAO true
```
Here is an example showing the reduction in code of using **salesforcer** if you
@@ -106,8 +106,8 @@ for(i in 1:nrow(new_contacts)){
}
rforcecom_results
#> id success
-#> 1 0036A00000SncEiQAJ true
-#> 2 0036A00000SncEnQAJ true
+#> 1 0036A00000cIQKwQAO true
+#> 2 0036A00000cIQJuQAO true
# the better way in salesforcer to do multiple records
salesforcer_results <- sf_create(new_contacts, object_name="Contact")
@@ -115,8 +115,8 @@ salesforcer_results
#> # A tibble: 2 x 2
#> id success
#>
-#> 1 0036A00000SncELQAZ true
-#> 2 0036A00000SncEMQAZ true
+#> 1 0036A00000cIQL1QAO true
+#> 2 0036A00000cIQL2QAO true
```
### Query
@@ -132,11 +132,11 @@ this_soql <- "SELECT Id, Email FROM Contact LIMIT 5"
result1 <- RForcecom::rforcecom.query(session, soqlQuery = this_soql)
result1
#> Id
-#> 1 0036A00000RUqb0QAD
-#> 2 0036A00000RUqedQAD
-#> 3 0036A00000RUqeeQAD
-#> 4 0036A00000RUpmQQAT
-#> 5 0036A00000RUpnnQAD
+#> 1 0036A00000SncIGQAZ
+#> 2 0036A00000SncIHQAZ
+#> 3 0036A00000RUqb0QAD
+#> 4 0036A00000RUqedQAD
+#> 5 0036A00000RUqeeQAD
# replicated in salesforcer package
result2 <- salesforcer::rforcecom.query(session, soqlQuery = this_soql)
@@ -144,11 +144,11 @@ result2
#> # A tibble: 5 x 2
#> Id Email
#> *
-#> 1 0036A00000RUqb0QAD NA
-#> 2 0036A00000RUqedQAD NA
-#> 3 0036A00000RUqeeQAD NA
-#> 4 0036A00000RUpmQQAT NA
-#> 5 0036A00000RUpnnQAD NA
+#> 1 0036A00000SncIGQAZ NA
+#> 2 0036A00000SncIHQAZ NA
+#> 3 0036A00000RUqb0QAD NA
+#> 4 0036A00000RUqedQAD NA
+#> 5 0036A00000RUqeeQAD NA
# the better way in salesforcer to query
salesforcer_results <- sf_query(this_soql)
@@ -156,11 +156,99 @@ salesforcer_results
#> # A tibble: 5 x 2
#> Id Email
#> *
-#> 1 0036A00000RUqb0QAD NA
-#> 2 0036A00000RUqedQAD NA
-#> 3 0036A00000RUqeeQAD NA
-#> 4 0036A00000RUpmQQAT NA
-#> 5 0036A00000RUpnnQAD NA
+#> 1 0036A00000SncIGQAZ NA
+#> 2 0036A00000SncIHQAZ NA
+#> 3 0036A00000RUqb0QAD NA
+#> 4 0036A00000RUqedQAD NA
+#> 5 0036A00000RUqeeQAD NA
+```
+
+### Describe
+
+The **RForcecom** package has the function `rforcecom.getObjectDescription()` which returns
+a `data.frame` with one row per field on an object. The same function in **salesforcer**
+is named `sf_describe_object_fields()` and also has better printing and datatype
+casting by using tibbles.
+
+
+```r
+# the RForcecom way
+result1 <- RForcecom::rforcecom.getObjectDescription(session, objectName='Account')
+
+# backwards compatible in the salesforcer package
+result2 <- salesforcer::rforcecom.getObjectDescription(session, objectName='Account')
+
+# the better way in salesforcer to get object fields
+result3 <- salesforcer::sf_describe_object_fields('Account')
+#> Parsed with column specification:
+#> cols(
+#> .default = col_character(),
+#> byteLength = col_double(),
+#> digits = col_double(),
+#> length = col_double(),
+#> precision = col_double(),
+#> scale = col_double()
+#> )
+#> See spec(...) for full column specifications.
+result3
+#> # A tibble: 67 x 166
+#> aggregatable autoNumber byteLength calculated caseSensitive createable
+#>
+#> 1 true false 18. false false false
+#> 2 false false 0. false false false
+#> 3 true false 18. false false false
+#> 4 true false 765. false false true
+#> 5 true false 120. false false true
+#> 6 true false 18. false false true
+#> 7 true false 765. false false true
+#> 8 true false 120. false false true
+#> 9 true false 240. false false true
+#> 10 true false 60. false false true
+#> # ... with 57 more rows, and 160 more variables: custom ,
+#> # defaultedOnCreate , deprecatedAndHidden , digits ,
+#> # filterable , groupable , idLookup , label ,
+#> # length , name , nameField , namePointing ,
+#> # nillable , permissionable , polymorphicForeignKey ,
+#> # precision , queryByDistance , restrictedPicklist ,
+#> # scale , searchPrefilterable , soapType ,
+#> # sortable , type , unique , updateable ,
+#> # defaultValue.text , defaultValue..attrs , referenceTo ,
+#> # relationshipName , compoundFieldName , extraTypeInfo ,
+#> # picklistValues.active , picklistValues.defaultValue ,
+#> # picklistValues.label , picklistValues.value ,
+#> # picklistValues.active.1 , picklistValues.defaultValue.1 ,
+#> # picklistValues.label.1 , picklistValues.value.1 ,
+#> # picklistValues.active.2 , picklistValues.defaultValue.2 ,
+#> # picklistValues.label.2 , picklistValues.value.2 ,
+#> # picklistValues.active.3 , picklistValues.defaultValue.3 ,
+#> # picklistValues.label.3 , picklistValues.value.3 ,
+#> # picklistValues.active.4 , picklistValues.defaultValue.4 ,
+#> # picklistValues.label.4 , picklistValues.value.4 ,
+#> # picklistValues.active.5 , picklistValues.defaultValue.5 ,
+#> # picklistValues.label.5 , picklistValues.value.5 ,
+#> # picklistValues.active.6 , picklistValues.defaultValue.6 ,
+#> # picklistValues.label.6 , picklistValues.value.6 ,
+#> # picklistValues.active.7 , picklistValues.defaultValue.7 ,
+#> # picklistValues.label.7 , picklistValues.value.7 ,
+#> # picklistValues.active.8 , picklistValues.defaultValue.8 ,
+#> # picklistValues.label.8 , picklistValues.value.8 ,
+#> # picklistValues.active.9 , picklistValues.defaultValue.9 ,
+#> # picklistValues.label.9 , picklistValues.value.9 ,
+#> # picklistValues.active.10 , picklistValues.defaultValue.10 ,
+#> # picklistValues.label.10 , picklistValues.value.10 ,
+#> # picklistValues.active.11 , picklistValues.defaultValue.11 ,
+#> # picklistValues.label.11 , picklistValues.value.11 ,
+#> # picklistValues.active.12 , picklistValues.defaultValue.12 ,
+#> # picklistValues.label.12 , picklistValues.value.12 ,
+#> # picklistValues.active.13 , picklistValues.defaultValue.13 ,
+#> # picklistValues.label.13 , picklistValues.value.13 ,
+#> # picklistValues.active.14 , picklistValues.defaultValue.14 ,
+#> # picklistValues.label.14 , picklistValues.value.14 ,
+#> # picklistValues.active.15 , picklistValues.defaultValue.15 ,
+#> # picklistValues.label.15 , picklistValues.value.15 ,
+#> # picklistValues.active.16 , picklistValues.defaultValue.16 ,
+#> # picklistValues.label.16 , picklistValues.value.16 ,
+#> # picklistValues.active.17 , …
```
In the future more features will be migrated from **RForcecom** to make the