OmniAICreator/Qiita-1.07M huggingface dataset:
ポートフォリオの流れ　WEBアプリケーションの場合

# ポートフォリオって何作ればいいんだろ？

私と同じく初心者の方はポートフォリオで何を作ればいいのか非常に悩ましいと思います。
しかも、ポートフォリオでいいなと思ってもらえる工夫をしながら、使われているサービスというのが最強となると更に難しいですよね。

ただ、ポートフォリオからは絶対に逃げられないので、まずは最終的に自分がどうなっていればポートフォリオを作れるのかということを自分なりにまとめていきたいと思います。

## そもそも何をどう作るのか

①どういうサービスを作りたいのか
②見た目を考える
③コーディング＆実装する
④WEB上にアップする
⑤使ってもらってフィードバックもらう
⑥こだわった部分などについてスライドでまとめる



## どういうサービスを作りたいのか
これに関しては各自で考えるしかないのですが（元も子もない）
誰かに使ってもらうということを前提に考えると困っている人の役に立つようなサービスを考えるといいと思います。
冒頭にも書いたようにポートフォリオは使われることがすごく重要みたいです。

普段生活しているとき、遊んでいるとき、働いているときに不便だったこととかを常に考えて、
メモしていくといいかなと思います。

例えば私だと、生活の中だと家事やるタイミングが妻と合わないとか、晩御飯のレシピ考えるのが面倒とか、キャンプしたい友達連れて行ってもなかなかキャンプ道具買って始めようとしないとか…（連れて行くとお金と時間かかる…この記事見てないこと祈ろう）

結構有名な未経験のポートフォリオ見ると「それいいんや(笑)」（勘のいいひとは気づくはず）と、思うものもあって気にしないようにしました。

## 最後にポートフォリオ作るときに便利なサイトが色々あったので参考までに書いておきます。

①どういうサービスをリリースするか考える
→意外とtwitterのトレンドになるようなハッシュタグの内容とかを簡単に作れるアプリケーションとか面白いしアイデアが転がってるような気がする。
https://note.com/haken_se_30manen/n/n4f379cc91f11

②Webページの見た目を考える
→まずはオシャンな見た目から入りたいよね
https://io3000.com
https://siiimple.com
→じゃ自分のやつ作ってみよ(サイトマップとかワイヤーフレームとかデザインとか)
https://app.moqups.com
https://www.figma.com

④実装する 
フレームワークは使ってもいいけどちゃんと言語の基礎はやろうね。
Ruby on Rails
Laravel

⑤WEB上にアップする
サーバーにアップしていきましょう。個人なんでAWSの1年間無料の期間を大事に。
https://aws.amazon.com/jp

⑥使ってもらってフィードバックをもらう
これは言わずもがな。普段から独学とかしていること発信してると使ってくれる人増えると思います。
ちなみに私はSNS弱いです…　
https://twitter.com/ssfactory_engin
フォローしてね
https://twitter.com

⑧こだわった部分などについてスライドでまとめる
まぁこれはgoogleスライドとかパワポでいいでしょう。


以上初心者の私が考えているポートフォリオの準備に必要だと思っていることです。
他にもポートフォリオ作る上で役に立ったよーということがあればコメントで教えてください！
SAPユーザの一括登録

新規SAPシステム（ABAPインスタンス）を構築した際にユーザを大量に登録する必要がある場合があります。

SU10で一括登録が可能ですが、以下の問題がありました。
・氏名等、アドレスタブの内容を個別に登録しなければならない
・初期パスワードの指定ができない（自動発行の複雑かつ長いもの勝手に設定される）

そのため、SU10で一旦登録し、eCATTをつかってアドレスタブと初期パスワードの設定をしました。
（作り込みをすればeCATTを使ってユーザ登録全体を自動化することも可能です。）

以下、eCATTの使用方法の概要になります。


①Tr-cd：SECATT
②テストスクリプト登録
　テストスクリプトに任意の名称を入力し[オブジェクト登録]ボタンを押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2820929/21f49378-b1de-459e-7f8f-d83fa382c681.png)

　属性タブにて表題とApplicationコンポーネントを入力する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2820929/cb3eb196-1fa7-a3fe-17a2-24aa5e059877.png)

③トランザクション記録
　[パターン]ボタンを押下
　以下の内容を入力
　　・グループ：UIコントロール
　　・TCD（Record）
　　・トランザクション：SU01
　　・インターフェース：<自動提案>　※トランザクション入力後にEnterを押すことで自動で入力される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2820929/afd1d14f-f667-e68e-eb51-930d1ee3f183.png)

　自動実行させたい処理を行う。
　処理完了後に[前画面]ボタンで戻る。
　記録終了のポップアップにて[はい]を選択。

④コマンドインターフェースの登録
　SECATTの画面に戻るのでエディタタブを選択する
　コマンドインターフェース欄に表示されているインターフェース名をダブルクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2820929/f900d0a7-d772-5ff6-0069-439df374af98.png)

　DYNPROを選択し、[シミュレータ]ボタンを押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2820929/4f1cc9cb-2cdc-6926-b482-166cb37a1514.png)

　先ほど登録したトランザクションが再度実行されるため、変更対象の項目をダブルクリックする（赤枠で表示されている項目）
　ポップアップにて任意のパラメータ名、項目内容を入力する
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2820929/c2db8650-7fb3-d005-07fc-64893f049994.png)

　画面遷移がある場合は[次画面]ボタンを押下し、同様の処理を繰り返す

　最後の画面まで遷移すると元の画面に戻るので[保存]お端を押下する

⑤バリアントのダウンロード
　メニューバーより、[ユーティリティ] -> [テスト設定] -> [登録]

　[バリアントをダウンロード]押下し、テキストファイル形式でダウンロードする
　ダウンロードしたファイルを編集のためExcelで開く
　A列は連番、C列以降に登録したいデータを入力し、保存する

⑥eCATTの実行
Variantタブから[外部バリアント/パス]に先ほど作成したアップロード用のファイルを選択する
[実行]ボタンを押下

開始オプション画面に遷移するので、[実行]ボタンを押下し処理を開始する
処理終了後にログが表示されるため正常終了していることを確認する

【補足】
・eCATTの処理がエラーになる場合はUI Controlタブでフォアグランド実行し、エラー箇所やエラー内容を確認する
・SCC4のクライアントの設定でeCATTが許可されていない場合でも特にエラーは発生しない（処理自体が行われないため）
初めてのPowerApps


# 目次
- 初めに
- Power Appsとは
- SharePointとは
- よく使いそうだと思った関数
- 最後に

# 初めに
この記事は、初めての投稿です。
私のアルバイト先でPower Appsを使うことになったため、学習してきたことをまとめるためにこの記事を書きました。

# Power Appsとは
Microsoft Power Appsとは、Microsoftが提供しているローコード開発ツール **「Power Platform」** の中の一つであるアプリケーションです。

Power Appsでは、プログラミングをしなくても直感的な操作で、ビジネス用アプリケーションを作成し、実行できるアプリケーションです。

大きな特徴として、アプリ画面を同じくMicrosoftが提供しているPowerPointのように作り、Excelのように関数を使ってアプリを動かすことができるため、プログラミング経験がなくても簡単に作成出来るのが大きな特徴です。

# SharePointとは
Microsoft SharePointとは、Microsoftが提供している **「Microsoft 365(旧Office 365)」** のアプリケーションの一つです。

SharePointでは、組織内のチームごとにポータルサイトを作成することができ、そのサイト上で情報の保存、共有などを組織内で安全に利用できます。

今回はSharePointをPower Appsでアプリケーションを開発をするうえで必要なデータベースとして利用します。

# よく使いそうだと思った関数
アルバイト先から提供されたオンライン学習で学んでいった中で、個人的にPower Appsで作成する時によく使いそうだと思った関数をいくつか挙げていきます。

- Navigate
```
 Navigate(画面名)
```
アプリ画面を移動する時に使います。

- Reflesh
```
 Refresh(データベース)
```
特定のデータベースの情報を最新に更新する時に使います。

- If
```
 If(数式, 正の場合, 負の場合)
```
ある数式について合っているか否かで操作を変更する時に使います。

- Back
```
 Back()
```
ひとつ前の画面に移動する時に使います。

- Remove
```
 Remove(データベース, レコード1 [, レコード2, ... ])
```
特定のデータベースからデータを削除する時に使います(複数可)。

- Choices
```
 Choices(テーブル名.列名)
```
選択欄にデータベース内の列の選択肢を表示させる時に使います。

- Distinct
```
 Distinct(テーブル名, 列名)
```
選択欄にデータベース内の列の重複をしないようにする時に使います。

- Filter
```
 Filter(テーブル名, 数式1 [,数式2, ... ])
```
数式を満たしているテーブルの表示を数式によって絞り込む時に使います。

- NewForm
```
 NewForm(フォーム名)
```
フォームを新規作成モードにする時に使います。

- EditForm
```
 EditForm(フォーム名)
```
フォームを編集モードにする時に使います。

- SubmitForm
```
 SubmitForm(フォーム名)
```
フォームに記入されたデータをデータベースに送る時に使います。

