きゃらめるの備忘録

Salesforceに関してお勉強したことをまとめるブログ。目指せ週1更新~~~!

LWCのコンポーネント間イベントのクセが強い(気がする)

こんばんは、きゃらめるです。
なんとか10月内に2本、技術的な内容のブログを更新できました!やった!

本題:コンポーネント間のイベントのクセ、とは

ということで、前回の記事にてお話していた、LWC(Lightning Web Component)でコンポーネント間でのイベントについてです。
前回のブログで私は、「LWCは、子から親へのイベント発火部分が、階層構造を感じさせないような作りになっている」と書きました。

私が今まで触った経験のあったVue.jsは、親子関係がとてもはっきりしており、子→親にしかイベントを発火できません。
この関係性はとてもシンプルですが、コンポーネントの階層が深くなるとバケツリレー的にイベントを発火する必要があります。
qiita.com
※まさにこちらの記事が分かりやすかったので引用しました。

一方、LWCは、孫から親にイベントを発火できます。
正確に言うと…孫が発火したイベントを、孫の直属の親である子だけではなく、その親も受け取れてしまいます。
なんなら、自分の子ではないコンポーネントからのイベントすらも受け取れてしまいます。

図で書いた方が分かりやすい気がしたので図にしてみました。
f:id:calamel_nuts:20201030194656j:plain
f:id:calamel_nuts:20201030194621j:plain

得意なこと・不得意なこと

2つのイベントの違いを見てきましたが、場面によって得意・不得意があると思っています。

例えば、自分の子コンポーネントがイベントを発火した時だけ親コンポーネント側で処理をしたいという場面は結構発生すると思います。
Vue.jsでは「子からのイベントしか受け取らない」という制約のお陰で「イベントを発火したのが自分の子であるか?」をプログラム側で確認する必要がありません。
一方LWCでは別の子が発火したイベントも拾ってしまうため、実装時には「イベントを発火したのは自分の子であるか?」を確認する処理を書きました。(ここ、私の知識不足だったら教えていただきたいです…最適解を知りたい…)

逆に、コンポーネント階層が深くなった場合や親の兄弟等にイベントを渡したい場合、Vue.jsで管理しようとすると複雑になってしまう問題点もありました。(こういった状態管理の複雑さを軽減するために、Vuexが出てきたと認識しています。)
LWCではイベントの受け取り相手に制限がない分、階層の構造や深さに依存して複雑性が上がる、という部分は軽減されているように思います。

おわりに

なんだか、Vue.jsとLWCの比較をしてしまったばかりに、「どっちがいいのか?」みたいな記事になってしまいましたが、LWC上でVue.jsをインポートして使おうぜ!みたいなことではないです。(今思いつきで書いたけど、できるのかな…。)

まだまだLWCに関する記事ってあまり出てこないので、もっとLWCの特性を学んで正しく使って行きたいものです。
もし間違っているよ!という記述があれば、ぜひとも教えてください…。

コンポーネント設計について考えてみた

こんばんは、きゃらめるです。
最後の公開記事の更新が9/1なので、ギリギリ月1回頻度の更新ですね…。
今期は、会社の個人目標にブログの更新を掲げてみました。最低月2回は技術的な更新を目指して頑張ります!
と言っても、本日正式に目標提出したばかりなので、10月がかなりギリギリ…!!
なんとか今週2本、記事をアップできればと思います。

一旦近況報告をしておきますと、前回のブログ更新日となっている9/1から2つ資格を取得しました!

嬉しい!!!!
資格という自分のスキルの証拠が欲しかったので、本当に本当に嬉しいです!!!
次の目標は「Salesforce 認定 Platform デベロッパー」を取ることです。
そして来年の7月…転職して1年でアプリケーションアーキテクトになることを一つの年間目標にしています。
頑張るぞ…!!

本題:LWCのコンポーネントはどんな単位で分割するか

ということで本題です。相変わらずLWC(Lightning Web Component)を触っているので、またLWCの話です。

