OmniAICreator/Qiita-1.07M huggingface dataset:
【Flutter】縮小するヘッダ + タブ + ListView の実装方法

タイトルがわかりにくいですが、下のgifのようなUIをFlutterでどのように実現するかという話です。

![result.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18273/c6923d44-a9a9-950b-1f04-d61c3dd38d5e.gif)

# 実装方法
## 全体の構造
NestedScrollViewを使って以下のようなViewの構造にします。
```
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: DefaultTabController(
          length: 2,
          child: NestedScrollView(
            headerSliverBuilder: (context, hoge) {
              return [
                SliverPersistentHeader(
                    pinned: true,
                    // floating: true,
                    delegate: MySliverPersistentHeaderDelegate())
              ];
            },
            body: TabBarView(
              children: [
                ListView.builder(
                  key: PageStorageKey(0), // keep scroll position
                  itemBuilder: (context, index) {
                    return ListTile(
                      title: Text("page one:$index"),
                    );
                  },
                  itemCount: 50,
                ),
                ListView.builder(
                  key: PageStorageKey(1),
                  itemBuilder: (context, index) {
                    return ListTile(
                      title: Text("page two:$index"),
                    );
                  },
                  itemCount: 80,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
```

SliverAppBarが便利そうだったのですが、bottomのタブだけ残すという動作ができなかったのでヘッダは `SliverPersistentHeader` を使って、タブだけ残るようにしています。

## MySliverPersistentHeaderDelegate
MySliverPersistentHeaderDelegateは以下のような実装にしています。
スクロールによって緑の部分の高さを減らしていって、最終的にタブの部分だけ残るようにしています。
サンプルなので常にリビルドしています。

```
class MySliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
  @override
  double get maxExtent => 200;

  @override
  double get minExtent => 48; // from tab height

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    print("so:$shrinkOffset, oc:$overlapsContent");
    return Container(
      color: Colors.pinkAccent,
      height: max(maxExtent - shrinkOffset, minExtent),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Container(
            color: Colors.green,
            height: max(maxExtent - shrinkOffset - minExtent, 0),
          ),
          TabBar(tabs: [
            Tab(
              text: "page1",
            ),
            Tab(
              text: "page2",
            ),
          ]),
        ],
      ),
    );
  }

  @override
  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
    return true;
  }
}
```

## まとめ
この手のUIをiOS/Androidで両方実現しようとすると、どちらにしても結構コスト掛かりそうですがFlutterでそれなりに簡単に両OSに対応できるのは素晴らしいですね。

## サンプルプロジェクトはこちら
https://github.com/sekitaka/sliver_appbar_tab_example

## 参考
https://blog.logrocket.com/how-to-add-sliverappbar-to-your-flutter-app/
Linux X Windows Systemについて（自分用メモ

X Window System（通称はXまたはX11）はUNIXやLinuxでGUIを実現するために使用されています。Linuxで標準的に使用されているX Window SystemはX.Orgです。
X Window Systemはクライアント・サーバ方式を使用しているため、XサーバとXクライアントは異なるマシンで動作していても使用できます。例えば、Xサーバが動作するマシンの画面上に、異なるマシンで起動したXクライアントプログラムを表示できます。
Xサーバは、キーボードやディスプレイなどのハードウェアを管理するソフトウェアで、XクライアントはWebブラウザやメーラーなどのGUIアプリケーションです。


X.Orgの設定ファイルは「/etc/X11/xorg.conf」。
各セクションは「Section "セクション名"」から始まり、「EndSection」で終わります。


・xhostによる認証
Xサーバへのアクセスを許可するには「xhost」コマンドを使用。

xhost [[+-]ホスト名 ...]


Xクライアント（192.168.1.20）上で実行したプログラム（xeyes）をXサーバ（192.168.1.10）上で表示する場合、以下のような手順が必要です。

■Xサーバ側
xhostコマンドで、「192.168.1.20」からのアクセスを許可します。

$ xhost +192.168.1.20
192.168.1.20 being added to access control list

■Xクライアント側
環境変数DISPLAYで表示先（Xサーバ）を指定し、Xサーバに表示させたいプログラム（xeyes）を実行します。
環境変数DISPLAYの書式は以下の通りです。

[Xサーバ]：ディスプレイ番号.スクリーン番号

デフォルトのディスプレイを使用する場合はディスプレイ番号に0を指定します。スクリーン番号は省略できます。
複数のXサーバが起動している場合は、ディスプレイ番号0から1, 2, 3...の順で番号を指定します。
複数のモニターが接続されている場合は、スクリーン番号0から1, 2, 3...の順で番号を指定します。

$ DISPLAY=192.168.1.10:0
$ export DISPLAY
$ xeyes &

上記コマンドを実行するとXサーバ側でxeyesプログラムが表示されます。


xeyesコマンドは、目玉のグラフィックがマウスカーソルを追うプログラムです。

・xauthによる認証
xhostコマンドはホスト単位でアクセスを許可するため、セキュリティ上好ましくありません。xauthコマンドはユーザ単位でXサーバへのアクセスを制限します。

■Xサーバ側
xauth listコマンドでXサーバごとの接続に使用される資格情報が表示されます。


■Xクライアント側
xauthのaddコマンドで、接続ユーザの「~/.Xauthority」ファイル（クライアント認証ファイル）にXサーバと同じ資格情報を保存します。Xサーバと資格情報が一致したユーザのみがアクセスできるようになります。



X Window Systemの主なプログラムにディスプレイマネージャ、ウィンドウマネージャ、統合デスクトップ環境があります。

■ディスプレイマネージャ

ディスプレイマネージャはランレベルが5の時にユーザにグラフィカルログイン画面（GUI環境のログイン）を提供し、ログイン認証、ログイン後のデスクトップ環境の準備を行います。
SysVinitの場合は、initが起動する「prefdm（Preferred Display Manager）」が環境変数DISPLAYMANAGERを読み取って必要なディスプレイマネージャーが起動されます。systemdの場合は「display-manager.service」として起動されますが、これはgdmやkdmなど、使用するディスプレイマネージャーサービスへのシンボリックリンクとなっています。
指定したディスプレイマネージャが起動すると、ユーザ名とパスワードを入力するログインプロンプトの認証画面が表示されます。

主なディスプレイマネージャは以下の通り。

・XDM（Xディスプレイマネージャ）
X.Org標準のディスプレイマネージャです。
XDMCPプロトコルを使用して、ネットワーク上にあるX端末にもグラフィカルログイン画面を提供します。
XDMの設定ファイルは「/etc/X11/xdm」ディレクトリに格納されています。

・GDM（GNOMEディスプレイマネージャ）
GNOME標準のディスプレイマネージャ
GDMの設定ファイルは「/etc/X11/gdm」ディレクトリに格納されています（ディストリビューションによって異なる）。

・KDM（KDEディスプレイマネージャ）
KDE標準のディスプレイマネージャ
KDMの設定ファイルは「/etc/X11/kdm」ディレクトリに格納されています（ディストリビューションによって異なる）。

■ウィンドウマネージャ
ウィンドウの概観、アイコンやカーソル、メニューなどを提供するXクライアントのアプリケーションです。
最小限の機能を備えた「twm」、KDE標準の「kWin」などがあります。

■統合デスクトップ環境
ディスプレイマネージャやウィンドウマネージャのGUI環境とアプリケーションをまとめて統一的な操作を提供します。
Raspberry-Py ロボットカー製作Go学習

### 2020　64歳の誕生日にスキルアップ電子工作始ました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/bac97163-ee47-4d73-528d-f13c86dab167.png)
### メーカーサイト資料
https://www.youtube.com/watch?v=4Zv0GZUQjZc

Visit our online store to purchase this product ☛ http://freenove.com/store
Download tutorial and code for this kit ☛ http://freenove.com/fnk0043

###  Go学習も進めながらAIも進めました　
https://www.udemy.com/course/python-drone/

https://www.udemy.com/course/go-drone/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/1244a301-85be-3ccb-3c1d-61b75c024e4f.png)


### モニター、Webカメラ、スピーカー追加しました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/98a23e28-f690-648c-c7a6-44255e4d86d4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/be042787-8c04-d88b-673f-d2d3fa50cf67.png)

### Raspberry-Py　Python　PyQT5で　Gui制御ソース付きです、Qtの学習に良い教材でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/a402fbdd-1cd7-2b78-7b1c-0ba68f7b5c04.png)

```python
#!/usr/bin/python 
# -*- coding: utf-8 -*-
import numpy as np
import cv2
import socket
import os
import io
import time
import imghdr
import sys
from threading import Timer
from threading import Thread
from PIL import Image
from Command import COMMAND as cmd
from Thread import *
from Client2_Ui import Ui_Client
from Video import *
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
```
### アプリでも動きました
https://play.google.com/store/apps/details?id=com.freenove.suhayl.Freenove
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/f215c2c1-57d7-e421-b412-1dc78944b483.png)

