SalesforceにおけるWebサービスコールアウトのテスト完全ガイド

SalesforceでRecord Typeを動的に取得および利用する方法


SalesforceでRecord Typeを動的に取得および利用する方法

Salesforceでは、Record Typeを正確に取得するための戦略が重要です。特にAppExchangeアプリのような強力なアプリケーションを開発する際には、IDやNameを直接参照するのではなく、DeveloperNameを使用してRecord Typeを識別することが推奨されます。以下に、Record Typeを動的に取得し、環境やユーザー設定に依存しない方法を詳しく説明します。


1. なぜDeveloperNameを使用するのか

  • Idの問題: Record TypeのIDは環境ごとに異なるため、特定のIDに依存するコードは移植性がありません。
  • Nameの問題: Nameはユーザーの言語やローカライズ設定に基づいて変化するため、信頼できる識別子として使用できません。
  • DeveloperNameの利点: 変更不可能な一意の識別子であり、どの環境でも同じ値を保持します。

2. 動的なRecord Type取得メソッド

以下は、指定したオブジェクトの利用可能なRecord TypeをDeveloperNameで動的に取得するユーティリティメソッドの例です。このメソッドはキャッシュを活用して効率を向上させています。

  1. public class Utils {
  2. // Record types cache
  3. private static Map<Schema.SObjectType, Map<String, Id>> rtypesCache;
  4. private static List<SObject> results;
  5.  
  6. static {
  7. rtypesCache = new Map<Schema.SObjectType, Map<String, Id>>();
  8. results = new List<SObject>();
  9. }
  10.  
  11. /**
  12. * 指定されたオブジェクトタイプの利用可能なRecordTypeを取得する
  13. * @param token Schema.SObjectType
  14. * @return Map<String, Id> DeveloperNameをキーとするRecordType IDのマップ
  15. */
  16. public static Map<String, Id> getRecordTypeMapForObjectGeneric(Schema.SObjectType token) {
  17. // キャッシュ確認
  18. Map<String, Id> mapRecordTypes = rtypesCache.get(token);
  19. if (mapRecordTypes != null) {
  20. return mapRecordTypes;
  21. }
  22.  
  23. mapRecordTypes = new Map<String, Id>();
  24. rtypesCache.put(token, mapRecordTypes);
  25.  
  26. // Describe情報を取得
  27. Schema.DescribeSObjectResult obj = token.getDescribe();
  28.  
  29. // RecordTypeをSOQLで取得
  30. if (results.isEmpty()) {
  31. String soql = 'SELECT Id, DeveloperName, sObjectType FROM RecordType WHERE IsActive = TRUE';
  32. try {
  33. results = Database.query(soql);
  34. } catch (Exception ex) {
  35. results = new List<SObject>();
  36. }
  37. }
  38.  
  39. // RecordTypeInfoを取得し、ユーザーに利用可能なものをフィルタリング
  40. Map<Id, Schema.RecordTypeInfo> recordTypeInfos = obj.getRecordTypeInfosByID();
  41. for (SObject rt : results) {
  42. if (recordTypeInfos.containsKey(rt.Id) && recordTypeInfos.get(rt.Id).isAvailable()) {
  43. mapRecordTypes.put(String.valueOf(rt.get('DeveloperName')), rt.Id);
  44. }
  45. }
  46.  
  47. return mapRecordTypes;
  48. }
  49. }

3. 使用例

以下のコードは、`Account`オブジェクトのRecord Typeを動的に割り当てる例です。

  1. // Utilsクラスを使用してAccountのRecordTypeを取得
  2. Map<String, Id> accountTypes = Utils.getRecordTypeMapForObjectGeneric(Account.SObjectType);
  3.  
  4. // 各RecordTypeのDeveloperNameとIdをデバッグ出力
  5. for (String developerName : accountTypes.keySet()) {
  6. System.debug('RecordType DeveloperName: ' + developerName + ', Id: ' + accountTypes.get(developerName));
  7. }
  8.  
  9. // 特定の条件に基づいてRecordTypeを利用
  10. if (accountTypes.containsKey('Really_Stinking_Big_Account')) {
  11. System.debug('RecordType "Really_Stinking_Big_Account" is available with Id: ' + accountTypes.get('Really_Stinking_Big_Account'));
  12. } else {
  13. System.debug('RecordType "Really_Stinking_Big_Account" is not available.');
  14. }

4. この方法の利点

  1. 移植性の高さ: DeveloperNameを使用することで、どの環境でも正確にRecord Typeを特定可能。
  2. ユーザーや環境に依存しない: `isAvailable`プロパティを活用して、実行中のユーザーに利用可能なRecord Typeのみを使用。
  3. AppExchange対応: 動的SOQLを利用するため、Record TypeをサポートしないProfessional EditionやGroup Editionにも対応。
  4. パフォーマンス: キャッシュを利用してクエリ回数を削減。

まとめ

このアプローチにより、Salesforceアプリは柔軟性と堅牢性を備えた設計が可能になります。特に複雑な権限管理や多言語対応が求められる場合に効果的です。

コメント