LWCに限らずですが、コンポーネントを利用する際、どんな単位でコンポーネントを分割するかを決めるのって、結構コツが要る気がしています。
シンプルな画面であれば、1画面に1コンポーネントでもなんとかなると思うのですが、ちゃんとコンポーネント設計を行い、各コンポーネントの役割を単純にしてあげた方が保守性は高くなると思います。
…と言っても、深い階層関係(親・子・孫…のような関係)を作ってしまうと、データのやりとりが煩雑になって逆に保守性が下がってしまう可能性もありますよね。
そこで今回は、私がコンポーネントを使って画面作成する場合に、どんな単位に切り分けているのかを残しておこうと思います。

その1:モーダルウィンドウ

モーダルウィンドウは以下の水色枠で囲われた部分のような要素です。
f:id:calamel_nuts:20201026220720p:plain
この画像ははてなブログの編集画面で「もっと見る」(画像の黄色枠の部分)をクリックすると表示されます。
このようなモーダルウィンドウは、1要素として切り出すのがおすすめです。
モーダルウィンドウはウィンドウというだけあって、別のページを重ねて表示しているような要素なので、親の状態を気にせずに切り出すことが可能な場合が多いです。

ちなみに、モーダルウィンドウの表示・非表示の切替についてですが、表示・非表示を管理するフラグを用意してあげるのがわかりやすいかと思います。

その2:繰り返しのある要素

HTML側でforやiteratorを使う場合や、同じ見た目のまとまりをページ内に複数回記載する場合は、その1要素分をコンポーネント化できないか考えます。
例えば表がある場合に、表の1行分を1コンポーネントとするイメージです。

ただし!今回LWCを使ってみて知ったのですが、LWCで表の1行をコンポーネント化しようとすると単純には行きません。。
コンポーネント化することで、なぜか「1マス」に1行分のデータが入り込んでしまう現象が発生します。
その時はCSSに以下の記述を記載します。

:host {
    display: table-row;
}
その3:複雑なロジックを持つ1要素

これが一番言葉にするのが難しいのですが…私がお仕事で実装した機能を例にすると、「商品型番の最初の何文字かを入力すると、前方一致で商品を検索して候補を表示してくれるルックアップフォーム」を実装した際はコンポーネントに切り分けました。

このフォームを実装する場合、

  • 入力文字から商品の情報を検索
  • 商品候補の表示・非表示を切り替える
  • ユーザが商品を選択した場合は確定した商品名を表示し、入力を受付ないようにする

などなど、細かい制御やデータ取得が必要になります。
これを親ページにべたっと書いてしまうと、親ページのJSが長くなり、保守性が下がります。

コンポーネントに切り分ける意図は、コンポーネントの責務を分離することによる保守性の向上だと思っています。
小さな要素1つであっても、そこに複雑なロジックや複数の状態管理が必要なのであれば、それを分離する旨味は十分あるかなと思います。

これらを全部コンポーネント化すればいいの?

最初にも記載しましたが、無闇にコンポーネントを増やしても旨味は少ないため、
コンポーネント化が必要か否か」を考えることが大事かと思います。
観点としては、
(1)切り分けたコンポーネント単位での処理が行われることがあるか?
(2)コンポーネント内のコンテンツは動的な計算やデータ取得などの加工を行う必要があるか?
(3)コンポーネント化することによって、階層が深くなりすぎないか?
あたりは考えるようにしています。

(1)は例えば、表の1行単位で行の追加機能や削除機能がある場合、1行を1コンポーネントに切り分けた方が楽かもしれません。
特に、その1行の中に複数の要素がある場合、その塊を複製したり、削除したり、という処理は面倒なことが多いです。
複数の要素を1コンポーネントとして扱うことで、一見、親側では「1要素」を複製・削除するように扱うことができるため、管理がシンプルになるかと思います。

(2)については、コンポーネントの中身の複雑性です。
計算やデータ取得など、一手間加えた内容を表示させる場合は、コンポーネントに切り出すことで1つのJSに記述される量を減らすことができます。
逆に、表示しているだけで何も動的に値が変わらない場合は、切り分けても旨味が少ない可能性があります。

(3)については、階層が深くなりすぎる場合、親側でのデータ管理が複雑になりやすいため、避けるようにしています。
コンポーネントから子コンポーネントへデータを渡す場合、子側では@apiプロパティを用意して受け取ることになります。
階層が深くなる場合、例えば「ひ孫でしか使わない情報を、ひ孫を呼び出す孫と、その親の子コンポーネントに渡す」というような感じで、親からバケツリレー形式でデータを渡すことになります。

