OmniAICreator/Qiita-1.07M huggingface dataset:
JSXの書き方

#JSXって？
Reactが表示される流れは、[Reactの表示される仕組みについて〜DOMとは?〜](https://qiita.com/aliceroot0678/items/9a78435a805e7b4eddb0)にも書いた通り、
①DOMの要素を取得
②仮想エレメントを作成
③レンダリング
です。
この流れを毎回書くのは大変なので、同じことをやるとしてももっと簡単な書き方があります。
それが、JSXです。:point_up:
##JSXについて
JSXはJavascriptを拡張した書き方で、HTMLのタグをJavascriptのスクリプトに直接記述する仕組み。JSXはJavascriptなので、もちろんJavascriptを埋め込むこともできます。
JSXは②のエレメントオブジェクトを生成する部分を担当します。
JSXが作るのは1つのエレメントで、複数のエレメントを作ることはできません。
`<div>...</div>`で囲んであげて、一つの要素として扱います。
大事:bangbang:
#JSXの書くときの決まり
これからJSXの書き方のルールについて、まとめていきます。:relaxed:

##変数をうめこむ
```react
  let text = "テキスト"
  let link = "https://qiita.com/"

  let el = (
          <div>
            <h4>{text}</h4>
            <h5><a href={link}>Qiita</a></h5>
          </div>
        )
```
タグの中身でも、属性にも`{}`で指定できる。
変数として認識されなくなるので、クォーテーションで囲んだりしないように。

##クラスを設定
```js
<div className="〇〇">
```
クラス属性を設定するときはこのように記述します。
##スタイルを設定
2つのやり方があります。
①タグに直接styleを書き込む
`{{}}`で囲む

```react
 let el = (
          <div>
            <h4 style={{color:"red",fontSize:20}}>message</h4>
          </div>
        )
```
②変数にまとめて定義してstyle属性に設定する

```react
   const msg_style = {
        fontSize:20,
        color:"red"
      }
  let el = (
          <div>
            <h4 style={msg_style}>message</h4>
          </div>
        )
```

###注意
####ハイフン(-)は使わない
`font-size`、`margin-top`など間にハイフンが入るプロパティはハイフンをなくして、その後の文字を大文字にして対応します。ハイフンを使うとエラーになっちゃいます！:point_up:
####数字を扱うとき
`20px`と`20`では扱いがちがいます。
20pxと単位が付く場合は`""`とクォーテーションで囲まないとエラーになるので、気をつけましょう。
[paiza]スキルチェック見本問題 Java Fizz Buzz (paizaランク C 相当)

<h2>初めに</h2>

今回スキルアップチェック見本問題CのFizz Buzzに挑戦しました。
見本問題のため、問題の掲載、解答の掲載は自由です。

https://paiza.jp/works/mondai/skillcheck_sample/fizz-buzz


```
整数 N が入力として与えられます。

1からNまでの整数を1から順に表示してください。

ただし、表示しようとしている数値が、

・3の倍数かつ5の倍数のときには、"Fizz Buzz"
・3の倍数のときには、"Fizz"
・5の倍数のときには、"Buzz"

を数値の代わりに表示してください。
```

<h2>解答コード</h2>


```java:
import java.util.*;


public class Main {
    public static void main(String[] args) {
        // 自分の得意な言語で
        // Let's チャレンジ！！
        Scanner sc = new Scanner(System.in);
        int count = sc.nextInt();
        for(int i=1; i<=count; i++){
            if(i%15==0){
                System.out.println("Fizz Buzz");
            }else if(i%3==0){
                System.out.println("Fizz");
            }else if(i%5==0){
                System.out.println("Buzz");
            }else{
                System.out.println(i);
            }
        }
    }
}
```

"Fizz Buzz" の間のスペースを忘れ一度不正解になってしまいましたが、
なんとか正解できました。
paiza側の解答もほぼ同じような感じでした。

<h2>参考サイト</h2>

https://qiita.com/ki_87/items/e2800fb0e5f64c196243

<h2>Rubyでのfizz buzz</h2>

https://qiita.com/ki_87/items/8263e4846212458d99ab
TeraTermを使ったサーバログイン手順

#TeraTermを使ったサーバログイン手順

## 目的
TeraTermを全く使った事の無い方であっても、サーバにログインができる手順書であること。

## 前提
1. クライアントPCはWindowsPCであること
2.  TeraTermがクライアントPCにインストールされていること
3. ログイン対象のホストのIPアドレスは事前に取得できていること。※お使いのクライアントPCからの接続が許可されている事を事前にご確認ください。
4. 環境にログインする為のユーザ名は既に取得できていること。
5. 環境にログインする為のパスフレーズ(パスワード)は既に取得できていること。
6. 環境にログインする為のプライベートキーは既に取得できていること。

## 手順
### 1. 虫眼鏡を起動
PCのデスクトップの画面左下隅に並んでいるアイコンの、左から2番目の虫眼鏡マークをクリックする。
![01. teraterm起動-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/76827b00-554d-c6b4-fc83-17dc6d1a873b.png)

### 2.「Tera」と入力
入力欄が表示されるので、「Tera」と入力する。
![02. teraterm起動-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/6a00ab71-2f62-9dc6-b7a7-44b4d099fbea.png)

### 3. TeraTerm起動
表示された「Tera Term」というアプリをクリックしてTeraTernを起動する。
![03. teraterm画像-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/548a8fbc-26b8-732a-e96e-3ad682c0aff8.png)

### 4. ホスト欄へ入力
「ホスト欄」にログインする対象のホストのIPアドレスを入力。
![04. teraterm画像-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/c24117f3-fa29-e327-94e6-f86ecf4da199.png)

### 5. 「OK」ボタンをクリック
「OK」ボタンをクリックする。
![05. teraterm画像-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/9a3b056c-74c5-a530-a8f5-cdb5b3964f8d.png)

### 6. ユーザ名、パスワードを設定
「ユーザ名」欄にユーザ名、「パスフレーズ」欄にパスワードを入力。
![06. teraterm画像-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/e8eedd7e-c484-7e6c-8427-b11dc458e0b7.png)

### 7. Authentication methodsを設定
RSA/DSA/ECDSA/ED25519鍵を使う、のトグルマークを選択する。
![07. teraterm画像-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/8f613020-bc71-4480-6e9f-13ce41fe1ba3.png)

### 8. ファイルを選択
「...」を選択してダイアログを起動する。プライベートキーを選択してOKをクリックする。
![08. teraterm画像-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/c8057392-fb54-edee-9e32-1b508ca11f2a.png)

### 9. 「OK」ボタンをクリック
「OK」ボタンをクリックする。
![09. teraterm画像-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/1011a293-868f-d477-da79-8ed2d3b886f8.png)

### 10. ログイン成功
ログインに成功するとそれまで表示されていた入力画面が消滅します。
以下図のような、コマンドプロンプトと呼ばれる画面に切り替わったら、ログイン成功です。

![10. teraterm画像-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/4508c08e-60a8-0177-f165-9dacf28a7fa4.png)


### ログインできない場合
ずっと以下のような画面になったまま、ログインできない場合がありますが、
それは多くの場合、ログイン操作に時間がかかりすぎていたケースですので、
再度手順を最初から行ってみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/028c8ee6-4fab-d661-36b1-a70145953f37.png)

以上です。
WindowsにおけるSDカードへのラズパイOSのインストール

ラズパイ初心者のかなめです。
購入するだけで満足し、利用していなかったRaspberry Pi 2 Model Bを引っ張りだしてきました。コロナ禍における趣味として活用していこうと思っています。

これからラズパイに関してやったこと・調べたことをまとめていこうと思います。

#本記事の内容
- Windowsで「Raspberry Pi Imager」を利用してRaspberry piのOSをSDカードにインストールする

#実施環境
- Windows 10
- Raspberry Pi Imager 1.6.2

#手順の流れ 
1. Windowsに「Raspberry Pi Imager」をインストールする
2. 「Raspberry Pi Imager」で Raspberry piのOSをSDカードに書き込む

## 1. Windowsに「Raspberry Pi Imager」をインストールする
こちらの[ラズパイのサイト](https://www.raspberrypi.org/software/)に行く。
![00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/ec500a75-698e-5e97-f277-1ace89b4d7ee.png)

Download for Windowsをクリックすることで、Raspberry Pi Imagerインストーラーのダウンロードが始まる。インストーラーはWindows内の任意の場所に保存し、保存完了後インストーラーを実行して、Raspberry Pi Imagerのインストールを完了する。
こちらがRaspberry Pi Imagerを起動した画面。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/bdde82f7-7ca1-668e-5ade-00d1682ddc9c.png)