https://twitter.com/tkurume/status/1481080833775906816?s=20&t=cG6NP2_pOFLUgP82I8z_BA
【Rails】好きなログファイルを作って出力

# 環境
- Ruby 2.7.6
- Rails 5.2.8

# コード
```ruby
@log = Logger.new('log/check_site.log')

msg = "AAAAAAAAAAAAA"

@log.info(msg)
```

# まとめ
設定ファイル触るとかありますけど、その場その場でちょっと違うログファイルに出力したかったりするので、この方法が良いと思います。

カンタン便利。

ログレベルをdebugやらinfoやらあるのは、他記事を参考にして下さい。

これとか↓
https://qiita.com/sobameshi0901/items/b963e7046e2ae8b8e813

終わり
ポモドーロ・テクニック初心者

# ポモドーロで疲弊していた自分
僕は以前は、意識的に25分の集中をするだけでかなりの疲労を感じていた。1日中引きずるような疲れだ。何度か試してもそうなのだった。

なのでこのテクニックの弊害を大きく感じてしまい、すぐにやめていた。

だが今は再チャレンジしているところだ。

# 再チャレンジ
最近改めてポモドーロ・テクニックを試してみると、そんなに悪くはない感じがする。エネルギーの消耗よりも集中力の高まりを感じる。

自分自身の健常状態、エネルギー状態が改善したのかもしれない。

集中を妨げる注意散漫に対しても対抗しやすくなったように思う。というより対抗するしかないのだ。なぜなら25分間はきっちりと集中するからのがこのテクニックの大原則だからだ。

# 初心者は時間を短くすると良い
ポモドーロテクニックのオリジナル本では、最初は25分集中できなくても良いと語られている。

最初に集中できるのは10分かもしれないし、5分かもしれないが、その時間を日々伸ばして25分に近づけて行くのだ。

ゆくゆくはポモドーロのセット数も伸ばしていくことが出来るだろう。たとえば1日に4セットのポモドーロを取り入れるなど。

# 初心者はゆるくやろうぜ
僕自身もこのテクニックの初心者なので、まだゆるい運用をしている。

たとえば特に予定表も作らないし、結果の記録もしない。

ポモドーロをやりたくなった時に気ままに試しているし、4セットを続けてやったりもしない。

だけどまずはそれで良いと思っている。なぜなら今までにしていなかった集中方法にチャレンジするだけで、少なからずプラスになっているし、練習になっているはずだからだ。

完璧主義は立ち行かない。ゆるくやろうぜ。

# ポモドーロ時間は調整可能なのだろうか？
25分の集中と5分の休憩を合わせて、基本的にはトータル30分らしいが、これは絶対ではないようだ。

個人個人で集中力の違いもあるだろうしね。

オリジナル本によるとトータル15分-40分程度がオススメされている。



<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
MeCabでUniDicの出力をカスタマイズ

ちゃお…†

MeCabでUniDicをIPAdicみたいにCSVフォーマットで出力したくて `--node-format` オプションとかで指定したのになぜか無視されてるっていうのが地味に困る問題。。。

検索すると同様の問題にぶつかってる人がいて解決法がありました。

