OmniAICreator/Qiita-1.07M huggingface dataset:
【環境設定】ターミナルのプロンプトの表示の変更方法

## 背景
- ターミナルのスクショを取りたいが、ホスト名が本名になっているので、常に加工が必要だった。
- ターミナルのプロンプトの表示を変更し、加工の手間を省きたい。
![プロンプト_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/01e8a567-1bee-4c05-3776-d4bcc3f11baa.png)

## 目標
- ターミナルのプロンプトの表示を変更する。

## プロンプトの表示に使用される環境変数を確認する。
- プロンプトの表示は「PS1」という環境変数によって決まっているらしい。
- まずは、現状の「PS1」の設定値を以下のコマンドで確認してみる。
`$echo $PS1`
- デフォルトのmacであれば下記の通りになっているはず。
`%n@%m %1~ %#`
- それぞれの変数の意味は以下の通り。

|コマンド  |説明  |
|---|---|
|%n | ユーザー名　|
|%m | ホスト名 |
|%1~ | 調べたけどわかりませんでした。<br>誰か教えてください。 |
|%# | ユーザー種別 |

## プロンプトの表示に使用される環境変数を変更する。
- 環境変数なので`export`コマンドで値を上書きすれば表示を変更できる。
- ターミナルの立ち上げ時に読み込まれる`.zshrc`ファイルを編集する。
- `open`コマンドで`.zshrc`ファイルを開いて編集する。
`$open .zshrc`

・自分好みの表示ルールを`export　PS="[プロンプトの表示ルール]"`で指定し、`.zshrc`ファイルに追加する。
`export PS1="%n@ %1~ %#"`

- 私は上記のルールとし、本名が入っていたホスト名を無くした。
- 変更後の表示が下記。
![プロンプト_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/8f9e27d5-0da6-74e0-e39a-09a33a92dd90.png)

## 補足
（1）プロンプトとは？
- 調べたところ、CUIの入力箇所を示すものという意味ぽい。
https://wa3.i-3-i.info/word11367.html

