OmniAICreator/Qiita-1.07M huggingface dataset:
【Firestore × JavaScript】配列フィールドに変数で指定した複数要素を追加・削除したい

こんにちは！

今回は「Firestoreで配列に要素を複数追加・削除」する方法について、JavaScriptを使った書き方を共有したいと思います。

公式ドキュメントの例だと一つの要素を追加（削除）する例しか見当たらなかったので、記事にしました。


### はじめに
以降の例では、以下の構成で`users`フィールドにデータを追加する場合で考えていきます。
`room`コレクション＞`room1`ドキュメント＞`users`フィールド（配列）

### （おさらい）配列フィールドに要素を追加する

配列に要素を追加したい場合、arrayUnion、arrayRemoveを使います。

#### 追加
```javascript
const db = firebase.firestore();
db.collection('users').doc('room1')
  .update({
    users: firebase.firestore.FieldValue.arrayUnion('user1'), // あusersフィールド（配列）に要素'user1'を追加
  });
```

#### 削除
```javascript
const db = firebase.firestore();
db.collection('users').doc('room1')
  .update({
    users: firebase.firestore.FieldValue. arrayRemove('user1'), // usersフィールド（配列）から要素'user1'を削除
  });
```

### 複数要素を追加したい場合（基本形）

`,（カンマ）`を使うことで、複数の要素を追加することができます。

#### 追加
```javascript
const db = firebase.firestore();
db.collection('users').doc('room1')
  .update({
    users: firebase.firestore.FieldValue.arrayUnion('user1', 'user2'), // usersフィールド（配列）に要素'user1','user2'を追加
  });
```

#### 削除
```javascript
const db = firebase.firestore();
db.collection('users').doc('room1')
  .update({
    users: firebase.firestore.FieldValue. arrayRemove('user1', 'user2'), // usersフィールド（配列）から要素'user1','user2'を削除
  });
```
### 複数要素を追加したい場合（変数を使いたい）
スプレッド構文`...array`を使うことで、複数の要素を追加することができます。

#### 追加
```javascript
const db = firebase.firestore();

const usersArr = ['user1', 'user2'];

db.collection('users').doc('room1')
  .update({
    users: firebase.firestore.FieldValue.arrayUnion(...usersArr), // スプレッド構文を使って、usersフィールド（配列）に`usersArr`の要素を追加
  });
```

#### 削除
```javascript
const db = firebase.firestore();

const usersArr = ['user1', 'user2'];

db.collection('users').doc('room1')
  .update({
    users: firebase.firestore.FieldValue. arrayRemove(...usersArr), // スプレッド構文を使って、usersフィールド（配列）から`usersArr`の要素を削除
  });
```


### さいごに

配列の要素追加・削除は`arrayUnion``arrayRemove`が便利です！

配列取得(get)→配列加工→更新(update)のように、排他制御的のためのトランザクションが必要なくなるので、積極的に使ってみてください。

### 参考
https://firebase.google.com/docs/firestore/manage-data/add-data?hl=ja
【Java Silver】(例外処理)try-catch-finally文とtry-with-resource文について

#try-catch-finally文とtry-with-resource文
どちらも例外処理を記述するための構文。

##**※例外処理とは**
Javaの例外には、Error、Exception(検査例外)、RuntimeException(非検査例外)がある。

・**Error**はプログラムでは対処できない問題（※**コンパイルエラーとは異なり**、あくまで**例外**）
・**Exception(検査例外)**は、例外発生時の処理を記述しないとコンパイルエラーが発生する問題
・**RuntimeException(非検査例外)**は、例外発生時の処理が任意の例外。
　Exceptionのサブクラスなので、先にExceptionをキャッチするcatchブロックを書いたあとで、RuntimeExceptionをキャッチするcatchブロックを書くと、到達不能コードとなりコンパイルエラーが発生する

##メソッドに例外を無視させる・メソッドから例外を発生させる

・**throws** : メソッド内で該当の例外が発生した場合、自信のメソッド内でcatchするのではなく、呼ばれる側に例外を投げる処理。**検査例外をスローするメソッド**は、**throwsでスローする可能性を宣言しなくてはならない。**

例）

```java
public test() throws IndexOutOfBounsException {
   //処理
}
```
→処理の過程でIndexOutOfBounsException が発生しても、testメソッドは無視。testメソッドを実行した側にIndexOutOfBoundsExceptionが発生する。

・**throw** : メソッドから例外を発生させる
例）

```java
public test(){
  throw new IndexOutOfWxception();
}

```
→testメソッドを実行すると、testメソッドにIndexOutOfWxception例外が発生する

#try-catch-finally文

・tryブロック：例外が発生する可能性がある処理
・catchブロック：例外が発生した時の処理
・finallyブロック：どのような場合でも一番最後に実行する処理

**【try-catch-finally文の例】**

※return処理は、finally文の実行後に行われる

```java
public class Main {
	public static void main(String[] args){
     System.out.println(test(null));  

    //finallyブロックの処理
    //引数がnullです

   //と表示される

     System.out.println(test(10));

  //引数の値は10
  //finallyブロックの処理
  //引数は有効でした

   //と表示される

  }

    public static String test(Object obj){
        try{
            System.out.println("引数の値は" + obj.toString());
        }catch(NullPointerException e){
            return "引数がnullです";
        }finally{
            System.out.println("finallyブロックの処理");
        }
        return "引数は有効でした";
    }
}
```



#try-with-resource文
例外が発生した時に、自動的にリソースの**closeメソッド**を呼び出して、**リソースを解放する**構文

**・処理の実行順**
①closeメソッドでリソースを解放する
②catchブロックの例外処理を行う
③finallyブロックの処理を行う

**※例外処理よりも先にリソースの解放を行う**

**【try-with-resource文の例】**
（Java Silver黒本より）

```java
public class Main {
	public static void main(String[] args){
     try(Sample s = new Sample()){
         throw new Exception();  //Exceptionを発生させる
     }catch(Exception e){
         System.out.println("A");
     }finally{
         System.out.println("B");
     }
  }
}

class Sample implements AutoCloseable{
    public void close() throws Exception{
        System.out.println("C");  //closeメソッド実行時にはCと表示される
    }
}

```

↓
「C　A　B」と表示される。
closeメソッド→catchブロック→fianllyブロックの順に実行されるため

