You need to sign in to do that
Don't have an account?

Grab the record name from any Id
I am trying to write a trigger that will look at a field where a salesforce Id has been loaded. I want to then have the trigger populate another field with the record's name. The catch here is that the Id can be from any object including chatter objects. Is this something that can be done since the object itself is not defined? Also, these records would need to handle in batches since they will be dataloaded. I'm am only just learning apex so any help from the community would be really appreciated.
Thanks
Thanks
<pre>
trigger GetRecordNameFromId on Funky_Object__c ( before insert, before update )
{
// this is a map of "name" fields for objects that don't have one
Map<String,String> nameFields = new Map<String,String>
{ 'Task' => 'Subject'
, 'FeedItem' => 'Title'
// add more object and field names here
};
// this map will hold Record IDs grouped by object name
Map<String,Set<String>> idsBySObjectName = new Map<String,Set<String>>();
// this map will hold Funky Objects that look up to a specific record
Map<Id,List<Funky_Object__c>> funkyObjectsByRecordId = new Map<Id,List<Funky_Object__c>>();
for ( Funky_Object__c funkyObj : Trigger.new )
{
// no Record ID, no Record Name
if ( funkyObj.Record_Id__c == null )
{
funkyObj.Record_Name__c = null;
continue;
}
// use the Record ID to get the object name
String sObjectName = String.valueOf( Id.valueOf( funkyObj.Record_Id__c ).getSObjectType() );
// add the Record ID to the collection for that object name
if ( ! idsBySObjectName.containsKey( sObjectName ) )
{
idsBySObjectName.put( sObjectName, new Set<String>() );
}
idsBySObjectName.get( sObjectName ).add( '\'' + funkyObj.Record_Id__c + '\'' );
// add the Funky Object to the collection for the Record ID
if ( ! funkyObjectsByRecordId.containsKey( funkyObj.Record_Id__c ) )
{
funkyObjectsByRecordId.put( funkyObj.Record_Id__c, new List<Funky_Object__c>() );
}
funkyObjectsByRecordId.get( funkyObj.Record_Id__c ).add( funkyObj );
}
for ( String sObjectName : idsBySObjectName.keySet() )
{
String nameField = nameFields.get( sObjectName );
if ( nameField == null ) nameField = 'Name';
// create a query for all records of a single type
List<String> queryStrings = new List<String>
{ 'SELECT Id,'
, namefield
, 'FROM'
, sObjectName
, 'WHERE Id IN'
, '(' + String.join( new List<String>( idsBySObjectName.get( sObjectName ) ), ',' ) + ')'
};
// for each record in the query results,
// write its name to all the Funky Objects that look up to it
for ( sObject obj : Database.query( String.join( queryStrings, ' ' ) ) )
{
Id recordId = (Id) obj.get( 'Id' );
String name = (String) obj.get( nameField );
for ( Funky_Object__c funkyObj : funkyObjectsByRecordId.get( recordId ) )
{
funkyObj.Record_Name__c = name;
}
}
}
}
</pre>
All Answers
<pre>
public trigger GetRecordNameFromId on Funky_Object__c ( before insert, before update )
{
// build a map of all the Record ID Prefixes in this org
Map<String,String> keyPrefixes = new Map<String,String>();
for ( Schema.SObjectType sObjectType : Schema.getGlobalDescribe().values() )
{
Schema.DescribeSObjectResult objDescribe = sObjectType.getDescribe();
keyPrefixes.put( objDescribe.getKeyPrefix(), objDescribe.getName() );
}
// this is a map of "name" fields for objects that don't have one
Map<String,String> nameFields = new Map<String,String>
{ 'Task' => 'Subject'
, 'FeedItem' => 'Title'
// add more object and field names here
};
// this map will hold Record IDs grouped by object name
Map<String,Set<String>> idsBySObjectName = new Map<String,Set<Id>>();
// this map will hold Funky Objects that look up to a specific record
Map<Id,List<Funky_Object__c>> funkyObjectsByRecordId = new Map<Id,List<Funky_Object__c>>();
for ( Funky_Object__c funkyObj : Trigger.new )
{
// no Record ID, no Record Name
if ( funkyObj.Record_Id__c == null )
{
funkyObj.Record_Name__c = null;
continue;
}
// use the Record ID prefix to look up the object name
String sObjectName = keyPrefixes.get( funkyObj.Record_Id__c.left( 3 ) );
// add the Record ID to the collection for that object name
if ( ! idsBySObjectType.containsKey( sObjectName ) )
{
idsBySObjectType.put( sObjectName, new Set<String>() );
}
idsBySObjectType.get( sObjectName ).add( '\'' + funkyObj.Record_Id__c + '\'' );
// add the Funky Object to the collection for the Record ID
if ( ! funkyObjectsByRecordId.containsKey( funkyObj.Record_Id__c ) )
{
funkyObjectsByRecordId.put( funkyObj.Record_Id__c, new List<Funky_Object__c>() );
}
funkyObjectsByRecordId.get( funkyObj.Record_Id__c ).add( funkyObj );
}
for ( String sObjectName : idsBySObjectName.keySet() )
{
String nameField = nameFields.get( sObjectName );
if ( nameField == null ) nameField = 'Name';
// create a query for all records of a single type
String queryStrings = new List<String>
{ 'SELECT Id,'
, namefield
, 'FROM'
, sObjectName
, 'WHERE Id IN'
, '(' + String.join( new List<String>( idsBySObjectName.get( sObjectName ) ), ',' ) + ')'
};
// for each record in the query results,
// write its name to all the Funky Objects that look up to it
for ( sObject obj : Database.query( String.join( queryStrings, ' ' ) )
{
Id recordId = (Id) obj.get( 'Id' );
String name = (String) obj.get( nameField );
for ( Funky_Object__c funkyObj : funkyObjectsByRecordId.get( recordId ) )
{
funkyObj.Record_Name__c = name;
}
}
}
}
</pre>
<pre>
Map<String,Set<String>> idsBySObjectName = new Map<String,Set<String>>();
</pre>
<pre>
public trigger GetRecordNameFromId on Funky_Object__c ( before insert, before update )
{
// this is a map of "name" fields for objects that don't have one
Map<String,String> nameFields = new Map<String,String>
{ 'Task' => 'Subject'
, 'FeedItem' => 'Title'
// add more object and field names here
};
// this map will hold Record IDs grouped by object name
Map<String,Set<String>> idsBySObjectName = new Map<String,Set<String>>();
// this map will hold Funky Objects that look up to a specific record
Map<Id,List<Funky_Object__c>> funkyObjectsByRecordId = new Map<Id,List<Funky_Object__c>>();
for ( Funky_Object__c funkyObj : Trigger.new )
{
// no Record ID, no Record Name
if ( funkyObj.Record_Id__c == null )
{
funkyObj.Record_Name__c = null;
continue;
}
// use the Record ID to get the object name
String sObjectName = String.valueOf( Id.valueOf( funkyObj.Record_Id__c ).getSObjectType() );
// add the Record ID to the collection for that object name
if ( ! idsBySObjectType.containsKey( sObjectName ) )
{
idsBySObjectType.put( sObjectName, new Set<String>() );
}
idsBySObjectType.get( sObjectName ).add( '\'' + funkyObj.Record_Id__c + '\'' );
// add the Funky Object to the collection for the Record ID
if ( ! funkyObjectsByRecordId.containsKey( funkyObj.Record_Id__c ) )
{
funkyObjectsByRecordId.put( funkyObj.Record_Id__c, new List<Funky_Object__c>() );
}
funkyObjectsByRecordId.get( funkyObj.Record_Id__c ).add( funkyObj );
}
for ( String sObjectName : idsBySObjectName.keySet() )
{
String nameField = nameFields.get( sObjectName );
if ( nameField == null ) nameField = 'Name';
// create a query for all records of a single type
String queryStrings = new List<String>
{ 'SELECT Id,'
, namefield
, 'FROM'
, sObjectName
, 'WHERE Id IN'
, '(' + String.join( new List<String>( idsBySObjectName.get( sObjectName ) ), ',' ) + ')'
};
// for each record in the query results,
// write its name to all the Funky Objects that look up to it
for ( sObject obj : Database.query( String.join( queryStrings, ' ' ) )
{
Id recordId = (Id) obj.get( 'Id' );
String name = (String) obj.get( nameField );
for ( Funky_Object__c funkyObj : funkyObjectsByRecordId.get( recordId ) )
{
funkyObj.Record_Name__c = name;
}
}
}
}
</pre>
<pre>
public trigger GetRecordNameFromId on <your object> ( before insert, before update )
{
}
</pre>
I created a new trigger in the developer console. I'm getting a compile error on line 43 : No viable alternative at character"
That line reads: for ( String sObjectName : idsBySObjectName.keySet() )
<pre>
trigger GetRecordNameFromId on Funky_Object__c ( before insert, before update )
{
// this is a map of "name" fields for objects that don't have one
Map<String,String> nameFields = new Map<String,String>
{ 'Task' => 'Subject'
, 'FeedItem' => 'Title'
// add more object and field names here
};
// this map will hold Record IDs grouped by object name
Map<String,Set<String>> idsBySObjectName = new Map<String,Set<String>>();
// this map will hold Funky Objects that look up to a specific record
Map<Id,List<Funky_Object__c>> funkyObjectsByRecordId = new Map<Id,List<Funky_Object__c>>();
for ( Funky_Object__c funkyObj : Trigger.new )
{
// no Record ID, no Record Name
if ( funkyObj.Record_Id__c == null )
{
funkyObj.Record_Name__c = null;
continue;
}
// use the Record ID to get the object name
String sObjectName = String.valueOf( Id.valueOf( funkyObj.Record_Id__c ).getSObjectType() );
// add the Record ID to the collection for that object name
if ( ! idsBySObjectName.containsKey( sObjectName ) )
{
idsBySObjectName.put( sObjectName, new Set<String>() );
}
idsBySObjectName.get( sObjectName ).add( '\'' + funkyObj.Record_Id__c + '\'' );
// add the Funky Object to the collection for the Record ID
if ( ! funkyObjectsByRecordId.containsKey( funkyObj.Record_Id__c ) )
{
funkyObjectsByRecordId.put( funkyObj.Record_Id__c, new List<Funky_Object__c>() );
}
funkyObjectsByRecordId.get( funkyObj.Record_Id__c ).add( funkyObj );
}
for ( String sObjectName : idsBySObjectName.keySet() )
{
String nameField = nameFields.get( sObjectName );
if ( nameField == null ) nameField = 'Name';
// create a query for all records of a single type
List<String> queryStrings = new List<String>
{ 'SELECT Id,'
, namefield
, 'FROM'
, sObjectName
, 'WHERE Id IN'
, '(' + String.join( new List<String>( idsBySObjectName.get( sObjectName ) ), ',' ) + ')'
};
// for each record in the query results,
// write its name to all the Funky Objects that look up to it
for ( sObject obj : Database.query( String.join( queryStrings, ' ' ) ) )
{
Id recordId = (Id) obj.get( 'Id' );
String name = (String) obj.get( nameField );
for ( Funky_Object__c funkyObj : funkyObjectsByRecordId.get( recordId ) )
{
funkyObj.Record_Name__c = name;
}
}
}
}
</pre>