OmniAICreator/Qiita-1.07M huggingface dataset:
タビアンが求めるエンジニアの基準〜フロントエンドの場合〜

![whiteboard-849810_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870510/5b6f2a83-62fc-f558-ea66-6ee7801d906b.jpeg)

こんにちは、タビアン採用担当の金子です。
こちらの記事は、タビアンに興味を持っていただいたエンジニアの方にぜひ読んでもらいたいものです。

タビアンが思い描くエンジニア像と具体的なスキルセットについてお話しています。

あくまでも「タビアンで、フロントエンドエンジニアとして業務を行うための、最低限の基準」を示しているものですが、一採用担当としても **「事業会社や開発会社で、まともにエンジニアとして働く基準としては妥当だなあ」** と感じる内容になっていると思います。ぜひご一読いただければ幸いです。

## タビアンの描くエンジニア像

タビアンは、 **「技術を通して、『つながり』を創る」** ことをミッションとして掲げています。
そして、 **「エンジニアは、システム（サービス）を動かすために必要なことは全て取り組む」** ことをバリュー（行動指針）とし、タビアンでPJTを共にするメンバーは**オールスタックエンジニア**を目指して日々研鑽を行っています。

:::note info
**オールスタックエンジニア**とは、

「エンジニアリングだけではなく、事業企画をサービス化するためのPM/PdMスキル、サービスがエンドユーザーに選ばれ使い続けてもらうためのUIUXスキルを満遍なく習得した、新規事業の実現屋エンジニア」

というタビアン独自の定義です。
:::

そのため、技術を原理と歴史から理解しているエンジニア集団でなければいけない、と考えています。
自らにも、これから新しく仲間になってもらう方にも、エンジニアに求める基準は自然と高いものとなります。

タビアンの利用している技術スタックと、技術力の基準は以下の通りです。

### タビアンの技術スタック
フロントフレームワーク: Vue.js + TypeScript + NuxtJS
UIフレームワーク: Vuetify
サーバサイド: AWS Amplify

### Must =業務で必須で習得していないと仕事にアサインできない技術
- Nuxt.jsでページ・コンポーネントを作成できること
- `emit` を使えること
- `v-model` を理解していること
- `v-bind="boundedVar"` を使えること
- `<slot name="my-slot" v-bind="boundedVar">` と `<template #my-slot="boundedVar">` を使えること
- `watch` を使えること
- `emit('input')` を使えること
- Nuxt.jsのstoreでモジュールを作成できること
- 基本的なTypeScriptの読み書きができること
- `const value: any` のように、`any` 型を使わないで書けること

### Want =業務で必要とされるが業務開始後の習得でも間に合う技術
- `type MyCustomType` や `interface MyInterface` の型定義ができること

## カルチャーフィットについて

基準を厳しく決めている一方で、タビアンはカルチャーフィットも大事にしています。

たとえば、エンジニアリングを行う上で、現在の技術力がいくら高くても、コミュニケーションのスタイルがチームメンバーと合わなかったら一緒には働けないと考えています。
反対に、技術力が基準に達していなくても、一定の研修期間を置いてからプロジェクトに入ってもらうことも可能です（真摯に技術に向き合う姿勢、かつ基礎的な技術力は必要です）。

### オールスタックエンジニアへの理解と共感

また、前述したオールスタックエンジニアの考え方に対する理解と共感は必須条件といえます。

タビアンでは、ジュニアエンジニアや参画したての方については、本記事のようにフロントエンド主体で業務を行っていただくことが多いです。
しかしながら、早い段階でフルスタックエンジニアリングを活用する方向へシフトしてほしいですし、ソフトウェア工学や事業企画を実現するためのビジネススキルやUIUXスキルの習得にも励んでいただくことを期待しています。

**「しばらくはフロントエンド一本で仕事をしたい」「バックエンド以外はやりたくない」「コードだけ書いていたい」** といった、少々硬直的なエンジニア観をお持ちの方はなかなか活躍しづらい環境と言えます。
一方で、 **「将来起業をしたい」「自分が中心となって事業を立ち上げたい」「スタートアップの1桁メンバーとして参画したい」** など、チームで新しいサービスや事業を作る時にエンジニアリングを軸とした中心人物としてコミットをしたい(そして何でもやる！)といった柔軟性が必要とされる考えをお持ちの方がフィットしますし、参画いただく本人にとっても得るものが大きいと考えています。

## さいごに

この基準を見て、疑問がある、物申したい、もっとVueが書けるようになりたい、オールスタックエンジニア最高！など…
何か感じた方、ぜひ一度当社メンバーとお話ししましょう！

また、ネットワークエンジニアからフルスタックエンジニアになった人、AWS Summit登壇経験のあるインフラの人、画像認識を研究している大学院生、他社CTOをやっていたが代表難波に惹き付けられ参画した人などなど、色んなエンジニアが働いています。

一緒に働いてみたいというエンジニアメンバーも絶賛募集中ですので、ぜひ以下URLから募集状況をチェックしてみてください！お話できることを楽しみにしています！

https://www.wantedly.com/projects/1319283

https://www.wantedly.com/projects/1648417

https://www.wantedly.com/projects/1692870
supabaseで登録時にフォームに入力した内容が画面に表示されない事象について

# 問題の原因
* フォームに入力して登録を行ったデータのみが配列の中のオブジェクトに格納されていたため。

# 今回の事象
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/8041bfe8-7126-ff8b-f174-33d1f90d54ca.png)
※上記３つはデータベースから取得したデータです。
※一番最後の時間だけ表示されている箇所

# 問題の箇所
```App.jsx
 const { data, error } = await supabase
          .from("study-record")
          .insert({ content: inputs.content, time: parseInt(inputs.time, 10) })
          .select()
```
# 解決方法
* 配列を返すのではなく１行のオブジェクトを返すようにする。
* supabaseの.single()を使用する。

# 登録時に入力した内容が表示されたときのコード・実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/b4b0c573-91d2-9a01-dfc6-57103bacf826.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/9807875b-c71a-f50b-fd9f-83fc949d45cb.png)

```App.jsx
const { data, error } = await supabase
          .from("study-record")
          .insert({ content: inputs.content, time: parseInt(inputs.time, 10) })
          .select().single()
```
# 参照したドキュメント
* supabase公式ドキュメント:1行のデータを取得するという箇所を参照
* URL:https://supabase.com/docs/reference/javascript/single
よく使うGitの便利なコマンドたち

## Gitのコマンド集
タイトルの通り、よく使う便利なGitコマンドをまとめました。

### add編
#### 初回
- git init直後の全てのファイルのgit addを取り消す
```git
git rm --cached -r .
```

- git init直後の特定のファイルのgit addを取り消す
```git
git rm --cached -r [ファイル名]
```

#### 2回目以降
- 全てのファイルのgit addを取り消す
```git 
git reset HEAD
```

- 特定のファイルのgit addを取り消す
```git 
git reset HEAD [ファイル名]
```

### commit編
- 1度でもaddしているファイルを対象にaddとcommitを同時に行う
```git
git commit -am 'コメント'
```

- コミットしてしまった状態を元に戻す。HEAD^は直前のコミットを表している。git logで出力したコミットIDを指定することも可能
```git
git reset HEAD^ --hard
```

- 直前のコミットメッセージを変更する
```git
git commit --amend -m "変更したいメッセージ"
```

### push編
- 間違えてpushした時に、間違えたコミットIDを指定することで打ち消すことが可能。コミットが無かった状態にローカルリポジトリが戻るので、そのうえでpushすることでリモートブランチにも反映することができる
```git
git revert [コミットID] --no-edit
```

### log編
- ログを見やすく表示する
```git
git log --all --graph
```

### tag編
- コミットに対してタグを付与することができる。コミットIDを指定しない場合、直前のコミットが指定される

```git
git tag [タグ名] [コミットID]
```

- 指定したタグを削除することができる
```git
git tag -d [タグ名]
```

- 指定したタグのコミットログを確認することができる。qキーで脱出可能
```git
git show [タグ名]
```

### stash編
- 現在stashしている内容の一覧を確認する
```git
git stash list
```

- ステージングしていないファイルを対象にstashする
```git
git stash save '作業途中のコメント' -u
```

- stashした内容を適用する。stash@{0}のstash番号はstash listで確認することができる
```git
git stash apply 'stash@{0}'
```

-stashを削除する。特定のstashを指定しない場合、最新のstashが削除される
```git
git stash drop 'stash@{0}'
```

### branch編
- 新しいブランチ名に名前を変更する
```git
git branch -m [現在のブランチ名] [新しいブランチ名]
```


## 最後に
随時更新中です。
最後まで見ていただきありがとうございました！
【SwiftUI】アニメーション State 付きの Button の作り方


Apple 公式チュートリアルから引用。

```swift
Button {
  showDetail.toggle()
} label: {
  Label("Graph", systemImage: "chevron.right.circle")
    .labelStyle(.iconOnly)
    .imageScale(.large)
    .rotationEffect(.degrees(showDetail ? 90 : 0))
    .animation(nil, value: showDetail)
    .scaleEffect(showDetail ? 1.5 : 1)
    .padding()
    .animation(.spring(), value: showDetail)
 }
 ```
 https://developer.apple.com/tutorials/SwiftUI/animating-views-and-transitions

アニメーションとエフェクトの関係を考えればいろいろ書けますよね。

以下、微妙な差があったりなかったりするの見えますか。