[\[小ネタ\] mecab + unidic で出力フォーマットを整形する方法 | NaviPlus Engineers' Blog](http://tech.naviplus.co.jp/2014/05/14/%E5%B0%8F%E3%83%8D%E3%82%BF-mecab-unidic-%E3%81%A7%E5%87%BA%E5%8A%9B%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88%E3%82%92%E6%95%B4%E5%BD%A2%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/)

> -Oオブションにブランクを指定する

と解決します。

なので、下のコマンドでMeCab実行すればUniDicをIPAdicと同じくCSVフォーマットで出力できます。

```
$ mecab -d `mecab-config --dicdir`/unidic -O '' -F '%m\t%H\n'
```

IPAdicの`-Oyomi`みたいに読みだけ取得したい場合はこちら。

```
$ mecab -d `mecab-config --dicdir`/unidic -O "" -F "%f[6]" -U "%m" -E "\n"
```
VSCode PythonのSuggestサジェストが重複duplicate表示する時の解決方法

# 環境
OS: Windows10
VSCode : バージョン1.69.2
LSP: Pylance
Notebook使用

# この症状が出るシーン
.pyファイルと.ipynbファイルを同時に編集しているとき
.pyファイルのみ、.ipynbファイルのみのときは問題ない。

# 解決方法

settings.jsonに`"python.pylanceLspNotebooksEnabled": true`と記述してnotebookのLSPをpylanceにすることを明示する。

# ※追記

.pyファイル上のsuggestの重複はなくなったものの、.ipynbファイル上のsuggestの重複がなくならない。

Microsoftの`Pylance`からPython標準の`jedi`に変更することにした。

settings.jsonへ`"python.languageServer": "Jedi",`を記述
Amazon SNSへの複数メールアドレス設定と既存メールアドレスの変更はできない？

# Amazon SNSとは
Amazon SNS (Amazon Simple Notification Service)は、フルマネージド型メッセージングサービス。
サブスクリプション対象としてSQSやLambda、HTTPエンドポイント、SMSなどが選べるが、本記事ではエンドポイント「Eメール」に関して投稿する。
※内容は2022/06/20時点

## 既存サブスクリプションのメールアドレス変更
編集画面に遷移しても、既存のメールアドレス(エンドポイント)は変更できない。
いったん削除してから再度購読するしかなさそう。

## サブスクリプションにメールアドレスを複数設定
どうやら1サブスクリプションにつき1メールアドレスの模様。
スペース、セミコロン、カンマで区切ってみたが無効だと怒られる。
数名であれば手作業でも良いが、大人数になるとなかなか大変。
対象者だけを含めたメーリングリストを作成できる環境であれば良いが…
![SNS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519630/1881ec11-5baf-6a51-c090-52413aeef4e2.png)
AWS Systems Manager / Incident Managerの設定例

# AWS Systems Managerとは
AWSリソースだけでなくオンプレミスに構築されたサーバも対象とし、運用負荷を大幅に減らすことができる。
一口にSystems Managerといっても機能は多岐にわたり、2022/06時点では18もの機能が存在する。
https://aws.amazon.com/jp/systems-manager/features/#Explorer

本記事ではSystems Managerの中でも、インシデント管理を行うIncident Manager関して記載する。

# Incident Managerとは
CloudWatchAlarmやEventBridge(旧CloudWatchEvents)のイベントをトリガーとして
インシデント起票し、その後の自動復旧の実行や、メール/電話による通知が可能なサービス。
昨今話題のSOAR(Security Orchestration, Automation and Response)に近いサービス。
- インシデントへの対応プランと連絡先を定義できる
- インシデント発生時に対応するためのRunbook(コマンドや手順内容をまとめたもの)を自動実行
- エスカレーション先として、Slack、メール、電話を選択可能。
以下のような細かい制御も可能
    - 検知後0分でメール、5分で電話連絡
    - 第一担当者不在時には第二担当者へ連絡
- エスカレーション連絡が来た後の解決と分析を定義
PDCAサイクルを回し、次回以降のアクションの向上に役立つ

# やりたいこと
- CloudWatchで検知したアラートをIncident Managerに集約する
- 運用負荷を減らすためメール通知をなるべく削減する

## 設定例
以下を参考に実施

https://aws.amazon.com/jp/blogs/news/creating-contacts-escalation-plans-response-plans-aws-systems-manager-incident-manager/

https://aws.amazon.com/jp/blogs/news/aws-systems-manager-incident-manager-integration-amazon-cloudwatch/

# 不明点の問い合わせ
## 重複排除文字列

https://docs.aws.amazon.com/ja_jp/incident-manager/latest/userguide/response-plans.html

>重複除外文字列を指定します。Incident Manager は、重複除外文字列を使用して、同じ根本原因が同じアカウントに複数のインシデントを作成しないようにします。

この「重複排除文字列」という言葉から察するに、入力した文字列を含む内容は、1回目は通知され2回目以降は通知抑制されるものと推測。
結果としては、ここに入力しなくても抑制できるとのこと。
以下サポートからの回答
> 重複排除文字列を入力せずとも同じCloudWatchAlarm / EventBridgeイベントから
作成されるインシデントは同じものとなる。
（例）
複数インスタンスでCPU使用率が80%を超えると発報するアラームを設定したとして、
　インスタンスAのCPU使用率80% → ALARM
　インスタンスAのCPU使用率50% → OK
　インスタンスAのCPU使用率80% → ALARM
と2回アラームが発報してもインシデントを解決していなければ
重複してインシデントが作成されることはない。
一方で、インスタンスBでCPU使用率が80%を超えて発報した場合は
別のインシデントとして作成される。

因みに、重複除外文字列を指定した場合どうなるかも問い合わせたが、
同じ対応プランから作成されたインシデントは、
作成のされ方に関わらず同じインシデントとなるそう。

これは非常にわかりづらい記載だったので、
是非ともドキュメントを修正してもらいたい。

## 料金
1対応プランにつき100件のSNSまたは音声メッセージ含め7$/月
大量のプランを作成するとなかなかの金額となってしまうので精査が必要。
https://aws.amazon.com/jp/systems-manager/pricing/
CloudWatchで通知抑制は出来るのか？

# やりたいこと
CloudWatchAlarmで監視しているインスタンスAがCPU高騰した際に、
CloudWatchAlarmのSNS(Eメール)にて、
初回のみ指定のメールアドレスに通知し、2回目以降は通知さない。

# 結論、できない！
##### サポート回答
>CloudWatchAlarmには上記要件を実現する機能は存在しておらず、
初回のみアラームのアクションを実行するといった対応は出来かねます。

# 対応策
##### サポート回答
CloudWatchAlarmのDisableAlarmAction API(AWS CLIのdisable-alarm-actionコマンド)にて、
アクションの実行を無効化をする。

## 具体的には？
##### サポート回答
CloudWatchAlarmの通知先をSNSではなくLambdaを選択し、
DisableAlarmActionを実行したうえで、次回以降のアクションを無効化する方法。
**CloudWatchAlarm --> SNS --> Lambda --> SNS --> Eメール**

1つ目と2つ目のSNSでは異なるトピックを選択する
- 1つ目
トピックのサブスクリプション：Lambda
- 2つ目
トピックのサブスクリプション：Eメール

Lambda関数を作成しSNSへ通知しつつ、DisableAlarmAction APIアクションを実行したうえで、
CloudWatchAlarmのアクションを無効化する処理を実装する。

参考ドキュメント

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html#alarms-and-EventBridge

>アラームを無効または有効にするには、DisableAlarmActions および EnableAlarmActions API アクション、または AWS CLI の disable-alarm-actions および enable-alarm-actions コマンドを使用します。
WorkSpaces認証失敗をCloudTrailもしくはCloudWatchで監視したい

# やりたいこと
証明書が導入されていない端末、もしくは合致しない証明書を導入している端末からWorkSpacesへアクセスがあった際、認証に失敗したことを監視したい。

# AWSサービス概要
- CloudTrail
ログインなどのユーザアクティビティとAPI操作をログに記録
- CloudWatch
条件に合致した場合アラームで通知を行うなど、AWSリソースの状態を監視
- WorkSpaces
仮想デスクトップサービス
- AWS Managed Microsoft AD
Active Directoryのマネージドサービス
- AD Connector
オンプレに存在するActive Directoryへのゲートウェイサービス
- Simple AD
比較的小規模な環境で利用するユーザー向けのActive Directory

## 結論、ログイン時の「認証失敗」エラーは監視できない
- サポート回答　※2022/05/17時点
>AWS Managed Managed ADもしくはSimple ADを用いてWorkSpacesを利用する場合は、
ログイン失敗時にログの記録ができません。


## 回避策
- サポート回答　※2022/05/17時点
>AD Connectorを使った場合であれば、AD Connectorの接続先ADにて、
Kerberos認証の監査を有効にすることで、
ログイン失敗時にログの記録が可能になります。
Ruby でも Python の if __name__ == '__main__' がやりたい

# やりたいこと

- Ruby ファイルを ruby コマンドや bin/rails runner コマンドなどで直接実行した場合のみ、特定のコードを実行したい。
  - 別の Ruby ファイルから require した場合は実行したくない。
  - Python ファイルでよく見る以下の記述のようなことがやりたい。

```py
def hello_world():
    print('Hello World 🌍')

if __name__ == '__main__': 
    hello_world() 
```

# 方法

```rb
if __FILE__ == $PROGRAM_NAME
end
```

を使う。

# 例

```shell
$ ruby body_mass_index.rb
```

のように Ruby ファイルを直接実行した場合だけ単体テストを実行したい。

```body_mass_index.rb
require 'delegate'

class BodyMassIndex < DelegateClass(Float)
  def initialize(height:, weight:)
    value = weight.fdiv(height ** 2) * (100 ** 2)
    super(value)
  end
end

if __FILE__ == $PROGRAM_NAME
  require 'minitest'
  require 'minitest/autorun'

  class BodyMassIndexTest < Minitest::Test
    def test_round
      bmi = BodyMassIndex.new(height: 170, weight: 60)

      assert_equal(21, bmi.round)
      assert_equal(20.8, bmi.round(1))
      assert_equal(20.76, bmi.round(2))
    end
  end
end
```
```shell
$ ruby body_mass_index.rb
Run options: --seed 12009

# Running:

.

Finished in 0.000706s, 1416.4306 runs/s, 4249.2918 assertions/s.

1 runs, 3 assertions, 0 failures, 0 errors, 0 skips
```

# 解説

- `$PROGRAM_NAME` は現在実行中の Ruby スクリプトの名前の文字列。
  - `$0` と同じ。
- `__FILE__` は現在実行しているファイルの名前の文字列。


たとえば以下の calculate_bmi.rb を ruby コマンドで実行した場合は

```/Users/quanon/workspace/calculate_bmi.rb
require 'optparse'
require './body_mass_index'

opts = ARGV.getopts('', 'height:', 'weight:')
bmi = BodyMassIndex.new(height: opts.fetch('height').to_f, weight: opts.fetch('weight').to_f)
puts("あなたの BMI は #{bmi.round(2)} です。")
```

```shell
$ ruby calculate_bmi.rb --height 171.8 --weight 64.5
あなたの BMI は 21.85 です。
```

| `__FILE__` | `$PROGRAM_NAME` |
|--|--|
| "/Users/quanon/workspace/body_mass_index.rb" | "calculate_bmi.rb" |


となる。一方で同じディレクトリにある body_mass_index.rb を ruby コマンドで実行した場合は

| `__FILE__` | `$PROGRAM_NAME` |
|--|--|
| "body_mass_index.rb" | "body_mass_index.rb" |

となる。

# 参考

- [変数と定数 (Ruby 3.1 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/doc/spec=2fvariables.html)
  - `__FILE__` は「擬似変数」と呼ばれる変数のひとつらしい。 
- [$0 (Ruby 3.1 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/method/Kernel/v/0.html)
GASの使用ライブラリのソースコードを確認する方法


以下のようにURLを直打ち。

https&#x3A;//script.google.com/d/***<font color="red">スクリプトID</font>***/edit
又は
https&#x3A;//script.google.com/home/projects/***<font color="red">スクリプトID</font>***/edit

<br>
参照:

https://stackoverflow.com/a/31997641
【Laravel】laravel/uiのAuth機能のCSSが反映されない

# 環境
MacOS 11.5.2(Big Sur)
Laravel 9.17.0
php 8.1.2

# 困っていること
laravel/uiのAuth機能を実施しようとしたところ下記のような画面に。おそらくCSSがうまく反映されていない様子。

# ![スクリーンショット 2022-08-05 10.02.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25498/c99e9ad8-6f53-3ff0-e785-33c5069c1bf0.png)

# 解決方法
Terminalにて下記コマンドを実行。
``` npm run dev ```


参考記事
https://teratail.com/questions/332840
PLZ-SA354400B Spectrum Analyzer の使い方

# はじめに
電界強度を測りたい。
どこまで出力を絞ったら、微弱無線局のなるのか知りたくなりました。

# そこで
AliexpressでPLZ-SA354400B Spectrum Analyzerを買ってきました。
[Aliexpressで売っています。](https://ja.aliexpress.com/item/1005003027570549.html?spm=a2g0o.productlist.0.0.2a634018MVGISa&algo_pvid=24eb7606-c4c7-40cc-bfe6-f132222b6343&algo_exp_id=24eb7606-c4c7-40cc-bfe6-f132222b6343-21&pdp_ext_f=%7B%22sku_id%22%3A%2212000023315839495%22%7D&pdp_npi=2%40dis%21JPY%2110241.0%215939.0%21%21%21%21%21%402101e9d516596629997734706e9301%2112000023315839495%21sea&curPageLogUid=UQ2jMOKSvNdb)
大変に安価で動作するのか不安でした。
![SA](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245853/64c743f9-19a3-445b-5ccf-9f7fbda2288e.jpeg)
ソフトウエアの同梱はなくPLZ-SA354400Bで検索しても見つかりません。
でも、探し回るうちに「ほかのSAのソフトでも使えるものがあるんじゃないのか？」と気づき、検索方針を変えたところ見つかりました。
https://www.dl4jal.de/nwt4x/nwt4000.html
ドイツ語ですが、自動翻訳で読んでください。
インストールしたら、起動する前に、USBにつながっているSerial Terminalを外します。スキャンしてハードを探してくれるんですが、これが大きなお世話で目的ハードでないものもひっかけてしまいます。
逆に拾わない場合もあります。その場合はデバイスマネージャーでCOM portを固定してください。

うまく立ちあがったら、Setupを叩き、LTDZ (old) を選択します。これ以外はうまくいきません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245853/c4388fde-cea2-4529-f4ed-a0974701a72c.png)

うまくいけば、下記が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245853/856ab3a0-a1b8-fd54-b88d-e95f05cb68f9.png)
Angular14にJestを入れてみた

AngularのデフォルトテストフレームワークはKarma＋Jasmineとなっていますが、
流行りのJestを使いたいと思ったのでセットアップしてみました。

# 環境
Angular１４

# 調査から
Jestを導入したいと思って`angular jest`と調べると自分でインストールやら設定ファイルやらで少々面倒。
eslintみたく、いい感じのschematicないの？と思って調べたらありました。
[briebug/jest-schematic](https://github.com/briebug/jest-schematic)というものが！
早速導入してみた！

# インストールしてみた
インストールは至ってシンプル
```
ng add @briebug/jest-schematic
```
以上でインストールが完了！

とりあえず、テストが実行してみる
```
npx jest
```
動きました。
なお、テストはデフォルトのもののみ…
```
Test Suites: 5 passed, 5 total
Tests:       6 passed, 6 total
Snapshots:   0 total
Time:        20.278 s
Ran all test suites.
```

# 課題点
開発者的には何も考えないで`ng test`と何も考えずに実行したいですが、実行すると…
```
● Test suite failed to run

    Cannot set base providers because it has already been called

    > 1 | import 'jest-preset-angular/setup-jest';
```
こんなエラーが出力されます。
どこの設定なのだろうか…引き続き調査して、解決したら更新します…

:::note warn
ご指摘等ありましたら、気軽にしてください…
:::
CADSでMLOps #1モデル作成

SPSS Modelerで作ったモデルをCADSと組み合わせてMLOpsで管理していきます。

MLOpsを4つのパートに分けて説明します。
この記事はモデル作成の記事です。

**1.モデル作成**
2.[スコアリング](https://qiita.com/kawada2017/items/f7aa3716bb916ca76603)
3.[モデルモニタリング](https://qiita.com/kawada2017/items/43ea5d0a4589f402d9eb)
4.[モデルリフレッシュ](https://qiita.com/kawada2017/items/e5a8cd9ad53817d47cb1)


全体イメージの中では、学習データからモデル作成・パイプライン(Modelerストリーム)でモデルを作成して、CADSのレポジトリに保存するところまでの解説になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/80cfc80a-cfca-bac2-9089-90298cda477b.png)


# モデル作成ストリームの作成
例として、年齢と性別の情報からキャンペーン反応を予測するモデルを作ります。
学習データは以下のようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/45f1e267-c03e-db12-8131-97b84ea53923.png)

まずデータ加工を行います。
ここでは年齢と性別のデータがNULLではないレコードのみにクレンジングしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/13b6f27b-a519-acfa-6bb3-d0a9148c03f8.png)


次にデータ型ノードで年齢と性別を「入力」、キャンペーン反応を「対象」と指定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/87cf36ca-359d-bc22-fe95-82577e023dd8.png)

CHAIDでモデルを作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/5e129d12-6cc4-a2ea-ecf9-cac21b8aa1ab.png)

モデルの精度を評価します。ここでは85.75％の精度があるモデルができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/dcbfc03a-9baf-294c-79c2-3d0d73fb098c.png)