- ResetForm
```
 ResetForm(フォーム名)
```
フォームを初期値にする時に使います。

# 最後に
私は今までいろんなノーコードやローコードツールを使ってきましたが、個人的にはPower Appsはかなり使いやすくて気に入っています。

まだ触ったばっかりなので、今後はPower Appsを利用していき、更に深く理解できるようになりたいと思っています。
プリザンターのサーバスクリプトで複数値を取得するルックアップを実現する

# はじめに
今回の記事では、プリザンターのルックアップ機能で実現できない「複数値」を取得する機能をサーバスクリプトで実現します。今回のお問い合わせでは、プリザンター標準機能である「ルックアップ機能」に関するものでした。プリザンターのルックアップ機能では、条件に合致した値を一つだけ取得します。今回のお問い合わせでは、複数値を取得するルックアップ機能をサーバスクリプトで実現できるかどうかというお問い合わせでした。下記スクリプトで実現できましたので共有させていただきます。

# サーバスクリプト
```JavaScript
try {
    // 分類Bに表示する要素
    let lookupElement;
    // リンク先のサイトID
    let siteId = XXXX;
    // 分類Aに何かしら表示されていたら
    if (!(model.ClassA === '[]')) {
        let array = new Array();
        // フィルタ条件を設定
        let data = {
            View: {
                ColumnFilterHash: {
                    // 分類Aの表示内容をもとにリンク先のレコードを絞り込み
                    ResultId: model.ClassA
                }
            }
        }
        // 絞り込み結果をもとにレコード情報を取得
        let results = items.Get(siteId, JSON.stringify(data));
        // 絞り込んだリンク先レコードごとに分類Bを取得
        for (let result of results) {
            // 配列に要素を設定
            array.push(result.ClassB);
        }
        // 配列を「,」区切りの文字列に設定
        lookupElement = array.join(',')
        // 要素を分類Bに設定
        model.ClassB = lookupElement;
    } else {
        model.ClassB = '';
    }
} catch (ex) {
    context.Log(ex.stack);
}
```
リンク先のテーブルからレコードIDとClassAに入力された値が合致するレコード情報を取得します。for文でレコード情報数分処理を反復し、リンク先テーブルから取得したレコードのClassBの値を配列「array」に設定していきます。joinによって、配列「array」に設定された要素を「,」(カンマ)区切りで文字列に変換します。「,」区切りの文字列をClassBに設定します。

# さいごに
今までは「,」区切りの文字列を作成する際は下記のコードのようにif文で作っていました。↓上記サーバスクリプトのfor分内の処理です。  
```JavaScript
    // 絞り込んだリンク先レコードごとに分類Bを取得
    for (let result of results) {
        // 要素がない場合
        if (!lookupElement) {
            // リンク先レコードの分類Bの値を取得
            lookupElement = result.ClassB;
            // 要素がある場合
        } else {
            // リンク先レコードの分類Bの値をカンマ区切りで取得
            lookupElement = lookupElement + ',' + result.ClassB
        }
    }
```
このコードはよくないと指摘を受けましたため、修正したコードが上記のサーバスクリプトになります。動作も確認済みです。  
最近、SI案件やサポートWEBの対応を実施するにつれてプリザンターにはできないことはないのではないかと思っています。そんなプリザンターを作ってしまう社長に対してはとても尊敬しています。それだけではなく、社長は私の上司でもあるのですが、理解力のない私にも私が理解できるまで説明してくれます。指摘してくださる際も私の意見を聞いてくれて、優しく時に厳しく接してくれる社長には感謝しかないです。インプリムに入社して本当に良かったと思っています。
[Tricentis tosca]More than one control found for action

みなさま、お疲れ様です。
最近、回帰テストに於いてTricentis Toscaを使う事がありましたので
良く発生した不具合についてまとめましたので皆さんのお役に立てればと思います。

## 経緯
添付ファイルのような外面をTricentis Toscaを通してテストを実施します。
![スクリーンショット 0004-06-02 11.34.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2500270/91ab41c0-27dc-dedf-cd52-6460522269de.png)
テスト内容は以下の通りです。
１）「確認」のダイアログが表示されていることを確認する。
２）「キャンセル」ボタンを押下します。

Tricentis Toscaから失敗の報告が行われます。
![スクリーンショット 0004-06-02 11.41.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2500270/7f4040a7-79db-3ccf-75e8-551dc8143c4f.png)


## More than one control found for action
エラーの内容としては
画面上に同じコントローラーが見つかりました。

...
なるほど、同じコントローラーがあるとダメ
なら、もう少し細かく見れば良いっということで

## 解決方法１[IDに固定値を設定する]
1)どの「キャンセル」ボタンかを明示的に示す

Tricentis＞module＞キャンセル
![スクリーンショット 0004-06-02 11.50.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2500270/5e02bdb7-c89e-2adb-4c78-a83517e8d45c.png)
「キャンセル」ボタンに実際に設定されている「id」を設定します。
これであれば問題なく「キャンセル」ボタンを押下時のエラーが発生しなくなります。
![スクリーンショット 0004-06-02 11.55.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2500270/39c8095c-8a1e-47d7-80cb-d1e598ee890d.png)

ただし、この修正だと問題があります。
Fiori UI5では「id」の後ろのナンバーは自動的に生成されます。
その為、次に画面を開いた際は対象の「id」が見つかりませんと怒られます。

## 解決方法２[Tricentis　ToscaのScan機能を使い一つ上の要素を範囲に指定する]
Tricentis＞module＞Scan
![スクリーンショット 0004-06-02 11.37.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2500270/3c98e67a-286d-ebda-0180-14d293303ae1.png)
画面右下を見ると
![スクリーンショット 0004-06-02 11.37.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2500270/96b3a7aa-e112-67dd-ab26-e068eb5a638f.png)
添付ファイルのように表示されています。
これは設定した内容が「ユニーク」な値になっていないですよ。
っと言われていますこの部分が「ユニーク」になっていれば今回の場合だと解消されます。
なので
![スクリーンショット 0004-06-02 11.33.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2500270/ab0a2889-5bd3-1780-1d5d-9d410782e7eb.png)
添付ファイルのように「確認」というダイアログの要素に対してチェックを入れることによって
明示的に示すことができます。

## 結果
![スクリーンショット 0004-06-02 11.55.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2500270/39c8095c-8a1e-47d7-80cb-d1e598ee890d.png)
Tricentis Toscaのテストを何度実施しても同じ結果を得ることが出来るようになりました。
rex0220 一覧説明プラグイン

kintone 一覧画面とグラフに説明を表示するプラグインです。

主な特徴
・文字色指定
・html 形式で指定可能
・３ヶ国語対応
・PC対応

Ver.3
・プラグイン設定画面のデザイン変更対応
・プラグイン設定に、「説明」設定機能を追加

# 概要

一覧画面とグラフに説明を表示します。

![2023-04-28_14h56_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/2b15a99e-d228-5341-a841-e0a20a3b87b1.png)

# プラグイン設定

一覧とグラフがリスト表示されますので、表示するメッセージを指定します。

- NOTE：プラグイン設定についてのメモ等
- プラグイン有効
- プラグイン設定のダウンロード
- プラグイン設定のアップロード
- チェック：一覧・グラフの指定有効/無効
- 文字色：　メッセージの色
- メッセージ：　一覧・グラフに表示する説明
    - 未入力時は、一覧名を表示
- 英語：　英語表記のメッセージ
- 日本語：　日本語表記のメッセージ
- 中国語：　中国語表記のメッセージ

![2023-04-28_15h00_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/d9047f27-2f29-0c06-1bec-bc7b5c11eccf.png)

## 文字色

クリックするとカラーパレットが表示されますので、色を選択します。

![2023-04-28_15h02_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ac7be3aa-f5aa-2e9c-e071-4fa2effd9e3e.png)

## メッセージ
クリックすると編集モードになります。

- 文字指定例
![2023-04-28_15h03_48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3996faeb-de35-fdc6-d194-3fb3b85aa722.png)

- html 指定例：フォントサイズを指定
```.html
<div style="font-size:24px;">担当者別売り上げ実績（当月）</div>
```
![2023-04-28_15h04_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a0375760-aac0-1dc2-be06-688847568a34.png)


# 注意事項
- 既に、JavaScript によるカスタマイズを行っているアプリの場合、処理が競合して、エラーになる場合があります。その場合は、該当するアプリでプラグインの使用を中止してください。
の値が設定されていないか、割り当てられていないため、フローでこの値にアクセスできませんでした。


:::note alert
エラー要素 test001 (FlowRecordUpdate)。
このエラーは、フローでレコードの更新が試行されたときに発生しました: $Record.ApprovalRoute__r.Authorizer1__r.User__r.Email の値が設定されていないか、割り当てられていないため、フローでこの値にアクセスできませんでした。
:::

数式リソースを少々変更してからこのエラーになりましたね。

+ $Record.ApprovalRoute__r　はトリガーを発生しているメインのオブジェクトの承認経路という項目。
+ Authorizer1__rは承認経路というオブジェクトの承認者１という項目（ユーザの参照項目）
+ User__r.Emailは上記にセットされている　ユーザのメールアドレス

上記の関係があります。

元の式

