OmniAICreator/Qiita-1.07M huggingface dataset:
ipmitoolのパスワード指定オプションについて

サーバーのリモート管理でipmitoolを使う際、`-P`オプションでパスワードをコマンドラインの中で指定すると画面上で丸見えですね。ipmitoolにはパスワード関連で`-a`、`-E`、`-f`オプションがあるのでまとめておきます。

## -P \<password>
`-P`オプションはBMCのパスワードをコマンドラインで指定します。サポートされている場合、`ps aux`などのプロセスリストではパスワードが非表示になります。[man ipmitool(1)](https://linux.die.net/man/1/ipmitool)でもこのオプションは非推奨ですね。

```
# ipmitool -I lanplus -H 172.25.130.28 -U user -P password sol activate
[SOL Session operational.  Use ~? for help]


# ps aux
root      353369  0.0  0.1   8900  2236 pts/1    S+   19:23   0:00 ipmitool -I lanplus -H 172.25.130.28 -U user -P XXXXXXXXXX sol activate
```


## `-a`
`-a`オプションはコマンド実行前にBMCパスワードの入力を求めるプロンプトを表示します。OSのログインプロンプトと同じで入力したパスワードは非表示です。ipmitoolを対話的に使う場合はこれもありですね。

```
# ipmitool -I lanplus -H 172.25.130.25 -U user -a fru
Password: 
```

## `-E`
`-E`オプションは環境変数`IPMI_PASSWORD`に設定した値を読み取りパスワードとしてコマンドを実行します。これは`printenv`を実行すると見えてしまいますね。変数名も分かりやすいですしね。

```
# ipmitool -I lanplus -H 172.25.130.25 -U user -E fru
Unable to read password from environment
Password: 
#
# 
# export IPMI_PASSWORD=password
# 
# ipmitool -I lanplus -H 172.25.130.25 -U user -E fru
#
# printenv 
SHELL=/bin/bash
HISTCONTROL=ignoredups
...
IPMI_PASSWORD=password
```

## `-f`
ファイルにBMCのパスワードを保存し、そのファイルを`-f`オプションで指定しコマンドを実行します。`chmod 400`などとしておけば他のアカウントからは読み書きできず安全ですね。

```
# echo password > pwfile.txt
# 
# chmod 400 pwfile.txt
#
# ls -l
total 8
-rw-------. 1 root root 1420 Oct 24 21:02 anaconda-ks.cfg
-r--------. 1 root root   11 Dec  3 19:49 pwfile.txt
# 
# ipmitool -I lanplus -H 172.25.130.25 -U admin -f ./pwfile.txt fru
```
golang でPDFの表紙サムネを高速作成！

## はじめに
golang からPDFの表紙サムネを高速に作成する方法を紹介します。
よくある選択肢としてはImageMagickがあると思いますが、今回はより軽量なlibvipsを利用します。

## やってみよう

#### 必用なもの
* golang
* libvips (`apt insall libvips` on Utuntu 20.04)

#### やりかた？
libvips を golang から使えるようにしてくれるありがたいパッケージ bimg (https://github.com/h2non/bimg) を使います。

```go:main.go
package main

import (
	"log"
	"github.com/h2non/bimg"
)

func main() {
	buffer, err := bimg.Read("input.pdf")
	if err != nil {
		log.Fatal(err)
	}

	jpg, err := bimg.NewImage(buffer).Convert(bimg.PNG)
	if err != nil {
		log.Fatal(err)
	}

	thumb, err := bimg.NewImage(jpg).Resize(256, 256)
	if err != nil {
		log.Fatal(err)
	}

	bimg.Write("thumb.png", thumb)
}
```

input.pdf を用意して上記のコードを実行すると、PDFの1ページ目のサムネが thumb.png に保存されます。
非常に高速で大きなサイズのPDFでも高速でした。
ファイラーやDrive系サービス用のサムネ生成などにはいいかもしれません。
画像認識＋強化学習で株の自動売買システムをつくる

近年、個人投資家で自動売買を導入している人が増えてきていて、高度なデータ分析を取り入れたアルゴリズムを使われることもあります。
この記事では画像認識と強化学習で自動売買システムの事例を紹介します。

# データの流れ

まずシステムの全体の流れを図で簡単に説明します。

![blog用 (5).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211078/10779df9-4951-7e1e-3c24-0e371045fddc.jpeg)




HYPER SBIは株の取引きをするソフトウェアです。
①では取引が行われる板の文字を画像認識で読み取る機能（OCR）
②は①のOCRの学習モデルを作る機能
③はOCR結果を解析して他プレイヤーの買い圧力や売り圧力を推定する機能で、強化学習の特徴量として使います
④は強化学習の学習モデルを作る機能
⑤は強化学習モデルで推論する機能
⑥はLINE notifyを使って⑤の結果を通知
⑦は⑤の結果でトレードする機能
になります。以降は各機能を簡単に紹介していきます。

# ①板の画像認識 OCR　②OCRの学習モデル
板とはこういうものです。この画像を読み取る方法については過去の記事で説明してあります。OCRの学習モデルは画像認識のディープラーニングで作っていてその点についても以下の記事で触れてあります。
[株の自動売買のための板OCR](https://qiita.com/shiibass/items/20235d3952a804e1a1e9)

![AnyConv.com__video_2020-03-30_very_small.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211078/5aa10065-296f-5340-5ff9-1912df24fb98.gif)

OCRの推論は0.5秒ごとくらいのタイミングで推論したいので通信を介さないようにHYPER SBIを起動してる環境で行っています。windowsでtensorflowを動かすのは設定が面倒でした。

https://bizlog.tech/windows-maxpath-change/
でパスの260文字制限の解除して、
https://support.microsoft.com/ja-jp/help/2977003/the-latest-supported-visual-c-downloads
でVisual C++をダウンロードしてできるようになりました。

# ③板解析
前セクションで添付した動画でピコピコと数字が変化したり光ったりしています。これは大半がアルゴリズムで、ごくまれに人間が注文を出すことによって動いています。大口投資機関でアルゴリズムを導入していないところはまずないと言っていいと思います。アルゴリズムということは何らかの規則に従って取引していますので、どういう規則で動くのかを推定しています。私の予想では、時間をトリガーにして作動するアルゴリズム、ニュースをトリガーにして作動するアルゴリズム、株価の急騰急落で作動するアルゴリズムなどがいると思っています。
推定方法についてはこの記事では触れません。

# ④⑤強化学習
③で取得した特徴量をインプットに強化学習を行います。強化学習については過去の記事でまとめておきました。
[株の自動売買アルゴリズムを強化学習でつくる](https://qiita.com/shiibass/items/a930340ad07f80812735)
推論時はAPIサーバをたてて、５分ごとに推論するリクエストを送っています。


# ⑥⑦通知
買うか買わないかの戦略をLINEで通知します。LINE notifyを以下の記事を参考にすれば10分くらいでメッセージボットをつくれます。
[PythonでLINE Notifyへ通知を送る](https://qiita.com/akeome/items/e1e0fecf2e754436afc8)

LINE notifyアカウントを使えば以下のような感じでトレード戦略を通知して、人間はただそれに従うのみという運用です。

![IMG-0445.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211078/6775970c-0a5e-e344-36c8-a782c1c9f636.png)

# 費用
システムのインフラも含めて毎月3万円くらいで運用できています。二人で開発していますが人件費は0円です。

# データ量
使っているデータは①で記したような板の録画データ約2年分です。
株では高い価値の情報を持っていることが非常に重要です。価値はその情報を知っている人の少なさと業績インパクトの大きさの掛け合わせで効いてくると考えると、容易に手に入らない録画データは価値が高く、その点で差別化を図ろうという狙いです。

# 最後に
機械学習できる人はアルゴリズムトレードに挑戦してみてほしいです。死に物狂いで身につけたでしょうから有効に活用すべきです。ただし、安易な気持ちで参戦すべきではないとも思っています。アルゴリズムを使っていない投資家は、機械学習で処理しづらいような情報を頭の中で処理できるという点でアルゴリズムトレードとは違う強さを持っています。アルゴリズムを使う人（主に機関投資家）はクオンツが勝つ方法をひたすら研究してるので単純に強いし、資金が半端ないので反対の行動をしたら十中八九負けます。うまく自分の武器を見つけてかろうじて生き残るためのデータ分析をやっていきましょう。

次回はまた別の研究を紹介していきます。

作ったコードはここで管理しています。
OCR
https://github.com/shiibashi/board_ocr
板録画・LINE通知
https://github.com/shiibashi/board_monitor_private
強化学習（学習・推論API）
https://github.com/shiibashi/daytra
IAMポリシーで特定のタグを持つEC2操作を制限する

# 特定のタグを持つEC2操作を制限する
はい皆さんこんにちは

この記事はIAMポリシーによってEC2のタグを参照して権限を付けた事例の紹介です。

# 詳細
要件としては以下の内容でした。
・EC2にEnvタグ（値：dev）が付いたものだけ操作したい。
・Envタグ（値：prod）は操作出来ないようにする。
・タグが一致しているならAMIやスナップショットも取りたい

環境：
AWS EC2（AmazonLinux2）
コンソールにログインするユーザーのIAMポリシーを編集しながら検証

##最終的な設定
必要な権限を付与しつつ、EC2:*を許可しておく。
そのうえで、prodタグを持っているEC2の操作を拒否する。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Action": [
                "trustedadvisor:*",
                "iam:*",
                "cloudwatch:*",
                "s3:*",
                "logs:*",
                "cloudtrail:*",
                "ec2:*",
                "support:*",
                "inspector:*",
                "directconnect:*"
            ],
            "Resource": "*"
        },
        {
            "Sid": "2",
            "Effect": "Deny",
            "Action": [
                "ec2:*"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "ec2:ResourceTag/Env": "prod"
                }
            }
        }
    ]
}
```


##色々やってみる
EC2のインスタンス一覧にはprodのサーバも表示される（これは仕方ない）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532987/ca381210-e538-574e-be64-db47efe9e670.png" width=50%>

prodが入っているEC2のタグを操作しようとするとエラーになる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532987/201199a7-0a1b-692a-1035-cd75701859f9.png" width=50%>

prodが入っているEC2の再起動でエラーになる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532987/2b8546b4-5b14-d8f5-c3e7-df64c6d7cf9f.png" width=50%>

devが入っているEC2の再起動はOK
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532987/ff606a22-6b32-fd6a-14cc-4183934d13be.png" width=50%>
devが入っているEC2のAMIが取得できる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532987/003c6a4d-bdc7-158c-167c-8485f16caa5b.png" width=50%>

devが入っているEC2でスナップショットも可能です。

##注意事項
タグが付いていないサーバも同様に操作が可能です。
何故こうしているかと言うと、
AMIやスナップショットが作成される時にタグが付いていないのでエラーになってしまいます。
なのでタグが無くてもAMIやスナップショットを許可する必要があります。

なお、スナップショットにEnv:prodのタグを付けた後に削除しようとした場合、想定通りエラーになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532987/816442a4-5b70-7a42-b932-c81c61a1c72b.png" width=50%>

運用で必ずタグをつけるようにしましょう。


##感想
本当はもっと権限を絞れると思いますが、今回は細かい制限は入れませんでした。
（あまり時間が無かったのもあり。）
これ以外にもっと効率の良いものがあれば更新します。



**ありがとうございました。**
ERROR: Service 'web' failed to build : The command '/bin/sh -c apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs' returned a non-zero code: 100

#Udemyのゼロからはじめる Dockerによるアプリケーション実行環境構築にて
レクチャーと同じコードでrubyのverを2.6.3に変えて`RUN apt-get update -qq && apt-get install -y build-essential`を行うとこのエラーがでてしまいます。

```
Step 2/8 : RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs

