OmniAICreator/Qiita-1.07M huggingface dataset:
Pythonの仮想環境を使うときが来た: Debian12でsudo pip installが使えない件

## 問題
Debian11から12にアップグレードすると，11にインストールしていたpipを含めたパッケージが使えなくなりました．そこで，パッケージをインストールするためにpipをget-pip.pyから入れようとするとエラーでインストールができません．このエラーは，パッケージをシステムに入れることで起こる諸問題を解消するため，ユーザに仮想環境を使用させるため出現しました．つまり，sudo pip installのようにシステムにパッケージを入れる行儀の悪い行為はせずに仮想環境を構築しなさい，というエラーです．

## 解決法

大人しく仮想環境を使いましょう．まず，仮想環境を使うためのソフトをインストールします．
```
sudo apt install python3-venv
```
次に仮想環境を作ります．
```
python3 -m venv .venv
```
ここでは，.venvは仮想環境の場所です．.venvとしましたが，これは好みで変えて良いです．次に仮想環境を起動します．
```
source .venv/bin/activate
```
起動したらプロンプトの前に.venvが表示されます．表示されたら，次のコマンドで使用するパッケージをインストールします．
```
python3 -m pip install パッケージ
```
作成したプログラムを実行するときは，仮想環境に入ったまま実行します．仮想環境に入らない，もしくは仮想環境から抜けると，仮想環境にインストールしたパッケージは使えなくなります．仮想環境から抜けるには次のコマンドを打ちます．
```
deactivate
```
【Elasticsearch】パパ！ドキュメント（Document）って何？

## 登場人物
かーくん：だいちの息子、リアルはパパと言ってくれない1歳4ヶ月の男の子。
だいち：かーくんのパパ。パパ歴1年4ヶ月、嫁とかーくんをこよなく愛してる。

## 質問は思いつくままに…
ある日、だいちと息子のかーくんはリビングで一緒に過ごしていました。かーくんは最近Elasticsearchについて学び始め、新しい概念について質問を思いつくたびにだいちに聞いていました。

かーくん「ねえ、パパ。Elasticsearchのドキュメントって何？」
だいち「ドキュメントね。それは、Elasticsearchで扱うデータの最小の単位だよ。」

かーくん「それってどういうこと？」
だいち「うーん、例えば、図書館の本を想像してみて。本の中にはたくさんの情報があるよね。それぞれの本がElasticsearchの"ドキュメント"に相当するんだ。」

かーくん「なるほど、でも、そんなにたくさんのドキュメントがあったら、探しているドキュメントを見つけるのは大変じゃない？」
だいち「それがElasticsearchのすごいところなんだ。Elasticsearchは各ドキュメントの内容を解析して、キーワードとその位置を記録しているんだ。だから、特定のキーワードを含むドキュメントをすぐに見つけ出すことができるんだよ。」

かーくん「へえ、それなら大量のデータでもすぐに検索できるんだね！」
だいち「その通り。それに、ドキュメントはJSON形式で保存されるから、様々な種類のデータを扱うことができるんだよ。」

かーくん「JSONって何？」
だいち「JSONは"JavaScript Object Notation"の略で、データを交換するための軽量なフォーマットだよ。人間にとっても機械にとっても読みやすい形式なんだ。」

かーくん「なるほど、だからElasticsearchはデータを効率的に検索できるんだね！」
だいち「その通り！さすが、かーくん。早くも理解が深まってきたね。」

かーくんは満足そうに笑いました。Elasticsearchについての理解が深まり、新しい知識を得ることができたからです。
かーくんはにっこりと笑い、新たに得た知識を消化するためにパソコンに向かいました。
【ChatGPT無】プロンプトの変数のスコープは、どこまで有効？

:::note info
本記事は、ChatGPT（無料版）で
行なっております。GPT4での確認
はできておりません。あしからず。
:::

　どうも、カーブミラーです。

　今回は、
　　「同一チャット内で、
　　　変数を使い回せるのか？」
　　　　です。

　ちょっと、
　　わかりづらいですかね。

　ほかの方のプロンプトで、
　　「{{name}}」みたいな書き方を
　　　見たこと、ありませんか？

　この“name”が変数名です。
　　この変数名に、値を入れて、
　　　プロンプトの指示に
　　　　埋め込むわけです。

　「{{name}}」が
　　プロンプトの中に
　　　あちこちあって、
　　　　最初に
　　　　「name」という変数名に
　　　　　例えば“柴犬太郎”と
　　　　　　代入したとします。

　　　　いないよね、キョロキョロ
　　　　　あっ、柴犬さん！
　　　　　　良かった、メスだ。

　プロンプト内のすべての
　　「{{name}}」が“柴犬太郎”として、
　　　ChatGPTさんに
　　　　伝わるわけです。

　この変数名に入れた値が、
　　今回、私が問題にしている点。

　当然だと思いますが、
　　この変数とその値を、
　　　NewChatした
　　　　別のチャットセッションに
　　　　　持ち込むことは、
　　　　　　できません。

　問題は
　　同一チャットセッション内の
　　　どこまでの範囲で、
　　　　この変数が
　　　　　有効なのか、です。

　そう、
　　変数のスコープです！
　　　globalなのか！　localなのか！

　えっと、まぁ、言いたいことは
　　わかってもらえる、かと……。

　globalとは
　　同一チャットセッション内で、
　localとは
　　プロンプト内。

　ちょっと考えると、
　　globalでも良くない？

　でも
　　localってのも考えられるよねぇ。
***
　だから
　　聞いてみました、
　　　ChatGPTさんに。

　すっごくやり取りしまして、
　　出てきた答えは……

　　　　　　　　　　　local。

　つまり、
　　**変数のスコープは、
　　　ひとつのプロンプト内だけのもの**
　　　　　なのだとか。
***
　これが、globalだったら、
　　入力プロンプトと
　　　作表プロンプトに
　　　　分けて、使えるはず。

　と、目論んでいたわけです。残念。
***
　エディタを閉じようとして、
　　ふと思い出しました。

　人の名前を
　　入力するプロンプトが
　　　あったよな、と。

　変数の保持が
　　できているじゃん！

　ってことは、
　　プロンプトだけのものじゃない！

　NewChatして、
　　ChatGPTさんに
　　　よくよく聞いてみました。

　　そのままのセッションで
　　　尋ねると、ChatGPTさんも
　　　　こんがらがるので。

　私のイメージしていた変数は、
　　「**セッション変数**」
　　　と呼んでいるそうです。

　その説明です。
>私の場合では変数はセッションの範囲内で有効であり、セッションが終了するまで保持されます。つまり、一連の会話の中で変数を使用して情報を保持し、後続の入力においても参照することができます。

　こうも言っています。
>セッション変数は、特定のセッションや会話の文脈に関連する情報を一時的に保持するために使用される変数です。一般的に、セッション変数は特定のセッションの開始から終了までの間だけ有効であり、セッションが終了すると変数の値も破棄されます。

　やはり、だ。

　ふむふむ。
　　これならば、
　　　二分割プロンプトも
　　　　イケるかも。

　よし、構想を練ろう。

　ということで、
　　**変数のスコープは、
　　　ひとつのセッション内だけのもの**
　　　　　だよ、と。決定！
Googleドメイン売却!? 良さげな移行先サービスを比較してみた

2023年6月16日、今朝のIT界隈はこちらのニュースで持ちきりでした。

https://www.itmedia.co.jp/pcuser/articles/2306/16/news083.html

Googleさんが直々に提供している人気のドメインホスティングサービス、Googleドメインが事業売却となるということです。

かくいう私も自分の個人用ドメインをGoogle Domainsでホストし、個人用メールアドレスや技術検証などに活用しているので引っ越しを検討しなければなりません。色々調べてまとめてみました。


# 今回の事業売却の影響は？
Webニュース等でも紹介されているとおり、以下です。
- 現行ユーザーが直ちに対応を行う必要はない
- 2023年後半をめどにSquarespace社へドメインや顧客を移管予定
- 移管完了から少なくとも1年間は現在の価格を尊重

ただし現Squarespaceのサービス価格相場を比較すると、Googleドメインの倍ぐらいの価格設定になってしまうリスクもありそうです。

https://twitter.com/m2wasabi/status/1669508520587464704?s=20


# 他社の主なドメインサービス比較

:::note info
最新の各社公式情報を参照したうえで記載していますが、本記事はあくまで参考とし、できる限りつど最新の情報をご自身でも参照されることをお勧めいたします。もし誤り等あればお知らせくださいますと幸いです。
:::

### お名前.com
https://www.onamae.com/

メリット
- 国内トップシェアのドメインサービス
- 価格が安い

デメリット
- オプションサービスの売り込みがとにかく嫌らしい。これがエンジニアから好かれていない原因ではないでしょうか。オプションサービスの宣伝メール・SMSが多い、契約操作時にとにかくオプションを抱き合わせて契約させようとしつこく誘導するUX、など…。

