OmniAICreator/Qiita-1.07M huggingface dataset:
brew doctorで吐かれたunbrewed header filesを一括で消したい

# はじめに

Homebrewでインストールすると**Warning**だらけになるのが気になり調査してみました。

動作環境
PC:MacbookPro(2018)
OS: Big Sur(11.6.2)
ターミナルはzshを使用

#### ※Windowsユーザ様へ
今回ご紹介するコマンドの中にはMacのみ搭載のものを使用しています(`pbpaste`)。
その為参考にならない部分があるかと思います。

## まずはbrew doctor

:::note info `brew doctor` とは
Homebrewの問題をチェックするコマンド。
Homebrewのインストールやアップデート後に表示されるコマンド一覧にも**Troubleshooting**のカテゴリで紹介されています。
:::

```:zsh
% brew doctor
```
最初に実行した際にでた問題は
- `~/.zshrc`に不要なPATHがある
=>言われた通りのコマンドを打って`source`で保存または`.zshrc`を開いてexport~を貼り付けて保存
- phpのバージョンが~~争い~~競合している
=>個人用のPCで切り替えて使うことは今無いので表示されたほうをアンインストール

ぐらいだったのですが、いつまでも消えないWarningが大量に残ったままでした。
```:zsh
Warning: Unbrewed header files were found in /usr/local/include.
If you didn't put them there on purpose they could cause problems when
building Homebrew formulae, and may need to be deleted.

Unexpected header files:
/usr/local/include/node/openssl/archs/darwin64-arm64-cc/asm_avx2/crypto/include/internal/bn_conf.h
/usr/local/include/node/openssl/archs/darwin64-arm64-cc/asm_avx2/crypto/include/internal/dso_conf.h
/usr/local/include/node/openssl/archs/darwin64-arm64-cc/asm_avx2/include/openssl/opensslconf.h
長いので省略
```

## Unbrewed header files were foundのファイルの削除
最初は手作業でやってたのですが一括で削除する方法があったのでご紹介します。

こちらの質問の答えを参考にさせていただきました。

https://teratail.com/questions/149293

1. **Unexpected header files:** より下の文章をすべて選択してコピーします。
やり方①：ターミナルで出力された結果をコピー
やり方②：`txt`ファイルとして保存したものを開いてコピー。
2. ターミナルを開き、以下のコマンドを入力
```:zsh
% pbpaste > ~/hoge.sh
```
:::note info
pbpasteとは：クリップボードの内容をターミナル内にペーストするコマンド
:::

上記のコマンドでは、ユーザーのホームディレクトリにhoge.shを作成し、クリップボードの内容を保存しています。
3. hoge.shをテキストエディターで開き、各行の先頭に`rm`とつけて保存
```:zsh
rm /usr/local/include/node/openssl/archs/darwin64-arm64-cc/asm_avx2/crypto/include/internal/bn_conf.h
rm /usr/local/include/node/openssl/archs/darwin64-arm64-cc/asm_avx2/crypto/include/internal/dso_conf.h
rm /usr/local/include/node/openssl/archs/darwin64-arm64-cc/asm_avx2/include/openssl/opensslconf.h
```
4.実行の権限を全ユーザーに与える
```:zsh
chmod +x ~/hoge.sh
```
5.処理を実行
```:zsh
sudo sh ./hoge.sh
```
::: note info
shが実行のコマンドです。今回はhoge.shに記述した内容を実行してくれます。
sudoをつけないとoverrideと表示されファイルごとに確認を求められるのでつけておきます。
:::
```zsh:sudoなしの一例
override rw-r--r--  root/wheel for /usr/local/include/node/openssl/archs/darwin64-arm64-cc/asm_avx2/crypto/include/internal/bn_conf.h? 
override rw-r--r--  root/wheel for /usr/local/include/node/openssl/archs/darwin64-arm64-cc/asm_avx2/crypto/include/internal/dso_conf.h?
```

### 再度brew doctorを実行
```:zsh
% brew doctor
```

ようやくWarningがなくなりスッキリしました！
```:zsh
Your system is ready to brew.
```

## まとめ
### 今回の処理の流れ
brew doctorの出力情報をコピー
↓
ターミナル上でhoge.shを作成しつつコピーしたものをペースト
↓
hoge.shを開き各行先頭に`rm`を付けて保存
↓
hoge.shを全ユーザーが操作できるように設定
↓
hoge.shに書かれたコマンドを実行
↓
brew doctorで確認