# CADSレポジトリへの保存

モデルができたのでCADSのレポジトリに保存します。
「ファイル」メニューの「格納」「ストリームとして格納」で保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/1965406f-9ac3-80d9-53ff-7c8dec83f8f9.png)

ファルダを選び保存しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/96d4fcda-1e78-cbc7-5ef2-bbb0148e5aae.png)

ここまででモデルが完成しました。


# サンプルストリームやデータ、PES

https://github.com/hkwd/spsssample/tree/master/220805CADSMLOps

* テスト環境
  * Modeler 18.3
  * CADS 8.3
  * Windows 2019


# 参考情報
なぜMLOpsが必要なのか(vol97-0014-ai) 
https://community.ibm.com/community/user/japan/blogs/provision-ibm1/2021/08/17/vol97-0014-ai

失敗しないMLOps (vol97-0017-ai) 
https://community.ibm.com/community/user/japan/blogs/provision-ibm1/2021/10/31/vol97-0017-ai

MLOpsのキホンと動向 | IBM ソリューション ブログ 
https://www.ibm.com/blogs/solutions/jp-ja/mlops-2021-data/
【備忘録】Rust × WebAssembly 環境構築【project作成からnpm run startまで】

## 背景
簡単に Rust × WebAssembly 環境を作りたいのに、毎回チュートリアルを探すことが多かったです。
あまり日本語での情報も少ないので、備忘録として残しておきます。