価格（.com ドメインの例）
- 登録料：0円
- 更新料：1,287円/年〜
- 移管料：1,012円


### Amazon Route 53
https://aws.amazon.com/jp/route53/

メリット
- 世界トップシェアのクラウドAWSのドメインサービス
- SLAが高い（データプレーンは100%)

デメリット
- 価格が高い

価格（.com ドメインの例）
- 登録/更新/移管料：1,820円/年 ※１ドル140円換算
- その他：ホストゾーン利用料＋クエリー従量コストが年間700円〜ほど発生


### Cloudflare Registrar
https://www.cloudflare.com/ja-jp/products/registrar/

メリット
- 近年グローバルで勢いに乗っているエッジ系クラウドサービスが提供
- 後発のためダッシュボードも整理されており使いやすい
- 価格が安い

デメリット
- jpドメイン、co.jpドメインには対応していない

価格（.com ドメインの例）
- 登録/更新/移管料：1,124円/年 ※１ドル140円換算


### さくらのドメイン
https://domain.sakura.ad.jp/

メリット
- 安心の国内ホスティング老舗企業が提供

デメリット
- 価格が高い

価格（.com ドメインの例）
- 登録/更新/移管料：2,614円/年


### ムームードメイン
https://muumuu-domain.com/

メリット
- 低価格なホスティング系サービスで有名な国内ブランドが提供
- 価格がやや安め

デメリット
- 特になし？

価格（.com ドメインの例）
- 登録料：750円
- 移管/更新料：1,728円


# 比較した結果
私はもともとお名前.comの（お上品でない）宣伝攻勢に嫌気がさしてGoogleドメインへ移行したクチなのですが、Squarespace社への移管後はネームバリュー・価格ともにメリットが無くなってしまう可能性があるため移管する可能性が高いです。

私は国内サービスへのこだわりはなく、かつ業務上AWSをよく利用するため勉強もかねてAmazon Route 53、もしくは最近人気のCloudflare社のRegistrarのいずれかへ乗り換えようと思います。価格重視なら迷わず後者ですね！


# おまけ：独自ドメイン用のメールサービス
私はもともと有料でGoogle WorkspacesのGmailを利用していましたが、数年前からZoho Mailを愛用しています。
インドの企業が提供しており、無料で使えてかなり高機能、Google Workspaceのジェネリック版といった印象です。

https://www.zoho.com/jp/mail/

ウェブUIはGmailほどシンプルではないですが、私の場合はWebブラウザーからの利用ではなくMacやiPhoneの標準メールクライアントから利用しているためあまり支障ありません。

※ちなみに少し前にiCloud+が独自ドメインに対応したため乗り換えを試みましたが、実際運用すると機能不足だったためZohoに戻りました。iCloudメールは障害もたびたび発生していますね…。


# 参考になるウェブ記事など

https://blog.ch3cooh.jp/entry/2023/02/24/093000

https://blog.serverworks.co.jp/route53-domain-registration
[HMC Tips] AIX, RHEL(ppc64le) から HMC で LPAR参照コードを出力する方法

#### はじめに

HMC (Hardware Management Console) の参照コードをLPARのOS側からコードを表示させる方法を確認しました。


---
#### 環境

HMC V10R2.1031

LPAR: 
　　AIX 7.3 TL0 SP1
　　RHEL 8.6 (ppc64le)

IBM Power S1014

---
#### 確認 (AIX)

/usr/lib/methods/showled  というコマンドを使用します。

```
# /usr/lib/methods/showled 39321
```

HMCを確認すると、対象LPARの参照コードに "9999" がすぐに表示されました。

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/51601b90-2c70-d9e9-cd9c-f06d110120e9.png)



#### 確認 (RHEL)

9999 を /proc/ppc64/rtas/progress に送ります。


```
echo 9999 > /proc/ppc64/rtas/progress
```

HMCを確認すると、対象LPARの参照コードに "9999" がすぐに表示されました。
こちらは RMC 通信はないLPARでしたが、表示できています。


![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/2f1f035c-79be-8b2e-97a9-04b7d4a214f0.png)






以上です。
【Xcode ショートカットキー】開発を効率的にするコツ【意外と知らない】

# ①【Command + Shift + L】

「Command + Shift + L」をすると

![スクリーンショット 2023-06-16 10.31.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/8da8b69d-7bc1-8f14-8ecd-4386ac86480d.png)

「ライブラリペイン」を開くことができます。

![スクリーンショット 2023-06-16 10.31.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/77886b67-64b4-8430-0b07-569a8d226ea5.png)

# ②【追加したいパーツをCommandキーを押しながら選択】

「追加したいパーツをCommandキーを押しながら選択」すると

![スクリーンショット 2023-06-16 10.35.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/3328efbc-8bbf-2afc-87ff-c85550eb22dd.png)

同時に複数選択することができます。

![スクリーンショット 2023-06-16 10.35.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/47bc8725-a161-78b4-b2cf-5bf08e8fa94d.png)

# ③【対象のパーツを選択してその状態でオプションキーをクリック】

「対象のパーツを選択してその状態でオプションキーをクリック」すると

![スクリーンショット 2023-06-16 10.46.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/222921de-b415-560b-5fdb-2ce8d4ebd623.png)

対象間の距離が数字で表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/b986b6ae-53c7-fec2-01d3-bae707a28d1a.png)

# ④【Ctrl + Shift + 対象パーツ】

「Ctrl + Shift + 対象パーツ」をすると

![スクリーンショット 2023-06-16 10.51.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/d6cf2c64-e08e-29b1-e85f-29a2b64f7155.png)

対象パーツの階層が文字で可視化できるようになります。

![スクリーンショット 2023-06-16 10.51.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/47f199da-f3e9-5722-0fdc-f092f639e6b5.png)

# ⑤【Option + Command + /】

「Option + Command + /」をすると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/2a04f8f2-86b2-5ee5-bf15-9592c35d2c9b.png)

ドキュメントコメントを挿入することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/39e00233-c21e-6292-f8f4-9cff2bc41a6c.png)

# ⑥【Command + Shift + { or }】

「Command + Shift + }」をすると

![スクリーンショット 2023-06-16 11.15.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/247e1cbd-ed28-d999-bf1b-434f15c24e05.png)

右のファイルに移動します。

![スクリーンショット 2023-06-16 11.16.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/7784a201-b8eb-7894-3163-a84a7c73d538.png)

反対に、「Command + Shift + {」をすると

![スクリーンショット 2023-06-16 11.15.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/247e1cbd-ed28-d999-bf1b-434f15c24e05.png)

左のファイルに移動します。

# ⑦【関数の上にコメントアウトを3本線で書く】

関数の上にコメントアウトを3本線で書いた後に
二本指でタップして「Show Quick Help」をタップすると

![スクリーンショット 2023-06-19 15.25.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/0f640f7f-178a-ae65-cb9d-3146244b4743.png)

「Summary」が現れます。

![スクリーンショット 2023-06-19 15.22.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/c3e7af4b-2af5-cf9c-7331-0b146cad1d98.png)
Appleシリコンでseleniumを日本語環境にする

# Laravelにはテスト用につくられたduskという機能があります
* 基本はPHPUnitのwrapperですが、E2Eに特化した機能が盛り込まれています。
* 裏で動くのはphpwebdriverです、つまりchromedriverとかseleniumサーバが必要なわけです。
* 手書きで申し訳ないですが、以下のような構成が一般的かと思います。(local部分は書かないほうがわかりやすかったかも)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585901/45024701-c768-0c09-005b-fd0f9f3751d5.png)

## dusk(一般的なWebDriverを使ったテスト)が動く順序
1. 右上のdocker内php-fpmのコンテナ内でphp artisan duskでテストを動かします。
1. テストコード内で指定したSeleniumサーバに接続します。
1. 同じくテストコード内で指定したブラウザを使うように指示されたもの(Chrome, Firefoxなど)をSeleniumサーバ上で立ち上げます。
    * この図では左上のdockerコンテナ内です。
1. コードからの指示によりSeleniumサーバは立ち上がったブラウザを操作します。
1. 表示された結果を精査(テスト)して、右上のphp-fpmコンテナ内でOK/NGの判断します。

# 難関その1: どのdockerイメージを使えば良いのか
* 昔はJava入れてSeleniumのjarとってきて、chromedriverとってきてVNCとか設定してもしくはxvfbインストールして・・・とかまあ大変でしたけど、今はおれたちのdockerがあるので数分で立ち上がります。(Thanks Docker!)
* Googleでselenium docker imageでググると早速GithubのURLが出てきました
    * https://github.com/SeleniumHQ/docker-selenium
* このままこれを使えば良いのかと思いきや、READMEを読み進めるとこういうことが書いてあります。