## 2. 「Raspberry Pi Imager」で Raspberry piのOSをSDカードに書き込む
Raspberry Pi Imagerを起動する。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/bdde82f7-7ca1-668e-5ade-00d1682ddc9c.png)

"Operating System"の"CHOOSE OS"にてOSを選択する。今回は、"Raspberry Pi OS(32-bit)"を選択。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/6acdf194-f5ae-e9fd-f1fa-4ed39cb1a6d8.png)

"Operating System"欄に"Raspberry Pi OS(32-bit)"が選択されたことを確認。
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/e47da59d-7c26-2b4f-71a0-f2b61f286e5e.png)

"Storage"の"CHOOSE STORAGE"を選択する。Windowsに接続したSDカードが表示されたので、それをクリックする。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/0ef44c84-8459-7408-5d97-e19f36f01457.png)

"Storage"欄に選択したSDカードが表示されるので、OSを書き込むために"WRITE"をクリックする。
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/6d76ec08-44d4-21ff-c053-9a84ea88a4fa.png)


※データがすでにある場合は、クリアしてよいか聞かれるので"YES"をクリックする。
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/79eaf347-4e8d-ade8-b279-40c193ee9404.png)

書き込みが進むので、完了するまで待つ。"Prepare to Write... "→"Writing"→"Verifying"と進む。

![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/8c5b0b54-4f4c-f7c8-7c4a-504085d14700.png)
![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/c70598ad-dcbc-69ac-79f9-d40ec3fe77f0.png)
![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/130108f1-b4d0-c622-32ac-d8477a6da016.png)

"Write Successful"のメッセーが出たら"CONTINUE"をクリック。ファイルエクスプローラーにてSDカードの取り出し操作をにて行い、SDカードをPCから抜き取る。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/7e6fe855-5e6f-efab-8e83-ec05ec8a8a5d.png)

以上でラズパイOSのSDカードへのインストールが終了。
誕生日から年齢を計算する関数 [PL/pgSQL]

postgres 9.5
ストアドファンクションは、PL/pgSQLを使用。

sqlだけで誕生日から年齢を計算したいことがあり、
sqlに直書きしたら結構長くて見にくくなってしまったので、ストアドファンクションを定義する。

弊社のdbでは、日付がYYYY/MM/DDの形式で保存されてることが多いので
引数はYYYY/MM/DDを想定してる。

年齢の計算方法は、　
(YYYYMMDD　- YYYYMMDD) / 10000　の小数点以下切り捨てで求める。　

コードは以下

```sql
CREATE OR REPLACE FUNCTION calc_age_from_birth(
 birth_day varchar
 -- birth_day = 'YYYY/MM/DD'
) RETURNS int AS $$	

DECLARE
  converted_to_int_birth_day int;
  converted_to_int_today int;
  calced_age int;
 
BEGIN
   converted_to_int_birth_day := cast(REGEXP_REPLACE(birth_day,'/','','g') as integer);
   converted_to_int_today     := cast(TO_CHAR(current_date, 'YYYYMMDD') as integer) ;
   calced_age                 := trunc((converted_to_int_today - converted_to_int_birth_day ) / 10000,0);
   RETURN calced_age;
END;
$$ LANGUAGE plpgsql;
```




筆者の誕生日で実行、、、

```sql
select calc_age_from_birth('1996/09/08');
=> 25
```

正解。
【ServiceNow】ナレッジ記事内で添付ドキュメントを表示する