参考）
[公式ドキュメント・AutoCloseableインターフェース ](https://docs.oracle.com/javase/jp/8/docs/api/java/lang/AutoCloseable.html)

> 閉じられるまで、リソース(ファイルやソケット・ハンドルなど)を保持できるオブジェクト。
AutoCloseableオブジェクトのclose()メソッドは、リソース指定ヘッダーでそのオブジェクトが宣言されているtry-with-resourcesブロックの終了時に自動的に呼び出されます。
この構築によって即時解放が確保され、それ以外の場合に発生する可能性のあるリソース不足例外およびエラーを回避できます。
iPhoneで四隅のタッチダウン反応が遅い問題の解決

# 問題
添付スクショのように画面端に配置したボタンから` UIControl.Event.touchDown`イベントを受け取ろうとすると、タッチダウンしてワンテンポ遅れてイベントがきます。

<img width="300px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149856/240bc178-b89d-0e14-705d-210e3d030439.png">

# 解決策
OSのジェスチャイベントが先に優先されるため、アプリへのイベントが遅れるようです。
そこで、下記のように[preferredScreenEdgesDeferringSystemGestures](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887512-preferredscreenedgesdeferringsys)をオーバーライドして、アプリ側のイベントを優先するように指定します。

```swift
class ViewController: UIViewController {
    override var preferredScreenEdgesDeferringSystemGestures: UIRectEdge {
        // 右端のボタンダウン反応が改善できます
        [.right]
    }
}
```
ARC067 C - Factors of Factorial

# 問題
整数$N$が与えられたときの，$N!$の正の約数の個数を$10^9+7$で割った余りを求める．

# 考え方
$N!$の素因数を｛$ p_0,p_1,...,p_k$｝とする．また，各素因数の個数をそれぞれ，｛$i_0, i_1,...,i_k$｝とする．この時，$N!$は以下のように表される：
$N! = p_0^{i_0} \cdot p_1^{i_1} \cdot ... \cdot p_k^{i_k}$.

従って，$N!$の約数の個数は，
$(i_0+1) \cdot (i_1+1) \cdot ... \cdot (i_k+1)$
となる．

以上のことから，$N!$の各素因数の個数を求めればその約数の個数が求められるということが分かる．

# 実装
ここでは，各素因数の数を数えるために，
$（N!に含まれる素因数pの個数）= \Sigma_{k=1}^{ \infty } \left\[ \frac{n}{p^k} \right \]  = \left\[ \frac{n}{p^1} \right \] + \left\[ \frac{n}{p^2} \right \] + ...$
を利用する（この定理の詳細は[こちら](http://www.mathlion.jp/article/ar073.html)）．

```python
import math
N = math.factorial(int(input()))

res = 1
p = 2  # チェックする因数

# p<=sqrt(N)を満たす因数を調査すれば十分
while p*p <= N:
    i = 1
    # p^k(k=1~)の倍数の個数を数えて足し合わせていく
    while(N % p == 0):
        i += 1
        N //= p

    # N!の約数の個数は i_0*i_1*...*i_k
    res *= i
    p += 1

if(N != 1):
    res *= 2
print(res % (10**9+7))

```
MetabaseにREST APIを使ってアクセスしSQLを実行する

# やりたいこと

Metabase（REST API 経由）で、SQL を実行する。

# やること

- `username`, `password` を使って、`セッションID` を取得する。
- `セッションID` を使い、Metadase にアクセスして、SQL を実行する。

# 参考ドキュメント

- [Using the REST API](https://github.com/metabase/metabase/wiki/Using-the-REST-API)

> The Metabase API only supports JSON; all responses are returned as JSON, and request bodies must be JSON. As such, you'll want to pass the `Content-Type: application/json` header with all of your requests.

- [API Documentation for Metabase](https://github.com/metabase/metabase/blob/master/docs/api-documentation.md)

# 手順

## セッションID の取得

```shell
_USERNAME_='<username>'
_PASSWORD_='<password>'
_METABSE_URL_='<url>'

curl -X POST \
  -H "Content-Type: application/json" \
  -d "{\"username\": \"${_USERNAME_}\", \"password\": \"${_PASSWORD_}\" }" \
  https://${_METABSE_URL_}/api/session
```

↑を実行すると、↓のような`セッションID`が取得できます。

```
{"id":"6ce27067-23a4-4d2f-beeb-80ef31e034a9"}
```

#### セッションに関する注意点

> Sessions are good for 14 days by default; you can configure this value by setting the env var MAX_SESSION_AGE (value is in minutes).

セッションはデフォルトで 14日間有効。環境変数の `MAX_SESSION_AGE`（秒単位）で指定可能。

> Logins are rate-limited for security purposes. Thus you should cache the credentials you receive and reuse them until they expire.

セッションは期限が切れるまで使い回すこと。

> If a session is expired or otherwise no longer valid, the API will return a response with a 401 (Unauthorized) status code.

セッションが切れた場合、API は 401（Unauthorized）を返す。

> We recommend writing your code in a way will fetch a new session token and automatically retry requests a single time when the API returns a 401.

401 が返された時は、セッションを再取得して一度リトライすることを推奨する。

## Metabase で SQL を実行する

↑で取得した`セッションID`を使って REST API 経由で SQL を実行します。

```shell
_SESSION_ID_=<session_id>
_METABASE_URL_=<url>

curl -X POST \
  ${_MTABASE_URL_}/api/dataset \
  -H "Content-Type: application/json" \
  -H "X-Metabase-Session: ${_SESSION_ID_}" \
  -d '{
  "database": 4, // database の番号を指定する。Metabase の GUI で確認可能。
  "native": {
    "query": "SELECT COUNT(*) FROM foo"
  },
  "type": "native"
}'
```

レスポンスは、`data.rows` の中に配列で入っています。

```
{"data":{"rows":[
[43]
],
...
```

参考：https://stackoverflow.com/questions/50620095/is-it-possible-to-get-raw-data-from-a-metabase-mbql-sql-query-via-the-rest-api
【Flutter】AppBarの背景色と文字の色を変更する

##AppBarの背景色と文字の色を変更する
![2020-10-10 15.58のイメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/844142cc-1986-b9b6-ea5f-92747df08ab8.jpeg)
画像のように背景色と文字の色をそれぞれ指定する方法を紹介します。他にやり方やアドバイス等あれば教えて欲しいです。

##背景色の設定
appBarのパラメータには`title`の他,`backgroundColor`というものがあるので,Colorクラスから色を選択します。

##文字の色の指定
`title`に指定したTextの文字の色を`style`から変更します。

```Dart
Text("テスト",
                   style: TextStyle(color: Colors.black),
```

##ソースコード
コピペしてそのまま使えます。

```Dart
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
      appBar: AppBar(title: Text("テスト",
                   style: TextStyle(color: Colors.black),
      ),
                    backgroundColor: Colors.red),
        body: Center(
          ),
        ),
      );
  }
}
```
Teamsの使い方　俺的メモ

#Teamsの会議の参加の仕方メモ

勉強開催にあたり、Teams使い初めての方がいらっしゃるのでここ見てね的なメモです。

##Teamsには

- アプリ版
- ブラウザ版

が存在します。アプリ版はMicrosoftが推してますが、機能追加が頻繁ですし、やたらと重い感じです。
職場でTeams使って1年近くになりますが、CPU2コア、メモリー4GB、個人領域10GBのVDIというな貧弱な環境ではアプリ版はかなり動作が重く、私はアプリ版は使ってません。

自宅の個人マシンはめもり32Gですが、職場の流れでアプリ版をほとんど使ってない状態です。

ブラウザ版で不都合はないですね。

また、職場とプライベートではユーザー表示名を変えたい。プライベートでは本名は隠しておきたいというニーズもあるかと思います。

そこでブラウザ版でかつプライベートモードでの使い方のメモを記載しておきます。

ブラウザ版にはアプリ版に使えない機能がいくつかあります。
背景画像を入れ替えはブラウザ版ではできないようです。部屋の様子がわかる状況は困るという人は、カメラOFFで。
またはSnapCameraと組み合わせてとなります。SnapCameraは結構重いアプリです。

##検証環境

検証しているブラウザはChrome、OSはWindows10です。

検証済み環境が増えてきたら、情報は追加していきます。ここにあるよって情報サイトリンクも募集します。相互援助ということで。

##ブラウザ版プライベートモードとは

Chromeではシークレットウィンドウと呼ばれてます。FirefoxやIEにも同じような機能はあります。
このモードで起動しアクセスした記録は履歴には残らない仕組みです。ちょっと他人の環境を緊急で借りたり、共用PCで作業したりするときはこのモードでブラウザを使ったがいいですね。

情報漏洩の危険性は完全に0とうわけではありませんが、防御策の1つです。
##ブラウザ版プライベートモードでの使い方

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664298/6f91c92f-7493-9fe7-8257-9a9bd264292b.png)

シークレット　ウィンドウを開く(I)　を選択して、プライベートモードを起動してください。
会議のURLをコピペしてアクセスしてください。
connpassなんかでは参加者への情報として記載されてたりします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664298/0a1b3b8c-8d59-e535-b72c-f05340805ce8.png)

- キャンセル　をクリック
- このプラウザーで続ける　をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664298/912a32f4-65d6-90a1-b7f9-b67b72815c75.png)

- 許可をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664298/d52a3456-517f-6fdf-9cb4-d3af819d8ffc.png)

- 名前を入力してください
- 必要に応じてカメラ、マイクのミュート設定してください
- 今すぐ参加　をクリックして参加です


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664298/9786efaf-88f8-1134-2471-d4e92fe18e30.png)

- 主催者の参加許可をお待ちください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664298/9f866378-fde3-0f5c-156c-3a9ced920590.png)
GitHubのerror: GH007: Your push would publish a private email address.への対応方法

# 問題
GitHubに新規リポジトリを作成し、ローカルのレポジトリをコミットをしようとしたところ、謎のエラーに遭遇しました。

# 作業内容
GitHubサイト上にリポジトリを作成後、ローカルで下記の通りにレポジトリ作成、コミット、プッシュを実行。


```bash
git init
git remote add origin git@github.com:username/reponame.git
git add .
git commit -m “initial commit”
git push origin master
```

した結果、下記のエラーが発生。

```bash
remote: error: GH007: Your push would publish a private email address.
remote: You can make your email public or disable this protection by visiting:
remote: http://github.com/settings/emails
```

#原因
下記条件の時にエラーが起きるようです。目的は意図しないメールアドレスの公開を防ぐためでしょう。

- GitHubアカウントのメールアドレスを公開しない設定にしている
- Publicなリポジトリを作成している
- リポジトリのauthorが上記設定で非公開にしたメールアドレスになっている

# 解決策
解決先は単純でエラーに記載の通り、メールアドレスの公開設定を変更するだけです。

## メールアドレスの公開設定を変更