```
Experimental Mult-Arch aarch64/armhf/amd64 Images
For experimental docker container images, which run on platforms such as the Mac M1 or Raspberry Pi, see the community driven repository hosted at seleniumhq-community/docker-seleniarm. These images are built for three separate architectures: linux/arm64 (aarch64), linux/arm/v7 (armhf), and linux/amd64.

Furthermore, these experimental container images are published on Seleniarm Docker Hub registry.
```

* つまり、macのm1以降のひとはこのイメージじゃなくて、seleni***arm***をつかってねと。
* ですのでそちらを使うことにします

# 難関その2: 日本語ファイル名問題
* お客様ご要望で日本語ファイル名でダウンロードさせるという機能があるのですが、どうしてもダウンロードファイル名が download になってしまう。これはchromeの仕様でファイル名が正しく認識できないとfallback nameとして download になるそうです。
* テストでダウンロードしたファイル名が想定したものとなってるか調べたいときにこれでは大変困ります・・・。

## 考えられる原因と対処
1. もともとのコードが悪いんじゃないか説
    1. content dispositionのファイル名がよろしくない
        * RFCにじつは規定がちゃんとあって
        * Content-Dispositionが　filename*=utf8''urlエンコードされたファイル名　となっている必要がある
        * その部分がRFC準拠してなかったので準拠してみたが、ダメ
1. つかってるライブラリが影響してる説
    1. 別のライブラリに変更してみたがダメ
1. んんーOSか・・・

# 結局のところロケールです
* ロケールって？
    * https://wiki.archlinux.jp/index.php/%E3%83%AD%E3%82%B1%E3%83%BC%E3%83%AB
* ロケールを日本語にしてあげれば解決するんじゃないか
    * 日本語がブラウザで表示できていたので、てっきりロケールも日本語になっていると思っていたがそうではない


# seleniarmを日本語ロケールにする
* 環境変数だけではどうにもならなかったので、イメージビルドします
```dockerfile
services:
(略)
    selenium-server:
        build: ./selenium
(略)
```
```dockerfile
# あえてlatestにしていませんが、用途に合わせてlatestで良いかと思います
FROM seleniarm/standalone-chromium:114.0
USER root

# set timezeone
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

RUN localedef -i /usr/share/i18n/locales/ja_JP -f UTF-8 /usr/lib/locale/ja_JP.UTF-8 && \
    dpkg-reconfigure --frontend noninteractive locales

ENV LANGUAGE ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LC_ALL ja_JP.UTF-8

RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y chromium-l10n fonts-ipafont
```

これで日本語ファイル名をダウンロードしても日本語ファイル名としてダウンロードできます
S3のオブジェクトをライフサイクルルールを使用して削除してみた

# 背景・目的
以前、大量（小サイズでたくさんのファイル）のオブジェクトを使用して、Glueの検証をしました。
その際に、残ったファイルが複数のバケットで、約2億オブジェクトありました。

こちらを、S3ライフサイクルルールで削除したときのメモになります。

# まとめ
S3にある大量のオブジェクトを削除する際には、ライフサイクルルールが利用することで比較的早く削除が可能です。

# 実践
## 現在の状況を確認
現在の状況は下記のとおりです。

当該アカウント全体のサイズとオブジェクト数は、下記の通りです。
- サイズ：25.5TB 
- オブジェクト：194.6M 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/807c3165-ef09-5f8a-aa30-4d867cdc0dd5.png)

上位2つのバケットで、10TB超が2つあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/e4e9eda9-1cc6-cff1-9968-863391165fad.png)

## ライフサイクルルールを設定
1. S3で、対象のバケットを選択し、①管理タブ＞②ライフサイクルルールを作成するをクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/729338f6-fab9-a404-122a-bfc26a91c329.png)

1. ライフサイクルルールの作成画面で、下記を入力し「ルールの作成」をクリックします。
    - ライフサイクルルール名を任意の名前で設定
    - ルールスコープを選択を「バケット内のすべてのオブジェクトに適用」を選択
    - バケット内のすべてのオブジェクトに適用を選択
    - ライフサイクルールのアクションを選択
        - オブジェクトの現行バージョンを有効切れにする
        - オブジェクトの非現行バージョンを完全に削除
        - 有効期限切れのオブジェクト削除マーカまたは不完全なマルチパートアップロードを削除
    - 下記の日数を1日に設定する
        - オブジェクトの現行バージョンの有効期限が切れる
        - オブジェクトの非現行バージョンを完全に削除
        - 有効期限切れのオブジェクト削除マーカーまたは不完全なマルチパートアップロードを削除
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/e48c8e19-608f-4edf-548c-07c68d68bb96.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/61db66c4-cb47-4d68-911c-45097ac69c5c.png)

1. ルールが作成されました。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/509ff9ba-f6ee-b2ad-326e-8834fbc4fa53.png)

## 設定内容を確認

1. オブジェクトのプロパティーをクリックし、設定したルールを確認します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/f185f51c-203d-e231-627e-ef16fe78c908.png)

1.  オブジェクトのプロパティを選択し、有効期限ルールと有効期限日を確認します
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/81fde57e-737b-61a2-43dc-49d44b12c82e.png)

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/7e7d3dc7-f39d-feff-3d5f-cb27aabc83fc.png)

## 翌日の確認
エビデンスを取り忘れてしまいましたが、翌日、ほとんどのS3データが消えていました。

# 考察
以前は、`s3 rm --recursive` や、 `s3 rb --force`などで削除していましたが、それと比較してあっという間に削除できました。大量かつ、多量なオブジェクトを削除するのにとても効果的と考えます。

# 参考
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/lifecycle-expire-general-considerations.html
【Xcode】Simulatorで画面録画する方法

Xcodeのシミュレータはターミナルを使わずに画面録画することができます。

`⌘(command)+ R` もしくは `⌥(option)`を押しながら`Save Screen`ボタン（右から２つ目のカメラマーク）をクリック
![Screenshot 2023-06-16 10.44.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457154/23421533-d66f-d888-0e2a-9e45b7ba56a4.png)
Save Screenボタンのマークが変われば録画スタートです。
![Screenshot 2023-06-16 10.45.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457154/cb987786-0b91-f942-9aa0-0163fce474f8.png)

同じボタンをもう一度クリックすれば録画がストップされます。
動画は特に指定していなければ、デスクトップに保存されます。
Rails  環境変数の設定方法（dotenv-rails）

こんにちは！
今回はGmailアドレスやパスワードなど、第三者に知られたくない情報をgithubに上げない方法として
dotenv-railsを使用した環境変数変化を学んだので記事にしてみました。

## 環境変数とは
環境変数とはAWSのパスワードや、APIの秘密鍵などGithubにあげたくない機密情報の第三者への漏洩を防ぐためにサーバーなどのOSに保存しアプリに渡す仕組みです。
今回はdotenv-railsというgemを利用して方法を紹介したいと思います。

## 「dotev-rails」とは
環境変数を管理することができるgemになります。
環境変数として管理する事で、下記3つのメリットが生まれます。

１. パスワードや外部のAPIキーの情報を、公に漏洩しない
２. 環境変数として指定した変数はGithubなどにアップロードされない
３. 開発したアプリケーションが開発環境に依存してしまう事を防ぐ

これらのメリットを生み出す為に、「dotenv-rails」を導入するという事になります。

## 導入方法
### dotenv-railsを導入
gemfileの最終行に下記を記述します。

```Gemfile.
gem 'dotenv-rails'
```
追記できましたら、bundle installを実行します。

### .envファイルの作成
環境変数を設定したいアプリのappファイルやconfigファイル、Gemfileなどが置いてあるルートディレクトリに「.env」というファイルを作成してください。

### .envファイルで環境変数の記述
```.env
KEY='１２３４５６' #使用したいキーやパスワードを記述
SECRET_KEY='aaaaaa'
```

記述と保存ができたら、
環境変数ができているか確認します。
ターミナルでrails cを実行します。

```
username:~/environment/アプリ名 $ rails c
```
設定した環境変数の中身を見る場合は、以下のようにENV['KEY']と入力します。
```
3.1.2 :001 > ENV['KEY']
=> "１２３４５６"
```
```
3.1.2 :002 > ENV['SECRET_KEY']
=> "aaaaaa"
```
先程.envファイルの中でKEY、SECRET_KEYに代入した値が表示されていれば、環境変数に値が格納されているという事です。
確認ができましたら、exitでrails consoleを抜けましょう。

### .gitignoreを編集
作成した.envファイルがgithubにアップされないように.gitignoreファイルに記述します
```.gitignore
#下記を追記
/.env
```
これで環境変数をgithubにアップすることなく使用することができます。

.envファイルがGit管理下から除外されたか確認するため下記コマンドを入力します。
```
$ git status
```
実行結果に.envファイルが表示されなければ、.envファイルをGit管理下から除外することに成功しています。
このようにdotenv-railsを利用する場合、.envファイルを作成して環境変数の設定を記述するため、
Git管理下から.envファイルを除外しなければ意味がありません。

