OmniAICreator/Qiita-1.07M huggingface dataset:
rails マイグレーションファイル増えまくってない？30秒で既存テーブルに新規カラム追加・修正する方法

# 1.はじめに

この記事では既存のテーブルに新たにカラム追加する際に、永遠とマイグレーションファイルが増えてしまう人に向けて、マイグレーションファイルを最小限化方法を解説します。

「いやいや当たり前でしょ。」と思うかもしれませんが、僕も過去にrailsを学び始めて一番最初にぶち当たった壁なので初心者向けに書いています！


# 2.マイグレーションファイルとは？
マイグレーションファイルは、データベースを生成する際の設計図になるものです。
また、マイグレーションファイルを実行することで、記述した内容に基づいたテーブルが生成されます。


# 3.ロールバックのやり方

まずはロールバックをする方法をおさらいしましょう。
```shell-session:ターミナル (一つ前まで戻す)
$ rails db:rollback
```

複数のファイルをロールバックしたい時は以下のように記述しましょう。
```shell-session:ターミナル (任意のファイルまで戻す)
$ rails db:rollback STEP=○
```
すなわち5つのマイグレーションファイルとrollbackしたいときはSTEP=5となるわけです。


ここまでがロールバックのおさらいです。


# 4.既存テーブルにカラムの追加方法


tweetsテーブルにtitleというカラムをstring型追加する時、
```shell-session:ターミナル
$ rails g migration AddTitleToTweets title:string
```
のよう形で書いていませんか？

厳密には正しいですが、このままだとカラムを追加する際にマイグレーションファイルが永遠と増殖してしまいます。

今回の方法は、直接マイグレーションファイルを編集するという方法です。


1.ターミナルでマイグレーションファイルのrollbackを行う。
(※この際、必ずstatusがdownになっていることを確認しましょう！🚨)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873347/766032c2-89fb-b42e-cd74-337037cdd32a.png)

2.編集したいマイグレーションファイルを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873347/565a0164-fac7-20a7-096c-30ebfbf2c57a.png)

今回だと、以下のように追加してください

```ruby:マイグレーションファイル
class CreateTweets < ActiveRecord::Migration[6.1]
  def change
    create_table :tweets do |t|
      t.text :body
      t.text :name
      t.string :image
      t.string :title   #追加する行

      t.timestamps
    end
  end
end
```
その後、ターミナルで以下を打ち込みましょう。
```shell-session:ターミナル
$ rails db:migrate
```


schema.rbを見てみましょう
![スクリーンショット 2023-12-11 10.59.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873347/59b5f02d-d978-50c5-05a0-6ab71d246630.png)

titleというカラムがstring型で追加されました。

(🚨注意点🚨)
・必ずstatusはオフにしましょう
・マイグレーションファイルを直接書き換えるので、間違いがないか必ず確認しましょう
・rails db:migrateした際にschema.rbをみて更新されているか確認しましょう

# まとめ
今回はマイグレーションファイルをスッキリし、簡単にカラムを追加する方法を紹介しました。

追加をメインで行いましたが修正したい場合も同様で
status down → ファイルの修正 → マイグレーション
の流れで一発です！

これでrails 初学者でも気軽に、好きなように開発ができますね🌟

それでは楽しいrails開発の旅を〜！
リクエストに値があったら検索条件に含める　をワンライナーで書こう！！

## 概要
実装されている検索機能で、このような処理を見かけます

```php
$query = User::query;
if(!is_null($request->input('name') && $request->input('name') !== ""){
  $query->where('name',$request->input('name'));
}
$users = $query->get();
```

リクエストオブジェクトの`whenHas`メソッドを使えばごちゃごちゃしてる所をワンライナーで書けるぜ！！！！


```php
$query = User::query;
$request->whenFilled('name', fn (string $input) => $query->where('name',$name));
$users = $query->get();
```

Cooooooool


## 参考

https://readouble.com/laravel/10.x/ja/requests#determining-if-input-is-present
【非エンジニア】自分に適切な『タスク管理方法』で円滑なプロジェクトの進行を

## はじめに
この記事は、ミロゴス Advent Calendar 2023 6日目の記事です。

この記事を読んでくださっている読者の皆様はじめまして！
自分は社会人2年目（もうすぐ3年目）になる非エンジニアのUEと申します。

入社して最初の半年間は営業として活動していましたが、昨年の秋から現在に至るまでプロジェクトの進行・管理を担当しています。

ありがたいことに大なり小なり様々な案件・施策等の進行を任せていただいており、日々ゴールに向かって邁進しております。

さて、そんな私からは実体験を元に『タスク管理方法』についての記事を紹介したいと思います。

## そもそもタスク管理とは？
そもそもタスク管理とは何なのでしょうか。そして何のために必要なのでしょうか。
ChatGPT先生に聞いてみました。

:::note info
タスク管理は、個人または組織が仕事やプロジェクトを効果的かつ効率的に遂行するために行うプロセスです。このプロセスでは、仕事を計画し、組織し、追跡し、優先順位をつけ、完了させるための方法やツールを用いています。タスク管理の目的は、目標の達成やプロジェクトの成功に向けて、作業を効果的に組織し、時間やリソースを最適に利用することです。

タスク管理は個人だけでなく、企業やチームにおいても重要なスキルであり、効果的なタスク管理は生産性向上や目標達成に寄与します。さまざまなタスク管理ツールや手法が存在し、個人や組織の好みやニーズに応じて選択されます。
:::

ChatGPT先生が解説してくれましたが、私もタスク管理をする上でのポイントとして以下があると思います。
>効果的なタスク管理は生産性向上や目標達成に寄与します。さまざまなタスク管理ツールや手法が存在し、個人や組織の好みやニーズに応じて選択されます。

第一に、自身がプロジェクト内において「何をすべきなのか」「何が必要になるのか」というTODO的なものを洗い出す上でタスク管理は効果的です。
言わずもがなその後のプロジェクトを円滑に進行していく上での重要な道標となるからです。
また、最初に適切なタスク管理を実施することで無駄な作業を発生させることなく、効率的にいくつものプロジェクトを同時進行することすらも可能にします。

そう、つまりはタスク管理がいかに重要であるかということを私は伝えたいのです。
では、そんな私のタスク管理方法を勝手ながらご紹介させていただきます。

## 私の『タスク管理方法』
- **メイン：Googleカレンダー**
- **サブ：Notion**

上記2つのツールですべてのタスクを管理しています。

使い方も以下のように至ってシンプルです。

1. 必要になるタスクを大中小（※内容によって粒度は変動）に分解しNotion上に箇条書き、もしくはチェックボックスなどの形式で書き込む
2. そのタスクをGoogleカレンダー上に反映させる
3. カレンダーを確認する
4. 当日、Googleカレンダーの通知が飛ぶ
5. 以上

1点ポイントとしては、「**3. カレンダーを確認する**」というところでしょうか。

こと就業中は必要に応じてカレンダーを確認するぐらいなものですが、プライベートな時間ではGoogleカレンダーが擦り潰れるんじゃないかというレベルで見ています。
ふとした瞬間にカレンダーに目を通す、お風呂に入るタイミングで目を通す、寝る前に目を通すなど。
※これはプライベートのタスクもきっちりと管理しているからではあるのですが、、

なので、基本的には明日はどういうタスクが発生し、完了させないといけないかを時間帯とセットで把握していたりします。

このように結構原始的だったりします。
「効率的に〜」とか言うもんだからもっとすごい管理の仕方をしているのではないかと思わせてしまったかもしれません。

でもそんなことはないのです。
この『タスク管理方法』こそ今の僕には合っていると考えています。

## 今の『タスク管理方法』に落ち着いたワケ
プロジェクトの進行・管理を任されるようになってから「どうしたらタスク漏れがなくなって効率的・生産的に活動できるだろうか」「円滑に進めていくにはどのような『タスク管理方法』が良いだろうか」と考えたものです。

本を少しばかり読んだりYoutubeを見たりして、他の人がどのようにタスクを管理しているのかを探ってみたり。
また、その中で「これは！」と思わせるものを実際に試してみたり。
はたまた、それらを経験した上で自分の思い描く理想（当時）のタスク管理方法を一から作って整えてみたりと試行錯誤しました。

ただ、どれも長続きはしませんでした。

## タスク管理を実行する上でのコツ
色々と試してきた私ですが、どれも長続きしなかったのは何故か。

それはこの章で述べたいコツでもあるのですが、「自分には適切ではなかった」からなのです。
だからこそ、現時点での最適解としてたどり着いたのが「Googleカレンダー+Notion」での管理だったのです。

振り出しに戻ります。
>効果的なタスク管理は生産性向上や目標達成に寄与します。さまざまなタスク管理ツールや手法が存在し、個人や組織の好みやニーズに応じて選択されます。

上記のようにタスク管理は適切に実行することで生産性の向上や目標達成に寄与する一方で、**個人や組織の好みやニーズがあります。**
むしろ個人や組織のニーズに適したタスク管理をすることでタスク管理を適切に実行でき、それがひいては生産性の向上や目標達成に寄与するのではないでしょうか。

つまりは、**自分に適切な『タスク管理方法』を見つける**ということこそが、プロジェクトを円滑に、そして目標達成に近づくためのコツであると考えています。

## 最後に
『タスク管理方法』は世の中にたくさん存在しています。

どれが正解というわけでもないです。
むしろ自分に適した『タスク管理方法』こそが正解だと思います。

そしてそれは必ず見つかると思いますので、是非色々と試してみてください。
僕も引き続き探し続けるつもりです！