```
IF(ISBLANK({!$Record.ApprovalRoute__r.Authorizer1__r.User__r.Email}) ,NULL,{!$Record.ApprovalRoute__r.Authorizer1__r.User__r.Email} ))
```

解決できた式

```
IF(ISBLANK({!$Record.ApprovalRoute__r.Authorizer1__r.User__c}) ,NULL,{!$Record.ApprovalRoute__r.Authorizer1__r.User__r.Email} ))
```

どうもIF文で承認経路のAuthorizer1__r(承認者１)というフィールドが設定されていて、この承認者オブジェクトにはいくつかのフィールドがあります。この承認者オブジェクトのユーザが設定されているか見て判断しないといけなかったのに、そのユーザオブジェクトのメールアドレスがNullなのかを見てしまったのがエラーの原因のようです。

承認者オブジェクトのUser__c(ユーザの参照項目)が設定されていない場合はnullですが、そのnullのメールアドレス項目を参照したのがいけなかったようです。



# 解決に役に立ったヘルプ

+ [プロセスビルダーの「値が設定されていないか、割り当てられていないため、フローでこの値にアクセスできませんでした」エラー](https://help.salesforce.com/s/articleView?id=000382782&type=1)

この種のエラーを回避するには、クロスオブジェクト参照を行う前に、外部キー (別名リレーション) 項目に基づいて、その項目が null かどうかを確認する条件を使用します。

この条件の順序に注意します。参照項目が null でないことの確認は、その参照でクロスオブジェクト参照を行う条件を評価する前に実行する必要があります。

上記の例の続きとして、プロセス条件は [Contact].AccountId Is Null False と [Contact].Account.Name equals Acme で、この順序でなければなりません。AccountId が null かどうかの確認は、値が入力される取引先項目に依存するクロスオブジェクト参照の前に行う必要があります。


[アクションの実行条件] で [数式の評価が true になる] を使用する場合、この例では以下の式を使用できます。

AND (NOT(ISBLANK( [Contact].AccountId )), [Contact].Account.Name = "Acme")

多くの標準リレーションは、項目名に「Id」が含まれ、混乱を招くことがあるため、null 値を確認する必要があります。上記の例を引き続き使用すると、よくある間違いは、[Contact].Account.Id の null を確認しようとすることです。これは、取引先の ID 項目へのクロスオブジェクト参照であるため、[取引先] 参照項目が空白であれば失敗します。正しい条件は [Contact].AccountId (つまり、取引先責任者の [取引先] 参照項目) を確認するものです。ここで注意すべき重要な点は、条件が、別のオブジェクトの「Id」項目へのクロスオブジェクト参照を行うのではなく、参照項目自体を確認することです。
Sqlite3 create table で syntax error が出た時に見てほしい

sqlite3のエラーの備忘録です。

### 結論?
```FOREIGN KEY```より後にカラムを宣言できない

## エラーの再現方法

test.sql
```sql
CREATE TABLE test (
    id INTEGER PRIMARY KEY,
);

CREATE TABLE test2 (
    test_id INTEGER,
    FOREIGN KEY (test_id) REFERENCES test (id),

    bbb INTEGER -- 9行目
);
```

test.sqlと同フォルダ内で次のコマンドを実行します
```
sqlite3 test.db < test.sql
```
すると次のエラーが出力されます
```
Error: near line 6: in prepare, near "bbb": syntax error (1)
```

## エラーの解決方法

結果的に分かったエラーの原因は9行目の```bbb INTEGER```文が

```FOREIGN KEY (test_id) REFERENCES test (id)```

よりも下にあるからと言うことです。

test2.sql
```sql
CREATE TABLE test (
    id INTEGER PRIMARY KEY,
);

CREATE TABLE test2 (
    bbb INTEGER,

    test_id INTEGER,
    FOREIGN KEY (test_id) REFERENCES test (id)
    -- bbb INTEGER
);
```

変えたのは``` bbb　INTEGER ```の位置だけです

しかし、```test2.sql```ではエラーは出力されません。

ドキュメントに目を通してはみましたが、それらしいことは書いていませんでした。

[ドキュメント](https://www.sqlite.org/lang_createtable.html)

## 僕の環境
関係あるかはわかりませんが載せときます
```
$ sqlite3 -version
3.37.0 2021-12-09 01:34:53 9ff244ce0739f8ee52a3e9671adb4ee54c83c640b02e3f9d185fd2f9a179aapl

$ brew -v
Homebrew 4.0.15
Homebrew/homebrew-core (git revision 6819e9e2a22; last commit 2023-02-16)
Homebrew/homebrew-cask (git revision cc58401c09; last commit 2023-02-16)
```

```
macOS Monterey
バージョン 12.6.3
チップ Apple M1
```

## 最後に
調べてもそれらしい記事は見つけられず、エラー文もあまり親切とは言えないので、記事を書きました。

間違いを見つけた場合

エラーを再現できなかった場合

エラーが解決できなかった場合

表現がわかりにくいと感じた場合は

次に記事を見にきた方のためにも、教えて頂けると幸いです。
Azure DevOpsでAzure ADのユーザータイプ情報が反映されるフローと条件

株式会社船井総研デジタルの@fsd-jumeです。
Azure初心者も恐れることなくAzureを触れるようになることを目標に毎回記事を投稿しております。
そのため、内容は各技術の表面的な部分であることが多いので、さらに詳しく知りたい方は他の方も様々な記事を投稿しておりますので、ぜひそちらも含めて知識を深めていただけたらと思います。
私の投稿では、その入り口になれば幸いです。

## 今回のテーマ
最近Azure DevOpsを使っていて、連携するAzure ADのディレクトリを変更しようとしたときに、「ゲストユーザーがいるから変更できないよ」というエラーが出てきました。この問題自体は下記の設定を変更することで事なきを得たのですが、そもそもこの「ゲスト」がどこで定義された情報か分からなかったため調査いたしました。本投稿ではその調査で分かった内容を記載いたします。
**※設定内容(Azure DevOps)**
Organization Settings > Security > Policies > User Policies > External guest access

### 「ゲスト」とは？
Azure DevOpsではユーザーが「ゲスト」かどうか、下記で確認が可能です。
Organization Settings > General > Users > All users > AAD User Type
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/3d2e419d-2253-6070-c52f-1c555e5b8837.png)
つまり、Azure DevOpsではAAD(Azure AD)のユーザータイプ情報を基に、「ゲスト」の判断をしていることが分かります。

### AADユーザータイプとは？
Azure ADでは下記でユーザータイプが確認可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/40e9bd29-2679-7f82-aca7-9094dc734257.png)
なお、外部ADのユーザーを招待した場合のユーザータイプのデフォルトは「ゲスト」です。
※上の画像はデフォルトから変更しています

### Azure AD側での変更とAzure DevOpsへの反映
このユーザータイプをAzure ADで変更した場合、公式のドキュメントでは「数時間～数日」でAzure DevOpsに反映されると記載がありました。

:::note info
公式ドキュメントの記載は2023年4月現在のものとなります
:::

https://learn.microsoft.com/ja-jp/azure/devops/organizations/accounts/faq-azure-access?view=azure-devops#convert-azure-ad-usertype-from-guest-to-member-using-azure-ad-powershell

しかし、実際に試してみたところ、記載通り数時間～数日でAzure DevOpsに反映されたユーザーもいれば、1か月近く反映されなかったユーザーもいました。
そのため、Azure ADにおけるユーザータイプ変更がどのようなフローでAzure DevOpsに反映されるのかを知るために、Microsoftに問い合わせを行いました。

## Microsoftからの回答
### Azure ADの変更がAzure DevOpsに反映される条件
**変更したユーザーが完全な手順でAzure DevOpsにサインインした場合​**
※完全な手順：ユーザー名とパスワードをダイアログ上で入力する形(InPrivateでのサインインが確実)​
⇒反映に最大で24時間かかる​

​**変更したユーザーが不完全な手順でAzure DevOpsにサインインしていた場合​**
※不完全な手順：キャッシュやクッキー等の影響でユーザー名／パスワードを入力しないままアクセス​
⇒反映に数時間から数日かかる場合がある​

### Azure DevOpsへの反映のフロー
(1)Azure ADでユーザーのユーザータイプを変更(開始タイミング)​
(2)該当ユーザーがAzure DevOpsに不完全なアクセスを継続(数時間～数日)​
(3)該当ユーザーがAzure DevOpsに完全なサインイン手順を実施(0～24時間)​
⇒変更の反映に「数時間～数日」＋「0～24時間」の時間がかかる​

**※不完全なアクセスを続けていた場合​**
完全なサインインプロセスが実行されない限りは永久に反映されない

## 結論
Azure ADでユーザータイプを変更した場合は、Azure DevOpsへの反映を確実に行うためにも、Azure DevOpsにInPrivateでサインインしてもらうように該当ユーザーに依頼しましょう。
terraform aws

# software
- aws cli
- Terraform
- tfenv

### terraform
https://releases.hashicorp.com/terraform/1.4.6/terraform_1.4.6_windows_amd64.zip

https://developer.hashicorp.com/terraform/downloads?product_intent=terraform