情報は主に[こちらのチュートリアル](https://rustwasm.github.io/docs/book/introduction.html)を参考にしています。

## 前提
* Rust ツールチェーンがインストールされている （ rustup, rustc, cargo ）
* npm がインストールされている

## 必要なツールのインストール

### wasm-pack のインストール

wasm-pack によって Rust で生成された WebAssembly をビルド、テスト、公開することができます。
下記のコマンドを実行してインストールしましょう。

```bash
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
```


[こちら](https://rustwasm.github.io/wasm-pack/book/)がドキュメントになります。

### cargo-generate のインストール

既存の git リポジトリをテンプレートとして活用して、新しい Rust プロジェクトを立ち上げて実行できます。

```bash
cargo install cargo-generate
```

[こちら](https://github.com/cargo-generate/cargo-generate)がドキュメントになります。


### npm の最新版をインストール

JavaScript バンドラーと開発サーバーを最新版にしておきます。
（冒頭で紹介したチュートリアルの最後に、コンパイル.wasmしたものをnpmレジストリに公開する工程があります）

```bash
npm install npm@latest -g
```

## Rust プロジェクトの作成

下記のコマンドで雛形のリポジトリからプロジェクトを作成します。
```bash
cargo generate --git https://github.com/rustwasm/wasm-pack-template
```

プロジェクト名を要求されるので、適した名前をつけてあげましょう。
スネークケースかケバブケースにすると良いです。

ここでは便宜上、`hello_world`というプロジェクト名とします。

`cd hello_world`でプロジェクトのディレクトリ内に移動しておきましょう。



## wasm-packでビルドする

最初は　`Hello, ~~!`とアラートを出すプログラムが書かれています。


プロジェクトディレクトリ内で下記のコマンドでビルドを実行します。

```bash
wasm-pack build
```

デフォルトでは`--release`オプションで最適化されたビルドを行います。
作成されたファイルは`pkg`フォルダに格納されています。
詳細は[こちらのドキュメント](https://rustwasm.github.io/docs/wasm-pack/commands/build.html)を参照してください。

## npmでモジュールを導入する

`npm init`でパッケージマネージャを初期化します。
ここでは`www`という名前にしています。

```bash
npm init wasm-app www
```

作成された`package.json`ファイルの`devDependencies`に下記を追記します。
ここではモジュール名を`wasm-hello-world`としています。

```json:package.json
{
  "devDependencies": {
    "wasm-hello-world": "file:../pkg",
  }
}
```
追加したモジュールを`index.js`内でimportします。
```javascript:index.js
import * as wasm from "wasm-blur-detection";

wasm.greet();

```

`www`ディレクトリ内で`npm install`をします。

```bash
cd www
npm install
```

## 実行してみる

```bash
npm run start
```

`http://localhost:8080/`にアクセスすると、`Hello, wasm-hello-world!`とアラートが出るはずです。

この時、Node.js v17 以降では`npm run start`が実行できないようです。
その場合は、下記のコマンドで環境変数を変更して再度実行するとうまくいきます。
```bash
export NODE_OPTIONS=--openssl-legacy-provider
```
詳細は[こちらの記事](https://qiita.com/iorn121/items/1779d07a3f699b655991)を参考にしてください。

## まとめ

以上で、簡単に Rust × WebAssembly の環境構築をして、hello, worldまで済ませることができました。

紹介したチュートリアルではライフゲームを実装しており、テストの方法やボタンを用いたインタラクティブな実装まで説明があります。
とても参考になるので、ぜひご覧ください。
【Docker】.envの環境変数をDockerfileで使用する


## .env
```.env
SAMPLE_ENV=example
```

## `docker-compose.yml`
`.env`ファイルに記述した環境変数を`args`に記述します。
```docker-compose.yml

version: '3.9'
services:

  ・・・

  api:
    build:
      context: .
      dockerfile: ./docker/api/Dockerfile
      args:
        - SAMPLE_ENV=${SAMPLE_ENV}

  ・・・

```

## `Dockerfile`
`ARG`で`docker-compose.yml`の`args`に記述した環境変数を取得します。
```Dockerfile:Dockerfile
ARG SAMPLE_ENV

RUN echo ${SAMPLE_ENV}
```
Rails6でorder(:id)ではなく任意のID順で並び替えたい

## 駆け出しにもわかる簡単な並び替え
はじめまして、1年を経過した駆け出しRailsエンジニアです。
`Model.where()` で取得したリレーションを任意のID順で並び替えたいということがありました。
この記事は**Rails6**向けとなっており、**Rails7**の方は最後の項目だけ読んで頂ければOKです:ok_hand:

それでは早速、下記のような `animals` テーブルを例として進めて行きます。

ID|名前(必要な情報)|年齢(不要な情報)
---|---|---
1|taro|2
2|hanako|7
3|jiro|4

## まずはID順に並べる場合

```rb
animal_ids = [1, 3, 2]
Animal.where(id: animal_ids).order(:id).pluck(:name)
# SELECT "animals"."name" FROM "animals" WHERE "animals"."id" IN ($1, $2, $3) ORDER BY "animals"."id" ASC 
# => ["taro", "hanako", "jiro"]
```

何も気にすることはありませんね。
それでは本題へ:thumbsup:

## 指定したID順に並べたい
**MySQLの場合**は `FIELD` が使えるそうです。
```sql
ORDER BY FIELD( id, '1', '3', '2');
```

私の環境はPostgreSQLの為、上記は見なかったことにします:innocent:

**PostgreSQLの場合**は `CASE` でやるようです。
```sql
CASE id WHEN '1' THEN 0 WHEN '3' THEN 1 WHEN '2' THEN 2 END
```

というのがSQLでの並び替え方法のようです。
`Arel`を使用してSQLを書けばできるそうですが、、、 **駆け出しには難しい :rolling_eyes:**

## `sort_by` を使った並び替え
今回はもっと簡単にRailsで `sort_by` を使用して並び替えることにします。

```rb
animal_ids = [1, 3, 2]
Animal.where(id: animal_ids).sort_by { |animal| animal_ids.index(animal.id) }.pluck(:name)
# SELECT "animals".* FROM "animals" WHERE "animals"."id" IN ($1, $2, $3)
# => ["taro", "jiro", "hanako"]
```

SQLで取得したものをRailsで並び替えていますが、多くの場合はこれで十分ではないでしょうか:zipper_mouth:
違いはSQL上で並び替えていないという点と `ActiveRecord_Relation` から `Array` に変わっている点です。

少し気になるのは `SELECT "animals".*` となっており `pluck(:name)` が効かず、全ての値を取得しています。
これは必要な値(name)とIDをSELECTしてあげましょう！
```rb
Animal.where(id: animal_ids).select(:id, :name).sort_by { |animal| animal_ids.index(animal.id) }.pluck(:name)
# SELECT "animals"."id", "animals"."name" FROM "animals" WHERE "animals"."id" IN ($1, $2, $3)
# => ["taro", "jiro", "hanako"]
```

良さそうですね:clap:
抽象化したscopeを作っておいても色々使えるかもしれません。
任意のカラムを好きな順に並べ替えることができます。

```rb
# @return [Array]
# @example
#   ActiveRecord_Relation.in_order_of(:id, [1, 3, 2])
#   => [Model(id: 1), Model(id: 3), Model(id: 2)]
scope :in_order_of, -> (column, values) {  
  sort_by { |x| values.index(x[column]) }    
}  
```

ん、`in_order_of` って、なに？

## Rails7になれば `in_order_of` が使えます
はい、色々頑張りましたが、**Rails7**の方はSQL上でできちゃいます:angel:

https://techracho.bpsinc.jp/hachi8833/2021_10_28/113117

ということで、今回の内容は**Rails6**の方で**Rails7**に上げるまで用として検討して頂ければと思います。
最後まで読んで頂きありがとうございました。
laravel Featureテストを実行したら「No application encryption key has been specified.」のエラーが出た

# 概要

- Featureテストを実行したらエラーが出たので筆者の場合の解決策をメモ的にまとめる。

# エラー

```
No application encryption key has been specified.
```

# エラー原因

- テスト用の.envの`APP_KEY`の値が空だった。
- 通常動作で使用する.envの`APP_KEY`の値をテスト用.envに記載し実行したところエラー解消
[Python] matplotlibの日本語対応(venv環境下)

# 最初に
Pythonでグラフ作成に用いるmatplotlibに関して、グラフのタイトルなどに日本語を用いる場合、設定を変更する必要がある。
設定の変更の仕方をまとめた。

# 方法
フォントの情報をダウンロードし、package内の適切なディレクトリに格納する。

## ①fontのダウンロード
以下のURLからフォントをダウンロードする。
https://moji.or.jp/ipafont/ipaex00401/
対象は任意であるが、以下を例に示す。

|内容|ファイル|
|---|---|
|2書体パック(IPAex明朝(Ver.004.01)、IPAexゴシック(Ver.004.01))|IPAexfont00401.zip(9.3MB)|
|IPAex明朝 (Ver.004.01)|ipaexm00401.zip(5.3MB)|
|IPAexゴシック(Ver.004.01)|ipaexg00401.zip(4.0MB)|


## ②ディレクトリに格納
venvで作成した仮想環境があるディレクトリにダウンロードした.ttfファイルを格納する。

```
c:\...\[仮想環境名]\Lib\site-packages\matplotlib\mpl-data\fonts\ttf
```

対象ファイル
 * ipaexg.ttf
 * ipaexm.ttf


## ③設定の書き換え

以下の設定ファイルを書き換える。

```
c:\...\[仮想環境名]\Lib\site-packages\matplotlib\mpl-data\matplotlibrc
```


|変更|書き換え|
|---|---|
|変更前|#font.family : sans-serif
|変更後|font.family : IPAexGothic


## ④キャッシュのクリア
Pythonをユーザインストールした場合、以下にキャッシュのファイルが生成される。
ファイルを削除してキャッシュをクリアする。
```
C:\Users\[ユーザ名]\.matplotlib\fontlist-v330.json
```

# 最後に
Anacondaとは違うので注意する必要がある。
Web Chat Basics


[Web Chat Basics](https://trailhead.salesforce.com/content/learn/modules/web-chat)

# Create Pre-Chat and Offline Support Forms

**We can't find a case with the subject 'My solar panel is broken'. Make sure you entered the subject name correctly with no punctuation, and try again.**

試に何にもしないで検証ボタンを押してもこのエラーです。ということで、subjectに指定されたMy solar panel is brokenを入力したCaseを作ってみたら、なんとそれでけでクリアーできました。　甘い検証ロジックです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/f0ebfdf8-5b0a-9386-34c9-0f2c63064ef7.png)


[Create Pre-Chat and Offline Support Forms - last steps not found](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000HEezmSAD)
ロールの階層


[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)

元の質問 : [ユーザの階層化されたロール名の取得](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000HEewESAT)

user オブジェクトのManagerフィールドは親の情報を再帰的に検索できます。

```
select Name,UserRole.Name,Manager.UserRole.Name,Manager.Manager.UserRole.Name from user
```

しかし、親のロールはできないです。
１階層上のロールのIdは取得できるのですが、Nameや更にその上の階層にはアクセスできませんでした。

```
select Name,UserRole.Name,UserRole.ParentRoleId from user
```


# 外部ユーザについても同じように機能しそう。

+ [ロール階層の外部個人取引先](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000HEfy1SAD)


-----------------------------------------------------------
不具合

# ロールの新規追加ができない。

+ [ロールの新規追加ができない](https://qiita.com/Keiji_otsubo/items/3f6d6381cb4683e5c36f)

+ [issue with adding roles](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000HEM5aSAH)

画面もクラッシックに勝手に切り替わるらしい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b7b59b56-2aa3-52cb-61f9-e235e8cf2845.png)

# Create a Role Hierarchy げぇ、上記と同じじゃん。

[Data Security Create a Role Hierarchy Problem because move to Lighting](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000J78llSAB)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/77eacf75-4370-beba-5a0b-143de3b9e220.png)

# Experience Cloud サイト

https://trailhead.salesforce.com/ja/content/learn/projects/communities_share_crm_data/account_roles_hierarchy?trail_id=customize-your-community

新しい組織には、デフォルトで Experience Cloud ユーザーに最大 50,000 の取引先ロールを設定できます。取引先ロール数を 100,000 に増やすには、サポートに連絡する必要があります (ただし、承認を得るには詳細なシステムデザインビューの提出が必要になります)。Salesforce に設定できる取引先ロールの絶対最大値は 500,000 で、それだけの数にするには Salesforce の特別な承認が必要です。


サイトユーザーに関連付けられた取引先ごとに取引先ロールが生成されるため、取引先ロールは急速に増えます。つまり、組織で 2 つのパートナー取引先ロールを設定し、100 件のパートナー取引先があれば、200 件の取引先ロールが作成されます。

# トレイルヘッド

+ [We can’t find a role named ‘Recruiting Manager](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000TiyOn)

:::note
As you requested, I went back to the new dev edition org, and it worked. I may have switched the org while practising. Thanks very much for pointing it out! 
:::

+ [役割において、ユーザーテッドを作成しながら西洋の営業チームを見つけることができず、ユーザーノアを作成しながら国際的な顧客サポートを見つけることができない](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000Tixn5)

:::note
ロールを作成した後、問題は解決しました。
:::
Snowflakeでバックアップ・リストア

# 結論
## バックアップの方法
- Time Travel
- 定期的にClone
- Fail Safe

## リストアの方法

**Cloneからのリストア**
予めクローンしたテーブルとSWAPする
```SQL
alter table my_table swap with backup_table_clone;
```

**Time Travelからのリストア**
指定の状態のテーブルをTime Travelでクローンし、現在のテーブルとSWAPする。

```SQL
-- 指定した時刻のテーブルをクローン
create table backup_table_clone clone my_table at (timestamp => to_timestamp_tz('04/05/2013 01:02:03', 'mm/dd/yyyy hh24:mi:ss'));
-- OR
-- クエリの実行前のテーブルをクローン
create table backup_table_clone clone my_table before (statement => '8e5d0ca9-005e-44e6-b858-a8f5b37c5726');

-- クローンしたテーブルと現在のテーブルをSWAPする。
alter table my_table swap with backup_table_clone;
```

**Fail Safe**
サポートに問い合わせ！！

https://docs.snowflake.com/ja/user-guide/data-failsafe.html

**SWAPの代わりにINSERT OVERWRITE**

SWAPを行うと元テーブルのタイムトラベルなどの情報が無くなってしまうため、 `INSERT OVERWRITE` も使える。

```SQL
-- クローンからのリストア
insert overwrite into my_table
  select * from backup_table_clone;
-- Time Travelからのリストア
insert overwrite into my_table
  select * from my_table at (timestamp => to_timestamp_tz('04/05/2013 01:02:03', 'mm/dd/yyyy hh24:mi:ss'));
```

https://docs.snowflake.com/ja/sql-reference/sql/insert.html#optional-parameters

# Time Travel と Fail Safe

Time TravelとFail Safeの説明は省略
ドキュメントへのリンク

https://docs.snowflake.com/ja/user-guide/data-availability.html

ドキュメントを読むとテーブルをDROPしたときはTime TravelでUNDROPができることが分かる。
......間違ってUPDATEやINSERTをしたときはどうやって戻すんだろう？

# ALTER TABLE SWAP

ここで冒頭に記載したリストアの方法の出番

1. Time Travelで過去のテーブルをクローンする。
1. クローンしたテーブルと対象のテーブルを `ALTER TABLE SWAP` する。

```SQL
-- 指定した時刻のテーブルをクローン
create table backup_table_clone clone my_table at (timestamp => to_timestamp_tz('04/05/2013 01:02:03', 'mm/dd/yyyy hh24:mi:ss'));
-- OR
-- クエリの実行前のテーブルをクローン
create table backup_table_clone clone my_table before (statement => '8e5d0ca9-005e-44e6-b858-a8f5b37c5726');

-- クローンしたテーブルと現在のテーブルをSWAPする。
alter table my_table swap with backup_table_clone;
```

`ALTER TABLE SWAP` のドキュメントはこちら

https://docs.snowflake.com/ja/sql-reference/sql/alter-table.html#parameters

アクセス制御権限もSWAPしてくれて便利

> テーブルに定義された整合性制約を含む、2つの指定されたテーブル間ですべてのコンテンツとメタデータを交換します。また、すべてのアクセス制御権限付与を交換します。2つのテーブルは、基本的に1つのトランザクションで名前が変更されます。

`ALTER TABLE SWAP` の使用感は以下の記事を参照。

https://dev.classmethod.jp/articles/snowflake-advent-calendar-2019-12-alter-table-swap-is-useful/

# Cloneでバックアップ・リストア

Standard Editionの契約をするとTime Travelの時間は24時間だが、もっと時間を延ばしたいときはテーブルのクローンをするという抜け道がある。

Snowflakeのマイクロパーティションはテーブルから参照されている限り消えない。そのため、テーブルのクローンをするとクローンをした時点のマイクロパーティションは削除されなくなる。

テーブルに対する更新が多い場合にTime Travelの日数を0 or 1日にして、Cloneを実行することマイクロパーティションの量を抑えることもできる。

実はSnowflakeのドキュメントに似たようなことが書いてある。

https://docs.snowflake.com/ja/user-guide/tables-storage-considerations.html



## 定期的なCloneタスク

Time Travelのようにバックアップするために、定期的にクローンを作成し、一定期間後にクローンを削除するタスクを作成する。

## リストア
クローンからリストアしたい場合は以下のクエリを実行する。
```SQL
alter table my_table swap with backup_table_clone;
```

クローンで引き継がれるもの、引き継がれないものはドキュメントを参照

https://docs.snowflake.com/ja/sql-reference/sql/create-clone.html

https://docs.snowflake.com/ja/user-guide/object-clone.html

# 複製とフェイルオーバー・フェイルバック

リージョンをまたいでバックアップできる。

https://docs.snowflake.com/ja/user-guide/replication-failover.html
プログラムを設計するってなんなのか考えてみた～2022夏～

# コンピューターにとって設計は必要なのか？
プログラムとはコードから作られる、コンピューターに命令するための成果物である。
コンピューターは、この成果物に対して設計が必要なのだろうか？

答えは **ノー** である。

なぜならコンピューターは、洗練された設計のコードで書かれていても、スパゲッティなコードで書かれていても、同じ命令であれば同じ動作をするからである。

# 設計を必要としているのは誰なのか？
コンピューターは設計を必要としない、つまり完成したコードには設計が必要がないのである。では、設計がいつ必要になるのか？

それはコードが変化する時、つまり**人間がコードを書くとき**にはじめて必要になってくるのであるのではないか？

# 人間にとって設計が必要な理由
人間とは、考えが変化し続ける極めて曖昧なもの存在である。
そしてプログラムも人間が望むために作られているので、人間の考えによって変化し続ける必要がある。
この変化し続けることに耐えるために、設計というものが作られたのではないだろうか？
変化に耐える、変更を容易にすることこそが設計である。

つまり、すべての設計の考えは**変更容易性のため**に存在していることになる。

# 変更容易性とは何なのか？
これも、人間という存在により以下の３つの性質がある。

* **人間がコードを変更しやすくするための性質**
変更容易性そのものであるが、単一責任の原則やエンティティなど疎結合なコードにすることにより変更を容易にする性質

* **人間がコードを知覚しやすくするための性質**
コメントの記入、ネストの回避、メソッド化、高凝集にする、DRY原則などにより人間が読みやすくコードを理解しやすくすることにより変更を容易にする性質

* **人間がコードを強制しやすくするための性質**
privateなどのアクセス修飾子、ユニットテスト、値オブジェクトなどによって、人間のコードの書き方を強制させることにより変更を容易にする性質

# 設計を考える
世の中には、オブジェクト指向やデザインパターン、ドメイン駆動設計などの様々な設計にまつわる考え方が存在する。
難解な内容で何のためなのかわからないことがあると思うが、すべては変更容易性のためであり３つのいずれかの性質をもっていると考えれば内容の把握もしやすくなるのではないだろうか？


世界中のプログラマーが設計を理解できることを祈り、2022夏の話を終わりにしたいと思う。
jest.spyOnでclassのインスタンスメソッドをモック化するとnot a functionエラーになる場合

# 問題

クラスのインスタンスメソッド内で、APIで何かをfetchしてくるケースを考えます。たとえば以下のように`getGlobalIp()`でグローバルIPを取得。

```ts:Hoge.ts
import axios from 'axios';

export class Hoge {
  getGlobalIp = async (): Promise<string> => {
    const { data } = await axios.get<{ origin: string }>('https://httpbin.org/ip');
    return data.origin;
  };
}
```

この戻り値が常に固定値になるように、`jest.spyOn`でモック化してみます。

```ts:Hoge.test.ts
import { Hoge } from './Hoge';

it('グローバルIPアドレスを取得', async () => {
  jest.spyOn(Hoge.prototype, 'getGlobalIp').mockReturnValue(Promise.resolve('8.8.8.8'));

  const hoge = new Hoge();
  expect(await hoge.getGlobalIp()).toBe('8.8.8.8');
});
```

すると、`because it is not a function`とか叱られてエラーになっちゃいました。

```
 FAIL  test/Hoge.test.ts
  ✕ グローバルIPアドレスを取得

  ● グローバルIPアドレスを取得

    Cannot spy the getGlobalIp property because it is not a function; undefined given instead

      2 |
      3 | it('グローバルIPアドレスを取得', async () => {
    > 4 |   jest.spyOn(Hoge.prototype, 'getGlobalIp').mockReturnValue(Promise.resolve('8.8.8.8'));
        |        ^
      5 |
      6 |   const hoge = new Hoge();
      7 |   expect(await hoge.getGlobalIp()).toBe('8.8.8.8');

      at ModuleMocker.spyOn (../../node_modules/jest-mock/build/index.js:783:15)
      at Object.<anonymous> (test/Hoge.test.ts:4:8)
```

TypeScriptで書いてるので、エディタでエラーが出ないってことはメソッドはちゃんと存在するということ。
![CleanShot 2022-08-05 at 07.20.47@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24333/25324cf3-699e-69f0-acfc-3acc516ecf68.png)

もしメソッド名間違えてたら、こうなります。
![CleanShot 2022-08-05 at 07.20.28@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24333/a9ea838d-d257-4f54-f073-ce5debb18cd8.png)

最初ぜんぜん意味がわからずドハマリしたのですが、一応回避策が見つかったので書いておきます。

# 対策

インスタンスメソッドの書き方が問題でした。
クラスフィールド（インスタンス変数）に関数オブジェクトを代入する記法だと、`jest.spyOn`では関数として認識してくれないのです。
アロー関数でもfunctionでも、どちらもNG。

```ts:NGパターン
export class Hoge {
  getGlobalIp = async () => {};
}

export class Hoge {
  getGlobalIp = async function () {};
}
```

メソッド構文で書くと、ちゃんと`spyOn`成功します。
```ts:OKパターン
export class Hoge {
  async getGlobalIp() {}
}
```

修正版の全体

```ts:Hoge.ts
import axios from 'axios';

export class Hoge {
  async getGlobalIp(): Promise<string> {
    const { data } = await axios.get<{ origin: string }>('https://httpbin.org/ip');
    return data.origin;
  }
}
```

実行結果
```
 PASS  test/Hoge.test.ts
  ✓ グローバルIPアドレスを取得 (1 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.501 s, estimated 4 s
```

# おわりに

`this`の関係でクラスフィールド＆アロー関数でメソッド定義したいことも多いから、クラスフィールドで定義したメソッドも`spyOn`できるようにならないもんかなぁ・・・
誰か詳しい人いたら教えて下さい！

ちなみに、クラスメソッド（`static`）は、クラスフィールドとしてメソッド定義してもちゃんと`spyOn`できました。インスタンスメソッドも、Jestのバージョンアップで対応される可能性はありそうですね。

この記事で使ったライブラリのバージョンは以下です。

* typescript@4.7.4
* jest@28.1.3
【Unity】スマホアプリのプロジェクト作成手順

## 前提条件
Unity Hubをインストールしていること

## モジュールのインポート
1. Unity Hubを開く
1. Installsタブを選択
1. 利用するバージョンの設定画面を開く
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/e9ba413d-4ceb-9251-79c0-796d9bd9eca2.png)
1. add modulesを選択
1. Android Build SupportとiOS Build Supportを選択してInstall
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/054c87a3-3825-d4f0-7227-c67c1036f99e.png)

## 新規プロジェクトの作成
1. Unity HubでProjectsタブを開く
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/ca325cdf-3e47-d600-eaf5-1988209215b2.png)
1. New projectを選択
1. 利用したいtemplateを選択
1. Project nameを入力
1. Locationに好きな保存先を指定
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/e07fc4a1-1191-cfc6-d79b-071683f55c5c.png)
1. Create projectを選択
1. しばらく待つとEditorが開く