##概要
ServiceNowのナレッジ記事にファイルを添付すると、記事内のリンクから保存をするかアプリで開きなおしたりする必要があるかと思います。
ナレッジ記事の画面内にドキュメントファイルを表示させる手順を備忘録として記します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1984141/697df9a9-5a77-6dce-26bc-de2cb8fd2c05.png)
###環境
PDIで作成しています。
バージョンはQuebecです。
System Administrator（admin）で操作しています。
##HTML sanitizerの編集
ドキュメントビューアをHTMLソースコード内で有効にするために最初に[HTML sanitizer](https://docs.servicenow.com/bundle/quebec-platform-administration/page/administer/security/concept/c_HTMLSanitizer.html)のWHITE LISTへ追記します。

・ナビゲーションメニューで［System Definition＞Script Includes］を開きます。
・「HTMLSanitizerConfig」レコードを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1984141/e7819b3b-647f-7a42-27ea-28661d816055.png)
・「Script」フィールドの「HTML_WHITELIST」に以下の記述を追加します。
```
iframe:{
   attribute:["src","width","height"],
   attributeValuePattern:{src:"^\\$viewer\\.do.*$", width:"^[0-9]*%$", height:"^[0-9]*px$"}
  },
```
・「Update」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1984141/b0dfd783-0926-2f6d-bb5f-d1918bd2fcf2.png)
##ナレッジ記事の作成
・ナレッジ記事を作成し、「Knowledge Base」や「Short Description」等の必要事項を入力してファイルを添付します。
・添付後にファイルの右側に表示される［View］をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1984141/71418eca-fc35-65c3-bb0a-7b2c6f5aee4d.png)
・開いたファイルの画面URLの「$viewer.do?～」をコピーしてメモ帳等に控えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1984141/97c8ff66-eba8-5082-9268-ed5de0ad3b02.png)
・ナレッジ記事作成画面に戻り「Article body」フィールドの「Source code」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1984141/e5e18cda-4330-4bca-9375-f9c00c366fcc.png)
・HTML source code入力欄に下記のコードを入力します。
・「OK」ボタンをクリックします。
```
<p><iframe src="ここに前手順で控えた添付ファイルのURLを貼り付けます" width="100%" height="700px"></iframe></p>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1984141/299aa6e0-18b2-220b-5ece-683955ad7dea.png)
その後ナレッジ記事を「Submit/Save」し、承認フローに基づいて記事を公開して完了です。
ナレッジやナレッジベースから記事を開くと添付ファイルがビューアで表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1984141/697df9a9-5a77-6dce-26bc-de2cb8fd2c05.png)
Microsoft information protection(MIP) SDK

AIPのSDKをC#で呼び出すサンプル

■MIP SDKのセットアップ
https://docs.microsoft.com/ja-jp/information-protection/develop/setup-configure-mip

■ラベルの取得
https://docs.microsoft.com/ja-jp/information-protection/develop/quick-app-initialization-csharp

■ラベルを付与
https://docs.microsoft.com/ja-jp/information-protection/develop/quick-file-set-get-label-csharp

■テンプレートの取得
https://docs.microsoft.com/ja-jp/information-protection/develop/quick-protection-app-initialization-csharp
【3】python キャスト（授業資料3 演習）


# 演習問題
値「123」と値「'123'」の違いを説明してください.
「'123' + '123'」の結果がどうなるか確認し、キャストを使って結果が246になるように式を変更してください.

解き終わり次第，[まなBOX](https://daltontokyo.mana-box.jp/epf-web/Servlet/)にて提出しましょう．演習の提出状況で成績判断をします．

→[次の演習]()へ
#### 演習問題一覧は[こちら](https://qiita.com/hakukikun/items/ce55fef4fa1ffefb4e6d)


#引用
[Amazon: たった1日で基本が身に付く! Python超入門](https://www.amazon.co.jp/%E3%81%9F%E3%81%A3%E3%81%9F1%E6%97%A5%E3%81%A7%E5%9F%BA%E6%9C%AC%E3%81%8C%E8%BA%AB%E3%81%AB%E4%BB%98%E3%81%8F%EF%BC%81-Python%E8%B6%85%E5%85%A5%E9%96%80-%E4%BC%8A%E8%97%A4-%E8%A3%95%E4%B8%80-ebook/dp/B074WVKQVP/ref=as_li_ss_tl?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=Python+%E4%BC%8A%E8%97%A4&qid=1586415008&sr=8-1&linkCode=sl1&tag=grit-22&linkId=b689fc38acfbc841b9b1d2dc3af4cc32)
[1日で基本が身につく! Python超入門 - Speaker Deck](https://speakerdeck.com/yuichi110/1ri-deji-ben-gashen-nituku-pythonchao-ru-men)
→こちらのなかのキャストに関する演習問題を取りあげました．Python3初学者限らずコーディング初心者にとっても「正確で」「理解しやすい言葉を用いた」資料だと言えます．是非参照して下さい．
Angularプロジェクト作成

## はじめに

最近仕事でAngularを触り始めました。
まずは環境構築から、自分の備忘録用に残していこうと思います。

## Angularとは

AngularとはGoogleによって開発された**JavaScriptフレームワーク**です。
元々は「AngularJS」という名前でしたが、バージョン2.0から「Angular」という名前に変更されています。

バージョンについては[こちら](https://angular.jp/guide/releases)を参照


## 環境構築

とりあえずプロジェクトを作成してみましょう。

### Node.jsのインストール


Node.jsとはJavaScript実行環境のこと  
[参考記事：Node.jsとはなにか？なぜみんな使っているのか？](https://qiita.com/non_cal/items/a8fee0b7ad96e67713eb)

ReactだろうがVueだろうが、Node.jsのインストールは必要。

インストール後は以下コマンドでバージョン確認が出来ます。

```
$node -v
```

### Angular CLIのインストール

Node.jsをインストールしたことで、Node Package Manager(npm)が使えるようになりました。
次にAngular CLIをインストールします。

```
$npm install -g @angular/cli
```

CLIとはCommand Line Interfaceのことで、これをインストールすることで、プロジェクト作成がコマンド一つで簡単に出来るようになります。

インストール後は以下コマンドでバージョン確認が出来ます。

```
$ng version または ng --version
```


### プロジェクト作成

Angular CLIをインストール出来たので、早速プロジェクトを作成します。
プロジェクトは以下コマンドで作成できます。（途中に色々と聞かれるので選択していく）

```
$ng new プロジェクト名
``` 


### プロジェクト起動

プロジェクトが作成できたので、一度起動して見ましょう。プロジェクトのディレクトリに移動して以下のコマンドを実行します。

```
$ng serve または npm start
```

ローカルサーバが立ち上がるので[http://localhost:4200/](http://localhost:4200/)でページが表示されることを確認しましょう。



ところで `ng serve`と`npm start`ですが、どっちもサーバを起動させるコマンドです。`npm start`は`package.json`に記載された`start`スクリプトを実行しています。`package.json`の`scripts`部分を確認してみると、プロジェクト作成直後は以下のようになっています。

``` package.json
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  }
```
結局どちらも`ng serve`を実行しているようです。
1年間Flutterで開発をしていてわかったアクセシビリティの問題(Android編)

この1年コンスタントにFlutterでコーディングをしていてわかった_スクリーンリーダー(TalkBack)_の問題についての記録です。
(この問題は2022/01/13リリースのベータ版_2.10.0-0.1.pre_で修正されています。)
iOSについては[1年間Flutterで開発していてわかったアクセシビリティの問題(iOS編)](https://qiita.com/yama_1983/items/b669c011874671efdbaa)をご覧ください。

-----

## 文字入力時にボリュームボタンでカーソル移動した時の文字読み上げがない
iOSに比べAndroidは動作の安定性や不具合の修正があり、現状ほとんど問題なく開発ができています。
ただ最近のバージョンで上記の問題が発生しています。
これはAndroid特有のアクセシビリティ機能であり、大変協力な物です。
文字入力中に

- ボリュームダウンボタン  → 左カーソルキー
- - ボリュームアップボタン → 右カーソルキー

の役割を果たします。
スワイプによるジェスチャーでも同様のことができますが、ボタン操作のほうが確実です。
が、残念ながらこのカーソル移動の時にフォーカスされた文字を読み上げない問題が起きています。
これは以前からあった問題ではなくバージョンアップに伴い起きている物です。
私が確認しているところでは_バージョン2.1.0-12.2.pre_までは正常に動作していました。
全てではありませんが、_バージョン2.5.0-5.3.pre_までのいくつかで試してみましたが、読み上げがされませんでした。

-----

## まとめ
上記問題はissueとして報告していますが、暖簾に腕押しな状況です。
ほんとうは最新のバージョンで開発をしたいのですが、この問題のため古いバージョンを使っています。
Flutterの開発に関わっている方やバグ修正の得意な方がいらっしゃいましたら、改善に力を貸していただけますと幸いです。

下記サンプルでTalkBackをONにすると問題の確認ができます。
TalkBackは
設定 → ユーザ補助 → TalkBack
から
_ショートカットの設定_
_TalkBackを使用する_
の順で有効にしてください。
TalkBackがONになるとジェスチャーが変わり、操作に戸惑うことと思います。
上記の順番で有効にすることでいつでも_ボリュームボタンのアップとダウンの同時押し_でON/OFFを切り替えることができます。
端末内にTalkBackの項目がない場合は
[Android ユーザー補助設定ツール - Google Play のアプリ]( https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback&hl=ja&gl=US)
からインストールをお願いします。

[TalkBackサンプル](http://yama3nomori.jp/download/tb.zip)
Quantum Computing

# Quantum Computing Programing Language
- QCL
    - https://github.com/aviggiano/qcl
- Qiskit (IBM)
    - https://qiskit.org/
- Q# (Microsoft)
    - https://docs.microsoft.com/ja-jp/azure/quantum/overview-what-is-qsharp-and-qdk
- Silq (ETH Zurich)
    - https://silq.ethz.ch/
    - https://github.com/PacktPublishing/Quantum-Computing-with-Silq-Programming

# Quantum Computer Could
- Amazon Braket
    - https://aws.amazon.com/jp/braket/
- IBM Quantum
    - https://quantum-computing.ibm.com/
    - https://www.ibm.com/quantum-computing/
- Google
    - https://quantumai.google/quantum-computing-service
スクラムにおける見積もり手法

※ 社内向けメモをそのまま公開しています。

## 提案
1. プロダクトバックログは「Tシャツ見積もり」を使う
2. スプリントバックログは絶対時間を使う

## 調査報告
### プロダクトバックログの見積もりについて
#### 手法
- Tシャツ見積もり
  - S、M、L、XLの4種類

#### タイミング
- スプリントプランニングの前
- スプリントプランニング

### スプリントバックログの見積もりについて
#### 手法
- 絶対時間見積もり

#### タイミング
- スプリントプランニング

#### コツ
- SBIは一つ最大5時間で終わるサイズにする
  - さらに1つ1,2時間で終わるサイズに分割する

### スパイクについて
- スパイクとは、技術的課題に対する質問に答えたり情報を収集したりすることを目的とした作業
- 技術的課題を解決する必要がある場合は、「どのような状態になったら解決となるか」を明らかにする
- タイムボックスを定めてその範囲内で行う
- スパイクの所要時間見込みによって以下のどちらで対応するかを決める
  - バッファで対応する
  - PBに追加し、次のスプリングで対応する

## 参考
https://www.ryuzee.com/contents/blog/7101
https://www.ryuzee.com/contents/blog/3716
https://www.ryuzee.com/contents/blog/7121
https://eh-career.com/engineerhub/entry/2020/05/12/103000
1年間Flutterで開発していてわかったアクセシビリティの問題(iOS編)

この1年コンスタントにFlutterでコーディングをしていてわかった_スクリーンリーダー(VoiceOver)_の問題についての記録です。
Androidについては[1年間Flutterで開発をしていてわかったアクセシビリティの問題(Android編)](https://qiita.com/yama_1983/items/6c51e83b980c512019ab?utm_campaign=post_article&utm_medium=twitter&utm_source=twitter_share)をご覧ください。

-----

## 1. 項目を選択したときのガイドアナウンスが読み上げられない
ボタンや項目などを選択したときには通常
_開くにはダブルタップします_
のようなアナウンスがあります。
これによりユーザは項目が操作可能かどうかを知ることができます。


## 2. リストをスクロールしたときの度合いを読み上げない
通常リストをスクロールさせた場合

* リストの総数
* 表示されている項目の開始位置
* 表示終了位置

が
_全50行中10行目から20行目まで_
のように読み上げられます。


## 3. 垂直スクロールバーにフォーカスされていない
検索をすると表示させることは造作もないことのようですが、残念ながらVoiceOverがフォーカスできていないようです。(水平も同様)
垂直スクロールバーでは

* その画面がトータルでいくつの画面が連なって構成されているのかという情報の読み上げ
* 1本指の下または上のスワイプでスクロールを行うことができる

という利点があります。


## 4. Semanticsクラスのヒントがアナウンスされない
項目に対し、アクセシビリティ機能を付加するクラスが_Semanticsクラス_です。
その中の_hint_ _onTapHint_ _onLongPressHint_ の内容が読み上げられません。
1. によく似ていますが、これはOSがデフォルトで用意している内容をアナウンスします。
(少なくともAndroidではそのように動いていると思われます)
上記の3つは開発者側でアナウンスする内容を指定するプロパティです。
ユーザに明確に操作したときの結果を伝えることができます。

-----

## まとめ
上記は開発をしつつissueとして報告していますが、改善されていない問題です。
Androidの場合は正常に動作しています。
また_WebView()_で記述した場合には発生しません。

issueで報告しても暖簾に腕押しで困っています。
Flutterの開発に関わっている方やバグ修正が得意な方がいらっしゃいましたら改善に力を貸していただけますと幸いです。

下記のサンプルコードで上記4つの問題が確認できます。
VoiceOverをONにしてお試しください。
VoiceOverはSiriでON/OFFができます。
安易に設定から有効にするとジェスチャーが変わり、戸惑われますのでご注意ください。

[VoiceOverサンプル](http://yama3nomori.jp/download/vo.zip)
【GCP】Cloud VPN,Cloud Routerにかんするドキュメント

###CloudVPN
CloudVPNの記事はここ
https://cloud.google.com/hybrid-connectivity?hl=ja
↓
ガイド　https://cloud.google.com/network-connectivity/docs/vpn/how-to?hl=ja

FWの設定
https://cloud.google.com/network-connectivity/docs/vpn/how-to/configuring-firewall-rules?hl=ja

サードパーティーごとの注意
https://cloud.google.com/network-connectivity/docs/vpn/how-to/interop-guides?hl=ja#vendor-specific-notes
ここに記載のある内容はルーターに関するものもある。
例えば、CiscoをみるとCisco ASRはルーター

###CloudRouter
Cloud VPNを作成するとき、BGP経路を作成するためにCloud　Routerも関係してくる
https://cloud.google.com/network-connectivity/docs/router/concepts/overview?hl=ja

#####参考
https://dev.classmethod.jp/articles/gcp-vpc-cloud-vpn-with-cisco-router/
ここがCiscoと接続した記事

VSRはここ　https://www.cpi.ad.jp/managed/detail/vsr.html　
ここはGoogleとは接続できないみたい
【2】複合代入演算子を用いた四則演算（授業資料3 演習）

変数numに3を代入し，複合代入演算子を用いて，

まずnumに16789769を足し，
次にnumから823639を引き，
次にnumに4927492を掛け，
最後にnumを2で割り，

計算過程と解をスクリーンショットし，まなBOXにて提出しましょう．

#参考
[Amazon: たった1日で基本が身に付く! Python超入門](https://www.amazon.co.jp/%E3%81%9F%E3%81%A3%E3%81%9F1%E6%97%A5%E3%81%A7%E5%9F%BA%E6%9C%AC%E3%81%8C%E8%BA%AB%E3%81%AB%E4%BB%98%E3%81%8F%EF%BC%81-Python%E8%B6%85%E5%85%A5%E9%96%80-%E4%BC%8A%E8%97%A4-%E8%A3%95%E4%B8%80-ebook/dp/B074WVKQVP/ref=as_li_ss_tl?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=Python+%E4%BC%8A%E8%97%A4&qid=1586415008&sr=8-1&linkCode=sl1&tag=grit-22&linkId=b689fc38acfbc841b9b1d2dc3af4cc32)
[1日で基本が身につく! Python超入門 - Speaker Deck](https://speakerdeck.com/yuichi110/1ri-deji-ben-gashen-nituku-pythonchao-ru-men)
Dockerコンテナ上でTerraformとAWS CLIを実行する方法

# はじめに

ローカル環境を汚さずに手軽にTerraformとAWS CLIを利用したい...

本記事では、TerraformとAWS CLIの公式Dockerイメージを用いて、Dockerコンテナ上でAWS環境用のTerraformとAWS CLIを実行する方法をご紹介します。

Terraformとは、AWSなどの様々なクラウドサービスの環境を、Terraform用の設定ファイルを元に自動的に構築するツールです。AWSのWeb上のコンソール画面から環境を作成するのではなく、Terraform用の設定ファイルから環境を作成、変更、削除することができ大変便利です。

AWS CLIとは、AWSの操作をコマンドライン上から行えるツールです。

# 前提条件

- AWSアカウントを持っている
- Dockerがインストールされている
  - Windowsの場合: [Docker Desktop for Windows](https://docs.docker.jp/docker-for-windows/install.html) 
  - Macの場合: [Docker Desktop for Mac](https://docs.docker.jp/docker-for-mac/install.html)

# TerraformとAWS CLIの環境構築

## ファイル構成

下記の構成でファイルを作成します。

```yaml:/docker-compose.yml
version: '3'
services:
  terraform:
    image: hashicorp/terraform:1.0.6
    env_file:
      - ./.aws/aws.env
    volumes:
      - ./terraform:/terraform
    working_dir: /terraform
    entrypoint: sh
    tty: true
  aws-cli:
    image: amazon/aws-cli:2.2.36
    env_file:
      - ./.aws/aws.env
    volumes:
      - ./aws-cli:/aws-cli
    working_dir: /aws-cli
    entrypoint: sh
    tty: true