ただ、LWCは、子から親へのイベント発火部分が、階層構造を感じさせないような作りになっているので、もしかすると階層の深さの影響は少ないかもしれません。
(ここらへん、他の方どうしてるんだろう…)

コンポーネント設計のはじめ方

私は画面を実装する時、画面イメージに線を書いてみて、どこを切り出すか考えます。
例えば、はてなブログの記事の管理画面の、記事一覧をコンポーネント化するならこんな感じかもしれません。
f:id:calamel_nuts:20201026213319p:plain
オレンジの枠は、例でも挙げた、表の1行の繰り返し部分です。
ピンクの枠や水色の枠の部分は、オレンジの枠内にある1つの部品です。
では、ピンクの枠・水色の枠で囲っている部品と、枠で囲われていない部品の差はなんでしょうか?
例えば、タイトルはリンクという機能がついているものの、コンポーネント化は必要ないと判断しました。
これは、aタグ一つで実現できる程度の機能だからです。そういったシンプルな要素をコンポーネント化する旨味はないと判断しました。

ピンクの枠で囲った要素は、クリックするとリストメニューのようなものが出てきます。
つまり、状態の管理やクリック時にイベントが発生するなど、このボタンがクリックされ、メニューが選択されるまでにいくつかの処理が挟まります。
そのため、これはコンポーネントに分けておくことで、親ページ側の記述を減らすことができます。

水色の枠で囲った要素は、正直切り分けるか悩みましたが、元データになっているブログ内容を固定の文字長に切る、という加工が入っているので、コンポーネント分けてもいいかもな〜と思って分けてみました。ここは好みかと思います。

といった具合に、画面イメージに直接書き込むことで、コンポーネント化する部分が目で見て分かりやすくなるので、自分の備忘録としてももちろん、チーム内レビューや設計書として残す場合にも伝わりやすくなるのでオススメです!

おわりに

えらい長くなってしまった。。

こんなことを言ってしまうと元も子もないのですが、結局自分の思ったようにコンポーネントを分けてみて、失敗したり、成功したりすることで、感覚が掴める部分なのかなと思っています。また、場合によってメリットよりデメリットが上回ることもあり得ます。
今回もLWC開発でコンポーネント設計をしてみて、「LWCがこういう仕様なら、ここはコンポーネント分けなきゃよかったな…」みたいなこともありましたので、基礎的な考えは持ちつつ、実装してみて都合が悪かったらやめることも大事かと思います!

今週、もう一本書きたいな〜と思っている内容は、LWCの親子間イベントの渡し方についてです。
上でちょっと触れましたが、あまり階層関係を感じさせないイベントの渡し方になっているなと思ったので、他のフレームワークも調査して、ブログを書ければと思っています!
よかったらそちらもよろしくお願いします!

LWCのリアクティブプロパティで詰まった話

こんばんは。きゃらめるです。
最近、お仕事でLWC(Lightning Web Component)を触っているのですが、LWCの奥深さに四苦八苦しています。。
Trailheadをやっていただけじゃ分かっていなかった、あんなこと、こんなことが盛り沢山でした…。
ひさびさに、こんなガッツリフロント側のコード書いてる〜〜〜〜!!!!楽しい〜〜〜〜!

本日の本題:LWCのリアクティブプロパティ

※そもそも、@trackを指定した変数=リアクティブプロパティと呼ぶことすら、このブログを書いている時に知りました。アウトプット大事。

そんな感じでLWCを触っていて、まじ!?って思ったことが一つ。
リアクティブプロパティのデータのバインディングが双方向じゃないところ。

元々JS側のフレームワークでまともに触れたことあるのがVue.jsだけだったので、なんとなく「リアクティブプロパティは双方向バインディングなんだろう」という前提でコードを触っていました。
今回のお仕事では、画面にたくさん入力フォームがあり、lightning-inputを使っています。そのvalueにリアクティブプロパティをセットしてあげると、初期値は正しく入るのですが、入力フォームに値を入力しても、バインドしているはずの変数に値が入ってくれない!!
最初は、私の書き方が悪いのか、それとも元々の仕様なのかも切り分けできなかったので、とにかく調べた&上司にヘルプを出しました。

しばらく調べた結果、下記の記事に辿り着きました。
www.desynit.com