## プロジェクトの初期設定
1. File - Build Settingを選択
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/a127b73d-a170-6b80-d750-30afb9c8aed5.png)
1. PlatformからAndroidを選択
1. Switch Platformを選択
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/8f4610bc-7850-47e0-7a3b-7fb60c50d8a1.png)
値を対数変換する(SPSS Modeler データ加工逆引き3-10)

## 値を対数変換する（logN変換）

![スクリーンショット 2022-07-25 17.20.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/5e9cd166-ee5b-1845-63e6-e1344312e9ce.png)

## 1.想定される利用目的

・偏りのあるデータを扱いやすくする
・予測モデルの性能向上のための特徴量作成

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/blob/main/log_transformation.str?raw=true

## 3.サンプルストリームの説明

![スクリーンショット 2022-07-25 15.20.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/a74e359b-db23-5cc3-127f-1822c3d3b5a2.png)

a.入力するデータは以下の通りです。
![スクリーンショット 2022-07-25 15.21.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/fc80047f-e470-1f49-6ee0-62b8d182d82d.png)

b.[ヒストグラム]ノードを実行します。
![スクリーンショット 2022-07-25 15.22.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8c26c000-6135-4946-bbc9-8476ecc8e1da.png)

c.[フィールド作成]ノードを編集します。対数変換LogNの関数はlog(フィールド)です。
![スクリーンショット 2022-07-25 15.22.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/96399001-aab4-1008-cb92-1becbb240af5.png)