### aws cli setup
https://awscli.amazonaws.com/AWSCLIV2.msi
```
aws --version
```
```
aws configure --profile [profilename]
```
```
aws configure
AWS Access Key ID [None]: XXXXXXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
Default region name [None]: ap-northeast-1
Default output format [None]: yaml-streaming
```
```
aws ec2 describe-instance --profile [profilename]
```
Gitで誤ったコミットをしないために

# 概要
gitでコミットする際に、デバッグログや不要な情報などが入ってしまうことが多々ある。
プルリクで毎回それを指摘されると申し訳なくなるため、ヒューマンエラーはgitの機能で対処しようと思う。

# pre-commitを使用する
gitには特定タイミングでスクリプトを実行する[フック](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA-Git-%E3%83%95%E3%83%83%E3%82%AF)という機能がある。
今回はこれのpre-commitを使用する。
とりあえず、変更部分に"Debug"の文字列が入っていた場合はコミットさせないようにしてみる。


.git/hooks/pre-commitのファイルを次のように設定する
```sh
# "Debug"の文字列が入ったコミットを禁止
files=`git status|grep -e "modified" -e "new file"|sed "s/new file:\(.*\)/\1/g"|sed "s/modified:\(.*\)/\1/g"|cut -f 2`

for file in $files
do
   result=`git diff --cached -w --ignore-blank-lines --unified=0 $file | grep -e "Debug"`;

   if [ -n "$result" ]; then
       echo -e "${file} にデバッグ文が入っています。 \n $result}";
       exit 1
    fi
done
```

# おまけ
ついでに、誤ってdevelopブランチにコミットしないようにもしてみる。
```sh
# develop branchでのcommitを禁止
BRANCH_NAME=`git symbolic-ref HEAD | sed -e 's:^refs/heads/::'`
if test $BRANCH_NAME = upstream -o $BRANCH_NAME = develop; then
    echo "We cannot commit on ${BRANCH_NAME} branch."
    exit 1
fi
```
[クロスアカウント]S3バケット間でのs3sync(IAMロールによるSTS認証編)

# はじめに
AWSアカウントを跨いで、ファイル連携をしたい場面が多く、
手軽に実装できるS3を介した連携について、まとめてみました。
S3での連携方法はいくつかありますが、
今回はIAMロールによるSTS認証を使用した方法について記載します。

# やりたいこと
アカウントAにあるEC2から、アカウントBが所有するS3バケットにアカウントBのIAMロールを使用してアクセスし、アカウントAが所有するS3バケットにファイル連携がしたいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/f1170eb3-7471-937c-f478-6046e7283b5f.png)


# 作成手順
ポリシーの記載内容が混乱しがちなので、主にポリシーについて記載します。

### アカウントA側
- S3バケット作成
S3バケットポリシーは下記の通りです。
　※アカウントBのIAMロールからのアクセスを許可する必要があります。
　　設定していない場合、ListObjectsV2でAccess Denied (アクセス拒否) エラーとなります。
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "{アカウントBのIAMロールARN}"
            },
            "Action": [
                "s3:ListBucket",
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": [
                "{アカウントAのS3バケットARN}",
                "{アカウントAのS3バケットARN}/*"
            ]
        }
    ]
}
```
- EC2作成
- EC2にアタッチするIAMロール作成
IAMロールのポリシーは下記の通りです。
 　※アカウントBのIAMロールの権限にてs3syncコマンドを実行する為、
　 　アカウントBのIAMロールにスイッチロールする権限のみで問題ありません。
　※SSMでOSにログインする場合は「AmazonSSMManagedInstanceCore」も付与しておきます。
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowAssumeCrossAccountRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "{アカウントBのIAMロールARN}"
        }
    ]
}
```
### アカウントB側
- S3バケット作成
- アカウントAからのスイッチロール先IAMロール作成
IAMロールのポリシーは下記の通りです。
 　※アカウントBのIAMロールの権限にてS3syncコマンドを実行する為、
　 　アカウントBのS3バケットへの操作権限に加え、
　　 アカウントAのS3バケットへの操作権限も必要です。
```json
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": [
            "s3:ListBucket",
            "s3:GetObject",
            "s3:PutObject"
        ],
        "Resource": [
            "{アカウントAのS3バケットARN}",
            "{アカウントAのS3バケットARN}/*",
            "{アカウントBのS3バケットARN}",
            "{アカウントBのS3バケットARN}/*"
        ]
    }
}
```
以上で設定作業は完了です。

# やってみる

### s3sync実行前の状況

- アカウントAのS3バケット
なにも格納されてません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/b33cf3a3-30c5-bfa8-f37d-87bf62101d5f.png)


- アカウントBのS3バケット
tst.txtを格納しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/dddf402a-e5c2-7687-8111-aa9b332affa5.png)

### s3sync実行
アカウントAのEC2にSSMにてログインし、アカウントBのロールの権限を使用してs3syncを実行します。
末尾のprofile指定でアカウントBのIAMロールの権限を使用してコマンドを実行しています。

アカウントBのS3バケットに格納していた、「tst.txt」がアカウントAのS3バケットにコピーされました！
![EC2_S3sync.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/a19caa1a-8e58-74b6-0220-bd5acb0640ac.png)
下記、実行したコマンドのサンプルです。
```
aws s3 sync s3://{アカウントBのS3バケット名} s3://{アカウントAのS3バケット名} --profile {プロファイル名}
```

### s3sync実行後の状況
- アカウントAのS3バケット
コンソール上でも「tst.txt」が存在していることを確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/00a2e808-53e5-d6a4-33a1-0f7bc6387a1f.png)

# さいごに
ポイントとしては、アカウントBのIAMロールに、アカウントAのS3バケットへの操作権限を設定しつつ、
アカウントAのS3バケットポリシーに、アカウントBのIAMロールからの操作権限を設定することです。
感覚的にはどちらか一方で設定していれば問題ない気がしてしまいますが、
双方で設定する必要があり、ハマりポイントになりやすいので、ご注意ください。
アンドリュー・ヤン＋OpenAI: ChatGPTプロンプトエンジニアリング-開発者のための講座（期間限定で無料）の紹介

このコースはAIのマスターのアンドリュー・ヤン氏とChatGPTの作成者であるOpenAIによって提供されています。ビデオとインタラクティブなJupyterノートブックを通じて、ChatGPTアプリケーションを開発するためのベストプラクティスを学ぶことができます。

学習内容：
対象者：初心者から上級者まで
長さ：1時間
講師：Isa Fulford　(OpenAI), Andrew Ng (DeepLearning.AI)
価格：期間限定で無料
言語：英語

コースの内容：
1. はじめに
2. ChatGPTの利用のガイドライン（4つの原則）
3. 反復的なプロンプト開発
4. 文章の要約
5. 情報の抽出（センチメント分析、トピック抽出）
6. テキストの変換 (翻訳、スペルチェック、文法の修正)
7. 拡張 (メールの作成、文章の作成、アイデア出し)
8. カスタムチャットボット
9. まとめ

講座のリング
https://www.deeplearning.ai/short-courses/chatgpt-prompt-engineering-for-developers/

コースの感想：
> 開発者として、新しい技術に追いつくために新しいことを学ぶ必要があります。ChatGPTは、AI革命を起こす可能性のある技術の1つです。最高の講師から学び、1時間程度の時間をかけて学ぶことができます。このコースを受講しない理由はないと思います。
cloud functions for firebaseを使っていて2023/4/20あたりからデプロイでエラーが出るようになった



cloud functions for firebase を使っているのですが
2023/4/20あたりから全くソースコードに修正を加えていないのにも関わらずdeployがエラーを返すようになりました

firebaseではない cloud functions でも同じエラーが出ると思われます

```
$ firebase deploy --only functions
...
色々なログが出る
...
i  functions: cleaning up build files...
Error: There was an error deploying functions:
- Error Failed to update function xxxxxxx in region asia-northeast1...
...
```

# 原因

4/11にfunctionsのサーバー側に変更が入ったようです

https://cloud.google.com/functions/docs/release-notes#April_11_2023

## 要約

- buildスクリプトを書いてるとdeploy時に（おそらくサーバー側で） `npm run build` が実行されるようになった
- 実行してほしくないなら `"gcp-build": ""` を書け

# 対応

今回`npm run build`で `/functions` 外に置いてあるコードを読み込んで行う処理をしていたため、deploy時にサーバー側ではそのファイルが存在しておらず、エラーになっていたようです


ということで`package.json`を以下のように修正したら問題なくdeployされるようになりました


```package.json
{
  "name": "functions",
  "scripts": {
    "lint": "eslint",
    "test": "jest",
    "build": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
    "gcp-build":"", ←追加
```
プリザンターのサーバースクリプトで項目で選択されたユーザーがグループに所属しているかどうか調べる

# はじめに
今回の記事では、ClassRで設定されているユーザーが事前に指定したグループに所属しているかどうかを調べるものになります。今回はユーザーがグループに所属している場合の処理を実装していきます。

