カスタムオブジェクトおよびパッケージでの動的参照の使用
パッケージ開発者は動的 Visualforce バインドを使用して、ユーザがアクセスできる項目のみをリストできます。これが必要になるのは、オブジェクトの項目を表示する Visualforce ページを含む管理パッケージを開発する場合などです。パッケージ開発者は登録者がアクセスできる項目がわからないため、動的ページを定義して登録者ごとに表示を変えることができます。
次の例は、Visualforce ページを使用するページレイアウトと一緒にパッケージされたカスタムオブジェクトを使用して、異なる登録ユーザに同じページを表示する方法を示します。
-
Book という名前 (API 参照名は Book__c) で次の項目とデータ型を持つカスタムオブジェクトを作成します。
- Title: Text(255)
- Author: Text(255)
- ISBN: Text(20)
- Price: Currency(5, 2)
- Publisher: Text(255)
- Book ページレイアウトを編集して、カスタム項目が最初に表示され、作成者、最終更新者、所有者、名前など、いくつかの標準項目が削除されるようにします。
- 新規カスタムオブジェクトタブを作成します。オブジェクトを Book に、タブスタイルを Books に設定します。
- [Book] タブに切り替えて、Book オブジェクトをいくつか作成します。値は関係ありませんが、数件のレコードが実際に存在する必要があります。
- 次のコードで BookExtension という名前のコントローラ拡張を作成します。
1public with sharing class BookExtension { 2 3 private ApexPages.StandardController stdController; 4 5 public BookExtension (ApexPages.StandardController ct) { 6 this.stdController = ct; 7 if( ! Test.isRunningTest()) { 8 // You can't call addFields() in a test context, it's a bug 9 stdController.addFields(accessibleFields); 10 } 11 } 12 13 public List<String> accessibleFields { 14 get { 15 if (accessibleFields == null) { 16 // Get a list (map) of all fields on the object 17 Map<String, Schema.SobjectField> fields = 18 Schema.SobjectType.Book__c.fields.getMap(); 19 20 // Save only the fields accessible by the current user 21 Set<String> availableFieldsSet = new Set<String>(); 22 for (String s : fields.keySet()) { 23 if (fields.get(s).getDescribe().isAccessible() 24 // Comment out next line to show standard/system fields 25 && fields.get(s).getDescribe().isCustom() 26 ){ 27 availableFieldsSet.add(s.toLowerCase()); 28 if(Test.isRunningTest()) System.debug('Field: ' + s); 29 } 30 } 31 32 // Convert set to list, save to property 33 accessibleFields = new List<String>(availableFieldsSet); 34 } 35 return accessibleFields; 36 } 37 private set; 38 } 39} - このコントローラ拡張を使用して Book オブジェクトの値を表示する、booksView という名前の Visualforce ページを作成します。
1<apex:page standardController="Book__c" extensions="BookExtension" > 2 3 <apex:pageBlock title="{!Book__c.Name}"> 4 <apex:pageBlockSection > 5 6 <apex:repeat value="{!accessibleFields}" var="f"> 7 <apex:pageBlockSectionItem > 8 9 <apex:outputLabel value="{!$ObjectType['Book__c'].Fields[f].Label}"/> 10 <apex:outputText value="{!Book__c[f]}"/> 11 12 </apex:pageBlockSectionItem> 13 </apex:repeat> 14 15 </apex:pageBlockSection> 16 </apex:pageBlock> 17 18</apex:page> - コントローラ拡張はパッケージ化されるため、Apex クラスのテストを作成する必要があります。手始めに次の基本的なコードで BookExtensionTest という名前の Apex クラスを作成します。
1@isTest 2public class BookExtensionTest { 3 4 public static testMethod void testBookExtension() { 5 6 // Create a book to test with 7 Book__c book = new Book__c(); 8 book.Author__c = 'Harry Lime'; 9 insert book; 10 11 Test.startTest(); 12 13 // Add the page to the test context 14 PageReference testPage = Page.booksView; 15 testPage.getParameters().put('id', String.valueOf(book.Id)); 16 Test.setCurrentPage(testPage); 17 18 // Create a controller for the book 19 ApexPages.StandardController sc = new ApexPages.StandardController(book); 20 21 // Real start of testing BookExtension 22 // BookExtension has only two methods; to get 100% code coverage, we need 23 // to call the constructor and get the accessibleFields property 24 25 // Create an extension with the controller 26 BookExtension bookExt = new BookExtension(sc); 27 28 // Get the list of accessible fields from the extension 29 Set<String> fields = new Set<String>(bookExt.accessibleFields); 30 31 // Test that accessibleFields is not empty 32 System.assert( ! fields.isEmpty()); 33 34 // Test that accessibleFields includes Author__c 35 // This is a bad test; you can't know that subscriber won't disable 36 System.assert(fields.contains('Author__c'.toLowerCase()), 37 'Expected accessibleFields to include Author__c'); 38 39 Test.stopTest(); 40 41 } 42 43} - bookBundle という名前のパッケージを作成し、カスタムオブジェクト、Visualforce ページ、bookExtensionTest Apex クラスを追加します。ページのコントローラ拡張 Apex クラスなど、その他の参照される要素は自動的に追加されます。
- bookBundle パッケージを登録者組織にインストールします。
- パッケージがインストールされたら、Book のオブジェクト管理設定から、Rating という名前の新しい項目を追加します。
- 新規 Book オブジェクトを作成します。ここでも、レコードの値は実際には関係ありません。
- URL にパッケージ名前空間とブック ID を追加したものを使用して、booksView ページに移動します。たとえば、GBOOK が名前空間で、a00D0000008e7t4 がブック ID の場合、最終的な URL は https://Salesforce_instance/apex/GBOOK__booksView?id=a00D0000008e7t4 になります。
登録者組織からページが表示されると、ページにはパッケージ化された Book 項目のすべてと、新しく作成された Rating 項目が含まれます。異なるユーザおよび組織は引き続き必要な項目を追加でき、動的 Visualforce ページは、適宜調整されて表示されます。