[プレビュー]します。
![スクリーンショット 2022-07-25 15.22.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/b3d28305-5b4c-4b41-abfb-f8132e17adbf.png)

d.[ヒストグラム]ノードを実行します。
![スクリーンショット 2022-07-25 15.23.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/f90d3a99-6df5-116e-73a1-b9d17616b032.png)

#### [変換]ノードを利用する

e.[変換]ノードを編集します。
![スクリーンショット 2022-07-25 15.23.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/4b12d655-14ed-1444-c159-ab072e59cf47.png)

[実行]をします。LogNを選択して[生成]から[フィールド作成ノード]を選択します。
![スクリーンショット 2022-07-25 15.26.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/6ffb4592-7ff8-6e75-c4b7-44e989293f87.png)

[標準化されていない変換]を選択します。fが自動生成されdと同じ結果が得られます。
<img width="300" alt="スクリーンショット 2022-01-12 10.02.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/0505ae6d-5022-8e26-9e85-7778ef8bfd49.png">

＊[標準化された変換]を選択すると平均0で標準偏差1に標準化します。

![スクリーンショット 2022-07-25 15.27.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/562b1b83-8279-3c77-2fa9-fc9885cf3b58.png)

#### 注意点

回帰モデルのように入力フィールドが正規分布を仮定する場合には利用されますが、これにより必ずメリットがある訳ではありません。

## 4.参考情報

#### 対数変換を扱った記事

https://www.ibm.com/blogs/solutions/jp-ja/modeler-tips-17/

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
Flutter URL内のタグ情報を取得（最後に個人開発アプリリリースされたのでかるく紹介）

# はじめに
Flutterを使ってアプリを個人開発中（まだまだ奮闘中の身）
ユーザーにURLを入力してもらい、そのURL内のタイトルとサムネイルを抽出する機能を作成したため紹介

#開発環境
・使用言語：dart(flutter)
・AndroidStudio 4.1.2
・iOS シミュレーター(iOS14.5)

# モデルの作成
まずはタイトルと画像情報のURLを管理する用のモデルを作成
今回はyoutubeのURLを使用することを前提としているのでYoutubeDataとしていますが、今回の実装であれば別にyoutubeのURLではないURLでも問題なく動作します

```dart
class YoutubeData {
  YoutubeData({
    required this.title,
    required this.thumbnailUrl,
  });
  // 
  final String title;

  final String thumbnailUrl;
}
```

# URLへアクセス

今回使用したライブラリはこちら

https://pub.dev/packages/http

URLをStringからUriにparseして使用
全ての情報を取得した後にHTMLタグごとでタイトル情報およびサムネイル情報を引っ張りたいため、HTMLタグとして認識
```dart
// URLにアクセスして情報をすべて取得
    final response = await get(Uri.parse(url));
// HTMLパッケージでHTMLタグとして認識
    final document = parse(response.body);
```

# タグの中身を抽出
あとはtitleとimageのタグ情報を抽出して返却するだけ
比較的簡単でした！！！