# ソースコード
```JavaScript
try {
    // ClassRに入力されているユーザーのユーザーIDを取得
    let classR = model.ClassR;
    // グループIDが「1」のgroupオブジェクトを取得
    let group = groups.Get(1);
    // グループIDが「1」のグループメンバーの情報を取得する
    let menbers = group.GetMembers();
    // グループIDが「1」のグループに所属しているメンバー分処理
    for (let menber of menbers) {
        // ClassRのユーザーがグループIDが「1」のグループに所属していればtrue
        if (classR == menber.UserId) {
            // 所属している場合の処理を記載
            context.Log('グループに所属しています。');
            // 処理を抜ける
            break;
        }
    }
} catch (ex) {
    context.Log(ex.stack);
}
```

# おわりに
最近はサーバスクリプトの実装をするサポートが多い印象です。入社当初に比べたらサポートの回答速度も上がり、スクリプトの実装も少しずつきれいになった来たのかなと思っています。この調子で頑張ります。ユーザー様が私の記事を読んで少しでも実装ができるようになってくれると嬉しいです。自分の書いたコードで動いているシステムなんて素敵ですよね！
プリザンターで読み取り専用項目がブランクだった場合に処理を制御する

# はじめに
プリザンターのプロセス機能では、「読み取り専用と入力検証」のどちらも実現することができません。お客様の使い方によっては、項目にマスタから参照してきた値を自動的に設定している方もいらっしゃいます。その際、任意の値に編集できないようにするためにプロセス機能で読み取り専用を設定することが多いと思われます。しかし、マスタに不整合が発生し値が設定されない場合、そのままワークフローが進行してしまいます。すると、値が設定されていないといけない項目がブランクのままワークフローが進行してしまいます。そして、プロセス機能では読み取り専用を実現しながら、入力検証を実現することができません。そのため、このような事象を防ぐために下記サーバスクリプトで入力検証を実現しています。

# ソースコード
```JavaScript
try {
    // 作成ボタン、もしくはプロセスIDが1のボタンが押された時の処理
    if (context.ControlId === 'CreateCommand' || context.ControlId === 'Process_1') {
        // 分類A項目がブランクの時の処理
        if (model.ClassA == '') {
            // アラート出力
            context.Error ('ClassAがブランクです。')
        }
    }
} catch (ex) {
    context.Log(ex.stack);
}
```
上記のスクリプトでは、デフォルトで設定されている作成ボタン、もしくはプロセス機能で追加したプロセスIDが「1」のボタンが押された際に動作するサーバスクリプトになります。ClassA項目に値が設定されていなければ「ClassAがブランクです。」と画面下部に赤い帯でエラー表示をします。その際、「context.Error」を使うことで後続の処理を実行しません。そのため、本来であればこの処理の後にプロセス機能が動作し、状況が遷移するのですが、「context.Error」が実行されることでプロセス機能が動作することがなく、状況も遷移することがありません。

# さいごに
今回はプロセス機能では実現できない「読み取り専用と入力検証」を実現する方法を記載いたしました。プロセス機能によって読み取り専用を実現し、上記のサーバスクリプトによって入力検証を実現することができました。現在のプリザンター(ver.1.3.37.3)では、プロセス機能で「読み取り専用と入力検証」をどちらも実現することができないため、上記の方法で実現してください。
【備忘録】SAP BTPアプリ開発プロジェクトで、コーディング規約・命名規約の作成したときの資料一覧

# はじめに
SAP社のエンタープライズPaaS製品である、SAP Business Technology Platform（BTP） でアプリケーション開発をしている@fussasyです。アプリケーション開発プロジェクトを経験する中で、コーディング規約や命名規約をイチから作成することがありました。その際の参考資料を簡単に整理しておきます。

# 命名・コーディングガイドライン
### JavaScript（SAPUI5）公式ガイドライン
Development Conventions and Guidelines
https://help.sap.com/saphelp_uiaddon10/helpdata/en/75/3b32617807462d9af483a437874b36/frameset.htm

### Java11（Spring Framework）各社ガイドライン
・フューチャー株式会社（Future Enterprise Coding Standards）
https://future-architect.github.io/coding-standards/
・フューチャー株式会社（Future Enterprise Coding Standards > Javaコーディング規約）
https://future-architect.github.io/coding-standards/documents/forJava/
・Google Style Guides
https://google.github.io/styleguide/
・Google Style Guides（Java）
https://google.github.io/styleguide/javaguide.html

### Springリファレンスドキュメント（SpringBoot）
https://spring.pleiades.io/

### Java非推奨API
・Oracle提供
https://docs.oracle.com/javase/jp/8/docs/api/deprecated-list.html


# セキュリティコーディング
以下、基本的なセキュリティ対策は考慮して実装する旨を記載
実装方法については、検索すると具体的な内容がたくさんヒットしますので割愛します

・SQLインジェクション対策
・OSコマンドインジェクション対策
・ディレクトリ・トラバーサル対策
・セッション管理の不備対策
・クロスサイト・リクエスト・フォージェリ対策
・HTTPヘッダインジェクション対策
・メールの第三者中継対策

# 暗号化
機密性を確保する必要がある情報は、当該情報の保存期間や取得難度に応じて、暗号化の必要性を検討
こちらも、実装方法については、検索すると具体的な内容がたくさんヒットしますので割愛します

・暗号アルゴリズム
・暗号ライブラリ
・暗号鍵
・電子署名

# その他
他、システム構成によっては、OData（CloudSDK）の利用規約やCAP（SAP Cloud Application Programming Model）の規約も、それなりに決めておくと良いと思います。

# おわりに
2次請けだと、コーディング規約や命名規約が発注元（大手システムインテグレーターや、コンサルティングファーム等）から提供されている場合が多いですが、1次請けだとイチから作る必要があり、中には成果物としてお客様から求められることもあります。そういう時は、先述したフューチャー株式会社様が提供しているコーディングガイドラインや、各種フレームワークの公式ガイドライン等を読み込み、引用していくのが早いと思います。また、各種フォーマッターに規約の設定を盛り込んでおけば、レビューの際に細かくコードを見る必要もなくなるので開発効率も上がって良いと思います。

# おまけ
SAP BTPアプリケーション開発プロジェクトを推進する際のために、レビュー用のチェックシートも作成しましあ。併せてご活用ください。

【チェックシート】システム開発において、基本・詳細設計書のレビューでよくある指摘観点をまとめる
https://qiita.com/fusassy/items/109c7e1f1f49573a1310

【チェックシート】システム開発において、Java11・SpringFrameworkで実装した際のコードレビューでよくある指摘観点をまとめる
https://qiita.com/fusassy/items/9c275570b1241ec68e75

【チェックシート】システム開発において、SAPUI5で実装した際のコードレビューでよくある指摘観点をまとめる
https://qiita.com/fusassy/items/80ae30b1863c9834fded

【チェックシート】システム開発において、テスト設計・テストのレビューでよくある指摘観点をまとめる
https://qiita.com/fusassy/items/ad9828e93e17652d6d73
アカウント間で共有したAMIから作成したEC2インスタンスが即「終了済み」となってしまった

# 1.原因
原因は下記記事をご参照ください。
対応方法も記載されていますが私の場合はうまく実行できませんでした。

https://techblog.nhn-techorus.com/archives/22967

# 2.対応方法
私の場合は下記手順で成功いたしました。

1.KMS > カスタマー管理型のキー > 作成したキーを選択します。
2.キーポリシー > 別の AWS アカウントを追加で共有先のAWSアカウントIDを記載するだけです。



# 3.アカウント間のAMI共有で参考にした記事

アカウント間のAMI共有方法

https://oji-cloud.net/2019/11/08/post-3509/

「Snapshots encrypted with the AWS Managed CMK can’t be shared. Specify another snapshot.」エラーの対応方法

https://dev.classmethod.jp/articles/tsnote-aws-managed-cmk-cannot-be-shared/
Googleカレンダーの予定(終日)をスプレッドシートから一気に登録するGAS（コピペでOK）

# スプレッドシートの準備
A列に日付、B列に予定を書いたスプレッドシートを用意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/d1aae3a2-e47c-73f9-a9df-bdabaed8ffcc.png)

# スクリプトを用意
拡張機能＞Apps scriptを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/98cc3f7f-81bd-3c95-5fe6-82d7404c2839.png)

## デフォルトのカレンダーに登録する場合
以下のコードをコピペ
```
// デフォルトのカレンダーに登録する場合
function myFunction_1() {
  const calender = CalendarApp.getDefaultCalendar();

  // スプレッドのシート名を指定する
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');
  var vals = sheet.getRange('A:B').getValues();
  // スプレッドシートの値を順番に見ていく
  for(var row_val in vals){
    var day = vals[row_val][0];
    var eventname = vals[row_val][1];
    // B列が空じゃなかった場合に該当の日付に登録する
    if(eventname!=""){
      calender.createAllDayEvent(eventname, day);
    }
  }
}
```

実行する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/62b1ef13-2a4b-ebc6-d544-3926cbf40235.png)

※初回は実行していいか聞かれるので許可する

## カレンダーを作成してから登録する場合
Googleカレンダーのページから使うカレンダーを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/290bde51-5e30-dc55-9215-ff2632da5651.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/b863ac70-1674-716f-e6fc-3d25bbf1f427.png)

