OmniAICreator/Qiita-1.07M huggingface dataset:
【VSCode】【Ruby】if文などのend を自動入力してくれる拡張機能

# end の自動入力
VSCode の[endwise](https://marketplace.visualstudio.com/items?itemName=kaiwood.endwise)という拡張機能を入れることでif文などのend が自動で入力されるようになります。

今まで何回もend の入力漏れでエラーを起こしていたので、もっと早く設定しておけば良かったです...

https://marketplace.visualstudio.com/items?itemName=kaiwood.endwise
web開発初心者がlocalhost環境から外部にサイトを公開するまでに躓いたこと[Vue.js+nginx]

#最初に
frontendはvue
backendはfastapi
serverはnginxを使いました。
一応自分と同じくらいの知識量の人を対象にして書くのでわかってる人にはくどく感じるかも。
web開発は初めてで間違っている部分もあるかと思うので、
間違いあればぜひご指摘ください。

#まずやったこと
vueのプロジェクトをnpm run buildした。
これでbuild結果としてdistディレクトリが生成される
/var/www/htmlをnginxのルート(https://ewords.jp/w/%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88%E3%83%AB%E3%83%BC%E3%83%88.html)としたので
distディレクトリ内部を/var/www/htmlにコピーして
systemctl start nginx
でnginxを起動した。

以下遭遇した問題


#そもそもグローバルＩＰ先が応答しない
最初自分のコンピュータそのものをwebサーバーにしようとしたしたときに発生した。
これはおそらく自身が契約しているルーターの設定周りの問題。
おとなしくGCP,AWSといったクラウドサービスでインスタンス立てるか、レンタルサーバーを借りよう。以下GCEでインスタンス立てて話を進めることにする。
なおGCEに開発環境を持っていくのはgitを使えばよい。
あと、注意点としてdocker環境で構築している場合にも外部にはつながらなくて、
繋がるようにするには特殊な設定が必要みたいです。

#CSOR問題
これはlocalhostでも同様にある問題だけど一応のせとく。
ログインやデータベース周りはfirebaseを使っていたので問題なかったが、
stripeのapiを使おうとしてCSORにぶち当たった。
回避策としてfirebaseのcloud functionとか使ったりもしたが、
そもそもCSORでcloud functionが呼び出せない。
結論としては素直にbackendで書こう。
vueはfrontend。
vueはfrontend。
大事なことなので2度言います(主に自分に向けて)。
frontendで外部のサイトにアクセスするのは基本NGです。
firebase使えばbackendは要らないという幻想にとらわれていたせいで、
だいぶ時間を無駄にしました。
fastapiとかちょっとpython触ったことあるならめちゃ簡単にかける。
あまりbackendに難しいイメージを持たなくていいです。
実際の連携としては
nginxにプロキシ設定を書きます。これについては後ほど。


#リロードすると404 not found
これは実際にはroot以下に対応するフォルダ、ファイルがないから起きる。
ちゃんとvueを経由して問い合わせてあげないといけない。
そのために.htaccessファイルが必要です。
https://router.vuejs.org/guide/essentials/history-mode.html#example-server-configurations
上記に.htaccessファイルの書き方あります。
そこで行き意気揚々とvueのpublicディレクトリに追加してbuildしたんですが、
無常なるかな404 not found が自分をあざ笑うかのように再び表示されるだけであった。
ここでnginxの罠１です。
nginxは.htacesssファイルが使えない！
解決策の一つとしては.htaccssの内容をnginx用に変換してくれるコンバータを使うことです。
https://winginx.com/ja/htaccess

変換された内容を
nginxのsites-available以下に追記すれば、上手く働きました。

#プロキシがうまくいかない
nginxの罠2
localhostでは上手くいっていた
vueのvue.congfig.jsに書いたproxy設定が
公海サーバーでは機能しなかった。
ちなみにvue.config.jsのproxy設定はこちら。
fastapiは標準でhttp://127.0.0.1:8000
がAPIのURLになるので

```vue.config.js
 devServer: {
'^/api': {
                target: "http://127.0.0.1:8000",
                changeOrigin: true,
            }
}
```
としました。
この問題の解決策は
プロキシ設定をnginxにかいてやること。
自身の場合fastapiを使っていたので

```default
location /api {
        proxy_pass http://127.0.0.1:8000;
    }
```
のように追記した。

#まとめ
web開発もサーバー通信も初めてだったのに、まあいけるやろってのりで公式ドキュメントをろくによまず進めていったのがぬまった原因だなと思う。急がば回れだね。
まあ、この失敗の経験が誰かの役に立てば幸いです。
Cloudwatch EventsとSSM オートメーションを使用してRDSの自動停止・起動を試してみた

## 概要
クラスメソッドさんの記事の通りです。
RDSの設定方法がなかったので、主にRDSの検証内容について記載します。
https://dev.classmethod.jp/articles/tsnote-ec2-ssm-automation/

## 作業手順

### IAMロールの作成
ロール名: event-ssm-automation-role
ポリシーをアタッチ: AmazonSSMAutomationRole

Cloudwatch Eventsにロールを付与するので、信頼関係の編集を実施します。

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "events.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```


■RDS用のポリシー作成
必要な権限は以下の通りです。
※DescribeDBInstances がないとSSMオートメーションの実行前と実行後のステータスチェックができなくなります。ステータスチェックが失敗しても動作はしましたが全体のステータスも失敗になります。

```rds-stop-start
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBInstances",
                "rds:StopDBInstance",
                "rds:StartDBInstance"
            ],
            "Resource": "arn:aws:rds:ap-northeast-1:<AWSアカウントID:db:<DBインスタンス名>"
        }
    ]
}
```

#### エラーが出ている場合はSSM→StepIDからエラー詳細を確認できます。
> An error occurred (AccessDenied) when calling the DescribeDBInstances operation: User: arn:aws:sts::xxxxxxxxxxxx:assumed-role/event-ssm-automation-role/ba0cd0d13d1b38bbae3b4b2f8bb71482 is not authorized to perform: rds:DescribeDBInstances on resource: arn:aws:rds:ap-northeast-1:xxxxxxxxxxxx:db:kaba-test-auto-start-stop-20210706

## CloudwatchEventsの設定
CloudwatchEventsの設定方法についてはクラスメソッドさんの記事にある通りなので割愛いたします。
インスタンスIDの部分はRDSのインスタンス識別子でOK
cron方式の場合は、UTCなので注意が必要です。
SSM ドキュメント
 - 停止の場合: AWS-StopRdsInstance
 - 起動の場合: AWS-StartRdsInstance

### あれ？っとなったところ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233935/cd213315-c4c6-d132-4195-4a74208f6b64.png)

全体的なステータス が成功してもステップ1が失敗になるのが気になって調べてみました。
SSMドキュメントのAWS-StopRdsInstanceを確認すると `DesiredValues: ["stopped", "stopping"]` で RDSのステータスがstoppedかstoppingになっていれば、ステータスが成功になるので起動中のRDSに対しては「失敗」になっていることが正常でした。
試しに停止中のRDSへ実行してみると「AssertNotStopped」は成功になりました。
なんか気持ちわるいですね(^^;

```
ステップ名: AssertNotStopped
アクション: aws:assertAwsResourceProperty
ステータス: 失敗
```

SSMドキュメントのAWS-StopRdsInstance

```
##一部抜粋
 -
    name: AssertNotStopped
    action: aws:assertAwsResourceProperty
    isCritical: false
    onFailure: step:StopInstance
    nextStep: CheckStop
    inputs:
      Service: rds
      Api: DescribeDBInstances
      DBInstanceIdentifier: "{{InstanceId}}"
      PropertySelector: "$.DBInstances[0].DBInstanceStatus"
      DesiredValues: ["stopped", "stopping"]
```

#### 最終的な実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233935/b6feebb2-db3e-66ff-b2c7-831670650ddf.png)


## まとめ
RDSも簡単にcron形式でstop/startが自動化できました！
SNSでSSMオートメーションが失敗した時に通知を送ることもできるようなので次回検証してみたいと思います。

https://dev.classmethod.jp/articles/cloudwatch-event-for-failed-of-ssm-automation/
Macのカメラがおかしいなあ



## 「カメラ使っていいですか？」の許可をリセット

```
% tccutil reset Camera
```


## iPhoneをWebカメラにするアプリのpluginを消す

```
tkrmbp:/Library/CoreMediaIO/Plug-Ins/DAL% ls -la
total 4
drwxr-xr-x  6 root  wheel  192  6  2 16:59 .
drwxr-xr-x  3 root  wheel   96  7  5  2020 ..
drwxr-xr-x  3 root  wheel   96 12 29  2020 EpocCamPlugIn.plugin
drwxr-xr-x@ 3 root  wheel   96  6  2 16:59 ImmersedCamera.plugin
drwxr-xr-x  3 root  wheel   96  3 31 02:41 IriunCamera.plugin
-rw-r--r--  1 root  wheel   37  7  5  2020 plugins-info.txt

tkrmbp:/Library/CoreMediaIO/Plug-Ins/DAL% sudo rm -rf EpocCamPlugIn.plugin ImmersedCamera.plugin IriunCamera.plugin
```

なおったぁ。。。。
YOLORで動画物体検出やってみた

## はじめに

物体検出モデルYOLORを使って動画の物体検出をする機会がありましたので、実行までの手順をまとめてみました。

## 環境

今回使用する環境はGoogle Colaboratoryです。

## 前準備

今回はGoogle ColaboratoryのGPU環境を使って実行していきます。

- メニューバーから「ランタイム」→「ランタイムのタイプを変更」をクリック

- 「ハードウェアのアクセラレータ」のプルダウンからGPUを選択

## 実行手順

- Google Driveをマウント

```python
from google.colab import drive
drive.mount('/content/drive')
```

- YOLORリポジトリのクローン(クローンは最初の一回のみ)

```bash
%cd "drive/My Drive" 
!git clone -b paper https://github.com/WongKinYiu/yolor
%cd yolor
```

- 各種ライブラリをインストール(最初の一回のみ)

```bash
!pip install -qr requirements.txt
!git clone https://github.com/JunnYu/mish-cuda
%cd mish-cuda
!python setup.py build install
%cd ..
!git clone https://github.com/fbcotter/pytorch_wavelets
%cd pytorch_wavelets
!pip install .
%cd ..
```

- YOLORの学習済みモデルをダウンロードする(最初の一回のみ)

```bash
!bash scripts/get_pretrain.sh
```

- 動画の物体検出を実行

    動画ファイルは[Pexels(フリー動画サイト)](https://www.pexels.com/videos/)からダウンロードしました

    ```bash
    !python detect.py --source '/content/drive/My Drive/movies/Pexels Videos 3644.mp4' --weights yolor-p6.pt --conf 0.25 --img-size 1280 --device 0
    ```


    推論後の動画は`./runs/detect/exp`ディレクトリに作成されます。

## 結果

約23秒の動画では、2分53秒で推論ができました。

※ Qiitaに載せられるファイル形式・サイズの都合上、mp4ファイルをgifファイルに変換し、23秒の動画を1秒にカットしています。

- 動画のカットにはiMovieを使用

- gif変換に使ったツールは[こちら](https://convertio.co/ja/mp4-gif/)

![Pexels-Videos-3644.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1705127/f583a306-9a6f-5ba0-6a7b-616ee51b0f9d.gif)

## まとめ

今回は、YOLORを使った動画の物体検出を行いました。

人混みで被写体が小さくても検出できており、ハンドバックなどの持ち物まで検出できているのはかなりすごいなと思いました。
MLOpsでのモデルやデータのモニタリング要件を考える

いわゆるMLOps、すなわち機械学習/AIモデルを継続的に運用していく仕組みにおいては、考えるべきポイントが多岐にわたる。その中で、モデルやデータのモニタリングに関する要件を整理してみる。

## MLOpsの全体像

MLOｐsは非常にスコープが広い概念なので、この記事で語るMLOｐｓの全体像を一旦定義する。基本的な教師あり学習を題材として、添付図のようなモデル開発+運用の流れをイメージしている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397277/b887413e-7264-2bbb-ee68-d24eebf72bf3.png)

* オリジナルデータからデータの準備(クレンジングや特徴量抽出)を行い、特徴量(features)データと予測対象(target)データのテーブルを作成
* その特徴量データの一部を学習用とし、モデル学習を実行
* 残りの特徴量データを使ってモデル評価を実行し、学習モデルの精度測定を行う
* 学習済モデル(ML model)はモデル管理用レジストリにて蓄積されリリース管理される
* 本番運用モデルがデプロイされると、日々のモデル実行が行われる
* モデル実行はREST形式の待受型(online型)と、定期的に実行されるバッチ型(batch)が代表的な方式

## モニタリング目的

上のMLOpsのスコープにおいて、モデルやデータを監視する目的は何か。2つほど挙げてみた。

* モデルが本番運用可能な品質であることを確認する
* 学習、評価、実行のデータが適切であることを確認する

## モデルのモニタリング要件

具体的な要件を整理してみる。３つの観点で要件が存在すると考えた。1,2はモデル、3はデータに対するもの。

**1. (再)学習結果のモデルが適切であること (モデル学習&モデル評価時)**
**2. 運用中のモデルが劣化していないこと (モデル実行時)**
**3. 学習、評価、実行のデータが適切であること**

1を更に具体化してみると、

* 学習済モデルの精度が十分高いこと
* 学習済モデルが過学習していないこと (モデルの汎化能力)
* 学習済モデルがアホなモデルになっていないこと (アホなモデル : 白なら犬、茶色なら猫というシンプルすぎるモデル構造。1分岐しか無い決定木のイメージ。過学習の一種だが再学習時に発生したことを見逃してしまう可能性があるので別に扱う)
* 学習済モデルが公平であること (人を対象にしたモデルでのFairnessやBias。倫理的に差別すべきでない人の属性グループ(男女など)に対して予測結果に差がついていないか）
* 学習済モデルの予測根拠が適切であること (モデルの説明性)　※特に大域的な説明（モデル構造)

2を更に具体化してみると、

* 本番運用モデルの精度が劣化していないこと (IBM OpenScaleでモデルのドリフトと呼ばれるもの)
* 本番運用モデルの予測根拠が適切であること (モデルの説明性) ※特に局所的な説明(各レコードがどういう根拠で判断されたのか）

3.を更に具体化してみると、

* 本番運用モデルの入力である特徴量データ傾向に大きな変化が生じていないこと (IBM OpenScaleでデータのドリフトと呼ばれるもの)
* 再学習、評価、実行データの分布が適切であること (再学習データが過去のモデル実行の影響を受けている場合、適切な学習結果にならないため、モデル実行の影響を受けていないコントロールグループ(統制群)のデータを用意する必要がある)

## モニタリング要件への対応方針

上記の具体的な要件への対応方針を整理してみた。

**1. (再)学習結果のモデルが適切であること (モデル学習&モデル評価時)**

| 要件 | 対応方針 |
|:-|:-|
|学習済モデルの精度が十分高いこと|テストデータに対する予測精度の評価 (Holdout or CrossValidation)|
|学習済モデルが過学習していないこと|テストデータに対する予測精度の評価 (Holdout or CrossValidation)|
|学習済モデルがアホなモデルになっていないこと|テストデータに対する予測精度の評価 (Holdout or CrossValidation)<br>テストデータに対する予測値の分布確認(ヒストグラム,混同行列,etc)<br>モデル構造の確認(ホワイトボックス型モデルの場合のみ)、予測変数の重要度リストの確認 |
|学習済モデルが公平であること|モデルの公平性の評価|
|学習済モデルの予測根拠が適切であること|モデル構造の確認(ホワイトボックス型モデルの場合のみ)<br>モデル説明性の評価(LIME,shap,etc)|

社内勉強会でディスカッションしたが、「アホなモデル」への対応方針が難しいよねとなった。モデルが本当にアホなのかどうかは、データの意味やビジネス知識も総動員して判断するケースもあるのではないか、それは自動的には無理でしょう、と言った感じ。

(2021/7/9追記) 機械学習におけるテストの良記事があったのでメモ。機械学習におけるテスト駆動開発という大きなテーマがここにある。
https://www.nogawanogawa.com/entry/machinelearning_testing

**2. 運用中のモデルが劣化していないこと (モデル実行時)**

| 要件 | 対応方針 |
|:-|:-|
|本番運用モデルの精度が劣化していないこと|本番運用データに対する予測精度の評価 (結果データを使った直接的評価)<br>本番運用データに対する予測精度の推定 (予測精度予測モデルによる間接評価)|
|本番運用モデルの予測根拠が適切であること|モデル説明性の評価(LIME,shap,etc)|

**3. 学習、評価、実行のデータが適切であること**

| 要件 | 対応方針 |
|:-|:-|
|本番運用モデルの入力である特徴量データ<br>に大きな変化が生じていないこと|特徴量データの変化検出<br>モデルが有効であるデータ範囲を超えてているかどうか(学習データから大きく外れたレンジのデータが入力されているか）|
|再学習、評価、実行データの分布が適切であること|特徴量データの分布確認(ヒストグラム,etc)|

## まとめ

要件のまとめと対応方針のみを整理してみた。
今後、クラウド各社サービスや製品との対応についても整理する予定（適切に整理できるのかやや不安・・・）。
alias_methodについて

## alias_methodとは

メソッドの別名を定義するメソッドになります。

## 使用方法

```example.rb
class
　
alias_method :hello, :hello_good_morninng

end

```
alias_method :別名メソッド, :元のメソッド名

で指定できます。

## 参照
https://docs.ruby-lang.org/ja/latest/class/Module.html#I_ALIAS_METHOD
PixivのイラストをID毎に一括でダウンロードする実験

## 特徴
Windows10 OSへのランタイムインストールが不要です。

[PixivPy](https://qiita.com/yuki_2020/items/716fa4e4ada65306f688)で必須な
**Pysonのインストール不要** 
[私立メロン高校パソコン部氏作](http://shimarisu.webcrow.jp/pixiv_api.html)で必須な
**VisualBasic のインストール不要** 

「車輪の再発明をしてはならない」の原則から、できる限り先人の作ったものを活用します。

## 必要なもの

[FireFox](https://www.mozilla.org/ja/firefox/new/)
[Selenium IDE（アドオン）](https://addons.mozilla.org/ja/firefox/addon/selenium-ide/)
[Pixiv Downloader（アドオン）](https://addons.mozilla.org/ja/firefox/addon/px-downloader/)
[私が書いたコード20行](https://github.com/team3star/pixivADL)
[100Mbps以上の光ファイバー回線(IPv6が望ましい)](https://mitsuboshitx.blog.fc2.com/blog-entry-725.html)

これだけ

※広告収入で営業しているお絵かきサイトなので普段使いはやめましょう。今回はあくまで実験です。

## 仕組み

ブラウザを自動操作することで一括ダウンロードを行います。
作品IDの一覧さえあれば、3～6秒毎にまとめてDLしてくれるのでPCを放置していてもOK。

## ID等は[サクラエディタなどお気に入りのテキスト編集ソフト](https://mitsuboshitx.blog.fc2.com/blog-entry-597.html)で置き換えてください

※メモ帳たちの宗教戦争回避

2021-08-09追記

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">機能改善を行ったのでご活用ください<br>マサカリも歓迎です<br><br>&lt;主な変更点&gt;<br>1.ブックマークでDL済か分かります<br>2.Bookmark2回目の時は自動コメント残します<br>3.私が死んでも <a href="https://twitter.com/hashtag/SeleniumIDE?src=hash&amp;ref_src=twsrc%5Etfw">#SeleniumIDE</a> なのでご自身で修正して <a href="https://twitter.com/hashtag/Pixiv?src=hash&amp;ref_src=twsrc%5Etfw">#Pixiv</a> の仕様変更にも対応可能<a href="https://twitter.com/hashtag/Qiita?src=hash&amp;ref_src=twsrc%5Etfw">#Qiita</a> <a href="https://twitter.com/hashtag/GitHub?src=hash&amp;ref_src=twsrc%5Etfw">#GitHub</a> <a href="https://t.co/SyxaAsCRzM">https://t.co/SyxaAsCRzM</a> <a href="https://t.co/ziE3Mht27m">pic.twitter.com/ziE3Mht27m</a></p>&mdash; 愛王丁花伝 (@iotkaden) <a href="https://twitter.com/iotkaden/status/1424564691985080321?ref_src=twsrc%5Etfw">August 9, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【Ruby】条件演算子を使ってif文をスッキリさせる

# 条件演算子とは
Rubyでは以下の形で ? を使って条件分岐をさせることができる。

```ruby
# 式 ? 真だった場合の処理 : 偽だった場合の処理
```

例えば以下のif文は、

```ruby
n = 55
if n > 50
  '50より大きい'
else
  '50以下'
end
#=> "50より大きい"
```

条件演算子を使うと次のように書き換えが可能。

```ruby
n = 55
n > 50 ? '50より大きい' : '50以下'
#=> "50より大きい"
```

単純なif文の場合は、上のように条件演算子を使ったほうがスッキリ書ける場合がある。

# 参考文献
伊藤 淳一 「プロを目指す人のためのRuby入門」, 技術評論社, 2017

https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html#cond
Seleniumで自動ログイン --メモ--

Selenium、PowerShellを使って、ライブドアブログの自動ログインを試した。
WebDriver.dll , chromedriver.exe など必要なファイルを'C:\Tools\selenium'に入れておいた。


```powershell

$work_dir = 'C:\Tools\selenium'

[System.Reflection.Assembly]::LoadFrom("$work_dir\WebDriver.dll")
$ChromeDriver = New-Object OpenQA.Selenium.Chrome.ChromeDriver
$ChromeDriver.Navigate().GoToURL('https://member.livedoor.com/login/')
$ChromeDriver.FindElementByXPath('//*[@id="livedoor_id"]').SendKeys('ライブドアブログのID')
$ChromeDriver.FindElementByXPath('//*[@id="password"]').SendKeys('ライブドアブログのパス')
$ChromeDriver.FindElementByXPath('//*[@id="submit"]').Click()
$ChromeDriver.Navigate().GoToURL('https://livedoor.blogcms.jp/member/')

```

 [参考にした記事]
[Getting Started in Web Automation with PowerShell and Selenium](https://adamtheautomator.com/selenium-powershell/)
CSS 親要素の背景色が表示されない

##”親要素の背景色が指定できなくなった場合”の解決策リスト
1. 親要素ボックスに高さ ``height``を指定
(子要素がその高さを超えてしまった場合はレイアウトが崩れる)

2. 親要素ボックスに ```overflow: hidden;``` を指定
(子要素の高さに依存する)

3. 親要素ボックスに``clearfix``を指定
(親要素ボックスの下にさらにボックスを作るイメージ）
4. 親要素ボックスに ``float:left;`` を指定
※``width: 100%;``にすること

(参考URL https://pata2.jp/127/stylesheets/css_others/float_container.html)
【Excel初心者向け】勝手にR1C1参照形式になってしまったときの対処法

## あなたはA1派？R1C1派？
Excelで編集しているとき、VBAプログラミングなんかでR1C1参照形式のほうが都合が
良いから、と意図的にR1C1参照方式にする方も多いと思います（スプレッドシートを編集していてGASを扱う方も多いと思います）。しかし、普段からR1C1参照形式を使わない方にとって、

### 突然列番号のアルファベットが数字になった！

と驚かれる方も多いでしょう。Rはrow（行）、Cはcolumn（列）の略ですが、
この表示形式を知らないと、

### 行も列も数字になってしまって訳わからん！

とパニックに陥らないように、A1方式に直す方法を貼っておきます。

![R1C1toA1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666984/ab4df113-e0aa-27ed-210e-35c711e94fba.jpeg)

ファイル→オプション→数式→数式の処理
「R1C1参照形式を使用する(R)」のチェックボックスを外す。

これで元通りになるはずです。
javascript FormDataオブジェクトの中身確認

Every Qiita #4
のんびり独学初学者の毎日投稿チャレンジ 4日目
今回は・・・
自作コミュニティアプリ開発でフォームデータの中身をjavascriptで確認する際に躓いた時の備忘録です

##FormDataで送られたデータを確認したい
```javascript:index.js
const 任意の変数 = document.getElementById('任意のid');
定義した変数.addEventListener("イベント", function(event){
const data = 定義した変数.files[0];//input type=fileの場合
const form_data = new FormData();
form_data.append("任意のname",data);
```
FormDataインスタンスを作成するとinputから送られてきたデータを取得することができます。
何が送られているのか確認したいので、

```javascript 
console.log(form_data);
```
結果:  FormData{}
***あれ？***
確認できない・・・

###修正後
```javascript
console.log(...form_data.entries());
```
結果：  ["image",File]
0: "image"
1: File {name: "画像名.png"}
length: 2
***確認できました！***
オブジェクトなので、関数使って中身確認しないといけないみたいです。
フレームワークとライブラリの違い

#はじめに
React学習中に、__「Reactはフレームワークではなくライブラリ」__と知り、
今まで勘違いをしていたため、「フレームワークとライブラリの違い」について調べたので備忘録。
この記事では、__フレームワークとは?__  __ライブラリとは？__について記載する。

#フレームワークとライブラリの違いとは？
下記サイトに自動車を例として記載が解説があった。
[【3分ITキーワード】 フレームワークとライブラリの違いは?](https://www.pentasecurity.co.jp/pentapro/entry/framework_library)
>フレームワーク : Webアプリケーションを開発する際、枠組みとして機能する開発ツール

>ライブラリ : Webアプリケーション開発する際、簡単に活用できるコードの集まり

 

>フレームワークとライブラリを自動車に例えると、自動車の仕組みがフレームワークであり、ヘッドライト、ナビゲーション、タイヤ等の部分的な要素がライブラリだと言えます。

なるほど。
VueとReactでは使用感が異なると感じていたのは、このためだったと理解した。
自分なりに例を上げると下記の様なイメージ。

__フレームワーク__
→熱帯魚飼育セット
　とりあえず1セット購入することで必要なものは揃っており、アクアリウムを始めることができる。

__ライブラリ__
→アクアリウム専門店
　店自体にはアクアリウムに必要なものは揃っている。そこから、自分が必要なものをピックアップして購入する。
<br>
アクアリウムは一切触ったことがないが、かなりイメージがついた。
制御する主が異なると理解。

>・フレームワークとライブラリはどちらも、一般的なソフトウェアの機能を比較的簡単な方法で実装できるように、他の誰かが書いたコードの集まりです。

>・フレームワークはプログラムの制御を反転します。フレームワークは必要な情報を開発者に尋ねていきます。しかし、ライブラリは異なります。プログラマは必要な場所で、必要な時にライブラリを呼び出します。

[「ライブラリ」と「フレームワーク」は何が違うのか](https://qiita.com/baby-degu/items/7dc4548bf7befc2671f4)

#まとめ
* 両者の違いはプログラマーが持つ「自由度」の差であり、「主導権」が変わってくる
* フレームワークの利用では、ルールに沿って記述する必要がある（空白を埋める感覚）
* ライブラリの利用は、必要な時に必要な場所で呼び出すことができる(書き手の自由)
拡張されたWSL2のディスクサイズを最適化する

```
wsl --shutdown
diskpart
# open window Diskpart
select vdisk file="C:\WSL-Distros\…\ext4.vhdx"
attach vdisk readonly
compact vdisk
detach vdisk
exit
```
or

```
wsl --shutdown
optimize-vhd -Path C:\WSL-Distros\…\ext4.vhdx -Mode full
```
RailsのActiveRecordでPOROをコンポジションするメモ

ちょっと思いついたのでメモ。

例えばユーザーに関係する処理だけどドメイン的にユーザークラスに実装するのは…けどユーザーのインスタンスメソッドとして扱いたい。Concernだと他のConcernとの関係が…。

そんなときPOROなクラスをコンポジションすればテストもしやすいのでは、と。

ActiveRecordの`after_find`コールバックでコンポジションする。

```ruby:user.rb
class User < ApplicationRecord
  after_find do
    @hoge = Hoge.new
  end
  delegate :fuga, :piyo, to: :@hoge
end
```

```ruby:hoge.rb
class Hoge
  def initialize
    # 初期化処理
  end
  
  def fuga
    # 複雑な処理
  end
  
  def piyo
    # 複雑な処理
  end
end
```

こうするとふつうにユーザーのインスタンスメソッドとして呼び出すことができるはず

```ruby:sample.rb
user = User.find_by(email: "test@example.com")
user.fuga
user.piyo
```

## メリット
* 役割が明確
* Hogeクラスに対してテストできる
* 他のConcernを気にしなくていい

## デメリット
* 委譲するメソッドが多くなると大変そう
* これってただモデルの行数減らしたいだけじゃ…
pythonを使ってリアクティブなWebアプリをお手軽に1分で作りたい

そう思ったことはありませんか。私はあります。
まず最初にチャレンジしたのは、Flask単体で作るWebアプリです。
おおよそ静的なページのみで構成する分には課題を感じません。
フォームに入力し、送信ボタンを押して画面をリロードする。シンプルな入力フォームならそれで済むのですが、時は令和。そんな貧弱なUXで、ユーザーが使ってくれるかというと疑問符がついてしまいます。

昨今では様々なフロントエンドのフレームワークが提供されており、こちらを使うことでぐるんぐるんと動くWebアプリの開発が比較的簡単に出来る環境が整っています。
今回は、Vue.jsを使うことにしました。
とはいえ、１から立ち上げていては時間がかかりすぎてしまいます。
プロトタイピングがしたいだけなのに！著者は叫びました。

そこから数ヶ月。色々なチャレンジをした結果、汎用化したのでこちらに公開しておきます。

https://github.com/geeorgey/vue_flask_template

## 環境
フロントエンドはVue.js です。
テンプレートはこちらからお借りしてきました。
https://github.com/tookit/vue-material-admin

バックエンドはFlaskです。どうしてもpythonで処理を書きたかったからです。

デプロイ先はHerokuです。無料の範囲で色々なことが出来ます。
こちらのページにあるDeploy to Herokuボタンを押せば、デプロイが完了します。
https://github.com/geeorgey/vue_flask_template
あとはちょこっと設定を加えます。

### Herokuに環境変数を設定する
Heroku postgresをインストールする
Heroku管理画面のResourcesタブを開き、Add-ons部分からHeroku Postgresを選択。 FreeプランでOKです。

### 環境変数を設定する
Settingsタブを開き、Reveal Config Varsボタンをクリック。 
環境変数欄にすでにDATABASE_URL が入っているのがわかると思います。
その下に４つ追加します。 
Key　｜　Value 
ENV　｜　development
FLASK_APP　｜　backend
FLASK_DEBUG　｜　1 
VUE_APP_BASE_API　｜　ここには、Heroku画面の右上にあるOpen App ボタンを押して開いたURLを入れてください。

## 現時点で実装してある機能
ログイン画面でメールアドレスとパスワードを入力してログインすることが可能です。 
ログイン画面でメールアドレスとパスワードを入力してRegisterボタンを押すとユーザー登録できます。
DBに登録されるパスワードはハッシュ化されておらず平文で保存されます。


## Just Do It
デプロイ後のイメージはこちらです。
https://vueflasktestgeeorgey.herokuapp.com/#/auth/login?redirect=%2Fdashboard
メアドとパスワードを入力することで登録・ログインが出来ますので使ってみて下さい。
メアドの認証はしていないのでダミーのもので構いません。

ログイン後のイメージはこちらと同様です。
http://vma.isocked.com/#/dashboard
色々なパーツが取り揃えられているので、必要なものをピックアップして画面に配置していきましょう。

## オプション
Slack用のbotを組み込む場合はこちらを参照。
https://qiita.com/geeorgey/items/7844dee644524dacac41


##関連リンク
[pythonを使ってリアクティブなWebアプリを作りたい【基礎編】](https://qiita.com/geeorgey/items/3f86b207cd412680b835)
[pythonを使ってリアクティブなWebアプリを作りたい【開発編】](https://qiita.com/geeorgey/items/ea60afe0c44a5f9db483)
Nginxダウンロード，インストール

VirtualBoxでLinux・CentOS環境構築の第三歩目です。

本ページではNginxをインストールします。

#前提条件
(ホストOS：Windows10)
VirtualBox 6.1.22
ゲストOS:CentOS-8.4

VirtualBox上でマシンを起動させて、以下のように行いました。


#手順
###Nginxをダウンロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1620534/b1b50533-4f70-5df0-306a-506f8d860a39.png)

保存し、解凍

###レポジトリ登録

```
 sudo vi /etc/yum.repos.d/nginx.repo
```

以下のように

```
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
```
####起動
```
sudo nginx
```
localhostで開くと以下のような画面が表示されました。
こちらはRedHat系だとこのような画面になるようです。
Nginx～の画面が表示されても成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1620534/c4a6759c-4e33-6d61-d112-33c2bedbb8c1.png)

#FAQ トラブルシューティング
###インストールがうまくいかない
→私の場合は、そもそもインターネット接続が切れていたりしていました。
Firefoxやping等で接続の確認をしてみてください。

###権限がありません
前述の通り、sudo~ で実行しました。
sudo無しで実行した際に言われた場合は試してみてください。
Beyondcorp Enterprise の Google Cloud Console and the Google Cloud APIs でService accountのアクセスが制御できるか？A. 現状はできない


#はじめに
Beyondcorp Enterprise の Google Cloud Console and the Google Cloud APIs (Context aware access for Google Cloud Console and the Google Cloud APIs) で Service account が制御できるかについて記載されたドキュメントがなかったので確認してみました。

結論としては、現状(2021/7/6)ではサポートされていません。

#やってみた結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/b85c384e-64a1-b065-a5f8-2f14cabf8479.png)

#その他の考慮点
Service accountの鍵が流出した場合の対策として、Beyondcorp Enterprise の Google Cloud Console and the Google Cloud APIs でIP制限を実施することはできないので、VPC Service Contol で制御することを検討したほうがよい。
SQLAlchemyとpydanticを組み合わせる

「（機械学習のモデルをS3に保存し）そのメタデータをDB（MySQL）で管理するクラス」の実装です。JOINなどの処理は行なっていません。


```python
from __future__ import annotations
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy import Column, Integer, String, Date
from sqlalchemy.ext.declarative import declarative_base
from pydantic import BaseModel, constr
from datetime import date


class DbClient:
    """MySQLへの問い合わせを管理する。"""

    def __init__(self, *, host: str, user: str, passwd: str, db: str):
        """データベースへの接続情報を保持する。

        Args:
            host (str): ホスト名
            user (str): DBのユーザー名
            passwd (str): DBのパスワード
            db (str): 利用するデータベース
        """
        engine = create_engine(
            f"mysql://{user}:{passwd}@{host}/{db}?charset=utf8",
            echo=True,
            encoding="utf-8",
        )
        self.session = scoped_session(
            sessionmaker(autocommit=False, autoflush=False, bind=engine)
        )

    def store_model_info(
        self, *, data_create_date: date, entry_market: str, cv_market: str
    ) -> MlModelModel:
        """データベースにモデル情報を保存する。

        Args:
            data_create_date (date): データの作成日
            entry_market (str): 対象マーケット
            cv_market (str): 成果対象
        Returns:
            MlModelModel: 追加したモデル情報
        """
        orm = _MlModelModelsOrm()
        orm.data_create_date = data_create_date
        orm.entry_market = entry_market
        orm.cv_market = cv_market
        self.session.add(orm)
        self.session.commit()
        # commit時点でauto incrementのidも参照できるようになっており、それをpydanticオブジェクトに変換する
        return MlModelModel.from_orm(orm)

    def fetch_model_info_by_id(self, model_id: int) -> MlModelModel:
        """idをキーにしてモデル情報を取得する。

        Args:
            model_id (int): モデル名

        Raises:
            ValueError: 対象のidのデータが存在しなかった場合

        Returns:
            MlModelModel: モデル情報
        """
        m = (
            self.session.query(_MlModelModelsOrm)
            .filter(_MlModelModelsOrm.id == model_id)
            .first()
        )
        if m is None:
            raise ValueError(f"model not found: id={model_id}")
        return PfsModelModel.from_orm(m)


class MlModelModel(BaseModel):
    id: int
    data_create_date: date
    entry_market: constr(max_length=255)
    cv_market: constr(max_length=255)

    class Config:
        orm_mode = True


Base = declarative_base()


class _MlModelsOrm(Base):
    __tablename__ = "ml_model_models"
    id = Column(Integer, primary_key=True, nullable=False)
    data_create_date = Column(Date)
    entry_market = Column(String(255))
    cv_market = Column(String(255))
```

# 参考資料

* [pydanticのfrom_ormのドキュメント](https://pydantic-docs.helpmanual.io/usage/models/#orm-mode-aka-arbitrary-class-instances)
* [【PythonのORM】SQLAlchemyで基本的なSQLクエリまとめ](https://qiita.com/tomo0/items/a762b1bc0f192a55eae8)
ApacheTomcatとNginxを連携する

本ページではApacheTomcatとNginxを連携する手順についてまとめていきます。
それぞれのインストールについては前の記事等をご覧ください。

#前提条件
ゲストOS：CentOS8
ApacehTomcat8.5
Nginx


#手順
###設定ファイルの追加
```
sudo vi /etc/nginx/conf.d/tomcat.conf
```
上記ファイルに、以下の内容を記述します。

```
server{
    listen 80;
     server_name localhost;
     root /var/local/www/nginx;
     access_log /var/log/nginx/tomcat_access.log;
     error_log /var/log/nginx/tomcat_error.log;
     location / {
        proxy_pass http://localhost:8080/;
     }
 }
```

###Nginx起動
```
sudo nginx
```



####確認
localhost:8080に接続し、以下のようにTomcatのページが表示されれば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1620534/0c9364a4-cbaa-71a7-b56b-c0f3304a8c3a.png)

#FAQトラブルシューティング
####上記の方法でできなければ
/etc/nginx/nginx.confを以下のように修正・追記するのも一つかもしれません。
再起動するとtomcat.confから読み込まれるようなので、この方法は二重に設定することになるかと思います。

```
...
    server {
        listen       80;
        server_name  _;
        location / {
            root   /usr/local/www/nginx;
            index  index.html index.htm;
        }
        location /examples/servlet {
            proxy_pass http://localhost:8080;
        }
        location ~ \.jsp$ {
            proxy_pass http://localhost:8080;
        }
    }

...
```
【CSS】背景固定のパララックスデザインをお手軽に実装する方法

# 概要

backgroundプロパティをいくつか指定するだけ背景固定のパララックスデザインを実装できます。

## 前提

今回は背景は動かさず固定が前提です。

## サンプルコード

```html

<div class="parallax"></div>

<style>
.parallax {
  /* 基本設定 */
  background-image: url('指定画像パス');
　　　　background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
  height: 300px;
  width: 100%;

  /* パララックス用設定 */
　　　　background-attachment: fixed;
}
</style>

```

## 参考記事 

パララックスデザインとは
https://saruwakakun.com/html-css/reference/parallax
ハイパスやバンドパスをかけたsacファイルを作成するシェル

#ハイパス+二乗
```hp_sqr.sh
#!/bin/bash

#使い方
#例 2Hzのハイパスフィルタ
#./hp.sh 2001 N.MMOH_U 2

for day in {1..9}
do
     echo "${1}0${day}"    
sac << EOF > /dev/null
r ${1}/${1}0${day}_${2}.s 
hp co ${3} p 2
sqr
w ${1}/${1}0${day}_${2}_hp${3}_sqr.s
q
EOF
done

for day in {10..31}
do
         echo "${1}${day}"
sac << EOF > /dev/null
r ${1}/${1}${day}_${2}.s 
hp co ${3} p 2
sqr
w ${1}/${1}${day}_${2}_hp${3}_sqr.s
q
EOF
done
```
#バンドパス+二乗
```bp_sqr.sh.sh
#!/bin/bash

#使い方
#例 10-20Hzのバンドパスフィルタ
#./bp.sh 2001 N.MMOH_U 10 20

for day in {1..9}
do
     echo "${1}0${day}"    
sac << EOF > /dev/null
r ${1}/${1}0${day}_${2}.s 
bp co ${3} ${4} p 2
sqr
w ${1}/${1}0${day}_${2}_bp${3}-${4}_sqr.s
q
EOF
done

for day in {10..31}
do
         echo "${1}${day}"
sac << EOF > /dev/null
r ${1}/${1}${day}_${2}.s 
bp co ${3} ${4} p 2
sqr
w ${1}/${1}${day}_${2}_bp${3}-${4}_sqr.s
q
EOF
done
```
1.1(易) ベン図書く

## 方針
事象AとBの対象差とは，一言で言うと「AとBの積集合でない部分」であり，次式で定義される．

```math
\begin{align}
A\Delta B=(A\backslash B)\cup(B\backslash A)
\end{align}
```
従って「和集合から積集合を抜いた部分」であることもすぐに分かる．あとは同値変形によって題意を証明する．

## 答案

```math
\begin{align}
P[A\Delta B]&=P[(A\cup B)\backslash(A\cap B)]\\
&=P[A\cup B]-P[A\cap B]\\
&=P[A]+P[B]-2P[A\cap B]
\end{align}
```

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
CentOSにApacheTomcatをインストールする

本ページではCentOSにApacheTomcatをインストールする手順についてまとめていきます。


#前提条件

ゲストOS：CentOS8
ApacheTomcat8.5をインストールします。

#手順

###Tomcat8.5のインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1620534/dc2cffdb-b52a-76a0-bbda-7034be80c91b.png)
ApacheTomcat本家のサイトからミラーサイトがいろいろあるので、各種~/tomcat-8/*version番号*などでcurlコマンドでダウンロードできそうです。
####ダウンロード・解凍

```
//opt配下にダウンロードします
cd opt
sudo curl -O https://ftp.jaist.ac.jp/pub/apache/tomcat/tomcat-8/v8.5.68/bin/apache-tomcat-8.5.68.tar.gz
```
curl のオプションは-O(オー大文字)にしました。

解凍

```
tar zxvf apache-tomcat-8.5.68.tar.gz
ln -s /opt/apache-tomcat-8.5.68 /opt/tomcat
```
権限

```
chown -R tomcat:tomcat /opt/tomcat/
chown -h tomcat:tomcat /opt/tomcat
```
削除しておきました 

```
sudo rm -f /opt/apache-tomcat-8.5.68
```

###Tomcatサービス化
OS上でサービス化し、簡単に起動等を行うために定義ファイルを作成します。

環境変数の設定です。

```
sudo vi /etc/sysconfig/tomcat
```
内容は以下のように

```
JAVA_HOME="/usr/lib/jvm/jre"
CATALINA_HOME="/opt/tomcat"
CATALINA_BASE="/opt/tomcat"
CATALINA_OPTS="-server -Xmx128m -Xms128m -XX:MaxMetaspaceSize=128m"
```

```
vi /etc/systemd/system/tomcat.service
```
ファイル定義内容は以下のように

```
[Unit]
Description=Apache Tomcat 8
After=network.target

[Service]
User=tomcat
Group=tomcat
Type=oneshot
PIDFile=/opt/apache-tomcat-8.0.50/tomcat.pid
RemainAfterExit=yes

ExecStart=/opt/apache-tomcat-8.0.50/bin/startup.sh
ExecStop=/opt/apache-tomcat-8.0.50/bin/shutdown.sh
ExecReStart=/opt/apache-tomcat-8.0.50/bin/shutdown.sh;/opt/apache-tomcat-8.0.50/bin/startup.sh

[Install]
WantedBy=multi-user.target
```

権限変更

```
chmod 755 /etc/systemd/system/tomcat.service
```

サービス有効化

```
systemctl enable tomcat
```

#ファイアウォールの設定

設定ファイルの変更

```
sudo vi /etc/firewalld/services/tomcat.xml
```
内容は以下のように

```
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>Apache Tomcat 8</short>
  <description>Apache Tomcat 8</description>
  <port protocol="tcp" port="8080"/>
</service>
```


```
firewall-cmd --list-services --zone=public --permanent
```

```
firewall-cmd --add-service=tomcat --zone=public --permanent
firewall-cmd --reload
```


#参考文献
Tomcat 9.0のインストール・設定・Webアプリケーションデプロイ (CentOS 8)
https://densan-hoshigumi.com/server/tomcat9-installation-centos8

Apache Tomcat 8 を CentOS 7 にインストールする手順
https://weblabo.oscasierra.net/installing-tomcat8-centos7-1/
VSCode+VimバインディングでEsc2度押しキーマップ

## 概要と目的

VSCode＋Vimエステンション(vscodevim)で利用しています。

https://marketplace.visualstudio.com/items?itemName=vscodevim.vim

Vimをターミナル利用する際は、検索文字列をハイライト、ESC2度押しでハイライト解除するように設定しています。

```vim:.vimrc
set hlsearch
nmap <Esc><Esc> :nohlsearch<CR><Esc>
```

VSCodeで同じキーマップにする方法がわからず、仕方なくイチイチ `:nohl` としていたのですが、設定方法がわかったのでメモします。

## 環境

- Windows10
- WSL2
- Ubuntu 20.04.2 LTS
- Visual Studio Code 1.57.1
- vscodevim 1.21.4

## 設定

Ubuntu上のホームディレクトリへ `.vimrc.vscode` を下記内容で作成します。

```vim:/home/user/.vimrc.vscode
nmap <Esc><Esc> :nohlsearch<CR><Esc>
```

Ubuntu on WSL上で、Windowsから上記ファイルを参照するためのパスを取得します
最後の `\\wsl$\<ubuntuへのパス>\home\user` 部分を控えます

```
$ pwd
/home/user
$ wslpath -w .
\\wsl$\<ubuntuへのパス>\home\user
```

VSCodeの設定へ下記記述します。
パス部分は バックスラッシュ`\` を2重に表記します（エスケープのため。見づらいですが）
パス末尾へ上記設定した `.vimrc.vscode` を記述し、ファイルを示すパスにします

```json:settings.json
{...
    "vim.vimrc.enable": true,
    "vim.vimrc.path": "\\\\wsl$\\<ubuntuへのパス>\\home\\user\\.vimrc.vscode"
}
```

以上でESC 2度押しで:nohlsearch が動作します。

## アレンジ

### ターミナルで利用している `.vimrc` をそのまま使う

普段ターミナルでvimの設定している人はこれでもいいかもしれません。
私はそれでも動作しています。が、vscodevimの vimrc読み込み機能がどこまで読み込むのか把握しておらず、安全そうな分離する方法を紹介しました。

### 設定ファイルをWindows管理下のディレクトリへ配置する

WSL使っていない場合は普通のディレクトリへ設定ファイルを配置しても大丈夫です。むしろそっちが普通かもしれません。
`c:\\Users\\user\\Desktop\\vimrc` とか
[ruby on rails]コメント機能の非同期通信

<h2>初めに</h2>
プログラミン初めて１ヶ月と少しですのでご注意ください。。


<h2>コメントの非同期通信</h2>

まず、いいねはこちらの記事を参考にすんなりできました！

https://qiita.com/rised/items/6483257e61724480e5bc

コメントも同様に〜と思ったのですが、案外つまづいたのでまとめます。
大体は、いいね　と同じなので違うところだけ記載してこうと思います。

![スクリーンショット 2021-07-06 10.41.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/63592bb4-dfea-db74-272d-42b27e1dc9c5.png)


<h2>まずやったこと　　
「いいね」の知識でいける部分</h2>
①コメント部分の部分テンプレート化する。
②本のshowページから、renderさせる。

```perl:books/show.html.erb
<div id="comments-area"><%= render "book_comments/comment",books: @books,book_comment: @book_comment %></div>
```
非同期通信の時は、idをつけてあげる。（idでなくてもcss記述するときみたいな識別できる何か）

③viewのbook_commentsフォルダ内にアクション名と同じjsファイル作成する。
![スクリーンショット 2021-07-06 10.47.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/b00bc767-9616-cbd1-4d4a-16427c93a37c.png)

④jsファイルの中身記述。

```perl:books/create.js.erb
$("#comments-area").html("<%= j(render 'book_comments/comment', books: @books,book_comment: @book_comment) %>")
```
comments-areaは、booksのshowページで指定したidを持ってきています。

⑤book_commentsコントローラー内のrenderやらredirect　toは消す。
これで、jsファイルを探してくれるようになる。

⑥コメント削除する"Destroy"の<%= link_to のところに、remote: trueを追記します！！これ忘れずに！！

```perl:_comment.html.erb
<td><%= link_to "Destroy", book_book_comment_path(book_comment.book, book_comment), method: :delete,remote: true,class:"btn btn-danger" %></td>
```

<h2>form_withを非同期通信に</h2>
⑦form_withのlocal trueを消す。

local true消すか、remote true追記するかで、非同期通信になるようです。

```perl:_comment.html.erb
<%= form_with(model:[books, book_comment], remote: true) do |f| %>
  <%= f.text_area :comment, rows:'5',placeholder: "コメントをここに",class:"form-control" %>
  <%= f.submit "送信する" %>
 <% end %>
```

<h2>ここから・・・つまずき　始める</h2>

```perl:books/create.js.erb
$("#comments-area").html("<%= j(render 'book_comments/comment', books: @books,book_comment: @book_comment) %>")
```
create.js.erbで@books @book_commentをわたしているので、book_commentsコントローラーでこの値を定義しないといけないんですよね・・・。

現状・・・

```
def create
   book = Book.find(params[:book_id])
   comment = current_user.book_comments.new(book_comment_params)
   comment.book_id = book.id
   comment.save
end

  def destroy
    BookComment.find_by(id: params[:id], book_id: params[:book_id]).destroy
  end
:
:
```

こうする！

```
class BookCommentsController < ApplicationController

def create
   book = Book.find(params[:book_id])
   comment = current_user.book_comments.new(book_comment_params)
   comment.book_id = book.id
   comment.save
   @books=Book.find(params[:book_id])
   @book_comment = BookComment.new
end

 def destroy
  @books=Book.find(params[:book_id])
  @book_comment=BookComment.find_by(id: params[:id], book_id: params[:book_id])
  @book_comment.destroy
  @book_comment = BookComment.new
  end

  private

  def book_comment_params
    params.require(:book_comment).permit(:comment)
  end
end
```

何を渡せばいいんだと思ってしまったんですが、そもそもbooksのshowページから、
renderしてるので、同じ値渡せばいいだけ　なんですよね。なのでコピペしました。
destroyあくしょんで@book_comment = BookComment.newとしてるのは、投稿が残らないようにするためです。

```perl:books_controller.rb
def show
    @books=Book.find(params[:id])
    @book=Book.new
    @book_comment = BookComment.new
  end
```

<h2>終わり</h2>
jsファイルに渡す値が間違っていたりすると、うまくいきませんので、要注意！！
【toio.js】Windowsでexampleを動かしたときに出たエラーの対処法

#エラー内容
　[toio.js](https://github.com/toio/toio.js/)のサンプルコードを動かしてみようとしたところ、id-readerとchaseは問題なく動いたが、keyboard-controlだけ動かない。

```:git_bash
$ yarn example:keyboard-control
yarn run v1.22.10
$ node examples/keyboard-control
noble warning: unknown handle 69 disconnected!
(node:11800) UnhandledPromiseRejectionWarning: TypeError: process.stdin.setRawMode is not a function
    at main (C:\toio.js\examples\keyboard-control\index.js:49:17)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:11800) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:11800) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
```

#対処法
　git bashではなくコマンドプロンプトで動かしたらキーボードでtoioを動かすことができた。

```:コマンドプロンプト
yarn example:keyboard-control
yarn run v1.22.10
$ node examples/keyboard-control
```
音声ファイルを Youtube にアップロード出来るように変換する

# 本来は音声ノミで配信が想定されちょらん

音声ファイルだけでは現在の [YouTube](https://youtube.com) には登録できんけ、ダミーの動画をでっち上げる必要がある。
一枚の静止画像から YouTube にアップロードしよるには、[ffmpeg](https://ffmpeg.org) を用いて静止画像の動画素材を生成しよって、音声ファイルと結合させて動画ファイルとして、生成させる必要がある。

# 用意する物
静止画像一枚と音声ファイル。
あ、ffmpeg の実行ファイルw

# 例
```shell:ffmpeg mp4版
ffmpeg \
	-loop 1 \
	-i fm816-top01.jpeg \
	-i "みのべありさのPOP ROCK RADIO_20210703_JOZZ7BL-FM.m4a" \
	-vcodec libx264 \
	-acodec copy \
	-r 24000/1001 \
	-b:v 64k \
	-metadata title="みのべありさのPOP ROCK RADIO 20210703放送分" \
	-metadata:s:1 language=JPN \
	-shortest \
	-y \
	"みのべありさのPOP ROCK RADIO 20210703 JOZZ7BL-FM.mkv"
```
# 例2
```shell:ffmpeg vp9版
ffmpeg \
	-loop 1 \
	-i "20241108 みなと元町 みなと亭.jpeg" \
	-i "mm_20241108 みなと 元町 みなと亭.wav" \
	-vcodec libvpx-vp9 \
	-acodec libvorbis \
	-r 1 \
	-ab 48k \
	-metadata title="みなと 元町 みなと亭 20241108放送分" \
	-metadata:s:1 language=JPN \
	-shortest \
	-y \
	"20241108 みなと元町 みなと亭.mkv"
```
# 蘊蓄?
ffmpeg のスイッチ順列に注意が必要で、静止画像ファイルの前に繰り返し指定が必須で、間違えよると変換が出来ん。
生成しよる動画のコーデックは[ここ](https://bit.ly/2SN0PBG)に記載しちょる型式で生成させちゃる。

静止画像じゃけ、ビットレートは低めに設定する方がアップロード時の負荷が少なくて良いのじゃが、画質が劣化するのけ適宜納得のいく帯域幅で生成すること。

必要であればメタデータを付記して最終的なファイルを生成し完了。

# 今回の例で記述している ffmpeg のスイッチ説明
<dl>
<dt>-loop 1</dt>
<dd>このスイッチの次に指定する静止画ファイルを動画変換する際の変換動作を指定する。</dd>
<dt>-i 入力ファイルネームの指定</dt>
<dd>半角スペースが途中で入る場合や全角文字が入る場合にはダブルクォーテーションで圍う</dd>
<dt>-vcodec libx264</dt>
<dt>-vcodec libvpx-vp9</dt>
<dd>生成する動画の圧縮コーデックの指定で、ffmpeg で使える物で先に記述しているコーデックを指定する。</dd>
<dt>-acodec copy</dt>
<dt>-acodec libvorbis</dt>
<dd>生成する音声の圧縮コーデックの指定で、ffmpeg で使える物で先に記述しているコーデックを指定する。</dd>
<dd> copy を指定すると入力ファイルのコードを再エンコードせずに出力する<dd>
<dt>-r 24000/1001</dt>
<dt>-r 1</dt>
<dd>動画のフレームレートの指定で、24 毎/秒以下だと正しくアップロード完了しない模様なので、24 毎/秒が適当。</dd>
<dd>1 毎/秒でも昨今では受け付けてくれる。</dd>
<dt>-b:v 64k</dt>
<dd>動画の転送レートの指定。</dd>
<dt>-b:a 48k</dt>
<dd>音声の転送レートの指定。</dd>
<dt>-metadata title="みのべありさのPOP ROCK RADIO 20210703放送分"</dt>
<dd>直接 Youtube には影響しないが、生成したファイルを再生ソフトを用いる時に、表題を表示させたい時や整理の際に必要であれば追記する。</dd>
<dt>-metadata:s:1 language=JPN<dt>
<dd>上記同様じゃが、生成しよるファイルの全体では無く、音声ファイルの対してノミ指定しよる際にスイッチの後方に<strong>コロン 「:」</strong>で区切っちゃって、どのストリームに対してなのかを更にコロンで区切っちゃって記述する。</dd>
<dt>-shortest</dt>
<dd>変換生成時に初めに変換が終わった時間に合わせて変換を終了させる。
これを指定しないと -loop 1 で永遠生成の指定をしちょるのけ、変換が終わらなくなるのを防ぐために必ず記述する。</dd>
<dt>-y</dt>
<dd>出力ファイルが存在しよる場合、返還前に上書きしよるか問い合わせられるのじゃが、無視して強制上書きしよるときに用いる。</dd>
</dl>

# 最後に
自分で変換生成する際に、いつも Google 先生にお世話になっちょるが、欲しい答えを教えてくれん時が多かったけ、忘備録として纏めてみよった。
mapやら、filterやら、reduceやらややこしいぜ！！

初学者のJSメモ、、

`javascript`でよく見る `map`,`filter`,`reduce`関数。
これらはリスト反復処理をしてくれるライブラリ関数である。


map
--
通常の書き方であれば、

```javascript
const array1 = [1,2,3]
const array2 = array.map(x=>2*x)
console.log(array2)→[2,4,6]
```

ラムダ関数Ver

```javascript
function realMap(f,list) {
 let answer = [];
   for(let i = 0; i < list.length; i++) answer.push(f(list[i]));
   return answer;
}
console.log(realMap(function(){x=>x*2},array1)→[2,4,6]
```

こんな感じです。

filter
--
通常の書き方

```javascript
let list1 = [1,2,3,4,5,6,7,8,9,10]
console.log(list1.filter(x=>x%2!==0));→[2,4,6,8,10]
```

ラムダ関数Ver

```javascript
function realFilter(f, list){
   let answer = [];
   for(let i = 0; i < list.length; i++){
       if(f(list[i]) === true) answer.push(list[i]);
   }
   return answer;
}
 
console.log(realFilter(x=>x%2!==0, list1));→[2,4,6,8,10]
```

reduce
---
通常Ver

```javascript
let list1 = [1,2,3];
console.log(list1.reduce((total,x)=>total*x));→６
```

ラムダVer

```javascript
function realReduce(callback, list, start){
  let answer = start;
  for(let i = 0; i < list.length; i++){
      let result = callback(list[i], answer);
      answer = result;
  }
  return answer;
}
console.log(realReduce((x,total)=>x*total, list1, 1));
```

前回の記事と合わせれば理解が深まるはず、、、
enebularでherokupostgres その6

#概要

enebularでherokupostgresに繋いでみた。
api、テストしてみた。

#参考にしたページ

https://qiita.com/naoqoo2/items/4ecfe2d0922215850965

#html側

フォームをjsonにして、jqueryのajaxでpostする。


#enebular側


postで受けて、そのデータをjsonヘッダー付けて、返す。


#成果物

https://embed.plnkr.co/plunk/ZOPTKjXfSxYRac8D

以上。
【CSS】親要素を超えて画面幅いっぱいまで子要素を表示する方法

# 概要

子要素にmarginを指定することで画面幅最大で表示ができる

## 前提

親要素がmargin: 0 auto;などで画面中央寄せとなっていること
※親要素の中央を起点としてmarginを取るため、子要素の表示が範囲がおかしくなる(子要素のmarginをいじってみるとわかる)

## サンプルコード

```html

<div class="parent">
  <div class="child"></div>
</div>

<style>
.parent {
  border: 1px dotted blue;
  height: 300px;
  margin: 0 auto; /* 前提 */
  width: 1000px;
}

.child {
  border: 1px solid red;
  height: 300px;
  margin: 0 calc(50% - 50vw); /* 画面幅いっぱいに表示 */
}
</style>

```
Git操作　備忘録

以前使用しましたが、忘れそうだったので記事を書きます
自分用なので間違っている可能性があります　実際に使用する際は調べてから使用してください

### git add -u
以前のcommitで追加されたファイルであり、かつ今回更新されたファイルのみがステージングされる

### git restore [filename] 
特定のファイルを以前のcommitの状態に戻す 
``` git restore . ```　だとカレントディレクトリが全部戻る

-s オプションをつけてコミット番号を指定するとそのバージョンに戻せる

### git reset [—soft|—mixed|—hard] [commitの指定]
[commitの指定]フィールドで指定された段階のcommitを取り消す
—soft commitを取り消す
—mixed addとcommitを取り消す
—hard addとcommitを取り消してファイルの中身も巻き戻す

[commitの指定]フィールドの記法
HEADに加えて^を巻き戻したいcommitの数だけ

Ex) ２つ前のcommitに巻き戻したいけど、ファイルは巻き戻さない場合
Git reset —mixed HEAD^^
CentOS8にMySQLインストール

本ページではCentOS8にMySQLインストールする手順についてまとめていきます。


#前提条件
ゲストOS:CentOS8
MySQL8.1をインストールしてきます。


#手順
###MySQLダウンロード
以下の公式サイトからダウンロードしたいバージョンを確認します。
https://dev.mysql.com/downloads/repo/yum/
![mysqlv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1620534/b80e8d32-77ea-5457-2a2c-60c35c5c7061.png)

*http://dev.mysql.com/get/*以降に**該当バージョン**の上記サイトの赤枠の部分を入力してインストールします。
mysql__の番号がMySQLのバージョン、
el_-_の番号がLinuxのバージョンのようです。

```
sudo yum install http://dev.mysql.com/get/mysql80-community-release-el8-1.noarch.rpm
```

###MySQLServerインストール

```
sudo yum　-y install mysql-server
```
mysql-community-serverは一致するものがありませんでした。上記のもので良さそうです。
名称が変わっているようでした。
参照：第10回　yum, rpmインストールにおけるMySQL 5.6とMySQL 5.7の違いhttps://gihyo.jp/dev/serial/01/mysql-road-construction-news/0010

以下で確認できました。

```
mysqld --version
```

###起動
```
systemctl enable mysqld　//サービス有効化
systemctl start mysqld
```


###初回設定

```
mysqld  --initialize-insecure
mysql_secure_installation
```

いろいろ質問されるので答えていきます。
・PASSWORDのセットアップ→y
・パスワードのセキュリティ強度→環境にあった数字を入力
　LOW 0,MEDIUM 1,STRONG 2
・新しいパスワードの入力(2回)、パスワードの強度が表示される
・匿名ユーザーを削除するか？→y(不要なので)
・rootユーザーでリモートログインを許可しないか→許可しないのでy
・テストDBと接続が不要,削除するか→y
・上記設定を上書きするか→y

###他のユーザー作成

rootユーザーでログインする

```
mysql -u root -p
```
使用したいユーザー名と(ホスト名,)パスワードでユーザーを作成します

```
mysql> CREATE USER ユーザー名@localhost IDENTIFIED BY 'パスワード';
```
変更反映

```
mysql> flush privileges;
```
上記create userも小文字でも大丈夫です。



#FAQトラブルシューティング
###MySQLの設定を他のサイトを参考にしてもできない
MySQL8は他のバージョンとは違うようです。
上記のように設定する必要があるようでした。

従来は以下のようにパスワード設定ファイルで確認などが必要だったようです。

```
sudo cat /var/log/mysql/mysqld.log | grep root
```
私の場合は上記の場所にありました。log配下にある場合もあるようです。
findコマンドで探してみるのも良さそうです。 
>sudo find -name mysqld.log

###パスワード設定がうまくいかない
####rootパスワード設定は上記の質問の中で設定できたが、他のユーザーの設定がうまくいかない
質問の中でセキュリティレベルの低いパスワード設定にしても、他のユーザーのパスワードには適用されないようでした。
**8文字以上かつ英大文字・小文字・数字・記号**を含める必要があるようです。
Box カスタムアプリでサーバー認証（クライアント資格情報許可）を使う

とりあえずサービスアカウントで実行する場合は、そのままアプリを作るだけでOK

1. アプリの新規作成
2. カスタムアプリ
3. サーバー認証（クライアント資格情報許可）

![Client Credentials Grant.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84947/0dc33408-88f5-319b-966a-cc93007d40bd.png)

クライアントシークレットを取得します。
クライアントシークレットの取得には 2要素認証を有効にする必要があるので注意。

忘れないように管理者に「承認」を依頼します。

![approve.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84947/5060a530-d989-0ab4-a7c1-378c2cc95de1.png)
approve.png

承認されてないと invalid_grant になるので必須です。

```
{"error":"invalid_grant","error_description":"Grant credentials are invalid"}
```

この辺は JWT と一緒です。

以上で準備完了。

サービスアカウントとして実行する場合は下記のような感じでリクエストすると access_token が返却されるので、それを使って API を実行します。

```
curl --location --request POST 'https://api.box.com/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=<client_id>' \
--data-urlencode 'client_secret=<client_secret>' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'box_subject_type=enterprise' \
--data-urlencode 'box_subject_id=<enterprise_id>'
```

本家だと、この辺りのドキュメントに書いてあります。

https://ja.developer.box.com/guides/authentication/jwt/without-sdk/#%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%E8%B3%87%E6%A0%BC%E6%83%85%E5%A0%B1%E8%A8%B1%E5%8F%AF

Box で使えるサーバー認証だと JWT も有りますが、JSONファイル読み込んで実行するとか、ちょっと面倒だったりします。

クライアント資格情報許可を使うとクライアントIDとクライアントシークレットだけで実行できるので楽です。
Flutter:  android studioのバージョンが1.12未満に作られたプロジェクトのビルド時に起きるエラーの対処法

#開発環境
`Flutter doctor`

```
[✓] Flutter (Channel master, 2.3.0-17.0.pre.366, on macOS 11.4 20F71 darwin-x64, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.2)
[✓] VS Code (version 1.47.3)
[✓] Connected device (1 available)

```

#発生した問題
Flutterの学習時、教材に記載してあるURL先のGitHubからローカル環境にレポジトリをクローンした際、`flutter pub get`を実行した時に以下のエラーがでた。

```
/Users/'UserName'/flutter_dev/flutter/bin/flutter --no-color pub get
Running "flutter pub get" in `Project Name`...                   3.6s
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Warning
──────────────────────────────────────────────────────────────────────────────
Your Flutter application is created using an older version of the Android
embedding. It's being deprecated in favor of Android embedding v2. Follow the
steps at

https://flutter.dev/go/android-project-migration

to migrate your project.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

```

1.12未満のバージョンで作成されたプロジェクトの一部の処理が非推奨となったため、URLの記事を参考にしなさい、というもの。
https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects

#対処法
##1.MainActivityのファイルを更新する
ファイルの場所: `android/app/src/main/java(or Kotlin)/[プロジェクトの名前]/MainActivity.java(or Kt)`

先頭に-がついている行を削除。
+の行を追加。

```MainActivity.java
-import android.os.Bundle;
-import io.flutter.app.FlutterActivity;
+import io.flutter.embedding.android.FlutterActivity;
-import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {
-  @Override
-  protected void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-    GeneratedPluginRegistrant.registerWith(this);
-  }
 }

```

```MainActivity.kt
-import android.os.Bundle
-import io.flutter.app.FlutterActivity
+import io.flutter.embedding.android.FlutterActivity
-import io.flutter.plugins.GeneratedPluginRegistrant

class MainActivity: FlutterActivity() {
-  override fun onCreate(savedInstanceState: Bundle?) {
-    super.onCreate(savedInstanceState)
-    GeneratedPluginRegistrant.registerWith(this)
-  }
}

```
以前はコードからプラグインを登録していたが、新バージョンでは自動で登録してくれるため、その処理が不要とのこと。
##2.マニフェストファイルを更新。
ファイルの場所: `android/app/src/main/AndroidManifest.xml`

###2-1applicationのnameタグを削除
```
<application
  android:name="io.flutter.app.FlutterApplication" この行を削除
  >
  <!-- code omitted -->
</application>
```
###2-2meta-dataのタグの値を更新
二つの値をそれぞれ変更する。

```
<meta-data
    android:name="flutterEmbedding"
    android:value="2" />
```
#解決
再度`flutter pub get`を実行すると、、、

```
/Users/`username`/flutter_dev/flutter/bin/flutter --no-color pub get
Running "flutter pub get" in `Project Name`...                1,029ms
Process finished with exit code 0
```

#注意点
自作したプラグインを使う場合は記事の項目1b. If you had existing custom platform 〜を参照してください。

スプラッシュ画面を実装する場合は、記事の項目4. Update splash screen behavior (if splash behavior is desired).を参照してください。

私の場合は外部のサンプルを試したいだけなのでノータッチです。
(必要時に更新するかも。。)
CentOS カーネルパッチ適用の仕方(1/2)

CentOSのカーネルはRPM形式で配布されています。RPM形式のファイルに対して、パッチを当てるためには、リビルドをする環境が必要になります。リビルドをするには、SRPM(source RPM）をダウンロードする必要があります。


###1.対象のバージョンのkernerl RPMのSRPMをダウンロード

```
dnf download --source kernel-4.18.0-305.3.1.el8
```

もし、dnfでダウンロード可能なrepositryに指定したバージョンが存在していない場合、以下のURLからダウンロードしてください。
https://vault.centos.org/8.4.2105/BaseOS/Source/SPackages/kernel-4.18.0-305.3.1.el8.src.rpm


###2.SRPMをインストール

```
rpm -ivh kernel-4.18.0-305.3.1.el8.src.rpm
```

SRPMをインストールすると、ソースファイルなどRPMビルド必要なデータが
`/root/rpmbuild` 配下にインストールされます。

###3.RPMをビルド

```
cd /root/rpmbuild/SPECS
rpmbuild -bb kernel.spec
```
ここでビルド依存性の失敗というエラーが出る場合があります。この場合、下記ページを参照してください。
[CentOS RPMパッケージビルド手順](https://qiita.com/start-action/items/642dfcc493b40cc1f065)

ビルドが完了すると、ビルドに使われたカーネルソースは、`/root/rpmbuild/BUILD` 以下に展開されています。そのカーネルソースに対して、パッチを適用していきます。


####続きは次回 [「CentOS カーネルパッチ適用の仕方(2/2)」](https://qiita.com/start-action/items/fa82c49c604eafeb2286)