```

```text:/.gitignore
.terraform
*.tfstate
*.tfstate.*
aws.env
```

```text:/.aws/aws.env.default
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=

AWS_REGION=ap-northeast-1
AWS_DEFAULT_REGION=ap-northeast-1
```

```terraform:/terraform/test/main.tf
# プロバイダ
provider "aws" {
    region = "ap-northeast-1"
}

# VPC
resource "aws_vpc" "test-vpc" {
    cidr_block = "10.1.0.0/16"
    instance_tenancy = "default"
    enable_dns_support = true
    enable_dns_hostnames = true
    tags = {
        Name = "test-vpc"
    }
}
```

## IAMのアクセスキーとシークレットアクセスキーを設定

自分のAWSアカウントにログインし、下記のページからIAMのアクセスキーとシークレットアクセスキーを作成します。

- [AWSのIAMアクセスキーの作成画面](https://console.aws.amazon.com/iam/home?#/security_credentials)

下記の環境変数ファイルをコピーして、IAMのアクセスキーとシークレットアクセスキーを設定します。

```text
コピー元: /.aws/aws.env.default
コピー先: /.aws/aws.env

/.aws/aws.env の追記例:
  AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXX
  AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXX
```

不正アクセスの原因になるため、`/.aws/aws.env` はGit等にプッシュしないようご注意ください。
`/.gitignore` で`/.aws/aws.env`をGit対象外にしています。

# Terraformを実行

下記のコマンドを実行してTerraformを実行します。
今回はサンプルとして`test-vpc`の名前でVPCを作成します。

実行対象ファイル: `/terraform/test/main.tf`

```text
> docker-compose up -d

> docker-compose exec terraform sh
# cd /terraform/test/
# terraform init  (Terraformの初期化を行う。初回に1回だけ実行)
# terraform plan  (AWSの変更内容を確認します。まだAWSには反映されません)
# terraform apply  (実際にAWS上にtest-vpcのVPCを作成します。
「Enter a value:」と表示されるので「yes」を入力します)
# terraform destroy  (AWS上のtest-vpcのVPCを削除します。
「Enter a value:」と表示されるので「yes」を入力します)
# exit

> docker-compose down  (もうDockerコンテナを利用しない場合)
```

# AWS CLIを実行

下記のコマンドを実行してAWS CLIを実行します。
今回はサンプルとしてEC2のリージョン一覧を表示します。

```text
> docker-compose up -d

> docker-compose exec aws-cli sh
# aws ec2 describe-regions  (EC2のリージョン一覧を表示。エラーになる場合は /.aws/aws.env の内容が間違っている。q を入力すると終了)
# exit