---> Running in 36ea4384800f

E: Failed to fetch http://deb.debian.org/debian/dists/buster/main/binary-amd64/by-hash/SHA256/e8455b55666b3c399ac4605281f20a90fa86617fd75c3a9f26a1efa5c0687a5b File has unexpected size (13341 != 7906408). Mirror sync in progress? [IP: 151.101.90.132 80]

Hashes of expected file:

- Filesize:7906408 [weak]

- SHA256:e8455b55666b3c399ac4605281f20a90fa86617fd75c3a9f26a1efa5c0687a5b

- MD5Sum:ecae7a32cc589c20b7895517deda55e5 [weak]

Release file created at: Sat, 26 Sep 2020 09:54:48 +0000

E: Failed to fetch http://security.debian.org/debian-security/dists/buster/updates/main/binary-amd64/by-hash/SHA256/695dc865096aea89c8019fd5c2eb1d60be9d26c9a274c1261851a845e5144f08 File has unexpected size (13391 != 253900). Mirror sync in progress? [IP: 151.101.90.132 80]

Hashes of expected file:

- Filesize:253900 [weak]

- SHA256:695dc865096aea89c8019fd5c2eb1d60be9d26c9a274c1261851a845e5144f08

- MD5Sum:735dc48c9149a23603b4a8e6b5b21628 [weak]

Release file created at: Fri, 04 Dec 2020 02:01:41 +0000

E: Failed to fetch http://deb.debian.org/debian/dists/buster-updates/main/binary-amd64/by-hash/SHA256/e26b70071e36b418e8b95c6b7ec6d0a733973708aa308f856b0c9ebb2d884fcf File has unexpected size (13357 != 7856). Mirror sync in progress? [IP: 151.101.90.132 80]

Hashes of expected file:

- Filesize:7856 [weak]

- SHA256:e26b70071e36b418e8b95c6b7ec6d0a733973708aa308f856b0c9ebb2d884fcf

Release file created at: Thu, 03 Dec 2020 20:30:16 +0000

E: Some index files failed to download. They have been ignored, or old ones used instead.

ERROR: Service 'web' failed to build : The command '/bin/sh -c apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs' returned a non-zero code: 100
```
#解決方法
```
RUN printf "deb http://archive.debian.org/debian/ jessie main\ndeb-src http://archive.debian.org/debian/ jessie main\ndeb http://security.debian.org jessie/updates main\ndeb-src http://security.debian.org jessie/updates main" > /etc/apt/sources.list
```

をDockerfileの`RUN apt-get update -qq && apt-get install -y build-essential`の前に追加
#最後に
解決するのに時間がかかりました。node.jsのupdateも要求されたので下記参考
https://qiita.com/kodai_0122/items/795438d738386c2c1966
Chrome拡張機能: JK Shortcuts Navigator 設定 2020/12/04動作確認

# JK Shortcuts Navigator 設定
Google検索結果のリンクをjkで選択移動ができる[JK Shortcuts Navigator](https://chrome.google.com/webstore/detail/jk-shortcuts-navigator/chgfodomgimhbcmlfljhkgildehakgif)を使いたかったが、動かない。
どうやらGoogleの検索ページはしばしばhtmlの構造が変化するらしく、拡張機能の設定をそれに合わせて変更する必要がある。

拡張機能のoptionからgoogleの設定を開き、"selectors"の部分を以下に変更する。

```
    "selectors": [
        "div#main>div#cnt>div.mw>div#rcnt>div.col>div#center_col.eIYMdc>div#res>div#search>div>div#rso>div.g>div.rc>div.yuRUbf>a:nth(*)"
    ],

```

とりあえずこれでjkが動くようになった。
ruby2.7.1, rails 6.0.3でrailsコマンドを叩くと大量の警告が出た話

ruby3以降で`rb_check_safe_obj`が削除されるらしくsqlite3が大量の警告を吐いて邪魔だったので対処した話

```shell
> rails test
Running via Spring preloader in process *
**/sqlite3/database.rb:89: warning: rb_check_safe_obj will be removed in Ruby 3.0
```

# 対応
sqlite3のバージョンを1.4.2以降に更新

```shell
# Gemfile
gem 'sqlite3', '1.4.2'
bundle update
```

# 対応後

```
> rails test
Running via Spring preloader in process *
Started with run options --seed *

  5/5: [======] 100% Time: 00:00:01, Time: 00:00:01
```
ahamoでローミングできる国をPower BIを使って3分で可視化する

まずdocomoの[ahamo発表サイト](https://www.nttdocomo.co.jp/info/news_release/2020/12/03_00.html)にいって、国の一覧が表示されているところをコピーします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157693/0de84cb0-e0f0-40cd-1e0e-cc77fcdbad1d.png)

メモ帳を開いてペースト。適当な名前でとりあえずデスクトップに保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157693/e62cfbf8-61ec-fae4-2c68-f6cf2521bbf5.png)

Power BIを起動して、Get dataメニューからText/CSVを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157693/a3e2af6e-2bdc-3f5a-26c2-71c58916215c.png)

先程のファイルを選択すると、何故か文字化けしているので、文字コードをUTF-8にしてLoad。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157693/b8723dd9-3ffe-db16-7a2e-9b0f225107e0.png)

VisualizationsメニューのFilled Mapをクリックして、FieldsからコラムをLocationにドラッグしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157693/91a48719-4e71-eacc-a4eb-7197057e14ed.png)

できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157693/86479c78-821c-25f7-56de-1628930fca28.png)

タイ、アメリカ、ルクセンブルクが含まれているのに白いままですね。
DynamoDBの知らなかった事

##きっかけ
DynamoDBについて調べていて、
「知らなかった:open_mouth:」と思ったので、記事にしました。
AWS初学者向けです。「知らなかった:open_mouth:」が2つあります。

##:open_mouth:知らなかった①　DynamoDBはSQL操作もできる？
認定試験に向けて、DynamoDBはNoSQL対応と覚えていたのですが、
なんと、**SQLも使える様になりました**。
ただし、**SQLで操作可能になるSQL互換のクエリ言語「PartiQL」に対応**という事で、
との事なので、そのままSQLが使えるわけではない(使い勝手の悪い所もある)そうです。
認定試験はどうなってくるかわかりませんが、早々の対応はないそうですが、いずれひっかけ問題になってくるんでしょうか。

参考）
[AWS、DynamoDBをSQLで操作可能に　SQL互換のクエリ言語「PartiQL」対応を発表](https://www.itmedia.co.jp/news/articles/2011/30/news129.html)
[Kota / もりしーのパソコン動画]
(https://www.youtube.com/watch?v=WGUk6DaRBK0&list=UUsgQtIeFObrixeJIYBCi5VQ)


##:open_mouth:知らなかった②　DynamoDBへの画像保存は、、、
DynamoDBさん、大規模データの取り扱いのイメージだった。

>Amazon DynamoDB は、数ペタバイトのデータや、1 秒あたり数千万の読み込みおよび書き込みリクエストをサポートするために、

参考）
[Amazon DynamoDB の特徴](https://aws.amazon.com/jp/dynamodb/features/)

しかし、よく読んでみると、、、
認識違いでお恥ずかしいかぎりです:sweat:

>Amazon DynamoDB は、key-value およびドキュメントデータモデルをサポートする NoSQL データベースで、開発者は、数ペタバイトのデータや、1 秒あたり数千万の読み込みおよび書き込みリクエストをサポートするために、小規模からグローバルまで開始できる最新のサーバーレスアプリケーションを構築できます。DynamoDB は、高性能でインターネット規模のアプリケーションを実行するように設計されており、従来のリレーショナルデータベースに負荷がかかる場合があります。

「[Amazon DynamoDB の特徴](https://aws.amazon.com/jp/dynamodb/features/)」より

ドキュメントデータモデルをサポートって書いてますね、画像の取り扱い注意です。
こちらもなるほど参考になりました。

>DynamoDBは個々のレコードを64KBに制限するので、画像が小さくなければDynamoDBを使用することはできない


参考）
「[amazon-s3 - 多くの画像を保存するS3対DynamoDB]
(https://stackoverrun.com/ja/q/3431911)」

あと、DynamoDBは、データベースサービスだしね。

##結果
①　DynamoDBはSQLも使えるようになったけど、SQL互換のクエリ言語「PartiQL」で、そのままSQLが使えるわけではない。

②　画像保存は、DynamoDBではなく、S3等に保存してね。
Next.jsでFirebase Admin SDKを複数プロジェクトに対して使う

レッドインパルスのたかけんです。
REDIMPULZ Advent Calendar 2020 の4日目のエントリーです。

## Firebase Admin SDKをNext.jsで使う

**注意 : firebase Admin SDKの認証情報は環境変数で扱い、サーバーサイドで利用する想定です。
認証情報の扱いに注意して、フロントエンドで実行されるコードからは参照しないようにしてください。**

### Firebase Admin SDKのセットアップ

https://firebase.google.com/docs/admin/setup?hl=ja#top_of_page

Next.jsだと、firebaseの初期化が再実行されるとエラーになるので、工夫が必要です。

https://stackoverflow.com/questions/44034691/react-nextjs-firebase-error-refresh-firebase-app-named-default-already-exist

回避策として、以下のようにしています。


```ts:lib/firebaseAdmin.ts
import admin from 'firebase-admin';