（2）元々あった(base）の表示がなくなったのはなぜ？
- （base）という表記は、condaを使用したときの仮想環境でデフォルトで表示されるものらしい。
- 私はanacondaを使用している環境だったので、その影響だと思われる。
https://code-graffiti.com/base-is-displayed-at-the-top-of-the-terminal-on-mac/

## 参考資料

https://wa3.i-3-i.info/word11367.html

https://code-graffiti.com/how-to-change-the-prompt-display-on-the-mac-terminal/

https://www.lecu1012.com/bash_terminal_customize/

https://code-graffiti.com/base-is-displayed-at-the-top-of-the-terminal-on-mac/

## 個人サイト

https://takuma-tech.com/2022/10/01/302/
"間違った"モックアップを作ってクライアントのニーズを引き出すのだ！ (アドレナリンジャンキー)

>最高のかかしモデルには、意図的な間違いまで組み込まれていることがある。アナリストは、クライアントの注意をうながし、モデルに対して自由に批判をしてもかまわないことを示すために、モデルに傷をつける。「道化を演じる」ことを高度な手段として受け入れられる忍耐強いアナリストなら、この方法によって速くソリューションに近づける。

アドレナリンジャンキー プロジェクトの現在と未来を映す86パターン (Japanese Edition) (p.122). Kindle 版. 

<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura

<!-- Update From Qiita API -->
不均衡データに対するアプローチ　〜SMOTE・重み付け・アンダーサンプリングバギングの比較〜

# 本記事の概要













記事作成中
# 不均衡データって何？　なぜ問題なの？

<details><summary>詳細はこちら（前提内容のため折り畳み）</summary>

### 不均衡データとは
### どんな問題が起こるの？
</details>


# 不均衡データの対処法は？
SMOTE
重み付け
アンダーサンプリング×バギング

# 使用データ
RPAエンジニアが教えてる英語学習におけるおすすめ書籍

# 概要
英語初心者が外資系企業の現場で働くことになり、実際に現場で感じたことのレポート。
苦労や驚いたことを共有していきたいと思います。

今回は英語学習をこれから始める人に対しておすすめの書籍を紹介したいと思います。
自分はRPAエンジニアなのですが、RPA製品は外国製が多いため調べものなどの際に英語が必要なシーンもあるかと思います。
ここから興味をもって英語にチャレンジしてみるのも面白いですよ！

# そもそもどの順番で英語を学習すべきか？
私が考える英語の学習の順番については以下がよいと考えています。

1. 発音・発声・英単語
1. 文法・英単語
1. 音読・Toeic学習・英単語
1. 英会話・英単語

まずは発音と発声を正しいものにしておくことでそのあとすべての工程での理解度が変わってくるとおもいます。
今回はこの各工程でのおすすめのご紹介です。

# それぞれのおすすめ書籍
正直おすすめ書籍はたくさんあるのですが、今回はこれが１番だと思うものをピックアップしました。

## １・発音・発声・英単語
・発音・発声
発音については英語耳ではないでしょうか。
発音記号も含めてどのような音があるのかをしっかり解説してくれます。
![81fEV5aMXsL._AC_UL320_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846650/c9381958-2a66-9dca-f09c-b304df065888.jpeg)
ただ発音・発声についてはyoutubeで実際の音声や口の形を見ながら覚えることが大切です。


・英単語
英単語については文句なしで金フレではないでしょうか。
英語学習においてToeicの点数は自分の実力を測るわかりやすい指標であり、通過点だと思います。
abceedというスマホアプリでも購入が出来るのでアプリでの購入がおすすめです。
![81-QtfDYTsL._AC_UL320_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846650/de2c391d-d852-91e3-12fb-4abae440ab62.jpeg)

## ２・文法・英単語
・文法
文法については一億人の英会話がお勧めです。
一億人の英文法で挫折してしまった人に特におすすめで、まずはこちらから取り組んだ方が文法全体をおさらいできるので良いと思います。
必読の一冊です。
![816WBN88NwL._AC_UL320_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846650/92b4f0c1-0b32-1659-c2ee-0600b305ad6b.jpeg)


## ３・音読・Toeic学習・英単語
・音読
音読についてはTOEIC L&Rテスト出る語句1800+です。
Toeicで出てくる単語がストーリにちりばめられています。
読み物としても面白いのですごくよい教材です。
![71VCbUI-lJL._AC_UL320_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846650/26fc0b4c-2cb5-cb44-60ff-b36098bcb786.jpeg)


・Toeic学習
Toeic学習については普通に公式問題集を使いましょう。
Toeicで高得点を取るためには問題に対する慣れが必要です。
実際と同じ問題形式でやりこむことで点数が底上げされます。
![41fhpGrpDWL._SX218_BO1,204,203,200_QL40_ML2_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846650/d20ff7fb-7d54-ecdf-2b64-a493db03b78b.jpeg)


## ４・英会話・英単語
・英会話
英会話についてはおすすめの書籍はありません。
まずは英語を話す機会を増やすためにオンライン英会話を始めましょう。
そして自分が使う必要がある表現を学び、先生に自分の会話のクセを指摘してもらいましょう。
（特にFillerに注意してください）


# 終わりに
というわけで、今回は英語学習における書籍をまとめてみました。

英語学習はいかに諦めずに継続できるかが大事ですので、自分が楽しんで学べるものでしたら基本何でも良いと思います。
楽しんで勉強していきましょう！
devise_token_authでログイン前のパスワードリセット機能を作っていたら、react router domの理解不足で一瞬詰まった

はじめに
--
現在実装中のポートフォリオでは、react router domを使用してフロント側のルーティングを制御しています。

ネットの記事を参考にする中で、react router domがルーティングを照合する精度の違いを理解していなかったことで詰まった部分があったので、備忘録として残します。

環境
--
react 18.0.0
react router dom 5系
rails 6.1.4
M1mac

前提
--
devise_token_authでユーザーのログイン機能を作っており、ログイン前に入れない/そもそも存在しないURLに移動しようとするとサインインの画面に自動で移動するように設定しています。

何に困ったのか
--
devise_token_authでログイン前にパスワードを忘れた時のために、メールアドレスをフォームに入力すれば、パスワード変更用のリンクがメールに送られてきて、そのリンクからパスワードを変更できる機能を作成していた時にルーティングの精度が原因で詰まったので、その内容も備忘録として記載します。

パスワード変更の機能を作るために、メールから移動できるredirect_urlを指定し、しっかり求めている画面が表示されるように、下記のようにルーティングも設定しました。

~~~react
<Route exact path="password/reset/form" component={パスワード再設定用の画面} />
~~~

URLを直で打ってみるとちゃんと表示されることも確認できます。

![スクリーンショット 2022-09-01 1.38.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641341/50e24c6a-7160-05c7-0b65-33a4c7f071be.png)

![スクリーンショット 2022-09-01 1.33.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641341/8d66d976-0f48-983b-0821-70e08a34a74d.png)

しかし、上記のように送られてきたメールのリンクを押して移動をすると、パスワード再設定画面ではなく、サインイン画面に移動してしまいます。
![スクリーンショット 2022-09-01 2.08.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641341/de96e607-a778-5bf7-f612-10086bcc69c5.png)


原因はURLにパロメータがついていたからだった
--
少し話はずれますが、ログイン前にパスワードを変更するには、"ログインしてないけどパスワードを変更してOKになるパスワード的なもの(reset password tokenとか、accsess-tokenとかのトークン）"が必要です。

そのパスワード的なものが下記のような形で付属されているリンクがメールに貼り付けられてきます。

~~~
パスワードを変更する画面のURL + パロメータ（これがパスワード的なもの）

//こんな感じ。"~form?"までがパスワード変更画面のURL(pwで隠している部分にトークンが入ります）
http://localhost:4000/api/v1/auth/password/reset/form?access-token=[pw]
&client=[pw]&client_id=[pw]&config=default&expiry=[pw]&reset_password=true&token=[pw]&uid=[pw]
~~~

メールから送られてくるリンクに"ログインしてないけどパスワードを変更してOKになるパスワード的なもの(reset password tokenとか、accsess-tokenとか）"がURLのパロメータとしてくっついて帰ってきます。


ルーティングの記述を修正
--
サインインの画面に移動してしまう原因は、先ほど下記のように記述したルーティングの設定の箇所です。
~~~react
<Route exact path="password/reset/form" component={パスワード再設定用の画面} />
~~~

この"exact"という文言がついていると、"URLが完全一致した場合にコンポーネントを表示する"ということになります。
一文字でも間違っていると表示されないということです。

"Route path"のみで何もついていないと、前方一致が指定ればOKです。それ以降何か文字がたされていても画面を表示してくれます。

~~~react
//password/reset/form以降に何か文字が入っていると表示されない
//password/reset/form?~だともちろん表示されないのでサインインの画面に移動する
<Route exact path="password/reset/form" component={パスワード再設定用の画面} />

//password/reset/form以降に文字が入っていても、formまでが一致していれば表示される
//form?~（パスワード変更に必要なパラメータ)が付属していてもコンポーネントは表示される
<Route path="password/reset/form" component={パスワード再設定用の画面} />
~~~

ちなみに
"sensitive"をつけると大文字・小文字も厳格にチェックする、などの条件を追加できます。

前方一致がデフォルトの機能だったのでちゃんと理解して使っていれば普通にオプションを加えることはないので問題なかったと思うのですが、
react-router-domを全く理解せずにとりあえずネットの記事を真似てコードを書いていたあの頃は気づけなくて当たり前だと思うので仕方ないなと割り切っています。
今回知れてよかった。

ちなみに、無事exactを外して前方一致がするように修正をしたら問題なくメールからパスワード再設定画面を表示させることができました。
~~~react
<Route path="/api/v1/auth/password/reset/form" component={RedirectForgetPassword} />
~~~

終わりに
--
ここだけの話今回の画面移動できないエラーよりも、URLのパラメータを使ってどうやってパスワードを変更するのかというロジックを記述する方が体力使った気がします。。
今さっきなんとか完成できたので達成感半端ないです。。
リファクタリングもできたら頭の整理も兼ねてqiitaに書こうかなと思います。

理解不足でも手を動かしながら学んでいるので、間違った解釈の部分があるかもしれません。
もしそのような場所があったら優しくご指摘いただけますと幸いです。
React Native 0.69 のバージョンアップで、RCT-Folly linker error: ld: -U and -bitcode_bundle cannot be used together というエラーになる。

# 発生環境
React Native 0.69.4

# 原因
Issueが立っていました。
https://github.com/facebook/react-native/issues/34148

- 詳細な原因までは理解できていませんが、Xcode 14ではBitcodeは廃止となるようです。
- Reactの関連ライブラリがその対応に追随できていないものがあるのではないかと思われます。
- 単にBitcodeをOFFにすると良い、ということなので、対応方法を記載します。

# 対応方法
Podfileに以下を記載します。
```ruby
  post_install do |installer|
    react_native_post_install(installer)
    __apply_Xcode_12_5_M1_post_install_workaround(installer)
  end
```

↓

```ruby
  post_install do |installer|
    # pods_projectとsubprojectの2箇所でENABLE_BITCODEをNOに設定
    installer.pods_project.build_configurations.each do |config|
      config.build_settings['ENABLE_BITCODE'] = 'NO'
    end
    installer.pod_target_subprojects.each do |subproject|
      subproject.targets.each do |target|
        target.build_configurations.each do |config|
          config.build_settings['ENABLE_BITCODE'] = 'NO'
        end
      end
    end
    react_native_post_install(installer)
    __apply_Xcode_12_5_M1_post_install_workaround(installer)
  end
```

# 参考
AppleがどうしてBitcodeを廃止するのか、については以下をご参照ください。

https://stackoverflow.com/questions/72543728/xcode-14-deprecates-bitcode-but-why

- React Nativeではたくさんのライブラリを使用していますが、それらを直接修正することはできないので、Podfileで操作するということがわかりました。
- 同様の事象で困っている方がおられたら、参考にいただければ幸いです。
三項演算子　returnできない時の対処法

実務でTSを書いている時に、「三項演算子使お！」と思って書いてみたのですが、初歩的なミスをしてしまい、
少し忘れたら嫌なので、メモとして残します！
（対処法だけ見たい方は最後のセクションをみましょう！）

# 流れ
1. 三項演算子とは
1. returnできないエラー
1. 対処法


# 1. 三項演算子とは
簡単に言うと、if文をかなり省略した**式**です。
実際に通常のif文と三項演算子を比較してみるとわかりやすいと思います。

React(ts)内で記述した三項演算子
```typescript:index.tsx
let style = disabled ? { backgroundColor: 'gray' } : {}
```

通常のif文
```typescript:index.tsx
let style
if(disabled) style = { backgroundColor: 'gray' }
else style = {}
```
（このコードは、ReactのStyleの指定方法を用いて、背景色の設定をオブジェクトで返します。）
若干行数が増えますね〜！
この**行数を削減**したり、**TorFしかない時に使う**のが三項演算子です。
（この条件以外だとそんなに利点ないです。
三項演算子もネストもできますが、ネストすると、可読性Down💦）

三項演算子の公式的な書き方は以下の通りです。
```typescript
条件式 ? Trueの時の式 : Falseの時の式
```

# 2. returnできないエラー
先ほど学んだ三項演算子ですが、早速Reactの関数（実質tsの関数）で使ってみましょう！
```typescript:index.tsx
const returnDisableStyle = (disabled: boolean) => {
  disabled ? return { backgroundColor: 'gray' } : return {}
}
```
if文の時の雰囲気からして、こんな感じで書くのでは！と思いましたが、
エラーが出て、実行できません、、、😭
if文と若干違うところがあるのが、三項演算子の難しいポイントです、、、

# 3. 対処法
先ほど、エラーが出ましたが、以下のように記述すれば、解決できます🙌
```typescript:index.tsx
const returnDisableStyle = (disabled: boolean) => {
  return disabled ? { backgroundColor: 'gray' } : {}
}
```
関数などで、`return`と三項演算子を組み合わせる場合は、
```typescript
return 三項演算子
```
としましょう。
これは、三項演算子が式であることに由来します。
プログラミング言語では、関数の引数として、計算式を渡したり
条件式を変数に代入できたりして、式と値がほぼ等価な価値観の世界です。
（コンパイラの勉強をすれば、言語処理がわかるので、もう少し理解できるかもしれません）
そんな世界なので、三項演算子（条件式）を値として考えて、returnできます。

以上で、returnできない三項演算子の対処法を終わります！
JSのフレームワークの記法によっても変わってくるので、要注意です！

# 補足
複数行書きたい時は以下のように書きます（素のJS、バニラJS）
コンマをつける＋（）をつければOKです！
```javascript
条件 ? (
    コード,
    コード２,
) : (
    コード3,
    コード4,
)
```
可読性が下がるので、あまりお勧めはしませんが、、、😅
どうしても必要な時は使ってください！
（ここまでするのであれば、if文の方が良いので、なるべく避けましょう）

# 参考文献

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Conditional_Operator
ESP32 Arduino を設定

ESP32 開発環境を ArduinoIDE で使えるように設定。
インストール方法は最近は変わってないのかな?

# 環境

- Ubuntu 22.04 AMD64 Ja
- Arduino IDE 1.8.19
  - ポータブル化設定済  
-

検証日:
- 2022/09/01
  -  esp32 by Espressif Systems バージョン2.0.4
- 2024/01/05
  -  Stale release link を変更
  -  esp32 by Espressif Systems バージョン2.0.14
- 2024/02/22
  - serial を追加
  - esp32 by Espressif Systems バージョン2.0.14
# インストール

## 事前準備

Arduino IDE を展開したディレクトリで、以下のスクリプトを実行しておく
```
$ ./arduino-linux-setup.sh $USER
```
pyserial をインストールしておく
```
$ sudo apt install pip
$ sudo pip install pyserial
```

## ボードマネジャからインストール

公式ドキュメントはこれです。

https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html

この記述通りやっていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/8a2482f8-e92b-d775-2e55-784718874d65.png)

