OmniAICreator/Qiita-1.07M huggingface dataset:
【Rails】DBをリセットしてmigrateをやり直す方法

# はじめに
Railsで作成したアプリで、一番はじめに作ったモデルのテーブルが間違っていたことに気づいたため、DBをリセットしてmigrateをやり直しました。
以下の記事を参考にやり直すことができました。
参考　[Rails:migrateでDBをリセットして最初からつくり直す方法。](https://qiita.com/Atsushi_/items/a230fb7f624d1eebf2f3)
参考　[【Rails】$rails db:rollbackしたい時の間違えない手順](https://qiita.com/s_tatsuki/items/3e1f119c91e21b8f0c33)

#### 何が間違っていたのか
deviseでユーザー登録をさせる時に、生年月日のカラム型をstring型にしてしまっていた。このままでも登録は出来たが、生年月日の欄を入力した状態で他の部分のバリデーションに引っ掛かり、エラー文を表示させる画面に移った時に以下の表記。

```unix:ターミナルに表示されたエラー
ActionView::Template::Error (undefined method `day' for "{1=>1932, 2=>nil, 3=>nil}":String):
```

ページを遷移した時に、フォームに入っていた情報がdata型では無かったのでおかしいことになってしまった様子。（string型だと、ハッシュにして、それぞれの番号を年月日に当てはめていた？）

## 解決策
#### db:reset
カラム型を変更すると、既に登録されている生年月日のデータがおかしくなるかなと思って、まずはテーブルのデータを削除しようと思い、以下の記事を見つけた。
>①全てのレコードを空にしたい場合はrake db:resetを行う。
rake db:resetは全てのテーブルを dropし、"db/schema.rb"を元にテーブルの再作成を行います。

>②"db/migrate/" 以下の全ての migration を実行してテーブルを再作成したい場合は、rake db:migrate:reset
全てのテーブルを dropし"db/migrate/"以下の全ての migration を実行してテーブルを再作成を行うため、こちらの方が効力が強いかと思料されます。

migrationファイルを編集して②やればOKだなと思ったけど、なんか怖かったのでとりあえず①でDBをリセットすると無事に無事に、DB内のデータは全て削除されていた。

```unix:データベースをリセット
% rails db:reset

Dropped database 'database名_development'
Dropped database 'database名_test'
Created database 'database名_development'
Created database 'database名_test'
```
#### rollback

続いて、カラム型を変更するためにmigrationファイルを修正した。
`rails db:rollback`で良いのかなと思ってたけど、既にmigrationファイルが5つあったため、

```unix:指定箇所までrollbackする
% rails db:rollback STEP=(num)
# num個前のファイルまでrollbaｃｋできる
```
rollbackして、migrationファイルを修正して

```unix:migration
% rails db:migrate
```
一応確認すると無事に反映されていました。

```unix:ちゃんと反映されたかを確認
% rails db:migrate:status

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20200831104449  Devise create users
   up     20200902085108  Create items
   up     20200903070748  Create active storage tablesactive storage
   up     20200907074332  Create orders
   up     20200910081458  Create addresses
```
無事にカラム型も修正できてエラーも解決できました。
Chromium版のEdgeのDRM対応状況

Chromium版のEdgeがリリースされてだいぶ経ちました。
Windows 10以外でもEdgeが使えるならどの環境でもPlayReady使えるの？というとそうでもありません。

※今年の初めに確認した内容なので、最新版では対応状況が変わっている可能性がある旨ご了承ください

# 確認方法

Shaka Playerが公開しているMSE/EMEのサポート状況を取得するページを利用
https://shaka-player-demo.appspot.com/support.html

# 結果

|OS|Edge バージョン| PlayReady| Widevine|
|:--|:--|:--|:--|
|Windows 10 |80.0.361.9|〇|〇|
|Windows 8/8.1|79.0.309.54|×|〇|
|Windows 7 |79.0.309.54|×|〇|
|macOS 10.15 Catalina|79.0.309.54|×| 〇 |
|macOS 10.12 Sierra|79.0.309.54|×| 〇 |
|Android|42.0.4.4057|×| 〇 |
|iOS 10.0以降、 iPadOS 13以降|44.10.19|×|×|
YouTubeから動画をダウンロード（youtube-dl）

この方法はかなり安定して動画のダウンロードができます。動画ダウンロードサービスで四苦八苦するよりこちらがおすすめです。

コマンドラインで動作するためプログラムの機能として組み込むのも比較的容易です。


##youtube-dlとは
[youtube-dl](https://github.com/ytdl-org/youtube-dl) は、YouTube.com やその他のサイトから動画をダウンロードするための**コマンドライン**プログラムです。

Pythonインタプリタ、バージョン 2.6、 2.7、 3.2+ が必要で、プラットフォームに依存しません。UnixでもWindowsでもmacOSでも動作します。パブリックドメインに置かれているので、変更したり、再配布したり、好きなように使うことができます。

##youtube-dlの使い方
コマンドラインで使います。

```shell:書式
youtube-dl [OPTIONS] YouTube動画のURL [URL...]
```



```:使用例
$ youtube-dl https://www.youtube.com/watch?v=7wfUUZvybPY
[youtube] 7wfUUZvybPY: Downloading webpage
[download] Destination: How to Install YouTube-DL (Windows 10)-7wfUUZvybPY.mp4
[download] 100% of 14.28MiB in 00:09
```

###主なオプション

|オプション               |説明                                     |
|-----------------------|-----------------------------------------|
|-u, --username USERNAME|YouTubeのアカウント                        |
|-p, --password PASSWORD|アカウントのパスワード。省略すると対話的に入力   |
|-o, --output TEMPLATE  |出力ファイル名のテンプレート                  |
|-s, --simulate         |シミュレートするだけで実際にはダウンロードをしない|
|-t, --title            |出力ファイル名を動画タイトルにする             |
|-g, --get-url          |ダウンロードURLを表示する                    |


###アップデート
YouTubeに変更があるとyoutube-dlは使えなくなることがあります。その場合、アップデートする仕組みが用意されています。

```:youtube-dlの機能
sudo youtube-dl -U
```

上記でうまくいかない場合は、Windowsであればダウンロード、インストールのやり直し、Homebrew、pipは以下の方法でアップデートできます。

```shell:Homebrewの場合
brew update
brew upgrade youtube-dl
```

```shell:pipの場合
sudo pip install youtube_dl -U
````



##インストール

###Windows
Windowsユーザは、[.exeファイルをダウンロード](https://yt-dl.org/latest/youtube-dl.exe)し、`PATH`を通して使ってください。

###Mac
Homebrewでインストールすることができます。

```
brew install youtube-dl
```

もしくは、MacPortsでインストールすることができます。

```
sudo port install youtube-dl
```

###pip
pipを使うこともできます。
https://pypi.org/project/youtube_dl/

```
sudo -H pip install --upgrade youtube_dl
```

###Linux, MacOS, UNIX

curlを使う場合

```
sudo curl -L https://yt-dl.org/downloads/latest/youtube-dl -o /usr/local/bin/youtube-dl
sudo chmod a+rx /usr/local/bin/youtube-dl
```

wgetを使う場合

```
sudo wget https://yt-dl.org/downloads/latest/youtube-dl -O /usr/local/bin/youtube-dl
sudo chmod a+rx /usr/local/bin/youtube-dl
```


以上
Excelのメールリストを元にメールを送るコード

# なぜこんなものを？
業務（業務以外でも飲み会の出欠とか）で星取り表を作って、それに基づいてまだ未提出の人に催促を行うような、いわゆる雑務はかなりあります。そこでPythonで処理することにしました。ぶっちゃけMicrosoft Office365を使っているような企業ならAutomate Flowを使えばこんなのノーコードでできそうですが、身の回りで使える環境がないためちゃちゃっと用意しました。

## 参考にしたもの
* 退屈なことはPythonにやらせよう ―ノンプログラマーにもできる自動化処理プログラミング (2017/6/3）Al Sweigart(著), 相川 愛三 (翻訳)

## 用意するもの
下のような「maillist.xlsx」 というファイルを用意します。
![コメント 2020-09-11 144102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339767/603782de-4a69-1366-500e-44a3a796b8ab.png)

```Python:mail_send.py
import openpyxl, smtplib
from email import message

wb = openpyxl.load_workbook('maillist.xlsx')
sheet = wb.get_sheet_by_name('Sheet1')
lastCol = sheet.max_column
latest_month = sheet.cell(row=1, column=lastCol).value

# Excelファイルの確認
unpaid_Members = {}
for r in range(2,sheet.max_row + 1):
    payment = sheet.cell(row=r, column=lastCol).value
    if payment != 'paid':
        name = sheet.cell(row=r, column=1).value
        email = sheet.cell(row=r, column=2).value
        unpaid_Members[name] = email

# メールアカウントにログインする

smtp_host = 'smtp-mail.outlook.com'
smtp_port = 587
send_name = 'Master'
from_email ='master@outlook.jp'
username = 'master@outlook.jp'
password = 'password'

smtp_obj = smtplib.SMTP(smtp_host, smtp_port)
smtp_obj.ehlo()
smtp_obj.starttls()
smtp_obj.login(username,password)

# コマンドラインの画面でユーザにパスワードの入力を要求して
# 入力したいときにはsysパッケージをインポートして下のコードを実行。
# smtp_obj.login(username,sys.argv[1])

# メールを送信する
for name, email in unpaid_Members.items():
    msg = message.EmailMessage()
    msg.set_content("""
{}様
お疲れさまです。
まだ来週の歓迎会の参加費未払いのようです。
確認をお願いします。
    """.format(name))
    msg['From'] = '{}<{}>'.format(send_name, from_email)
    msg['Subject'] = '{}の支払い分に関しまして'.format(latest_month)    
    print('メールを送信しています {}...' .format(email))
    sendmail_Status = smtp_obj.sendmail(from_email, email, msg.as_string())
if sendmail_Status != {}:
    print('{}へメール送信中に問題が起こりました: {}'.format(email,sendmail_Status))
smtp_obj.quit()
```
## 使い方
後はこの.pyファイルを実行するだけです。タイムスケジュールを設定して実行することで毎日自動で飲み会の料金建替え徴収を未支払いの人に対して催促することができます。よいメールライフを。
javascript関数ドリル　初級編fill関数の実相のアウトプット

##fill関数の課題内容
詳細はこちら
　　　↓
https://js-drills.com/blog/fill/

##fill関数の取り組む前の状態
最後の

```jsonnet
console.log( fill([4, 6, 8, 10], '*', 1, 3) );
```
をどうすればいいのかわからづ悩んでいた状態

##fill関数に取り組んだ後の状態
難しくはなかったが発想が出てこないです。

##fill関数の実装コード（答えを見る前）
分かりませんでした。

##fill関数の実装コード（答えを見た後）

```js
function fill(array, value, start = 0, end = array.length) {
  for(let i = 0; i < array.length; i++) {
    if(start <= i && i < end) {
      array[i] = value;
    }
  }

  return array;
}

var array = [1, 2, 3];
console.log( fill(array, 'a') );
// => ['a', 'a', 'a']

console.log( fill(Array(3), 2) );
// => [2, 2, 2]

console.log( fill([4, 6, 8, 10], '*', 1, 3) );
// => [4, '*', '*', 10]
```
Maxでどの音を鳴らすかをマウスクリックで切り替える

#前の記事
[Maxで正弦波、短形波、三角波、ノコギリ波](https://qiita.com/waokitsune/items/4c588d0bdd5cdb6697bf)

#バージョン
Version 8.1.5（9359645）（64-bit windows）

#前回作ったやーつ
こんな感じで正弦波や短形波など、いろんな波を確認したよ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/828638a4-6628-2484-dff2-f8ffe1374800.png)
でもいちいちcycle~とかrect~とかキーボードで打ち込んで変更するのはめんどい…。
だから **マウスでクリックするたびに鳴らす音を切り替えられるやつが欲しい！** そう思ったのさ。


#出来上がったものがこちらになりまーす
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/fd1b0210-7d49-e8b3-4643-543e72be5f61.png)

**selector~** オブジェクトでどの音を鳴らすか切り替えます。
そして、selector~の選択を制御する為に **counter** オブジェクトを使いました。

#ちょっと気になるとこ
やりたいことはできたけど、こんなことをふと思った……
**cycle~を鳴らしている間もsaw~やrect~は音を出し続けてる。これってPCのリソースを無駄に使ってるんじゃない？**
（というか **音を出し続けてる** ってとこも本当にそうか検証する必要あるかも）

この辺は残課題ですなー(๑•﹏•)

#次の記事
[MaxでMIDIキーボードを使ってドレミファ](https://qiita.com/waokitsune/items/bcac5e247350877192b8)
ECRへの手動push方法メモ

## 動機
CircleCIで設定されてたのでECRへの手動pushは必要なかったけど、
CircleCIがイカれてしまったので、手動pushすることにした。


## ログイン認証

```
$ aws ecr get-login-password --region [リージョン] | docker login --username AWS --password-stdin [AWSアカウントID].dkr.ecr.[リージョン].amazonaws.com  
```

## ビルド

```
docker build -t [ECRのリポジトリ名] .
```


## イメージにタグ付け

```
docker tag [ECRのリポジトリ名]:latest [AWSアカウントID].dkr.ecr.[リージョン].amazonaws.com/[ECRのリポジトリ名]:latest
```

## ECRへpush

```
docker push [AWSアカウントID].dkr.ecr.[リージョン].amazonaws.com/[ECRのリポジトリ名]:latest
```

ECSのタスク定義を更新する必要がある
新しいリビジョンの作成でリビジョンが1つ上がることだけ確認して、その他の設定はいじる必要なし

あとは古いタスクとかサービスとか消せば完成。
Windowsのbatで複合化暗号化GPGコマンドでどうしてもパスレーズをきかれてしまう時の対処

・前提条件
パワーシェルが使える環境
OS：Windows Server2008R2以降 or Windows7以降

・事象
Windows Server2012で、batを用いてGPGコマンドを実装したところ、あらゆる記事を参考にしても
必ずパスフレーズを聞かれてしまい、自動化できなかったのでその時の対処法をメモ

・対処法
bat内でパワーシェルコマンドを実行することでパスフレーズをきかれなくなった。
Powershell -command "cho [パスフレーズ] | gpg --batch --pinentry-mode loopback --passphrase-fd 0 --decrypt-files --no-secmem-warning [復号対象ファイルのフルパス]"
Docker Desktop for Mac で Kubernetesが起動しないとき

## 状況
以前までは起動していたんですが、ある日突然起動しなくなり、
ずっと`Kubernetes is starting...`でスタックしてしまっている状況。
再起動しても状況は変わらず。
しかも、この状態でpreferenceも固まっていて、開くことができない。

環境： Docker Desktop for Mac

## 対処法
issueに上がっていた中で対処法がありました。
https://github.com/docker/for-mac/issues/2990#issuecomment-544754304

注意：Kubernetesのcontextとか諸々は消えます :crying_cat_face: 

### 1. pkiと.kubeの中身を削除
以下のコマンドを叩き、該当のものを消します。

```bash
rm -rf ~/Library/Group\ Containers/group.com.docker/pki/
rm -rf ~/.kube
```
### 2. Reset Kubernetes cluster
`Troubleshoot` -> `Reset Kubernetes cluster` をクリック
![スクリーンショット 2020-09-11 14.04.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120491/ca3f19e3-d7b8-8ee3-0f81-9bad70f68d3e.png)

### 3. Restart
Docker Desktop for Macを再起動したら起動した。

## 補足
- `.kube`の方を消すのは嫌だったので、`pki`だけ消してみてやってみたけどだめだった。。。
- preferenceを開こうにも固まっていて開けない :anger: 
    - Docker Desktop for Macを再起動すると十秒程度preferenceを動かせるタイミングがあるので、そこで気合で開く :innocent:

何か他にもっといい方法があるよって方はご教授いただけると嬉しいです。
Kotlin公式でJSON文字列に変換


(2020/11/27編集)読みづらいので文章を修正

# プロフィール

Spring BootでJava初めて半年

-> Kotlinに引っ越して半月

# Kotlin公式JSONとは

KotlinでJSONを文字列に変換するデフォルト実装機能。

https://kotlinlang.org/docs/reference/serialization.html

build.gradle.ktには

```kotlin
plugins {
     kotlin("jvm") version "1.4.10"
     kotlin("plugin.serialization") version "1.4.10"
 }
```

と

```kotlin
dependencies {
     implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.0-RC")
 }
```

を追記する。

# クラス -> JSON文字列

そもそもJSONとは、**JavaScript Object Notation**、

すなわち名前(key)と値(value)の組み合わせがいっぱい入った構造を、JavaScriptのObjectのような書き方で表現した文字列。

```json
{
  "name": "hoge",
  "age": 1,
  "friends": [
    {
      "name": "fuga",
      "like": true
    },
    {
      "name": "piyo",
      "like": false
    }
  ]
}
```

JavaScriptならJavaScriptのObjectをJSONに変換するが、

Kotlinでは、データクラスをJSONに変換する。

例

```kotlin
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

@Serializable
class Person(
    val name: String,
    val age: Int,
    val firends: List<Friend>
)

@Serializable
class Friend(
    val name: String,
    val like: Boolean,
)

fun main() {
    val hoge = Person(
      "hoge",
      1,
      listOf(
        Friend("fuga",true),
        Friend("piyo",false)))
    println(Json.encodeToString(hoge))
}
```

出力結果

```text
{"name":"hoge","age":1,"firends":[{"name":"fuga","like":true},{"name":"piyo","like":false}]}
```

要点は、

- JSON化するクラスには、**@<wbr>Serializable**をつける
- クラスのプロパティ名(nameなど)が、変換後に**JSONのkey**となる
- Listも使える
- クラスの入れ子もできる

# 応用 (特定のプロパティをJSONに変換しない)

### デフォルト

デフォルトでは、全てのプロパティがJSONに変換されてしまうので、ちょっと困る。

先の例だと、friendsが**null**でも、そのままJSONに変換される。

```kotlin
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

@Serializable
class Person(
    val name: String,
    val age: Int,
    val firends: List<Friend>? = null // 変更箇所
)

@Serializable
class Friend(
    val name: String,
    val like: Boolean,
)

fun main() {
    val hoge = Person("hoge", 1) // 変更箇所
    println(Json.encodeToString(hoge))
}
```

出力結果

```text
{"name":"hoge","age":1,"firends":null}
```

### 特定のプロパティをJSONから消す

```kotlin
// クラスとインポートは同じ

val format = Json {encodeDefaults = false}

fun main() {
    val hoge = Person("hoge", 1)
    println(format.encodeToString(hoge)) // Jsonがformatに変わっている
}
```

出力結果

```text
{"name":"hoge","age":1}
```

最初の行の encodeDefaults = false は、デフォルト引数と同じ値のプロパティ(今回は friends = **null** )はJSONに変換しない、という意味。

### 明示的に代入した場合

デフォルト引数と同じ値のプロパティは全て弾かれるので、

```kotlin
// クラスとインポートは同じ

val format = Json {encodeDefaults = false}

fun main() {
    val hoge = Person("hoge", 1, null) // nullを明示的に代入
    println(format.encodeToString(hoge))
}
```

出力結果

```text
{"name":"hoge","age":1}
```

明示的にデフォルト引数と同じ値を代入しても弾かれる

# さらに学びたい人へ

英語のガイドがあります

https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serialization-guide.md
Macのカーソル拡大トグルAppleScript・SystemEvents経由


もっとすっきりしたやり方あるはずなんすよなぁ

activateを入れなければシステム環境設定が隠れたまま設定されていいみたいです。

```applescript
tell application "System Preferences"
	set current pane to pane "com.apple.preference.universalaccess"
	tell application "System Events"
		tell window 1 of process "System Preferences"
			repeat until scroll area 1 exists
			end repeat
			set selected of row 6 of table 1 of scroll area 1 to true
			set mySlider to slider 1 of group 1
			if value of mySlider > 1 then
				set myMSize to 1
			else
				set myMSize to 4
			end if
			set value of mySlider to myMSize as number
		end tell
	end tell
	quit
end tell
```
Adminerでoracleに繋げる

#Adminerとは
AdminerはPHPで動作するWebSQLクライアントです。
https://www.adminer.org/

同じ物に言わずとしれたphpMyAdminですが使えるのはMysqlだけ。
一方AdminerではmysqlのほかにPostgreSQL、SQLite、MS SQL、Oracleなど幅広く扱えます。

#oracle
本題です。
そんななかoracleに繋げる時だけログインフォームに癖がありこれが毎度忘れるので記事にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36304/c1f7ae75-f804-70fc-4751-f02379a4e1a8.png)


これはDockerでoracleDBをインストールした場合のデフォ情報の場合です。

Serverにはホスト名(TNS名)/サービス名の両方を/で仕切り、入力する必要があります。
User名はログインユーザ
Databaseはスキーマ名となります。

大文字小文字が区別されるので注意です。
Next.jsのDynamic RoutesでSPA遷移

# Issue
Next.jsのDynamic Routesを使っているページに対して普通に`next/link`の`<Link>`を使ってリンクを貼ると、遷移時にブラウザのロードが発生してしまってSPA遷移にならない。
最初、Next.jsじゃなくてReactの何かがおかしい？と思って軽くハマった。

```react

import Link from 'next/link'

// これだとブラウザロードが発生してしまう
<Link href={`/posts/${post.id}`}>リンク</Link>
```

# Solution
[ドキュメント](https://nextjs.org/docs/api-reference/next/link)を見ると、`next/link`の`<Link>`には`as`属性というのが用意されており、「ブラウザのURLバーでレンダリングされるパスを示すもので、Dynamic Routesで使ってください」と書いてある。
じゃあ`href`は何なのかと言うと、「`pages`ディレクトリの内部のパスです」とのこと。

要するに、例えばDynamic Routesで`pages/posts/[post-id].jsx`としている場合は下記のように書けば良いらしいです。

```react

import Link from 'next/link'

<Link href="/posts/[post-id]" as={`/posts/${post.id}`}>リンク</Link>

```

`as`の方に普段`href`に書いているような具体的なパスを書くんですね。何か違和感。。。
[CloudWatch]CloudWatchアラーム

知ったことまとめ

# 1. アラームの有効/無効
マネジメントコンソールからは有効/無効の状態は確認できるものの、設定はできないという仕様。

#### 1.1. 各アラームの有効/無効の確認

AWSマネジメントコンソールからできる。

アラームの一覧ページで右上歯車アイコンから。
「アクションが有効になっています」スイッチをONにすると一覧で確認できるようになる。

#### 1.2. 各アラームの有効/無効設定

aws-cliからしかできない・・・

```
# aws-cliのインストール(Mac)
brew install awscli

# awscliの設定(アクセスキーID、シークレットアクセスキー、リージョン、出力形式を設定)
aws configure
```

```
# アラームの状態確認
aws cloudwatch describe-alarms --alarm-name-prefix <アラーム名の接頭辞文字列(表示を絞り込みたいときに)> --query "MetricAlarms[].[AlarmName,AlarmDescription,ActionsEnabled]" --output table

# アラーム無効化
aws cloudwatch disable-alarm-actions --alarm-name <AlarmName>

# アラーム有効化
aws cloudwatch enable-alarm-actions --alarm-name <AlarmName>
```

# 2. アラームの追加(aws-cliから行う場合)

<>内にセットすべき値は、コンソールで確認できる項目名の値に相当

```
# アラーム追加(アラーム無効の状態)
# パラメータ詳細はhttps://docs.aws.amazon.com/cli/latest/reference/cloudwatch/put-metric-alarm.html
aws cloudwatch put-metric-alarm --alarm-name <アラーム名> --alarm-description "<アラームの説明>" --namespace <名前空間> --metric-name <メトリクス名> --dimensions Name=InstanceId,Value=<InstanceId> --statistic <統計(※)> --threshold <...よりも> --comparison-operator <XXXが次の時...(※)> --period <期間> --evaluation-periods <アラームを実行するデータポイント(分母)> --datapoints-to-alarm <アラームを実行するデータポイント(分子)> --treat-missing-data <欠落データの処理(※)> --alarm-actions <アラーム状態になったときのアクション(※)> --no-actions-enabled

# アラームを有効化
aws cloudwatch enable-alarm-actions --alarm-name <アラーム名>
```

※統計：以下の値から設定
- SampleCount
- Average
- Sum
- Minimum
- Maximum

※XXXが次の時...：以下の値から選択
- GreaterThanOrEqualToThreshold : >=
- GreaterThanThreshold : > 
- LessThanThreshold : < 
- LessThanOrEqualToThreshold : <= 

※期間：秒単位で指定
(例) 1時間→3600

※欠落データの処理
- breaching : 欠落データを不正(しきい値を超えている)として処理 
- notBreaching : 欠落データを適正(しきい値を超えていない)として処理
- ignore : 欠落データを無視(アラーム状態を維持する)として処理
- missing : 欠落データを見つかりませんとして処理

※アラーム状態になったときのアクション：
以下から選択

```
# EC2停止
arn:aws:automate:*region* :ec2:stop 

# EC2終了
arn:aws:automate:*region* :ec2:terminate

# EC2回復(多分停止 + 起動。つまりインスタンスの物理ホストが変わる)
arn:aws:automate:*region* :ec2:recover

# EC２再起動(インスタンスの物理ホストが変わらない)
arn:aws:automate:*region* :ec2:reboot

# メール配信
arn:aws:sns:region :account-id :sns-topic-name 

# ?
arn:aws:autoscaling:region :account-id :scalingPolicy:policy-id :autoScalingGroupName/group-friendly-name :policyName/policy-friendly-name

# ロールで実行するとき
# EC2停止
arn:aws:swf:*region* :*account-id* :action/actions/AWS_EC2.InstanceId.Stop/1.0

# EC2終了
 arn:aws:swf:*region* :*account-id*
:action/actions/AWS_EC2.InstanceId.Terminate/1.0

# EC2再起動
 arn:aws:swf:*region* :*account-id* :action/actions/AWS_EC2.InstanceId.Reboot/1.0
```

# 3. アラートメールの通知テスト

アラートメールの通知テストをしたいアラームについて、
その状態を無理やり手動で「アラーム」や「OK」の状態にして飛ばす。

参考https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/US_AlarmAtThresholdEC2.html

```
# 通知テスト対象アラームの状態確認
aws cloudwatch describe-alarms --alarm-name-prefix <アラーム名> --query "MetricAlarms[].[AlarmName,AlarmDescription,StateValue]" --output table

# 強制的に「OK」にする
aws cloudwatch set-alarm-state --alarm-name <アラーム名> --state-reason "alert mail test" --state-value OK

# 強制的に「アラーム」にする
aws cloudwatch set-alarm-state --alarm-name <アラーム名> --state-reason "alert mail test" --state-value ALARM
```
javascript関数ドリル　初級編dropRight関数の実相のアウトプット

##dropRight関数について
　　　↓
https://js-drills.com/blog/dropright/

##dropRight関数の取り組む前の状態
前のdropメソットの時とほとんど同じなんじゃないかと思っていた

dropRight関数に取り組んだ後の状態
array.length-sizeという発想がありませんでした

##dropRight関数の実装コード（答えを見る前）

```js
function dropRight(array, size = 1) {
  if (size === 0) {
    return [...array];
  }
  if (array.length <= size) {
    return [];
  }

  const droppdedArray = [];
  for(let i = 0; i < array.length; i++) {
    droppdedArray.push( array[i] );
  }

  return droppdedArray;
}

const numbers = [1, 2, 3];

const result1 = dropRight(numbers);
console.log(result1, numbers);
// // => [1, 2]

// dropRight(numbers, 2);
const result2 = dropRight(numbers, 2);
console.log(result2, numbers);
// // => [1]

const result3 = dropRight(numbers, 5);
console.log(result3, numbers);
// => []

const result4 = dropRight(numbers, 0);
console.log(result4, numbers);
// => [1, 2, 3]
```
zipObject関数の実装コード（答えを見た後）

```js
function dropRight(array, size = 1) {
  if (size === 0) {
    return [...array];
  }
  if (array.length <= size) {
    return [];
  }

  const droppdedArray = [];
  for(let i = 0; i < array.length - size; i++) {
    droppdedArray.push( array[i] );
  }

  return droppdedArray;
}

const numbers = [1, 2, 3];

const result1 = dropRight(numbers);
console.log(result1, numbers);
// // => [1, 2]

// dropRight(numbers, 2);
const result2 = dropRight(numbers, 2);
console.log(result2, numbers);
// // => [1]

const result3 = dropRight(numbers, 5);
console.log(result3, numbers);
// => []

const result4 = dropRight(numbers, 0);
console.log(result4, numbers);
// => [1, 2, 3]
```
az feedback で Azure CLI の実行結果をフィードバックする

# はじめに

Azure Portal には、サービスに対する改善要望やバグの報告をフィードバックするメニューがあります。基本的にはフリーフォーマットで内容を入力、送信する形になっています。
![20200911_cli_feedback_01_portal.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685288/1805eab7-1d02-1abb-daf5-7e559693ea2d.jpeg)

これとは別に、Azure CLI の実行結果や不具合をフィードバックする **az feedback** という仕組みがあります。今回はこちらをご紹介します。

## 実行環境

Azure CLI が動けば、環境は何でも構いません。今回は Azure Portal 上の Azure Cloud Shell(Bash)で実行します。

## 使い方

それでは、実際に使ってみます。まず、何か適当な az コマンドを実行します。以下では、例として`az synapse`コマンドを実行したところ、予期せぬエラーが発生しました。
![20200911_cli_feedback_02_bash.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685288/c9268899-97c2-ec74-c41d-bc3d3893bbac.jpeg)
エラーメッセージの後に、`To open an issue, please run: 'az feedback'`という文言が確認できます。
![20200911_cli_feedback_03_bash.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685288/56ad1d23-92f8-69b5-87fc-146f74452931.jpeg)
言われたとおりに、コマンドを実行してみます。
![20200911_cli_feedback_04_feedback.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685288/fa3d27dc-b61b-4631-e47e-410c4fd2f7f5.jpeg)
直近で実行したコマンドの履歴が表示されるので、エラーとなったものを選択すればフィードバックが送信されます。非常に簡単です。

## 良いと思うところ

ここまでお読みになられて、通常のフィードバックと何が違うのか？と疑問に思われた方もいらっしゃるかもしれません。これは私見となりますが、az feedback の良いところは**ユーザーオペレーションを意識してフィードバックを送信するまでの導線を敷いている**ことだと思います。

上述のとおり Azure Portal からのフィードバックはフリーフォーマットとなるため、対象となる Azure リソースや文章の内容を考える必要があります。また、状況によっては現在作業している画面から遷移してフィードバックを作成・送信するケースもあり得るため、フィードバックを送ろうと思うまでに少々モチベーションが要るように思われます。

それに対して、az feedback の場合は現在作業しているコンソール上で案内に従ってコマンドを入力送信するだけでものの数秒で実行できてしまうため、非常に気軽にフィードバックを行うことができます。これは、ユーザビリティが考慮された良い設計だなと感じました。

## まとめ

az feedback による Azure CLI 実行結果のフィードバックについてご紹介しました。Azure CLI の改善については GitHub の issue によるリクエストも受け付けているようなので、機会があればそちらも実施してみたいと思います。

## 参考 URL

[az feedback](https://docs.microsoft.com/en-us/cli/azure/reference-index?view=azure-cli-latest#az_feedback)
JavaScriptで数値から¥, $, €, £を付けた文字列を作る

JavaScriptで金額を表す文字列に通貨の記号やカンマで区切りをつけて表示するには`toLocaleString`を用いる


ref: toLocaleStringの仕様 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString

### 日本円の場合

```js
const price = 1234567890.1234
const jpy = price.toLocaleString('JP',
  { style: 'currency', currency: 'JPY' })

console.log(jpy)
// => ￥1,234,567,890
```

### 米ドルの場合

```js
const price = 1234567890.1234
const usd = price.toLocaleString('US',
  { style: 'currency', currency: 'USD',})

console.log(usd)
// => $1,234,567,890.12"
```

### ユーロの場合

```js
const price = 1234567890.1234
const eur = price.toLocaleString('DE',
  { style: 'currency', currency: 'EUR' })
console.log(eur)
//=> 1.234.567.890,12 €
```

### 英ポンドの場合

```js
const pond = price.toLocaleString('GB',
  { style: 'currency', currency: 'GBP',})
console.log(pond)
//=> "£1,234,567,890.12"
```
fluorite-7　日本語リファレンス　動的名前解決


[日本語チュートリアルトップ](https://qiita.com/MirrgieRiana/items/a0906c72ebfb46693ab5)

# 基礎

定数や変数などによって名前が静的に解決可能な場合、識別子はそれを表す。

```perl:
iden : 777;
iden, TYPE(iden)
```

```bash:
$ fl7 'iden : 777; iden, TYPE(iden)'
777
NUMBER
```

未定義の識別子を記述すると、同じ内容の文字列となる。

```perl:
iden, TYPE(iden)
```

```bash:
$ fl7 'iden, TYPE(iden)'
iden
STRING
```

未定義の識別子の挙動は`PATH`定数によって制御されているが、これを再定義することにより、未定義の識別子の挙動を変えられる。

```perl:
PATH : pass, name -> name * 5;
iden, TYPE(iden)
```

```bash:
$ fl7 'PATH : pass, name -> name * 5; iden, TYPE(iden)'
idenidenidenideniden
STRING
```

# `PATH`の呼び出し

未定義の識別子`name`を評価したとき、動的名前解決が行われる。
動的名前解決時には、名前解決失敗を表す値`pass`を生成し、静的名`PATH`で解決される値に対して、`PATH(pass; "name")`という関数呼び出しを試みる。
`PATH`が`pass`を返した場合、名前解決は失敗する。
`PATH`が`pass`以外の値を返した場合、それを以って名前解決は成功する。

```bash:
$ fl7 'PATH : pass, name -> name * 2; a'
aa
```

```bash:
$ fl7 'PATH : pass, name -> pass; a'
/usr/local/bin/fluorite-7/fluorite-7.js:14191
            throw new Error("Can not resolve: name = " + name);
            ^

Error: Can not resolve: name = a
≪省略≫
```

# マウント演算子

マウント演算子`@resolver`は、`resolver`によって動的名前解決ができるように変数`PATH`を再定義する前置演算子である。
マウント演算子の結合優先度はその他の前置演算子と等しい。

## 関数のマウント

マウント演算子に関数を与えた場合、関数`function`は動的名前解決時に`function(pass; name)`として呼び出される。
ここで、`pass`は名前解決が出来なかった場合に返す値で、`name`は解決すべき名前である。
`function`が`pass`を返した場合、マウント前の`PATH`に動的名前解決を委譲する。

```perl:
@(pass, name -> name * 5);
@(pass, name -> name === "pie" ? 3.14 : pass);
PI,  // 定義済みなので円周率が出る
pie, // 未定義かつpieなので3.14が出る
pi,  // 未定義かつpieではないので5回繰り返す
```

```bash:
$ fl7 '@(pass, name -> name * 5); @(pass, name -> name === "pie" ? 3.14 : pass); PI, pie, pi'
3.141592653589793
3.14
pipipipipi
```

## オブジェクトのマウント

マウント演算子にオブジェクトを与えた場合、解決したい名前でプロパティアクセスを試みる。
プロパティが存在しない場合、マウント前の`PATH`に動的名前解決を委譲する。

```perl:
@{
  a : 777;
};
a, // プロパティが存在するので777が出る
b, // プロパティが存在しないのでデフォルトの挙動になる
```

```bash:
$ fl7 '@{a : 777}; a, b'
777
b
```

## マウント演算子はスコープに縛られる

マウント演算子は変数宣言と同様の挙動を持っているため、スコープが終わるとその効果は終了する。

```perl:
(
  // ここでマウント
  @{
    a : 777;
  };

  // マウントした名前を参照
  a
),

// スコープが切れているので通常の挙動に戻った
a,
```

```bash:
$ fl7 '(@{a : 777}; a), a'
777
a
```

# `STRICT`関数

`STRICT`は、2個の引数を取り、常にエラーを投げる関数が格納された定数である。
これをマウントのリゾルバと解釈すると、どんな名前の解決を試みても常にエラーになる挙動になる。

プログラムの先頭で`@STRICT;`を行うと、結果的にそのスクリプト内では未定義の識別子が許されない状態になる。

```perl:
@STRICT;
iden
```

```bash:
$ fl7 '@STRICT; iden'
/usr/local/bin/fluorite-7/fluorite-7.js:15062
          throw new Error("No such alias: name=" + args[1]);
          ^

Error: No such alias: name=iden
≪省略≫
```

`@STRICT;`は飽くまで関数のマウントにすぎないため、`@STRICT;`の前に行ったマウントは無効になり、`@STRICT;`の後に行ったマウントは有効であり、スコープに縛られる。
【Azure】ZPAとAzureについて

　ZPAとAzureの相性はいいみたい　ADだけで管理ができればそれはメリットがある
　でも思うのはお客様の状況にどっちがフィットするかという部分
　ZPAを使うことでオンプレもゼロトラストで行ける

https://www.zscaler.jp/products/zpa-for-azure
【Ruby on Rails】model,controllerターミナルコマンド

# 概要
個人的によく使うmodelとcontrollerのコマンドをまとめてみました。
コピペして使えるよう「$」の記述はなくしています。
メモ程度なので説明は最小限にします。
適宜更新していきます。

# model、table

```:【作成】
rails g model Post user:references body:string genre:integer
```
```:【モデル、テーブルを削除】
rails destroy Post
```
```:【テーブルのみ削除】
rails g migration DropPosts
```
```:【テーブル名変更】
rails g migration RenamePostsToBooks
```

# カラム
```:【カラム追加】
rails g migration AddNameToPosts name:string price:integer
```
<details><summary>他にも追加したい時</summary>
migrationファイルに追加
add_column :posts, :body, :text</details>
<details><summary>index追加時</summary>
【単数】
add_index :posts, :body, :unique => true
【複数】
add_index :posts, [:body, :price], :unique => true</details>

```:【カラム削除】
rails g migration RemoveNameFromPosts name:string price:integer
```
```:【データ型変更】
rails g migration ChangeDataNameToPosts name:text
```
```:【null追加】
rails g migration change_column_null :posts, :body, false
```
```:【カラム名変更】
rails g migration RenamePriceColumnToPosts 
```
<details><summary>migrationファイルに追加</summary>
rename_column :posts, :price, :変更後のカラム名</details>





# migration
```:【実行】
rails db:migrate
```
```:【１つ前のバージョンに戻す】
rails db:rollback
```
```:【数字分前のバージョンに戻す】
rails db:rollback STEP=3
```
```:【データベースの情報をリセット】
rails db:reset
```
```:【データベースとmigrationをリセットし、再度migrateする】
rails db:migrate:reset
```
```:【migrationのバージョン確認】
rails db:migrate:status
```


# controller
```:【作成】shopはディレクトリを分けている場合使用。
rails g controller shop::posts new
```
```:【削除】
rails destroy controller shop::posts
```

# 開発環境
ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina
[ CSS ] fliter brightness の ie11 対策

CSSのプロパティfilterは対象をボカしたりグレースケールにしたりできるため、画像を加工する必要がなくなり、非常に便利です。

今回私は、良くある形のブログで記事が一覧に表示されるページにおいて、画像をバックグラウンドにしてその上にテキストを配置することから、画像に暗くfilterをかけ読みやすいようにしました。

```
.box{
  background-image:url('sample.jpg');
  background-size:cover;
  background-position:center;
}
.box:before{
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  filter: brightness(50%);
}
```

が、これではie11には反映されませんでした。

対策を探すべくググったところ、最初に出会ったのは[ライブラリCSS-Filters-Polyfill](https://github.com/Schepp/CSS-Filters-Polyfill)でした。しかし、「Not supported Browsers」に「IE 10+,」の文字が。

説明もありました。

>Why is IE 6 - 9 supported, but not IE 10 or higher? Well, since Microsoft decided to switch sides and to now follow standards, they killed their old proprietary filters beginning with IE 10 which I rely on for emulation.
>Altough they did introduce SVG filters sadly those are limited to a usage inside SVGs. They cannot be applied to HTML-elements.
>Even triggering legacy mode does not help any more. So this is why we are left at the end with no hook/support at all in IE10+ :(
>
>引用：https://github.com/Schepp/CSS-Filters-Polyfill

ということだったので、別をググり、stack overflow に辿り着いて、fliter brightness を辞めて、background hsla で対応しました。

```
.box:before{
  content: "";
  position: absolute; 
  display: block; 
  top: 0; right: 0; bottom: 0; left: 0;  
  background: hsla(0,0%,0%,0.4);
}
```

##参考URL
[[CSS3][JS] CSS の Filter Effects を IE でも使用できるようにするライブラリ CSS-Filters-Polyfill ｜ memocarilog](https://memocarilog.info/jquery/7726)
[Schepp/CSS-Filters-Polyfill: This polyfill takes the official CSS filters syntax and translates it to the different equivalent techniques that the browsers know for those effects](https://github.com/Schepp/CSS-Filters-Polyfill)
[html - Crossbrowser brightness filter over img using css - Stack Overflow](https://stackoverflow.com/questions/23276405/crossbrowser-brightness-filter-over-img-using-css)
PHP(Imagick)でイメージをマスクして切り取る

## 完成形

<img src="https://camo.qiitausercontent.com/6f9a594a1840feb08385a53186d19ad6daf9b1a6/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3730353933372f65346264353761352d333538302d333931382d346331342d6435623565376466633638312e706e67" alt="test.png" data-canonical-src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705937/e4bd57a5-3580-3918-4c14-d5b5e7dfc681.png" loading="lazy" width="20%">

画像の左右を斜めに切り取っています。


![mask223.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705937/703f18a0-e3b9-12ca-dec9-c61f6355bc74.png)

やりたいこととしては、上記の画像の赤枠で囲っている、２つの画像を合わせてその合わさっている場所を切り抜きたい。

## 元画像とマスク用画像の用意

元画像
<img src="https://camo.qiitausercontent.com/f1a8a98fa934e4448fd54082aa52520bbd107183/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3730353933372f36336539323235622d363833392d353339362d316437342d3836633561396131386264362e6a706567" alt="Zoe_0.jpg" data-canonical-src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705937/63e9225b-6839-5396-1d74-86c5a9a18bd6.jpeg" loading="lazy" width="20%">

マスク用の画像（同じサイズで左右の斜めを透過してあります。）
<img src="https://camo.qiitausercontent.com/798e27c89cd8a757c257640b9cb51d5e5fca52e5/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3730353933372f38323863396134342d346634382d303334362d643562332d3165313635316537303936652e706e67" alt="mask2.png" data-canonical-src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705937/828c9a44-4f48-0346-d5b3-1e1651e7096e.png" loading="lazy" width="20%">


##　実装

```php

    //元画像をURLから呼び出し
    $thumbnail = file_get_contents("http://ddragon.leagueoflegends.com/cdn/img/champion/loading/Zoe_0.jpg");
    $image = new Imagick();
    $image->readImageBlob($thumbnail);
    //アルファチャネルの設定で、黒い部分を透明にする。
    $image->setImageAlphaChannel(Imagick::ALPHACHANNEL_RESET);
    //マスク用の画像を取得
    $mask = new Imagick(storage_path("mask.png"));
    //元画像を重ね合わせてマスクする
    //COMPOSITE_DSTOUTにすると、重なっている部分が切り抜かれる
    $image->compositeImage($mask, Imagick::COMPOSITE_DSTIN, 0, 0);
    //保存
    $image->writeImage(storage_path("test.png"));
```

以上で簡単な実装です。

さらにこれに画像を重ね合わせたり、文字を入れたりするとOGP的な画像の動的生成などができるかと思います。
既存の.erbファイルをhamlに変換する方法

#手順

gemファイルに以下を記載

```
gem 'hamlit'

group :development do
  gem 'erb2haml' 
end
```

'erb2haml' はhamlに変換する際に利用するため記載を忘れないこと

```
$ bundle install
```

イントール完了後

```
$ bundle exec rake haml:replace_erbs
```

これで変換が完了します。
electronを使った開発でハマったこと

こんにちは。[nisshii](https://twitter.com/nisshii0313)です。
最近はelectronを使って動画再生プレイヤーを開発したりしてます。

その中でハマったり、詰まったりしたことを徒然なるままに書いていきます。

## 1, new BrowserWindow() する時に height・widthがint型でないと、決められた初期値が代入されてしまう

公式docに(https://www.electronjs.org/docs/api/browser-window) に微妙に書いてありますね。
int型でない数値を設定すると、heightであれば600、widthであれば800が代入されます。
実装はこの辺かな
https://github.com/electron/electron/blob/e4180b3a3ab90f0cb479db18dff36b1e69242a30/shell/browser/ui/inspectable_web_contents.cc#L105-L114

エラーも出ずに、言わば勝手に代入されてしまうので結構焦りました(笑)

windowsユーザーのモニタースケールの変化(100~500%)に対応してウィンドウサイズを弄る際に、height・widthを拡大率で割り算していたためにこの問題にぶち当たりました。
素直に[screenscreentodiprect](https://www.electronjs.org/docs/api/screen#screenscreentodiprectwindow-rect-windows)あたりを使えば良かったですね。(windows専用APIですが)


## 2, applicationがreadyになる以前にnew BrowserWindow()すると、出来たwindowが軽くバグる

良い子の皆さんはapp.on('ready')からの流れでnew BrowserWindow()するか、app.whenReady()などでキチンと待ってからnew BrowserWindow()していることとは思いますが、そうしないと軽くバグります。

具体的には、通常windowを閉じる際はライフサイクル的に
- BrowserWindowのcloseイベント
- appのwindow-all-closedイベント(全windowを閉じた場合)
- appのbefore-quitイベント
- appのwill-quitイベント
- appのquitイベント
- BrowserWindowのclosedイベント

と言う順番だと思うのですが、今回のケースでは各BrowserWindowのcloseイベントの前にappのbefore-quitイベントが走るようになります。
なんとなくは確かにそうなりそうだとわかるのですが、具体的なソースを見つけられていないので詳しい方いらっしゃったら教えてください。

以上です。気が向けば更新していくかもです。

#### 参考資料：
https://qiita.com/hoto17296/items/72d3526bef332f9ce027
Hanamiでmysqlのsocketを指定する

## こうやる

[Hanami::Model](https://github.com/hanami/model)は内部的に[ROM](https://rom-rb.org/)(rubyのorm）を呼び出している


query parameterで渡せる

```ruby

DATABASE_URL="mysql2://root:password@host/database?socket=/mysql/mysql.sock"
```
#### 参考
https://rom-rb.org/learn/sql/3.2/#mysql





## Cloud RunでHanami
今回 GCPのcloud runでcloud sql と接続するのにsocketを指定する必要があった
#### cloud sql proxy経由で接続する
```ruby

DATABASE_URL="mysql2://root:password@host/database?socket=/cloudsql/<DATABASE_CONNECTION_NAME>"
```

Hanamiは文献が少ないので積極的にアウトプットしていこう
GitHub ActionsのHadolint Actionを使って安全なDockerfileを運用する

[GitHub Actions と hadolint を組み合わせて Dockerfile の静的解析を自動化しよう！ - kakakakakku blog](https://kakakakakku.hatenablog.com/entry/2020/07/08/004407) を読んで、自身のGHAにも組み込んでみた。

## hadolint (Haskell Dockerfile Linter)

hadolintとは、Dockerfileを[Dockerfile Best Practices](https://www.docker.com/blog/intro-guide-to-dockerfile-best-practices/)に沿って解析してくれるツールだそうな。

詳しくは本家へ↓↓
<a href="https://github.com/hadolint/hadolint"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/hadolint/hadolint.png" width="460px"></a> 
Created by https://ghlinkcard.com/

## さっそくGHAに組み込む

めちゃくちゃ簡単！
以下の感じで `brpaz/hadolint-action@master` を使うだけでGitHub ActionsでDockerfileを解析してくれる！

```yaml:.github/workflows/workflow.yml
name: Workflow
on: push
jobs:
  build:
    name: Hadolint
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Hadolint
        uses: brpaz/hadolint-action@master
```

## 結果

GHAの実行結果として、 `Dockerfile:23 DL3006 Always tag the version of an image explicitly` と返ってきた。

その時のDockerfileが以下

```dockerfile:./Dockerfile
    | ...
L23 | FROM gcr.io/distroless/base-debian10
    | ...
```

ベースイメージのタグを明示的に付けて〜的なやつの警告です。
対応としては、 `base-debian10:latest` とか `base-debian10:v1.0.0` とかにするのだが、この `distroless` とやらは バージョンタグがなく `latest` かハッシュ値しか使えない。さらに、今回の対応で `latest` を指定しても、hadolintで別の警告（ `DL3007 Using latest is prone to errors if the image will ever update. Pin the version explicitly to a release tag` ）が出される。

### 警告(`DL3006`)における対応

hadolint公式に[How to use](https://github.com/hadolint/hadolint#how-to-use)や[Configure](https://github.com/hadolint/hadolint#configure)という項目があり、起動オプションやyamlファイルで設定できるよ〜と書いたあった

ただ、`DL3006`の警告をすべて無視するとDockerfileのマルチステージビルド時に別の箇所（今回で言うL23以外）で同様の警告が出た際も無視され、本来やりたかったベストプラクティスに沿った安全な運用ができなくなってしまう。

悩んでいると同僚にhadolintにはDockerfileに直接警告を無視するコメントを付与できる、Inline ignoresというのがあることを教えてもらった（感謝！

確かに公式を見てみるとちゃんと書いてあった（公式をちゃんと読もうと再認識した

よって、以下のように1行コメント(Inline ignores)を入れて、再度git pushすると無事にGHAが走りhadolintの警告がなくなった。

```dockerfile:./Dockerfile
    | ...
L23 | # hadolint ignore=DL3006
L24 | FROM gcr.io/distroless/base-debian10
    | ...
```

## まとめ

- hadolintをGHAに簡単に組み込むことができた
- ベストプラクティスに沿った安全なDockerfileを運用できた
- Exh: 公式サイトはちゃんと読もう
ファイル一覧取得バッチファイル(DOSコマンド)

#内容

バッチファイル配下のファイルの一覧を取得する
ＤＯＳコマンドです
#ソース

```bat:File一覧作成.bat

@echo off

cd /d %~dp0

rem =======================================================
rem 年月日取得
rem 年
set sYear=%DATE:~0,4%

rem 月(ゼロ埋め対応)
set sMonth=0%DATE:~5,2%
set sMonth=%sMonth:~-2,2%

rem 日(ゼロ埋め対応)
set sDate=%DATE:~8,2%

rem 時間の取得（０時～９時までのゼロ埋め対応）
set sNowTIME=%TIME: =0%

rem 時(ゼロ埋め対応)
set sHour=%sNowTIME:~0,2%

rem 分(ゼロ埋め対応)
set sMinute=%sNowTIME:~3,2%

rem 年月日
set sYYYYMMDD=%sYear%%sMonth%%sDate%

rem 時間
set sHHMISS=%sHour%%sMinute%

rem 年月日時間
set sYYYYMMDD_HHMISS=%sYYYYMMDD%_%sHHMISS%

rem =======================================================


rem 自分のディレクトリ
SET MYDIR=%CD%\

rem タイムアウト時間
SET OUT_TIME=5

rem 作成フラグ
SET MAKE_LIST_FLG=0

rem 作成中メッセージ
SET MAKE_NSG=作成中…
SET END_NSG=作成完了


SET INPUT_DIR=""
SET FILE_NAME=""

echo %sYYYYMMDD_HHMISS%
echo ■■■■■■■■■■■■■■■■■■■■■■
echo ■　　　　フォルダ内一覧リスト作成　　　　■
echo.
echo  【注意】
echo.
echo  ・指定するパスはフルパスで記入してください
echo    例)D:\hoge/hoge
echo.
echo  ・検索結果はこのバッチファイルと同じところ
echo    に作成されます。
echo.
echo  ・ファイル名で半角記号は現在未対応です
echo    例)　^(^)^<^>^{^}…
echo.
echo ■　　　　　　　　　　　　　　　　　　　　■
echo ■■■■■■■■■■■■■■■■■■■■■■
echo 対象フォルダ(フルパス)を指定してください
SET /P INPUT_DIR=">"

rem ディレクトリ異動
cd /D %INPUT_DIR%

echo 出力ファイル名を指定してください
SET /P FILE_NAME=">"

echo 01

rem フォルダ区切り「\」がある場合はアンダーバーにする
SET FILE_NAME=%FILE_NAME:\=_%

echo 02=%FILE_NAME%

rem ファイル名の指定がない場合は固定で
IF %FILE_NAME% EQU "" (
echo 03
  SET FILE_NAME=ListFile.txt
) ELSE (
echo 04
  SET FILE_NAME=%FILE_NAME%.txt
)
echo 05

echo ****************************************
echo 対象:%INPUT_DIR%
echo.
echo 出力:%MYDIR%
echo.
echo ファイル名:%FILE_NAME%
echo.
echo 作成方法
echo ----------------------------------------
echo  1:ファイル一覧(フルパス表示)
echo  2:ファイル一覧(ファイル込みツリー表示)
echo  3:ファイル一覧(フォルダツリー表示)
echo ----------------------------------------

SET /P INPUT_STR=">"



rem ファイル作成
IF /I %INPUT_STR%==1 (
    echo %MAKE_NSG%
    SET MAKE_LIST_FLG=1
    dir /A:-D /b /s /O:GN > %MYDIR%\%sYYYYMMDD_HHMISS%_フルパス表示_%FILE_NAME%
 )

IF /I %INPUT_STR%==2 (
    echo %MAKE_NSG%
    SET MAKE_LIST_FLG=1
    tree /f >  %MYDIR%\%sYYYYMMDD_HHMISS%_ツリー表示_ファイル有_%FILE_NAME%

 )

IF /I %INPUT_STR%==3 (
    echo %MAKE_NSG%
    SET MAKE_LIST_FLG=1
    tree / >  %MYDIR%\%sYYYYMMDD_HHMISS%_ツリー表示_フォルダのみ_%FILE_NAME%
 )

rem 作成結果表示
IF %MAKE_LIST_FLG%==1 (
    echo %MYDIR% 配下を作成しました
    echo %END_NSG%
    TIMEOUT %OUT_TIME%
) else (
    echo 作成されませんでした
    TIMEOUT %OUT_TIME%
)


start "*" %MYDIR%\

exit

```
Pycharm(MacOS)のよく使うのに忘れるショートカット集

よく使うのにちょっと経つとすぐに忘れてしまうPycharmショートカット集

全ショートカットは公式がまとめてくれていますのでこちらをご参照ください
[PyCharmキーボードショートカット - キーマップを印刷する﻿](https://pleiades.io/help/pycharm/mastering-keyboard-shortcuts.html#ws_print_keymap)

## 参照していた場所に戻る/進む

`Command + B` 等で宣言元に移動した後、移動前の位置に戻りたい時など
キャレットの表示位置を戻したり進めたりできる

- 戻る
    - `Command + option + ←`
- 進む
    - `Command + option + →`

## 変数名/関数名の変更

変数名や関数名を 宣言元 や 使用箇所 含めて全て一括で変更できる

- 変更したい箇所にキャレットがある状態で `Shift + F6`

余談ですがタッチバー搭載のMacBookでPycharmを使用する時は、タッチバーに常にファンクションキーが表示されるようにしています。
参考：[Mac - 特定のアプリ起動時の Touch Bar にファンクションキーを表示](https://pc-karuma.net/mac-touch-bar-show-function-keys/)

## インポートの再編成

使用していないライブラリの削除 と インポート順の整列

- `Ctrl + option + O`

## 警告波線に対するアクション

「未インポートのライブラリを使用した時に出る赤波線」
「コード規約に準拠しない書き方をした時に出る黄波線」 など

これらに対してアクションを実行したい時

- 波線がある箇所にキャレットがある状態で `option + Enter`

## 最近見たファイル一覧の表示

閉じてしまったタブを再度開きたい時とかに

- `Command + E`

直近閉じたタブを復活させる場合は「任意のタブを右クリック → ReopenClosedTab」でもいける

### ファイル内の特定行にジャンプ

マウスやトラックパッドでのスクロールは指の関節に負担がかかるので出来るだけこれ使いたい

- `Command + l`

### あとがき

ショートカット忘れた時に、まぁいいかでマウス使ったり自力で探して修正したりしてたことを改めて反省
二度と忘れませんように...
XcodeでC++例外が取れないじゃないか、という方は

昔はXcodeでC++例外が普通に取れてた気がします。
Exception breakPointを追加するだけですね。

しかしここ数年、取れなくなってました。ちょっと困ったので調査したところ、取れました。

###Exception breakPointを追加する時に、allを指定するのみ。

デフォルトが変わったんですかねえ。

まあこれだけ。
OpenWRT(LEDE)使いこなし : rtorrent + LINE Notify

# はじめに
OpenWRT/LEDEのNASサーバーにrtorrentとLINE Notify環境を構築したので、
折角なので連携させてみました。

前記事:
[中華ファンレスNASをOpenWRT(LEDE)で使う](https://qiita.com/yo-he/items/74793b33c4761f9529f3)
[OpenWRT(LEDE)使いこなし : rtorrent](https://qiita.com/yo-he/items/72fcc53b9d9f4e1bb241)
[OpenWRT(LEDE)使いこなし : LINE Notify](https://qiita.com/yo-he/items/e54720c33d8d09df04c9)

# 前準備
やりたいことは、
「rtorrentでファイルのダウンロードが終わったタイミングで、完了したファイル名をLINEに通知して欲しい」
です。

LINE Notify自体の前準備は適当にggるか、
Qiitaであれば[この記事](https://qiita.com/YuHori/items/0e462119033e0906f982)辺りです。
LEDEへのLINE Notify環境構築は、[前記事](https://qiita.com/yo-he/items/e54720c33d8d09df04c9)を参照してください。

先ずはrtorrentにフックをかけて実行する為の
LINE Notify実行スクリプトを用意します。

```line-nortify.sh
#!/bin/bash
# Script for LINE nortify
token=XXXXXX
curl -X POST -H "Authorization: Bearer ${token}" -F "message=$1" https://notify-api.line.me/api/notify

```

LEDEは環境が貧弱で/home すらないので、
/root/sh 等、適当に配置して実行出来るようにしておきます。
尚、私はbashをinstallしていますが、標準のOpenWRT/LEDEではashだと思うので、
bashをinstallするか、読み替えるか、等して下さい。

# rtorrentへのフック
.rtorrent.rc にコードを書いていきます。
勉強したい方は、マニュアルとしては、以下を解読すれば良い様です。
https://rtorrent-docs.readthedocs.io/en/latest/cmd-ref.html

今回はダウンロード完了時にフックをか掛けたいだけですので、
以下の1行を、/root/.rtorrent.rc に追記します。

```/root/.rtorrent.rc
method.set_key=event.download.finished,notify_me,"execute2=/root/sh/line-nortify.sh,$d.name="
```

# 結構便利
私は、RaspberryPi等のinstallイメージファイルを色々と落として来る事が多く、
サーバーによっては物凄く(半日以上、等)時間がかかる為、
push通知でダウンロード完了タイミングを知る事が出来るのはとても便利です。

また、私の環境ではLEDEのrtorrent向けGUI(luci-app)がアクセス出来なくなる事が多いですが、
この場合でも、ダウンロード完了を知る事が出来る為、
安心してリセット・リブートを実施する事が出来ます。
【form_with】でhtmlタグのcheck_boxにclassやIDを付与する

#記述方法
{}のなかにまとめて記述すれば良い。

```ruby:具体的な記述
<%= f.check_box :diabetes ,{checked: true, class: "form-check-input", id: "diabetes" }, "true", "false" %>
```


```ruby:間違った例
<%= f.check_box :diabetes ,{ }, "true", "false", class: "form-check-input", id: "diabetes" %>
```
{}の中にはcheckd: :trueしか入れてはいけないと思っていたため、ハマってしまった。
備忘録として書き残しておく。
ParcelでVuetify環境

# きっかけ
[Vuetifyのクイックスタートで](https://vuetifyjs.com/ja/getting-started/quick-start/)

- Vue CLI のインストール
- Vue UI のインストール
- Nuxt のインストール
- Webpack のインストール

（※後々考えたら多分「の」は「環境での」っていうことなんだろうなぁって思う)

って書いててVue CLI入れないと環境つくれないのかなぁって思ってたのですが、Parcelで試してみたらあっさりできたので記事にして残します。

# Parcel
Parcelの設定は[クイックスタート](https://en.parceljs.org/getting_started.html)
`npm install parcel-bundler --save-dev`
をするぐらい

# Vuetify
Parcelが勝手にインストールなどしてくれるので不要

# ファイル内容
```index.html
<html>
  <head>
    <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/@mdi/font@5.x/css/materialdesignicons.min.css" rel="stylesheet">    
    <title>Parcel - Vue</title>
  </head>

  <body>
    <div id="app"></div>
    <script src="./index.js"></script>
  </body>
</html>
```

```index.js
import Vue from 'vue';
import vuetify from './plugins/vuetify' 


import App from './components/App.vue';

new Vue({
  vuetify,
  render: createElement => createElement(App)
}).$mount('#app');
```

```components/app.vue
<template>
  <alert></alert>
</template>

<script lang="ts">
  import Vue from "vue";
  import Alert from './Alert.vue';
  export default Vue.extend({
    components: {
      Alert,
    },
  });
</script>

<style lang="scss" scoped>
.container {
  color: green;
}
</style>
```

```components/Alert.vue
<template>
  <v-app id="inspire">
    <div>
      <v-alert type="success">
        I'm a success alert.
      </v-alert>
  
      <v-alert type="info">
        I'm an info alert.
      </v-alert>
  
      <v-alert type="warning">
        I'm a warning alert.
      </v-alert>
  
      <v-alert type="error">
        I'm an error alert.
      </v-alert>
    </div>

    <v-card
      class="mx-auto"
      max-width="344"
      outlined
    >
      <v-list-item three-line>
        <v-list-item-content>
          <div class="overline mb-4">OVERLINE</div>
          <v-list-item-title class="headline mb-1">Headline 5</v-list-item-title>
          <v-list-item-subtitle>Greyhound divisely hello coldly fonwderfully</v-list-item-subtitle>
        </v-list-item-content>

        <v-list-item-avatar
          tile
          size="80"
          color="grey"
        ></v-list-item-avatar>
      </v-list-item>

      <v-card-actions>
        <v-btn text>Button</v-btn>
        <v-btn text>Button</v-btn>
      </v-card-actions>
    </v-card>
  </v-app>
</template>
```

```plugins/vuetify.js
import Vue from 'vue';
import Vuetify from 'vuetify';
import 'vuetify/dist/vuetify.min.css';

Vue.use(Vuetify);

const opts = {};

export default new Vuetify(opts);
```

# 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142784/f93b3d39-4407-1041-674b-3e44b37c25f6.png)
【練習】Mapメソッド

```java

package map_renshuu;
//MapクラスとHashMapクラスをインポート
import java.util.HashMap;
import java.util.Map;

public class Map1 {

	public static void main(String[] args) {
		//Mapインスタンスを生成、キーはString型、値（要素）はint型を指定
		//左辺は”ざっくり”多態性をつかうためにMapクラス
		Map<String,Integer> bankList=new HashMap<String,Integer>();

		//<bankList>にキーと値をいれる
		bankList.put("福岡銀行",541);
		bankList.put("西日本シティ銀行",312);
		bankList.put("みずほ銀行",653);
		bankList.put("ゆうちょ銀行",685);
		bankList.put("三井住友銀行",797);

		//<bankList>に入っている値をとりだすには、一度変数に代入が必要。getメゾットを使う
		int sumitomo=bankList.get("三井住友銀行");
		System.out.println("三井住友の銀行コードは"+sumitomo+"です");
		
		/*----------------------------------------------
        removeメゾット(ここは実行するとちゃんと出力されるので、なぜremoveされないのか謎、確認中)
		bankList.remove("sumitomo");
		System.out.println(sumitomo);
         ------------------------------------------------*/
		
		//for文で回して出力
		//for文の右辺は順番にキーが返ってくる
		for(String nini:bankList.keySet()) {
			int value=bankList.get(nini);
			System.out.println(nini+"銀行のコードは"+value+"です");
		}
		//bamkListを単体で出力
		System.out.println(bankList);


	}

}

/*実行結果----------------------------

三井住友の銀行コードは797です
797
福岡銀行銀行のコードは541です
ゆうちょ銀行銀行のコードは685です
西日本シティ銀行銀行のコードは312です
みずほ銀行銀行のコードは653です
三井住友銀行銀行のコードは797です
{福岡銀行=541, ゆうちょ銀行=685, 西日本シティ銀行=312, みずほ銀行=653, 三井住友銀行=797}
--------------------------------*/

```
GitHubのユーザー名を変更する方法

n番煎じの記事やねんって話ですが自分の為に残します。

### 前書き
皆さんはGitHubのユーザー名を変えたくなったことはないでしょうか？
「めっちゃダサいユーザー名にしちゃって後悔してる」
「なんとなくユーザー名変えたい」

人によって様々な理由があると思いますが、皆さん思ったことはあると思います(決めつけ)。
ここでは簡単ですがGitHubのユーザー名を変更する方法をご紹介します。

### 手順
1.Githubに移動してsettingsからユーザー名を新しいものに変更
Change usernameの部分ですね
![スクリーンショット 2020-09-06 14.31.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257500/3dd166ca-a060-bb62-57e2-89edafff14d4.png)
2.グローバルのユーザー名を変更する
`$ git config --global user.name 'new_username'`
変更がされたかの確認は下記のコマンドで出来ます
`$git config --global -l`

3.過去のリポジトリのケアが必要になるので今まで作ったリポジトリで下記コマンドを実行
`$ git remote -v`
こちらのコマンドを実行すると今のリポジトリnameが出てくると思いますのでこちらを新しいユーザー名に変更する必要があります。

**変更前**
`origin git@github.com:old_name/repository_name.git(fetch)`
`origin git@github.com:old_name/repository_name.git(push)`

 こちらのコマンドでリポジトリのユーザー名を新しい名前に変更できます。
`$ git remote set-url origin git@github.com:new_name/repository_name.git`
**確認**
`$ git remote -v`
ここで新しいユーザー名に変更されていたらOKです。お疲れ様でした :)

**変更後**
`origin git@github.com:new_name/repository_name.git(fetch)`
`origin git@github.com:new_name/repository_name.git(push)`


ちゃんと新しいユーザー名で`push`出来るかどうかは確認してくださいね。


### 終わり
手順としては以上となります
ユーザー名の変更自体はとても簡単ですが、以前のユーザー名で作ったリポジトリのケアが少し面倒ですね。

自分はリポジトリ数がそこまで多くなかったこともあり、愚直に一つずつリポジトリを触るタイミングでユーザー名を新しいものに変更してたんですが、これ一括でやる方法あるんでしょうか？
やり方知ってる親切な方がいたら教えていただきたいです🙇‍♂️