```dart
// ヘッダー内のtitleタグの中身を取得
    title = document.head!.getElementsByTagName('title')[0].innerHtml;
    // ヘッダー内のmetaタグをすべて取得
    var metas = document.head!.getElementsByTagName('meta');
    for (var meta in metas) {
      // metaタグの中からname属性がdescriptionであるものを探す
      if (meta.attributes['property'] == 'og:image') {
        imageUrl = meta.attributes['content']!;
      }
    }

    return YoutubeData(title: title, thumbnailUrl: imageUrl);
```

# かるーーーく宣伝
この度初めて個人開発でアプリをリリースしましたーー(iOSのリジェクト辛かった。。)
内容は音楽練習用課題管理アプリです。（今回紹介した機能は参考演奏登録機能で使用しています）
まだiOSだけなのでAndroidも追々リリースする予定です（せっかくFlutterでやってるので）

音楽/楽器やってる方はぜひぜひ覗いてみてくださいな

https://apps.apple.com/jp/app/askmu/id1627601862
【Coroutinesガイド】IntelliJ IDEAを使ったコルーチンのデバッグ - チュートリアル

※ソース記事は[こちら](https://kotlinlang.org/docs/debug-coroutines-with-idea.html)
このチュートリアルでは、Kotlinコルーチンを作りIntelliJ IDEAを使ってデバッグする方法をデモする。
チュートリアルは、事前に[コルーチン](https://kotlinlang.org/docs/coroutines-guide.html)の概要の知識があることを想定している。

::: note
デバッグは`kotlinx-coroutines-core`バージョン1.3.8以上で動作する。
:::
# コルーチンの作成
1. IntelliJ IDEAでKotlinプロジェクトを開く。無い場合は一つ[作成](https://kotlinlang.org/docs/jvm-get-started.html#create-an-application)する。
1. `src/main/kotlin`内の`main.kt`を開く。
`src`ディレクトリには、Kotlinソースとリソースが含まれる。`main.kt`ファイルには`Hello World!`を出力するサンプルコードが含まれている。
1. `main`関数内のコードを変更する。
    - コルーチンをラップするために[runBlocking](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html)ブロックを使う。
    - deferred値の`a`と`b`を計算するコルーチンを作るため、[async](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html)関数を使う。
    - 計算結果を待つために[await](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/await.html)関数を使う。
    - アウトプットに計算状態と掛け算の結果を出力するため、[println](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/println.html)関数を使う。
    ```Kotlin
    import kotlinx.coroutines.*
    
    fun main() = runBlocking<Unit> {
        val a = async {
            println("I'm computing part of the answer")
            6
        }
        val b = async {
            println("I'm computing another part of the answer")
            7
        }
        println("The answer is ${a.await() * b.await()}")
    }
    ```
1. `プロジェクトのビルド`をクリックしてこのコードをビルドする。 
![imgc1](https://kotlinlang.org/docs/images/flow-build-project.png)

# コルーチンのデバッグ
1. `println()`関数呼びだしを持つ行にブレークポイントを設定する。
![imgd1](https://kotlinlang.org/docs/images/coroutine-breakpoint.png)
1. 画面の上にある実行構成のとなりの`デバッグ`をクリックすることで、デバッグモードでコードを実行する。
![imgd2](https://kotlinlang.org/docs/images/flow-debug-project.png)
`デバッグ`ツールウィンドウが表示される。
    - `フレーム`タブにはコールスタックが含まれる。
    - `変数`タブには現在のコンテキストの変数が含まれる。
    - `コルーチン`タブには、実行中か一時停止中のコルーチンに対する情報が含まれる。3つのコルーチンがあることが見えている。最初のものは`RUNNING`状態を持ち、他の二つのものは、`CREATED`状態を持っている。
![imgd3](https://kotlinlang.org/docs/images/coroutine-debug-1.png)
1. `デバッグ`ツールウィンドウの`再開`をクリックすることで、デバッグセッションを再開する。
現在`コルーチン`タブには次のものが見えている。
    - 最初のコルーチンは`SUSPENDED`状態であり、掛け算をするために値を待っている。
    - 二つめのコルーチンは`a`の値を計算している。`RUNNING`状態を持つ。
    - 三つめのコルーチンは`CREATED`状態を持ち、`b`の値を計算していない。
1. `デバッグ`ツールウィンドウの`再開`をクリックすることで、デバッグセッションを再開する。
現在`コルーチン`タブには次のものが見えている。
    - 最初のコルーチンは`SUSPENDED`状態であり、掛け算をするために値を待っている。
    - 二つめのコルーチンは値を計算し消えている。
    - 三つめのコルーチンは`b`の値を計算しており、`RUNNING`状態を持つ。

IntelliJ IDEAのデバッガーを使うことで、自分のコードをデバッグするためにそれぞれのコルーチンを詳しく調べることができる。
Blazorでselectタグを初期値に戻す方法

# 0.Intro
ちょっとした開発でBlazorを使っています。不慣れなので如何にもBlazorという要素は使用しておらずinputタグ,Buttonタグ等でやりくりしています。それでも所謂SPAの便利さを十分に享受できて便利になったとつくづく思います。
そんな中、あるデータのグルーピングをselectタグから選んだキーワードで変えながら比較して見るという案件がありました。キーワードを選ばせてグルーピングを変えるという機能は簡単にできたのですが、ではselectタグを初期値に戻すにはどうすれば良いか、大変悩みました。
画面表示時の最初の表示時はselectタグのvalueに紐付けた変数に値を代入するとその値に設定してくれます。ただ初回以降selectの値を変更するとvalueに紐付けた変数に値を代入しても変更されません。ある値に設定したいという時の第一選択肢はbindなのですが効きませんでした。selectにて値変更した後の後続の処理を入れたいので@onchangeを使っていました。なので@bindだとエラーにもなります。
そんな中、色々調べた結果以下のようにすると実現できました。

# 1.Code

```
@page "/selsample"

<PageTitle>SelSample</PageTitle>


 <select @bind=SelValue>
    @foreach(var t in @_menu)
    {
        <option value=@t>@t</option>
    }

</select>

    @if(_countlist.Count !=0)
    {
        @foreach(var i in @_countlist)
        {
            <p>@i</p>
        }
    }
    <button @onclick="Reset">
        Reset
    </button>

@code {

    List<string> _menu = new List<string> { "1", "3", "5", "7", "9"};
    List<string> countlist = new List<string> { "1", "2", "3", "4", "5","6", "7", "8", "9", "10"};
    List<string> _countlist = new List<string>();
    private string _SelValue = "1";
    
    private void Reset()
    {
        SelValue = "1";
    }

    private string SelValue
    {
        get {
            _countlist = countlist.Where(e => int.Parse(e) >= int.Parse(_SelValue)).ToList();
            return _SelValue; 
        
        }
        set
        {
                _SelValue = value;            
        }
    }
}

```

# 2.Explanation
カスタム バインディング形式、なるほど思いました。これだとバインドしつつ、必要な処理も書けますね。
目的通りの動きになりました。

簡単ではありますが大変悩みましたので共有させていただきます。
Ubuntu22.04 Python仮想環境にDjangoとDjango REST frameworkをインストールする

## 概要
UbuntuのPython仮想環境にDjangoとDjango REST framework(DRF)をインストールします。仮想環境はDjango推奨のvenv、環境はUbuntu22.04、Python3.10.6、Django3.2.15(LTS)、DRF 3.13.1です。

2022/8/10現在Djangoは3.2系の最新は3.2.15、Django REST frameworkの最新は3.13.1でした。
```
$ python3 -m pip install Django==
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/3c346799-5041-09d0-5de6-0d729b7104df.png)
```
$ python3 -m pip install djangorestframework==
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/a70e889d-d011-653e-af76-485634d47172.png)

## 手順1 仮想環境を作る
ユーザのホームにフォルダを作ってその中に仮想環境を作ります。
```
$ mkdir solution
$ cd solution
solution$ python3 -m venv .venv_drf
```

## 手順2 仮想環境をアクティブにしてpipを最新版にする
仮想環境でpipを最新にします。
```
solution$ source .venv_drf/bin/activate
(.venv_drf) solution$ python -m pip install --upgrade pip
```

## 手順3 Django3.2の最新版とDRFの最新版をインストールする
```
(.venv_drf) solution$ python -m pip install Django==3.2.*
(.venv_drf) solution$ python -m pip install djangorestframework
```

仮想環境を閉じます。
```
(.venv_drf) solution$ deactivate
solution$ 
```

## さいごに
今回は開発環境ですが、本番環境でも仮想環境を使えば他のwebアプリとライブラリを別にできるので、拡張性を考えて仮想環境を作ろうと思います。