今回は、Stable release link を使いました。

```
https://espressif.github.io/arduino-esp32/package_esp32_index.json
```

Arduino IDE から「ファイル」-「環境設定」で、以下のように「追加のボードマネージャのURL：」に先のリンクを登録して「OK」


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/e9c98bfc-d61a-638f-a3cd-e8f49f352e39.png)


「ツール」-「ボード」-「ボードマネージャ」で「esp32」を検索、「esp32 by Espressif Systems」を選択してして 「インストール」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/008629d9-3c28-47af-2171-f94ee1b57b4e.png)

しばらくインストール作業が進んで、「INSTALLED」になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/c9718e32-bc9d-d73f-9c68-be42fa1a0c3b.png)

# 動作確認

ESP32 ボードを接続し、シリアルポートとボードを合わせます。
動作確認プログラムは

「スケッチ例」-「ESP32」-「ChipID」-「GetChipID」を試してみました。

スケッチを書き込んでから、シリアルモニタを起動し、115200bps を選択すると Chip ID が表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/d99262b1-f2b3-27a7-24ab-d173be39a160.png)

# 手順について

ArduinoIDE では、 1.6.4 以降ボードマネージャを使ったやりかたが導入されました。
今回はチェックしたところそのやりかたのまま変更はありせんでした。
なお、追加のボードマネージャに設定する URL は新しくなってたですね!
openssl自己証明書実行手順



- 認証局の公開鍵と秘密鍵を作成
openssl genrsa -out ca_private_pem.key 2048
openssl rsa -in ca_private_pem.key -pubout -out ca_public_pem.key
- 認証局のサーバ証明書
openssl req -new -x509 -days 365 -key ca_private_pem.key -out ca_server_pem.crt


- webサーバ用の公開鍵と秘密鍵作成
openssl genrsa -out web_private_pem.key 2048
openssl rsa -in web_private_pem.key -pubout -out web_public_pem.key
- CSR
openssl req -new -key web_private_pem.key -out web_server_pem.csr


- v3.ext
authorityKeyIdentifier=keyid, issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = ec2-XXXXXXXX.ap-northeast-1.compute.amazonaws.com


### ③webサーバ用の証明書発行
openssl x509 -req -sha256 -extfile v3.ext -days 365 -CA ca_server_pem.crt -CAkey ca_private_pem.key -CAcreateserial -in web_server_pem.csr -out web_server_pem.crt


### ④apache関連の設定ファイル
 
- ssl.confを利用するために必要なモジュールのインストール

```txt:インストール後ssl.confが使えるようになる
yum install mod_ssl
```
```
sudo vi /etc/httpd/conf.d/ssl.conf

・・・・・・ファイルの中を変更・・・・・

SSLCertificateFile /etc/pki/tls/certs/localhost.crt

SSLCertificateKeyFile /etc/pki/tls/private/localhost.key

↓変更

SSLCertificateFile /home/ec2-user/web_server_pem.crt

SSLCertificateKeyFile /home/ec2-user/web_private_pem.key
・・・・・・・・・・・・・・・・・・・・・
```

https://9cubed.info/article/cipher3

https://www.youtube.com/watch?v=hxlQei0VFrg
【Linux】chownコマンドについて(所有者/所有グループの変更)

# ファイルの所有者/所有グループの変更について
chownコマンドを実施する事で所有者/所有グループの変更を行う事が出来ます。
構文は、「chown 所有者:所有グループ ファイル名」となります。
所有者のみ変更を行いたい場合は、「chown 所有者 ファイル名」で変更を行う事が可能です。

グループのみ変更を行いたい場合は、chgrpコマンドを使用します。構文は、「chgrp グループ名 ファイル名」です。あまり、chgrpコマンドは使う機会がないのかなと思います。(自分は業務で使った事がないです。)

:::note info
所有グループの変更については、chownコマンドでも変更出来ます。
「chown :所有グループ ファイル名」で行えます。所有グループの前には:(コロン)をつけます。
:::

再帰的に所有者等の変更を行いたい場合は、-Rオプションを使用する事で行えます。

# 実際にやってみた
以下ファイルの所有者/所有グループの変更を行いたいと思います。
現状はパーミッションが700となっており、所有者以外は 読み込み/実行 等が行えないような設定です。所有者は test_01ユーザー となっております。

今回は 所有者/所有グループ を test_02 に変更して、読み込み/実行を行うまでを目標とします。

```:ファイルの所有者確認など
[test_02@localhost tmp]$ ll
合計 8
-rwx------. 1 test_01 test_01 362  8月 30 07:37 memo.txt
-rwx------. 1 test_01 test_01   4  8月 30 07:04 test.sh
[test_02@localhost tmp]$ cat memo.txt
cat: memo.txt: 許可がありません
[test_02@localhost tmp]$ /tmp/test.sh
-bash: /tmp/test.sh: 許可がありません
```

変更を行う為に、特権ユーザーにスイッチします。

```:特権ユーザーへスイッチ
[test_02@localhost tmp]$ su -
[root@localhost ~]#
```

chownコマンドを実施し、所有者/所有グループを変更します。

```:所有者/所有グループを変更
[root@localhost ~]# chown test_02:test_02 /tmp/memo.txt
[root@localhost ~]# chown test_02:test_02 /tmp/test.sh
[root@localhost ~]# ll /tmp
合計 8
-rwx------. 1 test_02 test_02 362  8月 30 07:37 memo.txt
-rwx------. 1 test_02 test_02   4  8月 30 07:04 test.sh
```

test_02ユーザーにスイッチして、読み込み/実行を行ってみます。

```:実行
[test_02@localhost ~]$ cat /tmp/memo.txt
合計 8
-rwx------. 1 test_02 test_02 362  8月 30 07:37 memo.txt
-rwx------. 1 test_02 test_02   4  8月 30 07:04 test.sh
[test_02@localhost ~]$ /tmp/test.sh
Hello World!
```

無事実行出来ました。


以上、何かの参考になれば幸いです。
Rubyで標準入力から値を受け取る方法 2022年版

#  はじめに
この記事は、プログラミング問題などでよく見られる、標準入力から値を受け取る方法をまとめたものです。
#  前提
使用する言語はRubyです。
#  一行に1要素のとき(文字列)
###  標準入力
```
Ruby
```
### 標準入力を受け取るコード
```ruby
string = gets
```
### 出力するコード
```ruby
p string
```
### 出力結果
```ruby
"Ruby"
```
# 一行に半角スペース刻みで要素があるとき(文字列)

###  標準入力
```
Ruby PHP Python
```
### 標準入力を受け取るコード
```ruby
strings = gets.split
```
### 出力するコード
```ruby
p strings
```
###  出力結果
```ruby
["Ruby", "PHP", "Python"]
```
splitを使用することで、３つの要素をそれぞれ別のものとして配列に格納しています。

※splitの使い方
split(' ')としている記事などもありますが、
半角スペース刻みの入力値の場合は引数(' ')を指定しなくても問題ありません。

つまりsplit(' ') ≒ split  (※半角スペース刻みの入力値のときのみです) 

# 複数行に一つずつ要素が存在するとき(文字列)

### 標準入力
```
Ruby
PHP
Python
```
### 標準入力を受け取るコード
```ruby
strings = readlines.map(&:chomp)
#またはこちら(パフォーマンス的に推奨)
strings = readlines(chomp: true)
```
### 出力するコード
```
p strings
```
###  出力結果
```ruby
["Ruby", "PHP", "Python"]
```
# 複数行に半角スペース付きで要素が複数存在するとき(文字列)

### 標準入力
```
Ruby PHP Python
Java C# C++
```
### 標準入力を受け取るコード
```ruby
strings = readlines.map{ |i| i.split.map(&:chomp)}
# またはこちら(推奨)
strings = readlines.map(&:split)
```
### 出力するコード
```
p strings
```
出力結果
```ruby
[["Ruby", "PHP", "Python"], ["Java", "C#", "C++"]]
```
#  入力値が数値の場合

### 一行に数値がひとつのとき

###  標準入力
```
123
```
### 標準入力を受け取るコード
```ruby
number = gets.to_i
```
### 出力するコード
```
p number
```
###  出力結果
```ruby
123
```
# 一行に半角スペース刻みで数値があるとき