> docker-compose down  (もうDockerコンテナを利用しない場合)
```

# まとめ

Dockerコンテナ上でTerraformとAWS CLIを使うことにより、ローカル環境を汚さずに手軽にTerraformとAWS CLIを利用することができました。

このファイル構成でgit等でソース管理することにより、新しいプロジェクトメンバーが増えた際に、Gitのクローンと`docker-compose up -d`の実行だけで、プロジェクト全体で同じバージョンのTerraformとAWS CLIのローカル環境を素早く作成することができます。
【演習1】計算してみよう(授業資料1 演習) 

授業にて．python3で小学生レベルの計算（四則演算，累乗，剰余）について扱いました．以下の式をコマンドで実行し，スクリーンショットを[まなBOX](https://daltontokyo.mana-box.jp/epf-web/Servlet/)にて提出しましょう．

111×113の積
6782÷395の商（小数で構わない）
3689469÷86736の剰余(余り)
45の6乗

ヒント：
pythonもしくはpython3というコマンドを実行すると計算ができるようになります（>>>が表示）



→[次の演習へ](https://qiita.com/hakukikun/items/9535d71e76a67d9844fd)
AWS S3のCSVにWatson Studioからアクセスする

AWS S3のCSVにWatson Studioからアクセスします。
あらかじめS3にはバケットs3testwsとユーザーs3testwsuserを作っておきます。

参考：AWS S3の特定bucketにCLIやAPIでアクセスする設定 - Qiita 

https://qiita.com/kawada2017/items/40acfbaf6bce8f8011cf

Watson Studioからは「接続」オブジェクトでバケットへの接続情報を定義し、「接続データ」オブジェクトでバケット内のCSVを定義するとアクセスできるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/13cda552-8eb5-eca8-01d2-62312a8feb46.png)


#1. 接続オブジェクトの作成
「プロジェクトに追加」で「接続」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/5e67e258-5d0a-a34e-7b51-630e5eb33122.png)

接続タイプにAmazon S3を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/29da20a8-e9ce-c8b9-156c-b8a7e339d879.png)

接続の作成で詳細を入力します。
名前: 任意ですが、ここではバケット名を指定しています。
バケット: s3testws
エンドポイントURL：以下からリージョンにあったURLを探します。

https://docs.aws.amazon.com/ja_jp/general/latest/gr/s3.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/d3f4aead-d388-14ba-909d-2ae2a14ab8cd.png)

リージョンがap-northeast-1の場合は、https://s3.ap-northeast-1.amazonaws.comです。

リージョン:ap-northeast-1
アクセスキー：s3testwsuserのアクセスキーIDを指定します。
秘密鍵：s3testwsuserのシークレットアクセスキー指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/d3942b3e-fc48-7966-f67c-a79dc5f4c94d.png)

#2.接続データの設定
「プロジェクトに追加」で「接続データ」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/de6fb205-7e5e-b182-e684-fba93bea7088.png)
「ソースの選択」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/096b28cf-f93d-2e2e-09a6-7acfc38a56e7.png)

「接続」からs3testwsを選び、test.csvを選び、「選択」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/4142cec6-a2b1-c103-c129-22e556a7c6bd.png)

名前test.csvを付けて、作成をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/78bf667d-053b-3332-6f48-5fea8fe47da8.png)

データ資産にtest.csvが登録されたのでクリックして中身を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/1d759742-d910-307c-825d-e6397c39e56f.png)

中身を確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/4b2e482d-da58-5002-926d-1481feff7fb6.png)
ページング　kaminari ページャ

```ruby:gem
gem 'kaminari','~> 1.2.1'
```
```ruby:ターミナル
$  bundle install
$ rails g kaminari:config
$ rails g kaminari:views default
```


```Ostomy/index.html.erb
:
<%= paginate @ostomies %>
```
<h2>ページ数　指定する</h2>
<p>.page(params[:page]).reverse_order</p>
```app/controllers/〜controller.rb

#デフォルトで件数設定されているので後で変更
：
def index
  @ostomies= Ostomy.all.page(params[:page]).reverse_order
end

#それか.per(ほしいページ数)　　　　.reverse_order：最新から表示
def index
  @ostomies= Ostomy.all.page(params[:page]).per(7)
end
def index
  @ostomies= Ostomy.all.page(params[:page]).per(7).reverse_order
end

```
```config/initializers/kaminari_config.rb

Kaminari.configure do |config|
  # config.default_per_page = 25  デフォルトでは２５件となっているここ変更
  # config.max_per_page = nil
  # config.window = 4
  # config.outer_window = 0
  # config.left = 0
  # config.right = 0
  # config.page_method_name = :page
  # config.param_name = :page
  # config.max_pages = nil
  # config.params_on_first_page = false
end

```
<h2>日本語化する</h2>
```config/application.rb
config.i18n.default_locale = :ja
```
```config/lacales/ja.yml
ja:
  views:
      pagination:
        first: '最初'
        last: '最後'
        previous: '前ページ'
        next: '次ページ'
        truncate: '〜'
```
# 毎月壁紙を自動で変えたい！その２

# 毎月壁紙を自動で変えたい！その２
前回の記事で毎月自動で壁紙を変えるプログラムを作ってみたのですが、PCを再起動すると壁紙がリセットされてしまったので、いろいろ試行錯誤してみました。

https://qiita.com/ayk_f/items/1ffd640211de8c936b3f

# 改善点
プログラムを毎日実行すると毎日壁紙ダウンロードすることになり、それはちょっとナンセンスだと思うので`if文`を使って条件分岐してみました。
また、python環境が無くても動くように`exe形式`に変換して動かすことにしました。

# 条件分岐
if文を使って、指定された格納先に「wallpaper_yyyymm_1.jpg」というファイルがないかを判定。
プログラム実施月の画像ファイルがない場合は、壁紙をダウンロードします。

まず、実施日の日付を取得し、ファイル名を作成します。これは前回と同じです。

~~~python3
	#--- import Today's date ---
	dt_now = datetime.datetime.now()
	print(dt_now.strftime('%Y/%m/%d'))

	#--- path make ---
	dst_path = r'C:\Users\ayk_f\wallpaper\wallpaper_'+dt_now.strftime('%Y%m')+'_1.jpg'
	wname = 'wallpaper_'+dt_now.strftime('%Y%m')+'_1.jpg'
	print('path: '+dst_path)
~~~

~~~
$ python wallpaper_v2.py
2021/09/13
path: C:\Users\ayk_f\wallpaper\wallpaper_202109_1.jpg
~~~

ファイル名が作れたので該当するファイル名がないかを判定し、ない場合のみ壁紙をダウンロードします。

~~~python3
	is_file = os. path.isfile(dst_path)
	print(is_file)

	if is_file:
	    print(f"{wname} is a file.")
	    pass #なにもしない
	else:
	    print(f"{wname} is a not file.")
~~~

`os. path.isfile()`関数は、指定したファイル名が存在する場合にTrueを返す、という関数らしいです。
今回は「指定したディレクトリに wallpaper_202109_1.jpg が存在する場合はなにもしない、存在しない場合はダウンロードする」ということになります。
`pass`は、条件分岐の結果何もしない場合に入れておく必要があります。
今回は試験的に`print`を実行していますが、実際はコメントアウトするため`pass`を入れています。

参考までに
今月の壁紙（wallpaper_202109_1.jpg）があるとき～～～:laughing::laughing::laughing:！！！

~~~
$ python wallpaper_v2.0.py
2021/09/13
path: C:\Users\ayk_f\wallpaper\wallpaper_202109_1.jpg
True
~~~

ないとき～～～～:sob::sob::sob:

~~~
$ python wallpaper_v2.0.py
2021/09/13
path: C:\Users\ayk_f\wallpaper\wallpaper_202109_1.jpg
False
~~~

~~このネタがやりたかっただけ・・・・（笑）~~

ないとき（else時）に壁紙をダウンロードするコードを実行し、最後に壁紙を設定するコードを実行すれば完成です。
壁紙の設定は再起動時にリセットされてしまうので、if文の外に出しておく必要があります。


# コードのexeファイル化
[この記事](https://techacademy.jp/magazine/18963)の通りにやりました。
参考までに、記録しておきます。

### 1. pyinstallerをインストール
Pythonをインストールしている状態で、`pyinstaller`をインストールします。

~~~
$ pip install pyinstaller
~~~

### 2. exeファイル作成
インストールが完了したら、`exe形式`のファイルを作成します。

~~~
$ pyinstaller wallpaper_v2.0.py --onefile
~~~

`--onefile`オプションは、関連ファイルを1つにまとめてくれるとのこと。省略可能です。

実行後、3つのフォルダと`spec形式`のファイルができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1953283/9260f65e-c717-25ea-d4f7-58620851ed05.png)
distフォルダの中に、作成した`exe形式`のファイルが作成されています。
これで、`exe形式`に変換できました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1953283/15137ee9-ecdc-5d73-261c-1cfcb3c974b6.png)

# さいごに
前回投稿したコードの改版についてでした。
折角exe化したので、タスクスケジューラをやめてwindowsのスタートアップにほおりこんでおくことにしました。
毎日PC立ち上げたタイミングで実行してくれるので、もうこれで安心のはず・・・。


# 参考サイト
- [Python でファイルの存在確認をする - Python入門](https://python.keicode.com/lang/file-exists.php)
- [Pythonのファイルをexe化する方法【初心者向け】 - TechAcademyマガジン](https://techacademy.jp/magazine/18963)
- [Pythonのpass文の意味と使い方 - note.nkmk.me](https://note.nkmk.me/python-pass-usage/)
Cognitoのtoken検証

Cognitoログイン時に取得した、idToken　及び　accessTokenの検証。
また、payloadを返却する。

# 事前準備
```
npm i --save jsonwebtoken jwk-to-pem
```

# ロジック
- 不正トークンや有効期限切れはこれで弾けるはず

```
import * as jwt from 'jsonwebtoken'
import * as jwkToPem from 'jwk-to-pem'

async decodeToken(token) {

    const decode =  jwt.decode(token, {complete: true})

    // 検証用のデータ取得
    // ここではhttp通信にnsetjsのライブラリ使っているが、取れればなんでも良い。
    const result = await this.httpService.get(`${decode.payload.iss}/.well-known/jwks.json`).toPromise()

    // kid一致したデータを取得
    const jwk = result.data.keys.find(key => {
      return key.kid === decode.header.kid
    })
    if (!jwk) {
      throw new Error("cognito's jwks is not found.")
    }

    const pem = jwkToPem(jwk);
　　　　　　　　// 検証
    jwt.verify(token, pem, { algorithms: ['RS256'] }, function(err, decodedToken) {
      if (err) {
        throw err
      }
    });

    return decode.payload
  }