We can summarise this saying that, while in aura data binding was bidirectional, in LWC is unidirectional. This means, for sending information from a parent to a child LWC, we use properties. While child components pass data up by firing events.

Auraコンポーネントのデータバインディングは双方向だったけど、LWCは一方向のバインティングなので、親→子に値を渡せても、子が親を変更することはできない、というようなことが書いてあります。
私はAuraを触った経験も乏しいので、Auraはそうなんだーくらいに思っていました。

そこでやっと理解できたのですが、結局lightning-inputなどのフォームの要素も1つのコンポーネントなんですね。
つまり、画面全体を親コンポーネントだとみなした時、lightning-inputを配置することは「入力フォーム要素を持った子コンポーネント」を呼び出している、と。

f:id:calamel_nuts:20200902000724p:plain
※念のため…実際のお仕事の画面ではありませんm(_ _)m

valueに変数を指定しているのを見ると、あたかもその変数を共有して双方向に書き換えるようなイメージを持ってしまうのですが、
画面全体が親コンポーネント、lightning-inputが子コンポーネントだと考えてみると、

valueに値をセットするのは、親が子に初期値のデータを渡している。
親の値を変更したい時は子からイベントを発火して変更する。

ここら辺がすんなり理解できました。

逆に、もしかしてVue.jsの仕様の方が結構特殊なのか…??だから双方向データバインディングに慣れない、という人がいるのかも。。

ということで、勝手な勘違いで混乱したよ〜というお話でしたm(_ _)m
他にもいろいろ詰まっているので、ちょこちょこブログに残して行けたらいいなぁ…。

来週は、初級アドミンの試験を受けてきます!!今週は業務も試験勉強も頑張るぞ〜〜〜!!

VSCodeのExtensionによるオブジェクトメタデータの形式違いについて

すごくご無沙汰しています。きゃらめるです。
最近ブログ更新してないですね、とお声をかけてくださった方がいて、久々にブログ書こう!という気持ちになりました笑

Salesforceエンジニアになる!と始めたブログを、さぼり続けて1年以上…
先月7月1日付で、Salesforceエンジニアとして転職いたしました!
やった~~~~!!!

ブログの更新が止まり、勉強会へ顔を出す機会も減った2019年でしたが、業務としてはSalesforceに向き合う機会がかなーり増えていました。
その結果、ご縁があって、SalesforceのDeveloperとして受託開発のお仕事をさせていただくことになりました。
転職活動の話も、またブログに公開していきたいと思います!

また、9月16日(水)開催のイベント「Japan Woman In Tech #4」に、パネラーとして登壇させていただくことになりました!
こちらでも転職関連のお話をさせていただきます。どうぞよろしくお願いいたします!!!
trailblazercommunitygroups.com

本日の本題

ということで、久しぶりのブログでいろいろ書きたいネタはあるんですが、
前職での業務中に詰まりに詰まったことがあって、その経験が現職でも少し役立ったので、そちらの話を。
タイトルの通り、Visual Studio CodeVSCode)の拡張機能(Extension)の種類によってオブジェクトメタデータの形式が違うよね~って話です。
多分、VSCodeで開発している人だったら知っている人多いんだろうなーと感じたのですが、前職の私はめちゃくちゃはまって、調べてもわからなくて困り果てたので、ここに残しておきます。

SFDXとForceCode

VSCodeのExtensionの内、Salesforceのプロジェクトを管理できるものは(私が知っている限りでは、)2種類あります。
Salesforce Extension Pack」と「ForceCode」です。

以前、このブログで記載した開発環境構築の方法では、以下のQiita記事を参考に、Salesforce Extension Packを使いました。
qiita.com
VSCode内のコマンドが「SFDX:」なので、私はSFDXと呼んでいます。
Trailhead内でもおススメされているのはこのSFDXで、公式が管理しているOSSのようです。
すごく簡単にプロジェクト作成~デプロイまでできるのでいいですよね!

もう一方のForceCodeは公式が管理しているものではないようですが、こちらも同様にプロジェクトの作成やSalesforceの環境からのコードの取得、デプロイなどが行えます。
最初にプロジェクトを作ってみると、srcフォルダとforce.jsonという設定ファイルが一つだけ準備されるというシンプル構成になっています。
その後、接続するSalesforce組織の設定や、コードの取得をおこなっていくことによってファイルが増えていきます。