[アカウントの設定ページ](https://github.com/settings/emails)を開き、下記のチェックを外します。
![email_cofig.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88541/9fbe7ee4-ed3f-46eb-b842-80d396f18fa6.png)

GitのAuthor設定変更はGitHubの[この記事](https://docs.github.com/en/free-pro-team@latest/github/setting-up-and-managing-your-github-user-account/setting-your-commit-email-address#setting-your-commit-email-address-in-git)などを参照してください。
[Docker]dockerでRails5.2環境構築

## 前提
dockerとdocker-composeインストール済

##1. fileを用意
Gemfile, Gemfile.lock, Dockerfile, Docker-compose.ymlを~/Desktop/product-register下におく。

###1. Dockerfile

```
FROM ruby:2.5
RUN apt-get update && apt-get install -y \
      build-essential \
      libpg-dev \
      nodejs \
      postgresql-client \
      yarn
WORKDIR /product-register
COPY Gemfile Gemfile.lock /product-register/
RUN bundle install
```
###2. Docker-compose.yml

```
version: '3'
services:
  web:
    build: .    // imageとってくる場合は image: イメージ名
    ports:
      - '3000:3000'
    volumes:
      - '.:/product-register'
    tty: true
    stdin_open: true

```
注意点: インデントやスペースがシビア

###3. Gemfile
```
source 'https://rubygems.org'
gem 'rails', '~> 5.2'
```
##2. コンテナを作ってRailsアプリを作成
```
$ docker-compose up -d 
$ docker-compose exec web bash
:/product-register# rails new . --force --database=postgresql -skip-bundle // gemfileが更新されてしまう
$ docker-compose down // gemfileを更新するためにコンテナを一度落とす
$ docker-compose up --build -d  新しくdockerfileをbuildしたimageを使うために--buildをつける
$ docker-compose exec web bash //再度入る
:/product-register# rails s -b 0.0.0.0 // dbの設定がまだなのでエラーが出る
```

##3. DBの設定
### 1. 作成されたアプリのconfig/database.ymlの修正
```
adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: db                  
  user: postgres       
  port: 5432
  password: <%= ENV.fetch("DATABASE_PASSWORD") %> 

```

### 2. docker-compose.yml ファイルのdb部分の追記

```
version: '3'

volumes:
  db-data:             // docker volumeを作っている
services:
  web:
    build: .
    ports:
      - '3000:3000'
    volumes:
      - '.:/app'
    environment:
      - 'DATABASE_PASSWORD=postgres'
    tty: true
    stdin_open: true
    depends_on:
      - db
    links:
      - db
  
  db:
    image: postgres
    volumes:
      - 'db-data:/var/lib/postgresql/data'　　　　//上で作ったdockervolumeをマウントしてる
    environment:                      
      - 'POSTGRES_PASSWORD=postgres'   //最近必要になったらしい
```
Arduino Pro Micro(裸)をリセットする

数年前にいじっていたArduinoProMicroを発掘した。
謎のスケッチが入っており、ArduinoIDEにてCOMポートを認識しなかった。（多分USB機器として認識されたんだろうと思う）

そのため、スケッチ（とブートローダ等）の初期化を試みた。
が、Arduinoが裸の状態(<https://www.switch-science.com/catalog/3914/>)だったのと、親切なリセット方法が調べきれなかったので備忘メモを残す。

1. 基盤に書いてあるRSTとGNDを短絡する(この場合WindowsからUSBを抜きさしした時の音、ピンポロポンが鳴る)
1. 空のスケッチを書き込む(マイコンボードに書き込むボタンを押下する)
1. 数秒(体感5秒)で書き込まれていたスケッチが起動してしまうので、起動しないようRSTとGNDを短絡させる。
1. おわり！裸のProMicroを初期化できない人に届け！

[Arduino Leonardoのリセット](https://qiita.com/enkatsu/items/107b9308889117076fac)
[Arduino でなんだか起動しなくなった時の解決](https://qiita.com/mzmttks/items/25363d72a507c0ac1c92)

- 短絡する→通電させる、ショートする。記事によってはLowにすると書かれている。Lowにするってわかりにくいな。
- RST→Resetする電極
SourceTreeを使用して git: 'secrets' is not a git command. See 'git --help'. エラー解決方法

 環境

```
macOS 10.15.6
git 2.23.0
```

SourceTreeでコミット使用とした際に以下のエラー画面が表示された

```
git: 'secrets' is not a git command. See 'git --help'.
```
いろいろ調べたのですが、方法としては
そもそもgit-secretsがインストールされていない可能性

```
brew install git-secrets
```
自分の場合は下の結果が表示され既にインストール済みと

```
Warning: git-secrets 1.3.0 is already installed and up-to-date
```

次に指定したgitと同じパスにgit-secretsを置くこと
自分は置いていたのですが、うまくいかず...

```
$ which git
/usr/local/bin/git
$ which git-secrets
/usr/local/bin/git-secrets
```
次にSourceTreeの設定でそもそもgitの指定が間違っている
/usr/local/bin/gitを指定する（環境設定 > Git > 「システムの Git を使用する」）
![スクリーンショット 2020-10-10 15.29.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460518/01bbe3ed-05e4-1cec-bfc8-5b39099a17e9.png)
自分の場合は/usr/local/Cellar/git/2.13.1/bin/gitの指定になっていたのが問題のようでした。




参考記事
[【Git】git: 'secrets' is not a git command. See 'git --help'.というエラーがでたときの解決方法](https://qiita.com/chisaki0606/items/80a0d34eeec5e1c8e2c3)
[AWSアクセスキーをGitリポジトリに混入させないために git-secrets を導入した](https://dev.classmethod.jp/articles/startup-git-secrets/#toc-sourcetree)
ハッシュ

#【ハッシュ】

業務内でパスワードをハッシュ化するプログラムを書きました。
その際、ハッシュ化について少し調べたものをまとめました。

##ハッシュ
###・ハッシュ化

簡単にまとめると、あるルールに基づいて別の値に置き換えること。
→特定の文字列や数字の羅列を一定にルール（ハッシュ関数）に基づいた計算手順によって、別の値に置換する。

秘匿性を高めるためにデータを不可逆変換し、復号できない形にデータを変換する。

###・ハッシュ関数

暗号化や誤り・改ざん検出などに使われるデータを要約する数列を生成する演算手法。
入力した値に対して、まったく別の値が出力されるという暗号方式。

###・ハッシュ値

あるデータを変換して別の文字列や値に変換されたもの。

##普通の暗号化とハッシュ化との違い。

後々、復号する必要があるかで使い分ける。

ハッシュ化は復号を前提としていないので、第三者がハッシュ値から元のデータを割り出すのは不可能に近い。
お互いが持っている情報が同じものか確認するなど、復号が不要な場面で使われる。
（ハッシュ化されていても、同じ情報かの判断は可能である。）

ハッシュ化は、ECサイトなどのWebサービスの一般的なパスワードに使われている。
また、電子署名やブロックチェーン技術にも使用されている。

一方で暗号化は、クレジットカード番号を送信する時などに使われている。
2020年10月現在 の 一番簡単な WSL2 セットアップガイド

# よもやま話

WSL2使ってますか?
私は WEBエンジニアクラスタに属してまして、この界隈では右見ても左見てもMacがデフォルトなんじゃないかと思う賑わいです。
もちろん BSDベースなMacは素晴らしい環境なんですが、私は若干、人とは違うことをやっていたいと思う欲求があり、WindowsノートPCにデュアルブートでUbuntu入れて使ってました。Windows10を使っていなかった理由は察してください。。。

状況が変わったのがWSL2が出てからです。WSLも良かったんですが、いかんせんファイルシステム回りがイマイチでした。
それがWSL2ではさらにピーキーに、Windows側からアクセスした時の速度なんぞ知ったことかとぶん投げて、WSL2サイドからアクセスした場合には、ほぼLinuxネイティブといっていい感触。素晴らしすぎます。この点、NTFSの独自路線を突っ走るsymlinkの扱いに疲れ果てた諸子にはわかって頂けると思います。

そんなわけでWindows10に安息の地を見出したわけですが、公式のWSL2インストールガイドを見ると

https://docs.microsoft.com/ja-jp/windows/wsl/install-win10

なんですか。この分かりづらさは。わざとか。わざとなのか。
そもそもなぜ一発でインストールできるインストーラーを用意していないのか。
せめて``winget``でインストールできないのか。
まあ例外ケースはマイクロソフト様にお任せすることにして脳力ゼロでインストールできる手順をまとめました。
トラブったら、公式を参照してくださいね。


# WSL2インストール手順 

- PowerShellを**管理者権限で起動**します。

- 以下、PowerShellで実行します。

```sh
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
```

- **PCを再起動** します。

- 以下からLinuxカーネル更新プログラムをダウンロードし実行します。

https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

- WSL2がデフォルトになるよう設定します。

```sh
wsl --set-default-version 2
```


以上！

あとは好きなLinuxのディストリビューションをインストールしてください。
繰り返しになりますが、とらぶったら公式参照お願いします。
MySQL ユーザ名＆ホストの変更

# MySQL ユーザ名＆ホストの変更
## 概要
MySQLにおけるユーザ名＆ホストの変更について説明します。

## 手順
### 構文

```sql
RENAME USER 'ユーザー名'@'ホスト名' to '新ユーザー名'@'新ホスト名';
```

### 例文

```sql
RENAME USER 'admin'@'localhost' TO 'admin'@'%';
```

`「%」`を使う場合は`'(シングルコーテーション)`をつける必要があります。

### 確認方法
```sql
SELECT user, host FROM mysql.user;
```


## 参考
- [MySQL ユーザ名＆ホストの変更](https://bituse.info/mysql/30)
Windows10 で簡単に document や download にアクセスしたい

# 備忘録
個人的にはすごく便利な設定。
なのに、PCでこの設定のために調べ物したのが2回目…。
なので、自分用に備忘録を残しておきます。

手順は以下で実現できます。
1. ジャンクションの作成
2. ジャンクションをクイックアクセスに登録
3. エクスプローラデフォルトをクイックアクセスに変更

# やりたいこと
Windows + E でエクスプローラを開いた後、download や document にキーボードから簡単にアクセスしたい。
クリックしたり上下キーで選択すれば開けるけど、もっと早くアクセスしたい。

windows10 では、デフォルトでダウンロードやドキュメントがカタカナで表示されている。
任意で変えられれば doc や dow と入力しただけで上記フォルダにアクセスできるがリネームはできなそう…？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410015/b88de29f-fad0-fbad-9458-89df6a508ccd.png)


また、ショートカット作ればいいと思ったのですが、ショートカットはリネームしてもカタカナで出てきてしまう…。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410015/dbc34ec6-7b98-34e6-81f0-063e73449a70.png)

# ジャンクション
ショートカットではなくジャンクションというのを作ると、任意の名前でクイックアクセスに登録できる。

# 手順
備忘録欄に書いたとおり、実施内容は以下。
1. ジャンクションの作成
2. ジャンクションをクイックアクセスに登録
3. エクスプローラデフォルトをクイックアクセスに変更

## 1.ジャンクションの作成
ジャンクション作成のコマンドは以下の通り

```
mklink /J (ジャンクション名フルパス) (リンク先フォルダ)
```

例として、Documents 配下の quickAccess ディレクトリ配下に「Documents」という名前で Document ディレクトリへのジャンクションを作成する場合のコマンドは以下の通り。


```
mklink /J C:\Users\<ユーザー名>\Documents\quickAccess\Documents C:\Users\<ユーザー名>\Documents
```

## 2. ジャンクションをクイックアクセスに登録
作成したジャンクションをクイックアクセスに登録。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410015/fdc226eb-3754-739f-276e-abaf9669bd0b.png)

## 3. エクスプローラデフォルトをクイックアクセスに変更
エクスプローラを開いてファイル > オプションから
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410015/c183af09-995c-363c-49a3-e40961ed6dca.png)

エクスプローラで開く を クイックアクセス に設定。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410015/94520de0-31f4-651d-daae-72c98245874c.png)

## 4. しあわせ
Windows + E > doc + Enter や
Windows + E > dow + Enter で、ディレクトリにアクセスできる…。
幸せ…。

# 参考にさせていただいたサイト
[フォルダへのジャンクションの作成と削除 - Windows Tips](https://www.ipentec.com/document/windows-create-folder-junction
Google OAuth2.0 認証連携 概要

Googleの認証機能を用いて、Webアプリにログインする際のシーケンスや開発に必要な事前作業をメモする。

## 概シーケンス

![Login_with_Google.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/92b5f186-ed3b-fb29-ec7a-0798f2633359.png)

## 開発に必要な事前作業
※Googleアカウント必要
1. [Google Developers Console](https://console.developers.google.com/cloud-resource-manager)でプロジェクトを作成する。
2. プロジェクト用のクライアントIDとクライアントシークレットを取得し、リダイレクトURIを登録する。
3. OAuth同意画面でアプリケーション名やスコープを登録する。

## 参考情報

* [OpenID Connect](https://developers.google.com/identity/protocols/oauth2/openid-connect)
【Java Silver】ラムダ式に関するポイントまとめ

#ラムダ式とは
実装が必要なメソッドを１つだけ持つインターフェース型変数に、実行したいコードを代入する仕組み。

#関数型インターフェースとは
関数型インターフェースは、**実装が必要なメソッド**を**１つ**だけ持つインターフェースのこと。
入力に対して出力が１つに決まるから「関数型」と呼ばれる。

#関数型インターフェースの種類

|インターフェースの種類 |実装が必要なメソッド  | 特徴 　　
|---|---|---|---|
| Consumer\<T>  | void accept(T) |引数を受け取って処理する。結果を戻さない、引数の**消費者**  
|  Supplier\<T> |T get()   |何も受け取らずに結果だけを戻す**供給者**  
|  Predicate\<T> |boolean test(T) |引数を受け取って、それを評価する**断定者**    
|Function\<T, R> |R apply(T)  |引数を受け取って、指定された型(R)の結果を戻す**処理者** 

※\<T>とは：TはTypeの略。何型でも良い、ということを汎用化して表している。


##関数型インターフェースの例
参考）[Java8 ラムダ式用のクラス](https://qiita.com/irxground/items/983a7d25239eef02bf8f)





**・java.util.ListインターフェースのforEachメソッドはConsumer型のラムダ式を受け取れる**
参考）
[公式ドキュメント・インターフェースList＜E＞](https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/util/List.html)
[公式ドキュメント・forEach](https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/lang/Iterable.html#forEach(java.util.function.Consumer))


例）

```java
public static void main(String[] args){
   List<Integer> list = List.of(1,2,3);
   list.forEach((x) ->{System.out.println(x)}); //引数を受け取って処理し値はreturnしない
}
```


**・java.lang.StringクラスのtoUpperCaseメソッド**はFunction型のラムダ式を受け取れる

参考
[公式ドキュメント・toUpperCase()](https://docs.oracle.com/javase/jp/8/docs/api/java/lang/String.html#toUpperCase--)

例）

```java
public static void main(String[] args){
   Function<String, String> func = (x) -> {return x.toUpperCase();}; //引数を受け取って、指定された型の結果を戻す
   System.out.println(func.apply("hello world"));
}
```



#ラムダ式の書き方
＜基本＞
 > 関数型インターフェースの型　変数名 = (引数) -> { //処理　**return** };

```java
  Function<String, String> func = (x) -> { return x.toUpperCase(); }; 
```
 
 ＜引数が１つの時、()の省略＞
> 関数型インターフェースの型　変数名 = 引数 -> { //処理 **return** };
 
```java
　Function<String, String> func = x -> { return x.toUpperCase(); }; 
```

 <処理が１つの時、{}の省略>
> 関数型インターフェースの型　変数名 = 引数-> //処理;
 **※return文を書けない！！**
 
```java
list.forEach( x -> System.out.println(x) ); 
```

#ラムダ式の注意点
**【ラムダ式が持つ仮引数は、定数か実質的に定数】**

・コンパイルエラー例(Java Silver黒本より)
 
 ```java
void sample(){
  int i = 0;
  Supplier<Integer> foo = () -> i;    
　i++;   //iは実質的に定数である必要
  System.out.println(foo.get());
}
```

**【引数のデータ型に注意】**
ラムダ式の変数宣言は**データ型の指定を省略**できる。
代入しようとしている関数型インターフェースの型から引数の型を推論できるため。

ラムダ式の変数を引数を、型を省略して書いたとしても、それは新しく定義された変数ということになる
→**ラムダ式のスコープ内にある、既存の変数と重複しないか要確認！！**

・コンパイルエラー例

```java
final String val = "Hello World";
Consumer<String> func = (val) -> System.out.println(val); //ラムダ式のvalと、ローカル変数のvalで名前の重複がおこりコンパイルエラー
```


**【スコープに注意】**
ラムダ式の**スコープ**は、ラムダ式が書かれているブロック全体におよぶ
 
 ・コンパイルエラー例

 ```java
public class Main{
   public static void main(String[] args){
     Srting val = "A";  //ラムダ式のスコープ内にあるローカル変数val
     Function f = (val) -> {  //ラムダ式の変数val
       System.out.println(val);
     };
   }
}

```






















 


 
 



#今後の課題
正直なところラムダ式についてまだまだ全然理解できていない・・・。
ラムダ式の仕組みについて、下記のサイトを理解したいと思う。

[コンピュータサイエンスと魔法のYコンビネータ](https://yj.chibicode.com/)

また、実際にどんな時にラムダ式を使うのかいまいち理解できていない。
ラムダ式を受け取ることができるメソッドは何なのか？
再利用しない簡単な処理を記述する際にはいつでも利用できるのか？
関数型インターフェースのメソッドでないと使えないのか？関数型インターフェースのメソッドであるとどう見分けるのか？

などなど、理解できていないことがたくさんある。
javascriptで配列の中身に数値を入れたいときNaNになってしまう場合

配列にキーを指定して数値を入れたいとき初期化しないとNaNになる。
変数を0で初期化しないとNaNになるときがあって、それはすぐわかったが、今回の配列の中だとできなくてハマった。
ぐぐってもわからず、時間がかかってしまった。
どういう場面で、使うか不明だけど、既存のシステムがあって、一部カスタマイズしたいときなど使うことがあるかもしれない


```js
let arrayA = [0, 1, 2, 3, 4]
let arrayB = []
for ( value in arrayA ) {	
	arrayB[0] += Number(value)
}
// NaN
```

一度キーを指定して0で初期化しておく。

```js
let arrayA = [0, 1, 2, 3, 4]
let arrayB = []
for ( value in arrayA ) {	
	if (! arrayB[0]) {
	    arrayB[0] = 0
	}

	arrayB[0] += Number(value)
}
// 10
```
Heroku+ActiveStorage+Amazon S3

1 AWSコンソール → サービス → ストレージ → S3でパケット作成

|項目|入力・選択
|---|---|---|
|パケット名|ex: my-rails-app-first-bucket
|リージョン|:flag_jp:　東京|
|アクセス権限|チェック欄全てoff|
|上記以外|デフォルト|

2 アクセスキーを作る
下記参照
https://tech-blog.s-yoshiki.com/entry/135


3 必要なGemのインストール

```
gem "aws-sdk-s3", require: false #追記
```

4 S3へのアクセスキーを入力 

```
$ EDITOR=vim rails credentials:edit

# コメントアウトを解除する
aws:
 access_key_id: #ここに自分のアクセスキーIDをコピペ
 secret_access_key: #ここに自分のシークレットアクセスキーをコピペ
```
-vi/vim操作- 
iキーで編集開始、escで編集終了 、 ZZで保存して終了
後から入力を確認したいときは

```
$ rails credentials:show
```

5 Herokuでの画像の保存先をAmazon S3に変更


```php:config/storage.yml
amazon:
  # 以下3行はそのまま
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  # 以下２行は変える
  region: ap-northeast-1 #東京
  bucket: my-rails-app-first-bucket #自分で作成したS3のバケットの名前
```

```php:config/environmentas/production.rb 
config.active_storage.service = :amazon #amazonに変更
```

6　最後にHerokuでやること

```
$ heroku buildpacks:add -i 1 https://github.com/heroku/heroku-buildpack-activestorage-preview
$ git add .
$ git commit -m "added s3 to production"
$ git push heroku master
```
Railsプロジェックトのマスターキー(config/master.keyの中身)をコピーします

```
$ heroku config:set RAILS_MASTER_KEY=マスターキーをここに貼り付け
$ heroku run rails db:migrate
$ heroku open
```

-応用編-
ActionTextを使用している場合、S3の方でS3→パケット→アクセス許可→Cross-Origin Resource Sharing (CORS)に行き。CORSを設定する必要がある。

```
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "PUT",
            "POST",
            "DELETE"
        ],
        "AllowedOrigins": [
            "URL"
        ],
        "ExposeHeaders": []
    }
]
```
（自分メモ）PC 設定時に参考にしたサイト

WSL2, Windows Terminal などの設定した際に参考にしたサイト。

## WSL2
- https://docs.microsoft.com/ja-jp/windows/wsl/install-win10
- https://dev.classmethod.jp/articles/how-to-setup-wsl2/
- https://qiita.com/mainy/items/19862ebb1fa4df2ad497

## Windows Terminal
- https://docs.microsoft.com/ja-jp/windows/terminal/
- https://qiita.com/whim0321/items/6a6b11dea54642bd6724

## PowerShell
- https://docs.microsoft.com/ja-jp/powershell/scripting/install/installing-powershell-core-on-windows?view=powershell-7
- https://docs.microsoft.com/ja-jp/windows/terminal/tutorials/powerline-setup
- https://blog.mamansoft.net/2020/05/31/windows-terminal-and-power-shell-makes-beautiful/

## WSL2 × Docker
- https://dev.classmethod.jp/articles/docker-desktop-for-windows-on-wsl2/
Vue の style 内で Stylus 利用時に 絶対パスで import する

##1.絶対パスで import する ... けどうまくいかん

``Nuxt.js`` とかだとデフォルトで ``~`` でうまくいくんだけど、
``Vue.js`` だと ``@`` でうまく指定できずずっと悩んでた。
とりあえずシンプルに解決したのでメモ。

##2.結論

``@`` の前に、``~`` をつける。

##3.例えば ...

グローバルな ``.styl`` を ``import`` したい。

###失敗例
```hogehoge.vue
<style lang="stylus" scoped>
@import "@/assets/css/_mixins.styl"
</style>
```

``TypeScript`` でプロジェクトを作成していると、プロジェクト直下の ``tsconfig.json`` に以下の文がある。

```tsconfig.json
{
  "compilerOptions":
・・・中略
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
```

なので、``@`` つければいけるかと思いきや、失敗。
なぜかは今はわからないけど、``~`` をさらにつけることで解決。

###成功例
```hogehoge.vue
<style lang="stylus" scoped>
- @import "@/assets/css/_mixins.styl"
+ @import "~@/assets/css/_mixins.styl"
</style>
```

なんでや。


#追記 (2020/10/11 16:21時点)
上記の ``~@`` という記述方法はどうやら、 ``Stylus`` で適用されるらしい。
``script`` 内では結局 ``@`` だけでいいみたい。

```hogehoge.vue
・・・中略
<script lang="typescript">
import { defineComponent, computed } from "vue"
export default defineComponent({
  const data = reactive({
    style: computed(() => {
      return {
        backgroundImage: `url(${require(`@/assets/graphics/unit/unit1_1.png`)})`
      }
    })
  })
})
</script>
```

``~`` これはなんだ・・・
wsl2でDocker自動起動設定

wsl2を使ってみて、Dockerを自動起動設定ができないらしく、
毎回 serviceコマンドを打つのが面倒なので検討してみた

ユーザでパスワード無しで起動できるようにsudoに設定

```bash
$ sudo visudo
# docker deamon auto up
ユーザ ALL=(ALL:ALL) NOPASSWD: /usr/sbin/service docker start
```

```bash
停止時
$ service docker status
 * Docker is not running
起動時
$ service docker status
 * Docker is running
```
.bashrcにdockerが起動していないときだけ、スタートさせるように追記

```bash
$vim .bashrc
#追記
echo $(service docker status | awk '{print $4}') #起動状態を表示
if test $(service docker status | awk '{print $4}') = 'not'; then #停止状態
        sudo /usr/sbin/service docker start #起動
fi
```

この設定で、wsl2に入るときに、Dockerが停止していたら起動するようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274034/44d4fc82-db7f-f418-8e7a-d72372672e0f.png)
docker-slimを使うためにPATHを通そう

# インストールの手順
* 公式ページからzipファイルをダウンロード
    * https://github.com/docker-slim/docker-slim#installation

* zipファイルを解凍
    * 自分はダウンロードディレクトリからuserディレクトリに移動させました
* docker-slimにpathを通す
    * ここについて書きます

# pathを通す

```shell:.bash_profile
# ---docker slim ---
export PATH="Users/dsaku/dist_mac"

# ---main command ---
export PATH=/bin:/sbin:/usr/bin:/usr/sbin：/usr/local/bin
```
初めはこのように書いてました．
しかしうまいこと行かないなあと．これは書き方が間違っています，

```shell:.bash_profile
# ---main command ---
export PATH=/bin:/sbin:/usr/bin:/usr/sbin：/usr/local/bin

# ---docker slim ---
export PATH=$PATH:/Users/dsaku/dist_mac
```
これはしっかりPATHが通っています，
・export PATH=通したいPATH
で書いてしまうと上書き保存されてしまうので，うまくいってませんでした．
追加していくには
・export PATH=$PATH:通したいPATH
じゃないとダメみたいです．

基本中の基本ですが，知らなかったので備忘録として書きました．


# 参考リンク
PATHを通すために環境変数の設定を理解する (Mac OS X)
・https://qiita.com/soarflat/items/d5015bec37f8a8254380
Trailblazerでcreateを試してみる

# はじめに
抽象レイヤーを提供してくれるGem,Trailblazerの存在を知り勉強がてらにCreateを試してみた。
Trailblazerの概要については他の記事でわかりやすく説明していただいてるので割愛とする。

こちらの記事がとてもわかりやすかったです。
[TrailBlazer概要まとめてみた
](https://qiita.com/Y_eureka/items/6fad75e2138e553f3170)

# 環境
ruby '2.7.2'
'rails', '~> 6.0.3'
template engine: haml


# Create

## Trailblazerのディレクトリ構成

```
.
└── todo
    ├── cell
    │   ├── index.rb
    │   └── new.rb
    ├── contract
    │   └── form.rb
    ├── operation
    │   ├── create.rb
    │   └── index.rb
    └── view
        ├── form.haml
        ├── index.haml
        └── new.haml
```

## Operation

```ruby

module Todo::Operation
  class Create < Trailblazer::Operation
    class Present < Trailblazer::Operation
      step Model(Todo, :new)
      step Contract::Build( constant: Todo::Contract::Form )
    end

    step Subprocess(Present) # present classのstep呼び出し
    step Contract::Validate(key: :todo) # contractを使ってバリデーション
    step Contract::Persist() # モデルに保存する
  end
end
```

## Contract

```ruby

module Todo::Contract
  class Form < Reform::Form
    include Reform::Form::ActiveModel
    property :title
    property :description
    property :completed
      
    validates :title, presence: true
    validates :description, length: { minimum: 2 }

    # overrideもできる
    # def title
    #  super.capitalize
    # end
  end
end
```

## Cell

```ruby
module Todo::Cell
  class New < Trailblazer::Cell
    include ActionView::RecordIdentifier
    include ActionView::Helpers::FormOptionsHelper
    include SimpleForm::ActionViewExtensions::FormHelper
  end
end
```

## View

```ruby
= simple_form_for(model, html: {novalidate: true}) do |f|
  = f.input :title, placeholder: "Title"
  %br
  = f.input :description, as: :text, placeholder: "Description"
  %br
  = f.submit 'Submit'
  = link_to 'Back', todos_path
```

## 確認

![trab-todo](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325401/7c54c366-9940-2e01-29e0-d2879f6e3aa3.gif)

今回試した[プロジェクト](https://github.com/izumiiii/trail-todo)

# 参考記事

[TrailBlazer概要まとめてみた](https://qiita.com/Y_eureka/items/6fad75e2138e553f3170)
[trailblazer](https://github.com/trailblazer/trailblazer)
GitやGithubの使い方メモ

GitおよびGithubの使い方や各種設定および注意事項などのメモ書き

git init 
git remote add等の
初期設定とmasterブランチ作成済みとして
僕は以下のようにしています。

git checkout -b 〇〇でブランチを切って
git status
git diff
git add .
git commit -m "コメント"
git push HEAD
を使用しています。

プルリクで修正がありましたら
再度git add、git commitをした上で
git rebase -i
git push -f origin HEADを実施します。


その後Githubでmasterへのマージが完了したら
git checkout master
git pull origin master
をします。

途中で別のブランチで別のタスクを行うときは、git stashを使っています。

Gitは奥が深く、全ての機能を使いこなすのは難しいし、
余計なことをすると他の人に迷惑がかかるので、私の使う Git command は非常限定的です。

基本的には、git checkout -b {ブランチ名} でブランチを作り、
そこで git status, git add, git commit を使って様々な変更を加え、
git push origin {ブランチ名} でサーバーにブランチをプッシュした後、
Github にアクセスして pull request を作った上で、コードレビューをして、
マージも Github 上で行う、
そして、マージしたものを git checkout master、git pull origin master で取得する、
というのが流れです。

複数の作業を同時期にする場合は、常に一度 master ブランチに戻って、
最新のものを pull し、そこから新たなブランチを作って作業します。
Docker × Cypress で E2E テスト環境をつくる

Docker 上で Cypress を実行し E2E テストを行いたくて、環境構築の方法をいろいろ探ったメモ。

# 構成
```
e2e
├ cypress - integration - sample_spec.js
└ cypress.json
  docker-compose.yml
  Dockerfile
```

# ファイル
## Dockerfile
```
FROM cypress/base:10

RUN npm install --save-dev cypress
RUN npx cypress verify
```

## docker-compose.yml
```
version: '3'

services:
  e2e:
    container_name: cypress
    build: .
    command: >
      bash -c "cd cypress &&
        npx cypress run -s cypress/integration/sample_spec.js"
    volumes:
      - ./:/cypress
```

## cypress.json
```
{
    "video": false
}
```

# 実行
```
docker-comopse build
docker-comopse up
```

# 感想
いろいろ調べながらやってみるものの、なかなかうまいこといかず。。。
やっぱり公式サイトをちゃんと見るのは大切ですね。

- https://hub.docker.com/r/cypress/base
- https://docs.cypress.io/guides/references/configuration.html#Options
再帰関数を使って数値文字列（負数、小数含む）をカンマ区切りにする処理

練習でアプリを作成しているときに作ったコード。
`toLocaleString()`や正規表現は使わずに、再帰関数を使って数値文字列のカンマ区切りを実装しています。

# コード

```javascript:separate_commas.js
/**
 * 数値文字列の整数部分のみを3桁ごとにカンマで区切る
 * @param  {string} str 数値文字列。
 * @returns {string} 3桁ごとにカンマで区切った数値文字列
 */
const separateNumberByCommas = (str) => {
  const array = str.replace("-", "").split(".");
  const result = array.length > 1
    ? separateIntegerByCommas(array[0]) + "." + array[1]
    : separateIntegerByCommas(array[0]);
  return str.includes("-") ? "-" + result : result;
};

/**
 * 整数文字列を3桁ごとにカンマで区切る
 * @param  {string} str 整数文字列。
 * @returns {string} 3桁ごとにカンマで区切った整数文字列
 */
const separateIntegerByCommas = (str) => {
  const len = str.length;
  return len > 3
    ? separateIntegerByCommas(str.slice(0, len - 3)) + "," + str.slice(len - 3)
    : str;
};
```

**実行例**

```javascript:sample.js
console.log(separateNumberByCommas("123"));       //123
console.log(separateNumberByCommas("1234"));      //1,234
console.log(separateNumberByCommas("1234."));     //1,234.
console.log(separateNumberByCommas("1234.0"));    //1,234.0
console.log(separateNumberByCommas("1234.5678")); //1,234.5678
console.log(separateNumberByCommas("-123456.0")); //-123,456.0
```

`separateNumberByCommas()`で小数点以下とマイナス記号を一旦省き、`separateIntegerByCommas()`で再帰的にカンマで区切っています。
再帰が終わったら、省いていた小数点とマイナス記号を再度結合します。

8行目の`array.length > 1`は小数点を省いたかどうかを判定しています。
小数点があった場合は7行目で要素数2の配列が作成されるため`true`に、
もともと小数点が無い場合は7行目で要素数1の配列が作成されるため8行目で`false`になります。
末尾が小数点（例：`123.`）の場合は空文字が入った要素が作成されるため`true`になります。
（`array.length > 1`を`array[1]`に変えれば末尾の小数点も省けます）

# `toLocaleString()`や正規表現を使わなかった理由

- `0.`とか`0.0`など末尾が小数点だったり小数点以下に`0`しかない文字も表示できるようにしたいけど、`toLocaleString()`だとこのような文字は小数点以下が省略されてしまう。
- [正規表現使えば数行で実装できるらしい](https://blog.abelotech.com/posts/number-currency-formatting-javascript/)、けど正規表現良く分からないし理解できてないものをコピペして使うのは避けたい。
- for文でもいいけど再帰関数の方が三項演算子使ってスマートに書ける。  
  あと`let`使わないで済む。

# 参考

[数値をカンマ区切りにする | Qiita](https://qiita.com/zawascript/items/922b5db574ef2b126069)
配列のキーが連番でないときに、値を挿入する方法

##配列のキーが連番じゃない
配列のキーが連番じゃなくて良い感じに値を入れてあげたい時。

```
$array = array(0=>'a', 1=>'b', 3=>'d');
$array += array_fill(0, max(array_keys($array)), 'c');
ksort($array);
```
実行結果

```
array(4) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [2]=>
  string(1) "c"
  [3]=>
  string(1) "d"
}
```

こんな風に自然な配列の形に整形できます。

```
$array += array_fill(0, max(array_keys($array)), '空です。');
```
実行結果

```
array(4) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [2]=>
  string(12) "空です。"
  [3]=>
  string(1) "d"
}
```
こんな風にすれば抜けていた配列の判別も簡単にできます。
【PHP】TSVファイルを配列に変換する

webサイトなどでカテゴリを設定・呼び出す際に必要なときがちょいちょいあるかと思います。
##環境
**PHP 7.3.18**
##tsvデータ例
スプレッドシートなどで下記のような表を作成
※一番左の列に項目を、右に列でデータを追加していく

~/config/member.tsv

| name | 田中 | 斎藤|
|:-----------|:------------|:------------|
| id       | tanaka        | saito         |
| email     | tanaka@~      | saito@~       |
| age       | 24        | 31         |
| from         | tokyo          | saitama           |

##実装

```hash.php
toHash(~/config/member.tsv,"\t");

function toHash($filePath,  $format = false, $first = false)
{
    //formatはtsvしか許可しない
    if (!($format == "\t")) {
        return false;
    }

    //ファイルの存在判定
    if (!file_exists($filePath)) {
        return false;
    }

    $fl = file($filePath);
    $data = array();
    foreach ($fl as $k => $v) {
        $column = explode($format,  $v);
        if ($k == 0) {
            foreach ($column as $i => $j) {
                $title[$i] = trim($j);
            }

            if ($first == false) {
                continue;
            }
        }

        foreach ($column as $i => $j) {
            if ($i == 0) {
                $key = $j;
            } else {
                $data[$key][$title[$i]] = trim($j);
            }
        }
    }
    return $data;
}
```


##結果
```
array(4) {
  ["id"]=>
  array(2) {
    ["田中"]=>
    string(6) "tanaka"
    ["斎藤"]=>
    string(5) "saito"
  }
  ["email"]=>
  array(2) {
    ["田中"]=>
    string(6) "tanaka"
    ["斎藤"]=>
    string(5) "saito"
  }
  ["age"]=>
  array(2) {
    ["田中"]=>
    string(2) "24"
    ["斎藤"]=>
    string(2) "31"
  }
  ["from"]=>
  array(2) {
    ["田中"]=>
    string(5) "tokyo"
    ["斎藤"]=>
    string(7) "saitama"
  }
}
```
各行ごとに配列で返ってきます。
単体テストのケース出しとテストクラスコメントの書き方とその他学んだこと

# この記事は
新人エンジニアが単体テストを作る上で教わったことや自分で学んだことをまとめたものです。
順次更新予定。

## テストケースの出し方のポイント
- テスト対象のクラスから条件文（if文、for文、try-catchブロック）を探し、それぞれの分岐を書き出す
    - for文は「処理に入らなかった場合」「1回だけループした場合」「3回ループした場合」の3分岐を書き出す
- ありうるパターンを出せるだけ出して、後から無意味なものを削る
    - 漏れを防ぐため
- パターン出しはエクセル等を使って表にする
- 自分の作っているシステム外が要因となって起きるケースは想定しなくてよい

## テストクラスのコメント
- そのテストを実行するにあたって必要な手順があれば、ケースの前に書く
JQueryでscrollイベントが発火しない問題を解決しました

##概要
railsアプリを作っていて
ある時急にスクロールイベントトリガーを使った無限スクロールが動かなくなった時の原因と対処です

##原因
cssプロパティの
```overflow: auto;```
こいつが原因でした。
どうやらoverflowでscroll（要素がはみでたらスクロールして対処）が指定されるとscrollイベントが起こらなくなる模様です。
autoを指定していたことで私の使っていたChromeではスクロールイベントが発火しなくなった模様です。

##解決策
```overflow: auto;```または```overflow: scroll;```を消す
【Rails】deviseのviewやcontrollerの編集とカスタマイズ方法

#はじめに
deviseのviewとcontrollerを編集、カスタマイズする方法

deviseを導入した後、見た目が味気なく英語ばかりのviewを整えたい。
deviseのcontrollerに編集を加えてカスタマイズする必要がある。
そんな時の方法を簡単に紹介します。


###目次

1.前提
2.devise.rbの設定ファイルを変更
3.contorollerの生成・カスタマイズ
4.viewファイルの生成・編集
5.まとめ

#開発環境

ruby 2.6.5
rails 6.0.0
devise 4.7.3


#1.前提

devise導入済み
model生成済み
ルーティングは随所で設定

#実装
それでは実装します。
#2.devise.rbの設定ファイルを変更
config/initializers/devise.rbを開きます。config.scoped_viewsを有効にします。

```config/initializers/devise.rb

  # ==> Scopes configuration
  # Turn scoped views on. Before rendering "sessions/new", it will first check for
  # "users/sessions/new". It's turned off by default because it's slower if you
  # are using only default views.
  config.scoped_views = true #←デフォルトはfalse#
```

Railsサーバを再起動します。

#3.controllerファイルの生成・編集
deviseのcontrollerを生成します。



```ターミナル
rails g devise：controllers users
```

この時の講文は
　rails g devise：controllers モデル名
です。
今回はdeviseモデルをuserにしているので（大体userにしますが）その名前を使います。
app > controllers > users > 
の下にファイルができます。
![スクリーンショット 2020-10-10 11.27.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769854/bd46eca4-3ed3-e700-0c6a-ce23a2e39086.png)
例えば、ユーザー登録関連のcontrollerをカスタマイズしたければ、regisrations_controller.rbファイルを編集します。


ここで注意が必要なのが、ルーティングの設定です。
ルーティングで記述している

[コントローラー名]#[アクション名]
と実際の
[コントローラー]#[アクション]

が違うと、当たり前ですがうまく行きません。
なので、rails routes　等でしっかり確認する事をおすすめします。


#4.viewファイルの生成・編集
deviseのviewファイルを生成・編集します。

```ターミナル
rails g devise:views
```
app > views > devise > 
devise直下にフォルダができます。


![スクリーンショット 2020-10-10 11.04.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769854/c88f4b92-cc9f-da00-b799-d23f04257525.png)

例えば登録画面を編集したければ、regisrationsのディレクトリにあるファイルを編集します。

ここで注意するべきなのは、viewのファイル名です。
deviseではrenderやredirect_toで遷移先を指定しなければ、コントローラーの処理後メソッド名に遷移する様になってます。
なので、それぞれの名前を合わせる必要があります。


#5.まとめ
contorollerの生成・カスタマイズとviewファイルの生成・編集を紹介しました。
deviseのcontrollerを使うと、デフォルトで持ってる機能を自動で使えると言うメリットがあります。
しかし、その反面に間違った記述をしてても、裏でdeviseが動いてくれるので、思い通りの挙動にならずエラーも出ないという状況にも陥ります。
その為にも、ルーティング、コントローラー、ビューがどうの様に辿ってきてるか注意する事をおすすめします。

###最後に
私はプログラミング初学者ですが、自分と同じ様にエンジニアを目指す方々の助けになればと思い、記事を投稿しております。
それではまた次回お会いしましょう〜
VSCodeでOS側での色反転モードのときに強制high contrast modeになるときの対処法

#問題の概要
以前からMacOSの色反転モードを使って白ベースの画面を黒ベースに切り替え、目に優しい作業環境を整えていた。
しかし、あるとき、アップデート後にVSCodeを開くと、MacOSの色反転を検知して自動でHigh Contrastモードが起動され
白ベーツの画面がVSCodeにより色反転されそれがさらに色反転され、画面が明るくなり目が疲れる。

しかし、VSCodeを開くときにのみMacOSの色反転を無効にするのは面倒であった。
ネットで検索しても同様の事象は見かけられたが、対処法を見つけられなかった。
設定をいじっていたら対処法を見つけたので共有しておく。



#対処法

Settingsを開き、"high contrast"で検索すると以下の設定ページが出てきます。

Window: Auto Detect High Contrastのチェックを外します

![スクリーンショット 2020-10-10 13.37.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614389/6b8f22b9-a46d-724b-d86e-e2798c31948a.png)

あとは テーマをLight Modeに戻し、色反転すれば、目に優しい開発環境が構築できます。
時刻表記にlメソッドを使う

# 経緯
店舗の運営時間を表示したくて調べていたところstrftimeというものを使うことで時刻の表記を指定できることがわかった。

```ruby:view
 <%= @laundry.open_time.strftime('%-H:%M')%> 〜 <%= @laundry.close_time.strftime('%-H:%M')%> 

```

これで```07:00 ~ 23:00```といった表記ができるようになった。
しかしどうも```strftime('%H:%M')```が２回繰り返されていることが気になり他の方法を調べていたところ、lメソッド（エルメソッド)を発見。上記の書き方からlメソッドでの書き方に変更をした過程を記録しておく。

#  lメソッドを使うまでの流れ
1 タイムゾーンを設定(strftimeを使用した時点で設定は済んでいたが今後見返せるように記述しておく）<br>
lメソッドを使用する前にタイムゾーンを設定して日本時間で表示されるようにする必要がある（設定をしていない場合は```UTC（世界協定時）```になっており日本時間とは９時間の差がある）
```config/application.rb```に以下のように記述を行う。

```ruby:config/application.rb
 config.time_zone = 'Tokyo'
```


2 デフォルトの言語をjaに変更、ymlファイルの作成<br>
1と同じファイル内に以下のように記述をすることで言語を日本語に設定する。

```ruby:config/application.rb
config.i18n.default_locale = :ja
```

ファイルは```config/locales```に```ja.yml```という名前で作成する。（```default_locale ```の後に続く国名（日本の場合はja）とconfig/localesの```〇〇.yml```）の〇〇を一致させることでファイルを読み込んでくれる)

3 ```ja.yml```にフォーマットを作成する

```ruby:ja.yml
ja:
  time:
    formats:
      default: '%-H:%M'
```

``default:``の後の記述を変えることで好みの時間表記にすることができる。

4 ビューファイルに３で設定した時刻を表示
ここでlメソッドが登場する。lメソッドを使うことでymlファイルで指定したフォーマットを利用して時刻を表示させる。
使い方としては頭にlをつける。

```ruby:view
<%= l @laundry.open_time %> 〜 <%= l @laundry.close_time %>
```

これで```strftime```をビューファイルに直書きすることなく好みを時刻表記を表示することができる。




```ruby:view（strftime直書き）
 <%= @laundry.open_time.strftime('%-H:%M')%> 〜 <%= @laundry.close_time.strftime('%-H:%M')%> 

```
```ruby:view（lメソッド使用）
<%= l @laundry.open_time %> 〜 <%= l @laundry.close_time %>
```

lメソッドを使いすっきりとした見た目に変更！！
ちなみにフォーマットを複数用意して使い分け流ことも可能（下記参考記事参照)

## 参考記事
https://qiita.com/jnchito/items/831654253fb8a958ec25
【Java Silver】アクセス修飾子のポイントまとめ

#アクセス修飾子

|アクセス修飾子 |アクセス可能  |クラス図での記号  　　
|---|---|---|---|
|public  |どこからでも  |+  
|protected |同一パッケージのクラスとサブクラス  |#  
|  |同一パッケージのクラス  |~    
|private|現在のクラス  |-    

許可されていない箇所からのアクセスは**コンパイルエラー**となる

#アクセス修飾子を考慮する必要があるもの
・**クラス**（別パッケージからアクセス可能か判断するため）
・メソッド
・コレクション（配列、ArrayList）
・フィールド

#アクセス修飾子の注意点

##インターフェースとアクセス修飾子

インターフェースは**継承される前提**のものなので、インターフェース自体は暗黙的に**publicとみなされる**
→　インターフェースに定義できるメソッド　
　　・**抽象メソッド**の場合、暗黙的に**public**、abstractであると解釈される(public、abstractは省略可)
　　・**実装を持つ**場合、**staticメソッド**または**defaltメソッド**である必要がある（**アクセス修飾子に制限無し。privateも可**）

→　インターフェースに定義できるフィールド
　　・static変数(**publicのみ**)
　　・定数(**publicのみ**)
　　・インスタンス変数を定義することはできない



**【インターフェースを実装したクラスの具象メソッド】**

**インターフェースに定義された抽象メソッド**のアクセス修飾子と、インターフェースを実装たクラスにある、**抽象メソッドを実装した具象メソッド**は**同じアクセス修飾子**である必要がある。

例) ※コンパイルエラー発生

```java
interface A(){
  void doSomething(); //インダーフェースの抽象メソッド。暗黙的にpublicと解釈される
}

B implements A(){
  protected void doSomething(){ //コンパイルエラー。アクセス修飾子はインターフェースの抽象メソッドと同じ「public」である必要
   //処理
  }
}
```

##抽象クラスとアクセス修飾子
抽象クラスは**継承される前提**のものなので、抽象クラス(abstractで修飾)は暗黙的に**publicとみなされる**

→　抽象クラスに定義できるメソッド
　　・抽象メソッドの場合、**abstract**での修飾が必要。抽象メソッドは**オーバーライドされる前提**のメソッドなので、**アクセス修飾子はprivate以外**を設定できる
　　・具象メソッドの場合、アクセス修飾子は自由に設定できる

→　抽象クラスに定義できるフィールド
   ・設定に制限無し


**※メソッドをオーバーライドするときのアクセス修飾子は、元のメソッドと同じか制限を緩くする必要がある**

例）

```java
interface A {
    void doSomething();
    
}

abstract class B implements A {
   public abstract void doSomething(); //インターフェースを抽象メソッドで実装可能。アクセス修飾子はインターフェースのメソッドと同じ
}

class C extends B {
    public void doSomething(){ //抽象メソッドをオーバーライド。
        System.out.println("何かする");
    };
}

public class Main {
	public static void main(String[] args) {
		C example = new C();
		example.doSomething();
	}
}
```
MySQLで任意の順序でソートしたい場合

# はじめに

今回はMySQLを例にして書きますが、PostgreSQLやOracleでも同様のことはできるはずです。

# テーブルに持たせる

頻繁にソートを使用する場合、そもそもソート順をテーブルに持たせるのが一般的だと思います。

```sql
SELECT * FROM item ORDER BY item.sort_order;
```

しかし「そこまでするほどでもない」「集計で使いたいだけ」といった場合もあるかと思うので、SQL文の中で順序を決定する方法を紹介します。

# `CASE`文を使う

`CASE`文で優先順位を決めてあげれば簡単に実現することができます。

```sql
SELECT * from item ORDER BY
CASE WHEN item.size = 'SS' THEN 0 
CASE WHEN item.size = 'S'  THEN 1 
CASE WHEN item.size = 'M'  THEN 2
CASE WHEN item.size = 'L'  THEN 3 
CASE WHEN item.size = 'LL' THEN 4 
CASE WHEN item.size = 'XL' THEN 5 
END
```

しかし、このように値が増えると読みづらくなってしまうのが難点です。順番を変えたくなった時もソート順を1から振り直すのが多少面倒に思えます。

# `LOCATE()`関数を使う

もっと簡潔に記述する方法として、`LOCATE()`関数を使う方法があります。文字列が見つかった最初のオフセットを返してくれるので、検索文字列の出現順にソートすることができます。しかし下記の例はうまくいきません。

```sql
SELECT * from item
 ORDER BY LOCATE(item.size, 'SS S M L LL XL');
```

## 文字列が部分一致してしまう場合は要注意

上記の例だと、キーワードの長さがそれぞれ違うため、`S`を検索した場合、最初に`SS`の1文字目に一致してしまい、思った結果が得られないという問題があります。

### デリミタを使う

まず思いつく解決策はデリミタを前後につけることです。

```sql
SELECT * from item
 ORDER BY LOCATE(CONCAT(' ', item.size, ' '), ' SS S M L LL XL ');
-- 検索対象文字列の前後にもスペースが必要
```

### パディングする

あるいは、この現象は`item.size`の文字列長が違うことで起こるため、`LPAD()`などでソートキーの長さを揃えてしまうことでも解決できます。

```sql
SELECT * from item
 ORDER BY LOCATE(LPAD(item.size, 2, '_'), 'SS _S _M _L LL XL');
```


他によい方法があったら教えて下さい。
Vue.js（TypeScript）でvue-click-outsideライブラリを使う

Vue.js（TypeScript）で＠types/vue-click-outsideが存在せず、インポートに苦戦したのでメモ書き程度に残しておきます。

##結論
require('vue-click-outside')で読み込んで、directivesに記載

```vue:Compornent.vue
<template>
  <div>
    <button v-click-outside="click">クリック</button>
  </div>
</template>

<script lang="ts">
import { Component, Vue} from 'nuxt-property-decorator'
const ClickOutside = require('vue-click-outside')

@Component({
  directives: {ClickOutside}
})

export default class Compornent extends Vue {
  click() {
    alert('click');
  }
}
</script>
```
【JMH】JMH Gradle PluginでFAILURE: Build failed with an exception. A failure occurred while executing me.champeau.gradle.IsolatedRunnerと言われた場合の対処【Gradle】

`JMH Gradle Plugin`（`me.champeau.gradle.jmh`）で、以下のようなエラーが出る状況への対処法です。

```bash
> Task :jmh FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':jmh'.
> A failure occurred while executing me.champeau.gradle.IsolatedRunner
   > Error during execution of benchmarks
```

自分の場合、ベンチマーク関連のディレクトリ構成が原因でした。

[プラグインのREADMEに記載されている](https://github.com/melix/jmh-gradle-plugin#configuration)通り、`JMH Gradle Plugin`では`src/jmh`配下にベンチマークが有ることを想定しています。
このため、どこにベンチマークが有るかを設定するか、以下のような構成で`src/jmh`配下にベンチマークを配置することで上手くいきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280230/fa3ca27d-d053-f78a-f752-32745793f854.png)

ここで、[ベンチマーク本体は`build.gradle`の`groupId`に合わせたパッケージに配置する必要が有る](https://qiita.com/wrongwrong/items/b6afe8c62f3f4414edc0)点にも注意が必要です。

# おまけ
利用していた`build.gradle.kts`です。

```kotlin:build.gradle.kts
plugins {
    kotlin("jvm") version "1.4.10"
    id("me.champeau.gradle.jmh") version "0.5.2"
}

group = "com.wrongwrong"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation(kotlin("stdlib"))

    implementation(group = "org.openjdk.jmh", name = "jmh-core", version = "1.25.2")
}
```