```

# まとめ
Cognitoをtokenで毎回確認していれば不要かもって検証。
同時アクセスでCognioのクォータが引っかかりそうとかあれば、この辺りを使って工夫する必要あり。

# 参考
https://github.com/awslabs/aws-support-tools/tree/master/Cognito/decode-verify-jwt
https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html
https://qiita.com/FukuharaYohei/items/963b3ff293bf32062aa2
prophet で株価予測メモ

FB社が公開している時系列予測ツール prophet を使うと、今後の株価の動きが予測できるそうです。使い方のメモ。　Google Colaboratoryで実行できます。

### インストルール
```python
!pip install prophet
```

### 株価データの準備
stooq から取得

```python
import pandas_datareader.data as pdr

df = pdr.DataReader("{}.JP".format(2929), "stooq").sort_index()
df.tail()
```

![スクリーンショット 2021-09-13 12.15.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/4b83df57-930c-a4d8-a3a0-4f0cc6a12d57.png)

### 分析用に加工
prophet で分析するために ds:日付, y:終値のカラムを設ける

```python
df["ds"] = df.index
df = df.rename(columns={'Close': 'y'})
df.tail()
```

![スクリーンショット 2021-09-13 12.17.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/abac5b25-497c-0f96-a371-7ae066f88033.png)

### 分析実行

```python
from prophet import Prophet

m = Prophet()
m.fit(df)
future = m.make_future_dataframe(periods=365)
forecast = m.predict(future)
fig = m.plot(forecast)
```

![スクリーンショット 2021-09-13 12.26.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/70e4f19b-c9b1-cc80-f524-0182b99fb231.png)


2021-09-10 以降のグラフが予想結果
LaravelのRedisでワイルドカードのパターンに一致するキーを一括削除する

Redisではキーにワイルドカードを使って一括削除するコマンドがありません。
今回はLaravel5.8でRedisのキーをワイルドカードを使って、一括削除する方法を共有します。

## 一括削除する方法（prefixあり）

```php
$keyPattern = 'hogehoge_*';
$keys = array_map(function ($key) {
    return str_replace(config('database.redis.options.prefix'), '', $key);
}, Redis::keys($keyPattern));
if (!empty($keys)) {
    Redis::del($keys);
}
```

複数のコネクションを使っていてそれぞれprefixが違う場合は、
`config('database.redis.options.prefix')`の部分を適宜修正してください。

Laravel5.8からはデフォルトでprefixが指定されているので上記のprefixありで実行してください。

## prefixを使っていない場合はこちらでもOK

```php
Redis::del(Redis::keys('hogehoge_*'));
```
Laravel5.7はデフォルトだとprefixが指定されていないので、こちらでOK。

***

今回はリリース時の一部キャッシュのクリアでしたので、
`php artisan tinker`で上記のコードを実行しました。

### 参考URL
https://stackoverflow.com/questions/58506043/delete-redis-keys-matching-a-pattern-laravel-5-7
【Python】macOSのcronでpythonを自動実行してみた

#はじめに
macOSでPythonのプログラミングを書くようになった後はそれを自動実行させるのが次のステップかなと思います。
今回はcronを使ってpythonを自動実行する方法を記載します。

#環境
Python3.9
macOS Catalina10.15.7

#方法
####1.cronにアクセス権を付与
システム環境設定＞セキュリティとプライバシー＞プライバシー＞フルディスクアクセス
の順にクリックします。
次に、鍵マークをクリックして管理者パスワードを入力後、「＋」ボタンを押します。
![スクリーンショット 2021-09-13 10.41.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/d3f3f632-fe59-0e7d-9cf6-3bb1d0e59ac0.png)

アプリケーションの選択画面で[command] + [shift] + [G]押します。
検索バーに　/usr/sbin/cron　と入力してcronを追加します。

![スクリーンショット 2021-09-13 10.42.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/af27da02-9da3-8060-65c9-0246b2636fcd.png)

####2.ターミナルを起動
ターミナルを起動します。
Python3のプログラムの場所を[which python3]コマンドで確認します。

```TERMINAL
% which python3
/Library/Frameworks/Python.framework/Versions/3.9/bin/python3 
```
次に、デスクトップに置いたプログラムの位置を確認します。
右クリックして[情報見る]をクリックし[場所]を選択して[control] + [C]でコピーします。
メモに貼り付けておいて下さい。
![スクリーンショット 2021-09-13 11.24.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/e803b781-529a-6455-a8c8-451d2cafee3d.png)

メモに貼り付けたら、最後に[/とファイル名]を追加します。
以下の例は「/Mac_SBI_IPO.py」を追記しています。

/Users/hirockio/Desktop/python/Mac_SBI_IPO.py

####2.cronに記入
ターミナルをもう一つ開きます。
以下のコマンドを入力します。

```TERMINAL
% crontab -e 
```

以下の画面が開いたら、i をクリックします。
![スクリーンショット 2021-09-13 10.24.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/f082fc17-f188-eb37-8043-9596372540da.png)

画面下部が--INSERT--となったら記入できます。

![スクリーンショット 2021-09-13 10.27.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/2f60d69e-132e-4431-9c5d-15ed081c62e0.png)

####スケジュールの書き方

```
"分 時 日 月 曜日 /Python3のフルパス /実行したいプログラム"
指定しない場合は　*　を入れます。
```


(例)毎朝９時に実行する場合の例

```
0 9 * * * /Library/Frameworks/Python.framework/Versions/3.9/bin/python3 
/Users/hirockio/Desktop/python/Mac_SBI_IPO.py
```

分 0〜59
時 0〜23
日 1〜31
月 1〜12
曜日 0〜7（0,7=日曜、1=月曜、2=火曜、3=水曜、4=木曜、5=金曜、6=土曜）

###サンプル
毎朝8:30に実行するなら、30 8 * * * /フルパス /Mac_SBI_IPO.py
毎週水曜の18:45に実行するなら、45 18 * * 3 /フルパス /Mac_SBI_IPO.py
毎月26日の23:00に実行するなら、0 23 26 * * /フルパス /Mac_SBI_IPO.py



####はまり注意
上記の間は全て半角スペースです。
例えば、/フルパス[ここ]/実行したいプログラム
[ここ]に改行してしまうとエラーになって実行されません！

Python3.9でデスクトップにあるPythonフォルダ内のMac_SBI_IPO.pyを毎日11時20分に実行するサンプルは以下となります。
必要に応じてコピーしてお使いください。

```
20 11 * * * /Library/Frameworks/Python.framework/Versions/3.9/bin/python3 /Users/hirokio/Desktop/python/Mac_SBI_IPO.py
```
貼り付けます。
![スクリーンショット 2021-09-13 11.53.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/12023f18-85dc-4f2e-591a-6242c4e68397.png)

貼り付け後に「esc」を押しコマンドモードに切り替えてから　:wq　と入力して、returnキーでcronを保存します。

保存の際に以下のエラーが出た場合は文法が間違っています。
yを押して、半角スペースや書き方をもう一度見直してみて下さい。

```
crontab: errors in crontab file, can't install
Do you want to retry the same edit? 
```


#最後に
自動実行できましたでしょうか。
私はこれまで基本Windowユーザで、pythonはWindowsで書いていました。
自動実行には標準でインストールされている「タスクスケジューラ」を利用していました。

まぁこれが前回の実行結果→[0x1]で止まっていることが多いです。。。昨日まで動いていたのに・・・。
その原因追求に工数がかかります。

今のところWindowsよりmacOSの方が安定している印象です。
ご参考になれば幸いです。
Franka libfrankaネットワーク性能不足

Lenovo Yoga で実行

non-reltime-kernel で以下が表示されるのは当然

```shell
$ uname -a
Linux imi-masumi 5.4.0-81-generic #91~18.04.1-Ubuntu SMP Fri Jul 23 13:36:29 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
$ sudo ./generate_cartesian_pose_motion 172.16.0.2
WARNING: This example will move the robot! Please make sure to have the user stop button at hand!
Press Enter to continue...

libfranka: Running kernel does not have realtime capabilities.
$ 
```

reltime-kernel で以下が表示されるのが原因不明

```shell
$ uname -a
Linux imi-masumi 4.14.12-rt10 #1 SMP PREEMPT RT Sat Jul 17 18:45:55 JST 2021 x86_64 x86_64 x86_64 GNU/Linux
$ sudo ./generate_cartesian_pose_motion 172.16.0.2
WARNING: This example will move the robot! Please make sure to have the user stop button at hand!
Press Enter to continue...