const initializeApp = () => {
  admin.initializeApp({
    credential: admin.credential.cert({
      projectId: process.env.FIREBASE_ADMIN_PROJECT_ID,
      privateKey: process.env.FIREBASE_ADMIN_PRIVATE_KEY,
      clientEmail: process.env.FIREBASE_ADMIN_CLIENT_EMAIL,
    }),
    storageBucket: process.env.FIREBASE_ADMIN_STORAGE_BUCKET,
  });
};

admin.apps.length ? admin.app() : initializeApp();

export const firestore = admin.firestore();
```

## Next.jsでFirebase Admin SDKを複数プロジェクトに対して使う

Firebase Admin SDKは、複数プロジェクトに対して使うことが可能です。

https://firebase.google.com/docs/admin/setup?hl=ja#initialize-multiple-apps

参考にNext.jsで使う場合は、以下のようにすることで、できました。


```ts:lib/firebaseAdmin.ts
import admin from 'firebase-admin';

const initializeApp = () => {
  admin.initializeApp({
    credential: admin.credential.cert({
      projectId: process.env.FIREBASE_ADMIN_PROJECT_ID,
      privateKey: process.env.FIREBASE_ADMIN_PRIVATE_KEY,
      clientEmail: process.env.FIREBASE_ADMIN_CLIENT_EMAIL,
    }),
    storageBucket: process.env.FIREBASE_ADMIN_STORAGE_BUCKET,
  });
  admin.initializeApp(
    {
      credential: admin.credential.cert({
        projectId: process.env.FIREBASE_OTHER_ADMIN_PROJECT_ID,
        privateKey: process.env.FIREBASE_OTHER_ADMIN_PRIVATE_KEY,
        clientEmail: process.env.FIREBASE_OTHER_ADMIN_CLIENT_EMAIL,
      }),
      storageBucket: process.env.FIREBASE_OTHER_ADMIN_STORAGE_BUCKET,
    },
    'other'
  );
};

admin.apps.length ? admin.app() : initializeApp();

export const firestore = admin.firestore();
export const otherFirestore = admin.app('other').firestore();
```


## 補足

* [Next.jsの環境変数の設定方法](https://nextjs.org/docs/basic-features/environment-variable)
App Storeの手数料半額プログラム(App Store Small Business Program)へ登録すると収益はざっくりいくら増える？

## 概要

今まで30％だったApp Store手数料が、条件を満たせば15％に割引される「App Store Small Business Program」が
2020年11月に発表され、今月12月に詳細がアナウンスされました。

今現在の自分の収益だと、割引適用後はどのくらいお得か？を確認する方法を簡単にまとめました。
（内容的にはただの算数です）

「App Store Small Business Program」とは
前年収益が100万ドル以内のディベロッパに対するApp Storeの手数料率が15％に割引されるプログラムです。
なお、15％適用を受けるためには専用フォームからプログラムへの登録が必要です。
詳細：[https://developer.apple.com/app-store/small-business-program/](https://developer.apple.com/app-store/small-business-program/)

## 割引適用後の収益を計算する
折角（？）なのでPythonで書きます。

### 割引変更後の収益

```python
# Revenue: 今の収益
# NewRevenue: 新しい収益
NewRevenue = Revenue * 0.85/0.7
```

例) 現在の収益100万とすると

```python
NewRevenue = 1000000 * 0.85/0.7

# NewRevenue ≠ ¥1,214,285
```

新割引プログラムでは収益が、約¥1,214,285になりました。

収益に**ザックリと1.21を掛ける**形になるので、**20％ちょい増える**イメージですね。

## 収益の増分を計算

### 割引変更後の増分収益

```python
# Revenue: 今の収益
# Increase: 収益増分
Increase = (Revenue * 0.85/0.7) - Revenue
```

例）現在の収益100万とすると

```python
Increase = (1000000 * 0.85/0.7) - 1000000

# Increase ≠ ¥214,285
```

当然ですが、増分は¥214,285となりました。

こちらも端的に、現在の**収益に0.21を掛ける**ことでザックリとした**増額分を確認**できます。
【Rails】ActiveRecord::Relationから欲しい値を取出す方法。

## 条件にあてはまるデータを取得する
「沢山あるデータの中から特定のデータのみを取り出したいっ！」
そんな時はwhereメソッドを使うと便利ですよね。素晴らしいメソッドや・・・。感謝。
ただ、 whereメソッドを使った場合
**指定したモデルのインスタンスではないのでそのままデータを利用できない**
というこころが非常にむづかしいのです。
他の方も書かれているので、自分なりにまとめた物を書いていきます。
試しに、こんな物を作ってみました。

```ruby

checks = Product.where(z_code: 1039)
```

puroductモデルの中で「z_code」の値が「1039」のデータを見つけてきて！
出てきた答えがこんな物でした。

```ruby

>> checks
=> #<ActiveRecord::Relation [
#<Product id: 2, name: "りぼん", z_code: 1039, num: 3, release: "3", customer_id: 8, created_at: "2020-12-03 10:33:11", updated_at: "2020-12-03 10:33:11">, 
#<Product id: 349, name: "りぼん", z_code: 1039, num: 1, release: "3", customer_id: 9, created_at: "2020-12-04 01:20:38", updated_at: "2020-12-04 01:20:38">
]>
```

ん？なにこれ？
この中で、id:2のnum(冊数)だけを取り出したいのだけど、どうすればいいのだろう・・・。
この後、5時間ぐらいに渡りトライ&エラーを繰り返すハメに・・・。

## to_a

to_aメソッドとは、レシーバー自身を返すメソッドで、
Arrayのサブクラス（Arrayクラスを継承しているクラス）に対し使用した場合は、配列に変換されたものを返すそうです。
よく範囲オブジェクトを、配列に変換する時に使用される様です。

### to_aの書き方
to_aメソッドは、以下のように使用します。
`object.to_a`
オブジェクトが配列の時は、配列自身を返しますし
範囲オブジェクト（例えば、1..5など）の場合は、配列に変換したものを返します。
hashに対しても使用することが可能で、２次元の配列に変換されたものを返します。
と言う事で、早速試してみます。

```ruby
>>  checks.to_a
=> [
#<Product id: 2, name: "りぼん", z_code: 1039, num: 3, release: "3", customer_id: 8, created_at: "2020-12-03 10:33:11", updated_at: "2020-12-03 10:33:11">,
 #<Product id: 349, name: "りぼん", z_code: 1039, num: 1, release: "3", customer_id: 9, created_at: "2020-12-04 01:20:38", updated_at: "2020-12-04 01:20:38">
]
```

よしよし、ActiveRecord::Relationが外れて、ただの配列になってくれた。神よ！！
後はid:2のnumを取り出すだけだぜぇ〜・・・。(悪い顔)

```ruby
>> (checks.to_a)[2].num
NoMethodError: undefined method `num' for nil:NilClass
```

はぅ！！
どう言う事やねん・・・。