というわけで、この記事を読んでくださった皆様にも適した『タスク管理方法』が見つかり、円滑にプロジェクトが進行していくことを願ってそろそろこの記事を締めたいと思います。

最後まで読んでいただきありがとうございました！
機会があればまたお会いしましょう！

またね。
Discordに入らずに、投稿をするbotを作成してみた

# 初めに
Life is Tech ! Advent Calendar 2023の1日目を担当します、 Webサービスプログラミングコース メンターのつぼつぼです。

普段は、webサービス を中心に中高生に向けに、メンターをしています。
また、ITを活用したものづくりを学校の部活として学ぶことができる[SchoolX](https://prtimes.jp/main/html/rd/p/000000139.000019771.html)というプロジェクトにて、クラス全体の運営もしています。

本記事は、SchoolXでの取り組みの一つ **"もくもく宣言企画"** にて制作した物を紹介したいと思います。

# 作成経緯
SchoolXも4期目になり、生徒もだんだんPCを使った物作りが楽しくなってきていることを実感し、さらなる開発時間をとって欲しいという意図でDiscordにて、開発する時間を共有するチャンネルを作成しました。

しかし、Discordの年齢制限や学校ごとのSNSルールなどもあり、Discordを利用できない生徒も多くいました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664651/23bca472-eb67-a5d5-ad51-96569464a416.png" width="50%" alt="image">
引用：https://discord.com/terms#2

生徒全員がDiscordで、もくもく宣言をできるようにしたいという思いから、Discordに入らずとも、もくもく宣言ができるbotを作成しました。

# システム概略図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664651/e9be6261-eea2-b9b4-324c-de8f66c38c34.png)

1週間で実装かつコストをかけたくなかったので、フォーム画面は、ノーコードツールGlideを使用し、zapierにデータを送信し、Discordに送信する仕組みを考えました。
ちなみに、Glideの有料プランを使用すると、Discordに直接送信することができます。

# 実装！

### 1. GlideでFormを作成
GlideでGUI画面を作成します。
インプット画面を作成して、Zapierに送信します。
この辺りの記事が参考になるかと思います。

https://note.com/shinya_matsui/n/n874f88d1c1f9

1. Form Containerコンポーネントを使用して、送信したいデータボックスを配置します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664651/7fde7e02-511f-a731-47cc-d2919958699f.png)

2. Action機能を使用して、Zapierにデータを送信します。




:::note info
今回は、Glide実装で行いましたが、webhockからでもできるはず。
:::

### 2. データの中継 Zapierの設定
Zapierを使用して、連携の設定をします。
最近ZapierにもAIが登場し、自動化の自動化ができるようになりましたね 👀
やりたいことを送ると、以下のように候補を提案してくれてます。
https://zapier.com/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664651/f6b7760f-6007-00f0-da98-3bdb1e8e31ba.png)
Try it を押下し、詳細な設定に入っていきます。
Glideのアカウントとの接続は、API keyを使用して、接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664651/93ed9f8b-edc9-a90a-470a-b2f095244c5e.png)

<details>
<summary>Glide APIkey取得方法</summary>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664651/21ffe693-ef95-fb87-c828-837ee8c124cb.png)
</details>
Glideの設定の終了後、同様にして、Discord側の設定をし、publishをします。

### 3. Glide側でのアクション設定
Glide側で、Zapierに送る設定をします。
Form Container を押した後、右下のAfterSubmitAction項目を押下し、提出ボタンが押された際に、zapierに送信するようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664651/5ad840ac-d56e-b51e-f671-c2f6f7f629bc.png)
Action for Things → Create new actionをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664651/2c3b72be-33a2-e43f-ce8b-412f7a2b851a.png)
2個目のBOXをTriger Zapにすると、zapierにて、設定したZapname名の項目が出てくると思います。
後は、自分の設定した変数の数だけ、valueを追加するだけです。

以上で、設定周りは、終了です！

### 4. テスト！

実際に、Glide側から、データを送ってみましょう！
変数周りをうまく設定していれば、うまくDiscordに、データを送れるはずです！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664651/8a119a86-fd9f-8f20-887a-1939e73f192f.png)

アイコンやユーザーネームを変えると本当にその人っぽく投稿できるかもしれませんね！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664651/5c01eb7b-461b-5104-3fd4-2e1d90bc5cd4.png)

ここまで読んでくださりありがとうございました！！
【Laravel】ヘルパー関数data_getの第二引数がnullの場合の挙動

## はじめに
Laravelで提供されているヘルパー関数data_getの第二引数がnullだった場合の挙動が意図しないものだったので、結果と実際どのような処理が行われているかを理解するために記事をまとめます。

## 実証環境
PHP 7.4
Laravel 6.2

## 引数による結果の違い
第二引数によって、以下ような結果になります。
```php
$characters = [
    'player' => ['cuphead', 'mugman'],
    'boss' => ['The Root Pack', 'Goopy Le Grande', 'Ribby and Croaks']
];
dump(data_get($characters, 'player', '第二引数のキーなし'));
// array:2 [▼
//   0 => "cuphead"
//   1 => "mugman"
// ]
dump(data_get($characters, 'mob', '第二引数のキーなし'));
// "第二引数のキーなし"
dump(data_get($characters, null, '第二引数のキーなし'));
// array:2 [▼
//   "player" => array:2 [▼
//     0 => "cuphead"
//     1 => "mugman"
//   ]
//   "boss" => array:3 [▼
//     0 => "The Root Pack"
//     1 => "Goopy Le Grande"
//     2 => "Ribby and Croaks"
//   ]
// ]
```
1回目のdumpは第一引数に指定した配列やオブジェクトに第二引数のキーが存在するため、その中身を返しています。2回目については、キーが存在しないため、第三引数の値を返しています。
注目するのは3回目のdumpで、第二引数をnullにしたところ配列すべてが返ってきました。デフォルトを設定していますがこちらが返ってくることはありませんでした。

## 実際の処理
ソースコードは以下のようになっています。
```php
function data_get($target, $key, $default = null)
{
    if (is_null($key)) {
        return $target;
    }

    $key = is_array($key) ? $key : explode('.', $key);

    while (! is_null($segment = array_shift($key))) {
        if ($segment === '*') {
            if ($target instanceof Collection) {
                $target = $target->all();
            } elseif (! is_array($target)) {
                return value($default);
            }

            $result = [];

            foreach ($target as $item) {
                $result[] = data_get($item, $key);
            }

            return in_array('*', $key) ? Arr::collapse($result) : $result;
        }

        if (Arr::accessible($target) && Arr::exists($target, $segment)) {
            $target = $target[$segment];
        } elseif (is_object($target) && isset($target->{$segment})) {
            $target = $target->{$segment};
        } else {
            return value($default);
        }
    }

    return $target;
}
```
処理の最初で、キーがnullなら第一引数をそのままreturnしていました。

## 終わりに
単純な処理ではありますが、意図しない挙動があった場合はリファレンスだけではなくてソースコードの確認をすべきだと思いました。

