はじめに
Apexで開発していく中で、使用頻度が上位にくる(かもしれない)クラスとしてSchema.DescribeSObjectResultが挙げられます。
さて、このクラスを取得する方法によって、結果が異なることがありました、ということでいくつか試してみたいと思います。
DescribeSObjectResultの取得パターン
さて、DescribeSObjectResult
を取得するのに、3パターンほど思い浮かぶかと思います。(以下Account
オブジェクトを対象にしてます)
①SObjectクラスからトークンを取得しながら...
Schema.DescribeSObjectResult d = Account.sObjectType.getDescribe();
②Schemaクラスから対象オブジェクトのトークンを取得しながら...
Schema.DescribeSObjectResult d = Schema.getGlobalDescribe().get('Account').getDescribe();
③Schemaクラスから取得...
Schema.DescribeSObjectResult d = Schema.describeSObjects(new List<String>{'Account'})[0];
全て、Account
オブジェクトのDescribe Informationを取得するだけのコードで、特に変わったこともない(つもり)です。
さて、ココでAccount
オブジェクトへの作成、編集、削除権限がないユーザで、上記コードを実行してみましょう。
作成、編集、削除権限のないユーザで実行してみる
※以下のコードを試す場合には、test method内で実行ください
List<Profile> profiles = [Select Id From Profile Where Name IN ('Read Only','参照のみ')];
Profile p = profiles[0];
User testUser = new User(
alias = 'hogehoge',
email = 'smith@salesforce.com',
emailencodingkey = 'UTF-8',
lastname = 'smith',
languagelocalekey = 'en_US',
localesidkey = 'en_US',
profileid = p.Id,
timezonesidkey = 'America/Los_Angeles',
username = 'smith@salesforce.com.forsample'
);
System.runAs(testUser){
Schema.DescribeSObjectResult d1 = Account.sObjectType.getDescribe();
System.assertEquals(d1.isAccessible(), true);
System.assertEquals(d1.isCreateable(), false);
System.assertEquals(d1.isDeletable(), false);
System.assertEquals(d1.isUpdateable(), false);
Schema.DescribeSObjectResult d2 = Schema.getGlobalDescribe().get('Account').getDescribe();
System.assertEquals(d2.isAccessible(), true);
System.assertEquals(d2.isCreateable(), false);
System.assertEquals(d2.isDeletable(), false);
System.assertEquals(d2.isUpdateable(), false);
Schema.DescribeSObjectResult d3 = Schema.describeSObjects(new List<String>{'Account'})[0];
System.assertEquals(d3.isAccessible(), true);
System.assertEquals(d3.isCreateable(), false);
System.assertEquals(d3.isDeletable(), false);
System.assertEquals(d3.isUpdateable(), false);
}
上記のコードを実行してみると、
System.assertEquals(d3.isCreateable(), false);
の箇所にて、
System.AssertException: Assertion Failed: Expected: true, Actual: false
というエラーが発生します。上2つの方法で取得した結果と異なりました。
Schema.describeSObjects(List)のリファレンスを見ると、【使用方法】には
このメソッドは、Schema.sObjectType トークンの getDescribe メソッドと類似しています。getDescribe メソッドと異なり、このメソッドでは sObject 型を動的に指定して、複数の sObject を一度に記述できます。
最初に getGlobalDescribe をコールして組織のすべてのオブジェクトのリストを取得します。その後リスト内を反復処理し、describeSObjects を使用して個々のオブジェクトのメタデータを取得します。
とあります。
"リスト内を反復処理し...個々のオブジェクトのメタデータを取得します" といった中で、メタデータ取得に関しては、システム権限で実行されてしまうのだろうと推測します。
(そのため、期待する結果が得られなかった、と)
さいごに
結局のところ、Schema.DescribeSObjectResult
を取得したいときには、Schema.describeSObjects(List<String>)
を使わない方が無難だよ、ということでしょうか。
(システム管理者権限でしか使わない、という前提があれば話は別ですが)
しかし、気付きにくい違いだったなぁ...と。(苦笑)