$Action を使用した action メソッドへの動的参照
$Action グローバル変数を使用すると、オブジェクトの種別または特定のレコードに対する有効なアクションを動的に参照できます。これは、そのアクションを実行するために URL を作成する場合によく使用されます。
たとえば、<apex:outputLink> で式 {!URLFOR($Action[objectName].New)} を、sObject の名前を提供するコントローラメソッド getObjectName() と一緒に使用できます。
その例を次に示します。コントローラ拡張は、システムを照会して、ユーザがアクセスできるすべてのカスタムオブジェクトの名前を取得し、そのリストを、新規レコードを作成するためのリンクと一緒に表示します。最初に、DynamicActionsHandler という名前でコントローラ拡張を作成します。
この拡張では、次の点に留意してください。
1public with sharing class DynamicActionsHandler {
2
3 public List<CustomObjectDetails> customObjectDetails { get; private set; }
4
5 public DynamicActionsHandler(ApexPages.StandardController cont) {
6 this.loadCustomObjects();
7 }
8
9 public void loadCustomObjects() {
10 List<CustomObjectDetails> cObjects = new List<CustomObjectDetails>();
11 // Schema.getGlobalDescribe() returns lightweight tokens with minimal metadata
12 Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe();
13 for(String obj : gd.keySet()) {
14 if(obj.endsWith('__c')) {
15 // Get the full metadata details only for custom items
16 Schema.DescribeSObjectResult objD = gd.get(obj).getDescribe();
17 if( ! objD.isCustomSetting()) {
18 // Save details for custom objects, not custom settings
19 CustomObjectDetails objDetails = new CustomObjectDetails(
20 obj, objD.getLabel(), objD.isCreateable());
21 cObjects.add(objDetails);
22 }
23 }
24 }
25 cObjects.sort();
26 this.customObjectDetails = cObjects;
27 }
28
29 public class CustomObjectDetails implements Comparable {
30 public String nameStr { get; set; }
31 public String labelStr { get; set; }
32 public Boolean creatable { get; set; }
33
34 public CustomObjectDetails(String aName, String aLabel, Boolean isCreatable) {
35 this.nameStr = aName;
36 this.labelStr = aLabel;
37 this.creatable = isCreatable;
38 }
39
40 public Integer compareTo(Object objToCompare) {
41 CustomObjectDetails cod = (CustomObjectDetails)objToCompare;
42 return(this.nameStr.compareTo(cod.nameStr));
43 }
44 }
45}- loadCustomObjects メソッドは Apex スキーマメソッドを使用して、使用可能なカスタムオブジェクトに関するメタデータ情報を取得します。Schema.getGlobalDescribe メソッドは、使用可能なオブジェクトとカスタム設定に関する小さいメタデータセットを取得するための軽量の操作です。メソッドは、コレクションをスキャンして名前の末尾が「__c」(カスタムオブジェクトまたは設定であることを示す) の項目を探します。これらの項目は、getDescribe を使用してより詳細に調査され、選択したメタデータがカスタムオブジェクト用に保存されます。
- if(obj.endsWith('__c')) を使用して、項目がカスタムオブジェクトであるかどうかをテストするのは、「ハッキング」のように感じられるかもしれませんが、もう 1 つの選択肢である obj.getDescribe().isCustom() コールにはコストがかかり、getDescribe へのコール数にガバナ制限があります。大量のオブジェクトが含まれている可能性があるリストに対しては、「__c」文字列のスキャンを最初に行うのが効率的です。
- このメタデータは、内部クラス CustomObjectDetails に保存されます。このクラスは、保存すべき項目の単純な構造化されたコンテナとして機能します。
- CustomObjectDetails には Comparable インターフェースが実装されており、各オブジェクトの属性 (この場合はカスタムオブジェクト名) でカスタムオブジェクト詳細のリストを並び替えることができます。
ここで、次のマークアップで Visualforce ページを作成します。
特定のレコードが割り当てられていないページで使用できる便利なアクションは、New と List の 2 つのみです。レコードを照会するページで、$Action グローバル変数は、View、Clone、Edit、Delete などのメソッドを提供します。特定の標準オブジェクトには、データ型に適した追加のアクションがあります。
1<apex:page standardController="Account"
2 extensions="DynamicActionsHandler">
3 <br/>
4
5 <apex:dataTable value="{!customObjectDetails}" var="coDetails">
6 <apex:column >
7 <apex:facet name="header">Custom Object</apex:facet>
8 <apex:outputText value="{!coDetails.labelStr}"/>
9 </apex:column>
10 <apex:column >
11 <apex:facet name="header">Actions</apex:facet>
12 <apex:outputLink value="{!URLFOR($Action[coDetails.nameStr].New)}"
13 rendered="{!coDetails.creatable}">[Create]</apex:outputLink><br/>
14 <apex:outputLink value="{!URLFOR($Action[coDetails.nameStr].List,
15 $ObjectType[coDetails.nameStr].keyPrefix)}">[List]</apex:outputLink>
16 </apex:column>
17 </apex:dataTable>
18
19</apex:page>