## 参考サイト
[Laravel 6.x ヘルパ](https://readouble.com/laravel/6.x/ja/helpers.html#method-data-get)
【2023年12月版】WindowsでのApache 2.4のインストール・起動方法


この記事では、WindowsでのApache2.4のインストール・起動方法を紹介します。
Windows 10でテスト済みです。

:::note warn
コマンドプロンプト(ターミナル)は管理者権限で実行してください。
:::

<details><summary>用語説明</summary>

**PATHを通す**
「PATHを通す」というのは、簡単に言うと、
OSに「ここにもバイナリがあるよ！」って教えることです。

**サービス**
Windowsの稼働中にバックグラウンドで働き続けるプログラムのことです。
Apacheは、サーバーのソフトなので、バックグラウンドで動かす必要があります。

**32bit**
bitは、ファイルのサイズの大きさを表す単位です。
「16g」は、重さの単位ですね。
一方で、「32bit」は、「1bit」の32倍です。
GBとかよりめっちゃ小さい単位です。
Windows10には、32bit版と64bit(32bitの二倍)版があります。(サポート終了に近づいているため、執筆時点ではダウンロードページは見当たりません)
そのため、Apacheを64bitに対応していないコンピューターで動かす際に使えるように用意してくれています。
ただし注意してほしいのは、32bitコンピューターも32bit以上のファイルは扱えます。
ですが、実行するためのファイルが64bit版の場合、32bit版のOSでは使えません。
詳しくは調べて！

**bash**
bashは、シェルの一つです。

**シェル**
シェルは、OS（オペレーティングシステム）とユーザーの橋渡しをするプログラムです。シェルを通じて、ユーザーがOSの中核である「カーネル」とやり取りすることができます。シェルを利用すると、OSを移行しやすくなる、シェル上でエラーが発生した際にOSへの影響を最小限に止められるなどのメリットがあります。

シェルは、コマンドを入力することで、OSに対して様々な操作を行うことができます。例えば、ファイルの作成や削除、ディレクトリの移動、プログラムの実行などが挙げられます。また、シェルスクリプトと呼ばれるファイルを作成することで、複数のコマンドをまとめて実行することができます。

シェルには、sh、bash、zshなどの種類があります。それぞれ、副次的な機能やコマンド入力のしやすさなどに違いがあります。代表的なシェルは、Linux系OSにおける標準シェルであるbashです。

**OS**
WindowsやmacOSなどのことです。
詳しくは調べて！

ここまでが用語説明だよ！

</details>

# ダウンロード
1. [Apacheのダウンロードページ](https://www.apachelounge.com/download/) にアクセスする。
2. [httpd-2.4.58-win64-VS17.zip](https://www.apachelounge.com/download/VS17/binaries/httpd-2.4.58-win64-VS17.zip)をダウンロードする。(32bit版は[httpd-2.4.58-win32-vs17.zip](https://www.apachelounge.com/download/vs17/binaries/httpd-2.4.58-win32-vs17.zip))
3. 展開し、Apache24フォルダをCドライブ直下にコピー。管理者権限が必要なことがある。

# インストール

## PATHを通す
4. 検索ボックスから「システム環境設定の編集」を開く。管理者権限が必須。
5. 「システム環境変数」欄のPathをダブルクリックし、新規をクリック。
6. C:\Apache24\bin\を入力し、保存。
7. コマンドプロンプト(Win10標準)またはターミナル(Win11を新規インストールで標準)から新しいタブまたはウィンドウを開く。
8. httpd -versionを実行。バージョンが出たらPATHを通せたことになる。

## 設定ファイルの変更
:::note warn
構文などを間違えたりすると起動しなくなります。
気を付けてね！
:::
1. C:\Apache24\conf\httpd.confを開く。PulsarまたはVSCodeが個人的におすすめ。
2. ServerNameと書かれている行が1行あるので、下記のような変更を行う。

```diff_conf: httpd.conf
- #ServerName www.example.com:80
+ ServerName localhost:80
```

## サービスに追加
このコマンドを実行すると、サービスに追加できます。
```bash:サービスに追加するコマンド(bash)
cd "C:\Apache24\bin"
httpd -k install
```


# 起動方法
それでは以下の方法でサーバーを起動してみましょう！
```bash:Apacheを起動するコマンド(bash)
httpd -k start
```

# 起動テスト
テストしてみましょう！
http://localhost/
にアクセスしてみてください！

# おわりに
どうだったでしょうか。
Apache起動できましたか？
それでは、またほかの記事で！
～クリスマスプレゼントにいかが？～おすすめ技術書


どうも、皆様こんにちは。

昨日は@wchikarusatoさんの「[obsidianを使って1週間を楽に振り返る方法](https://qiita.com/wchikarusato/items/866fc2a2ec77d0b8f16e)」でした。

# 前置き
電車での移動中や時間が空いているときは、なるべく技術書を読むように意識しています。
普段はjavaでコードを書いているのでjavaの本多めですが、今まで読んできた本の中でおすすめの本を紹介します。
12月に入り、もうすぐクリスマスです。
恋人やお子さんのプレゼントに悩んでいる方は、この中の本をプレゼントすれば喜んでくれること間違いなしです！

## Java言語で学ぶデザインパターン入門第3版 
https://www.sbcr.jp/product/4815609801/
### 書評
こちらは題名通りJavaを使ってデザインパターンを学べる本となっています。
そもそもデザインパターンとは何か？や23種類あるデザインパターンそれぞれの特徴が書いてあります。
章末には練習問題があるので、理解度を確認することができます。
javaの書き方を知らないという方もいらっしゃると思いますが、javaの勉強も兼ねて手に取ってみてください。

## 良いコード／悪いコードで学ぶ設計入門 ―保守しやすい 成長し続けるコードの書き方
https://gihyo.jp/book/2022/978-4-297-12783-1
### 書評
クラスの責任の所在や早期returnなどコードを書く上で基本的だけれども重要なことが書いてあります。
サンプルコード（こちらもjavaだった気がします、、、）が書いてあり、理解がしやすいです。
大人数で開発するようなプロジェクトの場合はこの本に書いてあることを意識するとよいかもしれません。

## たった2日でマスターできるiPhoneアプリ開発集中講座
https://www.socym.co.jp/book/1278
### 書評
こちらの本を読めばswiftを使って、iPhoneアプリを作れるようになります。
iPhoneアプリはxcodeを使いGUIベースで開発していきますが（コードを書くところもあります）、写真付きで丁寧に記載してます。
3年ほど前のコロナ全盛期の頃ですが、この本を参考に簡単なコロナ診断アプリを個人開発しました。

## みずほ銀行システム統合、苦闘の19年史
https://bookplus.nikkei.com/atcl/catalog/20/277410/
### 書評
技術書とは少し離れてしまいますが、みずほ銀行のシステムリプレースに関する話です。
システム停止により行政から注意を受けたり、旧システムの謎仕様に惑わされたりと、悪戦苦闘する様子が描かれています。
エンジニアだけでなく、支店の事務員など全社で協力してリプレースに注力している感じが読み取れます。
リプレースの中で得た知見などが書かれているので、一読の価値があるかと思います。

## Software Design
https://gihyo.jp/magazine/SD
### 書評
こちらは皆さんご存じな月刊雑誌だと思います。
ソフトウェア開発に必要なトレンド技術からCPUの仕組みのようなハード技術など幅広く記載されています。
エンジニアなど座り仕事の多い人におすすめなストレッチ方法などアイスブレイク的な内容もあります。
年間購読だと少し安いみたいなので、申し込んでみてはいかがでしょうか？

## まとめ
いかがだったでしょうか？
気になった本がありましたら、ぜひ手に取ってみてください。

明日は@youngjae_wonさんです。
お楽しみに！！


ウェブクルーでは一緒に働いていただける方を随時募集しております。
私たちと一緒に働きましょう！
https://www.webcrew.co.jp/recruit/
分析基盤運用のためにAirflowを導入した話

この記事は[ツクリンクアドベントカレンダー2023](https://qiita.com/advent-calendar/2023/tsukulink)の14日目の記事になります！

# はじめに
ツクリンクでは2023/12月現在で約8万社の顧客データを扱っており、今年から本格的な分析環境、データマートの構築に注力してきました。
データマート自体の改修だけでなく、運用するための構成についても様変わりしましたのでまとめてみようと思います。

# 初期の構成
初期の構成を簡単な図にしました。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591967/cd826427-088f-89fc-ef95-ff4b6a658da1.png">
基幹システムからのデータをためているBigQuery上のテーブルをデータウェアハウスとし、BigQuery内でデータマートの作成まで行っていました。
データマート作成用のSQLをBigQueryでスケジュール設定して登録するだけなので、非常にリーズナブルと言えるかと思います。
ただし、以下の不満点も見えてきました。
- 監視がほぼ人力
    - その日のSQL実行がうまくいったかどうかを確認するには、BigQueryのWebページを確認する必要があります。もしかしたらgcloudコマンドとかでステータスを確認できるのかもしれませんが、そのためだけに環境を用意するのはちょっとやり過ぎている気がします。
- リリースも手作業
    - せっかくgitでコード管理しているのに、リリースが手作業でした。masterブランチでgit pullするとリリースされるような仕組みが欲しくなりました。

# Airflowを採用した構成
そもそもAirflowってなにかというと、ワークフロー管理ツールです。
詳しくは[こちら](https://aiacademy.jp/media/?p=1375)にお任せします。
動作環境としてGCEを設置し、Airflowを導入しました。
Airflowで処理されるDAGではpython等のプログラミング言語で柔軟に処理を設定したり、様々なAPIと接続することができます。
今回はpyhtonで実行失敗時にSlackに通知が届くような処理を設定しました。
また、リリース作業はAirflowを稼働させているインスタンス内のmasterブランチでgit pullすればOKになるようにしました。
以下、簡単な図です。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591967/f0ceef9d-4ad1-7d2c-8bc3-250c3566bcc2.png">
実行失敗時には手作業でAirflowにアクセスし登録しているDAGの再実行が必要ではありますが、Airflow導入前よりもかなり自動化が進みました。

# 終わりに
データマートは日々使っていくことで成長するものです。
それは、データマートがどのようなデータを持つか、だけでなくその運用や構成にまで当てはまることだと思います。
現状を完成とは思わず、より良い形を目指していきたいと思います。
Notionの定期タスクに相対日付を指定したかった

# 初めに

:::note warn
この記事はNotionバージョン2.3.2時点の物です。
後のバージョンによって解決されている可能性があります。
:::

Notionのアップデートによって以前はできなかった、定期タスクの日付プロパティに相対日付を指定することが可能になりました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916360/594ccb58-faaf-bbbc-1a58-424d84f29812.png)

これによって、週報ページを定期作成する際に週毎の日付を残せたりできるようになりました。
しかし、ショートカットで表示されるのは「今」と「今日」だけで、「明日」だったり「来週の金曜日」だったりを指定することはできません。

そこで、Notionの仕様を使って無理やり相対日付を定期タスクに指定できないかと考えました。

# Notionの日付プロパティの仕様

日付プロパティに日付を入れてからテキストプロパティに変換すると、中身が日付メンションであることが分かります。

:::note info
日付メンション例：@今日 @明日 @次の金曜日
:::

**テキスト変換前**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916360/e4ffdfc6-ca4e-31cf-2c67-e8a6c454e686.png)


**テキスト変換後**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916360/22d3687e-01ba-05ec-0f9e-56dbaf3fa3c5.png)

では、「テキストプロパティに「@明日」と入れてから日付プロパティに変換すれば他の相対日付も指定できるのでは？」と考えたので実際に実行してみました。


# 実際にやってみた

**実験方法**

1. 毎日の定期タスクのテキストプロパティに「@明日」と入力する
1. テキストプロパティを日付プロパティに変換する
1. 毎日生成される定期タスクの日付が1日ずつ推移しているかを確かめる

これで実際に一日ずつ推移していれば、定期タスクの幅が広がるぞ～

# が・・・・・駄目っ・・・・・！ 

@今日は定期タスクが生成された日付を参照してくれますが、@明日は**定期タスクのテンプレートを作成した日の明日**を参照してしまいます。
比較してみると分かるんですが、「今日」や「今」とは表示のされ方が違うんですよね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916360/42b0631e-7bb8-854d-78b3-4d107f506e1e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916360/30f19238-6cbc-c562-98ae-56fafe27de9d.png)

ウキウキで実験していたのですが、見事希望が打ち砕かれました。

# 終わりに

職場でNotion使っていると、結構定期タスクを生成する機能を多用するのでここら辺の融通が利くと嬉しいな～という感想です。
今後のアップデートに期待ですね。
添字の無いCollectionに値の存在判定を行う

## 概要
Collectionで特定の値の存在判定をする際こんな感じに`contains`を使うと思います

```php
$result = collect([
    [
        'hoge' => 3,
    ],
    [
        'hoge' => 2,
    ],
])->contains('hoge', 3);
//true
```

以下のようなCollectionの場合、困りますよね
```php
collect([3,2]);
```

こういう場合はクロージャを用いてこう書きます

```php
$result = collect([3,2])->contains(fn(int $value) => $value === 3);
//true
```
Jasmine Tea の関数(`FUNCTION`)を使ってみる

これは [Jasmine Tea アドベントカレンダー 2023](https://qiita.com/advent-calendar/2023/jasminetea) の  11 日目の記事です。

こんにちは、[Jasmine Tea](https://jasminetea.app/) の開発に参加している石川です。この記事では Jasmine Tea の関数 (`FUNCTION`) について説明します。

Jasmine Tea の関数(`FUNCTION`)は、手続き(`PROCEDURE`)と似ていて、複数の命令をひとまとまりにできる仕組みです。手続きと違う点は、関数に値を与えて命令を実行するだけでなく、関数から値を返すことができる点です。例えば、`inkey$()` 関数は今押されているキーの文字列を返しますが、似たような関数を独自に定義することができます。

## `FUNCTION` 命令

次のプログラムは[昨日の記事](https://qiita.com/mntsh/items/4f10d86b971d46c5d5d4)で作成したもので、クリックや十字キーでキャラクターを動かすプログラムです。(動作確認は[こちら](https://jasminetea.app/studio/projects/M1fTUvPB84EJRSI9nyJU))

```
procedure move_sprite number, x, y, sd, d
  sprite number, 0, number * 4 + sd
  show number, (x, y)
  direction number, d
  distance number, 600
  speed number, 20
  move number
end procedure

sprite_number = 0
do
  tap x, y
  if x <> -1 and y <> -1 then
    call move_sprite sprite_number, x, y, 3, 3
    sprite_number = (sprite_number + 1) % 13
  end if
  
  key$ = inkey$()
  if key$ = "ArrowLeft" then
    call move_sprite sprite_number, 320, 200, 2, 7
    sprite_number = (sprite_number + 1) % 13
  else if key$ = "ArrowUp" then
    call move_sprite sprite_number, 320, 200, 1, 1
    sprite_number = (sprite_number + 1) % 13
  else if key$ = "ArrowRight" then
    call move_sprite sprite_number, 320, 200, 3, 3
    sprite_number = (sprite_number + 1) % 13
  else if key$ = "ArrowDown" then
    call move_sprite sprite_number, 320, 200, 0, 5
    sprite_number = (sprite_number + 1) % 13
  end if
loop
```

このプログラムの `(sprite_number + 1) % 13` は、「つぎのスプライトの番号」を計算しています。この部分が繰り返されているので、ひとまとまりの命令のように書きたいです。しかし、計算結果を `sprite_number` に代入しなくてはならないため、手続きをここで使うことはできません。こういうときは、関数(`FUNCTION`)を使うとよいでしょう。

関数は命令を `function` と `end function` で囲み、返す値を `return` で決めます。 `function` の後ろには関数の名前と受け取る値（引数）を指定します。

```
function next_sprite_number()
  return (sprite_number + 1) % 13
end function
```

## 受け取る値（引数）や返す値(戻り値)の種類

受け取る値はなくてもよいですし、複数あってもよいです。また、数値、文字列、配列のどれでも使うことができます。一方で返す値は必ず 1 つである必要があります。ただし、受け取る値と同じように数値、文字列、配列のどれでも使うことができるので、もし 2 つ以上の値を返したいときは配列を使うと良いでしょう。

例として、 `inkey$()` の値に応じて、`move_sprite` の `sd` と `d` の値を決める関数を作ってみます。返す値は `sd` と `d` からなる配列にするため、関数の名前には配列の記号 `@` をつけます。また、受け取る値は文字列なので、受け取る値の名前には `$` をつけます。

```
function directions_of_key@(key$)
```

`directions_of_key@` の中身は以下のようにします。

- `key$` の値が十字キーの場合: `sd` と `d` の値を返す
- それ以外の場合: からの配列 `[]` を返す

このようにしておけば、`directions_of_key@` を使う側で `len` を使って配列の長さを確認し、`move_sprite` を呼び出すべきか決めることができます。(プログラムの全体は[こちら](https://jasminetea.app/studio/projects/ItFlpSKukO1AhIFj6Zxq))

```
...
function directions_of_key@(key$)
  if key$ = "ArrowLeft" then
    return [2, 7]
  else if key$ = "ArrowUp" then
    return [1, 1]
  else if key$ = "ArrowRight" then
    return [3, 3]
  else if key$ = "ArrowDown" then
    return [0, 5]
  else
    return []
  end if
end function

  ...  
  directions@ = directions_of_key@(inkey$())
  if len(directions@) = 2 then
    call move_sprite sprite_number, 320, 200, directions@[0], directions@[1]
    sprite_number = next_sprite_number(sprite_number)
  end if
  ...
```

## 次回は

次回は、二次方程式の解を求める関数を作成してみます。
wsl2に変更

https://learn.microsoft.com/ja-jp/windows/wsl/install-manual

これで![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587191/369648ac-585d-a10b-c219-c8bcc7a71de3.png)


この更新プログラムをインストール。

wsl --set-version <Distro> <Version>

を実行する。
動作が不安定な研究用サーバへの応急処置

研究の過程で，計算性能はそれほど必要無いものの，単純な作業をひたすら繰り返すことができるPCが必要となりました．そこで，そのために新しいPCを購入するわけにもいかないので，研究室内に転がっているPCパーツをかき集めて1台のサーバを構築しました．（ちなみに，ミニPCやラズパイなどを用いれば良いのではという声が聞こえてきそうですが，スペックが不十分なので今回は使っていません．）

そんなわけで，問題が発生しました．タイトルにもあるように，**動作が不安定になった**のです......（まあ，当然ですよね．用いたパーツの中には購入から5～6年経過している物もありました．）
当然，どのパーツが悪さしているか（ソフトウェアの方は構築の際に入れたばかりなので除外しています．）を調査して交換すべきですが，発表が近づいてきていることやその他の業務に忙殺されており，そのような時間が取れそうになく......
であれば，ソフトウェア側の操作で応急的に対処ができないか？と考えた次第です．

:::note
以下の内容は「こうしてみました」という一例だと考えていただければ幸いです．もしより良い方法があればご教示頂けますと大変喜びます．（正直，このようなエラー続きで萎え始めているところです笑）
また，詳細な説明は省いています．この記事の最後に参考にした記事へのリンクを掲示しているので，そちらを参照なさって下さい．
:::

# Watchdog の導入
先述の通り動作が不安定になったサーバですが，重い処理を実行した際に落ちるというわけではなく，特に何もしていない状態で落ちています．すなわち，許容範囲を超える処理のためにフリーズし，その結果落ちているわけではないと考えてます．
そのため，Watchdogの原理からはそれほど有効ではないと思われますが，可能性を可能な限り潰しておくという判断から導入することにしました．

## インストール方法
先ずはパッケージのインストールを実行します．

```bash
sudo apt install watchdog
```

次に，各種設定をおこないます．以下のように設定ファイルに書き込んでいきます．

```bash: /etc/default/watchdog
watchdog_module = "softdog"
```

```bash: /etc/sysctl.conf
kernel.panic = 60
kernel.panic_on_oops = 1
```

これらの詳細な説明や設定は最後に挙げている参照リンク，またはご自身で検索されて下さい．（今回の件で初めて検索したばかりなので，説明できるほどの理解には及んでいません．）

最後に，以上の設定を反映させます．

```bash
sysctl -p
sudo systemctl stop watchdog
sudo systemctl start watchdog
```

以上を実行し，`sudo systemctl status watchdog`で`Active: active (running)`と表示されていれば成功です．

:::note
`sudo systemctl restart watchdog`だと何故か上手くいきませんでした．自身の環境に依存する症状かもしれないので，ここで補足しておきます．
:::


# Wake on Lan の導入
根本的に全く問題が解決していないので，当然，サーバの電源が落ちることが予想されます．そこで，遠隔で電源を入れることができないかと調べた結果，Wake on Lanというものを発見しました．これはピッタリだと思い導入を決意．

:::note
クドいかもしれないが，そもそもサーバが落ちる根本的な原因を調査するのが良いのは自明で，しかし，パッと見での原因（ファンが回っていない，CPU温度が高すぎる，など．）が無いことと時間がないことからこのような対処になっています．（加えて，今回の繰り返し処理は毎日おこなう予定のものですが，数日くらい止まってしまっても問題ない処理であることも要因の1つです．）
:::

## インストール方法
先ずはBIOS/UEFIからハードウェアレベルのWake on Lanを有効化します．この処理はマザボメーカによって異なるため，「マザボ名 Wake on Lan」などで検索するか，あるいは詳しい人は PCIE の電源設定を有効にして下さい．
また，私のBIOSでは見当たりませんでしたが，節電モードや省エネモードの設定がある場合には無効にする必要があるそうです．

:::note alert
BIOS/UEFIの設定はPCの根本に関わる設定であり，間違った設定をおこなうことで重大な悪影響を被る可能性があります．十分な注意の上，自己責任でおこなって下さい．
:::

次に，以下のコマンドを実行し，`ethtool`をインストールする．

```bash
sudo apt install ethtool
```

インストール完了後，ソフトウェアレベルでのWake on Lanを以下のコマンドで有効化します．

```bash 
sudo ethtool -s <デバイス名> wol g
```

ちなみに，`<デバイス名>`の確認は`ip link`でできます．
以上の操作がうまくいっていれば，`sudo ethtool <デバイス名> | grep -i wake-on`に対して`Wake-on: g`という出力が得られます．

最後に，以上の設定を永続化させます．事前の準備として`nmcli con show`を実行し，上の`<デバイス名>`に対応する`"有線接続名"`を確認しておきます．

```bash
nmcli c modify "有線接続名" 802-3-ethernet.wake-on-lan magic
nmcli c up "有線接続名"
```

以上の操作がうまくいっていれば，`nmcli c show "<有線接続名>" | grep -i wake-on-lan`に対して`802-3-ethernet.wake-on-lan: magic`という出力が得られます．

## 動作確認
起動するPCと同じネットワークに入っている別のPCに``パッケージをインストールします．

```bash
sudo apt install wakeonlan
```

以下のようなコマンドで実行し，対象のPCが起動すれば成功です．

```bash
wakeonlan <対象のPCのMACアドレス>
```

# 補足事項
サーバのスペックなどについて関係すると思われる部分を簡単にまとめておきます．

|項目|説明|
|--|:-|
|OS|Ubuntu 22.04 LTS|
|CPU|AMD製|

# 最後に
サーバへの応急処置をおこなうにあたって参考にさせていただいた記事を以下に示します．この場を借りて，お礼申し上げます．

https://pcvogel.sarakura.net/2014/11/19/31386

https://chatnoirlibre.com/ubuntu-22-04-wake-on-lan/
Modelのタイムスタンプは自動でCarbonオブジェクトにキャストされるよ

## 概要
マイグレーションに
```php
$table->timestamps();
```
と記述すると、`created_at`カラムと'updated_at'カラムが生成されますよね。

これら2つはモデルオブジェクトから値を取り出した際にCarbonオブジェクトにキャストされます。これからそれを確認してみましょう。

## 内容

```php
dd(User::select(['id','created_at','updated_at'])->first());
```

![スクリーンショット 2023-12-06 17.44.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/c72e3e40-8e38-007b-b677-32fa26cd52a6.png)

ふむ、文字列のタイムスタンプが取得できてますね。

では次に値を取り出してみましょう
```php
dd(User::select(['id','created_at','updated_at'])->first()->created_at
);
```
なんとびっくり、Carbonオブジェクトになっています。
![スクリーンショット 2023-12-06 17.45.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/8519df22-e4e1-6a8e-3981-e6cc556880c4.png)

これで値を取り出す際に自動でCarbonオブジェクトにキャストされている事が分かりました。
## 参考

https://readouble.com/laravel/10.x/ja/eloquent-mutators.html?header=%25E6%2597%25A5%25E4%25BB%2598%25E3%2581%25AE%25E3%2582%25AD%25E3%2583%25A3%25E3%2582%25B9%25E3%2583%2588

> デフォルトでは、Eloquentはcreated_atカラムとupdated_atカラムをCarbonのインスタンスへキャストします。
2日目: A Model of Saliency-based Visual Attention for Rapid Scene Analysis(1998)

### A Model of Saliency-based Visual Attention for Rapid Scene Analysis(Christof, 1998)

古いが引用数が多く、おそらくこの分野でかなり重要と思われる論文．

ニューラルネットのアプローチを応用して画像上の注目点を求めるモデルを提案．
（近年のディープラーニングを応用したモデルの始祖？）

この研究では複雑なシーンを素早く解析するために、人間の視覚システムがどのように注視を行うかを模倣することを目指している．

人間の"注意の焦点"(focus of attnetion)は以下の2つの方法で決まる．
**1、高速でボトムアップな顕著性主導のタスクに依存しない方法(周囲と比べて目立つ部分)**
**2．低速でトップダウンの意思に制御された、タスクに依存する方法(自分が注目したい部分)**
この2つでシーンを走査している．
Attention モデルには上記トップダウン、ボトムアップの両方の制御に基づいた"動的ルーティング"というモデルがあるが、この研究では"特徴統合理論"(feature integrated theory)を基にする．画像を幾つかの**トポロジカル特徴マップ(topological feature map)**の集合に分解し、それぞれの**顕著性(saliency)(周囲に比べてどのくらい目立つか)**を求め、最終的に1枚に統合された**顕著性マップ**を求める．

具体的には図のようにカラー、強度、向きに分解し、顕著性マップを求める．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981660/d67020f2-3ad7-fd4a-627a-d564a2edb3dc.png)
論文内 図1

また，各マップには正規化ステップも含まれている（これが論文のコントリビュートの1つ？）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981660/63483214-1522-a72f-1abc-96bfac9502fb.png)
論文内 図2

提案手法であればノイズが含まれているような画像でも最もらしい顕著性マップを求めることが出来ている．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981660/f862cd44-0259-5762-308a-5f8678fa9df4.png)
論文内 図4


### 所感
1998年の時点ですでにニューラルネットを用いたアプローチをとっていることが興味深い．
機械学習は専門ではないが、"ニューラルネットの考え方自体は昔からありGPUなどマシンスペックの向上により高度なものが実用的になった"というよく聞く話が本当なんだなと実感．

引用数が多いのも納得で、もう少し時間をとって読み込みたい
ユーザー行動データの分析をSQLで（出来る範囲で）やってみた

こんにちは、アルファドライブのいわたです。

この記事は「[AlphaDrive Advent Calendar 2023](https://qiita.com/advent-calendar/2023/alphadrive-tech)」の6日目のエントリーです。

本日はSQLで簡単なデータ分析を行った時のTIPSについて書きます。
実装に使用した環境はPostgreSQL 13.7です。
記述したSQLは分かりやすく変更しています。

## はじめに
RDBなどのデータに対して、SQLでピボット的にクロス集計をしたい、というシーンはないでしょうか？
例えば、以下のようなテーブル（アクティビティデータという名称とします）があり、Webサービス上でユーザーが特定のアクティビティを行った時にデータが生成されるものとします。（だいぶ簡略化しています）

| ユーザーID | データ作成日 |
|:-:|:-:|
| 1  | 2023-12-01  |
| 2  |  2023-12-02 |
| 3  |  2023-12-02 |
| 1  | 2023-12-03  |
| 2  |  2023-12-02 |

## SQLを書いてみる
以下のように集計して分析しやすくしたいと考えました。
ひとつのユーザーIDは一行にまとめ、縦に持っている項目を横持ちに展開するイメージです。
| ユーザーID | 2023-12-01 | 2023-12-02| 2023-12-03|
|:-:|:-:|:-:|:-:|
| 1  | 1  | 0  | 1  |
| 2  | 0  | 2  | 0  |
| 3  | 0  | 1  | 0  |

試行錯誤した結果、以下のように書くことで上記のイメージに沿ったデータを取得することができました。
``` sql:
SELECT "ユーザーID",
       SUM(CASE WHEN "データ作成日" = '2023-12-01' THEN 1 ELSE 0 END) AS '2023-12-01',
       SUM(CASE WHEN "データ作成日" = '2023-12-02' THEN 1 ELSE 0 END) AS '2023-12-02',
       SUM(CASE WHEN "データ作成日" = '2023-12-03' THEN 1 ELSE 0 END) AS '2023-12-03'
FROM "アクティビティデータ"
GROUP BY "ユーザーID";

```

直感的に、ユーザーごとにGROUP BY を行うことが必要になると考えられると思います。
CASEを使用してサマリーすることでGROUP BYした時に複数行になる状態から変えることができました。
### アレンジ
上記ではデータの件数を取得していますが、データの有無を端的に見たい場合は以下のように書くことが出来ます。
``` sql:
       MAX(CASE WHEN "データ作成日" = '2023-12-01' THEN 1 ELSE 0 END) AS '2023-12-01',
```

件数0の場合を空欄にて視覚的にはっきりと見せたい場合は以下のように書くことも出来ます。
``` sql:
       MAX(CASE WHEN "データ作成日" = '2023-12-01' THEN '○' ELSE null END) AS '2023-12-01',
```
上記のように書いた場合、以下の結果になります。
| ユーザーID | 2023-12-01 | 2023-12-02| 2023-12-03|
|:-:|:-:|:-:|:-:|
| 1  | ○  |   | ○  |
| 2  |   | ○  |   |
| 3  |   | ○  |   |


## 上記以外の実現方法
今回のSQLを書いたあと、同様のことを実現する方法はないか調べてみました。
以下それぞれのRDBではビルトインの仕組みがあり、より簡単に書くことができそうです。

- PostgreSQL
    - crosstab
- SQL Server
    - pivot
- Oracle
    - pivot

用途に応じて適切に使用しデータ分析を行うことが重要だと思いました。
paiza.ioでelixir その263

# 概要
paiza.ioでelixirやってみた。
ためになる、コード見つけたのでやってみた。

# 参考にしたページ

https://qiita.com/makoto-developer/items/01d36c6a096575770288

# サンプルコード

```


defmodule Probrem do
  def get_input() do
    :stdio 
    |> IO.read(:all)
  end
  def get_input(input) do
    input
  end
  def solve(input) do
    result = input 
        |> String.trim() 
        |> String.split("\n") 
        |> Enum.join(",")
    result = result <> "\n"
    result
  end
  def answer(result) do
    result
  end
end

Probrem.get_input() 
|> Probrem.solve() 
|> Probrem.answer() 
|> IO.puts

```

# 入力データ

```
hello
world

```

# 実行結果

```
hello,world

```

# 成果物

https://paiza.io/projects/MkOlafxQv9pXGeQ1yToliA?language=elixir


以上。
クロスアカウントなCodePipelineとCodeCommitの連携

とある事情で AアカウントにあるCodeCommitリポジトリを、BアカウントのCodePipelineで取得する必要がありました。

その際いくつかハマったのでメモとして残しておきます。

# CodePipelineのRole

CodePipelineには、StageごとにRoleを指定する機能があります。
> [AWS::CodePipeline::Pipeline ActionDeclaration](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codepipeline-pipeline-actiondeclaration.html#cfn-codepipeline-pipeline-actiondeclaration-rolearn)

これは、CodePipelineが動作中に、指定されたRoleに AssumeRole してくれる機能です。
そのためCodePipelineのRoleのポリシーに、 `sts:AssumeRole` を追加しておく必要があります。

# CodeCommit

CodeCommitにはリソースベースのポリシーがありません。
そのため、今回はAアカウントに CodeCommitRoleを作成し、そのロールに以下の権限を付けてあります。

```yaml
Effect: Allow
Action:
  - codecommit:Get*
  - codecommit:GitPull
  - codecommit:UploadArchive
  - codecommit:CancelUploadArchive
Resource:
  - !Ref CodeCommitRepositoryARN
```

その上で、AssumeRolePolicyとして、BアカウントからのAssumeRoleを許可しました。

```yaml
AssumeRolePolicyDocument:
  Version: "2012-10-17"
  Statement:
    - Effect: Allow
      Principal:
        AWS: "<Bアカウント>"
      Action:
        - 'sts:AssumeRole'
```

# これだけでは動かない

しかし、残念ながらこれでは動きません。
Bアカウントのパイプラインは、CodeCommitRoleにAssumeRoleしているため、パイプラインのアーティファクトストア（BアカウントのS3）にCodeCommitから取得したソースコードをs3にPutすることができないのです。

そのため、CodeCommitRoleにs3へのPut権限を付ける必要があります。

```yaml
Effect: Allow
Action:
  - s3:PutObject
  - s3:PutObjectAcl
Resource:
  - !Sub "arn:aws:s3:::${バケットのプレフィックス}-*/*"
```

> ※ バケットはCloudFormationで作成しているので、プレフィックスを固定にしています。

# 無事にPutできた

s3に無事にPutすることができるようになりました。
しかし、Objectをダウンロードしようとすると、復号に失敗するエラーが発生します。

これは、CodeCommitRoleがs3へPutする際に、AアカウントのKMSキーを使って暗号化してs3にPutするために発生しています（おそらく）


# KMSで暗号化

それを回避するためにCodePipelineのArtifactStoreの設定で、KMSを明示するようにしました。
（aws/s3 のKMSキーを使用しようとして、それぞれのアカウントにデフォルトで存在するため、それが使用されてしまったという理解をしています）

これはBアカウントで作成するリソースです。

```yaml
ArtifactStore:
  Type: S3
  Location: !Ref ArtifactBucket
  EncryptionKey:
    Type: KMS
    Id: !GetAtt BucketEncryptionKey.Arn
```

KMSのキーポリシーには、Aアカウントが使用できるようにする必要があります

```yaml
BucketEncryptionKey:
  Type: AWS::KMS::Key
  Properties:
    KeyPolicy:
      Version: '2012-10-17'
      Statement:
        - Effect: Allow
          Principal:
            AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root'
          Action:
            - 'kms:*'
        - Effect: Allow
          Principal:
            AWS: "Aアカウント"
          Action:
            - 'kms:Encrypt'
            - 'kms:Decrypt'
            - 'kms:ReEncrypt*'
            - 'kms:GenerateDataKey'
            - 'kms:DescribeKey'
          Resource:
            - '*'
```

そして、CodeCommitRoleにこのKeyを使用できるようにします。

```yaml
- Effect: Allow
  Action:
    - 'kms:Encrypt'
    - 'kms:Decrypt'
    - 'kms:ReEncrypt*'
    - 'kms:GenerateDataKey'
    - 'kms:DescribeKey'
  Resource:
    - !Ref BucketEncryptionKeyARN
```

こうすることで無事BアカウントのCodePipelineがAアカウントのCodeCommitを取得できるようになりました。

# まとめ

クロスアカウントでCodePipelineからCodeCommitのリポジトリを使用する方法を考えました。
クロスアカウントは何をやるにしても大変なのでやらないで済むに越したことはないなと思いました。
都道府県コードはどこから来たのかそしてどう処理すべきなのか

Googleで「都道府県コード」を検索すると一位に出てくる国土交通省の[都道府県コード 〈 ファイル名称：PrefCode 〉](https://nlftp.mlit.go.jp/ksj/gml/codelist/PrefCd.html)が処理に適しないことで国のリテラシーを疑っているツイートが目にしました。該当ページを見ていろんな反応を見て、いくつか疑問が上がってきました。
1. 都道府県コードは誰が制定したものなのか
1. このページは本当にひどいのか
1. 正しそうな取得方法は何なのか

これらについて調べたものを記そうと思います。

## 都道府県コードは誰が制定したものなのか
詳しくは[全国地方公共団体コードのwikipedia](https://ja.wikipedia.org/wiki/%E5%85%A8%E5%9B%BD%E5%9C%B0%E6%96%B9%E5%85%AC%E5%85%B1%E5%9B%A3%E4%BD%93%E3%82%B3%E3%83%BC%E3%83%89)を参照すれば良いですが、簡単に話すと、
都道府県コードは（現）総務省が制定した全国地方公共団体コードから派生し、<b>（現）経済産業省</b>が制定している（現）JIS X 0402に規定されているものとなります。
オフィシャルに公式なものですと、[JIS X 0401「都道府県コード」](https://www.jisc.go.jp/app/jis/general/GnrJISNumberNameSearchList?show&jisStdNo=X0401)で公開されているものとなります。ただJIS X 0401は公文書でありPDFとなっている上で、ダウンロードするためには、新規登録、ログインなど煩雑な手順が必要になります。
## このページはひどいのか
個人的に誤解を生みそうな問題点をまとめました。

1. Googleが<b>勝手に</b>一番上に表示した
[該当ページ](https://nlftp.mlit.go.jp/ksj/gml/codelist/PrefCd.html)をもう少し詳しく見てみましょう。
    1. 紙に印刷しやすそうな形式
    1. 上位リンクの[国土数値情報ダウンロードサイト](https://nlftp.mlit.go.jp/ksj/)は一見該当ページへ遷移するリンクがない
    1. [国土数値情報ダウンロードサイト](https://nlftp.mlit.go.jp/ksj/)では似たような内容の[コードリスト「行政区域コード」](https://nlftp.mlit.go.jp/ksj/gml/codelist/AdminiBoundary_CD.xlsx)を提供している

    以上から見ると、<b>外部公開を想定していない</b>可能性があり、役所仕事のペンや紙を使う仕事で都道府県コードを参照するためのものだと推測できます。正直そこまでセンシティブな情報でもなく、実際印刷したい人もいると考えると、ブロックするほどでもありませんが、強いて言うならばrobots.txtによるクローラー対策は挙げられます
1. 都道府県コードをわかりやすい場所で公開していない
「都道府県コード決定版！！！」みたいなものを作って、一位に来るようにSEOを頑張れば（税金でSEO頑張るって言われると少しうーんって気持ちにもなりますが）、初見で困る人がかなり減ると思われます。

以上を踏まえてこのページは批判されるべきのものなのかどうかを考えると、<b>個人的に</b>はそうではありません。理由は単純です。この表はITエンジニア用に作っていません。明らかに印刷用で、むしろ置いてくれてパッと確認したいときに助かっている人もいると思います。<b>このページに列を分けてるとかで文句をつけてるということは、五十音順の表の並びに文句をつけているのと同じだと思います。</b>
## 正しそうな取得方法は何なのか
1. 総務省が[全国地方公共団体コード](https://www.soumu.go.jp/denshijiti/code.html)で公開している[「都道府県コード及び市区町村コード」のExcelファイル](https://www.soumu.go.jp/main_content/000894847.xls)を使う（以下Python/Pandasの処理例）。
    ```python
    import pandas as pd

    df = pd.read_excel(
            "https://www.soumu.go.jp/main_content/000894847.xls", 
            usecols="A,B", 
            names=["dantai_code", "prefecture_name"],
            dtype=str)
    df["prefecture_code"] = df["dantai_code"].str[:2]
    df = df[["prefecture_code", "prefecture_name"]].drop_duplicates()
    ```
1. 非公式ライブリーやコードスニペットを利用する
    Githubなどで検索すれば様々な言語のものが山ほど出てきますので、皆使うんだなって思いました。団体コードは常に変更する可能性があり、できる限り総務省のデータを使うべきですが、都道府県コードはよほどのことがない限り変わらないので利用しても（無論最低限のチェックはしたほうが良いが）さほど問題にはならないと思います。
    - Javascript: https://gist.github.com/mitsugu/569607
    - PHP: https://gist.github.com/miya0001/1916258
    - API: https://madefor.github.io/jisx0401/
1. 手打ち
    タイピングスピードにもよりますが、10分もいらないと思いますので、タイピング練習にいかがでしょうか。

## 最後に
同じデータでも世の中では様々な人に使われていて、その人たちによって様々な使い方をされているため様々な形式が存在するのは当たり前で、どれが正しい形式というものがありません。データを引っ張ってきて処理する前に、まず
1. このファイルの内容は正しいか
1. このファイルはこれからの処理に適しているか
1. 処理自体にかかる時間はどれくらいｎのか（手打ちのほうが速いのか）

を検討するところから始まるべきと考えています。Googleを使っているのはITエンジニアだけではありませんので、一般人が見たいものを一番上に出てくるものも普通にあり得ることだと思いますので、それだけではリテラシーなどの話は出てくることはまずないと思います。
【アンチパターン】そのGAS遅くない？ 処理が遅い場合の改善方法

# はじめに
GASは手軽にコードを実行でき、Googleアプリケーションとの連携が簡単にできます。
しかし、コードの書き方によっては処理に時間がかかる場合があります。
しかもGASには実行時間制限(6分)があるため、実装方法でミスをすると、処理が完了しないという事態も起こりえます。
この記事では、処理を早くするテクニックを実例を用いて解説します。

# APIの呼び出しは最小限に
Apps Script APIをGASから呼び出す際は気を付ける必要があります。
APIの呼び出しには一定の時間がかかり、これが積み重なるとどんどん処理が重くなっていきます。
特に、ループ文の中でAPIを呼び出す事はなるべく避けるようにしてください。

# データの取得や作成は一括でする
スプレッドシートなどからデータを取得する際には、なるべく一度にデータを取得しましょう。データの作成時も同様です。
一行一行処理をするといった場合でも、一行ごとにデータを取得するのではなく、一括取得したデータを配列として取り扱い、処理した後に、一括でデータを作成するほうが高速に動作します。

# 悪い例
以下の例では、forループの中で各行に対してAPIを呼び出しており、データの取り扱いも不適切です。

```javascript
function badExample() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート1");
  var totalRows = sheet.getLastRow();

  for (var i = 1; i <= totalRows; i++) {
    var range = sheet.getRange(i, 1, 1, 3); // Bad:何度もAPIを呼び出している
    var values = range.getValues(); // Bad:個別にデータを取得している

    // ここでvaluesを使って必要な処理を行う

    range.setValues(values); // Bad:個別にデータを作成している
  }
}
```

# 良い例
以下の例では、APIの呼び出しやデータの取り扱いが適切になされています。
```javascript
function goodExample() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート1");
  var range = sheet.getDataRange(); // Good：APIの呼び出しを最小限にする
  var data = range.getValues();// Good:一度に全データを取得
  var setData = [] //※2次元配列にしないと反映されない

  for (var i = 0; i < data.length; i++) {
  
    // ここでdata[i]を使ってsetDataに追加する
  
  }

  range.setValues(setData); // Good：変更後のデータを一度にスプレッドシートに反映
}
```

# 処理時間計測
それぞれの例の処理時間をスプレッドシートの行データを増やして比較してみました。
<table>
  <caption>実行時間の比較</caption>
  <thead>
    <tr>
      <th>行数</th> <th>badExample()</th> <th> goodExample()</th>
    </tr>
  </thead>
  <tr>
    <td> 10 </td> <td>1,905ms</td><td>239ms</td>
  </tr>
  <tr>
    <td> 100 </td> <td>22,839ms</td><td>447ms</td>
  </tr>
    <tr>
    <td> 1,000 </td> <td>231,814ms</td><td>592ms</td>
  </tr>
    <tr>
    <td> 10,000 </td> <td>実行時間制限オーバー</td><td>1,784ms</td>
  </tr>
</table>

badExample関数は、行数が10倍になるたびに、実行時間もほぼ10倍になってますね。1,000行を処理するのに、4分弱もかかりました。
それに比べてgoodExample関数は１万行を超えても2秒以内に処理が完了しています。

# まとめ
意外とやってしまいがちなアンチパターンの改善点をまとめました。良きGASライフを！
さくっとOpenTelemetryをElastic Observabilityで試す方法

# はじめに
オブザーバビリティ界隈では、ますますOpenTelemetryの人気が上がっていますが、本記事ではさくっとバックエンドの監視ツールとしてElasticを試してみる方法を紹介します。

OpenTelemetryのDemoアプリケーションを使います。Demoアプリケーションのバージョン1.5.0で動作確認しているので、それを使う前提です。
https://opentelemetry.io/docs/demo

# 前提
* 4 GB RAM のパソコンがあればかろうじて動くと思います。（公式的な推奨は6GBか8GBだったとかだったと思います）
* Docker Compose v2 以上が必要です。
* Elastic環境はv8の新しめのバージョンであれば使えると思いますが、今回は8.10でやっています。Elastic Cloudを使うと非常に楽に環境を作って消すことができます。

# 手順

手順1. v1.5.0のコードをダウンロードし、docker-compose upでまず起動確認してください。
```
git clone https://github.com/open-telemetry/opentelemetry-demo.git --branch 1.5.0  --single-branch opentelemetry-demo-1.5.0

cd opentelemetry-demo-1.5.0
docker-compose up --no-build -d
```

手順2. KibanaのAPM画面からAdd dataをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/7ccb6018-afa6-541e-5749-656d8e1ba50c.png)

手順3. OTEL_EXPORTER_OTLP_ENDPOINT と OTEL_EXPORTER_OTLP_HEADERSの値をコピーしてメモしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/36e009e7-0551-9d40-6e7f-636a510119b2.png)

手順4. 1.でダウンロードしたコードのsrc/otelcollector/otelcol-config-extras.ymlをエディタで開き、以下をコピーしてください。
```
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
# extra settings to be merged into OpenTelemetry Collector configuration
# do not delete this file
exporters:
  logging:
    loglevel: warn 
  otlp/elastic:
    endpoint: "<ELASTIC_APM_SERVER_URL>"
    headers:
      Authorization: "Bearer <ELASTIC_APM_SECRET_TOKEN>"

processors: 
  memory_limiter:
    check_interval: 1s
    limit_mib: 2000
  batch:

service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [logging, otlp/elastic]
    metrics:
      receivers: [otlp]
      exporters: [logging, otlp/elastic]
    logs: 
      receivers: [otlp]
      exporters: [logging, otlp/elastic]

```
手順5. メモしておいてURLとトークンを上記の<ELASTIC_APM_SERVER_URL> と <ELASTIC_APM_SECRET_TOKEN> へ置き換えてください。(トークンは: Authorization: "Bearer QlXHQrkIEFY6IMiNCl"　のような形となります。)

手順6. 
`docker-compose up -d`か`docker-compose restart otelcol`でコンフィグを反映させます。

数分すれば、以下のようにAPM画面でデータが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/e4296e2c-7391-db30-4a46-80bbed0cf505.png)

どうしてもメモリが足りない！　という場合、いくつかサービスを減らしたこちらのdocker-compose.ymlを試してみてください。
https://gist.github.com/nobuhikosekiya/428be2c7339d5821bdfc65eb63332e1e
ガチのエンジニア初心者がUdemyで受講すべき講座

# はじめに
私は現在、理系大学院生として学生生活を過ごしています。もちろん就活もあるわけで、IT業界での就職を志望しています。
大学院での専攻は、情報系ではないために自学自習でエンジニア就活のスキルアップに向けて日々邁進しております。
自学自習と言っても、技術書を読んでコーディングしたり、寄付講座を受けたり、授業で学習など...様々な勉強方法がある中で、私が今まで行った勉強方法の中で最も良かったのは、**Udemy**の講座を受講することです。

## Udemyとはなんぞや
簡潔にまとめると、**Udemy**は動画を見て学習するサービスです。教育テレビの高校講座みたいなイメージです。個人で動画がまとめられた講座を購入して学習します。
[Udemy](https://www.udemy.com/?utm_source=adwords-brand&utm_medium=udemyads&utm_campaign=Brand-Udemy_la.JA_cc.JP&utm_term=_._ag_106402441658_._ad_451172770945_._de_c_._dm__._pl__._ti_kwd-296956216253_._li_1009306_._pd__._&utm_term=_._pd__._kw_udemy_._&matchtype=b&gad_source=1&gclid=Cj0KCQiAsburBhCIARIsAExmsu4cu1A3F359KwI_LHJEkOD54KtxcXs2rH5mYMrZB__TVqJqGO1Pk6waAgzuEALw_wcB)のホームページを見てみると、プログラミングだけでなく、デザインやロジカルシンキングなど色々なジャンルの講座が幅広い価格帯で提供されています。
価格を見ると、高い...と感じるかもしれませんが、かなりの頻度でセールをやっている印象で、セール時にまとめて購入するのが良いのかと思います。（返金もできるみたいです。よく調べて購入してください）

## 実際に購入した講座
いくつか講座は購入しましたが、題名にもあるように***ガチの初心者***が受講すべき講座は
[こちら](https://www.udemy.com/course/web-app-development/)です。
![スクリーンショット 2023-12-06 17.15.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3559951/aeb5e908-c7b7-1372-3c0e-e0ac957c0e8c.png)

## おすすめしたい理由
* 内容がてんこ盛り（`HTML`から`Docker`まで、更には`AWS`の`EC2`も）
* -プログラミング初心者OK!-のようにわかりやすい解説とレベル感
* 内容の割にセール中だとコスバ良し
* 購入したら何回でも見れる

画像にもあるようにタイトルのプログラミング初心者OK!というアピールに引かれて購入しました。
また、Webシステム開発のことを勉強したかったので`HTML`から`Docker`まで、更には`AWS`の`EC2`までてんこ盛りの内容だったのも魅力でした。しかもセール中だと画像の値段で、購入するのが後ろめたくなるくらいの割引です。
**Udemy**の講座を受講する前にある程度学習していたので、受講しても全くわからないという状態にはなりませんでした。
効率の良い学習方法は、ある程度知識があったほうが理解スピードは早くなると思います。しかし、知識がなくても理解はできるレベル感で解説されているのでわかりやすかったです。

## 最後に
今は、`chatGPT`などの生成AIに聞いてみたり、インターネットの海にたくさん情報が無料で転がっているなかで、有料で購入するのは億劫かもしれません。しかし有料だからこそ、得られる情報が**Udemy**にはあると思います。
ぜひ皆様も素敵な**Udemy**ライフをお過ごしください。
最後までご覧いただきありがとうございました。
OpsRamp Logsのアラート設定方法

本記事では、OpsRamp Logsに収集されたログからアラートを発報する方法について説明します。

# 概要
OpsRamp Logsでは、収集したログからアラートを生成する条件を設定することができます。

# 設定方法
Infrastructure > Logs 画面左上のハンバーガーマークのLog Configurationにアクセスし、ALERTINGのページから設定可能です。
![configuration.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/e1218876-e262-f59f-8af9-2159cc34e298.png)

![ALERTING.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/c8bbde57-25ba-5e47-2d00-c647aafb79f3.png)

ADDリンクをクリックすると、設定ページが表示されます。
![Alert-Definition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/9cd47a9a-3002-a255-6d21-0f4502e005cb.png)

各設定項目には、以下意味があります。
- DEFINITION DETAILS: ログ検出条件の設定

|項目|説明|
|:-|:-|
|Name|アラート条件名|
|Filter Query|ログの検出条件|
|GROUP BY|グルーピング条件|
|Query Result|Filter Queryで検出されたログ統計|
- ALERT CONDITIONS: アラート生成条件の設定

|項目|説明|
|:-|:-|
|Alert on no data|データがない場合にアラートを生成するか|
|Alert Severity|生成したアラートのステータス|
|Operator|ログ数のアラート条件|
|Count|Duration内のログ数|
|Duration|ログ検出の時間範囲|
|STATIC THRESHOLD|アラートの追加条件|
|Alert on Heal|アラートの復旧条件|
- NOTIFICATION FORMAT: アラート内容の設定

|項目|説明|
|:-|:-|
|Subject|アラートの件名|
|Description|アラートの説明|

---------------------------------------
[<img width = 250 height = 200 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/111de30a-4d33-aa33-5c7d-83d9015093e6.png">](https://www.vistanet.jp/knowledge-base/)
コマンド忘れがち → GitHub Copilot in the CLI を使ってみよう

「◯◯するコマンド、何だったっけ...」と、たまになりませんか？
この記事では、そういった時に役立ちそうな 「GitHub Copilot in the CLI※」 を使ってみたいと思います。（※2023年11月8日 [パブリックベータ版の提供開始](https://github.blog/changelog/2023-11-08-github-copilot-in-the-cli-now-in-public-beta/)が発表されました）

## GitHub Copilot in the CLI とは
CLI（Command Line Interface）上でコマンド実行を補助するツールです。
現時点、できることは大きく２つです。
- 適切なコマンドを提案してもらう
- コマンドについて説明してもらう

## セットアップ
:::note warn
前提条件
- GitHub アカウントの所有
- GitHub Copilot のサブスクリプションに登録済（有料）
    - 登録は[Githubの設定画面](https://github.com/settings/copilot)から。初登録の場合、30日間無料で使えるようになっています（記事執筆時点）
- GitHub CLI インストール済
    - 未だの場合、インストール手順は [GitHub CLI リポジトリ](https://github.com/cli/cli#installation)を参照してください
:::

1. コマンド操作ツールを開き、GitHub に ログインします
```
gh auth login
```
2. Copilotの拡張機能をインストールします
```
gh extension install github/gh-copilot
```
以上、セットアップ完了です。

## 使い方その① コマンドを提案してもらう

下記を入力すると対話が始まります。
```
gh copilot suggest
```
はじめにコマンドの種類は何なのか質問されます。
```
? What kind of command can I help you with?  [Use arrows to move, type to filter]
> generic shell command //シェルコマンド
  gh command //GitHub CLI コマンド
  git command //Git コマンド
```
`shell command`を選択しました。
すると、何がしたいのか質問されますので回答します。
```
? What would you like the shell command to do?
> フォルダ名がtest-copilotのフォルダを探して、それをデスクトップに移動させたい
```
数秒後、回答がきました。

```
Suggestion:                                                                    
  find ~/ -type d -name "test-copilot" -exec mv {} ~/Desktop/ \;  
  
? Select an option  [Use arrows to move, type to filter]
> Copy command to clipboard //クリップボードにコピー
  Explain command //説明をしてもらう
  Revise command //入力を訂正
  Rate response //遅いと報告
  Exit  //終了
```
あとは、Suggestionが適切かを見て、よければ Copy して Exit します。
※`gh copilot suggest 何かやりたいこと`を入力すると、対話無しで、直接提案をもらうこともできます。

## 使い方その② コマンドについて説明してもらう
下記を入力すると対話が始まります。
```
gh copilot explain
```
以下では、例として `mkdir`の説明をしてもらってみました。
```
? Which command would you like to explain?
> mkdir
```
数秒後に回答がきました。
```
Explanation:                                                                   
  • mkdir is used to create a new directory.                                  
    • There are no flags used in the provided command. 
```
はい、ちゃんと回答してくれているようです。
※`gh copilot explain コマンド名`と入力すると、対話無しで、直接説明をもらうこともできます。

## まとめ
「GitHub Copilot in the CLI」を使って、コマンドの提案や説明をしてもらいました。
シンプルで対話的に進められ、便利なツールだなと思いました。
ただ、最低限のコマンドや頻繁に使うコマンドは覚えておくに越したことはありませんね:rolling_eyes:
Copilot界隈は、より進化していくと思うので今後に期待です。

## 最後に
株式会社HRBrainでは現在メンバー募集中です！:muscle:
カジュアル面談をしていますので先ずは話してみましょう:wave:
採用サイトは[こちら](https://www.hrbrain.co.jp/recruit)です！:runner:
[Capacitor] cap updateした時に[error] Analyzing dependenciesとでた時の対応法

プラグインをアップデートしたあと、それをネイティブプロジェクトに反映させようと `npx cap update` を実行すると、よく以下のエラーが表示されます。

```
[error] Analyzing dependencies
        [!] CocoaPods could not find compatible versions for pod "****":
        In snapshot (Podfile.lock):


        You have either:
        * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
        * changed the constraints of dependency `FBSDKCoreKit` inside your development pod
        `CapacitorCommunityFacebookLogin`.
        You should run `pod update FBSDKCoreKit` to apply changes you've made.

```

よく読むとそのままなのですが、これはCapacitor iOSで利用されているパッケージ管理ライブラリ「CocoaPod」が、「現在グルーバルに保存されている（npmでいうグローバルインストール先）のパッケージとバージョンが違いますよ」とエラーをだしています。~~エラーなんてださずに自動的にアップデートしてくれたらいいのに。~~

エラー文で表示されているように、 `pod repo update` か `pod install --repo-update` をやってあげる必要があります。これは、CocoaPodで管理されているディレクトリに移動する必要があります。これはpackage.jsonのあるレポジトリでしか `npm install` できないのと同じですね。

```
% cd ios/App
% pod repo update
```

これでグローバルに保存されてるパッケージのアップデートを行うことができました。続いて。このプロジェクトのパッケージのアップデートを行いましょう。

```
% pod update
```

これでパッケージのアップデートを行うことができました。念のために通ってることを確認しましょう。

```
% cd ../..
% npx cap update ios
```

まずこれでプラグインの更新が完了します。ちなみにまずないですが、何度かこの手順でもエラーがでたことがあったんですが、その場合 `ios/App/Podfile.lock` （npmでいう、package-lock.json）を削除して再インストールすれば直りましたので参考になれば。

それではまた。
Pythonを使いこなす！

Pythonを使うにあたって，いろいろやったこと＆できたことのメモ
* [Pythonのインストール](#Pythonのインストール)
* 基本構文
* [経路計画](https://qiita.com/Karin-Sugi/items/8e829a02fd54b50af171)：ロボットの移動経路を生成する
* [Open3D](https://qiita.com/Karin-Sugi/items/fa295bf2e14d763d66d0)：3次元画像処理を行う
* [シンボリック計算](https://qiita.com/Karin-Sugi/items/ea452fe633852d974b8d)：連立方程式などをコンピュータに解いてもらう

# Pythonのインストール
1. [Python公式サイト](https://www.python.org/downloads/)から，自分のOSに合ったPythonパッケージをダウンロード
2. ダウンロードしたパッケージを開いてインストール開始

::: note warn
インストーラを起動すると最初に出てくる画面で，一番下に書かれた"Add Python 3.x to PATH" に必ずチェックを入れる．
:::