以下のコードをコピーしカレンダーの名前「てすとよう」の記載を変更する
```
// カレンダー名を指定して登録する場合
function myFunction_2() {
  // カレンダーの名前を指定する
  var calendars = CalendarApp.getCalendarsByName('てすとよう');
  const calender = calendars[0];

  // スプレッドのシート名を指定する
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');
  var vals = sheet.getRange('A:B').getValues();
  // スプレッドシートの値を順番に見ていく
  for(var row_val in vals){
    var day = vals[row_val][0];
    var eventname = vals[row_val][1];
    // B列が空じゃなかった場合に該当の日付に登録する
    if(eventname!=""){
      calender.createAllDayEvent(eventname, day);
    }
  }
}
```

実行する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/faec28bd-f2c6-7f9f-58af-258ded43c902.png)


# 結果
登録できました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/52d55f4f-9cc5-97ad-5f0f-b32128ac39a3.png)
週一でPython勉強会やってみる④

前回の続き

https://qiita.com/Waddy675/items/f6b31f1ce5362758bd4f

今回は生徒が私ともう一人だけでした。まぁ自分のための勉強会でもあるので気ままにやっていきます。
コメントやいいねが付いてテンション上がってます。

## for文
繰り返し処理のため詳細は割愛。if文と同様に「：」を忘れないようにしたい。
```py
array = [0, 1, 2, 3]
for num in array:
    print(num)
# 表示→0 1 2 3
```
特に問題なし！ちなみにJSであったfor~ofはないようだ。
range関数でfor~of的なことはできそう。
```py
for index in range(3):
    print(index)
# 表示→0 1 2
```

## リスト型
いわゆる配列。２次元にすることも可能。
appendやpopでリストの項目の追加や削除が可能。
削除に関しては「del」を使って項目の削除ができる点が変わっている点かと・・・
```py
array = [0, 1, 2, 3]
print(array)
# 表示→[0, 1, 2, 3]
del array[1] #arrayは[0, 2. 3]となる
```

## タプル型
リストと同様に扱えるが、中身の変更が不可となっている。変更しようとするとエラーになる。
```py
tuple = (0, 1, 2)
tuple[0] = 1 #これはエラーになる
```

## 辞書型
辞書型はKey（文字列）/Valueでデータを格納する。個人的にはディクショナリーと呼んでる。
JSONと見た目は同じだが、JSONはフォーマット扱いなのでそのまま使うことはできず、ディクショナリーとして扱う場合には変換が必要。
```py
dic = {"apple": 5, "banana": 10, "grape": 20}
print(dic["apple"]) #apple
```
「in」を使うことで、Keyが存在しているかを確認できる。
keys()でKey一覧を取得したり、updateやpopなどへ内容の変更が可能。
リストと同様にdelで削除も可能。
```py
dic = {"apple": 5, "banana": 10, "grape": 20}
dic.update({"tomato":1, "onion":2})
print(dic)
# {"apple": 5, "banana": 10, "grape": 20, "tomato":1, "onion":2}
dic.pop("grape")
print(dic)
# {"apple": 5, "banana": 10, "tomato":1, "onion":2}
```

## まとめ
if文とfor文が書ければ基本的な部分は何でも書けるのでひと段落。
リストとディクショナリーはよく見てきたけど、タプルはどう使えばいいのかなと。
イミュータブルの配列として処理が速くなるとかあるけど、そこまで気にするレベルのものを作らないので一旦保留。
[Git] 動作を試す 実行例4：addとcommitでコミットする

Gitの動作を理解するために、Gitのコマンドを実際に試して、結果を見てみました。

1つの記事内で一連のGitコマンドが完結しているので、これら一連のコマンドを順に実行させて結果を見ることで、一連のGitの動作を実際に体感でき、一通り独習することが可能です。