```:zsh
% pbpaste > ~/hoge.sh
% chmod +x ~/hoge.sh
% sh ./hoge.sh
// 一旦取り消して先頭にsudoを追加
% sudo sh ./hoge.sh
Password:
% brew doctor
Your system is ready to brew.

```
## 最後に
ちまちまと消していると時間ももったいないのでコマンド操作(とエディタ)があれば大量の不要ファイルを削除できる方法を知り、コマンドの知識が増えました。
`hoge.sh`の中身に削除したいファイルやフォルダのパスを入れれば一括削除できそうなので応用が聞きそうです。
[OutSystems]Security Specializationのサンプル問題について解説 1/2(#1-#4)

Security Specializationは2022/5に追加された試験で、ReactiveのProfessional認定の条件の1つ。名前通り、OutSystemsで開発する際のセキュリティ関係の話題に関係する出題がある試験。

試験情報のPDFと一緒にダウンロードできるサンプル問題を解説する。
全部で8問で、この記事では1問目-4問目が対象。

[Security Specializationのサンプル問題について解説 2/2(#5-#8)](https://qiita.com/jyunji_watanabe/items/ff4e572b252173db0ddf)

サンプル問題は、
https://www.outsystems.com/learn/certifications/
の、「Security Specialist」項目のリンク「Exam Details」でダウンロードできる資料から。「Sample Exam」がついている方のファイルが該当する。

# 1 サイバーセキュリティ攻撃
サイバーセキュリティ攻撃の種類を聞く問題。
認証されたユーザーアカウントを使ったセキュリティ侵害が発生し、調査の結果、そのユーザーは実際にログインしたが別の誰かに乗っ取られた。
という状況で行われた攻撃の種類はどれか？

A. Man-in-the-middle: 中間者攻撃。クライアントとサーバーの通信の間に攻撃者が入り込んで盗聴などを行う
B. Session hijacking: セッションハイジャック。名前通りセッションを乗っ取ることなので、これが正解
C. Security misconfiguration: [セキュリティの設定ミス](https://owasp.org/Top10/A05_2021-Security_Misconfiguration/)。左のリンクによると、適切な設定をしていない、ソフトウェアの最新化をしていない、不要なデフォルト機能を切っていないなどの設定ミス。攻撃の種類ではない
D. Ransomeware: ランサムウェア。感染すると環境内のファイルを暗号化するマルウェア

というわけで正解はBだが、Aの攻撃の中でセッションハイジャックすることもあると思うので、少し微妙なところ。
ただ、やはり選択肢Bがズバリなので試験中ならこちらを選ぶ。

# 2 情報セキュリティの3要素
OutSystems特有の概念ではなく、組織内の情報セキュリティを検討するときに最も重要な要素を挙げたものであるらしい。
[Best Practices - Security](https://success.outsystems.com/Documentation/Best_Practices/Security#software-security-and-the-cia-model)に「The CIA Security Triangle is a model that represents the three base pillars of information security within an organization, confidentiality, integrity, and availability.」と選択肢Aそのままの文がある。
というわけでそのままの選択肢Aが正解。

# 3 SessionのMax. Idle Time
アプリケーションのログインセッションは、ユーザーが未操作のまま一定の時間が経過すると、サーバー側でそのセッションが無効化される。
この時間を10分に設定したいが、どこで設定をすればいいか、という問題。

セキュリティ設定は、LifeTimeとService Centerで迷うところだが、Environment Securityに分類されるものはLifeTimeで、Applications Authenticationに分類されるものはService Centerで行う。

問題の設定箇所は、Service Center > Administrator > Security > Applications Authenticationリンク > ページ下部のMax. Idle Time。よって選択肢Dが正解。

# 4 Captcha
OutSystemsの資料でCaptchaの解説を見た記憶がないが……。
ログイン画面でたまに見る、ジグソーパズルのピースをドラッグしたり、表示された言葉にマッチする画像を選択させることで、「人間による操作と、コンピュータによる自動操作」を区別するもの。

というわけで、操作が人間によるものだることを確認するとしている選択肢Aとボットによる自動アクセスを防ぐとしている選択肢Bは正しい。
選択肢Cは、「特定のIP等からの自動クエリを防ぐ」というもの。これはたまにGoogle検索時に見かける「Unusual traffic from your computer network」のような例を指しているのでこれもOK。
最後の選択肢Dは「すべての正しくないログインが適切な承認プロセスにリダイレクトする」となっているが、ログインの判定そのものはCaptchaの仕事ではないはずなので、正しくない。

問題は正しくないものを聞いているので、選択肢Dが正解。
自作言語 CheapBasic

昔作った自作言語「CheapBasic」をアップデートしてGithubに公開しました。
[こちらです。](https://github.com/natto2121/cheapbasic)

CheapBasicは簡単に言うと、文字列変数が使えない、関数もない、入出力はPRINTとINPUTしかないBASIC言語のインタープリタです。ソースはC言語で約650行です（コメント、空行を抜いた行数は540行程度）。

こんなちっぽけな言語で何ができるのかというと、
<b>円周率1000桁計算</b>
~~~
Pi =     3.
1415926535 8979323846 2643383279 5028841971 6939937510 
5820974944 5923078164 0628620899 8628034825 3421170679 
8214808651 3282306647 0938446095 5058223172 5359408128 
4811174502 8410270193 8521105559 6446229489 5493038196 
4428810975 6659334461 2847564823 3786783165 2712019091 
(以下略)
~~~
<br>

<b>マンデルブロ集合のグラフィックスを作成</b>
![mandel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1019283/73c1619b-2e55-da06-744e-845da782b599.png)
これらのプログラムが組めるということで、一応、実数値計算や多次元配列、再帰などの機能があります。実行速度は遅いですが。
サンプルではそのほかに万年カレンダーやマインスイーパーゲームなどがあります。詳しくは上記のGitHubで。
要は、<b>こんな小さな言語でも意外といろいろなことができる、ということを示したかったのです。</b>

##### 参考: FizzBuzzのプログラム
~~~
for i=1 to 100
A=i mod 3
B=i mod 5
if A*B then print i;
if A=0 then print”Fizz";
if B=0 then print”Buzz";
print
next
~~~
このように行番号が無いこと以外はいたって普通のBASIC言語です。
機械学習AIで洋服識別アプリを作ってみた！初心者Teachable Machine

 ## 機械学習って面白い！！
こんばんは！
千葉県在住、商業デベロッパーの会社で新規事業の企画検討をしています。
様々な分野への知見を広げるために、絶賛エンジニア分野を勉強中です。
前回は初めてLINE Botを作成しました！
その記事はこちら！読んでもらえると嬉しいです。

https://qiita.com/OPA-Shinmura/items/a6bd90939d946d2e52f1

今回は**Teachable Machine**を使って洋服の識別アプリを作ってみました。
何故洋服かというと、ちょうど今検討している新規事業の企画に
**ファッションロスを減らす為に不要な衣類を回収してリサイクルする**というものがあります。
そこで回収した衣類は基本人力で仕分けているのですが、
まあまあなコストがかかるのでデジタルで解決する方法ないかなーと探していたところだったんです！

このTeachable Machineを勉強した時に1番に思ったのは、
「え？これ回収した衣類の仕分けアプリ作れちゃうんじゃない？」でした笑

AIには学習が必要と言うのは知っていましたが、
ここまで簡単に作ることが出来るとは思っておらず、**本当に驚愕でした！！！**
この感動を少しでも皆さんに伝えたいと思います。では初めていきます！

 ## 完成品はこちら
まずは完成品から！はいTwitterからどうぞ！

https://twitter.com/Shinmura_opa/status/1533097818381987840

今回はTシャツとシャツとジャケットとズボンを判別出来るようなアプリを作りました！
容量の関係で動画は短くしてます。。。

まあまずはどれくらいのレベルまで判別出来るのかの確認も含めて簡単なところから！笑
ほんの数十分の機械学習で、Tシャツとシャツとジャケットを判別出来るってすごいですよね！

 ### 今回使ったツール
これは感動しました、**Teachable Machine！！**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667978/7333bd39-04a9-8433-96b8-7c6f65bf07dc.png)

PCのカメラを使えば簡単に写真の取り込みが出来ました。
洋服はサイズが大きいので窓につるして撮影！
写真に変化をつけるのを忘れて精度はいまいちですがそこはまあご愛敬。。笑

そしてここからp5.jsのほうのコードをコピーして

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667978/6446d364-8c3d-c0e4-8809-c96e6174e265.png)

**codepen**のHTML欄に貼付けたのがこちら！

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="JjpZgmZ" data-user="opa-shinmura" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/opa-shinmura/pen/JjpZgmZ">
  洋服診断</a> by OPA-Shinmura (<a href="https://codepen.io/opa-shinmura">@opa-shinmura</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

あとは少し触ってタイトルとかいれて完成！！
本当はもう少しおしゃれなデザインにしたかったのですが、
この**CSS**と**js**が理解しきれず断念。。もう少し時間をかけて勉強します！！

余談ですが、**Qiitaにcodepenを埋め込めることにびっくり！！**

https://qiita.com/Qiita/items/edae7417214c8e957f54?utm_source=Qiita%E3%83%8B%E3%83%A5%E3%83%BC%E3%82%B9&utm_campaign=5182d85711-Qiita_newsletter_295_01_24_2018&utm_medium=email&utm_term=0_e44feaa081-5182d85711-33849153

この記事参考にしましたが、色んなことが出来るんだなと新鮮な毎日です！

 ## ここまで勉強してみて
今までだったら余裕で外注してたものが**自分で作れるかも**って思えることが非常に大きな進歩です！
まだまだ初心者なのでレベルは低いですが、引き続き色んな技術を学習していきたいです！
今回のAIアプリもまだまだ未完成なので、
アウトプットの方法然り、精度然り、どの部分の業務を効率化出来るかを考えながら**実装イメージを膨らませていこう**と思います。

最後まで読んでいただきありがとうございました！！
Gitコマンドあれこれ



# 初期設定

**ユーザー名を設定**

```bash
git config --global user.name "Githubのユーザー名"
```

**メールアドレスを設定**

```bash
git config --global user.email "メールアドレス"
```

**エディタを登録**

```bash
git config --global core.editor "エディタ名"
```

- vscodeの場合： `code --wait`
- atomの場合： `atom --wait`

****コマンドラインの色の設定****

```bash
git config --global color.ui auto
```

- git statusなどをした時の、Untracked file, staged fileなどの表示色がわかりやすくする

## 設定確認

**設定を一覧で確認**

```bash
git config --list
```

# ローカルリポジトリ

## ローカルリポジトリ作成

```bash
git init
```

## ステージに追加

**変更分全て追加**

```bash
git add .
```

**指定したファイルを追加**

```bash
git add <ファイル名>
```

**指定したフォルダを追加**

```bash
git add <ディレクトリ名>
```

## ステージに追加（git add）した変更を取り消す

**ステージに追加した変更を取り消す**

```bash
git reset HEAD <ファイル名>
git reset HEAD <ディレクトリ名>
```

**ステージに追加した全ての変更を取り消す**

```bash
git reset HEAD .
```

## ローカルリポジトリに追加

**メッセージ付きで追加**

```bash
git commit -m "<コメント>"
```

**変更内容を確認して追加**

```bash
git commit -v
```

- コミットする前に変更内容を再度確認したいときに使用

# リモートリポジトリ（GitHub）

## リモートリポジトリを登録

**originという名前でリモートリポジトリを登録する**

```bash
git remote add origin <リモートリポジトリURL>
```

- 次回以降リモートリポジトリURLを入力しなくても良くなる

## リモートリポジトリへ送信

**指定したブランチでリモートリポジトリへ送信する**

```bash
git push -u origin <ブランチ名> 
```

- `-u`オプションは次回以降リモートにプッシュする際に `git push` で送信できるようなる。

## リモートリポジトリから取得する

**リモートリポジトリをクローンする**

```bash
git clone <リモートリポジトリURL> 
```

**リモートリポジトリの内容をローカルリポジトリに取得する**

```bash
git fetch <リモートリポジトリURL> 
git fetch origin 
```

- ※ローカルのディレクトリではなくローカルリポジトリに取り込む

**込んだ内容をローカルのディレクトリに取り込む**

```bash
git merge <リモートリポジトリURL> 
git merge origin
```

### fetchとmergeを一括で行う（git pull）

**指定したリモートブランチをローカルブランチに取り込む**

```bash
git pull origin <リモートブランチ名>
git pull origin master
```

### pullの注意点

- 自分がdevelopブランチにいる場合に `git pull origin master` を実行してしまうと、developブランチにmasterブランチの内容が取り込まれてしまう
- なのでファイルがぐちゃぐちゃになる可能性がある
- 基本的には `fetch` → `maerge` を使用する方が安全
- `git pull` を使う際は挙動を理解して使用するのがベター

## ファイル削除

**リモートリポジトリファイルのみ削除**

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

**ローカルとリモートリポジトリファイルの削除**

```bash
git rm <ファイル名>
```

# ブランチ

## ブランチを作成

**任意のブランチを作成（切り替えは行わない）**

```bash
git branch <ブランチ名>
```

**任意のブランチを作成し切り替え**

```bash
git checkout -b <ブランチ名>
```

## ブランチを切り替え

**指定したブランチに切り替え**

```bash
git checkout <ブランチ名>
```

**任意のブランチを作成し切り替え**

```bash
git checkout -b <ブランチ名>
```

## ブランチを変更

**自分が作業しているブランチの名前を変更**

```bash
git branch -m <新しいブランチ名>
```

## ブランチを削除

**ブランチを削除**

```bash
git branch -d <ブランチ名>
```

- master以外のブランチがmasterにマージされていない場合は削除できない

**強制削除**

```bash
git branch -D <ブランチ名>
```

## ブランチ一覧を表示

**ローカルブランチのみ表示**

```bash
git branch
```

**リモート追跡ブランチを含む全てのブランチを表示**

```bash
git branch -a
```

# ****現在の状態****確認

下記いずれかの条件を満たすファイルがあれば、一覧で表示するコマンド

- `git add` されているけどまだ `git commit` されていないファイルの一覧
- 編集・変更・削除されているが、まだ `git add` されていないファイルの一覧
- Git管理されていない、かつ `.gitignore` で管理除外対象にもされていないものの一覧

```bash
git status
```

# ログを確認

```bash
git log --oneline
```

# 参考

- [Git（公式ドキュメント）](https://git-scm.com/docs/git-status)
- [Git コマンドリファレンス（日本語版）](https://tracpath.com/docs/)
JavaScriptはインタープリター言語だけどビルドは必要？



## 目的

基本がまだまだだ。


## 結論

JavaScriptはコンパイル不要のインタープリター言語である。
ビルドはしなくてもブラウザで動く場合もあるが、ビルドが必要な時もある（後述）。


## インタープリター（逐次翻訳型）とは

実行時に一行ずつ翻訳しながら実行する作業のこと。


以下mdn引用。
> インタープリター言語では、コードが上から下に実行されてコードの実行結果がすぐに返ってきます。ブラウザーが実行する前にコードを何らかの形に変換する必要はありません。 コードはプログラマーに親しみやすいテキストで受け取られ、それが直接処理されます。

JavaScriptのほか、Pythonはインタプリター型言語に該当する。

## コンパイルとは

インタープリターとは対になる言葉。
開発者が書いたプログラムを、機械が理解できるように一括して翻訳する作業のこと。
JavaやC言語などはコンパイラ言語。

TypeScriptもJavaScriptにコンパイルされてから実行されるのでコンパイラ言語。

以下「TypeScript Deep Dive 日本語版」引用。
> TypeScriptは、 最終的にJavaScriptにコンパイルされます。実際に実行されるのは、JavaScriptです。開発をするときは、TypeScriptを書きますが、ブラウザで実行する時には、TypeScriptをコンパイルして作成されたJavaScriptを実行する、ということです(Node.jsでも同じです)。

## ビルドとは

（コンパイルしてできた）複数のオブジェクトファイルと、ライブラリが結合したり（この作業のことをリンクという）様々な手順を踏んで実行可能ファイルを作成するまでの作業のこと。


## JavaScriptのビルド

以下のケースの場合、JavaScriptでもビルドが必要になる。

* 複数のJavaScriptファイルをまとめたい場合（bundle）
* ES2015などの新しい規格を使用したい場合（transpile）
* ソースコードを圧縮させたい場合（minify）

「ビルド＝コンパイル＋リンク」と思っていたが、
JavaScriptファイルの場合はコンパイルしないかつ、リンク以外の処理もビルドに含まれるので、単に「ビルド＝コンパイル＋リンク」という解釈はよくなさそう。


## ちなみにデプロイとは

ビルドしてできた実行可能ファイルを実行環境（サーバーなど）に配置すること。


## ちなみにVue.jsでビルドは必要か
基本的なVueプロジェクトを作成して開発する場合は必要と思って良い。
ただし、ScriptタグでCDNからVueを読み込む場合は不要。

以下Vue.js公式ドキュメントから引用
> CDN から Vue を使用する場合は「ビルドステップ」は必要ありません。これによりセットアップが非常にシンプルになり、静的な HTML を拡張したり、バックエンドのフレームワークと統合したりするのに適しています。ただし、単一ファイルコンポーネント（SFC）の構文は使用できません。




## 参考

* TypeScript Deep Dive 日本語版

https://typescript-jp.gitbook.io/deep-dive/getting-started#typescript-ru-men-huan-jing-gou-zhu

* mdn web docs

https://developer.mozilla.org/ja/docs/Learn/JavaScript/First_steps/What_is_JavaScript#%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%97%E3%83%AA%E3%82%BF%E3%83%BC%E3%81%A8%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89

* Vue.js公式ドキュメント

https://ja.vuejs.org/guide/quick-start#using-vue-from-cdn
Emacsでgrepする方法（helm-agとripgrep)

久しぶりに使おうとするとやり方をいつも忘れているのでメモしておく．
Emacsのhelm-agからripgrepとかいう高速にgrepできるツールを使う．

# 事前準備

- ripgrepのインストール（Emacsのパッケージではない．homebrewでインストールできる）
- Emacsでhelmとhelm-agのパッケージをインストール

helm関係の設定（use-packageを使用）
``` lisp
;;; helm (melpa-stable)
(use-package helm
  :ensure t
  :pin melpa-stable
  :demand    ; 遅延ロードさせない
  :after migemo
  :bind (("C-x b" . helm-for-files)
         ("C-x C-f" . helm-find-files)
         ("M-x" . helm-M-x)
         ("M-y" . helm-show-kill-ring)
         :map helm-read-file-map
         ("<tab>" . helm-execute-persistent-action)
         :map helm-find-files-map
         ("<tab>" . helm-execute-persistent-action))
  :config
  (helm-mode 1)
  (helm-migemo-mode 1))    ; for migemo


;;; helm-ag (melpa-stable)
(use-package helm-ag
  :ensure t
  :pin melpa-stable
  :after helm
  :config
  (setq helm-ag-base-command "rg -S --vimgrep --no-heading"))    ; ripgrepが必要
```

# 使い方

1. M-x helm-ag
1. grepするワードを入力
1. カレントディレクトリ以下を検索した結果のバッファができる

上記3のバッファでの操作
| キー | 操作 |
|:-:|:-:|
| C-c o | 別バッファで開く   |
| C-c C-e | 編集モードに入る  |
| C-x C-s  | 検索結果のバッファを一時保存（保存しないとすぐ消える）  |


編集モード中の操作
| キー | 操作 |
|:-:|:-:|
| C-c C-c | 編集をコミット   |
| C-c C-k  | 中止  |
| C-c C-d  | 削除する行をマーク |
| C-c C-u  | マークを外す  |

一時保存したバッファでの操作
| キー | 操作 |
|:-:|:-:|
| Ret | 検索結果にジャンプ   |
| C-o  | 検索結果にジャンプ（別ウィンドウ）  |
| g  | 検索結果をアップデート |
Rails Devise 「undefined method `current_sign_in_at'」の直し方

# エラー内容

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324819/1e50b9a7-618c-29d6-cacc-01c2cd9d3952.png)

# エラー原因
deviseの機能の1つであるtrackableに必要なカラムがないためエラーが発生している

# 解決方法①
trackableを使用しない
```ruby:
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end
```

Userモデルの`:trackable,`を削除する

```ruby:
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
end
```

# 解決方法②
trackableに必要なカラムをusersテーブルに作成する

```ruby:
# frozen_string_literal: true

class DeviseCreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable 以下のコメントアウトを取る
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end
```

再度マイグレーション
```
$ rails db:migrate:reset
```

windowsの場合はこちら↓

https://qiita.com/kakeru0520sou1/items/092b9e633e085ad19e9b

# 参考資料


https://github.com/heartcombo/devise


https://www.rubydoc.info/github/heartcombo/devise/main/Devise/Models/Trackable
【RSpec】システムテストでcurrent_userが使えないことを解決する

## 記事の対象者

・RSpecのシステムテストでユーザーの情報を渡す方法を知りたい方

## 前提条件

Ruby 2.6.3
Rails 6.1.5

**< gem >**
・capybara
・rspec-rails
・factory_bot_rails
・faker

## 解決方法の手順
結論、この手順で進めると解決することができました！

・rails_helperにDeviseを記述する（include）
・FactoryBotでUserモデルのダミーデータを作る
・システムテスト画面のbeforeでsign_userを記述する

## 私がハマったところ
devise機能のcurrent_userをテストでも使用できる思っておりました。
しかし、エラーが出てしまうため、アドバイスをいただいたところ、下記のことが判明しました。

**current_user はテスト項目が通らない**

ということで、deviseのヘルパーを使用してuser情報を渡す方法がありました。
１つずつ手順を書いていきます。

## rails_helperにDeviseを記述する（include）
下記２行を追加してください。
詳しくはdeviseの公式GitHubのwikiで"test"と入力して検索してください。

```php:rails_helper.rb
RSpec.configure do |config|
/ここから
  config.include Devise::Test::IntegrationHelpers, type: :system
  config.include Warden::Test::Helpers
/ここまで

〜（以下略）
```

## FactoryBotでUserモデルのダミーデータを作る
ユーザー情報を作りましょう。spec以下にfactoriesフォルダを作成し、user.rbファイルを追加してください。ここは、自分のUseモデルの情報を参考に作成してみてください。
参考に、私が作ったダミーデータを記載します。
Fakerを使用すると簡単にダミーデータを作ることができます。

```php:spec/factories/user.rb
FactoryBot.define do
  password = Faker::Internet.password(min_length: 6, max_length: 8)

  factory :user do
    email { Faker::Internet.email } #=> "eliza@mann.net"
    password { password }
    password_confirmation { password }
    last_name { Faker::Lorem.characters(number: 5) } #=> 5文字生成
    first_name { Faker::Lorem.characters(number: 5) } #=> 5文字生成
    nickname { Faker::Lorem.characters(number: 5) } #=> 5文字生成
    introduction { Faker::Lorem.characters(number: 30) } #=> 30文字生成
    is_deleted { false } #=> boolen型
  end
end
```

## システムテスト画面のbeforeでsign_userを記述する
後は、使用したい部分で　sign_in user を追加するだけです！
私は投稿機能の確認に必要だったのですが、この手順でエラーがなくなりました。

```php:spec/system/テストしたいところ_spec.rb
 describe '活動地点の登録画面のテスト' do
    before do
　　　/ここから
      sign_in user 
　　　　/ここまで
      visit new_activity_point_path
    end
```

## おわりに
current_user を使用している方はぜひこの方法を試してみてください。
最後まで読んでいただきありがとうございました。
久しぶりにBybitテスト環境APIに接続しようとしたら一日費やしてしまった話

結論から！
APIキー作成時のIPホワイトリストに、IPを設定しないと3か月で失効します！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181863/f4260c98-cada-3a0d-2b20-cd376cce7313.png)
―― 二度と同じ人を生まないために記載しておきます

出てきたエラー１

```
2022-06-04 13:51:27,969 - BybitWebsocket - INFO - Authentication failed. Please check your api_key and api_secret. Topic: position
```

出てきたエラー２

```
Couldn't connect to WebSocket! Exiting.
---------------------------------------------------------------------------
WebSocketTimeoutException                 Traceback (most recent call last)
Input In [11], in <cell line: 6>()
      2 API_KEY    = 'XXX'
      3 API_SECRET = 'XXXX'
----> 6 bybitws = BybitWebsocket(wsURL="wss://stream-testnet.bybit.com/realtime",
      7                          api_key=API_KEY, api_secret=API_SECRET
      8                         )
      9 bybitws.subscribe_orderBookL2("BTCUSD")
     11 while True:

File ~\anaconda3\lib\site-packages\BybitWebsocket\__init__.py:43, in BybitWebsocket.__init__(self, wsURL, api_key, api_secret)
     40 # We can subscribe right in the connection querystring, so let's build that.
     41 # Subscribe to all pertinent endpoints
     42 self.logger.info("Connecting to %s" % wsURL)
---> 43 self.__connect(wsURL)

File ~\anaconda3\lib\site-packages\BybitWebsocket\__init__.py:74, in BybitWebsocket.__connect(self, wsURL)
     72     self.logger.error("Couldn't connect to WebSocket! Exiting.")
     73     self.exit()
---> 74     raise websocket.WebSocketTimeoutException('Error！Couldn not connect to WebSocket!.')
     76 if self.api_key and self.api_secret:
     77     self.__do_auth()

WebSocketTimeoutException: Error！Couldn not connect to WebSocket!.
```

ダメポイント１
本番環境のAPIキー見て、失効してないよなーとかいうチェックをしてしまう。
テスト環境のAPIキーを見よう！！

ダメポイント２
APIキーは絶対に間違ってないし、絶対に失効していない！という頭で調査し続けてしまう

ダメポイント３
ひたすら出てくるエラーについて調べてしまう
エラー「Authentication failed.」に全ての答えはでいてるようなものだった


あなたが同じようなエラーで困っていて少しでも時間の削減になればLGTM
gitignoreファイルを除外する方法メモ

## gitignoreをgitignoreでignore（無視）

- gitignoreファイルにgitignoreファイルを無視するように指定してgit管理から外す方法。

```gitignore
~~~
.gitignore
~~~
```

## .gitファイルのexcludeファイルに追記

- 対象のリポジトリにある.git/info/excludeファイルにgitignoreを追記する方法。

```exclude
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

/* 上記は元々記載された情報。この下から追記 */
.gitignore
```
RustでDistrolessのdocker imageを作成する

## 概要

RustアプリケーションをKubernetes上で動かすことを想定し、
DistrolessでのDocker imageを作成する手順を記載します。


## 参照
https://github.com/GoogleContainerTools/distroless/blob/main/examples/rust/Dockerfile


## Rustアプリケーションを作成

```console
% cargo new distroless_hello_world
     Created binary (application) `distroless_hello_world` package
% cd distroless_hello_world   
% cargo run                                                                              
   Compiling distroless_hello_world v0.1.0 (/.../distroless_hello_world)
    Finished dev [unoptimized + debuginfo] target(s) in 4.30s
     Running `target/debug/distroless_hello_world`
Hello, world!
```

## Dockerfileを作成

```dockerfile
FROM rust:1.61.0-bullseye as build-env
WORKDIR /app
COPY . /app
RUN cargo build --release

FROM gcr.io/distroless/cc
COPY --from=build-env /app/target/release/distroless_hello_world /
CMD ["/distroless_hello_world"]
```

## 動作確認

```
% docker build .
 ...
 => => writing image sha256:1adba3574ed863f3ba829eff0f4e817def15bf7dc313e689cc5b3b22caf8aabb

% docker image inspect -f "{{ .Size }}" 1adba3574ed863f3ba829eff0f4e817def15bf7dc313e689cc5b3b22caf8aabb | numfmt --to=si 
27M

% docker run 1adba3574ed863f3ba829eff0f4e817def15bf7dc313e689cc5b3b22caf8aabb            (git)-[master]-[~/src/github.com/takisawa/rust-study/distroless_hello_world]
Hello, world!
```
Laravelのクロスサイトスクリプト（XSS）対策

LaravelのXSS対策で意識することをまとめます。

# 要点
１、htmlのタグ内ではダブルクオテーションで囲う
``<input value="{{ $text }}">``

２、フロントに文字列を渡す時は、htmlspecialcharsでサニタイズする

## htmlのタグ内ではダブルクオテーションで囲う

ダブルクオテーションで囲わないと予期せぬ属性が追加されてしまう。

#### 実行例
```php:TestController.php
class TestController extends Controller
{
    public function index()
    {
        $text = "test onclick=alert(1);";  
        return view('tests.test', compact('text'));
    }
}
```
```php:test.blade.php
<input type="text" value="{{$text}}">  {{-- 正しい --}}
<br>
<br>
<input type="text" value={{$text}}> {{-- 誤り --}}
```
#### 結果
クオテーションで囲まない方はonclick属性が追加できてしまった。
![無題のプレゼンテーション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620908/18df972c-23d2-c529-5348-f2bfe10ce75f.png)

## フロントの言語に変数を渡す時は、htmlspecialchars関数でサニタイズする

#### 実行例
ボタンを押下したらlogが出力される機能を作成

```
{{-- ボタン(onclick属性) --}}
<button onclick="test({{$text}})">ボタン</button>

{{-- js --}}
<script>
 function test(text){
   console.log(text);
 }
</script>
```

渡すテキスト
``$text = "test' onclick=alert(1);";``
・シングルクオートあり
・()あり

### 出力されたログ
エラー
``Uncaught SyntaxError: missing ) after argument list (at``


## 修正例
```
{{-- シングルクオテーションで囲むことで()が文字列として扱われる --}}
{{-- さらにhtmlspecialchars関数でシングルクオテーションをサニタイズする --}}
<button onclick="test('{{htmlspecialchars($text,3)}}')">ボタン</button>
```

### 出力結果
``test&#039; onclick=alert(1);``

サニタイズする前の文字列を表示したい場合はjs側で処理する必要あり。
今回は範囲外とします。

## 追加
別パターン:json形式で渡す
```blade.html
<button onclick="test2( {{ json_encode(['text' => $text], JSON_HEX_TAG | JSON_HEX_AMP) }} )">ボタン</button>
```

```script.js
 function test2(text){
  console.log(text.text);
 }
```
### 出力結果
``test' onclick=alert(1);``
渡したテキストがそのまま取れました。これが一番良さそうです。
上司が教えてくれました。感謝。


#### 他にもっと有効な方法があれば是非教えてください。
【RSpec】テスト用のヘルパーモジュールを定義し、テストの種類ごとに読み込む

## はじめに

タイトルの通り、テストの種類（request, model）毎にヘルパーを読み込む方法をまとめておく。

## 結論

`spec/rails_helper.rb` に`config.include ModelSpecHelper, type: :model` などのようにtypeを指定して読み込むモジュールを定義する。

## 詳細

まず、`spec/support/`配下にテストで読み込みたいテストを含んだモジュールを用意する。

spec/support/model_spec_helper.rb

```ruby
module ModelSpecHelper
  def 〇〇
    ~~~~~
  end
end
```

spec/rails_helper.rbに以下のように

```ruby
RSpec.configure do |config|
  # ~~~~~~
  config.include JobSpecHelper, type: :job
  config.include ModelSpecHelper, type: :model
  config.include RequestSpecHelper, type: :request
  config.include AuthorizationHelper, type: :request
  # ~~~~~~
end
```

読み込みたいテスト毎にinclude~typeを記載する。

あとは、例えばテスト側で、

`RSpec.describe "Api::V1::Auth::Registrations", type: :request do`

とtypeを指定すれば上記の`RequestSpecHelper`, `AuthorizationHelper` が読み込まれ、その内部のメソッドが使えるようになる。

## おわりに

簡単にメソッドをモジュールに切り出せるので、テストコード内で何度もメソッドを定義することがなくなり重複がなくなる。コードをDryに保つことは大切なので積極的にモジュール化していきたい。
今日の作業はここまでにさせてください。

いいね(lgtm)せずにfollowする人の行動を分類

https://qiita.com/kaizen_nagoya/items/1496dac5a85d10b461d9

しながら、4,000通知確認させていただきました。

偽識別子(fake ID)と呼んでもいいですか

https://qiita.com/kaizen_nagoya/items/ad466661c9985457cb70

とも思いました。
調べてみると、ある言語の方の行動を、同じ言語を使うかたが真似ているだけの場合を見かけたような気がします。

Qiitaっていうよくわからないシステムを、こう使ったら、こういう反応があったから、
こしたらっていうのが伝わって、同じ人が別のIDを使っているとは限らないかもしれません。

最大の原因は

Qiita 表彰プログラム

https://qiita.com/kaizen_nagoya/items/cc82fefe1dda4b7250d8

かもしれません。
ここにならんでいる人をfollowすれば、いろいろ読めるよって伝わったかもしれません。
結果として起きた現象が下記かもしれません。

こんなにfollow順番が似てるのってどういう現象＝偽識別子

https://qiita.com/kaizen_nagoya/items/ea0de85a2e5fbcbdd06e

年間 TOP Contributor

が元凶かもしれません。こういうものに群がる人の行動は、私ら凡人からは計り知れないことがあるのかもしれません。

狙わないのが一番なのでしょう。取り巻きにならないことも大事ですね。
狙って行ってもいいことはない。


ブロックさせていただきました。followを取り消させていただきました。

https://qiita.com/kaizen_nagoya/items/a1bfb426cfed1b534dfe

ブロックさせていただきました。followを取り消させていただきました(2)

https://qiita.com/kaizen_nagoya/items/51363c3e3e6d4396a067


いろいろ振り回された１週間でした。
１週間前にくらべれば、いろいろ整理できました。

4000通知を連続で確認したのは初めてです。
この７ヶ月間くらいは、転職して書き込みが減っていた状態から、
３年前の元の量に戻りました。

その間に、傾向がだいぶ変わっていたこと、システムもかわっていたことから、戸惑いが生じたかもしれません。

また、海外からのアクセスも増えているのかもしれません。

今日の作業はここまでにさせてください。
STM32G031J6M6で二進固定小数点で遊ぶ


x 動作確認済み2022/6/5 23:39


目的
温度センサーの計算とか
S-5851A等
わからない人むけ



![o_con524.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f7519538-367c-c753-541e-aee53201db3a.jpeg)


https://seiai.ed.jp/sys/text/csc/ch12/c12a300.html


前提　十進固定小数点とは、適当な所に小数点を置く
簡単で分かりやすい

例　200 小数点は、十の位　→　20.0
例　3300 小数点は、千の位　→　3.300

ムズイからあんまり使っていなかったが
小学生にわかる位、簡単だが、大学生でも単位を落とすやつが数人いる
まず　1/2 ←→ 0.5は、同じである。　もんくあるか?


![o_con518.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/6c4d3f9f-05ab-70fd-a1ae-ed62769b9f35.jpeg)



1/4 ←→ 0.25は、同じである。　かかってこいやー? 苦情は、コメント欄へ


![o_con519.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/0df88d72-ac77-a6a4-e891-b98905802c6c.jpeg)


1/8 ←→ 0.125は、同じである。　今日は、このぐらいにしててやる?


![o_con520.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/4144443c-b84b-e400-c2df-d8032db77bc1.jpeg)


そうじゃん!!

二進固定小数点　1ビット　→　1/2 0.5
二進固定小数点　2ビット　→　1/4 0.25
二進固定小数点　3ビット　→　1/8 0.125

マイコンでよく使うのは、こんなところ

二進固定小数点　1ビット

```
char  *f[] = {".0",".5"};

```

![o_con521.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/d1b6f03b-ecd3-3118-8d40-06eaa4d5f865.jpeg)

二進固定小数点　2ビット

```
char  *f[] = {".0",".25",".5",".75"};


```


![o_con522.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f871e6c4-9aeb-1864-6b77-450a59d3b38f.jpeg)

二進固定小数点　3ビット

```
char  *f[] = {".0",
".125",
".25",
".375",
".5",
".625",
".75",
".875"};


```


![o_con523.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/09fdabf3-b879-c652-7e2d-7c8402fea6d6.jpeg)


だんだん　めんどちっく　なってきた


https://paiza.io/ja/projects/new?language=c


スターンダートC


```c++


#include <stdio.h>
int main(void){
    // Your code here!
    
char  *f2[] = {".0",".5"};

char  *f4[] = {".0",".25",".5",".75"};


char  *f8[] = {".0",
".125",
".25",
".375",
".5",
".625",
".75",
".875"};
  
    
    int a = (123<<1) + 1; //123.5
    
    printf("%d%s\r\n",a>>1,f2[a & 0x01]);
    
    
    int b = (123<<2) + 1; //125.25
    
    printf("%d%s\r\n",b>>2,f4[b & 0x03]);
    
 
    int c = (123<<3) + 3; //125.375
    
    printf("%d%s\r\n",c>>3,f8[c & 0x07]);
   

}


```


![o_con525.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/57f1f459-8143-c305-c3e6-6086f9948e90.jpeg)



```c++

//hold_val_031_1


#include <Arduino.h>
#include <HardwareSerial.h>


//初期化
void setup() {

  delay(3000); //not delete

  Serial.setTx(PA2_ALT1);
  Serial.setHalfDuplex();
  Serial.begin(9600);

}//setup


//メインループ
void loop() {




  char  *f2[] = {".0", ".5"};

  char  *f4[] = {".0", ".25", ".5", ".75"};

  char  *f8[] = {".0",
                 ".125",
                 ".25",
                 ".375",
                 ".5",
                 ".625",
                 ".75",
                 ".875"
                };


  int a = (123 << 1) + 1; //123.5

  Serial.print(a >> 1);
  Serial.println(f2[a & 0x01]);

  int b = (123 << 2) + 1; //125.25

  Serial.print(b >> 2);
  Serial.println(f4[b & 0x03]);

  int c = (123 << 3) + 3; //125.375

  Serial.print(c >> 3);
  Serial.println(f8[c & 0x07]);

  delay(2000);

}//loop



```
Java SE Bronze の勉強方法

# Java SE Bronze の勉強方法

## 目的
今回、[Java SE Bronze 1Z0-818](https://education.oracle.com/ja/java-se-bronze-available-only-in-japan/pexam_1Z0-818)に合格したので勉強方法をメモしておきたい

## 学習開始時スペック
* Javaは大学の授業で触ったことがある
* 細かい文法は忘れているが、型（int, float...）、For/While、Ifはわかっている
* オブジェクト指向の考え方はなんとなく知ってる

## 学習期間・時間
* 1ヶ月×1-2時間程度 ≒ 45時間ぐらい

## 学習教材
### オラクル認定資格教科書 Javaプログラマ Bronze SE(試験番号1Z0-818) 
https://www.amazon.co.jp/%E3%82%AA%E3%83%A9%E3%82%AF%E3%83%AB%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E6%95%99%E7%A7%91%E6%9B%B8-Java%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E-Bronze-SE-%E8%A9%A6%E9%A8%93%E7%95%AA%E5%8F%B71Z0-818/dp/479816206X/ref=cm_cr_arp_d_product_top?ie=UTF8

### 徹底攻略Java SE Bronze問題集[1Z0-818]対応
https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5Java-SE-Bronze%E5%95%8F%E9%A1%8C%E9%9B%86-1Z0-818-%E5%AF%BE%E5%BF%9C/dp/4295008958/ref=cm_cr_arp_d_product_top?ie=UTF8

## 学習方法
* まず紫の本を読みながらやる
* 次に黒い本を解き進める
* 2冊の問題を解きまくる

## 結果
正答率90%で合格できた

## 所感
上の2冊を何度か解いて、解説を理解していれば間違いなく合格できると感じた。
もし、Javaの概要を知っているようであれば黒本だけで良いのかもしれないが、2冊あるのが望ましいと思う。
Goでシンプルなコマンドラインツールを作ってみた

## はじめに

Goを使ったWebアプリケーション開発を半年以上経験していますが、業務外ではこれまで技術本を読んだり、Udemyなどを使った学習を主にしてきました。
これまでインプットをメインに自己学習をてきたので、これからはアウトプットもしていきたいと思い、Goを使ってコマンドラインツールを作ってみました。

## 作成したもの

今回作成したツールは **[pn-checker](https://github.com/gracefulm/pn-checker)** という「引数で指定した数字が素数かどうか判定するだけのシンプルなコマンドラインツール」です。
**実用性のない**且つ**くだらない**ツールを作ってみたいという思いから、さらに、50%くらいの割合で `Think for yourself, stupid!(自分で考えろバカ！)` と言ってくる仕様にしてみました。
まあ、いわゆるクソコマンドです。

コマンド作成には以下のパッケージを使用しました。

- [spf13/cobra](https://github.com/spf13/cobra)
  - コマンドラインツールを簡単に作成できるフレームワーク
  - すごく簡単にコマンドを作成できて便利だった。
- [fatif/color](https://github.com/fatih/color)
  - カラー出力を簡単にできるパッケージ

参考程度に、開発環境(使用ツール)は以下です。

- Mac OS (intel)
- go version go1.17.5 darwin/amd64
- (vs code) 別になんでも良い
- (git) gitで管理してた方が何かと便利

## 実際に使ってみる

まずはヘルプから

```shell_session
> pn-checker -h
pn-checker checks whether the number specified is a prime number or not.
And sometimes, it says "Think for yourself, stupid!" to you.

Usage:
  pn-checker [flags] [arg(positive integer)]

Examples:
  pn-checker 997

Flags:
  -d, --diligent   seriously check if it's a prime number
  -h, --help       help for pn-checker
  -v, --version    version for pn-checker
```

次に、コマンドライン引数に数字を入れてみます。

```shell_session:(素数の場合)
> pn-checker 997
Congrats!! The number 997 is a prime number.
```
```shell_session:(素数じゃない場合)
> pn-checker 997
The number 1000 is not a prime number.
```

ちゃんと判定してくれました。
基本的には入力した数値が素数かどうか判定してくれますが、たまに...

```shell_session:(真面目に判定してくれない場合)
> pn-checker 1000

   _____ _     _       _       __
  |_   _| |__ (_)_ __ | | __  / _| ___  _ __
    | | | '_ \| | '_ \| |/ / | |_ / _ \| '__|
    | | | | | | | | | |   <  |  _| (_) | |
    |_| |_| |_|_|_| |_|_|\_\ |_|  \___/|_|
                                   _  __        _               _     _   _
   _   _  ___  _   _ _ __ ___  ___| |/ _|   ___| |_ _   _ _ __ (_) __| | | |
  | | | |/ _ \| | | | '__/ __|/ _ \ | |_   / __| __| | | | '_ \| |/ _  | | |
  | |_| | (_) | |_| | |  \__ \  __/ |  _|  \__ \ |_| |_| | |_) | | (_| | |_|
   \__, |\___/ \__,_|_|  |___/\___|_|_|( ) |___/\__|\__,_| .__/|_|\__,_| (_)
   |___/                               |/                |_|

```

真面目に素数かどうかチェックしてくれません。
自分で作っておいてなんですが本当に実用性に欠けるコマンドですね。

ちなみに、`-d`オプションをつけると毎回真面目に判定してくれるようにしていいます。(せめてもの機能)

```shell_session:(素数じゃない場合-dオプション)
> pn-checker -d 1000
The number 1000 is not a prime number.
```

## まとめ

今回紹介したコマンドは **[git hub](https://github.com/gracefulm/pn-checker)** で公開しているので「試しに使ってみたい」という、ユニークな方は是非使ってみてください。

goが実行できる環境であれば以下コマンドで簡単にインストールできます。

```shell
> go install github.com/gracefulm/pn-checker@latest
```
オブジェクト指向の本質

オブジェクト指向の本質は、物に着目しているかどうかだけ。
物の考え方を単純にするのがオブジェクト指向。
オブジェクト指向は、システムのことも、対象のことも、オブジェクト指向のことも知らなくてもいいのがよい点かもしれない。

それ以外のいろいろな機能は、物に着目したときに、
効率的にプログラミングを記述できるように用意した道具類である。

道具に振り回されて、オブジェクト指向から離れて無駄なプログラムを書くように指導している話をしばしばお聞きする。

それではオブジェクト指向はばんばんざいかというとそうではない。

物の分類は、例えば遺伝子解読が進んで、それまでの分類がかならずしも本質的なものではなかったことがあちこちで露呈し、分類の大幅な書き換えがあった。

もともとの分類の構造、体系と、あたらしい分類の構造と体系の間の関係は、
オブジェクト指向であるかどうかに関係なくやっかいごとだったりする。

それでは、サブジェクト指向がいいか、アスペクト指向がいいかというと、類似した問題はかかえたままである。

振る舞いに着目して、振る舞いから設計する振る舞い指向なら、大丈夫だろうか。
振る舞いは、ある条件にならないと観測できず、初めから設計できるとは限らない。

データ中心設計はどうだろう。
データの構造がすでに把握できている対象に対しては、有効である。

データの構造がわからず、変化していくものに対しては、高度な直感力のある方なら、データ中心設計で乗り越えられていることを目撃したような気がする。

最終的には、何を解きたいかが事前にわかっているか、何を解きたいかは、時間の変化にしたがい、どんどん変わっていき、予測が困難であるかどうかにもかかっている。

それ以上に、その問題を解くためには、大きな空間がいるとか、長い時間の測定がティ右葉だとか、現在の技術では解決できない場合もある。その場合には、現在の技術そのものを劇的に変化させることに注力し、問題の解決はひとまず保留するといいかもしれない。

オボジェクト指向の本質は、物に着目するがゆえに、他の振る舞い指向、データ中心設計などのいくつもの考え方、道具類をとりそろえ、日々鍛錬していくことなのかもしれない。
MasoniteでチョットModel①（取得とか）

（Python素人が、）ひっそりとMasoniteして行こう、Model編。
今回は取得のみ。
※保存とか、Modelそのもののコーディングとかは別途書きたいなと。

[Masonite ORM](https://orm.masoniteproject.com/models)

DB周りを使用する場合、別途```Masonite ORM```のインストールが必要かと思います。
```bash
pip install pip install masonite-orm
```

# バージョン
```bash
Python 3.10.4
Masonite version 4.14.1
masonite-orm 2.11.10
```

# 取得
今回は簡単なものだけを記載しました。
いつかもっと充実できたら…

Laravelユーザみんな大好き```tinker```も勿論ありました。
```python craft tinker```
取得の確認とかはこちらを使うと便利。

ただ、取得した全値の確認とかは```to_json()```をしないとダメかもしれません。

クエリビルダの使用もできる様です。
また、```to_sql()```でクエリ確認ができます。
```python
from masoniteorm.query import QueryBuilder

query = QueryBuilder().table("users")
query.to_sql()
# => 'SELECT * FROM `users`'
```

## Select, SelectRaw
```python
User.select("email").get()
User.select("name AS user_name").get()
User.select_raw("COUNT(name) AS user_count").get()
```

## All, Get
Collectionが取得されます。
今回は確認しませんが、Collectionでのwhereとかも可能な様です。


```python
User.all()
User.get()
# ちょっと違うけど
User.paginate(10)
```
## First
対象のModelが取得できます。

```python
User.find(1)
User.first()
```

```FindOrFail()```と同様ものもあります。
```python
User.find_or_404(0)
# masoniteorm.exceptions.HTTP404

User.find_or_fail(0)
User.where("id", 0).first_or_fail()
# masoniteorm.exceptions.ModelNotFound
```

## Where
Where系のは色々あるので、よく使いそうなものを。

```python
User.where("id", 1).get()
User.where({"name": "Hoge", "age": 1}).get()
User.where("age", ">", 18).get()
User.where_null("email").get() # where_not_null()もあり
User.where_in("age", [1, 2, 3]).get() # where_not_inもあり
User.where_like("email", "%example.com").get # where_not_likeもあり
```

## その他
```join```や```group by```、集計関数なども問題なく使用できそうです。

# 終わりに
Modelとは関係ないですが、```tinker```で値がさっくりと確認できないのは面倒ですね。

```patinate```のカスタマイズとかLaravelだと可能だったと思いますが、こちらでできるか気に少しなるところ。
ってか、Masoniteの学習で、Laravelの学習にもなっているような気がします。

※さて、これは次回も続くのか。
ウォーターフォールとアジャイルの違い

# 背景
社会模型は、経験則で、条件が変われば、逆も真になる。間違いという概念は、その時代に統計に現れるかどうかという判定として成立するかもしれない。正しいかどうかは問題の外だと理解できれば先に進めるだろう。



ウォータフォールは、ハードウェア、OS、開発環境に焦点をあてた模型である。
アジャイルは人に焦点をあてた模型である。

条件を合わせれば、一つの事象をどちらでも説明できる。対立する模型ではない。

本で読んだ知識は、現象を追いかけただけであれば、役に立つかどうかは定かではない。原理的な記述は、条件の範囲を明記していなければ、架空の話かもしれない。

天才がプログラムすれば、どんな方法でも成功するかもしれない。

## ウォーターフォール 

ウォーターフォールは、メインフレームのように５年とか１０年に１度、システム更新があり、その繰り返しを何度かしてきたために、段階を追って作業する段取りがすでに安定していることを前提としている。

ハードウェアも、その上のソフトウェアも、プログラミング言語も、すべて計画的に機能拡張しており、一発勝負はウォータフォールとは無関係である。

そして、かなり先の未来まで計画があり、全く予測が必要のない開発方法である。

## アジャイル
アジャイルは、天才的なプログラマがやっていてよかったことをまとめたものである。
ウォータフォールでアジャイルしても全く矛盾はない。

# 属人化

## ウォータフォール
計画的な開発であり属人化は含んでいない。そのため、面白くないとい感じる人がいるかもしれない。アジャイル的な天才プログラマであれば、計画を前倒しに実現してしまえば、空いた時間を好きにできる。

## アジャイル
もともとは属人的な手法である。俗人が行うものではなく、天才が行うため、種類、範囲、方法などがさまざまで、人が真似をするのは難しいかもしれない。
そのため、真似をしやすいようなやり方を決める人たちがいるが、参加者の能力に応じた展開をしないと無駄なことを決めているだけのことがあるかもしれない。
# 構造
## ウォータフォール
体系的な構造で分割しているため、参加する人が構造を考える必要がない。


## アジャイル
天才的プログラマ以外の人が参加した場合には、天才のやっていることがどんどん変わっていくのに追従できない人を、どうするかが課題となる。そのため、本来は自由な手法であったアジャイルに、さまざまな取り決めを導入しようとする人たちがいて、面白さに欠けるようになっているかもしれない。

# 繰り返し
## ウォータフォール
５年、１０年というハードウェアの置き換えから、事細かに決まっており、１年ごとにやること、毎月やること、毎週やること、毎日やることまで決まっていて、繰り返しの効率化を埋め込んでいる。天才プログラマは、構造をそのままにして、劇的な改善を図ることがあり驚くことがあった。

## アジャイル
天才は気まぐれであるが、俗人がついてこれないため、繰り返しのばらつきを抑えるために規則を導入しようとして面白くなくしていることがあるらしい。知らんけど。


# 文書
## ウォータフォール
第四世代言語など、文書を最小限にする仕組みを作ったり、自動生成が流行った。COBOLは自然言語で記述すればそのまま動くことを志向した言語であり、文書がそのまま動くため無駄文書はいらない。
## アジャイル
天才の動きに追従できない俗人が、天才のやったことを解釈するためにシステム記述言語以外で文書を記述し、無駄をふやすことがあったらしい。

# 補足
ウォータフォールとアジャイルは、全く事なる視点を提供している。
そのため、一つのシステムをウォータフォールだと思うか、アジャイルだと思うかは、その人の関わり方によるところと、その人の能力によるところが大きいかもしれない。

ハードウェアが定期的に更新するとは限らなくなってくると、ウォータフォールで開発する条件がなくなったにもかかわらず、以前と同じ仕事の仕方をしているのを、ウォータフォールの問題だと誤解されている方が多いかもしれない。

制約条件の変化に追従できない問題は、ウォータフォール。アジャイルに限らず、その人の能力上の問題だけに限定せずに、それぞれの人の能力を発展させるための組織化のあり方で解決できるかもしれない。


# 参考資料　　

@kazuo_reve 新人の方によく展開している有益な情報

https://qiita.com/kaizen_nagoya/items/b9380888d1e5a042646b

@kazuo_reve 私が効果を確認した「小川メソッド」

https://qiita.com/kazuo_reve/items/a3ea1d9171deeccc04da

## 自己参照　


アジャイルサムライ & 公開算譜は機敏だ(An Open Source Project is Agile)GitHub with Docker。仮説（51）

https://qiita.com/kaizen_nagoya/items/5dd49a046b5991af3a5e

HP: 40年(60年）でソフトウェア開発の景色はどのぐらい変わったのか？仮説（165）

https://qiita.com/kaizen_nagoya/items/54c17cf751894eef56f8



Microsoftとの歴史　Basicに始まり、Cコンパイラ、Windows95、Githubまで

https://qiita.com/kaizen_nagoya/items/d7c0cc257e99de0573cf

NASAを超えるつもりがあれば読んでください。

https://qiita.com/kaizen_nagoya/items/e81669f9cb53109157f6


参考文献駆動執筆(references driven writing)・デンソークリエイト編

https://qiita.com/kaizen_nagoya/items/b27b3f58b8bf265a5cd1

小川メソッド　覚え（書きかけ）

https://qiita.com/kaizen_nagoya/items/3593d72eca551742df68

DoCAP（ドゥーキャップ）って何ですか？

https://qiita.com/kaizen_nagoya/items/47e0e6509ab792c43327

「@kazuo_reve 新人の方によく展開している有益な情報」確認一覧

https://qiita.com/kaizen_nagoya/items/b9380888d1e5a042646b


# 文書履歴(document history)
ver. 0.01 初稿 　 20220604
ver. 0.02 背景追記 20230504

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

####  Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
AWSで気づいたら課金されていたから調べた

# AWSから請求来た
AWSで何となくインスタンスを作って遊んだのが1年前。その後何となくほかの無料サービスも使った気がする。
1年くらい放置していたらなぜが請求が来るようになった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218589/f73df9c2-ea46-d2ad-7d30-8b63ca377045.png)

# 原因を調べるが見つからない
請求止めたい。

まずはEC2インスタンスが残ってないか調べてみた。
サービス＞コンピューティング＞EC2＞ダッシュボードの画面を開く。
・・・インスタンスは「0」と表示されている。
　　　どうも放置したままのインスタンスはなさそうだ。

次にググったりしながらAWSコスト管理で、何に課金されているか調査してみた。
サービス＞コスト管理＞Cost Exploereの画面を開く。
・・・「EC2その他」に＄1.9ほどコストが発生している。インスタンスないのに？
　　　EC2のオプションとか生き残っているのかな？
　　　データだけ残っているのかな？
　　　？？？

よくわからなかったので、アカウントごと消してしまおうかと思った。
が、いざ消そうとしたら、同じメールアドレスで二度とAWSアカウントが作れなくなるとのメッセージが。
それはいやだ！

# EC2インスタンスが残っていた！
使用中の全リソースを検索する方法の記事を発見した。
　　→　https://dev.classmethod.jp/articles/tag-editor-seach-allregion/

1、下記AWSのドキュメントからタグエディターコンソールに飛ぶ
https://docs.aws.amazon.com/ja_jp/ARG/latest/userguide/tag-editor.html

2、リソースの検索
リージョン：All region
リソースタイプ：EC2 インスタンス
を選択し、リソースを検索する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218589/418e65b6-3eab-85b3-5f30-ad5a16e0b4c7.png)

すると！なんと！EC2インスタンスが2つ検出された！
EC2のダッシュボードでは、表示されていなかったのに・・・
リソース一覧のリンクから、EC2インスタンスにアクセスする。
インスタンスの管理画面が開いたので「インスタンスの終了」実行し、インスタンスを消した。

インスタンスの終了後、EC2のダッシュボードを開くと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218589/1ca93fef-08d0-7759-af80-8f82ab71734f.png)

インスタンスの数が「2」になっている！！さっきは「0」だったのに！
なぜなのか。リージョンが切り替わっていたとかでしょうか？
一定期間過ぎるとダッシュボードに表示されないような設定とかあるのでしょうか？
とりあえずインスタンスを終了することはできたので、一安心。
来月課金されないことを祈ります。
同じレベルで悩んでいる初心者の皆様の助けになればよいです。
カスタムフックにタプル型を指定する方法



React + TypeScript でカスタムフックの返す返す方にタプル型を指定したところ、互換性エラーで怒られてしまいました。そのときのメモです。

まず、useState フックのおさらいから入ります。すでに、理解している人はスルーしてください。

## 【useState フックとは?】

### useState フック

useState フックは、「初期値の型に応じた値」と「その値を変更する関数」の２つの要素を用意したタプルを返します。タプル(配列)として返すことで、デストラクチャリングにより自分で変数の名前を設定することができます。

> **タプル(tuple)** - 複数のタイプの値を扱うことのできる不変(Immutable)な配列

カスタムフック作成して明示的にタプル型を指定しなかった場合、カスタムフックの使用先で以下のようなエラーが現れました。

### カスタムフック

```tsx
export const useInput = (initialValue: string) => {
  const [value, setValue] = useState(initialValue);
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) =>
    setValue(e.target.value);
  return [
    {
      value: value,
      onChange: handleChange,
    },
    () => setValue(initialValue),
  ];
};
```

### カスタムフックの使用先

```tsx
const AddColorForm: React.FC<Props> = ({ onNewColor = () => undefined }) => {
const [titleProps, resetTitle] = useInput("");
const [colorProps, resetColor] = useInput("#000000");

const submit = (e: React.FormEvent) => {
  e.preventDefault();
  onNewColor(titleProps.value, colorProps.value); // Property 'value' does not exist on type '(() => void) ...
  resetTitle();
  resetColor();
};

return (
  <form onSubmit={submit}>
  ...
  );
};
```

```
Property 'value' does not exist on type '(() => void) | { value: string; onChange: (e: ChangeEvent<HTMLInputElement>) => void; }'.
Property 'value' does not exist on type '() => void'.
```

`Property 'value' does not exist on type '() => void'.`2 行目のエラーで互換性がないと言われている型に注目してください。本来の value の型は、string 型ですが、ts に推測された型は、() => void をとなっています。

**通常の配列ではなく、タプルを推測する場合、 TypeScript に通知する必要があります**。

このエラーは以下の解決策は、2 つあります。

## 【解決策】

### 1. タプルの型を明示的に指定する

```tsx
type Input = readonly [
  {
    readonly value: string;
    readonly onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
  },
  () => void
];

export const useInput = (initialValue: string): Input => {
  const [value, setValue] = useState(initialValue);
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) =>
    setValue(e.target.value);
  return [
    {
      value: value,
      onChange: handleChange,
    },
    () => setValue(initialValue),
  ];
};
```

type キーワードを使って型を作成して前述の通り、明示的に定義します。

### 2. `as const` キーワードを使用する

```tsx
export const useInput = (initialValue: string) => {
  const [value, setValue] = useState(initialValue);
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) =>
    setValue(e.target.value);
  return [
    {
      value: value,
      onChange: handleChange,
    },
    () => setValue(initialValue),
  ] as const;
};
```

`as const` キーワードは配列やオブジェクトを内部の要素を含め readonly(読み取り専用)にします。as const キワードを付け加えることにより、返す型を不変なタプルに変更することができました。


以上、カスタムフックにタプル型を指定する方法でした。
タプル型の指定には、推論が効かないのでお気をつけください!
Linux版FileMaker Serverのインストール

Linux版FileMaker Serverのインストール備忘録
AWS EC2にUbuntu 18.04LTSのインスタンスを作成している前提

## FileMaker Server
FileMaker Serverをダウンロード
```
$ wget https://downloads.claris.com/esd/fms_19.4.2.204.zip
```
unzipがなければ
```
$ sudo apt install unzip
```
解凍してインストール
```
$ unzip fms_19.4.2.204.zip
$ sudo apt install ./filemaker-server_19.4.2.204_amd64.deb
```
Admin Consoleには以下でアクセス
```
https://[サーバーのアドレス]:443/admin-console
```
インストールの詳細は以下
https://community.claris.com/ja/s/article/FileMaker-Server-Linux-OnPrem-VolumeLicense

## SSL証明書
Elastic IPを取得してインスタンスに関連づけておく
Freenomなどでドメインを取得してAWSのRoute53のネームサーバーを登録、ElasticIPを紐付け
参考までにDNSが浸透していく様子を確認できるサイト
https://www.whatsmydns.net

Certbotクライアントをインストール
```
$ sudo apt install snapd
$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
```
Let's Encryptで証明書を取得（公式にはサポートされてないので自己責任で！）
```
$ sudo certbot certonly --email [メールアドレス] -d [取得したドメイン] --agree-tos --standalone
2: Renew & replace the certificate (may be subject to CA rate limits)　を選択して進む
...
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/[取得したドメイン]/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/[取得したドメイン]/privkey.pem
This certificate expires on 2022-09-02.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the 　background.
```
証明書の情報は以下で確認できる
```
$ sudo certbot certificates
```
作成された証明書をFileMaker ServerのCStoreフォルダにコピー
```
$ sudo cp /etc/letsencrypt/live/[取得したドメイン]/cert.pem /opt/FileMaker/FileMaker\ Server/CStore/
$ sudo cp /etc/letsencrypt/live/[取得したドメイン]/chain.pem /opt/FileMaker/FileMaker\ Server/CStore/
$ sudo cp /etc/letsencrypt/live/[取得したドメイン]/privkey.pem /opt/FileMaker/FileMaker\ Server/CStore/
```
FileMaker Serverにインポート
```
$ fmsadmin certificate import /opt/FileMaker/FileMaker\ Server/CStore/cert.pem --keyfile /opt/FileMaker/FileMaker\ Server/CStore/privkey.pem --intermediateCA /opt/FileMaker/FileMaker\ Server/CStore/chain.pem
```
FileMaker Serverを再起動
```
$ sudo service fmshelper stop
$ sudo service fmshelper start
```
上記の2ステップをcronにして自動更新予定 #2022-06-04
素人がレビューせざるを得ない時

## 人生の先輩をreviewしないといけなくなった

私は素人である。今の会社に実務1年で転職して来た。

1年なんて経験は無いに等しいから、「未経験」と強調して面接は押し切った。

そしたらなぜか「今まで色々経験されてるので」とった理由で給与などもある程度色をつけてくれた。

そんな事はしなくてよろしい。私に過度な期待はしないで下さい。なぜなら過去に勝手に期待値上げられた後、「実は大した事ないですね」って、惨めな思いをした経験があるからです。

大した事ないと思ってたけど、実は結構やりなさるねあんた。そういったストーリーを、そういった展開を私は好む。80点が30点にではなく、時間の流れとしては、その逆が望ましい。

その私は今、SES出身の年上先輩をgithub reviewしている。

### 言葉の威力を再確認せよ

ここへ来て1年経ってるから実務2年ではあるが、、。
その前にもwebデザイナー長い事やってたけどそれは置いといて。

個人的にはまだ「完全に理解した」ってステージにも立ってないわけで。

これまでの経験上、chatなどでやり取りする時はなるべく絵文字など装飾を使うようにして来た。

了解です、より了解です！
了解です！より了解です😃

以前の会社では絵文字使う事がmustになったぐらい、確かにこの手法は威力がある。果たして確かに、空気は自然と円満に。常時潤滑油ぬりぬりだった感はある。

しかし、、

そんな性格じゃないのですよ、私は。自分で打っててキモくなってくる。。どうにかならんものか。

もっと友人に句読点ないLINEするように、reviewもできんもんかと模索する事数日。

### ついにできた、、Let's構文

苦しんで来たのですよ、私も。

一度レビュー書いたその直後に数回書き直す訳です。

「必要な変更点だけpushして下さい」って書いたけど言い方きついかな、傷つくかなって思い直して

「今度からで大丈夫です」とか書いてみたり。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453553/a587f958-0c01-5395-a105-9e5e65208cb2.png)

「自動改行設定して下さい」って書いた直後に
「してみて下さい」って書き直したり。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453553/4795eb18-f20e-1c5e-3f30-558dac02ca34.png)

「なぜですか？」って書いたけどきついかなって思って
「何でですか？」に変えたり。（少しマイルドでしょう？）(それくらいの域でいつも戦ってる)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453553/5290cd01-3c46-6bc4-1ebb-aec833d7e6c4.png)


「理解して書いてますか？」って打った後
3回ぐらい書き直して「〜しなくても大丈夫です」ってしてみたり。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453553/8a318594-f6bb-0e08-0f6e-35bb3287ee0b.png)

そしてついに、、
句読点使わず、かつ、かどが立たない「Let's構文」（自称）を編み出したのだ！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453553/ba12b69f-bc16-2ed7-7fa0-928de1b92b5a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453553/79efeb4f-b72c-91a2-ee83-45dd650af100.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453553/55c312a6-dd94-8090-b922-1c18087a6b02.png)


ちょっと事務的感を出しつつも要件はしっかり伝えている。友達、同僚、上司部下の関係を超越した新しいアプローチ。

`Let's`は`Let us`の短縮系である通り、私もあなたと思いを同じくする仲間であるという、このメッセージ感。

いかがだろうか。この調子なら友人にLINE打った直後に、思わず「CIでキャプチャ撮りましょか」とうっかり書いてしまっても、極めて自然ではないか。

### 効果は、、？

そんな言葉使いがうんたら言いながら試行錯誤して数日、、

以前私がトスした参考URLに対し、かの人生の先輩から、こないだ初めてレスが来た。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453553/20359099-a206-0a8a-fcb0-0a55530b0b2d.png)

彼女もなかなか質問できず悩んでいたようである。

github上だとしても、聞きづらい空気を作ったかも知れない私もいくらか責任を感じるが、、

しかしもうそんな事はどうでも良い。いくつものストロークを経て、彼女とは今、信頼関係の域にあるのだから（主観）

、、、、、、

PS:

これまでレスがなかったのはもしかして、、

ゴールデンウィークに徳島出身の彼女に対し、
「実家へは電車で帰るんすか？」とボケたのだけど、、、
内心怒っていたのだろうか？？
（徳島には電車がない）

信頼関係がまだできてない時に切り込むのが、関西人の悪い癖である。