libfranka: Move command aborted: motion aborted by reflex! ["communication_constraints_violation"]
control_command_success_rate: 0.488372
$ 
```

このエラーをネットで検索すると以下が見つかる
CPUのクロックが低いのか、ネットワークの性能が低いのか
https://github.com/frankaemika/libfranka/issues/60
https://github.com/frankaemika/libfranka/issues/15
https://frankaemika.github.io/docs/troubleshooting.html#motion-stopped-due-to-discontinuities-or-communication-constraints-violation
https://frankaemika.github.io/docs/troubleshooting.html#simple-ping-tests

CPUのクロックを以下のように上げてみる

```shell
$ sudo sh -x cpuset.sh 
+ sudo cpufreq-set -g performance -d 4600000 -c 0
+ sudo cpufreq-set -g performance -d 4600000 -c 1
+ sudo cpufreq-set -g performance -d 4600000 -c 2
+ sudo cpufreq-set -g performance -d 4600000 -c 3
+ sudo cpufreq-set -g performance -d 4600000 -c 4
+ sudo cpufreq-set -g performance -d 4600000 -c 5
+ sudo cpufreq-set -g performance -d 4600000 -c 6
+ sudo cpufreq-set -g performance -d 4600000 -c 7
$ sh -x cpuinfo.sh 
+ cpufreq-info -c 0 -f
4161928
+ cpufreq-info -c 1 -f
3490430
+ cpufreq-info -c 2 -f
3074129
+ cpufreq-info -c 3 -f
3488721
+ cpufreq-info -c 4 -f
3140578
+ cpufreq-info -c 5 -f
4119507
+ cpufreq-info -c 6 -f
3069097
+ cpufreq-info -c 7 -f
3468292
$
```

pingを実行すると以下の結果

```shell
$ sudo ping 172.16.0.2 -i 0.001 -D -c 10000 -s 1200

[1631537154.993952] 1208 bytes from 172.16.0.2: icmp_seq=9998 ttl=64 time=0.819 ms
[1631537154.994909] 1208 bytes from 172.16.0.2: icmp_seq=9999 ttl=64 time=0.776 ms
[1631537154.995916] 1208 bytes from 172.16.0.2: icmp_seq=10000 ttl=64 time=0.783 ms

--- 172.16.0.2 ping statistics ---
10000 packets transmitted, 10000 received, 0% packet loss, time 10059ms
rtt min/avg/max/mdev = 0.360/0.781/0.924/0.031 ms
$ sudo ping 172.16.0.2 -i 0.001 -D -c 10000 -s 1200 | grep rtt
rtt min/avg/max/mdev = 0.216/0.782/0.975/0.050 ms
$ sudo ping 172.16.0.2 -i 0.001 -D -c 10000 -s 1200 | grep rtt
rtt min/avg/max/mdev = 0.300/0.782/0.970/0.052 ms
$ sudo ping 172.16.0.2 -i 0.001 -D -c 10000 -s 1200 | grep rtt
rtt min/avg/max/mdev = 0.287/0.782/0.947/0.049 ms
```

平均0.78msecだと性能が低い様子
AzureのRunBook(PowerShell)からSendGridを利用してメール送信する

## Azureで無料のSendGridのアカウントを作成する
よく纏められたサイトがあったのでそちらで作成してみてください。

https://www.tama-negi.com/2021/02/20/azure-sendgrid-free/



## 資格情報を作成する

| 項目名 | 設定値の説明 | 入力例　|
|:-:|:-:|:-:|
| 名前　　　 | 任意の名前　　　　　　　　　　　　　　　　　　　　 | SendGridAccount |  
| ユーザ名　 | SendGridアカウント？メアド？迷わず`固定`で入力　　  | `apikey` | 
| パスワード | APIを作成した時に1度しか表示されないパスワード 　　 | *** |

　

資格情報作成時のイメージ
![認証情報.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2005333/1bbe1c68-86c5-08a0-d0e6-31a9c42660f9.png)



SendGridサイトでのAPIKey作成時のイメージ
（パスワードはこのタイミングで1度だけしか表示されないので控えておく）
 ![APIKeyの発行.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2005333/d32bd086-0198-96e6-1938-ad4af573e401.png)


## Runbookを作成する

RunBook作成時のイメージ

![runbookの作成.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2005333/fac522f8-ce9e-bed9-6132-91ab390d1db7.png)




## PowerShellコード部分をシンプルに記載する

```

$SmtpCredential = Get-AutomationPSCredential -Name "SendGridAccount"

Send-MailMessage    -To "宛先のメールアドレス" `
                    -Subject "件名" `
                    -Body "from sendgrid ..." `
                    -UseSsl -Port 587 `
                    -SmtpServer "smtp.sendgrid.net" `
                    -From "発信元のメールアドレス" `
                    -Encoding ([System.Text.Encoding]::UTF8) `
                    -Credential $SmtpCredential

```


:::note 

 【今回躓いたところ】

 ・ SendGridのアカウントを作成する手順で、アカウント設定したメールアドレスに確認メールが届きますが、迷惑メールボックスに入っていて気付きませんでした。

 ・ 資格情報のユーザ名で迷いました。

:::
SRv6 End.DT4を試してみた

Linuxで SRv6 End.DT4 functionがサポートされたが情報があまり公開されていないため、
利用方法をまとめてみました。

https://lore.kernel.org/lkml/20201107153139.3552-5-andrea.mayer@uniroma2.it/


#構成例
![srv6-network-end-dt4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134927/5ac0fbfb-6b69-13bc-cc81-81f68bc5e412.png)


# SRv6 End.DT4とは
SRv6ルーターのエンドポイントノードが SRヘッダーを外して、そのルーターの指定された VRF RIBをルックアップして送信する Endpointファンクションである。
End.DX4の場合、コネクテッドな IPv4 Next-hopしか送信できないため、（ルーティングテーブルを参照しない）より柔軟な構成が可能である。


# Build Linux kernel & iproute2

## Ubuntu20.04 Linux kernel ビルド
Linuxの End.DT4は vrf strict modeの有効化が必要なため、CONFIG_NET_VRFが有効化されたカーネルが必要がある。
Ubuntu20.04の genericカーネルでは有効化されていないため、ビルドし直す必要がある。

以下のページのカーネルビルド方法を参考に、カーネルのビルド設定ファイル `.config` の CONFIG_NET_VRFを有効に変更してビルドする。
(CONFIG_NET_VRF=y) 

```
# vi .config
CONFIG_NET_VRF=y
```

https://qiita.com/Brutus/items/3ca1237efdf1711a6428

## iproute2最新版インストール
iproute2 を最新版をインストールする。

https://wiki.linuxfoundation.org/networking/iproute2


# 設定
細かい基礎設定は省きます。

## Router A

```
ip route add default encap seg6 mode encap segs fd01:b::1 dev ens192
ip -6 route add fd01:a::1 encap seg6local action End.DX4 nh4 192.168.0.2 dev ens224
```

## Router B
vrf strict modeを有効にする。

```
# sysctl -wq net.vrf.strict_mode=1
```

End.DT4は vrftableしか lookupできないので、vrfを作成する。

```
ip link add vrf100 type vrf table 100
ip link set vrf100 up
ip link set dev ens224 master vrf100
ip route add default via 192.168.1.1 table 100
ip route list vrf vrf100

ip route add 192.168.0.2 encap seg6 mode encap segs fd01:a::1 dev ens192 table 100
ip -6 route add fd01:b::1 encap seg6local action End.DT4 vrftable 100 dev ens192
```
RubyKaigi Takeout 2021参加したYO

はいどうもー！Ruby on RailsエンジニアYOです。
先日RubyKaigi Takeout 2021に参加したので、個人的に面白いセッション、感想も含めてメモりたいです。
個人向けのメモ程度の内容ですので、イベント自体に興味ある方は公式のYoutubeアーカイプ~~待ちましょうね。~~見てね：

https://www.youtube.com/playlist?list=PLbFmgWm555yYgc4sx2Dkb7WWcfflbt6AP

コロナの状況がまだ落ち着いていないので、今年のRubyKaigiもTakeout形式での主催になります。サイトはこちらです：
https://rubykaigi.org/2021-takeout

## (個人的に)面白かったセッション

イベントのタイムスケジュールとセッション表：

https://rubykaigi.org/2021-takeout/schedule#day1

**以下一日目のセッション**

### TypeProf for IDE: Enrich Dev-Experience without Annotations(by Yusuke Endoh)