### 標準入力
```
1 2 3
```
### 標準入力を受け取るコード
```ruby
numbers = gets.split.map(&:to_i)
```
### 出力するコード
```
p numbers
```
###  出力結果
```ruby
[1, 2, 3]
```
#  複数行に一つずつ数値が存在するとき
### 標準入力
```
1
2
3
```
### 標準入力を受け取るコード
```
numbers = readlines.map(&:to_i)
```
### 出力するコード
```
p numbers
```
###  出力結果
```
[1, 2, 3]
```
# 複数行に半角スペース刻みで要素が存在するとき
### 標準入力
```
1 2 3
4 5 6
```
### 標準入力を受け取るコード
```ruby
numbers = readlines.map{ |i| i.split.map(&:to_i) }
```
### 出力するコード
```
p numbers
```
### 出力結果
```ruby
[[1, 2, 3], [4, 5, 6]]
```
CakePHP4でDebugKitツールバーが404エラーになる解決法

# はじめに

CakePHP 4.4.3 にアップデートしたところ、いつの間にか DebugKit toolbar が表示されなくなっていました

- GET: <http://localhost/debug-kit/toolbar/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa>
    - 404 Not Found

表示するように対応します

![cakephp_debug_kit_404.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586387/62e0a665-684f-d1c5-0a68-1ff859cc4938.png)

# 結論

:::note info
routes.php に DebugKit の指定すれば OK
:::

```php
return static function (RouteBuilder $routes) {
    $routes->scope('/', function (RouteBuilder $builder) {
        $builder->fallbacks();

        if (\Cake\Core\Configure::read('debug')) {
            // サーバーの環境変数 DEBUG = true を指定していれば、DebugKit へのルーティングを追加
            $builder->connect('/{controller}/{action}/*', ['plugin' => 'DebugKit']);
        }
    });
}
```

# バージョン

- PHP
    - 8.1.0
- CakePHP
    - 4.4.3
- DebugKit
    - 4.8.1

# 確認

表示されるようになりました

![cakephp_debug_kit_200.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586387/b5d815ae-7f54-cce4-9af6-387f5bcca264.png)

## 確認したブランチ

https://github.com/q23isline/reinventing_the_wheel

# 参考

CakePHP4を試す (AuthenticationプラグインとDebug Kitプラグイン)

https://www.m-kobayashi.org/working_log/2020/06/04_01.html

Cakebook | Debug Kit - 4.x

https://book.cakephp.org/debugkit/4/ja/index.html
Java Silver SE11受験記

7月にJava Silver SE11を受験しました。
結果は残念ながら不合格だったのですが、受験期として残します。