### 環境変数の呼出し
```sample.rb
#設定した環境変数の呼び出し
ENV['KEY']
ENV['SECRET_KEY']
```
以上になります！！

## 最後に
最後までご覧いただきありがとうございます。
初学者なので、間違っていることや、分かりづらい箇所もあるかと思います。
何かお気づきがあれば遠慮なくご指摘頂けると幸いです。

ここまで長くなりましたが
最後までお付き合いいただきましてありがとうございました！！
Azure AppServiceで AADSTS9002325 が発生した

## まとめ
- AppServiceにデプロイしたspaで、認証リダイレクト先に以下のエラーが発生
> AADSTS9002325: Proof Key for Code Exchange is required for cross-origin authorization code redemption.
- 対応
    - IDプロバイダーのプラットフォーム構成を**シングルページアプリケーション** -> **Web**に変更

## 発生したエラー・状況
1. Vueでシングルページアプリケーションを作成
2. Azure AppServiceにWebアプリとしてデプロイ
3. AppServiceに対し、認証としてIDプロバイダーを設定
4. 数日後、アプリにアクセスすると認証リダイレクト先で以下のエラー発生

> AADSTS9002325: Proof Key for Code Exchange is required for cross-origin authorization code redemption.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072221/16cdbbaa-748f-40c1-8c18-84e75a4e1238.png)

## 対応
IDプロバイダーのプラットフォーム構成を**シングルページアプリケーション** -> **Web**に変更

### 手順
1. アプリケーションの認証設定からIDプロバイダーにアクセス
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072221/94b93029-d806-a574-923c-82414788fcfd.png)
2. IDプロバイダーの認証設定からリダイレクトURIをコピーし、削除
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072221/72a83d58-7443-3580-62ca-996a57a8f519.png)
3. **プラットフォームの追加**を選択し、構成は**Web**を選択
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072221/9f411fd5-d0ec-4779-456d-94241b95bbfa.png)
4. リダイレクトURIにコピーしたURIを入力し、**構成**を選択
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072221/093a0ddd-8ae8-686b-b231-34788d447725.png)


## 原因
不明…ご存じの方がいたら教えてください