![sc 2024-08-26 at 1.17.29.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588914/15ad6bd7-5577-c262-b6dc-6cb4706c2ec1.gif)

詳細コードは以下から。

https://android.benigumo.com/20240826/state-button/

animation, effect, withAnimation の順序と多くの引数。

いろいろな記述が考えられます。

どこまでこだわるか。

どれだけシンプルに書くか。

https://x.com/maochanz/status/1826954096848630014
ClerkでOrganizationProfileを使用したら出たエラーとその解決方法

### エラー内容
```
Error: 
Clerk: The <OrganizationProfile/> component is not configured correctly. The most likely reasons for this error are:

1. The "/organization/org_2kakdkCNc04Ds5H3vyWcrChCr63/settings" route is not a catch-all route.
It is recommended to convert this route to a catch-all route, eg: "/organization/org_2kakdkCNc04Ds5H3vyWcrChCr63/settings/[[...rest]]/page.tsx". Alternatively, you can update the <OrganizationProfile/> component to use hash-based routing by setting the "routing" prop to "hash".

2. The <OrganizationProfile/> component is mounted in a catch-all route, but all routes under "/organization/org_2kakdkCNc04Ds5H3vyWcrChCr63/settings" are protected by the middleware.
To resolve this, ensure that the middleware does not protect the catch-all route or any of its children. If you are using the "createRouteMatcher" helper, consider adding "(.*)" to the end of the route pattern, eg: "/organization/org_2kakdkCNc04Ds5H3vyWcrChCr63/settings(.*)". For more information, see: https://clerk.com/docs/references/nextjs/clerk-middleware#create-route-matcher
```

### 原因
Catch-allルートが設定されていないのが原因らしい。

### やったこと
[[...rest]]フォルダを作成し、その配下にエラーが出てるファイルを移動させた。
setteing/[[...rest]]/page.tsx
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3527006/9460ebb0-d166-91a0-517e-2e1c28ca7e86.png)


### 結果
エラーが解消され、メンバー情報が見れるようになった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3527006/cf16e84a-8aed-5ed2-37b2-262dc5847df7.png)
TryHackMe WriteUp：Blueprint


# Task1: Blueprint

まさかのお題は２つのみ


## root.txt

順番は逆だが、先にとけたのでこちらから記載

といいつつ、いろいろWriteupを調べてみましたが、どれもうまくいかず。。。

どのWriteupでも`searchexploit oscommerce`の結果から44374.pyを選んでいたが、これがうまくいかなかったので、おそらく新しい方だと思われる50128.pyを選んだところうまくいきました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2152468/9202abe9-5bb4-f912-f846-3b675a30be0e.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2152468/66a2b107-9b38-a36e-be84-0b419260fb97.png)


root.txtは以下にありました！
```
RCE_SHELL$ type C:\Users\Administrator\Desktop\root.txt.txt
<br />
<b>Notice</b>:  Undefined index: cmd in <b>C:\xampp\htdocs\oscommerce-2.3.4\catalog\install\includes\configure.php</b> on line <b>27</b><br />
THM{XXXXXXXXXXX}
```

次はユーザー名`LAB`のパスワードを入手しないといけない

以下のWriteupの内容をもとに実施しました！
https://github.com/kimignacio/TryHackMe-Writeups/issues/2

## "Lab" user NTLM hash decrypted

流れは以下になります

1. 攻撃対象端末でレジストリ値を保存
1. SMBで攻撃対象のフォルダをマウント
1. マウントしたフォルダ**C:\Users**に1で保存したファイルをコピー
1. ローカルから3のファイルを別フォルダーにコピー
1. impacket-secretsdumpでハッシュ値を抜き出す
1. Crack Stationに入れて解析する


それぞれ（つまづいたところを）詳細に説明していきます。。

### 1. 攻撃対象端末でレジストリ値を保存

以下のコマンドでSAMとSYSTEMのレジストリ値をテキストファイルで保存
```
reg save HKLM\SAM sam.txt
```
```
reg save HKLM\SYSTEM system.txt
```

このテキストファイルで保存することが重要で、参考にしたWriteupだと.saveで保存していたが、この拡張子だとローカルからSMBでマウントしたフォルダを確認しても、ファイルが表示されなかった。。。
てか、初めてみたよ、、.saveなんていう拡張子（初心者）


### 2. SMBで攻撃対象のフォルダをマウント

nmapのポートスキャンでSMBのポート番号445が開いていたので、
`smbmap -H 10.10.22.253 -u user  `でSMBが使えるか確認したところ、`Users`というユーザーがRead Onlyで使えそう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2152468/a0dde8e9-26c3-d2e0-488f-01b1bd085598.png)


ローカルの好きなところにフォルダを作成して、以下コマンドでマウントを実行
```
sudo mount -t cifs //10.10.22.253/Users mount -o username=guest
```




### 3. マウントしたフォルダ**C:\Users**に1で保存したファイルをコピー

**コピー**。。。これが重要でした。。。
攻撃対象端末はWindowsなのでcopyコマンドでコピーできるのですが、これをmoveコマンドで実行しても対象端末内で移動はさせれますが、ローカルからは確認できなかったです。。
権限か何かでしょうか。。。。


### 4. ローカルから3のファイルを別フォルダーにコピー
これは作業用に抜き出すだけです。sam.txtとsystem.txtは同じフォルダーに入れてください

### 5. impacket-secretsdumpでハッシュ値を抜き出す
以下のコマンドでUserとHash値を抽出します
```
sudo impacket-secretsdump -sam sam.txt -system system.txt local
```

少しだけ補足すると、SAM ファイルには以下の情報が含まれています:

- ユーザーアカウントの情報（名前、SID）
- 暗号化されたパスワードのハッシュ（LM と NTLM）

そして、パスワードのハッシュ値の暗号化を解除するキーがHKLM\SYSTEMに格納されているので、この二つの情報からユーザー名とパスワードのハッシュ値を抽出することができます！


### 6. Crack Stationに入れて解析する
得られたHash値をCrack Stationに入れて復号します。
コロンで区切られているので、全部分けて入力してくださいね（最初気が付かなかった(-_-;)）
Crack Station：https://crackstation.net/

## さいごに
いや、結構しんどかった。。。
設問は少なくてガイドの役割を果たしていなかったし、そのせいもあってかWriteupにはいろいろなやり方が記載されていて、うーんんという感じだった（しかもどれもうまくいかない( ；∀；)）

我慢強くいろいろ試していくことが重要なんだと身に染みた問題でした。。
翻訳レビュー体験記: スタッフエンジニアの道