オブジェクトメタデータの形式

オブジェクトメタデータは、各オブジェクトの項目やリストビュー、レコードタイプとそれに紐づく選択リスト項目の値などを管理しています。

開発者コンソールでは、Open Resourceから確認することができます。
f:id:calamel_nuts:20200823181800p:plain
この「.objectファイル」を、SFDXとForceCodeでそれぞれ取得してみましょう。

まずは、SFDXから。
force-app/main/defaultフォルダ内のobjectsフォルダに入っています。
f:id:calamel_nuts:20200823182916p:plain
1オブジェクト1フォルダになっているのがわかります。
取引先のオブジェクトのファイルの中身を見てみると、さらにfields、listViews、webLinksに分かれていますね。
そして、Account.object-meta.xmlがあります。
fieldsフォルダを見てみましょう。
f:id:calamel_nuts:20200823183230p:plain
1項目1ファイルで作成されています。
ファイルの拡張子の通りですが、XMLでそれぞれの項目の情報が記載されています。
f:id:calamel_nuts:20200823183414p:plain

それでは、ForceCodeでも見てみましょう。
srcフォルダ内のobjectsフォルダ内に入っています。
f:id:calamel_nuts:20200823183629p:plain
お気づきかと思いますが、1オブジェクト1ファイルになっています。
拡張子は「.object」ですが、中身はXMLです。
f:id:calamel_nuts:20200823183750p:plain
すべての項目の情報が1ファイルにまとまっています。
f:id:calamel_nuts:20200823184006p:plain

注意した方がいいこと

正直、Apex系の開発であれば、どちらのExtensionを使っていても大きな差は感じませんでした。
私はSFDXの方がお手軽な気がしてそちらで開発環境を作りがちですが、ForceCodeも至ってシンプルなので、それはそれで使い易いです。
ただ、チームで開発する場合…しかも変更対象にオブジェクトメタデータが含まれている場合は、どちらの形式で管理するのかを確認しておいた方がいいかと思いました。
そして、できればどちらでも使えるようになっておく方が便利かと思います!

独り言

前職でこの問題に詰まったとき、上司と私でオブジェクトメタデータの形式が違ってかなり混乱しました…笑
「あるオブジェクトの類似オブジェクトを作りたい。設定や項目を一つ一つ作り直すのはツラいから、オブジェクトのメタデータを使おう!」
となったのですが、上司が話している内容と、私の開発画面で見ているものの話が合わない…。
.objectが拡張子のファイルなんてそもそもないんだけど…?となりました。
ネットで調べてみましたが、それっぽい情報も見当たらず、最終的には上司のPCをしばらく借りて、設定ファイルの差分を洗い出してパラメータを書き換えてみたり、試行錯誤してやっとExtensionの違いに行きつきました。

つい最近の業務で、途中参加したプロジェクトのトリガーを書かせていただきました。
SFDXでプロジェクトを作って開発を始めたのですが、後から共有されたGitHubソースコードを見たら、オブジェクトがForceCodeの形式で管理されていて、その後オブジェクトの項目も更新することになったのでForceCodeで環境を作り直しました。
これ、前職で詰まった経験がなかったら、このタイミングで原因究明に時間がかかったんだろうなーと思います。。
というのも、チームにVSCode使って開発している人がいなかったので。。
Salesforceの専門性を高めたい!と転職しましたが、なんだかんだと前職での経験に生かされているな~と感じる今日この頃です。

ということで、最後はまた転職の話に戻ってしまいましたが…笑
自分がここで詰まった!みたいな部分はこれからまだまだ出てくると思うので、少しずつ記事にできればと思います!

恵比寿Salesforce勉強会とSalesforceSaturday 池袋に参加していました!

こんにちは、きゃらめるです。
最近本業務の方が大きなリリース前で、結構バタバタしております。。
本業務も好きなんですが、毎日遅くまで脳みそ使うのはしんどいですね…。

まぁ、平日の分、なんとか土日で勉強せねば~ということで、
1月19日の「第16回 恵比寿Salesforce勉強会」と
2月2日の「SalesforceSaturday 池袋 #03」に参加してきました!

恵比寿Salesforce勉強会

ebisu-salesforce.connpass.com