※前回記事のリポジトリ状態からの続きになっています。
| [前回記事へ](https://qiita.com/dl_from_scratch/items/14d1308c6d9d4c8aa4ac) | [目次へ：Git関連記事のまとめページ](https://qiita.com/dl_from_scratch/items/597bc28a4787a7901d21) | [次回記事へ](https://qiita.com/dl_from_scratch/items/a4db247acdfd3c7381ba) |
|:-:|:-:|:-:|

# 実行例

```
echo Sample-Added-11 > test1.txt
git add test1.txt
git commit -m "message1"
↓
結果: 
[master (root-commit) 4ace194] message1
 1 file changed, 1 insertion(+)
 create mode 100644 test1.txt

-----

echo Sample-Added-12 >> test1.txt
echo Sample-Added-21 > test2.txt
git add .
git commit -m "message2"
↓
結果: 
[master 00cad71] message2
 2 files changed, 2 insertions(+)
 create mode 100644 test2.txt

-----

echo Sample-Added-13 >> test1.txt
echo Sample-Added-**21 > test2.txt
git commit -m "message3"
↓
結果: 
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   test1.txt
        modified:   test2.txt

no changes added to commit (use "git add" and/or "git commit -a")

git commit -a -m "message3"
↓
結果: 
[master 20bbab7] message3
 2 files changed, 2 insertions(+), 1 deletion(-)
```

# 環境

Windows 10、PortableGit-2.40.0-64-bitを使用、全てローカルPC上で実施、GitHub等は不使用。
GitHubリポジトリをソースツリーにクローンする方法

## とても参考になった記事
この記事の通りに手順をすすめたら、できました。
https://qiita.com/kunosu/items/9ccafcb3991a1db72d99

上記の記事で十分わかりやすかったのですが、
所々つまったところがあったので補足しておきます。

## 補足①　公開鍵の種類について

記事の通りに作成すると、クローンしたときに

 > ERROR: You're using an RSA key with SHA-1, which is no longer allowed.

というエラーが出るので、公開鍵を作成するときは、
鍵のタイプを、「SSH-2 ECDSA key」にすると良い。

## 補足②　New SSH Keyについて

GitHubにSSHキーを追加するときの
Key typeの選択肢は「Authentication Key」でよい。

## 補足③　Gitレポジトリとして認識されない
> The server's host key is not cached. You have no guarantee
that the server is the computer you think it is.

のエラーが出たときは、
コマンドプロンプトで
```
C:\Users\[ユーザー名]\AppData\Local\SourceTree\app-3.4.8\tools\putty\plink.exe git@github.com
```
を実行し、
Store key in cache? (実行中にでてくる質問)にたいして「y」を答えればOK

### 環境
・Windows10
・ソースツリー 3.4.8
Google Cloud 初学者がいきなり予算10,000%の請求アラートを受け取った話

# 経緯
firebaseを利用して開発中、Google Cloud 請求アラートが届き、いきなり「予算の10,000%に達しました」とのこと。
予算額を￥1にしていたので実際の請求額は￥158だったのだが、おかしいと思い調査してみた。

# 結論(多分)
どうやらCloud Functionsのデプロイ方法に問題があったらしい。
「###.artifacts.###」というバケットが生成されたりなんやらでCloud Storageを大量使用したことになっているようだ。

↓↓↓非常に参考になった記事↓↓↓

https://halzoblog.com/gcp-cost/

# 私がやったこと
CLIでの操作に苦手意識があったので最初はコンソールから関数を作成し、コードを直書きしてデプロイしていた。25回程度は繰り返しデプロイしてしまっていた。
これだと「###.artifacts.###」バケットが生成されてしまう。
また、Google Cloud CLIでのデプロイでも同様のことが起きる。

改善策としてFirebase CLIを使用してFunctionsをデプロイする。
すると「###.artifacts.###」バケットは生成されなくなった。

## Firebase CLIでのFuncitonsのデプロイ方法
https://firebase.google.com/docs/functions?hl=ja

https://firebase.google.com/docs/functions/manage-functions?hl=ja
[Git] 動作を試す 実行例3：initでリポジトリ作成

Gitの動作を理解するために、Gitのコマンドを実際に試して、結果を見てみました。

1つの記事内で一連のGitコマンドが完結しているので、これら一連のコマンドを順に実行させて結果を見ることで、一連のGitの動作を実際に体感でき、一通り独習することが可能です。

※前回記事のリポジトリ状態からの続きになっています。
| [前回記事へ](https://qiita.com/dl_from_scratch/items/7cd7ac09f4f4089588ad) | [目次へ：Git関連記事のまとめページ](https://qiita.com/dl_from_scratch/items/597bc28a4787a7901d21) | [次回記事へ](https://qiita.com/dl_from_scratch/items/c214c521180ea0f68a1e) |
|:-:|:-:|:-:|

# 実行例

```
cd /
mkdir test-space
cd /test-space
mkdir local-repo1
cd /test-space/local-repo1

git init
↓
結果: 
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint:   git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint:   git branch -m <name>
Initialized empty Git repository in D:/test-space/local-repo1/.git/
```

# 環境

Windows 10、PortableGit-2.40.0-64-bitを使用、全てローカルPC上で実施、GitHub等は不使用。
Databricksマーケットプレイスを試してみる

こちらにあるように、Databricksマーケットプレイスがパブリックプレビューとなりましたので、早速試してみます。

https://qiita.com/taka_yayoi/items/ced86daa2606232c308a

サイドメニューの左下に**Marketplace**が表示されています。
![Screenshot 2023-04-28 at 13.22.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/646916d1-7ff5-9d0e-891a-c49cc048bd78.png)

このようにマーケットプレイスが表示されます。
![Screenshot 2023-04-28 at 13.22.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/9f78dddc-12b8-72a5-50fb-3fbf2a7745e9.png)

カテゴリ、プロバイダー、無料枠、キーワードなどで検索できます。ここでは、`covid`で検索してみます。
![Screenshot 2023-04-28 at 13.25.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/e951fd7c-69fb-285b-5e60-1ddfdd8630d3.png)

`COVIDcast (COVID-19) Epidemiological Data | CMU`を選択します。価格プランが**Instantly available**なのですぐに利用できます。
![Screenshot 2023-04-28 at 13.26.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/698b97a6-c69b-f00a-c5e9-94e14ac84845.png)

右上の**Get instant access**をクリックします。データを参照するカタログを指定します。以下の例ではすでにカタログが作成されているので、既存のものを使用するか別の名前を指定します。ここでは別の名前を指定します。
![Screenshot 2023-04-28 at 13.27.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/c735df75-a1fb-58d8-cf7a-ef3716018ef0.png)

**Get instant access**をクリックします。
![Screenshot 2023-04-28 at 13.28.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/f04699d8-4438-8303-fbf4-6350ffa0ef94.png)

データエクスプローラで指定したカタログを選択するとデータにアクセスできます。なんだこれ、便利だ。
![Screenshot 2023-04-28 at 13.29.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/d9f1f4ab-85d3-938c-c2bd-d099597cf0b9.png)
![Screenshot 2023-04-28 at 13.29.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/49452b24-4258-72af-1db6-67f2618a74b9.png)

なお、今回選択したデータの**Update frequency**はdailyなので、日次でデータが更新されます。Delta Sharingはデータをコピーするのではなく、ライブのデータにアクセスするので常に最新のデータにアクセスできます。
![Screenshot 2023-04-28 at 13.31.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/1567fd32-7d92-6ce0-6b93-1041f4589ab5.png)

また、サンプルノートブックも添付されているのでこれを活用することができます。
![Screenshot 2023-04-28 at 13.31.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/cb13b553-fb3d-0830-9c27-d43bff97a562.png)

### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
「クソコード」と言いたくなったら

# はじめに
業務後も自己学習したり、難しめのタスクを積極的にチャレンジしてくれる頼もしい新人がいました。しかも、コミュニケーションも積極的なメンバーでいてくれてありがたい存在でした。しかし、口癖で「**クソコード**」というワードを言いがちで（95%くらいは軽口）、業務上では直接の関わりがあまりない直属の上司から評価が良くありませんでした。おそらく、「クソコード」と言う言葉が遠巻きによく耳に入り、チームの士気を下げているのだと思われたのだと思います[^1]。

現場の評価と上司の評価が一致していなくてもったいないなと思ったのと、当時は有用なアドバイスができず、ここ数年で言語化できつつあるので、お焚き上げも込めて「クソコード」を言いたくなった時の向き合い方のポエムを投稿します。

# クソコードと言いすぎることのデメリット
上長の評価が悪くなること以外に、以下のようなデメリットもあると思います。

- 自分以外のメンバーにとってクソコードではなかった時に、自分の印象が悪くなる
- クソコードだと思っているコードを書いた人が同じチームにいた場合に、クソコードと言われた人が傷付くかもしれない
- 本当にクソコードだった時に、クソコードと言っても信じてもらえなくなる
- 意図せず自分がクソコードを書いてしまった時に、ブーメランが返ってくる可能性がある

# クソコードと言いたくなったら、言う前に考えるべきこと
対象のコードを「クソコード」と評価する前に、以下の4つの点を考慮してみると良いのかなと考えています。

1. **ドメイン知識の理解**
    - 現場に入りたての場合、ドメインの専門用語や業務ロジックが理解できていないと、コードが意味不明に感じられるかもしれません。そのため、まずはドキュメントを読んでみたり、チームの先輩に質問するなどして、ドメイン知識を補完することをお勧めします。
1. **ユーザに価値を提供しているかどうか**
    - 対象のコードがユーザに価値を提供している場合は、小さな積み重ねでそうなってしまった可能性があります。また、改修したいと思っているが、リソースの制限があり対応できていない場合もあります。その場合、「クソコード」と評価する前に、チームの先輩に歴史的な背景を聞いてみるのもありでしょう。
    - 対象のコードがユーザに価値を提供できていない場合は、そのコードを直したとしてもあまりインパクトがないかもしれません。他に優先度の高いタスクがあって修正できなかった場合は、「クソコード」と言った事実だけが残ります。期待した通りに動いているのであれば、一旦は心に留めておくのもありだと思います。
1. **公式ドキュメントで推奨されていない書き方かどうか**
    - 公式ドキュメントで推奨されていない書き方であり、重大な障害を引き起こす可能性のある場合は、チームのリーダーや上長に報告して、判断を仰ぐのが良いでしょう。
1. **言い換えができるかどうか**
    - 「クソコード」という表現は感情的で、他者に傷つける可能性があります。代わりに、公式ドキュメントで推奨されていないコードは「非推奨のコード」と表現したり、複雑なコードは「保守や機能拡張が難しそうなコード」と表現したりすることができます。コードメトリクスと併せて言い換えることで、より客観的な表現にすることができます。
    - 「クソコード」というとメンバーは攻撃されたと感じてしまい、反発してしまうかもしれません。適切な言い方や客観的な事実を添えることで、メンバーも協力的になり自分が考えていたより良い改善策が出るかもしれません。

# まとめ
クソコードを書いてやろうと思って書いている人はいないと私は信じています。ただ、「クソ」という言葉は、自分が思っている以上にネガティブに強い言葉なので、使うときは考えてから使おうという話でした。強いエンジニアだけでチームが構成されていれば、いわゆるクソコードが産まれない可能性があるかもしれません。しかしながら、現実としては強いエンジニアだけでチームが構成されている方が珍しいと思います。

普段はコードメトリクスが悪くならないようにチームで動いたとしても、急を要する対応で影響範囲を抑えるために仕方なくそうしたままになっていることもあるでしょう。ですが、歴史的な背景を知った上で、本当にクソコードと言うのかどうか、考える必要があります。コードには、当時の状況が反映されていることもあり、単にクソコードと片付けることはできないと思っています。

## 余談（この記事を書くきっけ）
半藤一利さんの[「幕末史」](https://www.shinchosha.co.jp/book/127181/)を読んだことです。本を読むと、幕末史で名を残した人は当時の文脈で優秀であることは間違いないと思います。しかし、勢いのある人に目をつけてもらい何かを任せてもらった結果、歴史に名を残したように見えました。環境はある程度自分自身で選べると思いますが、勢いのある人に目をつけてもらうということは運の要素の方が強いように感じました。運を自分でコントロールすることは難しいですが、悪目立ちをして目をつけてもらうチャンスを失わないことなら自分でコントロールできるのかなと思いました。気軽に「クソコード」と言ってしまうことは、悪目立ちだけしてしまうことにつながると思い、この記事を書くきっかけになりました。

[^1]: 自分も含めたいろんな話を混ぜて抽象化しています。
ログイン時にボーナスポイントを付与するシステム

先日、ユーザーのログイン頻度を増やすための機能を追加するためポイントシステムを導入しました。
具体的には、ログイン時にポイントを付与し、さらにユーザー間でポイントのやり取りが可能な仕組みです。

以下はその手順です。

## 目次
1. [ポイントを管理するカラムの追加](#ポイントを管理するカラムの追加)
2. [ログインボーナス機能の追加](#ログインボーナス機能の追加)
3. [ポイントのやり取り機能の追加](#ポイントのやり取り機能の追加)
4. [最後に](#最後に)

## <span id="ポイントを管理するカラムの追加">ポイントを管理するカラムの追加</span>
まずは、usersテーブル（各アプリによってテーブル名は任意です）にポイントを管理するためのカラムを追加します。

```:ターミナル
rails generate migration AddPointsToUsers points:integer
```
作成されたマイグレーションファイルに以下の内容を記載します。
```Ruby:Ruby
class AddPointsToUsers < ActiveRecord::Migration[6.1]
  def change
    add_column :users, :points, :integer, default: 0
  end
end
```
マイグレーションを実行します。
```:ターミナル
rails db:migrate
```

これで、ポイントを管理するためのカラムが作成されました。

## <span id="ログインボーナス機能の追加">ログインボーナス機能の追加</span>
※今回の実装ではログイン認証にDeviseを使用しています。Deviseを使用せずに実装をされている場合は、適宜コントローラ名、引数名等を読み替えて実装を進めてください。

<div style="border-bottom: 1px solid #e1e4e8; padding-bottom: 4px; font-weight: bold;">ファイル名: application_controller.rb</div>

```Ruby:Ruby
def after_sign_in_path_for(resource)
  # ↓のコードを有効にすると、ログインボーナスは一日一回という条件が付けられる
  if resource.last_login_bonus_date.nil? || resource.last_login_bonus_date < Date.today
    # ランダムなログインボーナスを生成
    login_bonus = generate_login_bonus
    # ユーザーのポイントにログインボーナスを追加
    resource.update(points: resource.points + login_bonus, last_login_bonus_date: Date.today)
    # ログインボーナスを通知
    flash[:success] = "ログインボーナス#{login_bonus} ポイント獲得！"
  end
  user_path(current_user) 
end

def generate_login_bonus
  # ランダムなログインボーナスを 1 から 5 の範囲で生成  
  rand(1..5)
end
```

## <span id="ポイントのやり取り機能の追加">ポイントのやり取り機能の追加</span>
以下は、ユーザ間でポイントをやり取りする機能を追加するためのcontrollerの記述です。
※params[:receiver_id]はポイントを送る相手のIDです。
※おまけ機能として、ポイントを送った際相手に自動でメッセージが届く設定にしています。
```Ruby:Ruby
# ... 省略 ...
  def new
    if params[:receiver_id]
      @user = User.find(params[:receiver_id])
    else
      @users = User.where.not(id: current_user.id)
    end
  end

  def create
    receiver = User.find(params[:receiver_id])
    amount = params[:amount].to_i
    if current_user.send_points(receiver, amount)
      # チャットルーム情報の取得・チャットルーム呼び出しまたは作成
      conversation = Conversation.between(current_user.id, receiver.id).first
      if conversation.nil?
        conversation = Conversation.create(sender_id: current_user.id, recipient_id: receiver.id)
      end
      # 送り先ユーザへのメッセージの作成
      message = Message.new(
        conversation_id: conversation.id,
        user_id: current_user.id,
        content: "#{current_user.name}があなたに#{amount}ポイントプレゼントしました。"
      )
      # 通知
      if message.save
        flash[:success] = "#{amount}ポイントを#{receiver.name}に送信しました。"
        redirect_to user_path(current_user)
      else
        flash[:alert] = "ポイントの送信に失敗しました。"
        redirect_to new_point_path
      end
    else
      flash[:alert] = "ポイントの送信に失敗しました。"
      redirect_to new_point_path
    end
  end
end
```

## <span id="最後に">最後に</span>
ログインボーナス機能を追加しようと思ったとき、結構ややこしいのではないかと思っていたのですが、案外簡単に実装できました。ポイント機能を実装したいと思っている方はぜひ参考にしてください。
aptとapt-getがわからない

# はじめに
先日Debian系のLinuxをUTMで動かす機会がありました。その際に、
apt???
apt-get???
何が違うの？
パッケージって何ｗ
etc...


一度に押し寄せてくる情報量に圧倒されてしまいました。それでも、１つずつ攻略しないと先へは進めません。
そこで今回は**apt**と**apt-get**をどう使えば良いのかについて記事を書いてみます。
# 対象とする読者
- Linux初心者
- エンジニア初心者
- aptがわからない人
# まずは調べてみる
### aptはこう書いてある
以下、ウィキペディア日本語版(2023年4月28日10:00時点での最新を取得)の[APT](https://ja.wikipedia.org/wiki/APT)を引用。
>APT（Advanced Packaging Tool、あるいは Advanced Package Tool）とは、ソフトウェアのインストールとアンインストール（削除）を自動的に行い、ソフトウェアの管理を簡単に行えるようにするための仕組みの1つ。
>もともと Debian用に開発されたコマンドラインベースのパッケージ管理システムである。現在では多数の Debian系の Linuxディストリビューションで採用されている。
::: note
ちなみに、apt-getはaptのページへ転送されました。
:::
ここで3つの疑問が、、、
- パッケージとは？
- パッケージ管理システムとは？
- aptとapt-getの違いは？

もう少し調べてみる必要がありそうですねー。
### パッケージって何？
段ボールのことも***a package***と言いますが、包装・梱包されていたりといったものを連想すると思います。その箱の中には複数の商品を入れられると思います。同じように、ソフトウェアをインストールするときに関連した(依存関係にある)ファイルがひとまとめになったものをパッケージといいます。
### パッケージ管理システムとは？
パッケージを一元管理して、インストール、アップグレード、削除をするツールのことを言います。さらに、依存関係の解決、バージョン管理、更新を自動化することができます。ここでの依存関係とは、パッケージ内の依存関係ではなく、パッケージ外との「すべての」ファイルの依存関係を解決することを指しています。つまり、パッケージ同士の依存関係まで解決してくれます。なんとすばらしい！！！
ただ、依存関係が複雑な場合は「手動」で解決する場合もあるようです。。。
### aptとapt-getの違いは？
[Debian管理者ハンドブック(2023年4月28日10:00時点)](https://debian-handbook.info/)のapt-getコマンドの節には、aptはAPTが提供する2番目のコマンドラインベースのフロントエンドで、**apt-getの設計上の間違いを克服している**とあります。また、**aptは最も推奨されるインターフェイス**とも書いてあります。ただし、**パッケージのインストール要求をスクリプト化する必要がある場合にはapt-getを使用**することになるとも書いてあります。
つまり、普段使いには**apt**コマンドを使い、シェルスクリプト化するときや、自動化する処理が必要な場合は**apt-get**を使用するのが良さそうです。
# apt-getが出てきたらどうすれば良いの？
何かをインストールしたいとき、アップデートしたいとき、削除したいとき、まずはネットで調べてみるはずです。そして、古い記事に行き着くとapt-getコマンドを使用されている例があるかもしれません。この場合はもう、その都度**apt**で読み替えられないか調べてみましょう。出来る限り、一次情報、複数人で書かれた記事から読むことをお勧めします。
# あとがき
わからないことを調べてみると、その説明にわからないことまた出てきて、さらにまた調べて...と続けていると、「当初の目的からズレてきている」ことに気付かされることがあります。ただ、「わからない」を「わかる」にかえたとき自身の成長を実感できるので、趣味の時間にこういうことをするのは良いかもしれないですね。
さて今回は、その「脱線」したときに見つけた「隠しコマンド」をご紹介して終わろうと思います。もちろん、apt-getをaptに読み替えましたｗ
他にもたくさんあるので調べてみてね！！！
```
$ apt moo
                 (__) 
                 (oo) 
           /------\/ 
          / |    ||   
         *  /\---/\ 
            ~~   ~~   
..."Have you mooed today?"...

$ apt install cowsay
$ cowsay モウモウ
 __________
< モウモウ >
 ----------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
```
[Git] 動作を試す 実行例1：始めの設定

Gitの動作を理解するために、Gitのコマンドを実際に試して、結果を見てみました。

1つの記事内で一連のGitコマンドが完結しているので、これら一連のコマンドを順に実行させて結果を見ることで、一連のGitの動作を実際に体感でき、一通り独習することが可能です。

※前回記事のリポジトリ状態からの続きになっています。
| 前回記事なし | [目次へ：Git関連記事のまとめページ](https://qiita.com/dl_from_scratch/items/597bc28a4787a7901d21) | [次回記事へ](https://qiita.com/dl_from_scratch/items/7cd7ac09f4f4089588ad) |
|:-:|:-:|:-:|

# 実行例

```
※始めに名前の設定が必要。
git config --global user.name "person1"
git config --global user.email person1@abc.def

※全ての設定を一覧表示 (--globalのもの)
git config --list --global
↓
結果: 
user.name=person1
user.email=person1@abc.def
color.ui=true
credential.helperselector.selected=<no helper>

-----

※全ての設定の一覧
git config --list
↓
結果: 
core.symlinks=false
core.autocrlf=true
core.fscache=true
color.interactive=true
color.ui=auto
help.format=html
diff.astextplain.textconv=astextplain
rebase.autosquash=true
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
credential.helper=helper-selector
user.name=person1
user.email=person1@abc.def
gui.recentrepo=D:/test-space/repo1
core.quotepath=false
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
```

# 環境

Windows 10、PortableGit-2.40.0-64-bitを使用、全てローカルPC上で実施、GitHub等は不使用。
.gitignoreを書き換えたのに内容が反映されない

.gitignoreを更新したのに適用されない・・・なんで・・・と困った時に
殴り書きしていたメモを発掘したのでまとめます。

### 原因
gitは一度ファイルをアップするとキャッシュを持つから

### 対策
gitのキャッシュクリアをする

### 手順
1. `.gitignore`を書き換える
2. gitのキャッシュを削除
3. `.gitignore`が更新されたか確認


## gitのキャッシュクリアコマンド

```
$ git rm --cached <ファイル名>
```

全体のキャッシュをクリアしても問題ないようですが、私は怖いので使ってません。

```
$ git rm -r --cached .
```

## ちゃんとignoreされたか確認するコマンド
```
$ git status --ignored
```
[API仕様書]yamlから静的html生成

swaggerなどを使用してAPI仕様書を作成した場合、yamlから静的htmlを生成したい場合がある。
その場合は以下で生成可能。
※npmをインストールするのが面倒な場合はAWS CloudShellを使えばすでにnpmが入っている。
```sh
sudo npm install -g redoc-cli
redoc-cli build yamlファイル名 -o 出力ファイル名
```
ただ以下の方が推奨っぽい
結果は同じ
```sh
sudo npm install -g @redocly/cli
redocly build-docs yamlファイル名 -o 出力ファイル名
```