概要
emacsでApexの開発をしたくて以下の環境で2日くらい試していた時の構成記録。
CUIのテキストエディタ+ターミナルに閉じて無理に開発してみた風になっており、Emacs成分はほとんどなし。
使うもの
- Emacs
- Apex Mode https://github.com/orangatame/apex-mode
- Force CLI https://force-cli.heroku.com/
環境
- Mac OS X Yosemite 10.10.3
- Salesforce Summer'15
- Emacs 24.3.1
Emacs
apex-mode( https://github.com/orangatame/apex-mode )を導入
site-lisp/あたりのパスの通るところに配置して
init.elあたりで (require 'apex-mode)
する。
java-mode風のインデントとApex特有のシンタックスハイライトがなされる。
Force.CLI セットアップ
- Download for Max OS X を押下すると、約9MBのforceファイルが落ちてくる
- 必要に応じてパスを通す
使い方
Force CLIを組織にログイン
force login
を実行するとブラウザが立ち上がりSalesforceのログイン画面が開くのでログイン(すでにログイン済みであればこの工程はスキップ)。
ログイン後、Force CLIのアクセス許可を求められるので、「許可」する。
ブラウザ画面がログイン成功を示す画面に変われば、ブラウザは用済み。
ターミナルはforce login
コマンドの実行が終了し、以下の出力がされる。
# force login
Logged in as 'your.user@name.com'
#
以上でログインは完了。
Force CLIで組織上のメタデータをダウンロード
force export metadata
metadataはダウンロード先ディレクトリ(実行時点で存在しなくてもよい)
上記実行により、metadataディレクトリ以下にメタデータが落ちてくる
# force export metadata
Not done yet. Will check again in five seconds.
Not done yet. Will check again in five seconds.
Not done yet. Will check again in five seconds.
Not done yet. Will check again in five seconds.
Exported to /path/to/metadata
# tree metadata -d 2
metadata
├── applications
├── approvalProcesses
├── assignmentRules
├── autoResponseRules
├── classes
├── communities
├── flows
├── homePageLayouts
├── labels
├── layouts
├── objectTranslations
├── objects
├── pages
├── permissionsets
├── profiles
├── quickActions
├── remoteSiteSettings
├── reportTypes
├── roles
├── sharingRules
├── tabs
└── workflows
Apexクラスの作成
HogeController.clsを作成するために必要なファイルは以下の2つ。
- Apexクラスファイル: HogeController.cls
- メタデータファイル:HogeController.cls-meta.xml
apex-modeによるApexクラスファイルのインデント、ハイライト具合はこんな感じ。
おおよそはJavaモードのインデントを引き継いでおり、Apexのプリミティブについてシンタックスハイライトが登録されている。
なお、2010年に1発コミットされて以来、開発に動きはない模様。
メタデータファイルの生成やテストメソッドの記述イディオムをちまちまyasnippetに登録し、
auto-complete-modeを併用して幾分つらみを和らげている。
メタデータを組織にデプロイ
force deploy
コマンドで作成したクラスのデプロイ実行。
単ファイルではなく、まとめてデプロイする場合はforce import
も用意されている。
# force push -f metadata/classes/HogeController.cls
Validating and deploying push...
Deploying now...
Successes - 1
HogeController: changed
The deployment took 3.316292192s to run.
なお、コンパイルエラーなどでデプロイに失敗した場合は Failuresに 対象クラスとエラー理由が出力される。
# force push -f metadata/classes/HogeController.cls
Validating and deploying push...
Deploying now...
Failures - 1
"metadata/classes/HogeController.cls", line 14: Error Invalid field total_inventory__c for SObject Merchandise__c
Successes - 0
The deployment took 3.287677949s to run.
上ではデプロイ対象の指定にファイルパス指定オプションを使っているが、他にもいくつか指定方法あり。
Apexテストの実行
force test テストクラス名
により、テストが実行され、テストの成否やカバレッジが出力される。
# force test HogeControllerTest
Coverage:
0% HogeController
Results:
[PASS] HogeControllerTest::throughTest
[FAIL] HogeControllerTest::failTest: System.AssertException: Assertion Failed: テスト未実装
Class.HogeControllerTest.failTest: line 7, column 1
verboseオプションを付与 force test -v
することで、詳細な実行ログが出力され、デバッグ出力やガバナ制限項目の消費値が確認できる。
# force test -v HogeControllerTest
{34.0 APEX_CODE,DEBUG;APEX_PROFILING,INFO
01:20:00.068 (68518045)|EXECUTION_STARTED
01:20:00.068 (68568478)|CODE_UNIT_STARTED|[EXTERNAL]|01p28000001HfrB|HogeControllerTest.failTest
01:20:00.069 (69227698)|METHOD_ENTRY|[2]|01p28000001HfrB|HogeControllerTest.HogeControllerTest()
01:20:00.069 (69244379)|METHOD_EXIT|[2]|HogeControllerTest
01:20:00.115 (115722142)|USER_DEBUG|[6]|DEBUG|*******SYSTEM DEBUG**********
01:20:00.115 (115858396)|EXCEPTION_THROWN|[7]|System.AssertException: Assertion Failed: テスト未実装
01:20:00.116 (116098970)|FATAL_ERROR|System.AssertException: Assertion Failed: テスト未実装
Class.HogeControllerTest.failTest: line 7, column 1
01:20:00.116 (116118234)|FATAL_ERROR|System.AssertException: Assertion Failed: テスト未実装
(中略)
01:20:00.181 (181497661)|TESTING_LIMITS
01:20:00.181 (181497661)|LIMIT_USAGE_FOR_NS|(default)|
Number of SOQL queries: 0 out of 100
Number of query rows: 0 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 1 out of 150
Number of DML rows: 1 out of 10000
Maximum CPU time: 0 out of 10000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 100
Number of Email Invocations: 0 out of 10
Number of future calls: 0 out of 50
Number of queueable jobs added to the queue: 0 out of 50
Number of Mobile Apex push calls: 0 out of 10
01:20:00.181 (181497661)|CUMULATIVE_LIMIT_USAGE_END
ログ出力は結構な量になるので、埋めたSystem.debugの確認だけがしたいときはgrepにパイプしている。
# force test -v HogeControllerTest | grep -F "USER_DEBUG"
01:23:38.058 (58869426)|USER_DEBUG|[6]|DEBUG|*******SYSTEM DEBUG**********
executeAnonymousコードの実行
適当なファイル(ex. snippet.cls)に実行したいコードを書いて、
M-x
からコマンド force apex snippet.cls
を叩いている。
バッファ内のコードを実行するのではなく、ただ保存ファイル指定を実行しているだけなので、ファイルバッファの保存が漏れていたりして悲しくなることがある。
使い捨てバッファの使い方とか、elispをちゃんと使えるとスマートに行けるのかもしれない。
SOQLの実行
termからforce query
するだけ。
# force query "
select id, name, (select name from contacts) from account
order by name
"
Id | Name | Contacts
--------------------+-------------------------------------+-------------------
00128000003D3jjAAC | Burlington Textiles Corp of America | Name
| |-------------------
| | Rogers Jack
--------------------+-------------------------------------+-------------------
00128000003D3jlAAC | Dickenson plc | Name
| |-------------------
| | Young Andy
--------------------+-------------------------------------+-------------------
00128000003D3jiAAC | Edge Communications | Name
| |-------------------
| | Forbes Sean
| | Gonzalez Rose
--------------------+-------------------------------------+-------------------
(中略)
(13 records)
出力フォーマットとしてcsvやjsonも指定できる。
親子クエリの結果で子が複数存在する場合のCSV出力 [map[a] map[b]]
が見慣れなくて3度見ぐらいした。
# force query "
select id, name, (select name from contacts) from account
order by name
" --format:csv
"Name","Contacts","Id"
"Burlington Textiles Corp of America","[map[Name:Rogers Jack]]","00128000003D3jjAAC"
"Dickenson plc","[map[Name:Young Andy]]","00128000003D3jlAAC"
"Edge Communications","[map[Name:Forbes Sean] map[Name:Gonzalez Rose]]","00128000003D3jiAAC"
"Express Logistics and Transport","[map[Name:Davis Josh] map[Name:Levy Babara]]","00128000003D3jnAAC"
"GenePoint","[map[Name:Frank Edna]]","00128000003D3jfAAC"
"Grand Hotels & Resorts Ltd","[map[Name:Bond John] map[Name:Barr Tim]]","00128000003D3jmAAC"
"Pyramid Construction Inc.","[map[Name:Stumuller Pat]]","00128000003D3jkAAC"
"sForce","[map[Name:Nedaerk Siddartha] map[Name:Llorrac Jake]]","00128000003D3jqAAC"
"United Oil & Gas Corp.","[map[Name:Song Arthur] map[Name:Green Avi] map[Name:Boyle Lauren] map[Name:Pavlova Stella]]","00128000003D3jpAAC"
"United Oil & Gas, Singapore","[map[Name:D'Cruz Liz] map[Name:Ripley Tom]]","00128000003D3jhAAC"
"United Oil & Gas, UK","[map[Name:James Ashley]]","00128000003D3jgAAC"
"University of Arizona","[map[Name:Grey Jane]]","00128000003D3joAAC"
"テスト取引先01","<nil> ","00128000003HpKWAA0"
sql-modeみたいに、カーソルがフォーカスしているクエリをC-c C-c
で送り込んで結果をバッファに出せる、となれば嬉しい...
tmux内で通知機能を使用する場合のハングアップ回避について
Salesforce組織とAPIでやりとりする都合か、単発のテストクラス実行でも数秒待たされる。
force notify true
としておくことで、テストやデプロイの終了時にデスクトップ通知を出すことができる。
事前にterminal-notifierをbrew install terminal-notifier
で入れておくこと。
ただし、tmux環境で使用していると、tmux-notifierがハングする現象が発生した。
下記に記載させていただいているページの対応を行い正常に通知が表示されることを確認。
ref.http://qiita.com/shrkw/items/33ba17224235b14a1649
願い
Apexクラス作成すると*-meta.xmlを勝手に作ってくれたり、テストクラス生成したり、テストクラスと実装クラスを行き来したり、カレントバッファのファイルをデプロイしたり、regionのApexコードとかSOQLを投げて結果をバッファに流すようなapex-modeの出現への期待が高まる。