こちらは今回が初参加!

前回参加した池袋の勉強会より、人数の規模も会場も大きかったです。
その分、作業中に参加者同士で話すことは少なく、
(知り合いの方と参加しておられる方はコミュニケーション取っておられました!)
作業を進めるというところに集中していた感じでした。
平日に時間取れない分、こうやって集中できる時間はありがたいですね!
イヤホンをしてノリノリで作業してました。

あと、おすすめのTrailMixの情報がイベントページのコメントで送られていたり、
Leaderboardでバッチやポイントの獲得数が可視化されていたり…。
タイトルに「Trailheadもくもく会」とついているだけに、
Trailheadを進めたい人のための情報が提供されているなと感じました!
ただ、別にTrailheadを進めている方だけではなくて、私もLT会の登壇資料とか作ってました~。

もちろん(?)、作業中の飲食はOK。
恵比寿駅からも近く、すぐそこにコンビニがありました。
会場は毎回同じなのかな?
人数は多いのですが、作業スペースは十分です!

もくもく会のあとは懇親会があります。
机や椅子を移動させて、お酒とピザ・お菓子が出ていましたよ~。
私は、先約があって懇親会には参加できなかったのですが、
あれだけ多くのSalesforce担当者の方が集まっているので、きっと面白い話が聞けたんだろうな…。
第17回は参加できないので、第18回を楽しみにしようと思います!

SalesforceSaturday 池袋

salesforcesaturday-ikebukuro.connpass.com

こちらは前回も参加して、ブログを書かせていただいていますm(_ _)m
calamel-nuts.hateblo.jp

参加人数も少人数で、場所もこじんまりとしているのですが、
個人的には、これくらいの規模感がちょうどリラックスできるかもしれない…笑

今回は、Salesforceを触り始めた方からSalesforceの猛者な方まで集まっていました!
Trailheadを進めておられる方が多かったですが、
業務で困っていることを質問して、猛者な方に教えてもらっている参加者の方もおられました!


※ツイート拝借しました;

私も便乗して、もくもく会終了~懇親会までの間に、業務の悩みを相談させていただいたり…。
作業時間を確保するために勉強会に来ている側面ももちろんあるのですが、
こうやって、Salesforce担当者の方とやりとりができるのは本当にありがたいです~~~!

また、前回もお菓子をお土産にもってきてくださった方がいらっしゃったんですが、
今回もお菓子をいただきました。。ありがとうございます!!
私なんて自分で食べる用のお菓子しか持ってきてなかったのに…かたじけない…。
次回用に日持ちするお菓子を買ってきておこうと心に決めました笑
懇親会は前回同様近くのお店で開催されるとのことだったんですが、今回は所用で参加できず…。
こちらもも次回こそかなー…。。

SalesforceSaturday 池袋 に参加してきた話

今更ながら、あけましておめでとうございます。
きゃらめるです。
今日は、こちらの勉強会に参加してきました。
salesforcesaturday-ikebukuro.connpass.com

SalesforceSaturday Tokyoとは?

上記のConnpassページの説明文をお借りすると、「土曜日にSalesforceの勉強をしたいみなさんを繋げて盛り上げる」コミュニティとのこと。
いわゆる、もくもく会形式の勉強会を開催しておられます。
Trailheadをやっておられる方が多かったですが、Salesforceの動画を見たり、イベントの準備をしたり、
いろんな方がいらっしゃいました^^
今回は池袋のイベントでしたが、恵比寿や赤坂でも開催しておられるそうです。
ちなみに、1月19日は恵比寿で開催されるそうです!(私も参加します!)

ebisu-salesforce.connpass.com

今回私がやったこと

今回は2つのモジュールを完了させました!


今までは既存のコードを見ながら雰囲気でApexを書いていました。
なので、ちゃんとイチからApexを学び直そう!と思い、この2つのモジュールを勉強することにしました^^
普段書いているコードなのに、改めて勉強し直すと知らないこともちらほら…。

例えば、Trailheadに例として出ていたこのSOQL。

SELECT Name, (SELECT LastName FROM Contacts) FROM Account WHERE Name = 'SFDC Computing'