## 参考
- [stackoverflow](https://stackoverflow.com/questions/64692600/aadsts9002325-proof-key-for-code-exchange-is-required-for-cross-origin-authoriz)
- [Microsoft Learn](https://learn.microsoft.com/en-us/answers/questions/1194524/how-to-fix-aadsts9002325-proof-key-for-code-exchan)
- [auth0 community](https://community.auth0.com/t/proof-key-for-code-exchange-is-required-for-cross-origin-authorization-code-redemption/44529)
EC2 Instance Connect Endpoint を試してみた

# EC2 Instance Connect Endpoint とは何か？
AWSのアナウンスを日本語訳したものを置いておきます。
![2023-06-16_103242.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/f1803cb4-9287-f5c7-9615-70810af3176c.jpeg)

# EC2 Instance Connect Endpoint の料金は？
最初の画像にもありますが、無料のようです。
VPCエンドポイントって1時間単位の従量課金だった気がするのでありがたいですね。

# EC2 Instance Connect Endpoint の設定方法
ほいほい Endpoint は作らずにセキュリティグループから作成して準備していきましょう。
クラスメソッドさんの記事が丁寧だったので、作成方法はリンク先を参照ください。
https://dev.classmethod.jp/articles/update-ec2-instance-connect-endpoint/

# EC2 Instance Connect Endpoint の接続画面
接続画面で「EC2 Instance Connect エンドポイントを使用して接続する」を選択し、
末尾の「EC2 Instance Connect エンドポイント」を選択するのみで接続できました。
![2023-06-16_100349.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/b9f5712d-9012-3d9c-d4a8-425dfd19b7c5.jpeg)
![2023-06-16_100233.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/4f535a10-9ae1-08c5-8eaf-6e884cadc955.jpeg)

# 所感
セッションマネージャーで接続する時もなんだかんだエンドポイントを作成したり、都度削除したりそんな事をしていた私からすると非常に簡単で便利でした。
そのエンドポイントも料金が無料なのであれば、今後の接続方法はこのやり方がスタンダードになっていくんじゃないかと感じました。

ただ、いくつかの技術ブログを確認していくと以下の制約があるんじゃないかとの情報がありました。
```
AWSアカウントごとに5 つのEIC エンドポイント
VPCごとに1つのEIC エンドポイント
サブネットごとに1つのEIC エンドポイント
１つのVPCに１つしかEIC エンドポイントを作成できません。
```
VPCに1つという制限下では、早々にはスタンダードにはならないかもしれませんね。。
個人の検証環境などでは存分に力を発揮してくれそうですね。
rubyでmkdirしてみた

rubyでmkdirするには以下の2つのやり方があります。
* Dirクラス
* FileUtilsクラス

# Dir クラス
```
Dir.mkdir("testdir")
```
注意点：
* 同名のディレクトリがあるとエラーになる。
* 事前に同名のディレクトリが存在するかどうかチェックするには以下のコマンドを実行。
```
Dir.mkdir("testdir") unless Dir.exist?("testdir")
```
* Dir クラスの mkdir メソッドでは複数階層のディレクトリを一気に作ることはできない。

Dirクラスは簡単ですが、色々と使い勝手良くないので、次のFileUtilsクラスの方がいいですねー。

# FileUtils クラス
まず冒頭でfileutilsを読み込む必要があります。
```
require "fileutils"
```
良い点は、
* 引数に配列を渡すことで複数のディレクトリを同時に作ることができる。
```
FileUtils.mkdir( [ "testdir1", "testdir2" ] )
```
* mkdir_p メソッドを使うことで複数階層のディレクトリを一気に作ることができる。
```
FileUtils.mkdir_p( "testdir3/testdir4" )
```
Amplify+Nuxt3+Stripeでカード決済機能を構築する

Amplifyを利用して構築したシステムにStripeで決済機能を導入した時のメモです。

# 前提
Amplify+Nuxt3でオンライン決済フォームを構築しました。

![スクリーンショット 2023-06-15 10.34.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1926542/117d7948-1a5f-37e1-f597-ea82e6e31786.png)

AmplifyでAppSync+DynamoDBのバックエンドを構築し、フロントエンドは静的サイトとしてS3にアップロードしています。
DynamoDBの更新にはGraphQLを利用する形で、みてわかる通りサーバレスな構成です。

さて、ここにStripe決済を導入したいと思います。
今回の要件は以下の通り。

* nuxt3で作成したフォームに必要情報を入力したら、Stripeの支払いページに飛ぶ
* 決済が完了したら、nuxt3の指定したページにリダイレクトさせ、DynamoDBに支払いが完了したことを登録する


# 【案1】Stripe決済画面へのリンクを画面に貼る方法
一番簡単なのはStripeから提供されている決済ページへのリンクを貼る方法です。

https://stripe.com/docs/no-code/payment-links

ただし、この方法だと決済が完了した後、自身のサイトにリダイレクトされずに終わってしまいます。

# 【案2】Stripe Checkout+Lambdaを利用
Stripe Checkoutを利用すると以下の手順で決済後、Webhook呼び出しができます。

1. nuxt3の画面からStripe決済画面へ飛ぶ
1. Stripe画面で決済処理をリクエスト後、決済完了ページに飛ばす
1. Stripeにて決済完了後Webhook呼び出しが行われ、非同期でlambdaにてDynamoDB更新処理を実行

Stripe決済画面へのリンクはStripeの商品ページから作成可能です。

https://stripe.com/docs/payments/accept-a-payment?integration=checkout

また最初のページからStripe決済画面に渡すsession情報内のclien_reference_idに顧客を識別する情報を渡すことでLambdaで処理する際に対象顧客を識別することができます。
これについてはStripeのAPIドキュメントを参照のこと。

https://stripe.com/docs/api/checkout/sessions/object#checkout_session_object-client_reference_id

この案の場合、決済完了後の処理を行うためのLambda関数を一つ作成してやる必要があります。
それに伴いAPIGatewayを作成し、LambdaにAppSyncへのリクエスト処理を書いて・・・と結構手間になります。

AWSがLambdaからAppSyncを叩くためのコードの書き方を紹介してくれています。
これを利用することで怖いくらいサクッとDynamoDBを更新する処理を書くことができました。
エラーが全く起こらず動いたので、不安になったくらい・・・。

https://docs.amplify.aws/guides/functions/graphql-from-lambda/q/platform/js/#create-from-scratch

ただし、node-fetchモジュールが必要で、node-fetchがCommonJSに対応していないためにrequireをimportに書き換えるあたりで手間取りました。

# まとめ
今回は要件をもとに【案2】で実装しました。

決済後の処理などがない場合は支払いリンクを利用する方が圧倒的に簡単です。
決済後の処理があったり、決済完了画面を独自に用意したい場合は色々と手間がかかりそうです。
ReactでsetStateが即座に反映されない問題を解消する

# はじめに

普段はBEをメインで開発している筆者がReactのstateの仕様を知らずに2日を溶かしたため

この記事を公開します。

# TL;DR

useStateで定義したset関数をコールしても即座にはstateに反映されない。

更新されるタイミングは再レンダリングされたあとに反映される。

set関数をコールした直後にstateを使う場合はuseEffectを使うと値を得られる。

# やりたかったこと

タイトルの通りにstateが更新されたら別の関数で新しいstateを用いて処理を行ないたい。

今回はinputに入力されたタイミングでコンソールに出力されるようなプログラムを書いてみます。

## NGパターン

set関数をコールした後にstateを直接参照するパターンを考えてみます。

```tsx
import React, { useState } from 'react'

const Sample: React.FC = () => {
  const [searchText, setSearchText] = useState<string>('')

  const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearchText(e.target.value)
    console.log(searchText)
  }

  return (
    <div>
      <input
        type="text"
        value={searchText}
        onChange={handleOnChange}
      />
    </div>
  )
}
```

このように書くと入力した瞬間には「最後に入力された文字が出力されない」という問題があります。

この原因はReactのuseStateで定義したstateは**レンダリングされた後に値を更新する**という仕様になっています。

では反映されたstateを見るためにはどうしたら良いでしょうか？

## Goodパターン

```tsx
import React, { useEffect, useState } from 'react'

const Sample: React.FC = () => {
  const [searchText, setSearchText] = useState<string>('')

  const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearchText(e.target.value)
  }

  useEffect(() => {
    console.log(searchText)
  }, [searchText])

  return (
    <div>
      <input
        type="text"
        value={searchText}
        onChange={handleOnChange}
      />
    </div>
  )
}
```

このようにuseEffectの依存配列にstateを指定し、レンダリング後にstateを参照すると更新後の値が得られます。
初心者でも大丈夫！OSSプロジェクトへの具体的なコントリビュートガイド

# はじめに

OSSに初コントリビュートをした感想と簡単な流れについて記述する。

---
# Agenda

- OSSとは
- OSSコントリビュートとは
- 具体的に何やったん？
- 実際にコントリビュートしたものたち
- 感想
- 最後に

---

# OSSとは

オープンソースソフトウェアのこと

ソースコードの改変、再配布を自由に行なって良いもの

PHP, Java, Rubyなど超有名プログラミング言語もOSS

---

# OSSコントリビュートとは

文字通りにOSSの開発の手助けをすること

例えば

- バグの修正
- 新機能の追加
- ソースコードのリファクタリング
- ドキュメントの修正（Typo、翻訳）

---

# 具体的に何やったん？

色々頑張ったけど要約すると以下が効果あった

- やり方をググる
- コントリビュートできるまとめページをdigった
- すぐにリポジトリをforkして変更作業着手

---

## やり方をググる

**OSS コミット やり方** で検索してみた

- コントリビュートできそうなOSSを探す = issueを報告しているOSSを探す
  - [good first issue](https://goodfirstissue.dev/)
  - [Github Help Wanted](http://github-help-wanted.com/)
  - [GitHub](https://github.com/)

---

## good first issue とは
GitHubのissueのラベルのうち `good first issue` が含まれるものをまとめてくれているページ

*good first issueは`初めてのコントリビュートに向いている Issue につけられる`ラベル

---

## issueの選び方
もちろん何でもコントリビュートできる訳ではない
ケイパや興味で選ぶ必要がある

僕の属性
- 得意なのはGo, TypeScript, DevOps(GitHub Actions)
- 興味があるのはテスト、スクレイピング、ORM、HTTPフレームワーク

---

## 変更作業
私がやった流れは以下

1. 良さげなissueに対して`Can I take this?`と投稿する
1. コントリビュートのルールを確認する (Readmeを読む)
1. 間髪を入れずリポジトリをfork（自分のアカウント配下にコピー）する
1. ブランチを切って変更作業をする
1. リモートリポジトリにpushしてコントリビュート先にプルリクエストを出す

---

# コントリビュートしたものたち

---

## Goのテストコードの修正
https://github.com/MontFerret/ferret/pull/781
https://github.com/gavv/httpexpect/pull/347

テストコードの軽微な修正

---

## GitHub Actions Warningの修正
https://github.com/fairhive-labs/go-pixelart/pull/16

実は10月にプロジェクトで行なった作業と全く同じ

---
## 不要な引数の削除
https://github.com/apache/camel-k/pull/4155

未使用の関数の引数を削除するだけ
なんとapacheのリポジトリにコントリビュート

---

# 感想
- Thank you というコメントが嬉しい
- 初めてで緊張したが楽しかった
- Thank you というコメントが嬉しい
- 会ったことない人とものつくりできるの楽しい
- Thank you というコメントが嬉しい

---

# 最後に
知らない人に自分のやったことを認めてもらうのは嬉しい
やろうぜOSSコントリビュート
「Git コミット 取り消す」でググった方へ

## TL;DR

以下の3つが使える

```sh
git revert HEAD

git reset --hard HEAD^

git rebase -i
# 削除対象のコミットをpickからdに変更する
```

revertは取り消したいコミットを打ち消すコミットを作るのに対して
reset/rebaseはコミット自体を削除する。

**reset/rebaseを実行する前には必ずテスト用のブランチで試してから本番ブランチで行いましょう。**

---

## ざっと復習とお約束

Gitとは Version Controll System の一つでソースコードのバージョニングに使用されるサービスである。

本記事では個人的な趣味から「歴史を作る」という表現をします。

また対象のコミットは今回は簡略化のために一つ前のコミットとします。（実際一つ前のコミットを打ち消したいケースが多いと思うのでこれを丸暗記するだけでも一部対応可能）

---

## 利用シーンの想定

例えば以下ケース

- チームでGitを管理しているとブランチが複数存在し、本来入れたくないコミットを入れ込んでしまった
- DBの情報、APIキーなどシークレットをソースコードに含めてコミットしてしまった
- ~~恥ずかしいポエムをソースコードに入れっぱなしにしてコミットしてしまった~~

いざという時のために使い方をなんとなく把握しておきましょう

---

## revert

gitには以下で定義されている

`Revert some existing commits`

一つ前のコミットを打ち消す場合は以下のコマンド

```
git revert HEAD
```

コミットメッセージを編集する画面に遷移するので保存して終了。

**編集を取り消したいコミットを打ち消すコミットを作成するため、もともとHEADであったコミットはコミットは残ったままになることに注意**

黒歴史もよい思い出という場合に使いましょう

---

## reset

gitには以下で定義されている

`Reset current HEAD to the specified state`

一つ前のコミットを打ち消す場合は以下のコマンド

```
git reset --soft HEAD^
```

コマンドを実行すると一つ前のコミット内容がstageに現れ、打ち消したいコミットがlogから消える

黒歴史は完全に排除したいという場合に使いましょう

---

## rebase

gitには以下で定義されている

`Reapply commits on top of another base tip`

（なるほど、わからん）

一つ前のコミットを打ち消す場合は以下の操作

```
git rebase -i
```

を実行すると

```
pick ${commit hash} ${commit message}
pick ${commit hash} ${commit message}
pick ${commit hash} ${commit message}
pick ${commit hash} ${commit message}
pick ${commit hash} ${commit message}
```

ここで削除したいコミットをエディタで行を `pick` から `d` に変更することでコミットの削除が可能

---

## 結局どれを使うか

個人的には以下のパターンを推奨

- コミットを残して良い => revert
- コミットを残したくない => reset

(rebaseはムズイからしっかりと練習してから使いましょう)
【React】Reactでアプリを作りデプロイするために必要な最小限のこと





こちらに移動しました。

https://note.alhinc.jp/n/n23f7d406b489

# 移動先について
本記事は、現在(2023/12/23)私の所属する[ALH株式会社](https://www.alhinc.jp/)が公開している、[こちら](https://note.alhinc.jp/all)のnote記事に移行することになりました。

ストックされている方は大変お手数ですが、上記リンクから参照ください。
Linode Regions API を使って場所とリージョンを取得する (Akamai)

# Linode Regions API
Linode API や Linode CLI や Terraform を使ってインスタンスを作成するときに、リージョンを指定します。例えば、Tokyo にインスタンスを作成したいときは、``ap-northeast`` を指定する必要があります。

Community でも次のような質問と回答があります。

https://www.linode.com/community/questions/23622/datacenter-locations-mapping-id-and-name

今後、利用できるリージョンも増えてきますので、そのときに最新の情報が取れるようにするのがこの記事の目的です。公開されている Regions API を使えば必要な情報は得られます。

https://www.linode.com/docs/api/regions/

以下は簡単に表示する例です。label と id をマッピングしています。2023年6月1日時点で 11 個のリージョンが見えます。

```
curl -s https://api.linode.com/v4/regions | jq -r '.data[] | .result = (.label) + ": " + .id | .result'
```
```
Mumbai, IN: ap-west
Toronto, CA: ca-central
Sydney, AU: ap-southeast
Dallas, TX: us-central
Fremont, CA: us-west
Atlanta, GA: us-southeast
Newark, NJ: us-east
London, UK: eu-west
Singapore, SG: ap-south
Frankfurt, DE: eu-central
Tokyo, JP: ap-northeast
```

以下は、配列形式で表示した例です。
```
curl -s https://api.linode.com/v4/regions | jq -r '.data | map({label: .label, id: .id})'
```

```json
[
  {
    "label": "Mumbai, IN",
    "id": "ap-west"
  },
  {
    "label": "Toronto, CA",
    "id": "ca-central"
  },
  {
    "label": "Sydney, AU",
    "id": "ap-southeast"
  },
  {
    "label": "Dallas, TX",
    "id": "us-central"
  },
  {
    "label": "Fremont, CA",
    "id": "us-west"
  },
  {
    "label": "Atlanta, GA",
    "id": "us-southeast"
  },
  {
    "label": "Newark, NJ",
    "id": "us-east"
  },
  {
    "label": "London, UK",
    "id": "eu-west"
  },
  {
    "label": "Singapore, SG",
    "id": "ap-south"
  },
  {
    "label": "Frankfurt, DE",
    "id": "eu-central"
  },
  {
    "label": "Tokyo, JP",
    "id": "ap-northeast"
  }
]
```

# Green Light プログラム
2023年6月1日時点で Washington DC が一部のお客様に公開されていますが、API 上ではまだ表示されていません。なお、新しいデータセンターをいち早く使ってみたい場合は Linode Green Light にご参加ください。

https://www.linode.com/green-light/

Regions API はトークンなしでも使えますが、以下のように Green Light に参加したお客様がトークンを使えば Washington DC の情報も得られます。
```
curl -s https://api.linode.com/v4/regions --header 'Authorization: Bearer YOUR_TOKEN' | jq -r '.data[] | .result = (.label) + ": " + .id | .result'
Mumbai, IN: ap-west
Toronto, CA: ca-central
Sydney, AU: ap-southeast
Washington, DC: us-iad
Paris, FR: fr-par
Dallas, TX: us-central
Fremont, CA: us-west
Atlanta, GA: us-southeast
Newark, NJ: us-east
London, UK: eu-west
Singapore, SG: ap-south
Frankfurt, DE: eu-central
Tokyo, JP: ap-northeast
```
# Linode CLI を使う
実は、Linode CLI を使えば、場所とリージョン名の関係が簡単にわかります。linode-cli コマンドもご活用ください。
```
linode-cli regions list
```
![linode-cli-regions-list.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264188/3b6d633b-c9bf-1367-277a-a61b2a473ea9.jpeg)

Linode CLI のインストールについては下記の記事を参考にしてください。

https://qiita.com/isss802/items/0b1be79031ee16ced521

# まとめ
Linode Regions API を使うとリージョン名を取得できます。そのリージョン名は Linode API や Linode CLI でインスタンスを新規作成するときに指定します。Akamai は今後新規データセンターを拡張する予定ですが、Linode Green Light プログラムに参加すれば、いち早く新しいリージョンを試すことができます。
【Git】permission denied (publickey)

久々permission deniedのエラーに出くわしたので、解決法をまとめました。

## エラーの原因

sshによるgithubの認証が失敗している。
pushする際やcloneしてくる際にエラーが起こる。

以下二つが原因として考えられる。
1. ローカルPCのファイルにsshキーが生成されていない。
2. sshキーがgithubに登録されていない。

## 解決方法

### 1. SSH Keyをローカルで生成する

以下のコマンドでディレクトリを変更
```php
cd ~/.ssh
```

以下のコマンドを実行し、ssh keyを生成
```php
ssh-keygen
```

以下のようにいくつか回答を求められると思いますが、全てEnterを押して進む。
(Enterを押したらデフォルトの設定が適用されます。)
```php
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/〇〇/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
```

現在いる.sshディレクトリでcatコマンドを実行し、生成されたSSH keyを確認する
catを実行して表示されたSSH keyは次のステップで使用するのでコピーしておいてください。

```php
% cat id_rsa.pub
```

### 2. ローカルで生成したSSH keyをgithubに登録する

githubの設定画面にある**SSH and GPG keys**をクリックしてください。
![de73f7bbc8cae88e1bde194d1c2dded2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470041/fd56a0d8-891d-2c38-b6b4-6f93d26304b9.png)


進むと以下の画面が出てくるので[**new SSH key**]ボタンをクリックして進んでください。
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470041/8a8acb09-dd2e-8753-2f12-e806ea31395c.png)


以下の画面が出てくるので、title、keyの部分を埋めます。
titileは任意の名前でkeyにはコピーしたSSH keyをペーストしてください。
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470041/6eb11152-dcec-e26d-860b-9eeaef854e9c.png)


## 参考

[Fix – git@github.com : permission denied (publickey). fatal could not read from remote repository | DevelopersIO](https://dev.classmethod.jp/articles/fix-gitgithub-com-permission-denied-publickey-fatal-could-not-read-from-remote-repository/)
Github Actionsで過去のコミットを参照しようとしたらunknown revision or path not in the working tree と言われたときの解決法

# TL;DR

actions/checkout@v3 はデフォルトでheadのみ設定になるため
過去のコミットを全て取得する場合はwithで `fetch-depth: 0` とする必要がある。

```yaml
~
jobs:
  codedeploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          fetch-depth: 0 # ここを追加してあげる
```
リポジトリにきちんと説明されている
参考
https://github.com/actions/checkout#fetch-all-history-for-all-tags-and-branches

# 背景

Github Actionsでソースコードのビルド（今回はトランスパイル）とオートデプロイを別ワークフローで管理するように構築していたため、

最新のコミットが最後にプッシュされたコミットと比較したときに、特定の拡張子のファイル（例えば.vue, .scssなど）が変更されているかを判定する必要があった。

# エラーが出る実装

```yaml
~
jobs:
  codedeploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: get build required files
        id: get-build-required-files
        run: |
          BaseHash=`git merge-base HEAD HEAD^`
```

[actions/checkout](https://github.com/actions/checkout) でブランチチェックアウトをして
`git merge-base`コマンドで過去のコミットハッシュを取得したかった。

が `unknown revision or path not in the working tree` というエラーが発生して上手くいかず。。。

# 原因と解決方法

actions/checkout@v3の設定には `fetch-depth` があり、デフォルトでは 1 に設定されている。
上記によりデフォルトではheadのみfetchするようになるため、すべてのコミットを取得するために`fetch-depth = 0` とすると良い。

# 上手くいった実装

```yaml
~
jobs:
  codedeploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: see past commit
        run: |
          BaseHash=`git merge-base HEAD HEAD^`
          ~
```

# 最後に
ローカルで同一の `git merge-base HEAD HEAD^` を実行してもエラーが出なかったため原因突き止めるまでに時間がかかった。
使用するライブラリのReadmeを早めに読んでおくべきでした。
「WebUSBでFeliCaのIDmとMIFAREのIDも読み込む」を、RC-S300に対応させたよ

## 前話
RC-S300が発売されて1年半経ちました。
まだまだ現場で現役だと思われる、RC-S380は/P（個人向け）は生産終了。
/S（業務用）は生産終了予定となっています。

以前、下の記事で、WebUSBでMIFAREを読みたいという記事を書きましたが、
もちろん当時はS380が現役S300は未発表だったため、S380のみの対応になっています。

https://qiita.com/MarioninC/items/97b82e8eeb3f626a5875

S300は発売日当日に、手に入れたのですが、
パケットの仕様が全く異なるので、様子見というか断念。対応をお蔵入りしていました。

## 今回のお話
今回カードリーダを買い足そうとしたら、生産終了を知り、S300のWebUSBネタを再捜索していたところ、
以下の記事を見つけました。

https://sakura-system.com/?p=2892

大変参考にしながら元のS380とMIFAREに対応したものにくっつけてアップデートを行いました。
MIFARE対応の記事やネタは見当たらなかったので、またまた自力でパケット見たりしながら書きました。
思っていたより簡単で拍子抜けでしたが、これで動作していそうです。
``` js
// リクエストヘッダーは省略
// TypeAのプロトコルに切り替え
[0xff, 0x50, 0x00, 0x02, 0x04, 0x8f, 0x02, 0x00, 0x03, 0x00]
// IDを取得
[0xff, 0xCA, 0x00, 0x00]
```

検証中に発生した事項ですが、動作したままほっておくと、
なぜかカードを検出しなくなることがあるようで原因不明です。
知っている人いたらコメントください。

## アップデート内容
* RC-S300に対応
* RC-S300でのMIFAREのUID読み取りにも対応
* ペアリング済みのリーダーがある場合、ダイアログを出さないように変更
* ほか細かいコード修正
## 技術的メモ
* RC-S380と、RC-S300は全くの別物。APIも違うので注意
* AndroidとRC-S300の組み合わせでは、バッファーINが分割で受け取れない、１回で受け取る必要あり。
* RC-S300はポーリング中LEDが点滅し続けるので、改札みたいに常に待ち受けるようなシステムを検討す場合は、LEDを隠した方がいい（別の機器を検討）
## 対応状態
| 機種 | カード |
| --- | ------ |
| RC-S380(S) | FeliCa MIFARE |
| RC-S300(S) | FeliCa MIFARE | 

## 検証済み機器
* Windows 10 Chrome 114.0.5735.199
* Android 10 801SO Chrome 114.0.5735.196

## ソースコード
https://github.com/marioninc/webusb-felica

## 参考情報
RC-S300の対応については、
https://sakura-system.com/?p=2892 の記事と記事中で公開しているライブラリを参考に修正しました。
カード内の情報の読み書きをしたい方、詳細の話は参考元の記事にしっかりと解説がありますので是非そちらをご覧ください。

さらに深みに行きたい方は、FeliCaの技術情報やJIS、ISOの規格を読むとカードとリーダーの通信方法など細かく書いてあります。

https://www.sony.co.jp/Products/felica/business/tech-support/

大規模に開発を検討している方、ちゃんとしたライブラリが欲しい方は、SONY公式に有料のものがあります。
開発試験用途なら無料です。（ライセンスの詳細は公式を見てください）

https://www.sony.co.jp/Products/felica/business/products/sdk/ICS-DCWC1.html

## ほか参考にした記事
https://www.hmcircuit.jp/nfc/rcs620_usbserial.html#f

https://blog.hirokuma.work/2011/08/felicacommunicatethruex.html

## 感想・あとがき
今回もパケット読んだり、数年前を思い出したり面白かったです。
リトルエンディアンってなんでこんなめんどいんでしょう。

技術的な話は今回あまりないので、記事が薄いですね。
追加してほしい情報や、間違っていることがあればコメントいただければと思います。
Advent Calender で社内布教に失敗したので Engineer Festa でリベンジする

## TL;DR 

- Organization として参加１年目のAdvent Calender 2022 では社内布教に失敗した。
- それから半年間、Engineer Festa 2023 に向けての社内布教を色々やってみた。
- それらの試みの結果や、考察のようなものはEngineer Festa 2023 終盤にまとめる予定。


## Advent Calender 2022では社内布教に失敗した
Organization（会社）として初めて参加したAdvent Calender 2022では、参加者4名、参加率としても1桁台でイマイチ盛り上がらず。

- [布教を目指す記事](https://qiita.com/oishi-d/items/77cf492396f073d2263e)
- [振り返り記事](https://qiita.com/oishi-d/items/388a7dc8f7692672a779)

そもそもとして、Advent Calenderのタイミングで社内布教を開始したので、それ以前の布教活動が足りず社内認知度が不足していた感ありあり。
その点を中心に、半年間とEngineer Festa 2023 前にやった施策などを記載します。

## 半年間でやってきたこと
### Qiitaとは何か？の解説ページを作成

社内でQiita他、エンジニアコミュニティという存在の認知がされていないため、まずはその解説を社内ポータルであるGrowiに作成。
目次としては以下のような感じ。

- Qiitaとは？
- こんな人におススメ
  - ~~ぶっちゃけお金ほしい人・転職考えている人向けとか明け透けなことも書いてみたり。~~
- 参加・閲覧・執筆のススメ
  - まずはアカウント作って、人の記事見て、いいねとかつけよう！とか。
  - 執筆する人はガイドライン見てね、とか。
- QA
  - 会社としての建付けは？とか。
- イベント参加履歴
  - Advent Calender などの履歴



### 周知方法の改善

社内のチャットツールとしてMattermostを利用していて、Advent Calender 以前は技術以外のetc的なチャンネルにRSSを連携したり、イベントの周知をしていたのですが、技術総合というチャンネルに独立して周知するように変更。
全社員強制参加のチャンネルとして新設したことや、クラウド・OS・ネットワーク・セキュリティなどのカテゴリで別れていた技術系のチャンネルにはまらない話題（直近だとChatGPTとか）を話せる場所として活用され、結果としてQiitaの認知度も上がった模様。



### 参加してくれそうな人へのダイレクトマーケティング
どんな組織にもやる気勢という人は存在すると思います。
そういう人は物足らなくて勉強会を設立したりするので、そこに参加してダイレクトマーケティングしました。




## イベントに向けて

### Qiita Organization ページの整理

[Qiita Organizationの概要](https://qiita.com/organizations/classact/profile) の作成を営業に片手間でお願いしてしまったり、Googleアナリティクスを設定していなかったり、ずさんなまま放置していました。
それをちゃんと書き直し、アナリティクスを設定し、全社的な活動であることをアピールしました。
~~というか社長に半強制的に概要のレビューやアナリティクスの設定をしてもらいました~~


### 記事のネタ一覧の共有

Qiitaの参加者そのものは増えていないものの、Qiitaで活動している人に刺激を受けて、Output文化に興味を持ちつつも「インターネット上に公開するのはちょっと…」みたいな人が増えたのか、社内ポータルのGrowiで技術情報を共有する人がちらほら登場しました。
ですが、１企業とインターネットでは分母が違うため、勇気を振り絞って公開した技術情報が「あまり見られないな…やめようかな…」とならないように誘導を試みます。

そこで、社内ポータルに外部受けしそうで、かつ執筆工数がかからなそうなネタ一覧を投稿する場所を作成して、そこにネタを投稿してみました。
中には８割ぐらい書いたけど公開してない下書き記事も置いておいたので、誰かが襷をもらってくれることを期待したい。

## 結果は？
現状大きな成果は上がってないので、社内における Engineer Festa 2023の盛り上がりを踏まえて、イベント終盤に記事を書こうと思います。
AWS CLIのプロファイルで複数アカウントを使い分けよう！

色んなAWSアカウントや複数のPCを使い分けていると、AWS CLI操作をするたびに「えっと…どのAWSアカウント向けに設定してたっけ？」ってなっちゃうので、自分用の備忘をかねてまとめました。


# 環境前提
- M1以降のMac
- ターミナルはzshを利用


# 現状確認
- そもそもこのPC、AWS CLI入ってたっけ？

```zsh:ターミナル
aws --version
```

- 今このPCに登録されているIAMアクセスキーの一覧は？

```zsh:ターミナル
cat ~/.aws/credentials
```

- 今このPCはどのプロファイルを向いている？

```zsh:ターミナル
aws configure list
```

- 現在のプロファイルへ試しに実行しやすい無難なコマンド

```zsh:ターミナル
aws s3 ls
```

※当該アカウントのS3バケット一覧を表示してくれます。


# AWS CLIのインストール
入ってなかったら入れましょう。

- GUIインストーラー（Mac用）

https://awscli.amazonaws.com/AWSCLIV2.pkg

※「すべてのユーザー用」にインストールするとパス設定が不要になるので楽です。

- インストールされたことの確認

```zsh:ターミナル
aws --version
```


# AWS CLIの構成ファイルは2つ！

ホームディレクトリ配下の隠しディレクトリ `~/.aws` に以下の2ファイルがあります。

### credentials（認証情報ファイル）
ログインに用いるIAMユーザーのアクセスキー情報を記載します。
複数のIAMユーザー情報を列挙して切り替えることができます。これらをプロファイルと言います。

```ini:~/.aws/credentials
[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

[project1-dev]
aws_access_key_id=AKIAI44QH8DHBEXAMPLE
aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY

[project1-prd]
aws_access_key_id=AKIAI44QA8DHBEXAMPLE
aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8avbEXAMPLEKEY
```


### config（設定ファイル）
前述のcredentialsファイルで定義した各プロファイルについて、デフォルトで利用するAWSリージョンなどを定義できるファイルです。

```ini:~/.aws/config
[default]
region=ap-northeast-1

[profile project1-dev]
region=ap-northeast-3

[profile project1-prd]
region=ap-northeast-3
```


# プロファイル切り替え方法
AWS CLI実行時に利用されるプロファイルは、Macの環境変数 `AWS_PROFILE` で指定できます。

- 現在このPCで有効なプロファイルを確認する

```zsh:ターミナル
echo $AWS_PROFILE
```

※出力なしの場合はデフォルトプロファイルが利用ます。

- 環境変数のセット

```zsh:ターミナル
export AWS_PROFILE=project1-dev
```

Mac（UNIX系のOS）では環境変数はターミナルを閉じるたびにクリアされてしまうので、ターミナル再起動後は環境変数のセットを忘れない様にしましょう。


# 注意点
今回紹介した認証方法は「Long-term credentials」と呼ばれますが、長期の認証情報が特定のデバイス内に残ってしまうことからセキュリティリスクの観点で非推奨とされています。

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-authentication-user.html

可能なかぎりアクセスキーの発行は避け、ユースケースに応じた別の手段を用いて目的達成するようにしましょう。
また、やむなく発行したアクセスキーは定期的にローテーションしてセキュリティリスクを最小化しましょう。


# 参考文献

- AWS CLIユーザーガイド

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-welcome.html

- AWS CLIのプロファイル切り替えをいい感じにする（@crossroad0201 さま）

https://qiita.com/crossroad0201/items/f84b3e2fece41750755b
【Laravel】PHPStan実行時にpivot関連のエラーが出た際の対処法

多対多のリレーションが行われている際に、中間テーブルからなんらかのデータを取得したいときに使用するpivotメソッドがPHPStanの実行時にエラーが出てしまう。

### エラー文

phpstan実行時にこの場合だと以下のエラーが発生します。

```php
// コード
foreach ($user->roles as $role) {
    echo $role->pivot->created_at;
}

// エラー文
Access to an undefined property App\Models\User::$pivot.
```

## 原因

簡単にいうとPHPStanは静的解析ツールであり、LaravelのEloquentが提供しているpivotのような動的なプロパティについて認識することができないため。

## 対処法
次に紹介する1 or 2で解決できると思います。

### 1. getRelationValue()を使用する

```php
foreach ($user->roles as $role) {
    echo $role->getRelationValue('pivot')->created_at;
}
```

getRelationValueはmodelクラスがtraitで読み込んでいる
**Illuminate\Database\Eloquent\Concerns\HasAttribute.php**に以下のように定義されています。

静的メソッドになるので、PHPStanでエラーになりません。

```php
/**
* Get a relationship.
*
* @param  string  $key
* @return mixed
*/
public function getRelationValue($key)
{
    // If the key already exists in the relationships array, it just means the
    // relationship has already been loaded, so we'll just return it out of
    // here because there is no need to query within the relations twice.
    if ($this->relationLoaded($key)) {
        return $this->relations[$key];
    }

    if (! $this->isRelation($key)) {
        return;
    }

    if ($this->preventsLazyLoading) {
        $this->handleLazyLoadingViolation($key);
    }

    // If the "attribute" exists as a method on the model, we will just assume
    // it is a relationship and will load and return results from the query
    // and hydrate the relationship's value on the "relationships" array.
    return $this->getRelationshipFromMethod($key);
}
```

### 2. phpstan.neonにpivotのエラーに関するignore設定を追記する

```php
includes:
    - ./vendor/nunomaduro/larastan/extension.neon

parameters:
    paths:
        - app

    # The level 9 is the highest level
    level: 6

    # 以下追記
    # pivot関連のエラーをignore設定する
    ignoreErrors:
        - '#^Access to an undefined property .*::\$pivot\.$#'
```


もっと良い対処法があれば追記するので教えてください！
マージン論理プロパティのすゝめ

## 概要
みなさんが使っているCSSのマージンプロパティですが、論理プロパティを使えばより効率よくスタイリングできます。
本記事では、いくつかのユースケースを紹介していきます。

なおユースケースに焦点を当てますので、論理プロパティについては詳しく言及しません。
以下のドキュメントを参照してください。

https://developer.mozilla.org/ja/docs/Web/CSS/CSS_logical_properties_and_values

## 中央寄せにするとき
使用するのは`margin-inline`です。インライン方向に余白を指定できます。
`margin-left: auto; margin-right: auto;`と同様の効果があります。

```html
<style>
.box {
  width: 200px;
  height: 200px;
  background: lightblue;
  margin-inline: auto;
}
</style>

<div class="box"></div>
```
![スクリーンショット 2023-06-13 8.39.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882125/8a04a9ec-0f31-681b-deed-57f1a7a406ff.png)

## アバターとテキストを組み合わせるとき
使用するのは`margin-inline-end`です。
アバター画像とテキストが並んでいる状態で、画像横に余白をつけます。
```html
<style>  
  img {
    width: 46px;
    height: 46px;
    object-fit: cover;
    border-radius: 23px;
  }
  .wrapper {
    display: flex;
    align-items: center;
  }
  .avatar {
    margin-inline-end: 1rem;
  }
</style>

<div class="wrapper">
  <img class="avatar" src="https://source.unsplash.com/random" alt="">
  <p>Your Name</p>
</div>
```
![スクリーンショット 2023-06-13 16.35.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882125/1cadbff8-ce63-5db0-8efc-a2c3e7e40f86.png)

これを右から左のレイアウトへ変更します。
```html
...
<div dir="rtl">
  <div class="wrapper">
    <img class="avatar" src="https://source.unsplash.com/random" alt="">
    <p>Your Name</p>
  </div>
</div>
```

![スクリーンショット 2023-06-13 16.41.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882125/8ba75d32-8479-d082-3249-2ae3a026dfe1.png)

論理プロパティはドキュメント方向に依存します。ドキュメント方向が右から左になったことで、余白の方向も変わっていることがわかります。
また、`[dir="rtl"] .avatar {}`みたいに指定する必要がありません。

## 縦書きの余白指定をするとき
使用するのは`margin-block-end`です。
レスポンシブによって横書きから縦書きにすることがあります。その際、段落同士の余白を取りたい場合に有用です。

まずは横書きで段落ごとに下余白をつけましょう。
```html
<style>
.wrapper {
  background: #ccc;
  padding: 1rem;
  height: 250px;
}
.wrapper p {
  margin-block-end: 1em;
}
.wrapper p:last-of-type {
  margin-block-end: 0;
}
</style>

<div class="wrapper">
  <p>段落１段落１段落１段落１段落１段落１段落１段落１段落１段落１</p>
  <p>段落2段落2</p>
  <p>段落３段落３段落３</p>
</div>
```

![スクリーンショット 2023-06-13 16.12.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882125/be2c449c-b654-9a0b-5792-0880c91549f2.png)


では縦書きにしてみましょう。
```html
<style>
.wrapper {
  writing-mode: vertical-rl;
}
</style>
...
```

![スクリーンショット 2023-06-13 16.13.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882125/0a8b0d38-b0c6-edf5-aab8-449bf084d3b3.png)

ここでわかるのは、縦書きになってもブロック方向の余白が取れていることです。
本来ブロック方向は垂直方向を示しているのですが、縦書きになることでブロック方向が変わります。

詳しい説明は以下が参考になります。

https://developer.mozilla.org/ja/docs/Web/CSS/CSS_flow_layout/Block_and_inline_layout_in_normal_flow#%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E6%95%B4%E5%BD%A2%E3%82%B3%E3%83%B3%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%81%AB%E5%8F%82%E5%8A%A0%E3%81%99%E3%82%8B%E8%A6%81%E7%B4%A0

## まとめ
論理プロパティを使用することでより簡潔にスタイリングすることができます。

しかし、扱うプロパティによっては思わぬ方向に余白がつく可能性があります。それぞれの特徴を把握して使用することが大切です。

## 最後に
**GoQSystemでは一緒に働いてくれる仲間を募集中です！**

求人は出していませんが、SREやQAエンジニアも今後募集していこうと考えています！
ご興味がある方は以下リンクよりご確認ください。

https://recruit.goqsystem.com?qiita=ad4948662aa11043ebac
destroyアクションのルーティングを設定しよう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/2e42fa6d-fbe4-da90-93fc-c5ed98e5e6e7.png)

１：削除機能を実装するために、まずはルーティングを定義していきます。
削除を行う際にはdestroyアクションを利用します。

 routes.rbを以下のように記述する。
config/routes.rb
Rails.application.routes.draw do
 　root to: 'tweets#index'
 　 resources :tweets, only: [:index, :new, :create, :destroy]
end
windowsでuser/1000/spring-1000の一時フォルダが消えてrails g コマンド時にエラーが起きる時の対処法

rails g コマンドを実行した時に以下のエラーが発生した。

```
 Permission denied @ dir_s_mkdir - /run/user/1000/spring-1000 (Errno::EACCES)
```

```
% sudo chown $USER:$USER /run/user/1000/spring-1000
```

上記コマンドで

・「No such file or directory」などのエラーが発生しなかった場合、今回実行したかったrails g controllerを実行


・「No such file or directory」などのエラーが発生した場合
以下のコマンドを一行ずつ実行する。

```
% sudo mkdir -p /run/user/1000/spring-1000
% sudo chown $USER:$USER /run/user/1000/spring-1000
```

これで一時ファイルを作成できたため、`rails g コマンド`を実行してもエラーが発生しなくなる。