# Summary
本日発売された、[スタッフエンジニアの道〜優れた技術専門職になるためのガイド〜](https://amzn.asia/d/dtrWz03)の英語版から日本語版への翻訳レビューに参加した際の経験を簡単にまとめました。
誰かの挑戦を後押しすることに繋がると嬉しいです。

# Who
[わたし](https://inside.dmm.com/entry/2020/08/06/yondemasu07)は、[合同会社DMM.com](https://dmm-corp.com/company/)で同人事業のエンジニアリングマネジメントに携わっています。
英語が特別に得意な訳では無く、翻訳のレビューに携わった経験は[カンバンガイド](https://kanbanguides.org/)のみでした。
[カンバンガイドの翻訳レビュー体験記も過去に書いています](https://qiita.com/umerin/items/e2b29750d77c32fbfc9e)ので、ご興味がある方はご参考ください。

# What
無償のボランティア(*)として、[The Staff Engineer's Path](https://amzn.asia/d/82TZ2Qh)の英語版から日本語版への翻訳レビューに参加させて頂きました。
*：書籍の実物を発売前にご恵贈は頂いております。

# Why
Xのタイムラインに以下のツイートが流れてきました。

https://x.com/snoozer05/status/1758637552893034594?s=46&t=19W031YjRX4_M8Fu1fkmsg

実は、島田さんのことをXでは当時まだフォロー出来ていなかったのですが、他にフォローしていた方のいいねによりタイムラインで偶然発見し、先着順になりうると思いすぐに対象のGoogleフォームから応募しました。
※案の定、最大1週間程度を想定されていた募集期間は、翌日には応募多数のため締め切られていた様子です。

具体的な原本は応募時点では不明なものの、島田さんが翻訳された本は何冊か自身でも持っており、特にエラスティックリーダーシップは何度も読んでいたので、勝手に親近感を持っていました。

また、募集されていた24年2月中旬の時期は、自身がテックリードやスタッフエンジニアなどのスペシャリスト軸のスキル評価やキャリアパス構築をどのようにしていくかを悩んでいた時期でもあったので、「上級技術リーダーの役割やあり方に関する翻訳書籍」という文言に凄く惹かれたことを強く覚えています。

# How
対象のGoogleフォームに必要事項を記入し応募しました。
面識が無いため、所属会社など身元が分かる情報とカンバンガイドの翻訳レビュー経験を付記しました。
仮に応募者が多数だと先着順もあり得ると考え、ポストを目にしてからすぐに応募しました（確かツイートされてから1時間以内くらい）。

# 翻訳レビュー
翻訳者の島田さんから期待されていたことは「用語や表現などが想定対象読者層にとって、理解できるものであるかを確かめたい。読者が読んでいて引っかかった、理解しづらかった点を明らかにしたい」という観点でした。

最終的にはGitHubのIssueに起票していく形ですが、文章のチェック方法は自由なため、以下の形で工夫しました。

* 指定された期間内に余裕を持って完了できるように、数ページ実際にレビューし自身のレビュースピード（Issue起票含む）を測った上で全体量を見積もり、1日のペース配分を逆算し計画する
* 翻訳文を全て音読する（これが一番誤字脱字や修飾語などの違和感を見つけ易い）
* (意訳の場合) 表現の違いが意図的な意訳であるかをGoogle検索する
* 馴染みの薄い日本語だった場合に別の辞書で翻訳の候補を探す
* URLリンクとなっている箇所は、リンク切れやリンク先の誤りが無いか実際にアクセスしてみる
* 日本語訳に何らかの違和感を感じた場合は、原文を比較する（そのために原著 The Staff Engineer's Path をペーパーバックで購入し手元でいつでも参照できる状態にしておく）
* 誤字脱字は自身が気になってしまうので、集中力を切らさないことを意識しつつもIssue起票はする

※カンバンガイドの翻訳レビューに参加した際は英語原文も全部音読していたのですが、今回は量があまりにも多いので早々に諦めました。

また、指摘コメントを書く際には以下の点に気をつけました。

* 敬意と礼儀を重んじる（断定しすぎたり強い主張は控える）
* 自らが誤って解釈したり読み違えていないか改めて確認する
* どの箇所に対する指摘なのかが一目で分かりやすい表現にする
* たまに感想も積極的にフィードバックする（激励の意味も込めて）

# Fun
すでに翻訳が完了した書籍を見るだけでは分からない、翻訳者の苦労（どの部分で翻訳を悩んだか、候補はあったが不採用にしたなど）が分かった事、他のレビューアの観点/指摘をリアルタイムで拝見できたことが楽しかったです。

# Done
訳注を含め全ページをレビュー。3/3〜3/29までの間で、合計レビュー時間が約45時間、合計100件ほどIssue起票させて頂きました。

特に印象深いのは、P241の銀河ヒッチハイク・ガイドの引用箇所を安原和見=訳の原文そのままに変えて（訳書に合わせるようにして）頂いたことです。
たまたま今年の1月に銀河ヒッチハイク・ガイドを読んだばかりだったので、セレンディピティを感じました。

# Learn
* 自身が知らない用語は、調べた際に別の類似した用語と誤解する場合があるので、類似した用語の存在も合わせて確認できるとなお良い

# Appendix
翻訳者の島田さんが本書の位置付けについて記事を書かれています。
https://snoozer05.hatenablog.jp/entry/the-staff-engineers-path
類似する本を既にお持ちの方は差分が気になると思いますので、ご参考まで。
【AWS】utf8mb4で「????」が表示された時はskip-character-set-client-handshakeも確認する

# 概要
RDSのパラメータグループで、文字セットをutf8mb4にしたのに、4バイト文字を連携すると「????」と表示されてしまいました。
解決方法を紹介します。

# 前提とエラー内容

RDSのエンジンバージョンについては、Aurora3のmysql8.0を利用。
Clusterのパラメータグループにて、以下はすべてutf8mb4にしました。

```
character_set_client
character_set_connection
character_set_database
character_set_filesystem
character_set_results
character_set_server
```

RDSデータベースの方を確認しても、DB自体やテーブルもそれぞれutf8mb4になっていました。

ここでアプリを通して4バイトの特殊文字などを連携すると「????」と返されてしまいます。

4バイト文字とは、絵文字や一部の旧字体などが該当し、utf8mb4文字セットではこれらを含むすべてのUnicode文字をサポートしています。本来ならば、正常に表示されるべきです。


# 解決方法

原因は、パラメータグループの`skip-character-set-client-handshake`にありました。
公式ドキュメントはこちら。

https://dev.mysql.com/doc/refman/8.0/ja/server-options.html

> クライアントによって送信された文字セット情報を無視しません。 クライアント情報を無視して、サーバーのデフォルトの文字セットを使用するには、--skip-character-set-client-handshake を使用します。これにより、MySQL は MySQL 4.0. のように動作します。

ここがデフォルトのままだと「-」と表示されており、これだと、Mysqlサーバはクライアントから送信された文字セット情報を無視し、サーバー側のデフォルト文字セットを使用する、という意味になります。

これが原因で、クライアントとサーバ間で文字セットの不一致が発生し、4バイト文字（絵文字や一部の旧字体など）が正しく処理されず、「????」と表示されたと考えられます。

そこで、この値を`1`にすると、サーバはクライアントから送信された文字セット情報を認識し、クライアントとサーバ間で文字セットが一致するようになりました。結果、旧字体も正常に出力されるようになりました。
[Memory] メモリの種類

# 一覧
|RAM<br>揮発性|||
|:--|:--|:--|
|SRAM|高速・低消費電力<br>フリップフロップを用いる|キャッシュメモリ|
|DRAM|高容量・低価格|主記憶装置|



|ROM<br>不揮発性|||
|:--|:--|:--|
|EPROM|電気的に書き換え可能紫外線照射でデータ消去|PC|
|EEPROM|電気的にデータの書き込み・消去|PC|
|フラッシュメモリ|高速・高集積|スマホ・デジカメ|
|マスクROM|製造時にデータが書き込まれる<br>読み出し専用・書き換え不可|辞書・電卓|

# 参考リンク
- [半導体メモリとは何か？種類と特徴まとめ](https://semi-journal.jp/basics/device/memory/variety.html)
- [R2A20_DRAM](https://www.ap-siken.com/kakomon/25_aki/q22.html)
- [R4A22_フラッシュメモリ](https://www.ap-siken.com/kakomon/04_aki/q22.html)
- [R5S11_ウェアレべリング](https://www.ap-siken.com/kakomon/05_haru/q11.html)
PHPのjson_decode()はデコードに失敗した場合nullを返す

調べればすぐだったのに、勘違いにより1時間くらい無駄にしたので備忘のために残します。
悔しい。

## サクッと理解したい人

参考記事：https://www.php.net/manual/ja/function.json-decode.php

:::note info
json のデコードに失敗したり エンコードされたデータがネストの最大値を超えているなどの場合、null を返します。
:::

てっきりエラーが表示されるのかと思ってました。
デコードに失敗した時はエラーではなくnullが返ります。

## デコードってなに

（デコードとエンコードいつもわからなくなっちゃう）

デコードとは、JSONをオブジェクトに変換することです。
逆にエンコードは値をJSON形式に変換することです。

## 今回失敗したパターン

今回、デコードするために渡したJSONが**ダブルクォーテーションで囲われていない**値があり、デコードに失敗しnullとなっていました。

```PHP:失敗例

<?php
$json = '{ hoge: "hoge" }';

var_dump(json_decode($json)); // null

?>
```


```PHP:成功例

<?php
$json = '{ "hoge": "hoge" }';

var_dump(json_decode($json));
?>
```

## その他の間違い例

シングルクォートはNG

```PHP:シングルクォートはNG

<?php
$json = '{ 'hoge': 'hoge' }';

var_dump(json_decode($json)); // null

?>
```

最後にカンマをつけるのはNG

```PHP:最後にカンマをつけるのはNG

<?php
$json = '{ "hoge": "hoge", }';

var_dump(json_decode($json)); // null

?>
```

## 最後に

なんでエラー出るって思っちゃってたんですかね
null = 値が取れてないみたいな固定概念無くします。反省。

反省したところで、、、最後に弊社の紹介をさせてください。

https://prum.jp/

ペーペーながら、わたくしも面接にも参加させてもらってます。
ご興味ある方、ぜひお話しさせてください。

https://www.wantedly.com/projects/1636998
Document、NodeList、HTMLElementオブジェクト JavaScript

## Documentオブジェクト
windowオブジェクトのプロパティの1つ
HTML要素を抽象化したもので
タグや属性にアクセスするプロパティを持つ。

DOM：Document Object Model
HTMLの文書構造をオブジェクトの集まりとしてみなす考え方のこと

## 主要プロパティ
head要素を返す
```
document.head
```
body要素を返す
```
document.body
```
ページのタイトルを返す
```
document.title
```
ページのURLを返す
```
document.URL
```
現在のページのひとつ前のURLを返す
```
document.referrer
```
クッキーの内容を返す
```
document.cookie
```

例)
```console
console.log(document.head);
// -> <head>...</head>

```
```
console.log(document.URL);
// -> https://qiita.com/
```

## 主要メソッド

文書全体から引数で指定したCSSセレクターに
一致する最初の要素を取得して返す。
戻り値はNodeListオブジェクト
```
document.querySelector("CSSセレクター")
```
一致するすべての要素を取得して返す
戻り値はNodeListオブジェクト
```
document.querySelectorAll("CSSセレクター")
```

例)
最初のh1要素を変数hに取得
```JavaScript
let h=document.querySelector("h1");
```

HTMLで指定したID属性comTotal要素のテキストに
getTotalメソッドで取得した値を入れる
※ID属性は#をつける
```JavaScript
document.querySelector("#comTotal").innerText=getTotal(comCards);
```

## NodeListオブジェクト
DOMのオブジェクトを配列のようにまとめたもの
ノードの個数を表すlengthプロパティがある。

例)
aタグの要素すべて（リンク）をlinksに取得
```JavaScript
let links=document.querySelectorAll("a");
```
ノードをすべて出力
```JavaScript
for(let i=0;i<links.length;i++){
	console.log(links.item(i));
}
```
配列と同じで要素番号は0からなので
0番目から、linksの要素数まで繰り返すことで
要素すべてを出力できる。
itemメソッドに引数で番号を指定してリストの中身が取り出せる。

## HTMLElementオブジェクト
Element:要素

## 主要プロパティ

要素のID属性を返す・設定する
```
id
```

要素内のHTMLを文字列で返す・設定する
```
innerHTML
```
要素のタグを含むHTMLを文字列で返す・設定する
```
outerHTML
```
要素内のテキストを文字列で返す・設定する
```
innnerText
```
要素内部の高さ
```
clientHeight
```
要素内部の幅
```
clientWidth
```
直前の要素を返す
```
nextElementSibling
```
直後の要素を返す
previous：先の
Sibling：兄弟
```
previousElementSibling
```
要素の最初の子要素を返す
```
firstElementChild
```
要素の最後の子要素を返す
```
lastElementChild
```

#### 例)tableの要素を変数tbに入れる
```console
let tb=document.querySelector("table");
```

①プロパティfirstElementChildにより
tableの最初の要素を返す
```console
console.log(tb.firstElementChild);
// -> <tbody>...</tbody>
```
tbody：table本体の要素のこと

②プロパティinnerHTMLにより
table内のHTMLを返す
```console
console.log(tb.innerHTML);
// -> <tbody><tr>省略</tr></tbody>
```

③プロパティouterHTMLにより
tableタグ含むtable内のHTMLを返す
```console
console.log(tb.outerHTML);
// -> <table><tbody><tr>省略</tr></tbody><table>
```
④innerTextを用いてID属性myTotalの要素に10をセット
セットする値が文字列の時は""で囲む
```
document.querySelector("#myTotal").innerText=10;
```

## 主要メソッド

属性keyの値を返す
```
getAttribute(key)
```

属性keyに値valueを設定
```
setAttribute(key,value)
```

子孫ノードから、引数で指定したCSSセレクタに一致する
最初の要素を取得して返す
```
querySelector(selector)
```
子孫ノードから、引数で指定したCSSセレクタに一致する
すべての要素を取得して返す
```
querySelectorAll(selector)
```
先祖ノードから引数に指定したCSSセレクタに該当する
最も近い位置にある要素を返す
```
closest(selector)
```
引数に指定したノードを子ノードの最後に追加
```
appendChild(node)
```
引数に指定したノードを直前に指定する
```
insertBefore(node)
```
引数に指定したノードを子ノードから削除
```
removeChild(node)
```
要素のイベントを扱うハンドラを登録する
```
addEventListener(event,handler)
```

例)
windowオブジェクトのloadイベント
ページの読み込みが完了したとき、newView関数を実行
```JavaScript
window.addEventListener("load",newView);
```

ボタンをclickしたとき、clickReset関数を実行
(ボタンにID属性resetを設定)、
```JavaScript
document.querySelector("#reset").addEventListener("click",clickReset);
```

## 参考書籍
https://www.amazon.co.jp/図解！-JavaScriptのツボとコツがゼッタイにわかる本-“超”入門編-中田亨-ebook/dp/B08ZHVJVHB
windowオブジェクト JavaScript

## windowオブジェクト

ブラウザのウィンドウそのものをあらわす。
ウィンドウの生成と同時にwindowという
グローバル変数が生成されるのでインスタンス化不要。
window.は省略できる。
```
console.log(document.title);
// -> 現在のページのタイトルが出力
```

## 内部オブジェクト
コンテンツのHTML文書
```
window.document
```
ブラウザの情報
```
window.navigator
```
現在のHTML文書のアドレス
```
window.location
```
ウィンドウに関連付けられたスクリーン
```
window.screen
```
ブラウザの閲覧履歴
```
window.history
```
ブラウザのコンソール
```
window.console
```

#### 上記オブジェクトの主要プロパティとメソッド
ブラウザのベンター名を返す
```
navigator.vendor
```
ユーザーのプラットホーム名を返す
```
navigator.platform
```
ブラウザのバージョン情報を返す
```
navigator.userAgent
```
現在のページのURL取得
またはこのプロパティに代入したURLに移動
```
location.href
```
現在のページをリロード
```
location.reload()
```
URLで指定したページに移動
```
location.replace(url)
```
画面の高さをピクセル数で返す
```
screen.height
```
画面の幅をピクセル数で返す
```
screen.width
```
ひとつ前に表示していたページに移動
```
history.back()
```
ひとつ先のページに移動
```
history.forward()
```
nで指定した数履歴をたどってページを移動
```
history.go(n)
```
## ダイアログを表示するメソッド
OKボタンのみ
```
alert("表示文字列")
```
OK・キャンセルボタン
戻り値としてOKはtrue、キャンセルはfalseを返す
```
confirm("表示文字列")
```
入力欄とOK・キャンセルボタン
戻り値として文字が入力されOKなら入力文字
入力なしでOKなら''、キャンセルならnull
```
prompt("表示文字列"[,デフォルト値の指定])
```

## タイマー機能をもつメソッド
何秒後に実行という指定ができる。

指定秒後に関数実行
```
setTimeout(実行関数,ミリ秒数[,指定関数の引数])
```
停止
```
clearTimeout(タイマー番号)
```
指定秒ごとに関数を実行、繰り返す
```
setInterval(実行関数,ミリ秒数[,指定関数の引数])
```
停止
```
clearInterval(タイマー番号)
```

例)リザルト画面に表示する関数を1秒後に呼び出し
```JavaScript
                 //実行関数、1秒、引数
window.setTimeout(showResult,1000,result);
```
例)タイマーを停止するためタイマー番号を指定する
```JavaScript
                            //実行関数,1時間ごと
const timerA=setTimeInterval(showView,1000*60*60);
clearInterval(timerA);
```

## 参考書籍
https://www.amazon.co.jp/図解！-JavaScriptのツボとコツがゼッタイにわかる本-“超”入門編-中田亨-ebook/dp/B08ZHVJVHB
Mathオブジェクト JavaScript

## 数値オブジェクト
・インスタンス化しないで使用できる
・Math.を使用

## 円周率
```
Math.PI
```

## 単数を処理するメソッド
小数点以下切り上げ
```
Math.ceil(x)
```

切り捨て
```
Math.floor(x)
```

四捨五入
```
Math.round(x)
```

引数の絶対値を求めるメソッド
```
Math.abs(x)
```

最大値・最小値
```
Math.max(x,x1,,,)
Math.min(x,x1,,,)
```

## 乱数を出力
0～a（aの値は含まない）を返す。
```
Math.random()
```
```
function getnum(a){
    let ransu =Math.random()*(a+1);
    return Math.floor(ransu);
}
```
10までの数字がランダムに出力
```
console.log(getnum(10));
//-> 8
```

## 参考書籍
https://www.amazon.co.jp/図解！-JavaScriptのツボとコツがゼッタイにわかる本-“超”入門編-中田亨-ebook/dp/B08ZHVJVHB
STATSPACKレポート取得のためのスクリプト

## はじめに

Statspackレポートが必要になったときに、毎回DBに接続してspreport.sqlを
実行するのも面倒なので、取得のタイミングと合わせて1時間に1回バッチ処理で
レポートを生成させることにしました。

参考にした記事は[STATSPACKレポートを全部一気に出力するスクリプト](https://yohei-a.hatenablog.jp/entry/20090825/1251173502)です。

この記事を読んだおかげで、spreport.sql は内部で sprepins.sql を呼んでいること、
sprepins.sql 実行時に3つの置換変数 begin_snap、end_snap、report_name の入力が
求められることを理解できましたが、いくつか注意点が見つかりました。

## 注意点①：SQL*Plusはサイレントモードで起動する

まず、レポート取得用のSTATSREPORT.sql（後述）をキックするバッチファイルですが、
SQL*Plusは-sを付けてサイレントモードで起動するといいです。
こうすることで、後述するstats.sqlの中に不要な文字列が含まれるのを防ぐことができます。

```batch:oracle_statspack_report.cmd
(略)
sqlplus -s /nolog @D:\basis_scripts\conf\STATSREPORT.sql
(略)
```

## 注意点②：STATSPACKスナップショットのidは1ずつ増えるとは限らない

上記の参考記事ではSTATSPACKスナップショットのidが1ずつ増えることを
前提にしていますが、実際には連続したスナップショットでもidが2増えたり
3増えたりすることがあります。

以上を踏まえると、select文のoffset n rows fetch first n rows onlyを活用して
下記のように書くのが良いかと思います。
なお、ASCIIコードの10は改行なので、chr(10)は改行を意味しています。

```plsql:STATSREPORT.sql
connect / as sysdba
whenever sqlerror exit sql.sqlcode

set echo off
set feedback off
set heading off
spool D:\oradata\STATS_REPORT\stats.sql

 -- 最新のひとつ前のidを置換変数 begin_snap に代入する

 select
 'define begin_snap='  || SNAP_ID      || chr(10)
 from stats$snapshot order by snap_id desc offset 1 rows fetch first 1 rows only; 

 -- 最新のidを置換変数 end_snap に代入する
 
 select
 'define end_snap='    || SNAP_ID			|| chr(10) ||
 'define report_name=' || 'D:\oradata\STATS_REPORT\'	|| SNAP_ID      || '.lst'  || chr(10) ||
 '@D:\oracle\product\19.3.0\dbhome_1\rdbms\admin\spreport.sql' || chr(10)
 from stats$snapshot order by snap_id desc fetch first 1 rows only;
 
spool off
@D:\oradata\STATS_REPORT\stats.sql

exit
```

以上を実行すると、下記のstats.sqlが実行されてレポートが取得されるという仕組みです。

```plsql:stats.sql
-- 空白行はご愛嬌
define begin_snap=17843                                                         

define end_snap=17844                                                           
define report_name=D:\oradata\STATS_REPORT\17844.lst                            
@D:\oracle\product\19.3.0\dbhome_1\rdbms\admin\spreport.sql        
```

## おわりに

なお、上記バッチファイル oracle_statspack_report.cmd は1時間に1回 JP1 でキックし、
7日分たまったら同様に JP1 で削除用ジョブをキックして消しています。

ディスク枯渇の心配もないので安心ですね。
Spring Bootでアプリを作成してみた【Enotes】

## 1.プロジェクトを作成する

公式：[spring initializr](https://start.spring.io/)

① ブラウザを開き、(https://start.spring.io/) を入力し、開く
② 下記を入力し、Dependenciesで下記を選択し、『GENERATE』ボタンを押す

- Project: Maven
- Language: Java
- SpringBoot: 3.1.1
- jar
- 17

- Group: com.becoder
- Artifact: Enote_spring_boot
- Name : Enote_spring_boot
- Description: This is mini project using spring boot
- Package name: com.becoder.Enote_spring_boot

Dependencies
- Spring Web
- MySQL driver
- Spring Data JPA
- Spring Security
- Thymeleaf
- Spring Boot DevTools

## 2.データベースをセットアップする

(1)resouces/application.propertiesを編集する

```resouces/application.properties


```

## 3.resouces/templatesにhtmlファイルを作成する

(1)resouces/templatesにbase.htmlを作成する

## 4.java/com/becoder/enoteにcontrollerを作成する

(1)java/com/becoder/enoteにcontrollerパッケージHomeController.javaを作成する


## 参考サイト
[#1 Enotes Spring Boot Project Prerequisites | Spring Boot,MVC,JPA,Thymeleaf Project](https://www.youtube.com/watch?v=E1EyrKnh0Lg)
【初心者向け】Amazon FSx for NetApp ONTAPとは

こんにちは、Koderaです。
Amazon FSx for NetApp ONTAPについて、改めて整理してみます。

### Amazon FSx for NetApp ONTAPとは
[Amazon FSx for NetApp ONTAP](https://aws.amazon.com/jp/fsx/netapp-ontap/)は、2021年のAWSオンラインイベントである「[AWS Storage Day 2021](https://aws.amazon.com/jp/blogs/news/welcome-to-aws-storage-day-2021/)」で新サービスとして発表されました。
NetApp独自のオペレーティングシステムを利用していて、1 つの名前空間でのペタバイトスケーリングのデータセットをサポートします。
オンプレミスのONTAPの全ての機能をAWSマネージドのファイルサービスとして利用することができます。


### Amazon FSx for NetApp ONTAPの特徴

#### フルマネージドサービス
NetApp ONTAPは、Amazon FSx のラインナップの1つとして提供されます。
アプリケーションやデータ管理方法の変更が不要で、オンプレミス同様にAWS上で利用できます。
フルマネージドサービスのため、以下の運用管理を行わずに、アプリケーション開発に集中できます。

・データのレプリケーション
・ファイルサーバソフトウェアのインストールとパッチ適用
・ハードウェア障害の検出と対処
・フェイルオーバー、フェイルバックの管理
・バックアップの手動による実行


#### NASとブロックストレージを兼ね備えた統合ストレージ
サーバーメッセージブロック (SMB)やネットワークファイルシステム (NFS)といったNAS用途だけでなく、インターネットスモールコンピュータシステムインターフェイス (iSCSI)でのブロックストレージ用途でも利用可能です。Microsoft Active Directory (AD) と統合して、Windows ベースの環境とエンタープライズをサポートします。

マルチテナンシー機能（ストレージ仮想マシン（SVM）)も標準搭載されており、不揮発性メモリエクスプレス (NVMe) プロトコルを使用したデータへのマルチプロトコルアクセスが可能です。

#### 高可用性なストレージ
ファイルシステムは2つのアベイラビリティゾーンにデプロイされ、ゾーン間でのデータの自動レプリケーションとフェイルオーバにより、マルチAZの場合99.99パーセントの可用性が担保されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858908/69124f64-a519-8256-cf72-e50610a6c4bd.png)



#### コスト最適化を実現
「データ圧縮」、「重複排除」、「シンプロビジョニング」の機能を提供し、アクセス頻度の少ないデータを自動的により安価なストレージに移動し、プールストレージに階層化します。各ボリュームには、データが非アクティブになったとき (コールド状態) 移動するかどうかを制御する階層化ポリシーがあります。

プールストレージは伸縮自在なストレージ層で、ペタバイト規模にスケールができ、様々なコスト最適化な機能が提供されています。

#### NetAppのオンプレミスキャッシュソリューションをサポート
NetAppがオンプレミスの機能として提供しているグローバルファイルキャッシュおよび FlexCacheをサポートします。

#### データ保護機能
AWS KMSを利用しファイルシステムデータおよびバックアップ時の暗号化が可能です。SMB Kerberos セッションキーを使えば、転送中のデータも暗号化することができます。

#### アンチウイルス機能
サードパーティのウイルス対策ソフトウェアと連携可能で、オンデマンドのアンチウイルススキャンを行うことができます。
現状でサポートされているウイルス対策ソフトは以下の通りです。
・McAfee 
[クラスター化されたデータのウイルス対策ソリューションガイドONTAP McAfee](https://www.netapp.com/pdf.html?item=/media/16298-tr-4286pdf.pdf)
・SentinelOne
[Vscan パートナーソリューション](https://docs.netapp.com/us-en/ontap/antivirus/vscan-partner-solutions.html)
[SentinelOne Singularity Cloud Data Security](https://www.sentinelone.com/platform/singularity-cloud-data-security)
・Symantec
[Vscan パートナーソリューション](https://docs.netapp.com/us-en/ontap/antivirus/vscan-partner-solutions.html)
[Symantec Protection Engine](https://techdocs.broadcom.com/us/en/symantec-security-software/endpoint-security-and-management/symantec-protection-engine/9-1-0.html)
・Trend Micro
[クラスター化されたデータに関するウイルス対策ソリューションガイドONTAP: Trend Micro](https://www.netapp.com/pdf.html?item=/media/16892-tr-4312pdf.pdf)

#### 監査機能
ファイルおよびディレクトリアクセス全体で、アクセス成功 (ファイルに正常にアクセスする十分な許可を持つユーザーなど)、アクセス失敗、またはその成功と失敗のログ出力がサポートされています。
監査イベントログは デフォルトでは、`EVTX`ファイル形式で保存され、Microsoft イベントビューワーで確認可能です。

### まとめ
FSx for ONTAPの特徴について簡単にまとめてみました。
AWSだけではなくオンプレミスで実行されている Linux、Windows、macOS コンピューティングインスタンスから幅広くアクセスできる高速、かつ柔軟な共有ファイルストレージサービスについて、理解が深まると幸いです。
Github Actionで設計図を自動でREADMEに追加する。

## はじめに
drawioでAWSのインフラ構成図を書いていたのですが、これをREADMEから閲覧できるようになれば楽だなと思っていました。
しかし、拡張子drawioファイルはそのままだとREADMEに埋め込めないので画像形式にする必要がありました。
ですが、drawioファイルをいちいち画像形式に変換するのは手間になるのでGithubActionでデプロイすると自動で画像形式に変換する処理を実装しました。
## GithubActionとは
GitHub Actionsは、GitHubが提供する継続的インテグレーション/継続的デリバリー（CI/CD）プラットフォームです。
これを使用することで、リポジトリ内でのイベント（例：プッシュ、プルリクエスト、リリースなど）に基づいて自動的にワークフローを実行できます。

## コードの説明

まず全体像を共有します。
```yml
name: Draw.io to PNG

on:
  push:
    paths:
      - '*.drawio'
  workflow_dispatch:

permissions:
  contents: write

jobs:
  convert:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20'

      - name: Install draw.io and dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y libasound2 libgbm1 libgtk-3-0 libnss3 xvfb libnotify4 fonts-noto-cjk fonts-roboto
          wget https://github.com/jgraph/drawio-desktop/releases/download/v22.1.11/drawio-amd64-22.1.11.deb
          sudo apt-get install -y ./drawio-amd64-22.1.11.deb
          rm drawio-amd64-22.1.11.deb  # インストール後に deb ファイルを削除

      - name: Convert .drawio to .png
        run: |
          for file in $(find . -name "*.drawio"); do
            xvfb-run --auto-servernum drawio -x -f png -o "$(dirname "$file")/$(basename "$file" .drawio).png" "$file" --no-sandbox --disable-gpu --font-family="Roboto, Noto Sans CJK JP"
          done

      - name: Commit and push changes
        run: |
          git config --global user.name 'github-actions[bot]'
          git config --global user.email 'github-actions[bot]@users.noreply.github.com'
          git add *.png  # 変換後の PNG ファイルのみを追加
          git commit -m "Auto-convert .drawio to .png" || echo "No changes to commit"
          git push
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

次に特徴的な部分を説明します。
##### 必要なフォントのインストール
```yml
- name: Install draw.io and dependencies
  run: |
    sudo apt-get update
    sudo apt-get install -y libasound2 libgbm1 libgtk-3-0 libnss3 xvfb libnotify4 fonts-noto-cjk fonts-roboto
```
このステップで、fonts-noto-cjk と fonts-roboto をインストールしています。これらは日本語を含む多言語対応のフォントです。
これがないと、pngに変換したときに日本語が文字化けしてしまいます。

##### drawio ファイルの PNG への変換
```yml
- name: Convert .drawio to .png
  run: |
    for file in $(find . -name "*.drawio"); do
      xvfb-run --auto-servernum drawio -x -f png -o "$(dirname "$file")/$(basename "$file" .drawio).png" "$file" --no-sandbox --disable-gpu --font-family="Roboto, Noto Sans CJK JP"
    done
```
このステップで特に重要なのは、```--font-family="Roboto, Noto Sans CJK JP" ```オプションです。これにより、デフォルトの Helvetica フォントではなく、日本語対応フォントを使用するよう指定しています。
## 終わり
github actionはあまり触っていなかったのですが、これを機会に調査し、色々実現できることが分かったので導入検討できるといいなと感じました。
障害報告のポイント

## はじめに
おはようございます。こんにちは。こんばんは。長谷川です。
今日は障害報告におけるポイントを、開発現場で報告を受ける立場から記載していこうと思います。

## 障害報告とは
利用者が期待した動作をしなかった製品、あるいはサービスについて、提供元に事象の報告をすることです。報告の内容によっては問い合わせと受け取られたり、クレームと受け取られたりするものです。

開発の現場においては、開発中の試験において期待した動作にならなかった場合、開発チームに修正してもらうために実施するものでもあります。

## 報告内容について
では、どんなことを報告内容に含めればいいのか、具体的に考えて行きます。
基本的には「いつ、だれが、何をして、どうなった。」で、余裕があれば「頻度」もあると尚良いです。

+ いつ
何故なのか、案外報告されません。
報告を受けた側が調査するためであったり、障害の記録として残すのに必要な情報ですので必ず伝えましょう。

例：2024年8月24日 10:21頃

+ だれが
こちらも何故なのか、案外報告されません。
扱うモノによって、ユーザーIDであったり、製品名の型番であったり変わってきますがこちらも伝えましょう。

例：ユーザーID：XXXXXX

+ 何をして、どうなった
こちらはさすがに漏らす方は少ないかと思います。
具体的な事象の内容を伝えましょう。
アプリであれば、エラー発生時に「エラーコード」を画面に表示する場合もあります。
もし、遭遇したら併せて報告内容に含めると報告を受けた側は助かります。

例：ログインをしたらエラーコード△△△が表示され、ログインできなかった。

+ 頻度
一度だけなのか、何回も発生しているのかです。
毎回発生しているのであれば、どこかしらで不具合が発生している可能性が高いですし、
一度だけであれば、たまたま通信が上手く行かなかったとかということもあり得ます。
調査において大事な要素ですので、余裕があれば試して伝えてあげましょう。

例１：一度だけ発生し、時間をおいて試したら発生しなかった。
例２：何回か時間をおいて試したが毎回同じエラーコードが表示された。

## 最後に
障害報告を受け取る側も人間です。
上手く行かなくてイラつく心を抑えて、攻撃的な文面にならないよう気を付けましょう。
もしかすると、これが一番大事なポイントかもしれません・・・。

以上、長谷川でした。
PocketBase y React y TypeScript

# PocketBase 良き

趣味コードでの利用です。
しばらくコード書きから離れてたのですが、TypeScriptが良さげだったので再び弄り始めました。

PocketBaseの概要と初期設定については、[@bear_montblanc
(Be4rR)](https://qiita.com/bear_montblanc/items/2fe0da8a8452e12d926d) さんの投稿が参考になります。

## 覚えたてのTypeScriptからのReactで

BaaSなので、フロントエンドだけ良いんじゃないか？ということで、触りたてのTypeScriptとReactでデータを取得し表示するとこまでを試してみました。

TypeScriptなので、とりあえず先に useStateで型を決めておくんだなとか、データを非同期で取る場合には useEffect 使うんだなとか、お勉強になりました。

ログイン処理や他の処理もまた投稿してみようかと思います。
React初心者なので、Reactの流儀が良くわかりませんが、こんな感じでしょうかね？

```react

import React, { useState, useEffect } from "react";
import PocketBase, { RecordModel } from "pocketbase";

function App() {
  return (
    <>
      <div>
        <h1>from App.ts</h1>
      </div>
      <div>
        <Products />
      </div>
    </>
  );
}

export default App;

interface Product extends RecordModel {
  name: string;
  price: number;
}

const Products: React.FC = () => {
  const [products, setProducts] = useState<Product[]>([]);

  useEffect(() => {
    const fetchProducts = async () => {
      const pb = new PocketBase("http://127.0.0.1:8090");
      try {
        const records = await pb.collection("products").getFullList<Product>();
        setProducts(records);
      } catch (error) {
        console.log(error);
      }
    };
    fetchProducts();
  }, []);

  return (
    <ul>
      {products.map((product: Product) => (
        <li key={product.id}>{product.name}</li>
      ))}
    </ul>
  );
};

```
ITパスポートの反省2024/6/1

# はじめに
2024年 6月 1日 に ITパスポートを受けたので、勉強方法などを書いていこうと思います。

インターネットを見ると IT パスポートについて簡単とか数日で受かるなどのことが結構書いてありましたが、スタートラインがみんな違う上に使える時間も違うのであまり気にしなくていいです。個人的には思ったより難しかったです。

# 勉強期間
2 ～ 3 週間　

# 試験前のやりこみ具合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3669184/8099c9bf-5de1-600e-21d8-443c32b3e6d3.png)
試験直前になると コンスタントに9割以上は取れていました

# 結果
総合評価点　　　　700/1000 点

ストラテジ系　　　655/1000 点
マネジメント系　　565/1000 点   
テクノロジ系　　　755/1000 点

# 勉強方法

1. 最新のシラバスに対応した本を１回通しで読む
2. 過去問道場を解きまくる（直近 8回くらい）

3日くらいで本を 1通り読みそのあとは過去問道場をベースに勉強していました。

## 過去問道場の使い方
1. わからない問題が出たら本などで見ながら理由をもって答える
2. 次にこの問題が出たらどうやって回答まで導くか考える
3. 本当に苦手な問題は後に回す

最初は計算問題を捨ててやりました。
この3つを意識して過去問道場をやれば、高速で周回できると思います


# 振り返り
・見たことがない問題が半分くらいでてきた
・最近の傾向を見てシラバスで対策すればよかった


# おすすめ教材

https://www.amazon.co.jp/%E3%80%90%E4%BB%A4%E5%92%8C%EF%BC%96%E5%B9%B4%E5%BA%A6%E3%80%91-%E3%81%84%E3%81%A1%E3%81%B0%E3%82%93%E3%82%84%E3%81%95%E3%81%97%E3%81%84-IT%E3%83%91%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88-%E7%B5%B6%E5%AF%BE%E5%90%88%E6%A0%BC%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8%EF%BC%8B%E5%87%BA%E3%82%8B%E9%A0%86%E5%95%8F%E9%A1%8C%E9%9B%86-%E9%AB%98%E6%A9%8B-%E4%BA%AC%E4%BB%8B/dp/4815624259

https://www.itpassportsiken.com/ipkakomon.php

# おわりに
10月から IT パスポートの範囲が変更され難しくなるかもと聞いたので早めにとったほうがいいかもしれないです。
最後までお読みいただきありがとうございます、一緒に勉強頑張りましょう！
Laravel 11で外部API呼び出しメソッドをMock化する方法

# はじめに
Laravelで外部APIと連携するアプリケーションを開発する際、外部APIの準備が整っていなかったり、APIの利用制限があるためなるべく通信したくない、などの理由で、ローカル環境での開発やテスト実行時に実際に外部APIを呼び出したくない場合があると思います。

そこで今回は、Laravelで外部API呼び出し処理をMock化する方法を紹介します。
この方法を使うことで、外部APIのレスポンスを擬似的に再現し、開発やテストをスムーズに進めることができます。

# 前提条件
- PHP 8.3.7
- Laravel Framework 11.14.0

# 実装手順
## APIサービスの作成
まずは、実際に外部APIにリクエストを送信するサービスクラスを作成します。
今回は呼び出し元でステータスコードを利用できるように、JsonResponse型で返していますが、配列など任意の型で実装できます。
その場合は、Mockクラスのメソッドの戻り値も合わせて変更してください。

``` php
// app/Services/ApiService.php

<?php

namespace App\Services;

use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Http;

class ApiService
{
    public function fetchData(array $param = null): JsonResponse
    {
        // 外部APIのエンドポイント
        $apiUrl = 'https://api.example.com/data';

        // APIリクエストを送信
        $response = Http::get($apiUrl, $param);

        return response()->json($response->json(), $response->status());
    }
}

```

## APIサービスのMockの作成
上記で作成したAPIサービスクラスを拡張してMockクラスを作成します。

``` php
// app/Services/ApiServiceMock.php

<?php

namespace App\Services;

use App\Services\ApiService;
use Illuminate\Http\JsonResponse;

class ApiServiceMock extends ApiService
{
    public function fetchData(array $param = null): JsonResponse
    {
        $data = [
            'id' => 1,
            'name' => 'Test Data',
        ];

        return response()->json($data, 200);
    }
}

```

## サービスプロバイダの作成
新しく独自のプロバイダを作成しても大丈夫です。
今回は、既存のAppServiceProviderに追記して説明します。

``` php
// app/Providers/AppServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Services\ApiService;
use App\Services\ApiServiceMock;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        if (config('is_api_mock')) {
            // 実行環境など任意の条件
            $this->app->bind(ApiService::class, function () {
                return new ApiServiceMock();
            });
        }
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        //
    }
}

```

プロバイダで実際のメソッドを呼ぶか、Mockのメソッドを呼ぶか判定しています。
今回は環境変数を利用していますが、任意の条件を指定してください。

## プロバイダの登録
独自のプロバイダで作成した場合で自動で追加されていない場合は、以下の配列に追加してください。

``` php
// bootstrap/providers.php

<?php

return [
    App\Providers\AppServiceProvider::class,
];

```

## コントローラーの作成

``` php
// app/Http/Controllers/ApiController.php

<?php

namespace App\Http\Controllers;

use App\Services\ApiService;
use Illuminate\Http\Request;

class ApiController extends Controller
{
    protected $apiService;

    public function __construct(ApiService $apiService)
    {
        $this->apiService = $apiService;
    }

    public function index(Request $request)
    {
        $response = $this->apiService->fetchData($request->input('param'));

         // 任意の処理
        return $response;
    }
}

```

# おわりに
本記事では、Laravelで外部API呼び出しをMock化する方法を紹介しました。
Laravel 11で外部APIを呼び出すメソッド自体をMock化する記事が見つからなかったため、ぜひ参考にしてみてください。
paiza.ioでelixir その308

# 概要
paiza.ioでelixirやってみた。
練習問題、やってみた。

# 練習問題
数値を２進数で表せ。

# サンプルコード

```

[74, 46, 94] 
|> Enum.map(&Integer.to_string(&1, 16)) 
|> Enum.join() 
|> String.downcase() 
|> (&("##{&1}")).()
|> IO.inspect

(
[74, 46, 94]
|> Enum.map(fn i -> 
    Integer.to_string(i, 16) 
end) 
|> Enum.join()
|> String.downcase()
|> (fn s -> 
    "#" <> s 
end).()
)
|> IO.inspect

14
|> Integer.to_string(2) 
|> String.codepoints
|> Enum.map(fn i -> 
    "<td>" <> i <> "</td>"
end)
|> Enum.join()
|> IO.inspect



```
# 実行結果

```
"#4a2e5e"
"#4a2e5e"
"<td>1</td><td>1</td><td>1</td><td>0</td>"
```


# 成果物

https://paiza.io/projects/Wy4upFy--NUIxBOjLDAtTg


以上。
Authより前に処理を差し込みたい

# Authより前に処理を差し込みたい
Laravel10の開発でAuthよりも前に処理を差し込みたい場合、どうすればいいのか書いていきます。
先に結論を言っておくと公式ドキュメントの「ミドルウェアの順序」の部分に従ってKernel.phpに$middlewarePriorityを定義します。
https://readouble.com/laravel/10.x/ja/middleware.html

```
protected $middlewarePriority = [
    \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
    \Illuminate\Cookie\Middleware\EncryptCookies::class,
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
    \Illuminate\Routing\Middleware\ThrottleRequests::class,
    \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class,
    \Illuminate\Contracts\Session\Middleware\AuthenticatesSessions::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
    \Illuminate\Auth\Middleware\Authorize::class,

    // ここから追加
    \App\Http\Middleware\BeforeAuth::class,
    \App\Http\Middleware\Authenticate::class,
];
```

$middlewarePriorityの部分はvendor/laravel/framework/src/Illuminate/Contracts/Http/Kernel.phpから引っ張ってきたほうが安全だと思います。

## なぜ記事にしているのか
### これ以降は問題解決後に暇だったら読んでください

middlewareの順番なんてroutes/web.phpのRoute::middleware(['before_auth', 'auth'])にするだけで解決するのでは？と思うかもしれませんが、どうもLaravelの機能に依存しているmiddlewareだとそうはいかないっぽいです。

ChatGPT君に聞いてみた結果
質問：
>これはlaravelが提供するauth機能より前にbefore_authを実行するために必要であり、自作したmiddlewareの場合は$middlewarePrioriryに記載せずとも実行できるということでしょうか？

ChatGPT:
>はい、その通りです。自作のミドルウェア同士で順序を管理する場合、通常は $middlewarePriority に記載しなくても、ルートで指定した順序に従って実行されます。
Laravelが提供する auth ミドルウェアとの順序関係
Laravelが提供する auth ミドルウェアは、一般的にフレームワークの一部として重要な役割を果たすため、他のミドルウェアと競合する可能性があります。特に auth ミドルウェアは認証に関わるため、その前に特定の処理を確実に実行したい場合は、順序を明示的に指定する必要があります。
$middlewarePriority は、そのような競合が発生する場合に使用するもので、Laravelが提供するミドルウェア (auth など) と自作ミドルウェアとの間で実行順序を明確にするために役立ちます。
自作ミドルウェア同士の順序
自作ミドルウェア同士であれば、以下のようにルートで指定した順序に従って実行されます。
Route::get('/dashboard', function () {
    // ダッシュボードのコード
})->middleware(['before_auth', 'another_middleware']);
この場合、before_auth が先に実行され、その後 another_middleware が実行されます。特に競合するようなミドルウェアがない限り、これで問題なく機能します。

Laravelの提供する機能だと依存関係が影響するの$middlewareProiorityで明示的に指定しないといけないんだとか。
ChatGPTくんのことを鵜呑みにしてはいけないのであくまで参考程度、可能性の話くらいの気持ちでいてください。

ちなみになんでそんなことに？と思ってvendor以下を見ようとしましたが、めんどくさそうなんで断念しました。
知りたい人はこの記事を参考にvendor以下読み解いていってほしいな...
[LaravelのMiddlewareはどのように動いているのか？](https://zenn.dev/bs_kansai/articles/6bb62cbc02445f)

Auth前に処理を差し込む記事があまり見当たらず解決に時間かかってしまったので、同じく困っている人の参考になればと思います。
ipynb on VSCodeにおいてmatplotlibで描画した3dグラフをいろんな角度から見られるように表示する方法 ~ipymplを使うよ~

【ポイント】
ipymplのインストールと`%matplotlib ipympl`の使用

## 下準備
（下記は、venvによる実行環境管理を前提とします）
- VSCode, Pythonのインストール
- プロジェクトディレクトリに移動
- 仮想環境の作成(venv)
  - `python3 -m venv myenv`
- 仮想環境に入る
  - `source myenv/bin/activate`(Mac)
  - `.venv/Scripts/Activate.ps1`(Windows)
- ノートブック用パッケージipykernel, ipymplのインストール
  - `pip install ipykernel ipympl`
- その他必要パッケージインストール（matplotlib, numpyは一つ前の手順で自動的にインストールされる）
- カーネルの選択
  - ipynbファイル右上の「カーネルを選択」から先ほど作成した環境を選択

## コードの実行
次のサンプルコードを、ipynbのセルに入れて実行してみます。

```python
import matplotlib.pyplot as plt
import numpy as np

# %matplotlib ipymplのマジックコマンドを使用
%matplotlib ipympl

# データの生成
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = np.linspace(-10, 10, 100)
y = np.linspace(-10, 10, 100)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2))

ax.plot_surface(X, Y, Z, cmap='viridis')

plt.show()
```

## あとがき
最近pythonあまり使っていなかったし、これからまあまあ使うようになる可能性があるので、ここいらで、グラフ表示とかも確認しておこうかと思って今回の記事を書きました。（VSCodeから離れられない...）

何か関連するご意見あればぜひお願いします！

題名をわかりやすくしようと思ったら、なんかなろう小説の題名みたいになってしまった...

ちなみに、nbviewerでサンプルを公開しました。↓
https://nbviewer.org/gist/Sengankou/d740c5a1bd1ca15a693df767aabc1fd7
【Excel関数】よく使う関数の備忘録

# よく使うexcel関数目次
* IF関数
* COUNTBLANK関数
* VLOOKUP関数
* FILTER関数

## IF関数
**使い方**
```
=if(論理式,[値が真の場合],[値が偽の場合])
```

**『A1に「猫」と書かれているとき、「猫派」と表示させる。そうでない場合は「犬派」と表示させる』という条件で関数を使いたい場合**

論理式がうまく反映されないパターン
```
=IF(A1="猫","猫派","犬派")
```
→解決策
countif関数を併用して使う！
```
=IF(COUNTIF(A1,"猫"),"猫派","犬派")
```
countif関数は一つ目の引数の値が二つ目の引数の値に一致しているとき正を返すので、IF関数の条件式で特定の文字と一致するかどうかを判断したいときはcountif関数を併用して使う。
## COUNTBLANK関数
![excelキャプチャ(1).png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3787081/500f06bd-9731-d648-158a-90170d8b1e3a.png)
COUNTBLANK関数は引数の値が空欄であるかないかを判断する。
キャプチャについて細かく説明すると、
1. E列のグレー部分が空欄であると判断している→countblankの返す値は正
1. COUNTBLANK関数を抜けてIF関数に戻る
1. IF関数の条件式(COUNTBLANK関数)が真となる場合の値を返す→「おなかはすいていない」と値が表示される
**補足・IFERROR関数**
同様に空欄のときはエラーを返さず空欄を表示させることのできるIFERROR関数もあるが、必ずしもエラーを返さない関数も多くあるためCOUNTBLANK関数のほうが汎用性があると勝手に思っています。。。
## VLOOKUP関数
特定の値を検索したときに、同じ行（もしくは列）にある値を抽出する。
![excelキャプチャ(2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3787081/5f633a48-1a99-7789-5363-9408c4f98c69.png)
K列の値を検索対象に以下論理式で抽出作業を行う
=VLOOKUP( **K**列 それぞれの値、検索場所は **E** 列から **H** 列、抽出したい列番号はE列から **4** 番目、完全一致でありたいので **FALSE** )
```
=VLOOKUP(K1,E:H,4,FALSE)
```
この結果がL列の値となる
シートをまたいで検索をかけたいときにとても便利な関数！
## FILTER関数
VLOOKUP関数は一致する値一つを返せるが、FILTER関数は一致する値が複数個ある時に便利な関数
![excelキャプチャ(3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3787081/14a5c8b0-4cc6-df7b-b88f-2b29bd0cb524.png)
=UNIQUE(FILTER(食べ物が何かを抽出したいから **Ｅ** 列,抽出する条件は種類の **H** 列が **「魚」** であるとき,当てはまる食べ物がないときは「なし」と返す)
```
=UNIQUE(FILTER(E:E,H:H="魚","なし"))
```
### どうしても関数が反映されないとき
HOMEタブの値の定義を確認してみる！
数字なのに文字列が指定してあったり、日付なのにユーザー定義になっていたりするとたまにうまく関数が働かないときがある。
自分は大体がこの理由で関数がうまく機能しないので、同じように困ったことがあったらこの部分を再確認してみてください！
![excelキャプチャ(4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3787081/d88e2375-7c1c-3ade-3116-3ec9fbc93ab4.png)
>日付は2024/08/26と表示されるがパーセンテージや時刻などと定義してしまうと全く違う値が表示されてしまう

## 最後に
ぼーっとしてても一瞬で資料作成できるように早くなりたいです:cry:
flutter doctorのandroid-licensesでJDK 17のエラーが出た場合

## 環境
Flutter　2.10.5
Android Studio Bumblebee | 2021.1.1 Patch 2
ちょっと古い環境のようであまり記事がなかった。

## エラー

```shell
flutter doctor --android-licenses

This tool requires JDK 17 or later. Your version was detected as 11.0.11.
To override this check, set SKIP_JDK_VERSION_CHECK.
```

## 対応
ローカルのJDKを17に更新する
Android Studio側はJDK11で動く模様。
```shell
brew install openjdk@17

~/.zshrcに下記追加
export JAVA_HOME=/usr/local/opt/openjdk@17
export PATH=$JAVA_HOME/bin:$PATH

source ~/.zshrc
```

## 結果
無事ライセンス認証フローに移れば成功です。

## 余談
環境をひと通り新しくしたいです。
Android開発やFlutter開発を積極的に行っていく。
Gitで内容が空のコミットをする

## 概要
大きな機能を開発するにあたりメインとなるブランチを作成するために、内容が空のコミットを行う必要があったためメモ

## コマンド
下記コマンドでdiffがなくてもコミットができます
```
$ git commit --allow-empty -m { commit message }
```

## 終わりに
知りませんでした。便利ですね
C++で乱数を作る

C++でランダムにテキストを出力したいことがあった。

```C++
std::random_device rd;
std::mt19937 gen(rd());

std::string Message[25] = {
    u8"そうね、あなたもワンちゃんには野菜ジュースを上げないでしょ？",
    u8"お前って本当にせっかちだな。",
    u8"箱の中に...帰りたい...",
    u8"荷物...届られなくなっちゃった...",
    u8"雷鳴が...止んでしまいます...",
    u8"浮世の夢のごとし...",
    u8"命は...いつか尽きるもの...",
    u8"枯れしぼむ刻...",
    u8"運命を見るのもこれでおしまい...",
    u8"これが逆らえない...運命...",
    u8"星空が...暗くなっていきます...",
    u8"皆の声が、聞こえないよ...",
    u8"灯火はいつか散る...わかってるんだ。",
    u8"フンッ、予想外アだぜ...",
    u8"みんな...元気で...",
    u8"命は永遠ではない...",
    u8"契約は...まだ終わっていない...",
    u8"また...封印されるの...？",
    u8"そんな馬鹿な...せっかく手に入れたのに...",
    u8"ここは...ゴールじゃない...",
    u8"全軍...撤退...",
    u8"策を見誤りました...",
    u8"クレー...もう帰りたい...",
    u8"うっ、呼吸、苦しい...",
    u8"私の番？",
};

int main() {
    std::uniform_int_distribution<> dist(0, 25);
    int random = dist(gen);
    std::cout << Message[random] << std::endl;
    
    return 0;
}
```
__メッセージが見たことある？知らんよわしゃ。__

distの範囲の乱数が生成されるようになってるらしい
ｼﾗﾝｹﾄﾞ... <- **なんで記事書いてるん**

# まとめ
`rand()` はかなり偏る
replaceメソッドを活用した関連テーブルの更新

# はじめに

Rubyには```replace```というメソッドがあります。

Rubyの配列 (Array) やハッシュ (Hash) などのオブジェクトに対して使われ、対象オブジェクトの内容を別のオブジェクトの内容で置き換えるメソッドです。

https://docs.ruby-lang.org/ja/latest/method/Array/i/replace.html



よく見るのは

```ruby
a = [1, 2, 3]
a.replace [4, 5, 6]
p a                 #=> [4, 5, 6]
```

```ruby
hash1 = { a: 1, b: 2 }
hash2 = { c: 3, d: 4 }

hash1.replace(hash2)
puts hash1.inspect #=> { c: 3, d: 4 }
```
この辺りでしょうか？？

今回は```replace```を配列やハッシュではなく、ActiveRecordと一緒に使ってみることにします。

# replaceを使ったコード例

:::note warn
設計内容や実装メソッドの意図に関しては思いつきなので、あまり気にしないでください
:::

### シナリオ
今回は、ユーザー (User) モデルがプロジェクト (Project) とそのプロジェクトに関連するタスク (Task)、さらにタスクに紐づくコメント (Comment) に関連しているという設定を考えます。

### モデル関係

User: 複数の Project を持つ。
Project: 複数の Task を持つ。
Task: 複数の Comment を持つ。
UserProject: ユーザに関連するプロジェクト。

### やること
Userに紐づいているUserProjectを全て削除する
新たに紐づいているTaskを取得し、それをキーにUserProjectをbuildする

今まで```destroy_all```を使用して実装していたので、今回は```replace```を使用して実装してみます。

### コード
```ruby:user.rb
class User < ApplicationRecord
  # association
  has_many :user_projects, dependent: :destroy
  has_many :projects

  # callback
  before_save :set_user_projects

  def set_user_projects
    user_projects.replace(
      project_tasks.map do |task|
        user_projects.build(task: task)
      end
    )
  end

  private

  def project_tasks
    Task.joins(project: :user)
        .where(projects: { id: project_ids })
        .distinct
  end
end
```

### 説明
ここでは、user_projects に対して replace を使用して、関連するタスク (Task) の情報を一括で更新しています。

```user_projects.replace``` 

既存の user_projects を置き換える処理です。このメソッドを使うと、destroy_all を使って既存のレコードを一旦削除する必要がなく、パフォーマンスの改善や無駄な削除処理の回避が可能です。

```project_tasks.map```

ユーザーに関連するプロジェクト、タスクを辿ってタスク (Task) を取得しています。


```user_projects.build```
それぞれの Task に対して、新たに user_project を作成しています。
replace メソッドを使うことで、既存のデータを無駄に削除することなく、効率的に関連テーブルのデータを更新できます。

### destroy_allでの実装時との違い

類似の処理を行うには、destroy_all を使って既存の関連を削除し、その後新しい関連を追加する方法もあります。

例えば、destroy_all を使った場合のコードは以下のようになります。

```ruby:user.rb
def set_user_projects
  user_projects.destroy_all

  project_tasks.map do |task|
    user_projects.build(task: task)
  end
end
```

こちらはぱっと見ると理解しやすいですが、次のようなデメリットもあります。

パフォーマンスの低下: ```destroy_all```は個別に削除を行うため、多くの関連オブジェクトがある場合にパフォーマンスが低下する可能性がある。

トランザクション管理の煩雑さ: 一連の操作が複数のステップに分かれているため、エラーが発生した場合にトランザクションの管理が複雑になります。

# まとめ
個人的にあまり```replace```を使用する場面に出会わなかった(気づいていなかった)のですが、今回の例に出したように時に```destroy_all```の代わりに使用したりと、使い所はあるなと感じました。
C++で超簡単にHTTPRequest

C++で簡単にHTTPRequestができるライブラリ(?)を見つけたので覚書
※HTTPSで接続したい人はブラウザバック
※C++17以降である必要がある

# ライブラリ

https://github.com/elnormous/HTTPRequest/tree/master

これを使う

# 実装
DLした"HTTPRequest.hpp"をincludeするだけ。
```C++
#include "HTTPRequest.hpp"
http::Request request{ "URL" }; // HTTPSのリンクは対応してないよ！
const auto response = request.send("GET");
std::string returned = std::string{ response.body.begin(), response.body.end() };
```
**これだけでHTTPRequestを送れちゃう。めちゃ省スペース。**
レスポンスはreturnedにはいる。

# 最後に
私はWebサーバーのPHPにGETを送るのに使いました。
複雑じゃないから初心者でも簡単に扱えて便利