取引先のName項目と、取引先に紐づく取引先責任者のLastName項目を取得することができます。
こんな風に、親レコードに対する子レコードの情報を1文のSOQLで取得することができるんです。
す、すごい~~~!なんで今まで知らなかったんだ~~~!笑
これ、カスタムオブジェクト同士だったら、参照/主従の関係を定義している項目のAPI参照名が、
FROM句(上のクエリだったら「Contacts」)に入るのかな?
試してみよう…。

あと、SOSLは本当に使ったことがなかったのでこちらも驚き。こんな言語もあったのね!
複数オブジェクトの全項目対象で検索かけられるの、すごいとは思うけど、
レコード数増えた時がちょっと怖いような気もしました。
レコード数が増えても高速に検索できるんだろうか…?

トリガに関しても学ぶことが多く…。
例えば、弊社のトリガでは(意外に)ちゃんと一括でデータ挿入や更新をしているんですが、
そのあたりの書き方も、今までは独自の実装なんだと思っていました。
今回Apexトリガのモジュールをやってみて、その方法がSalesforceから推奨された実装だということも分かりました。
今まで、
「既存がこう書いてるから、とりあえず合わせておこう」
「既存でこの処理したいときにこう書いてるから、コピペすればいけるやろ」
くらいの気持ちで書いてたApexコードの意味が、やっとちゃんとわかってきたような気がします…!
はじめてプログラミングを習って、if文とかfor文が使えるようになったころのワクワク感に似てる笑

イベント中は、基本的に自分のタスクをもくもくと進めていたんですが、
「同じSalesforceを勉強している人が近くにいる」という状況で勉強するのはいいですね!!!
すごく捗りますし、安心感がありました!!
また、飲み物・食べ物も持ち込み可能だったので、おやつをもぐもぐしながら勉強できたのもよかったです笑
19日の勉強会も楽しみです~~~!^^

SandBox更新をかけた結果、ローカル開発環境ではまった話

こんばんは、きゃらめるです。
今日は掲題の通りの話をしたいと思います。
ネット上で探しても、ズバリ!という解決策が見当たらなかったので、
せっかくなので残しておきます…。

発生したこと

以前の記事で、Apex開発時のローカル開発環境をVisual Studio Codeに変更しておりました。
calamel-nuts.hateblo.jp

私の場合、弊社のSandBox環境と連携させています。
これによって快適なローカル開発が行えていたのですが…
先週SandBoxを更新したことにより、「Retrieve Source from Org」が効かなくなってしまいました。
Retrieve Source from Orgは、親環境の最新のソースコードを下ろしてくる大事なコマンド。
その他、OAuth接続する系のコマンド全て(デプロイなども)効かなくなりました。

そして、エラーには以下の文言が…

ERROR:  This org appears to have a problem with its OAuth configuration. Reason: invalid_grant - authentication failure 
username: xxx@zzzz.co.jp.test, 
clientId: <Not Specified>, 
loginUrl: https://test.salesforce.com, 
privateKey: <Not Specified>. 

clientIdやprivateKeyが指定なしになっている…!!

原因調査

はじめに、弊社で使っているSalesforceSVF Cloudでも、SandBoxの更新をかけると接続できなくなるので、原因としては同じかな?という仮説を立てました。
つまり、

  • SandBoxの更新をかける
  • SandBoxが新しい組織になってしまう
  • 今までの接続情報ではログインできなくなる。

ということで、今までOAuth接続できていたものができなくなったと。

ということはやることは一つ!
再度、組織を紐づけ直してあげればいけるはず!

解決策

で、この組織を紐づけ直すという作業をどうしたらいいのかが分からず、
いろいろ調べていました。
その結果、

sfdx force:auth:web:login

このコマンドを実行することで解決しました!

コマンドを実行すると、いつものSalesforceのログイン画面が開きます。
その画面からログインをすると、アクセスの許可を求める画面が開きます。
そこでアクセス許可をすると、以下の内容がVisual Studio Codeのターミナルに表示されます。

Successfully authorized xxx@zzzz.co.jp.test with org ID 00Xx00000000xxxXXX
You may now close the browser

これで完了です!よかった~~~!

解決方法が分かっても、コマンドを覚えてなさすぎて結構ハマってしまいました。
sfdxのコマンドにも、これから少しずつ慣れて行かなきゃいけないなと思ったできごとでした…。
会社のTipsとしてもまとめておこう~~~。