Crystalから始めるsalesforce生活 

# 前口上

結構前ですが、Crystal用のHerokuのbuildpackを作りました。  
https://github.com/msky026/heroku-buildpack-crystal  

Crystal用のbuildbackは公式含め結構あるので、自分に合うのを使えばいいかと思いますが、個人的には色々と細かく設定できたほうがいいので（特に現在のcrystalは破壊的変更が多いのでバージョン指定が出来ないと辛いのと、frost用にビルドコマンドの指定が必要だったので）、自作してみました。  

使い方等は[こちら](http://qiita.com/HKDnet/items/73894c1fe49835ce98f2)でも解説いただいたり、また技術書典で配布しました「[Crystalの本（100円）](https://gumroad.com/l/SlTpy#)」に記載していますので今回は端折ります。

# crystalforce

さて本題ですが、Herokuに続いてCrystal用のsalesforceのREST APIクライアントを作りました。
というか、Ruby用のrestforceの仕様をベースに見よう見まねで作ってみました。

[crystalforce](https://github.com/msky026/crystalforce)

使い方については大体restforceの簡略版的なものになっていますので、先にこちらの記事を見ていると感覚がつかめると思います。

[databasedotcom(gem)、restforceでsalesforceに繋いでみる](http://qiita.com/msky026/items/0dbb22f59d61e578f77c)

## salesforceでの設定

sf側での設定手順はだいたい以下のとおりです。  

- 接続 -> ビルド -> 作成 -> アプリケーション から 新規の接続アプリケーションを選択し、適当な名前で作成。
- コンシューマ鍵と、コンシューマ秘密鍵を生成。
- コールバックURLはhttp://localhost/callbackとかで。
- 各ユーザの「私の設定」から、アクセストークンの設定（設定したメールに届く）も必要。

作成した接続用アプリの権限も適宜設定しておいてください。  
接続アプリケーションの、作成したアプリのOAuthポリシーで、「すべてのユーザは自己承認可能」とかになってないと繋がらないかもしれません。

## crystalforceの使い方

取り敢えずインストールはcrystalではお馴染みの、`shard.yml`に

```
dependencies:
  crystalforce:
    github: msky026/crystalforce
```

を書いて`shards install`で。

使用するときは、ソースに

```
require "crystalforce"
```

と書くと使えます。

## 認証

salesforceに接続するときは以下の設定をします。

```
client = Crystalforce.new({
  :username       => "foo",
  :password       => "bar",
  :security_token => "security_token",
  :client_id      => "client_id",
  :client_secret  => "client_secret"
})
```
- username メールアドレス形式のsalesforceのID
- password salesforceアカウントのパスワード
- security_token salesforceアカウントのトークン
- client_id 接続アプリケーションのコンシューマ鍵
- client_secret 接続アプリケーションのコンシューマ秘密鍵

追加オプションで

- api_version salesforceのAPIバージョンを指定（34.0とか割と新しめのにしとくとベター）
- host sandboxに繋ぐときは「test.salesforce.com」を設定

今のところ接続は、上記設定方法のみです。
（restforceはもっといろんな方法ができましたけども）

## CRUD

基本的な機能は今のところ、query発行、削除、更新、作成、のCRUDのみです。

### query

データを取得したいときはこんな感じです。

```
testobj = client.query("select Id, Name__c from Testobj__c")
```
上記で以下の様な結果が返ってきます。

```
[{"attributes" => {"type" => "Testobj__c", "url" => "/services/data/v34.0/sobjects/Testobj__c/a011000000hhd2oAAA"}, "Id" => "fafdafafad", "Name" => "typeb_1"}, {"attributes" => {"type" => "Testobj__c", "url" => "/services/data/v34.0/sobjects/Testobj__c/a011000000hhd2oAAA"}, "Id" => "a011000000hhd2oAAA", "Name" => "a1"}, {"attributes" => {"type" => "Testobj__c", "url" => "/services/data/v34.0/sobjects/Testobj__c/a011000000ku88tAAA"}, "Id" => "a011000000ku88tAAA", "Name" => "typea_1"}, {"attributes" => {"type" => "Testobj__c", "url" => "/services/data/v34.0/sobjects/Testobj__c/a011000000mLzZ7AAK"}, "Id" => "a011000000mLzZ7AAK", "Name" => "testobj222"}]
```

クエリに指定したIdとNameをtestobj["Id"]やtestobj["Name"]で参照できます。

### query_all

```
testobj = client.query_all("select Id, Name__c from Testobj__c")
```
上記でもクエリの結果が取得できますが、queryとの違いは隠しパラメータが見えるかどうかです。

### create

以下の手順でデータの作成が行えます。

```
# Add a new account
client.create('Account', {:Name => 'Foobar Inc.'})
# => '0016000000MRatd'
```

### update

データの更新は以下の用に設定します。

```
# Update the Account with `Id` '0016000000MRatd'
client.update('Account', '0016000000MRatd', {:Name => 'Whizbang Corp'})
# => true
```

### destroy

最後に削除は以下のとおりです。

```
# Delete the Account with `Id` '0016000000MRatd'
client.destroy('Account', '0016000000MRatd')
# => true
```

## 今後考えていること

restforceでやってたことで、クエリ結果のパラメータをオブジェクトのように参照できないかとか。

例えば、

```
testobj = client.query("select Id, Name__c from Testobj__c")
```
の結果はtestobj.Idとかの形で参照できないか、です。ただしこれはrestforceでもMashというツールを使っていることで実現しているのでCrystalでは別の方法が必要ですが。