# 使用した教材
・徹底攻略Java SE 11 Silver問題集[1Z0-815]対応
黒本と呼ばれるやつです。
[こちらの教材](https://www.amazon.co.jp/徹底攻略Java-SE-11-Silver問題集-1Z0-815/dp/4295007625/ref=nodl_?dplnkId=068007f9-e5fe-44a7-ac60-93372c287a24)



# 学習期間
1ヶ月弱



# 行った学習
[1回目]
とにかく解説を読む。
⇒簡単な知識しかなく、しばらくJavaのコーディングをしていなかった私にとっては、1回目からいきなり問題を解くのは難しかった。
何を問われているかを把握した後は、ひたすら解説を読み進めていった。
1度目から完全に把握するのは難しいので「へぇ〜こんなのあるんだ。」位のスタンスで良いと思う。

[2回目]
自力でできるところまでで問題を解く。
分からなくなったら解説を見る。
⇒1問毎に知らない知識が出てきて気が遠くなるが、とにかく心を折らさないことが1番大切。解けなくても気にしすぎないように気をつけた。



# 試験を受けてみての所感
・受験料が高いので落ちると痛い。。。
⇒楽天からチケットを購入すると、通常より安くなるので利用した。それでも30,180円。
[購入はこちらから](https://item.rakuten.co.jp/it-test/137327/?scid=wi_ichi_iphoneapp_item_share)
以前は再受験無料キャンペーンなどもあったようだが、2022年度は実施予定なしとのこと。

・試験の予約が複雑！！
予約にはOracleアカウントだけではなく、予約専用のサイト？のCertviewのアカウントが必要。
更にログインしたCertriewを通して、ピアソンVUEというサイトに飛んで初めて試験予約が出来るようになる。
(英語のサイトなので自動翻訳の日本語を理解しなければいけないのもイライラポイント。)
分かりやすく解説してくれているサイトがたくさんあるので、調べて言われるがままにやった方がいい。
また、場所によっては予約が埋まりやすかったので、余裕を持って早めに予約した方がいい。

・持ち物について
身分証以外は持ち込めないので、最低限の荷物だけあればよい。
試験時間は3時間あり長丁場になるが、真夏でも冷房が寒かった。長袖の羽織物を持っていった方がよい。

・試験中のメモについて
メモとしてラミネート加工したA4紙1枚とマッキーを渡されるが、メモは消せないため注意。
あまり大きく書かないように気をつけた。
書ける場所がなくなった場合は、試験官を呼ぶと新しいものをくれる(らしい)

・黒本の模試に出てきた問題が結構出てくる
そのままか、少しだけアレンジしてあるが同じ考え方で解ける問題が結構あった。
学習時間が取れず模試は適当になってしまっていたので、もっと解いていればよかった(というか模試中心に勉強していればよかった)と反省。



# 反省点
・学習時間
学習の時期に限って残業が続いてしまい、学習時間の確保が十分に出来ていなかった。もっと前々から時間をかけてゆっくり勉強すれば良かった。

・モチベーションの維持
これが一番難しく、モチベーションが維持出来なかったことが最大の敗因だと思っている。
慣れるまでは1問1問が難しく、重く感じてしまうので勉強に気持ちが乗らなかったり、
試験が近づくにつれて「あ〜あと〇〇日しかないのに全然進んでない…」という気持ちが更に勉強を嫌にさせてしまったり…
やはり短期戦の学習ではなく長期戦で、最初から完璧を目指さず少しずつ少しずつ自信を積み重ねていく方が良いと思う。
Heroku ClearDB(MySQL) デプロイ AutoIncrementの順番が飛ぶ！

表題のある通り、Herokuでデプロイする際に、ローカルDBからClearDBに移行したら、AutoIncrementの順番が飛んだのでその記録です。

同じように悩む人がいたら参考にしてください。
あれこれ試して２日間使った人間の言うことですが⭐️

## 起きていること
普通は、１、２、３、４、５.....と連番になるのに、4から始まり、10飛びで刻む。
ちなみにローカル環境に戻してみると正常、、、。
![dcf0440e-af7c-41ff-a9f1-521f1c56d8b8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2280802/a00562ba-9fa8-a773-0622-abfe8e0fa92e.png)

## 原因
```sql
SHOW GLOBAL VARIABLES LIKE 'auto_inc%';
(response)
auto_increment_increment = 10  //10飛びで刻む
auto_increment_offset　　= 4      //4から始まる
```
故に4,14,24,34 ....

##  解決法　（一般的）
普通、こんなことになりません。この２つの設定値はデフォルトで　「１」です。
```sql
SET @@GLOBAL.auto_increment_increment = 1;
SET @@GLOBAL.auto_increment_offset = 1;
```
この時、`@@GLOBAL.`としないと変更をセッションで停めてしまうので注意。
[Mysqlドキュメント](https://dev.mysql.com/doc/refman/5.6/ja/using-system-variables.html)参照

しかし、この時に下記のエラーが出る人もいると思いますが、今回は触れません。
```sql
Error Code: 1227. Access denied; you need (at least one of) 
the SUPER privilege(s) for this operation
```

## 解決法　(本件)

ClearDBの仕様らしいので諦める。以上
古いですが、他にもありますので「ClearDB　AutoIncrement　仕様　」で検索。
https://qiita.com/nsatohiro/items/0458e63c47c3d6ff37d0
https://thinkit.co.jp/story/2012/09/26/3717?page=0%2C2

また、怪しいなと思ったきっかけとしてはClearDBに接続し、ローカルDBからデータをエクスポートしてClearDBにGUI等経由でインポートすると思いますが、その前に、ClearDB上でGLOBALの設定値を確認すべく、上述のクエリを実行すると既に「４スタート、10飛び」だったのです。

## 後書き
個人的にはHerokuは個人のちょっとした開発に使用する程度だと思うので、
ここにエネルギーを使うのは良く無いですよね。
アプリは普通に使えるので諦めました(笑)

もし、諦めない解決法がある、または、これらは周知の事実だったならば、教えてください！
Laravel/PHPに使えるライブラリを自己学習的にまとめてみた

# Carbon
言わずと知れたPHPで日付を扱うためのライブラリ

インストールは以下のコマンドでcomposerから行う
`composer require nesbot/carbon`

インスタンスを生成して直感的なコードで日付の計算ができる

```php:例
$date = new Carbon(); // 2021-08-31

// 週末かどうか
echo $date->isWeekend();

// 金曜かどうか
echo $date->isFriday());

// 日付が何日間開いているか
$dateMay = new Carbon('2021-05-01');
$dateMay->diffInDays($date); 
```

# L5 Repository
リポジトリクラスを自前で用意しなくても
このライブラリを使えば共通化されたリポジトリからスタートできる。
5.5以上ならサポートされているらしい。

インストールは以下のコマンドでcomposerから行う
`composer require prettus/l5-repository`

[Github](https://github.com/andersao/l5-repository)

検索クエリを制御する`Criteria`が存在するため
検索条件に応じた検索処理もロジックを共通化できるのは利点。

詳しくは以下の記事を参考にされたし。

https://qiita.com/katsuren/items/c5c67dcfeeaa57bbf364

https://qiita.com/smith-30/items/e9f26bce158343ef3c83


# TCPDF+FPDI
PDFを読み込んだり、出力したりするライブラリ。
・TCPDF
・FPDI
の2つのライブラリでPHPからPDFを出力できる。
帳票の作成や請求書などのプログラム上で動的に変わるPDFファイルを生成する時に使える。

帳票テンプレート上に値を出力してユーザに表示させたい場合などは、
値の出力位置を座標で指定することができるので
任意の場所に値を出力設定が可能。

https://qiita.com/hinako_n/items/2bb3bd98bd7e50666c12

# Larastan
Laravelのコード解析を行うツール。
コードレビュー前にあらかじめこれで
チェックしておくことで余計な指摘事項を減らすことができそう。

`composer require nunomaduro/larastan:^2.0 --dev`

https://qiita.com/MasaKu/items/7ed6636a57fae12231e0

# Laravel Enum
PHPで定数を定義する際には
 `const HOGE = 1;` や `define("FOO", "something");`といったふうに定義をするが。

ところが、これでは定数に規則性を持たせるときに
`const HOGE_FALSE = True;`と`const HOGE_TRUE = False;`となってしまうので
名前が長くなったりする。

「クラス方式で持てる方がいいよね。」っていうのを解消するのが
`enum型（列挙型）`の概念。

`composer require bensampo/laravel-enum`

[クラス方式で持てる方がいいよね。](https://github.com/BenSampo/laravel-enum/blob/v4.2.0/README.md#guide)

# Laravel Pint

Laravel 9以上で導入された公式ライブラリ。
PHP-CS-Fixerと同じくルールに則ってコードを自動整形してくれる。

コーディングルールの統一に使えそう。

https://readouble.com/laravel/9.x/ja/pint.html
python 使いの ruby メモ

# 概要
python と ruby はメソッドなどは大体同じなんですがちょいちょい違うところがあるので個人的な備忘録として作成しました。随時加筆します。


# ruby メモ
## 文法・作法
- `:` はいらない
    - python だと定義文やコンテキストブロックを作るときに必要だが ruby は不要
- `if` `elsif` `else` `end`
    - python だと `if` ブロックを閉じるときはインデントを抜けるだけだが ruby は終了範囲を明示的に `end` で指定する必要あり
- `return` は書かない
    - 書いてもエラーは起きないが慣習的に書かない
    - 関数 / メソッドの最後に評価された値が勝手に戻り値になるので明示的に書かなくてよい
- `unless`
    - python で書くなら `if not`
- `case` `when`
    -  `case state` `when value` で条件分岐を書ける。複数条件あるときに便利
    -  python だと `match` `case` に相当。3.10 以降で実装
-  関数 / メソッド定義時・呼出時に引数がないときは `()` を省略可能
    - 定義時・呼出時いずれも `()` を書いてもエラーは起きない
    - python で同じことやるとメソッドだよ〜と言われるだけでメソッドが呼び出されずに終わるところが呼出しになる
-  メソッド呼出後に `!` をつけると inplace 処理
    -  pytorch でいうメソッド末尾の `_`　みたいなもの
    -  全てのメソッドに実装されてるのかは不明
-  `?` 付きのメソッドは `bool` を返す
    - クエスチョンマークの初見の違和感がすごい

## 基本オブジェクト
### 配列
#### python にも同じ機能はあるが表現が違う
- `include?(x)`
    - `x`　が配列に含まれるか否かの `bool` を返す
    - python で書くなら `x in list`
- `empty?`
    - 配列が要素を持っているかの `bool` が返る。`len(list) > 0` と等価
- `shuffle`
    - 配列をランダムシャッフルする。`random.sample(list, len(list))` と等価
    - python の `random.shuffle` は inplace 処理なので微妙に違う
- `(start..end).to_a`
    - start から end までの配列を作成する
    - python だと `list(range(start, end+1))` とか `[i for i in range(start, end+1)]`。end が1ずれるので注意
- `list << x` or `push(x)`
    - 配列末尾に `x` を追加する。python だと `list.append(x)`
- `shift`
    - 配列の最初の値を削除して戻り値として返す。python だと `list.pop(0)`
    - 全ての配列要素の index が shift するからこの命名かと思われる
- `uniq`
    - 配列のユニークな要素を返す。たぶん配列の順番を破壊しない
    - python で配列の順序を破壊して良い場合は `list(set(list))` で実現できる。順序を破壊しない場合は unique のフラグを管理しつつループで先頭からチェックしていくとかになる気がします
- `join`
    - 要素が文字列の配列を結合する
    - python の場合 `string.join(list)`　になるか
- `size`
    - 配列の要素数を返す。python だと `len(list)`
#### python に同名メソッドがあるが挙動が違う
- `reverse`
    - ruby は inplace ではない
    - python は inplace　。互換なのは `reversed(list)`

# メモ
- ruby 教材としては以下の講座を使わせていただきました
    - https://www.udemy.com/course/the-ultimate-ruby-on-rails-bootcamp/
    - 動画内では AWS を使っていますが面倒だったので docker で ruby のイメージを引っ張ってきて環境を作りました
- inplace 処理が `!` で表現できるのは統一的で良いなと思った
OkHttpのレスポンスボディを文字列に変換しても文字化けするとき

ハマりました・・・

現象としては、Postmanを使ってもCURLを使ってもきちんとレスポンスボディが読めるのですが、なぜかOkHttpを使うと文字化けしてしまい、ボディをデシリアライズできませんでした。
結論から言うと、gzipという暗号化処理がされていたせいでした。

これを解決するには二通りの方法があります。

1. Encodingを許可しない（こっちは簡単ですがセキュリティ面でリスクがありそうです）
2. GZIPで復号する


## 1. Encodingを許可しない

これは簡単で、リクエストヘッダーから「Accept-Encoding」を削除してしまえば大丈夫かと。
例えばInterceptorなどを用いて

```kotlin
        val request = chain.request().newBuilder()
            .removeHeader("Accept-Encoding")
            .build()
        val response = chain.proceed(request)
```
リクエストから`Accept-Encoding`を取り除きました。
ここにgzipが入っていなければサーバー側は配慮してくれる場合が多そう？です。実際にFirebaseのとあるエンドポイントは暗号化せずにレスポンスしてくれました。

## 2. GZIPで復号する

復号方法は
```kotlin
val jsonFormat = Json { ignoreUnknownKeys = true }
val buffer = GzipSource(response.body!!.source()).buffer()
val bodyJson = jsonFormat.decodeFromString<ErrorResponse>(buffer.readUtf8())
```

こんな感じです。Kotlin Serializationを使っていますが、そこはGsonでもJacksonでも何でもオッケーです。
着目すべきはGzipSourceで`response.body!!.source()`を囲っている部分ですね。
これによりGzipの復号化処理を行ってくれるようです。
※ちなみに暗号化されていないものを復号しようとするとまた別のエラーが出るので注意してください

ちなみにテストコードを書くときは
```kotlin
        val responseJsonString = """
                    {
                        "error": {
                            "code": 400,
                            "message": "INVALID_ID_TOKEN",
                            "errors": [
                                {
                                    "message": "INVALID_ID_TOKEN",
                                    "domain": "global",
                                    "reason": "invalid"
                                }
                            ]
                        }
                    }
                    """.trimIndent()

        /**
         * レスポンスがgzipでエンコーディングされているため、エンコーディングする
         */
        val buffer = Buffer()
        val byteOut = ByteArrayOutputStream()
        val gzipOut = GZIPOutputStream(byteOut)
        gzipOut.write(responseJsonString.toByteArray())
        gzipOut.close()
        buffer.write(byteOut.toByteArray())

        val server = MockWebServer().apply {
            enqueue(
                MockResponse().apply {
                    setResponseCode(400)
                    setBody(buffer)
                }
            )
        }

```

↑こんな感じで、GZIPOutStreamを使ってgzipで暗号化してbufferに書き込んで、MockResponseにsetBody()すれば暗号化されたレスポンスを再現できました。


恥ずかしながらたった今初めてgzipなるものを知りました。
一体何の文字化けなんだろう？とutf-8やら何やら探りましたが、こんなものがあったとは・・・
勉強します。
【Rails】CanCanCanでリソースが特定の条件を満たすときのみ権限を付与する方法

Railsにおいて権限設定を簡単に実装できる方法は、Cancancanを使うことが１つの手段として考えられます。
https://github.com/CanCanCommunity/cancancan
cancancanを使った権限設定では、**特定の条件を満たすリソースについては特定のアクションを許可したい**、という場合があります。
そんな時に取れる対応方法を紹介します。

# 想定ケース

**ユーザーは、企業名（name）にhogeの文字列を含む企業についてはメールを送れる。**

こんな権限設定がしたいとします。
準備として、companyモデルで「名前にhogeが入っている」ことを判定するインスタンスメソッドを定義します。

```ruby:company.rb
class Company < ApplicationRecord
...（略）

  def include_hoge?
    name.include?('hoge')
  end
end
```

# Abilityの書き方

この場合、ブロックを使って以下のように書くと、上記を満たす権限設定を書くことができます。

```ruby:ability.rb
class Ability
  include Cancan::Ability

  def initialize(user)
    can :send_mail, Company, { include_hoge?: true }
  end
end
```

Companyの中から、include_hoge?がtrueを返す企業に対してのみ:send_mailの権限を付与できます。

# ControllerやViewで使うのは基本の使い方と同じ
一応注意点として、この方法だと、authorize_resourceを使って自動的にaction名と一致した権限を見る、といったことができなくなるので、
before_actionやaction内でauthorize!メソッドを使いながら権限チェックをすることになると思います。

- Controllerで使いたい時

```ruby:foo_controller.rb
FoosController < < ApplicationController
  def xxx
    @company = Company.find(params[:id])
    authorize! :send_mail, @company
    ...（略）
  end
end
```

- Viewで使いたい時

```erb:xxx.html.erb
<% if can? :send, @company %>
  ...（略） <%# 権限があるときに表示したい項目を書く %>
<% end %>
```

# 他の方法（あまり良くないと思われる）

別の方法として、Abilityクラスのinitializeの引数でcompanyを受け取る方法でも同じことが実現できるように見えます。

```ruby:ability.rb
class Ability
  include Cancan::Ability

  def initialize(user, company: nil)
    can :send_mail, Company if company&.include_hoge?
  end
end
```

この時、controllerは以下のようなかたちで書けて、authorize_resourceも使えるので一見これでも良さそうです。

```ruby:foos_controller.rb
FoosController < < ApplicationController
  before_action :set_current_ability
  authorize_resource class: Company

  def xxx
　　　　　　...（略）
  end

  private

  def set_current_ability
    @current_ability = Ability.new(current_user, @company) # @current_abilityを上書きする。（@companyは別途定義しているものとします）
  end
end
```

ただし、この方法だと、Abilityのインスタンス（current_ability）をその都度生成する必要があり、拡張性に欠けます。
indexページなどでよくある、`@companies.each do |company| ...`のような、ループを回すときに、それぞれのcompanyに対して権限があるかどうかをチェックしたい時に都度Abilityインスタンスを生成することになり、あまり良くありません。
（最初、私はこの方法で実装していたのですがレビューで１番目の方法を教えていただきました。）
azure-functions-core-tools @3 → @4 にバージョンアップしてみました

## 概要

備忘録となります。azure-functions-core-tools を @3 → @4 にバージョンアップしたときの手順です

### 実行環境

macOS Monterey 12.3.1 
python 3.8.12
Azure CLI 2.34.1

### 現在の azure-functions-core-tools

```
$ func -v
3.0.3904
```

### azure-functions-core-tools のバージョンアップ

```
$ brew tap azure/functions
$ brew install azure-functions-core-tools@4
```

以下のメッセージが表示されました

```
==> Downloading https://functionscdn.azureedge.net/public/4.0.3971/Azure.Functions.Cli.osx-x64.4.0.3971.zip
Already downloaded: /Users/ituru/Library/Caches/Homebrew/downloads/f5844b8286814efd53231e309f48565fd8c1d6e34be6b0d6eeec7e864df8ff0b--Azure.Functions.Cli.osx-x64.4.0.3971.zip
==> Installing azure-functions-core-tools@4 from azure/functions

 Telemetry 
 --------- 
 The Azure Functions Core tools collect usage data in order to help us improve your experience.
 The data is anonymous and doesn't include any user specific or personal information. The data is collected by Microsoft.
 
 You can opt-out of telemetry by setting the FUNCTIONS_CORE_TOOLS_TELEMETRY_OPTOUT environment variable to '1' or 'true' using your favorite shell.
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink bin/func
Target /usr/local/bin/func
is a symlink belonging to azure-functions-core-tools@3. You can unlink it:
  brew unlink azure-functions-core-tools@3

To force the link and overwrite all conflicting files:
  brew link --overwrite azure-functions-core-tools@4

To list all files that would be deleted:
  brew link --overwrite --dry-run azure-functions-core-tools@4

Possible conflicting files are:
/usr/local/bin/func -> /usr/local/Cellar/azure-functions-core-tools@3/3.0.3904/bin/func
==> Summary
  /usr/local/Cellar/azure-functions-core-tools@4/4.0.3971: 2,065 files, 312.0MB, built in 9 seconds
```

追加で以下を実行

```
$ brew link --overwrite azure-functions-core-tools@4
```

無事、バージョンアップできました、、、

```
$ func -v                                           
4.0.3971
```

### 参考記事

以下の記事を参考にさせていただきました。
[azure-functions-core-tools 4.0.4736](https://www.npmjs.com/package/azure-functions-core-tools/v/4.0.4736)
[Azure Functions をローカルでコーディングしてテストする](https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-develop-local)
[Azure Functions Core Tools の操作](https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-run-local?tabs=v4%2Cmacos%2Ccsharp%2Cportal%2Cbash)
[Azure Functions ランタイム バージョンをターゲットにする方法](https://docs.microsoft.com/ja-jp/azure/azure-functions/set-runtime-version?tabs=azurecli)
useEffectってなんだ

## はじめに
ふわっ認識していることを調べる。
useEffect編です。
React hookの一つで、レンダーで実行する必要がなくて別で動かしたい処理を書く所のイメージ。

## useEffectとは
React hookの一つ。副作用がある可能性のある処理を受け入れます。useEffectはレンダーが画面に反映された後に動作されるため安全に処理できます。

## 使い方

```tsx
useEffect(() => {
    console.log("run useEffect");
});
```

**第2引数**
第2引数を指定することで、指定した値？変数が変更される場合のみ実行されるようになります。

```tsx
const [number, setNumber] = useState(0)

useEffect(() => {
  console.log("run useEffect");
}, [number]);
```

また第2引数に空配列を渡した場合は、初回レンダリング時のみ実行される形になる。

**実行されるタイミング**

- 第2引数未指定
    - `useEffect(() = console.log('hello'))`
    - レンダー後に毎回呼び出される
- 第2引数に変数
    - `useEffect(() = console.log('hello'), [number])`
    - number変更時に呼び出される
- 第2引数に空配列
    - `useEffect(() = console.log('hello'), [])`
    - 初回レンダー後のみ呼び出される

**返り値(クリーンアップ)**

返り値を指定することで、クリーンアップをすることができます。データフェッチやタイマーなどの変更や中断するために必要になってきます。

```tsx
function App() {
  const [count, setCount] = useState(0);
  const [number, setNumber] = useState(1000);

  useEffect(() => {
    const interval = setInterval(() => {
      setCount((count) => count + 1);
    }, number);
    return () => {
      setCount(0);
      clearInterval(interval);
    };
  }, [number]);

  return (
    <div className="App">
      <h1>Learn useEffect</h1>
      <span>{count}</span>
      <br />
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(Number(e.target.value))}
      ></input>
    </div>
  );
}

export default App;
```

## 所感
クリーンアップの動作がふんわりしていたが、なんとなく掴めたのが大きい。
あとはuseMemoと同じく乱用するべきではなさそうな雰囲気を感じた。一通り試したあとに下の記事を読むと良さそう。

**次に読むと良さそうなもの**

https://beta.reactjs.org/learn/you-might-not-need-an-effect

https://zenn.dev/fujiyama/articles/c26acc641c4e30

## 参考

https://ja.reactjs.org/docs/hooks-reference.html

https://www.youtube.com/watch?v=QQYeipc_cik&
ブランチを切り忘れてmasterで作業してしまった時の対処法を解説！

# はじめに
- うっかりブランチを切り忘れてmasterで作業してしまった、、、。
- 今からでも他のブランチに切り替えたいけど、そんなことできるのかなぁ。
- 下手なことをしてもっと面倒な状況に陥るのだけは避けたいです、、、。

こういった疑問に答えます。

この記事の内容を実践すれば、**わずか3回コマンドを入力するだけ**でmasterから他のブランチに移動することが可能です。

ぼく自身、何度もこの手のミスをしていますが、その度にこの方法で解決しています。

とてもカンタンなので最後までお付き合いくださいませ。

## 注意点
※この記事で紹介する方法は、**masterでコミットしていない前提**です。すでにコミットしてしまっている方は別の方法をお探しください。

## 手順①：変更内容を別の場所に一時保管する

以下のコマンドを打つことでmasterで作業してしまった内容を別の場所に退避させられます。
```
$ git stash
```
気になる方は`git status`コマンドを入力し、作業内容がmasterから無くなっていることを確認しましょう。

## 手順②：使いたいブランチに移動する

次に本来作業したかったブランチに移動しましょう。
作業ブランチを作ってない場合は、このタイミングで作ってOKです。
```
$ git checkout -b 〇〇〇〇
```
## 手順③：一時保管した変更内容を作業ブランチに反映する

退避させた変更内容を手順②で作った作業ブランチに反映させればミッション完了です。
以下のコマンドを実行しましょう。
```
$ git stash apply
```
ここからはいつも通りコミットすればOK。
masterに戻ってやることとかは特にないのでこれで全て終わりです！

# おわりに

ぼくのような初心者にとって、表題の失敗は本当によくあることだと思います！
でもこの記事のとおりにコマンドを叩けば問題ないので安心してください！
参考になれば幸いです。
CSS :has()疑似クラスの汎用性

## :has()疑似クラスの概要
みなさん、CSSの:has()疑似クラスについて追えてますか？
出回っている印象で言えば、**子要素を条件に親要素を選択**ですが、これは正確な表現ではありません。
より正確に表現するならば、**セレクタを条件に要素を選択する機能**です。
より正確に表現したほうが、分かりにくくなりましたね。
実際の例を見てみましょう。
```diff_html
<body>
    <p>はじめまして</p>
    <p>はじめまして、<span>こんにちは</span></p>
</body>
```
```diff_css
/* spanを含むpを選択 */
p:has(span) {
    color: red;
}
/* 直後にpが隣接する場合に選択(つまり直前に隣接するpを選択) */
p:has(+p) {
    color: blue;
}
```
指定した子要素の親要素を選択することは、これまでにできませんでした。
また、指定した要素の直前の要素を選択することもできませんでした。
すごくないですか？
僕はシンプルに興奮しています。
これを利用することによって、この例以外にも、今までできなかったことができるようになるはずです。
この記事では、:has()疑似クラスを用いて、こんなこともできるのではないか、という実験結果をまとめてみます。

## CSS :has()疑似クラスはもう使える？

目新しい機能ではありますが、つい最近のアップデート(Chroe v105)によって、Chromeでは:has()疑似クラスが使えるようになりました。
まだ、すべてのブラウザで利用できるわけではないですが、現時点(2022年9月)では、Safari(mobile/pc)とChrome(pc)で利用できるようです。また、polyfill(JS)によってサポートされていないブラウザも問題なく動作させることができるようです。

![スクリーンショット 2022-08-31 21.01.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821665/a40255e3-0764-1d03-aa3e-3e7d1bea6266.png)

https://caniuse.com/?search=has()

https://github.com/csstools/postcss-plugins/tree/main/plugins/css-has-pseudo

## 今までできなかったけど、できるようになった選択手段
### サンプルhtml
この記事で扱うサンプルは、以下のURLで確認・編集できます。
https://jsbin.com/fuvexejoco/1/edit?html,css,output

```diff_html
<p>para1</p>
<p>para2</p>
<ul class="list1">
  <li>1</li>
  <li>2</li>
</ul>
<ul class="list2">
  <li>1</li>
  <li>2</li>
</ul>
<ul class="list3">
  <li>1</li>
  <li>2</li>
</ul>
<select>
  <option value="1" selected>1</option>
  <option value="2">2</option>
</select>
```
### 以前の兄弟要素を選択
これまでも、指定要素以降の要素を選択することはできましたが、:hasを使うことで、以前の要素も選択できるようになりました。
```diff_css
/* ul以前のpを選択(以降にulを持つpを選択) */
p:has(~ ul) {
    color: red;
}
```

### 直前の要素を選択
同様に、直前の要素も選択できます。
```diff_css
/* ulの直前に隣接するpを選択(直後にulが隣接するｐを選択) */
p:has(+ ul) {
    color: red;
}
```

### n個以上の子を持つ要素を選択
```diff_css
/* .list2が2個以上のliを持つ場合に選択される */
.list1:has(li:nth-of-type(2)){
    background-color: red;
}
```

### 子要素がn個未満の時に選択
```diff_css
/* .list2が3未満のliを持つ場合に選択される */
.list2:not(:has(li:nth-of-type(3))){
    background-color: blue;
}
```

### 任意の数の子要素を持つ親要素を選択
つまり、n個以上n個未満というand検索ですね。
```diff_css
/* .list3が2以上3未満のliを持つ場合に選択される(つまり2つのliを持つ場合) */
.list3:has(li:nth-of-type(2)):not(:has(li:nth-of-type(3))){
    background-color: yellow;
}
```

### formの値によって先祖要素の変数を操作する
```diff_css
:root {
    --bg-color: transparent;
}
p {
	background-color: var(--bg-color);
}
/* selectの値として2が選択された場合に、htmlの変数を変更する */
html:has(option[value="2"]:checked) {
    --bg-color: #ccc;
}
```

## まとめ
いかがでしたでしょうか。
新しい機能(可能性)に触れるということは、興奮を憶えるものです。
ここで紹介した例は、実用的なものではありませんでしたが、次の機会(思いついたら)には実用例を紹介できればと思います。
特に要素数で選択する例は、カラム数によってレイアウトを変更するような場面で使えそうです。
その他、こんな方法もあるよ！というご意見などありましたら、どしどしお寄せください。
お待ちしております。
【Google Sheets API v4】OAuth Client ID を使ったセットアップ(token.jsonの生成まで)

Google Sheets API v4を使うために認証情報を取得する必要があるが、その方法は[3種類](https://developers.google.com/workspace/guides/create-credentials)ある。

API KEY はpublicのスプレッドシートを扱う時に使うよう。
今回はチームで管理するスプレッドシートを扱うのでServiceAccountかOAuthClientIdがよさそう。

ServiceAccountの方が必要な設定はラクだけどServiceAccountを作った時に１回だけダウンロードできる秘密鍵を管理する必要があるので、公式の[quick start](https://developers.google.com/sheets/api/quickstart/nodejs)通り、OAuthClientIdを使う。

# やること
1. credentialの取得
quick start の[prerequisites](https://developers.google.com/sheets/api/quickstart/nodejs#prerequisites)までやる。
OAuthClientIdでcredenctialを作成する時は「デスクトップ アプリ」を選択。
1. token.jsonの取得
    1. プロジェクトディレクトリを作成
    1. 以下を実行
        ```
        npm init -y
        npm install googleapis@105 @google-cloud/local-auth@2.1.0 --save
        ```
    1. index.jsを作成して[sample code](https://developers.google.com/sheets/api/quickstart/nodejs#step_2_set_up_the_sample)をcopy。
    1. index.jsの`SCOPES`を目的の権限に変更。（今回はスプレッドシートの読み書きをしたいので`https://www.googleapis.com/auth/spreadsheets`に変更）
    1. 1.でダウンロードしたものをcredencials.jsonにrenameしてrootに配置
    1. index.jsを実行
        ```
        node index
        ```
    1. token.jsonが生成される。

# まとめ
今回のプロジェクトは[こちら(github)](https://github.com/nkuro3/google-spread-sheet-api)。
読み書きのサンプルコードも軽く載せてます。
```js
// spreadsheet.js

const fs = require('fs').promises;
const path = require('path');
const process = require('process');
const {google} = require('googleapis');
const dotenv = require('dotenv');
dotenv.config();

const TOKEN_PATH = path.join(process.cwd(), 'token.json');

const authorize = async ()  => {
  const content = await fs.readFile(TOKEN_PATH);
  const credentials = JSON.parse(content);
  return google.auth.fromJSON(credentials);
};

authorize().then(async (auth) => {

  // 読み取り
  const sheets = google.sheets({version: 'v4', auth});
  const read = await sheets.spreadsheets.values.get({
    spreadsheetId: process.env.GOOGLE_SHEET_API_SPREADSHEET_ID,
    range: process.env.GOOGLE_SHEET_API_TEST_SHEET,
  });
  const rows = read.data.values;
  console.log(rows);

  // 更新
  rows.push(['update'])
  const update = await sheets.spreadsheets.values.update({
    spreadsheetId: process.env.GOOGLE_SHEET_API_SPREADSHEET_ID,
    range: process.env.GOOGLE_SHEET_API_TEST_SHEET,
    valueInputOption: 'RAW', // RAW/USER_ENTERED
    includeValuesInResponse: true,
    resource : {
      values : rows,
    }
  });
  // resource.valueの値
  console.log(update.data.updatedData.values);

  // 挿入
  const append = await sheets.spreadsheets.values.append({
    spreadsheetId: process.env.GOOGLE_SHEET_API_SPREADSHEET_ID,
    range: process.env.GOOGLE_SHEET_API_TEST_SHEET,
    valueInputOption: 'RAW',
    insertDataOption: 'INSERT_ROWS', // INSERT_ROWS/OVERWRITE
    includeValuesInResponse: true,
    resource : {
      values : [
        ['append']
      ],
    }
  });
  // resource.valueの値
  console.log(append.data.updates.updatedData.values);

}).catch(console.error);
```
[SikuliX] click関数を使いやすくする／独自関数／独自モジュール

SikuliX の `click(【画像】)` は、指定した画像が存在しないとエラー終了します。

```python: test.sikuli
click(【存在しない画像】)
```
↓ 実行結果
```python:
[error] script [ test ] stopped with error in line 1
[error] FindFailed ( 1661949799027.png: (128x39) in R[0,0 1536x1024]@S(0) )
[error] --- Traceback --- error source first
line: module ( function ) statement 
1: main (  <module> )     click("1661949799027.png")
[error] --- Traceback --- end --------------
```

画像の表示がされるまで待機する`wait`関数と組み合わせることで、
`表示されてからクリック`という操作にもできますが、
毎回 `wait`関数と`click`関数を並べて書くのは面倒です。
そこで、__独自関数__を使用します。


----
## 独自関数の定義と`exists`関数の利用

Pythonの独自関数は`def文`を使用します。
また、`wait`関数は__画像が見つかるまで待機し、見つかり次第先に進む__動きですが、
`exists`関数を利用すれば、__見つけた画像の場所を返す__動きを行います。

独自関数名は__予約語や定義済みの関数名と衝突しなければ__自由に使えますが、
ここでは`click2`という独自関数を定義することで、
「①画像が見つけたら」「②クリック」の操作を１行で書くことができるようになります。
```python: sample.sikuli
def click2(img, max_wait=30):
    reg = exists(img, max_wait) # ①画像を見つけたら
    click(reg) # ②クリック

# 使い方
click2(【画像】) # 30秒以内に見つかればクリック
click2(【画像】, 5) # 5秒以内に見つかればクリック
```
画像が見つからない場合、`exists`関数は`None`を返すため、`click(None)`は何もせず終了します。ちなみに引数なしで`click()`と実行すると、画面の中心をクリックするようです。


また、`exists`関数は「__画像の場所 ＝ Region__」を返すので、`Regionクラス`の持つ関数が利用できます。たとえば `highlight`関数を利用すると、次のような書き方ができ、実行速度がほとんど変えずに、`スローモーションで実行`と同じようにクリックする場所をわかりやすく表示させることができます。
便利なのでぜひ使っていただきたい！
```python: sample.sikuli
def click2(img, max_wait=30):
    reg = exists(img, max_wait)
    if reg is None:
        return
    reg.highlightOn()
    click(reg)
    App.highlightAllOff()

# 使い方
click2(【画像】, 5) # 5秒以内に見つかれば__ハイライトして__クリック
```

----
## モジュールの利用
プログラム内に独自関数を定義すれば、そのプログラム内では利用可能ですが、プロジェクト全体で使いたい場合、モジュールとして別に定義しておくと便利です。

SikuliX から `import` する Pythonファイルは、`%APPDATA%\Sikulix\Lib\site-packages` に格納すればパスを意識せず使うことができます。
また、独自モジュールとして分離する場合、`from sikuli import *` と書くことで、`click`関数などのSikuliX標準関数を使うことができます。
独自モジュールを「__custom.py__」という名称にした場合、下記のようになります。

```python: %APPDATA%\Sikulix\Lib\site-packages\custom.py
# -*- coding: utf-8 -*-
from sikuli import *

def click2(img, max_wait=30):
    reg = exists(img, max_wait)
    if reg is None:
        return
    reg.highlightOn()
    click(reg)
    App.highlightAllOff()
```

使い方は下記の通り、さらにスッキリ書けるようになります。独自モジュールは頻繁に修正する可能性があるため、`reload(【独自モジュール】)`を書いておくと変更の反映漏れがなくなって使いやすいです。
```python: sample.sikul
import custom
reload(custom)
from custom import *

click2(【画像】, 5) # 5秒以内に見つかれば__ハイライトして__クリック
```

端末に Python用エディタがない場合など、独自モジュールの作成が大変な場合、
独自モジュールも SikuliX で作成し、作成される`【独自モジュール】.sikuli`フォルダを、__フォルダごと__ `%APPDATA%\Sikulix\Lib\site-packages\` へ配備して使うことも可能です。

```python: %APPDATA%\Sikulix\Lib\site-packages\custom.sikul
# -*- coding: utf-8 -*-

from sikuli import *

def click2(img, max_wait=30):
    reg = exists(img, max_wait)
    if reg is None:
        return
    reg.highlightOn()
    click(reg)
    App.highlightAllOff()
```

こちらの方法だと、`site-packages` フォルダ内に格納されるモジュール類が
`Python標準モジュール` か `独自モジュールか` を管理しやすくなります。


----
## 参考情報

https://qiita.com/nemoplus/items/729257a039b59c6d1520

__動作環境__
* Windows 10
* OpenJDK Runtime Environment Corretto-16.0.1.9.1
* [SikuliX-2.0.5](http://sikulix.com/)
Goの構造体をJSON形式で出力するいくつかの方法

## はじめに

Goの構造体をJSON出力する方法をまとめてみました。

### 検証方法

以下のようなPerson構造体をJSON出力していきます。

```go
type Person struct {
	Name   string
	Age    int
	gender string
}
```

また、JSON出力した結果を見やすくするために、`Mrashal`ではなく`MrashalIndent`を使ってフォーマットしたものを出力するようにしています。

```go:main.go
package main

import (
	"fmt"
	"encoding/json"
)

func main() {
	p := Person{
		Name: "Mike",
		Age:  20,
		gender: "male",
	}

	m, _ := json.MarshalIndent(p,"","    ")
	fmt.Println(string(m))
}
```

## 方法1: そのままMarshalする

まずは、特に何もせずにそのまま出力すると以下のような出力が得られます。

```json:出力結果
{
    "Name": "Mike",
    "Age": 20
}
```

プライベートフィールドである`gender`は出力されず、パブリックフィールドのみ出力されました。
また、出力されたキーにはフィールド名が適応されます。

## 方法2: jsonタグをつけた構造体をMarshalする

Person構造体にjsonタグをつけると、タグに指定した値がキーとして反映されます。

```go
type Person struct {
	Name   string `json:"name"`
	Age    int    `json:"age"`
	gender string `json:"gender"`
}
```

```json:出力結果
{
    "name": "Mike",
    "age": 20
}
```

ちゃんと指定した値がキーとして反映されますが、プライベートフィールドは反映されないです。

## 方法3: Marshalerインターフェースを実装した構造体をMarshalする

では、プログラムとしては`gender`フィールドを外部のパッケージからは参照されたくないが、JSON出力したいとなった場合はどうすればよいでしょうか？

実は、`encoding/json`パッケージには[Marshaler](https://pkg.go.dev/encoding/json#Marshaler)というインターフェースが提供されています。

> ## type Marshaler 
> ```go
> type Marshaler interface {
> 	MarshalJSON() ([]byte, error)
> }
> ```
> Marshaler is the interface implemented by types that can marshal themselves into valid JSON.

Marshalerを実装した構造体に対してMarshalすると、`Marshaler#MarshalJSON()`の実装が適応されます。

例えば、`Person`構造体の各フィールドをプライベートにしてカプセル化して、外部からの参照を避け、その上でそれぞれのフィールドはJSONで出力の対象にしたいとします。

このような時に、`Person`構造体に`MarshalJSON`メソッドを実装することで、柔軟にJSON出力が可能となります。

```go
type Person struct {
	name   string
	Age    int
	gender string
}

func (p Person) MarshalJSON() ([]byte, error) {
	return json.Marshal(struct {
		Name   string `json:"name"`
		Age    int    `json:"age"`
		Gender string `json:"gender"`
	}{
		Name:   p.name,
		Age:    p.age,
		Gender: p.gender,
	})
}
```

```json:出力結果
{
    "name": "Mike",
    "age": 20,
    "gender": "male"
}
```

プライベートなフィールドもちゃんとJSON出力できるようになりました。

## まとめ

基本的に`方法2`を採用して、柔軟にカスタマイズしたい場合は対象の構造体に`Marshaler`を実装すればOK。
【Next.js】詳細ページに遷移した後にリロードすると404になった時の対処方法

# 概要

`next/link`・`next/router`を利用した詳細ページへの遷移時に遷移は成功するが、ページを更新したり別タブで開こうとすると404が発生する事象に遭遇した。
解決まで少し沼ったので解決方法をまとめておく

# 環境
- Next.js v12.1.6

# 対処方法

`trailingSlash`を有効にすることで以下の問題が解決したことで404になる事象が解決したようです。

https://stackoverflow.com/questions/54815348/nextjs-page-goes-to-404-on-refresh

## As Is
`/pages/hoge/index.tsx`が`hoge.html`で書き出される

## To Be

`/pages/hoge/index.tsx`が`/hoge/index.html`で書き出される


```js:next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
    // https://github.com/vercel/next.js/discussions/10522#discussioncomment-28307
    trailingSlash: true, // 追加!
    typescript: {}
};

module.exports = nextConfig;
```