### (オブジェクト.to_a)[欲しいid].求めるカラム名

データ2個しか出てないないのに、
(checks.to_a)[2].num = ３番目のデータ出してって言ってもそりゃダメですよね。
(*番号は0,1,2,3・・・って感じで0から始まります。)
と言う事で

```ruby
>> (checks.to_a)[0].num
=> 3
```
抽出できた！

### 宿題は山積み
問題は解けたのですが

- ActiveRecord::Relationってそもそもなんなの？
- レシーバー自身を返すってなに？

とわからない事が逆に増えてしまいました・・・。
よろしければ、こう言う意味だよと教えていただけると
嬉しくて小躍りします。
みんなで育てる仕様書デザイン

この記事は [Goodpatch Advent Calendar 2020](https://qiita.com/advent-calendar/2020/goodpatch) の5日目です。

# はじめに
開発において、仕様書はとても重要な役割を果たします。
私が仕様書を作成するときに考慮している観点を紹介します。

## 仕様書に求めること
### 正しい仕様が書かれている
本来の仕様書の目的です。
メンバーの目線を揃え、仕様を知りたいてときに知ることができ、新メンバーや未来の自分が仕様を理解できる必要があります。

### 属人化しない
誰が見ても正しく内容を理解できる必要があります。
誰でも書ける・読めるようにするため、エンジニアリング言語を使わず、正しい日本語で書くようにします。
エンジニア以外も仕様を書くことで、実装や運用を考慮したデザインを作ることができます。
また、現在の仕様に至るまでの過程がわかるようにしておくと、議論を蒸し返さずに納得感を得られます。


### 仕様書を開くコストを抑える
どれだけ素晴らしい仕様書があっても開かれないと意味がありません。
仕様書を開くコストを抑えるため、普段使っているツールに使うようにします。

### 仕様書作成・メンテナンスコストを抑える
仕様書は意思疎通手段であり、仕様書を作ることが目的ではありません。
なるべく低コストで作ることを目指します。
メンテナンスコストも意識し、古い仕様書はメンテナンスしなくても良い仕組みにします。

### 機能ごとに考える
画面ありきで考えると、本質的な課題が議論できなくなることもあります。
機能を考え、機能を書きます。

### デザインとは切り離して管理する
仕様書は機能を管理し、デザインは他のツールで管理します。
また、仕様は変更せずにデザインのみ変更することが多々あり、その都度仕様書を更新するのはコストがかかります。
画面に依存する仕様がある場合は、仕様書に書きます。

### 履歴を書かない
履歴を見るのはコストがかかります。
履歴を見ないでも理解できるように仕様を書きます。
どうしても履歴管理が必要な場合はツールに任せます。

### 経緯を書く
履歴ではなく、経緯です。
例えば、「法務観点でログインをAからBに変更した」など、どうしてこの仕様になっているのか Why を書きます。

### 議事録的に更新する
仕様書の更新にはコストがかかります。
コストを減らすため、仕様を決めたタイミングで、同時に仕様書を更新します。
更新したら、メンバーに周知します。

### 概念図や箇条書きは使いすぎず、文章で書く
一般的に、図や箇条書きにすると情報量が落ちるため、基本的には文章で書きます。
文章とセットで、補足で図を書くのはとても有用です。

### レビューする
仕様書をFIXさせる前に全職種がレビューし、認識のズレや仕様漏れがないかレビューします。

### 100%の仕様書を作ろうとしない
仕様書はあくまで手段です。
ある程度の認識ズレが発生することを許容して、ミスに気づける・カバーできる仕組みを作ったほうが、結果的に低コストになります。

### 階層構造で管理する
機能単位で管理します。
1つの機能が複数の画面にまたがることもあれば、複数の機能が1画面に入ることもあります。

#### Good
仕様書（機能単位）
｜
├共通
｜　├ライフサイクル
｜　└URLスキーム
｜　
├Version 1.0.0
｜　├新規登録機能
｜　├ログイン機能
｜　├ユーザー名変更機能
｜　└メールアドレス変更機能

#### Bad
仕様書（画面単位）
｜
├共通
｜　├ライフサイクル
｜　└URLスキーム
｜
├登録系
｜　├新規登録
｜　｜　├メールアドレス入力画面
｜　｜　└本人確認画面
｜　└ログイン
｜　　　├...
｜　　　
└マイページ
　　├ユーザー名変更画面
　　└メールアドレス変更画面

## おすすめツール
### Notion
#### Good
誰でも簡単に編集できます。
汎用性が高く、仕様書以外の情報も一括で管理できます。

#### More
リスト管理が得意ではないため、Googleスプレッドシートとの併用を推奨します。
汎用性が高すぎて自由に編集できてしまうため、運用ルールをしっかり決める必要があります。

### Confluence
#### Good
誰でも編集できます。
汎用性が高く、仕様書以外の情報も一括で管理できます。
Atlassian系サービスとの連携が強いのも強みです。

#### More
編集するために編集モードに入る必要があるため、編集のための敷居が少し高めです。

### Git
#### Good
社内サーバーで管理できるため、セキュリティ要件が高い会社でも使えます。
Markdownで書けばブラウザから簡単に見え、履歴管理もできます。

#### More
学習コストが高く、編集の敷居も高いです。
エンジニア職以外に普及させるのは難しいかもしれません。

## 仕様書テンプレート紹介
実際の仕様書は公開できませんが、簡単な仕様書テンプレートを紹介します。
プロジェクトによってカスタマイズして使えると思います。

```
# 概要
一行程度で機能を説明する
一行で説明できない場合は複数の機能が含まれている可能性が高いので、複数の仕様書に分割できないか考える

# 背景・目的
分析を元にした課題感と経緯を書く

# 目標
ユーザーゴールとビジネスゴールを書く
この目標を達成することが、この仕様書の目的になる

# 仕様
仕様を書く
エンジニアリング観点によりすぎず、誰でも理解できる言語で書く
議論した結果、しないと決まったことも書く

## インプット

## アウトプット

## 処理A

## 処理B

## 想定するエラー処理

## しないこと

# 実装詳細
実装時に注意する必要がある観点を書く
エンジニアリング言語で書く

# デザイン
デザインファイルへのリンクを貼る
デザイン仕様を書く

# ユビキタス言語
この仕様で新しく定義する言葉について説明を書く

# テスト
想定するテスト内容と方法を書く

# データ分析
分析観点を書く
目標を達成できたか判断できるように書く

# 参考リンク
関連する議事録等への参考リンク集
```

## More
仕様書の作成・テスト設計の難易度が高いため、ドキュメントを書くリテラシが求められます。
反面、全員で仕様を考えるため、チームの成長にも繋がると思います。

仕様を細かく書いていないため、エンジニア間での認識ズレは発生します。
このあたりは仕様書作成にかけるコストと相談です。
Slackのメモを種別ごとに整理する(API/bot不使用)

Slackの情報を整理するため方法の一つとしてリアクションが使えます。
APIやbotを使わない方法なのでどなたでも使えるかと。


# TL;DR
* 気になったメモやリンクをSlackにまとめているが、種別ごとに整理されていなかったので探すのが大変だった
* 投稿に対して、種別ごとにリアクションをした
* ``` has::book:```などでメモを種別ごとに検索できるようになって幸せ


# やり方
1. 気になったメモやリンクを投稿する
1. 種別ごとにリアクションをする
1. slackの検索枠で ```has:絵文字``` で検索する


検索チャンネルも絞りたい場合は、``` in:#channel_name```
時期も絞りたい場合は ```after:12/31/2019``` (←2020年1月1日以降の投稿検索) ```during:12月``` (←12月内の投稿検索。年情報は適宜補完される)

その他は[Slack内で検索する(Slack公式)を参照](https://slack.com/intl/ja-jp/help/articles/202528808-Slack-%E5%86%85%E3%81%A7%E6%A4%9C%E7%B4%A2%E3%81%99%E3%82%8B)

よいSlackライフを！

※TL;DRを書くまでもなかったですね笑
[Rails] アプリケーションの型作成　データベース作成　サーバー起動

まず初めに、サーバーサイドの準備を整えます。
サーバーサイドという箱には、[アプリケーション] [データベース]という２つのオブジェクトを入れてあげる必要があります。

*それでは、サーバーサイドを立ち上げる際の初期操作を３つ見ていきましょう*

①アプリケーションの型作成
---

「　rails　version　new　アプリケーション名　-d データベース管理システム名　」



②データベース作成
---

「　rails　db : create　」



③サーバー起動
---

「　rails　s　」　　※control + C でサーバーを停止できます。
Elasticsearchでコサイン類似度を求める

M2のmarutakuです。カレンダーが全然埋まらなくて困ってます。どんどん参加登録してくださいお願いします。
今回は、過去に自分が作ろうとした画像検索のシステムでElasticsearchを使ってコサイン類似度を求めた話をします。
## コサイン類似度について
コサイン類似度は、ベクトル同士の類似度を比較するために用いられます。数式は他のサイトでよく開設されているので割愛します。Word2Vecで、単語の類似度を測るときに使われています。gensimを使っているときは、`gensim.models.Word2Vec.most_similar`でコサイン類似度を求めると思います。しかし、Pythonでコサイン類似度を比較する処理を書くと遅くなりがちな気がしています。
そんな時にElasticsearchの登場です。

## Elasticsearchについて
Elasticsearchはオープンソースの検索エンジンです。 大量のデータから高速に検索を行うことができます。全文検索や、ログ収集・可視化などに用いられています。Dockerの環境も用意されていて、手軽に試せるので是非試してみてください。

https://www.elastic.co/jp/blog/text-similarity-search-with-vectors-in-elasticsearch
上記に記事にもあるように、Elasticsearch7.0からベクトルを格納することができるようになり、Elasticsearch7.3からベクトルのドキュメントスコアリング向けの使用をサポートはじめました。これにより、Elasticsearch内でコサイン類似度を算出できるようになりました。

## Elasticsearchを用意する
ElasticsearhはDockerイメージが用意されているので、今回はそのイメージを使用したいと思います。以下はdocker-composeで使用するdocker-compose.ymlの内容です。

```yml
version: "2.3"
services:
    elasticsearch:
        image: "elasticsearch:7.5.1"
        ports:
            - "9200:9200"
        volumes:
            - es-data:/usr/share/elasticsearch/data
        tty: true
        environment:
            discovery.type: single-node
volumes:
    es-data:
        driver: local
```

Elasticsearchでは、MySQLでテーブルを定義するように、あらかじめデータの構造を定義する必要があります。この定義のことをMappingと呼びます。以下は、過去に自分が画像の検索システムを作る時に使ったMappingです。
ベクトルは`dense_vector`というフィールドタイプで、ベクトル長はあらかじめ指定しておく必要があります。

```
{
    "mappings": {
        "properties": {
            "item_url": {
                "type": "text"
            },
            "item_description": {
                "type": "text"
            },
            "image_vector": {
                "type": "dense_vector",
                "dims": 512
            }
        }
    }
}
```

## Pythonでデータを挿入する
Pythonを使ってデータを入れてみようと思います。
ElasticsearchをPythonで操作するためのモジュールが提供されているので、まずはそれをインストールします。

```bash
pip install elasticsearch
```

Elasticsearchのなかにデータを入れます。

```python
from elasticsearch import Elasticsearch

INDEX_NAME = 'test_index'
es_client = Elasticsearch(host=es_host, port=es_port)

def insert(tensor, item_url, item_description):
    es_client.index(index=INDEX_NAME, body={
        "item_url": item_url, "item_description": item_description, "image_vector": tensor
    })
```


## 検索してみる
データを格納することができたら実際に検索をしてみます。

```python
def search(vector):
        query = {
            "script_score": {
                "query": {"match_all": {}},
                "script": {
                    "source": "cosineSimilarity(params.image_vector, doc['image_vector']) + 1.0",
                    "params": {"image_vector": vector}
                }
            }
        }
        response = es_client.search(
            index=INDEX_NAME,
            body={
                "size": 5,
                "query": query,
                "_source": {"includes": ["item_url", "item_description"]}
            }
        )
        return response
```

これで検索することができます。
自分の環境では、約1万件の512次元のベクトルから類似したものを検索するのに40ms程度でした。多分とっても速いと思います。

## 終わりに
今回はElasticsearchでコサイン類似度を求めてみました。
Pythonでやるよりも高速なので是非試してみてください。
Windows robocopy

#ドライブまるごとバックアップ同期
```
# Cドライブ
robocopy C:\ F:\drive_C /MIR /R:0 /NP /TEE /NFL /NDL /V /XD "System Volume Information" "$RECYCLE.BIN" "C:\Windows" /XF "pagefile.sys" /LOG+:"C:\temp\task\log\copylog_drive_C_error.log"
attrib -S -H "F:\drive_C"

# Dドライブ(データディスク)
robocopy D:\ F:\drive_D /MIR /R:0 /NP /TEE /NFL /NDL /V /XD "System Volume Information" "$RECYCLE.BIN" /XF "pagefile.sys" /LOG+:"C:\temp\task\log\copylog_drive_D_error.log"
attrib -S -H "F:\drive_D"

```
Kotlinで複数の変数をnullチェックしてから処理を実行したい

# guard letとif let
KotlinにSwiftにあるような`guard let`と`if let`が欲しいときのサンプルです。
また、この記事で検証したKotlinのversionは`1.3.72`です。

## guard let is 何？
引数のいずれかにnullがあると処理を実行する。
早期リターンとかでよく使います。

## if let is 何？
引数すべてがnullではなかった時に処理を実行する。

# ソースコード
[StackOverflow](https://stackoverflow.com/questions/35513636/multiple-variable-let-in-kotlin)より引用しました。

## extendedLet.kt

```kotlin
package hogehoge.common

inline fun <T: Any> guardLet(vararg elements: T?, closure: () -> Nothing): List<T> {
    return if (elements.all { it != null }) {
        elements.filterNotNull()
    } else {
        closure()
    }
}

inline fun <T: Any> ifLet(vararg elements: T?, closure: (List<T>) -> Unit) {
    if (elements.all { it != null }) {
        closure(elements.filterNotNull())
    }
}
```

# 備考その1
Kotlinはクラスやオブジェクトでなくても直接関数を定義できるので`common`パッケージ的なものを作成して
`extendedLet.kt`みたいなファイルを作って入れておけばそのプロジェクト全体で使えるようになるので便利です(依存/結合度気にしなければ)。

実際に使用するときは

```kotlin
import hogehoge.common.ifLet
import hogehoge.common.guardLet

// example
fun guardLetSample(var1 : Float?, var2 : Float?, var3 : Float?) {
    // var1,var2,var3いずれかがnullなら早期リターンする
    // 戻り値のvar1, var2, var3はアンラップされている
    val (var1, var2, var3) = guardLet(var1, var2, var3){ return }
    
    // 本来の処理
}

fun ifLetSample(var1 : Float?, var2 : Float?, var3 : Float?) {
    ifLet(var1, var2, var3){ (var1, var2, var3) ->
        // var1, var2, var3いずれもnullでないなら実行する処理
        // var1, var2, var3はアンラップされている
    } 
}
```
みたいな感じでimportしてあげればいいんじゃないかと思います。

# 備考その2
ifLetの要素が6個以上になると`Destructuring declaration initializer of type List<Float> must have a 'component6()' function`とかいって怒られる。

## extendedDestructingDeclations.kt

```kotlin
package hogehoge.common

// Destructuring Declarations - Kotlinはcomponent5までしか用意してないので6以降は自作する必要がある？
operator fun <E> List<E>.component6(): E {
    return this[5]
}
```

[この記事](https://qiita.com/komitake/items/f1ea203737d5c9a6c2a6)によると、この呼び出しは`Destructuring Declarations`という仕組みで行われていて、
Collectionクラスではcomponent5までしかpredefineされていないとのこと(実際エラーで怒られた)。
なので、同様にcomponent6以降の関数を自作する必要があるみたいです。

また実際に使用するときは下記のようにimportしてあげないとダメです。

```kotlin
import hogehoge.common.component6
```

# 参考
- [Multiple variable let in Kotlin - Stack Overflow](https://stackoverflow.com/questions/35513636/multiple-variable-let-in-kotlin)
- [Destructuring Declarations in Kotlin（社内勉強会用） - Qiita](https://qiita.com/komitake/items/f1ea203737d5c9a6c2a6)
- [Destructuring Declarations - Kotlin Programming Language](https://kotlinlang.org/docs/reference/multi-declarations.html)
Teratermマクロで自動ログイン

業務でサーバにログインする際毎回IPアドレスを入力するのが面倒だったのと、ミスを減らすために自動でログインできるようにしてました。

やり方はほかにもいろいろあると思いますが、とりあえずこのやり方を記録として残します。

```login.ttl
;ログインするサーバのIP
HOSTDOR = 'xxx.xxx.xxx.xxx';
;ユーザー名
USERNAME = 'foo';
;パスワード
PASSWORD = 'bar';

COMMAND = HOSTDOR
strconcat COMMAND':22 /ssh /2 /auth=password /user='
strconcat COMMAND USERNAME
strconcat COMMAND ' /passwd='
strconcat COMMAND PASSWORD

connect COMMAND

wait '$'

end
```
macOS Big SurのHomebridge pluginでBluetoothを使用する方法

この記事は、ハンズラボ Advent Calendar 2020 5日目の記事です :snowman:

# はじめに
ハンズラボのPOSチームでテックリードをしている @zizi4n5 です :snowboarder:
macOS Big Surにアップデートしたところ、私が開発しているHomebridge pluginの[Homebridge SwitchBot](https://github.com/zizi4n5/homebridge-switchbot-for-mac)が動作しなくなったという報告がありました。[^1]

https://github.com/zizi4n5/homebridge-switchbot-for-mac/issues/23
![スクリーンショット 2020-12-04 15.27.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63892/e6177cb5-755f-436a-dcc9-59e40c3a6334.png)

この時に調べた原因、解決方法などについて共有したいと思います。


# 原因

macOS Big Surでは、**[設定]-[セキュリティとプライバシー]-[プライバシー]**の項目に**Bluetooth**が追加されており、Bluetoothを利用する場合はユーザーの許可が必要になったことが原因でした。
![bigsur-security-privacy-bluetooth.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63892/c3a3db42-9c5d-1834-f216-12f6c9a9579e.png)


# 解決方法

現時点では以下の対応でHomebridge pluginが正常に動作することを確認しています。

1. HomebridgeのRuntimeであるNode.jsバイナリを**[設定]-[セキュリティとプライバシー]-[プライバシー]-[Bluetooth]**に手動で追加する
2. Homebridgeを再起動する

![bigsur-security-privacy-bluetooth-node.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63892/e4caad6c-7021-f28a-6ee2-20e168f9bcf9.png)

なお、利用を許可するNode.jsバイナリのパスには気をつけてください。
homebrewでインストールしたNode.jsを利用している場合は、`/usr/local/bin/node` ではなく、 `/usr/local/Cellar/node/x.x.x/bin/node`を明示的に指定する必要があります。


# 最後に

以上で、macOS Big SurでもHomebridge pluginからBluetoothを使用できるようになります！
ちなみに、1日目にもHomebridge関連の記事[**「1,980円（Raspberry Pi Zero W）で Homebridge 環境を作ろう！」**](https://qiita.com/zizi4n5/items/1683d3c3a62eee2cdbb2)を書いたので、よかったら読んでみてください！

なお、今回はBluetoothについて取り上げましたが、Big Surから「プライバシー」環境設定に**Media & Apple Music**、**HomeKit** といった項目も追加されています。
「プライバシー」環境設定の詳細について興味がある方は、Apple公式サイトを参照してみてください。

* [Macの「プライバシー」環境設定を変更する](https://support.apple.com/ja-jp/guide/mac-help/mh32356/11.0/mac/11.0)


# 参考情報
* [Homebridge](https://github.com/homebridge/homebridge)
* [Homebridge SwitchBot](https://github.com/zizi4n5/homebridge-switchbot-for-mac)
* [Macの「プライバシー」環境設定を変更する](https://support.apple.com/ja-jp/guide/mac-help/mh32356/11.0/mac/11.0)
バイナリーサーチについて

## バイナリーサーチとは？
　ソース済みのリストや配列に入ったデータに対する検索を行うときに用いられる手法。
　まずは中央値を確認し、検索したい値との大小関係を用いて検索したい値が中央の値の右にあるか、左にあるかの判断を繰り返し片側には存在しないことを確かめながら検索する手法。

## 記述例

```ruby
 def binary_search(array, number_of_elements, target)
  left = 0
  right = number_of_elements - 1
  while left <= right
    center = (left + right) / 2
    if array[center] == target
      return center
    elsif array[center] < target
      left = center + 1
    else
      right = center - 1
    end
  end
  return -1 
end

array=[1,3,5,6,9,10,13,20,26,31]

puts "検索したい数字を入力してください"
target = gets.to_i
number_of_elements = array.length

result = binary_search(array, number_of_elements, target)

if result == -1
  puts "#{target}は配列内に存在しません"
else
  puts "#{target}は配列の#{result}番目に存在します "
end
git ~コンフリクト が起こる前、起こった後~

## はじめに
プログラミングバイトをしていて、自分の作業スピードが早くないのは技術不足という要因もあるが、gitの扱いに慣れていない、知識が十分にないという要因もあるということに気づいたのでgitに関するアウトプットを増やしていく。
今回の記事はバイト先で『この前出してもらったマージリクエストコンフリクト 起こしてるよ』と言われることに恐怖を覚えている人向けになっている。バイト先ではgitlabを使用しているのでプルリクエストのことをマージリクエストと呼ぶ。
コンフリクト を起こしてしまうと、業務の予定がくるってしまうのでできるだけ起こしたくない。今回の記事ではコンフリクト を起こさないための対策とコンフリクト が起こってしまった際の対処についてまとめる。
なお、コンフリクト を起こさないための対策に関しては自分も実践したことがなく、以下のサイトを参考にまとめた。
[コンフリクト させないための覚書](https://kojimanotech.com/2019/09/26/189/)

## コンフリクト とは？
コンフリクト はファイルの同じ箇所を編集したためにマージすることが出来なくなってしまう現象のことである。タイミングとしては一通りの作業を終え、マージリクエストを投げた際に起こる。

## コンフリクト を起こさないためには
現在作業している作業ブランチをworking_branchとして、統合ブランチをkitchenブランチとする。
自分の作業用ブランチを切った後に統合ブランチkitchenが更新されているとマージリクエストを出す際にコンフリクト が起こってしまう可能性がある。（自分と同じ部分を編集したブランチがマージされているかもしれないため）コンフリクト を防止するための手順を示す。

#### 作業内容をコミットする
```
git status
```
自分の作業状況の確認。

```
git add -p
```
addする。pオプションは差分を確認しながらaddすることができるのでお勧め。

```
git commit -m "コミットメッセージ"
```
コミット。

#### ローカルの統合ブランチkitchenを最新の状態にする
```
git checkout kitchen
```
kitchenにブランチ切り替え。

```
git pull
```
プルして最新の状態に。

```
git checkout working_branch
```
作業ブランチにチェックアウト

```
git merge kitchen
```
最新のkitchenを作業ブランチにマージ。

このタイミングでコンフリクト が起こる可能性がある。これをローカルで解消する。結局コンフリクト が起こるなら一緒じゃないかと思う人もいるかもしれないが、コンフリクト が起こるかもしれないという気持ちで投げるマージリクエストと、コンフリクト が起こらないことがわかって投げるマージリクエストでは次の業務に取り組む心持が変わってくると思う。
ここで注意しておきたいのが入力側の内容も取り込んでおかないとマージリクエストを出すときまたコンフリクト が起こってしまうので注意。

## コンフリクト が起こってしまったときの対処

先ほどまではマージリクエストを投げたときにコンフリクト を出さないための対策についてまとめていたが、それでもコンフリクト が起こってしまう可能性はあると思う。ここではコンフリクト が起こってしまったときの対処について述べる。

マージリクエストを投げたらコンフリクト が発生したことを知らせる表示が出てしまった！！
![スクリーンショット 2020-12-04 11.06.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574301/afa5538d-0de0-d19f-11f4-b126622734cc.png)

このときの対処をまとめる。

ローカルのkitchenを最新にする

```
git checkout kitchen 

git pull

git checkout working_branch
```

作業ブランチにマージする

```
git merge kitchen 
```

ここでコンフリクト した部分がエディタに反映されるので適切にコンフリクト を解消する

addする←gitにコンフリクト を解消したことを知らせる

```
git add コンフリクトを解消したファイル 
```

commit,pushする

```
git commit 
git push origin 作業ブランチ
```
これで問題なければコンフリクト解消できると思う。

## さいごに

コンフリクト を起こさないための対策は自分自身も業務内で実践してなんらかの知見を得ることが出来たらまた追記しようと思う。
RSpecを使った四則演算の構文

#はじめに
RubyやRailsでポートフォリオを作成していく上で、避けては通れないテスト実装。
Railsの標準装備はMinitestですが、実際の現場で使うことを考えて、RSpecを採用される方が多いと思います。

そこで、
「RSpecとはどういうものなのか？」
ということを、基本的な四則演算の構文を見ながら解説していきます。

#対象
これからRSpecを学ぼうと思っている人

#環境
Ruby 2.6
RSpec 3.9

#RSpecの構文例

``describe``は、国語でいうところの『章』のような意味合いです。
「この章では、いったいどんなテストコードが書かれているのか？」ということを表しています。

``it A do``で、「Aという結果をもたらすテストコードである」という意味を表します。

``expect X.to eq Y``で、「X = Y」という意味を持ったテストコードになります。
``eq``はマッチャと呼ばれ、「=」にあたる意味を持っています。

例を見ていきましょう。

```ruby
Rspec.describe '四則演算' do

 describe '足し算' do
  it '1 + 1 は 2 である' do
  expect(1 + 1).to eq 2
  end
 end

 describe '引き算' do
  it '2 - 1 は 1 である' do
  expect(2 - 1).to eq 1
  end
 end

 describe '掛け算' do
  it ' 2 × 3 は 6 である' do
  expect(2 * 3) to eq 6
  end
 end

 describe '割り算' do
  it '6 ÷ 2 は 3 である' do
  expect(6 / 2) to eq 3
  end
 end

end
```

逆に間違っていることを期待する場合には、``not to``を使います。

```ruby
Rspec.describe '四則演算' do

 describe '足し算' do
  it '1 + 1 は 3 ではない' do
  expect(1 + 1).not_to eq 3
  end
 end

 describe '引き算' do
  it '2 - 1 は 0 ではない' do
  expect(2 - 1).not_to eq 0
  end
 end

 describe '掛け算' do
  it ' 2 × 3 は 8 ではない' do
  expect(2 * 3).not_to eq 8
  end
 end

 describe '割り算' do
  it '6 ÷ 2 は 2 ではない' do
  expect(6 / 2).not_to eq 3
  end
 end

end
```

#おわりに
RSpecは、独自の構文のため、中々とっつきづらいかと思われます。
まずは分かりやすい構文から理解し、RSpecに慣れていきましょう。
デザイナーがM1のMacBookAirで満足できるか

![201203_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/866776/13e87ce8-9380-dede-d5c3-f67132bfe2ca.png)
土曜日の昼下がり、玄関先でごそっと物音をたてて、金属のラックが少し揺れた。
置き配用の金属ラックの3段目、飾り気のない段ボールをひとつ。その中には見覚えがあるソリッドの立った白い箱があり、それを右隅からビニールを心地剥がすと前回の記憶が蘇る。

**──正直そこまで期待していなかった**
世間的には「奇跡的だ」「魔法の絨毯だ」とブログ、YouTube界隈で過剰に騒ぎ立てて、疑心暗鬼になっていたが、旧MacBookから移行アシスタントが終了し、10分後にはその考えが覆った。

**──感想は「テスラ・モーターズ」**
起動速度、静音性、バッテリー性能、発熱性、どれをとっても新しく感じ、触った感想は「テスラ」（乗ったことないけど）。昨日まで使用していたMacはリッター15kmのワゴンだと感じた。もちろん、Rosetta2を還してのアプリケーションも多く、ユニバーサルバージョンにまだ移行していないアプリでこの速度だと半年後がさらに楽しみになってくる。

**──Apple M1チップ**
このプロダクトはAppleが独自で開発した「M1チップ」に集約されていると言っても過言ではない。（というか、他はほとんど変わっていない）プロセッサ、I/O、セキュリティ、メモリなどを1枚のシステムオンチップ（SoC）に集めたのがM1チップで効率が上がり、驚異的な性能を発揮している。またiPhoneやiPadに搭載されているプロセッサーが同じということもあり、iPhoneやiPadのアプリケーションも動かせるのも大きい。
![ 2020-12-04 9.33.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/866776/e1c9f2c6-4c8e-c972-6419-8d1193584983.png)

**──飛ぶように早い**
驚くのが2019年に販売された、ほとんどのMacのよりも早いということ。まず初速度が違う。これはユニファイドメモリアーキテクチャ（UMA）から来たもので、専用パッケージの中にある1つのプールに入れて、SoCにあるデータにアクセスでき、複数のメモリプールの間でデータをコピーする必要がなくなったためだと思われる。
![ 2020-12-04 10.03.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/866776/8fd9b962-8e36-9512-48fb-56337170d67b.png)

**──静寂そのものの**
筆者がこのMacBookAirに「テスラ」のメタファを用いるのはファンそのものがない静寂性を上げている。どれだけ負荷をかけた作業をしていても一切の音がしないのだ。想像して欲しい。今持っているiphoneにyoutubeなどで負荷をかけると高周波でファンのが鳴り出したら気が狂う。そう考えるとファンがある元のMacには戻れない。
![ 2020-12-04 9.31.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/866776/39af59b0-1536-7b7b-67a3-b05152a24262.png)

**──デザイナーはメイン機として使用できるか**
正直、世の中の90%ぐらいのデザイナーは一番安いモデル（12月3日時点で104,800円（税別））で満足できると思う。SSDの容量はクラウドで補完すれば良い。メモリは8GBと心許ない感じがするが、SoCにメモリが統合された「ユニファイドメモリ」が効率的に作用する。たとえスワップしたとしても、SSDの性能が向上でカバーできている。

**──購入すべきデザイナー（2つ以上該当する場合）**
　・所有Macのマルチコアベンチマークが3,500以下（https://browser.geekbench.com/mac-benchmarks ）
　・Macのメモリが8GB以下
　・macOS Big Surにアップデートをしている（予定がある）
　・20インチ以上のディスプレイを所有している（予定がある）
　・すごくお金がある人

**──プロとアマチュアの境界が消えていく**
今まで、Macで「Pro」を所有するというのは、デザイナーの自己顕示欲のようなものだったのは間違いない。30年ほど前、MacintoshはDTPの道を切り開き、デザイナーの道具の境界線を消してきた。それ以前は1mmの線の上に10本の線を烏口で引くことや、写植、活版など知識、技術がなければ、印刷物などに辿り着かなかったから。しかし、今現在では20万円ほどでプロと並ぶほどの道具は揃えられるし、ある程度PCを触れる主婦なら、3日ほどでラクスルへ入稿できる。そういった意味で確実にハードルが下がってきている。そういった中で、デザイナーはこれからどのようなバリューを提供していかなければいけないか、考え直す必要があると思う。
![ 2020-12-04 10.26.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/866776/c5eca82f-eb05-c545-ad78-df5de90a5c24.png)
Railsでスクレイピングしてみた（Mechanize)

## Railsでスクレイピングを実行してみた。
今回はrailsでスクレイピングを実行した流れを説明していきたいと思います。
gemを導入するだけで機能自体は使えるのですが、そこからが難しいというのが自分の印象でした。。。。。

##Mechanizeの導入
Gemfileに下記のように入力します。

```
gem 'mechanize'
```

ターミナルでbundle installを実行します。

```
bundle install
```

スクレイピングをするためのモデルを作成。
ターミナルで

```
rails generate model Scraping
```

Scrapingモデルを作成します。

scraping.rbファイルが作成されるので、下記のように記述します。


```ruby:Scraping.rb
require 'mechanize'

def self.scrape
      agent = Mechanize.new                 
      page = agent.get("https://www......")  　#ここには自分がスクレイピングしたいURLを記述
      elements = page.search('div h1') 　#search()には自分が取得したい箇所のタグ情報を記述します。cssのように指定したらいけます。
      elements.each do |element|       
        anime = Anime.new              #Animeは任意のクラス。ここでは、animeは任意のインスタンスです。       
        anime.title = element.inner_text　#この箇所では。animeのtitleカラムにelementのインナーテキスト（このように記述することで中の文を取って来れます）
        anime.save
      end
    end
end
```

ここで大事なのが、先頭で**require 'mechanize'**と宣言することです。

その後ターミナルで下記を実行します。

```
 rails c
```
でコンソールの中に入り

```
 Scraping.scrape #scrapeはscraping.rbで宣言したメソッドの名前です。
 ```


これでスクレイピングが実行されるはずです。



個人的に苦戦したのが。page.searchでタグを指定するところです。これは取得したいページの構成にもよるかと思うのですが、なかなか自分の欲しいところだけを取ってくるのは難しいです。試行錯誤するしかないですね:v:

なお、初投稿＆初心者中の初心者なので、間違っている部分や分かりにくい部分があったら申し訳ありません。
これから精進していきます！

参考サイト
https://qiita.com/tsubasaweb1/items/5be78cefed67020ac483
https://qiita.com/takuyanin/items/01256773e1cbfc84f51a
複数のライブラリを入れた場合にResultが干渉してエラーが出てしまうケース

複数のライブラリを使用していると
別々のライブラリで同じ命名が使われている場合にエラーが出ます。

今回はもともとNukeを使っていて、そこにURLEmbeddedViewを
追加導入したところ、下記コードにて

```swift
Nuke.loadImage(
    with: imageURL,
    options: ImageLoadingOptions(),
    into: cell.fullImageView, progress: nil) {
        (result: Result<ImageResponse, ImagePipeline.Error>) in
```

このようなエラーが発生しました。

```
Generic type 'Result' specialized with too many type parameters (got 2, but expected 1)
```

Xcodeでエラーを詳しく見てみましょう。
左パネルの①のあたりをクリックすると原因箇所に飛ぶことが出来ます。

![CleanShot 2020-12-04 at 11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6678/e29feca2-df9f-8244-9995-9820a49767f3.png)

②のあたりを見てみるとURLEmbeddedViewは独自にResultというenumを定義していますね。
ところでSwiftは5系になってからResultという機能を実装しました。

NukeはSwiftのResultを使っています。
SwiftのResultとURLEmbeddedViewのResultが干渉してしまっているのですね。

Xcodeから見るとResultと書かれても
Swift.ResultかURLEmbeddedView.Resultかわかんないわけです。

なので普段は省略しているSwift.Resultという風にどの名前空間なのかを
明示してあげることでXcodeが迷わなくなるって感じです。

というわけで、こんな風にすると修正できました。

```swift
Nuke.loadImage(
    with: imageURL,
    options: ImageLoadingOptions(),
    into: cell.fullImageView, progress: nil) {
        (result: Swift.Result<ImageResponse, ImagePipeline.Error>) in
```

参考資料：
- [Result | Apple Developer Documentation](https://developer.apple.com/documentation/swift/result)
- [【Swift】Result型を使ってみた](https://qiita.com/st43/items/d4b9a62d93af7c3ade9f)
kindle for macでログインしているはずなのにライブラリに本が表示されない

### 起きていたこと
きちんとkindle内でamazonのアカウントでログインしているのにも関わらずライブラリに何も表示されずにいました。
状況としてはこんな感じです。

- 今まで、kindle端末でもkindleformacでもきちんとライブラリが見れていた
- 新しく購入したmacで今回の事象が起きている


### 解決法
amazon.comとamazon.co.jpに同じidのアカウントを持っていたので、片方のidを変更して、co.jpのidでログインしてみたところ、ライブラリが想定通り表示された。

### 原因？(多分)
あくまで想像ですが、、

- amazon.co.jpとamazon.comに同じid,pwでアカウントを持っていた
- ログインのタイミングとアカウント作成のタイミングの問題？以下時系列

1. 過去のmacではkindleForMacでログイン出来ていた
2. おそらくその後amazon.comのアカウントを同じid,pwで作成した
3. 新しいmacでkindleForMacにログイン
4. amazon.co.jpではなくamazon.comのアカウントの内容が参照されてしまった・・？

### そんなことあるの・・？
.comのDBのテーブル方に一回アカウントあるかチェックしてその後co.jpの方でアカウントあるか見てるってことなの・・？
Windows Terminalを使用してsshでWindows Serverに接続

次に使う機会があるときのために記録

## sshクライアントの確認
Windows 10なら標準でOpenSSHクライアントが入っているので、すぐ使えるようです。
見つからない場合は"機能の追加"からインストール

## sshでServerに接続
ここでは詳しく説明しません。(面倒なので……)
解説はいろいろあるので、以下を参考に調べてください。

[Qiita: ssh windowsの検索結果](https://qiita.com/search?q=ssh+windows)

## settings.json
Windows Terminalからssh接続する設定は以下のようにしています。

```json
{
    "profiles":
    {
        "list":
        [
            {
                "guid": "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}",
                "name": "ssh",
                "tabTitle": "ssh",
                "commandline": "ssh -t username@hostname powershell",
                "colorScheme": "Monokai Night",
                "fontFace": "FiraCode Nerd Font Mono Retina",
                "backgroundImage": "spacecat.png",
                "backgroundImageOpacity": 0.5
            },
            略
        ]
    },
    略
}
```
### guid
powershellから`New-Guid`コマンドレットを実行すると新しいGUIDを取得できるので、これを使います。

### commandline
`username@hostname`は自分の環境に合わせて設定してください。
それだけだとコマンドプロンプトに入ってしまうのですが、powershellを実行するように指定しておけばServer側のpowershellに入れます。
コマンドを変えればPowershell CoreやGitBashなどにも入れるかもしれません(試してません)

### その他パラメータ
`colorScheme`,`fontFace`は指定してあるけど反映されていません。
passphraseを確認する画面では反映されてるようなのですが。
`backgroundImage`,`backgroundImageOpacity`はバージョン1.xのどこかで反映され続けるようになりました。

## 初期設定スクリプト
`$PROFILE`を確認するとログインしているpowershellの初期設定スクリプトの場所が分かります。
とはいってもファイルは存在しないので、`New-Item -Type File filename`で新規作成してしまいましょう。
~~この節powershellの設定の話でwindows terminal関係ないのでは~~
RailsのDBをmysqlに変える(メモ)

RailsでデフォルトのDB'SQlite'から'mysql'(ver8.0.22)に変更する際に詰まったので、
mysqlインストールから実際にDB作成をするところまでの手順をメモ。

__1.mysqlインストーラでmysqlをインストール。__
http://dev.mysql.com/downloads/installer/
からインストーラをダウンロード。
![mysqlインストーラ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849880/46ad5084-a9a1-9ecf-4cd5-f585b7b1ddef.png)



__2.ダウンロードしたインストーラを起動。__
あとは流れに沿ってインストールしていく。(rootのパスワード設定等。)
そして、この流れの中で後にRailsからmysqlを起動しようとするとErrorになってしまう設定項目があった。それがこの設定。
![Authenticate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849880/4309ef31-4858-1393-5cc3-cc4c921fe2e6.png)

ここで上の認証方式を選択してしまうと、認証方式が'caching_sha2_password'になるが、Railsではこの認証方式に対応していないらしい。(この認証方式はmysql8で使用可能。)
なので、下の設定を選択して認証方式を'mysql_native_password'にする必要があった。

__3.gemファイルでmysqlをinstall。__

```ruby:Gemfile
# Use mysql as the database for Active Record
gem "mysql2"
```

```
bundel install
```

__4.railsアプリケーションのDB設定__

```yml:config/database.yml

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  host: localhost
  timeout: 5000

development:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  database: <%= ENV['DATABASE_DEV_NAME'] %>
  pool: 5
  username: <%= ENV['DATABASE_DEV_USER'] %>
  password: <%= ENV['DATABASE_DEV_PASSWORD'] %>
  host: <%= ENV['DATABASE_DEV_HOST'] %>

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  database: アプリケーション名_test
  pool: 5
  username: root
  password: <%= ENV['DATABASE_TST_PASSWORD'] %>
  host: localhost

production:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  database: アプリケーション名_production
  pool: 5
  username: アプリケーション名
  password: <%= ENV['アプリケーション名_DATABASE_PASSWORD'] %>
  host: localhost
```

のように変更。

__5.パスワードを環境変数で管理する。__
dotenvというgemをinstall。

```ruby:Gemfile
gem "dotenv-rails"
```

```
bundle install
```

アプリケーションのルートディレクトリに.envファイルを作成し、その中に環境変数を設定する。

```ruby:.env
 DATABASE_DEV_NAME = 'アプリケーション名_development'
 DATABASE_DEV_PASSWORD = 'パスワードを記入'
 DATABASE_DEV_USER = 'MySQLユーザー名を記入'
 DATABASE_DEV_HOST = 'localhost'
 DATABASE_TST_PASSWORD = 'パスワードを記入'
```

.gitignoreファイルに.envを追加する。

```ruby:.gitignore
# Ignore env config
/.env
```

※mysqlユーザを作成しておく。

ここで

```
rails db:create
```

完了。
---------------------------------------------------------------

※mysqlユーザを作成する。

1.mysqlに接続する。
コマンドプロンプトを管理者権限で開き、以下を実行する。

```
net start mysql80
```

```
mysql -u root -p
```

mysqlインストール時に設定したパスワードを入力。

2.実際にmysqlユーザを作成する。

```
mysql> create user 'test-user'@'localhost' identified by 'password';
```

3.mysqlユーザに権限を与える。

```
mysql> grant all on *.* to 'test-user'@'localhost';
```
RailsのSystem SpecでJavaScriptエラーを検出する方法

## はじめに

最近のWebサイトであれば、JavaScriptを利用していないページを探すほうが難しいかと思います。
そんな中で単純にRailsのSystem Specによる検証だけだと、テストを通ったのでリリースしたら実は以下のようなJavaScriptエラーが発生していたみたいな見落としが起こることが時々ありますよね。

![Image from Gyazo](https://i.gyazo.com/ae7387f9ff86a2fc7f29b047156cc44b.png)


解決方法としての理想はJavaScriptが影響する全ての箇所を網羅するようなテストを書くことかもしれませんが、現実的にはそこまで書けないというケースが多いかと思います。
また、全てを網羅していたつもりでも実際には漏れがあって本番環境のコンソールにJavaScriptエラーが表示されていたみたいなことは起こりえます。

そこで今回の記事ではRailsのSystem SpecでJavaScriptエラーを検出する方法を紹介します。

## 設定例

```ruby:spec/support/system_test.rb
module Capybara
  module Matchers
    class JsNoErrorMatcher
      def matches?(page)
        errors = page.driver.browser.manage.logs.get(:browser)
        errors.find_all { |error| error.level == 'WARNING' }.each do |error|
          STDERR.puts 'WARN: javascript warning'
          STDERR.puts error.message
        end

        @severe_errors = errors.find_all { |error| error.level == 'SEVERE' }
        @severe_errors.empty?
      end

      def description
        'have no js errors'
      end

      def failure_message
        @severe_errors.map(&:message).join("\n")
      end
    end

    def have_no_js_errors
      JsNoErrorMatcher.new
    end
  end
end

RSpec.configure do |config|
  config.include Capybara::Matchers, type: :system

  driven_by :selenium, using: :headless_chrome

  config.after(:each, type: :system) do |example|
    if example.metadata[:skip_js_error]
      # ログリセット
      page.driver.browser.manage.logs.get(:browser)
    else
      expect(page).to have_no_js_errors
    end
  end
end
```

※説明を簡単にする為に1ファイルにまとめて書いていますが実際は分けたほうが綺麗だと思います。

## 使い方

これまで通りSystem Specを実行することで、JavaScriptエラーが発生した場合には、発生したエラーメッセージが表示されてテストが失敗するようになります。

![Image from Gyazo](https://i.gyazo.com/f26eeb4ea758f2814e492d10be0d29e0.png)

もしも外部のスクリプトに依存している等の理由により、エラーを無視するしかないみたいなケースでは以下のように書くことで特定のテストだけJavaScriptエラーの検証をスキップすることが出来ます。

```ruby
it 'ログインできること', skip_js_error: true do
  visit root_path
  # ...
end
```

## まとめ

というわけで、この記事では「System SpecでJavaScriptエラーを検出する方法」を紹介しました。
既存のテストに設定を足すだけで、JavaScriptエラーに気付けるようになったり、不安定なテストの原因が特定しやすくなったりと役立つことが多いかと思います。
Emacsのコマンド操作



# 表の見方

C-xはCTRLキーを押しながらxを押すことを意味する．


# カーソル操作

| キー   | 動作内容           |
|:-------|:-------------------|
| C-a    | 行頭に移動．       |
| C-e    | 行末に移動．       　|
| C-p    | 一行戻る(上に移動)．　|
| C-n    | 一行進む(下に移動)．　|
| C-b    | 一文字戻る(左に移動)．|
| C-f    | 一文字進む(右に移動)．|
| ESC-<  | ファイル先頭に移動．　|
| ESC->  | ファイル末尾に移動．　|


# テキスト編集

| キー 　| 動作内容  |
|:-------|:----------|
| M-w    | コピー    |
| C-y    | 貼り付け　　|
| C-k    | 一行削除　　|
| C-x u  | 一つ戻る　|


# ファイル操作

| キー     | 動作内容　　　　|
|:---------|:-----------|
| C-x C-s  | ファイルの保存．|
| C-x C-w  | 別名で保存．　　|
| C-x C-c  | Emacsの終了．　|



------
 - **source** ~/grad_members_20f/members/Kazufumi0823/aa.org