Ruby向けの型推測ツール（？）を作ったので、そのメリットとまだバグってるところの共有です。Rubyは静的型言語じゃないので、型はきっちり決めていなくて、渡された値によって型が決まります。
methodのautocompleteや、間違った関数を渡すときにもIDE上で警告を出せます。

感想：そういうツールを作るときの考え方は自分全く考えたことなかったので（考える必要もなかった）、その中身の話をしてくれて大変勉強になりました。あと世の中はどんどんVSCodeなので、そろそろIDEも切り替えたい。

slide: https://www.slideshare.net/mametter/typeprof-for-ide-enrich-development-experience-without-annotations

### RuboCop in 2021: Stable and Beyond(by Koichi ITO)

RuboCop 1.0 & それ以降のバージョンの話。
`--parallel` optionで並行実行ができます！
自動修正がもっとよくなったとか、`-A` optionで全部修正もできます（危険ですが。。。）

感想：Rubyやってる人ならほぼ全員が使ってるRuboCop、大変便利なツールを作ってくれてありがとうございます！書き方の指摘などで、勉強になることも何回かありました！

### Ruby Archaeology(by Nick Schwaderer)

Ruby考古学の授業を受けた感じです。
昔のRubyの書き方や、歴史を、今もよく使われてるツールのcommit日付が古いコードからピックアップして解説した感じです。


感想：良い意味での変人感が溢れてるスピーカーです。ｗあと色々お土産くれます(ruby version 1.8のvagrantbox?)。

vagrantbox: https://app.vagrantup.com/schwad/boxes/ruby_archaeologist

**以下二日目のセッション**

### Ractor’s speed is not light-speed(by Satoshi "moris" Tagomori)

**R**uby **Actor**からとって、Ractorと呼ぶらしいです。
RubyのParallel処理のために開発された新機能（？）らしいです。
自分はRactorの存在を今日まで知らなかったので、もうちょい勉強すべきです（土下座）
まだ大規模アプリケーションで検証していないので、本当に速くなるかどうかがまだ不明です。

感想：ある意味で今まで知らなかったことを知ることになったので、これからは少しずつアンテナを張って情報収集したいです！

### Ruby Committers vs the World

いわばRuby Commitersたちと対話できるセッション！
というものの、中の人が話しつつ、チャット欄を見てみんなの質問や疑問に答える感じのセッションです。
金曜日の午後でもあるため、ほぼ飲み会感が出てます。ｗ

感想：あぁー我々は巨人の肩の上に立ってるのだなぁーと感じさせました。そしてその巨人達を見る機会ができてよかったです。

**以下三日目のセッション**

### Do regex dream of Turing Completeness?(by Daniel Magliola)

「Game of LifeをRubyのregexだけで、実装できないか？」と、すごくチャレンジングなハックをやっている人です。
化け物みたいなでかいregexを生成して一発で置換させる方法です。
Turingマシーンの話も出てました。

感想：これもマニアックなセッションです。でもやってる試みがとっても面白いで、聞いてて楽しいセッションです。

資料&slide: https://github.com/dmagliola/regex_game_of_life

### Dive into Encoding(by Mari Imaizumi)

Rubyの文字エンコードを理解するために、IROHAエンコードを作った話です。
Rubyの文字エンコードをどうやって作られたのか、どうやって新しいエンコードを作るのか知ることができます。
Rubyのカーソルがかわいい。

感想：普段何も考えずに使ってる文字エンコードの中身がしれて、少し成長しました。最近は日本語の文字化けは結構出なくなったので、だいぶ楽な世の中になったなぁー

slide: https://speakerdeck.com/ima1zumi/dive-into-encoding

### Matz Keynote(by Yukihiro "Matz" Matsumoto)

我らRubyの生みの親、Matzさんからのキーノートです。
Matzさんのキーノートは過去に数回も聞きましたが、2.5 -> 2.7 -> 3.0 -> 3.1で、rubyのバージョンアップの話です。
2.7 -> 3.0 までは聞きましたが、それ以降は暫くブリなので、raptorやパフォーマンス向上なども結構進めたので、いい話です。
３日間のセッションの振り返り＆総括もしていました。
Rubyを速くすると賞金がもらえるシステムも考案中みたいで、Rubyがどんどん速くなることを押したいです！みんなも支援できればお願いします！（Rubyふるさと納税で盛り上がった！）

感想：Ruby 3.0も去年１２月２５日にリリースされて（クリスマスの日に毎年りりーするらしい）、そろそろ新しいバージョンも使って行かないとどんどん置いていかれちゃいそうです。

## 全体の感想

コロナで世の中がリモートワークの流れになりました。通勤時間が減って、個人の自由時間が増えたが、孤独との戦いや、精神的なストレスの対処をしてそろそろ一年半過ぎました。エンジニアとしてもニューノーマルに慣れてきた（と思う）ので、また昔見たいに、いろんな処の勉強会に参加して、新しい技術をどんどん触っていきたいです！
そんな考えを改めたイベントでした！
とりあえずasakusa.rbを調べて、次の勉強会から参加したいです！
composer installした際、メモリエラーになる場合の対応

docker環境で`composer install`した際、メモリエラーになる場合の対応。

```
PHP Fatal error:  Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes) in phar:///usr/bin/composer/src/Composer/DependencyResolver/Solver.php on line 223
Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes) in phar:///usr/bin/composer/src/Composer/DependencyResolver/Solver.php on line 223
```

`COMPOSER_MEMORY_LIMIT=-1`を追加して`composer install`を実行する。

```
COMPOSER_MEMORY_LIMIT=-1 composer install
```
nuxtで環境構築エラー String does not match the pattern of "^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$".　

#知らずに入口でつまづいた話
nuxtに限りませんが、初学者あるあるかもしれません。nuxt.jsの学習中の環境構築にて

```
$ npx create-nuxt-app my_app
$ cd my_app
$ npm run dev
```
をする所、どうせ「my-app」部分はフォルダが生成されるから、いいやと思い

```
$ npx create-nuxt-app
$ npm run dev
```

として、作業を進めていた所、作業途中で、何やらエラーが、、、

```
//エラーメッセージ
String does not match the pattern of "^(?:@[a-z0-9-*~][a-z0-9-*._~]*/)?[a-z0-9-~][a-z0-9-._~]*$".
```

```package.json
{
  "name": "MyApp", //ここが間違い
  "version": "1.0.0",
  "private": true,
```
<経緯>
デスクトップに「MyApp」フォルダを作る　
→ エディタのワークスペースにデスクトップの「MyApp」フォルダを追加。
→ 直接「$ npx create-nuxt-app」
→ 作業途中にエラー発生！！
→ 以下、規約がある事知らず...

**:point_up:nameの主な規約！**
・214文字以下(@scope/を含む)
・一文字目は「.(ドット)」「_(アンダースコア)」以外
**・大文字は禁止**
・URL、コマンドライン引数、フォルダ名の一部になるため、URLで使用可能な文字、記号

結局、以下で作業進めました。皆さんも気をつけてください。

```
$ npx create-nuxt-app my_app
$ cd my_app
$ npm run dev
```
***
参考
[nuxt.jsガイド](https://ja.nuxtjs.org/docs/2.x/get-started/installation)
[package.json の 仕様 (日本語)](https://garafu.blogspot.com/2016/11/packagejson-specification-ja.html)
単体テストの下準備　手順

※著者がiMacユーザーの為、
コマンドは「ターミナル」で実行するものとして記述しています。

Ruby on Railにおける
単体テストの手順をまとめます。

1. gem 'rspec'インストール
2. rails g rspec:install
3. .rspecに--format documentation
4. rails g rspec:model モデル名

#1. gem 'rspec' インストール

Gemfileに記述後、コマンドでbundle installをかけます。

注意点は、Gemfileの行末ではなく
group :development, :test do
の箇所に記述するところ。


```ruby:Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails', '~> 4.0.0'
end
```
```ruby:ターミナル
% bundle install
```

#2. rails g rspec:install
さらに、コマンドでrailsにrspecをインストールします。

```ruby:ターミナル
% rails g rspec:install
```

#3. .rspecに--format documentation
.rspecファイルに記述を追加します。
これを入れることで、テストコードの結果が可視化されるとのこと。

```ruby:.rspec
--require spec_helper
--format documentation
```

#4. rails g rspec:model モデル名
テスト用のモデルファイルを作成します。
ここではモデル名を仮にuserとしています。

```ruby:ターミナル
% rails g rspec:model user
```

これで準備は完了しました。
あとは作成されたモデルファイルに記述を行い
bundle exec rspec  spec/models/user_spec.rb
を実行して動作確認を行なっていきます。

なお、単体テスト時は
FactoryBot
Faker
といったgemを併用することで
効率よく進めることができます。

今回は以上です。

お読みくださりありがとうございました！