OmniAICreator/Qiita-1.07M huggingface dataset:
rails+stripeでカスタマーポータル導入

# やること

- stripeで継続課金
- クレジットカードの情報を編集したい
- でもクレジットカードの情報をやりとりしたり安全なフォーム作るの面倒
- カスタマーポータルでstripeに丸投げしよう

# カスタマーポータルの良さ

https://stripe.com/docs/billing/subscriptions/integrating-customer-portal

stripeで継続課金を実装しているとクレジットカード情報の変更を考えないといけない。このやり取りを自分で実装するのもいいが

- クレジットカード情報なので安全なフォームにしないといけない
- 普通にフォーム作るの面倒

だったりするがカスタマーポータルなら`Stripe::BillingPortal::Session.create`でurlを作ってそこに飛ばせばいいし、編集できる項目などをいじりたい場合は管理画面からボタン一つで変更できる。

# 実装

全体の流れは下記だけ

- 管理画面でカスタマーポータルの設定
- buttonからpost
- `Stripe::BillingPortal::Session.create`でurl作成
- urlをredirect

## buttonからpost

```ruby
    <form method="POST" action="/create_customer_portal_session">
      <button type="submit">クレジットカード情報確認・編集</button>
    </form>
```
## `Stripe::BillingPortal::Session.create`でurl作成

routesを作成

```
  post "/create_customer_portal_session" => "users#create_customer_portal_session"
```

```ruby
  def create_customer_portal_session
    session = Stripe::BillingPortal::Session.create({
      customer: current_user.stripe_customer_id,
      return_url: root_url(only_path: false) + '',
    })

    redirect_to session.url
  end
```

customerにはcustomer_idを

## 注意

csrf対策でやり取りできない場合はこのメゾッドだけスキップするなど対策する
備忘録: iOSシミュレーターでテストエビデンスを動画に残す

# 何がしたいのか

シミュレーターでアプリをテストする時、どういう操作をしたか、その結果がどうだったかを残したい。

# どうやってできるのか

Terminal を使って、 ``` xcrun ``` コマンドで録画開始、各種設定が可能です。同じ方法で静止画のスクショも保存できます。

コマンドの基本系：

## 静止画

```
xcrun simctl io booted screenshot <ファイル名>.<拡張子>
``` 

例

```
xcrun simctl io booted screenshot test-login-20210530.png
``` 


## 動画

録画開始：

```
xcrun simctl io booted recordVideo <ファイル名>.<拡張子>
``` 

例

```
xcrun simctl io booted recordVideo test-login-20210530.mov
```

終了：

``` ⌃ – control``` + ```c```

を押して、録画コマンドを終了する。


## 保存先、オプションについて

### 保存先

スクショ、動画ともコマンドが実行された Directory に保存されます。

```
pwd
```

して、確認しましょう。保存先として希望しているフォルダーに移動してから実行すれば、後からコピーなどの手間がなくなります。

### 動画・静止画で共通のオプション

``` --mask ``` を使って、マスク設定が可能です。デフォルトは ignored になっていて、ノッチなどが無視される感じになります。他の選択しは black, alpha です。

参考に実際の画像です: 

``` --mask=black ```

![myScreenshot-mask-black.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155732/e1d7799f-3d63-caf1-0d82-ec0df7e16f1b.png)


``` --mask=alpha ```

![myScreenshot-mask-alpha.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155732/23050dd4-e544-b521-2dea-e13126c8cd79.png)


``` --mask=ignored ``` （デフォルト）

![myScreenshot-mask-ignored.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155732/3e43aa5e-7636-5785-8789-b4df1fa183f2.png)


### 動画特有

保存される動画のcodec設定が可能です。 ```--codec``` で指定できるのは h264 または hevc。デフォルトは hevc です。

同じファイル名を強制的に上書き保存したい場合は ```--force``` を使います。 ※ 静止画の場合は、デフォルトで上書き保存されます。

### 静止画特有

``` --type ``` を使って画像の種類を指定することができます。 例：  ```--type=jpeg```など。デフォルトは png で、使えるオプションは png, tiff, bmp, gif, jpeg です。

## バグなど、躓きそうな点

### Xcode11.0 では iOS13 のシミュレータで画面収録しようとするとこのようなエラーになります

```
An error was encountered processing the command (domain=simctl.SimDisplayScreenshotWriter.ScreenshotError, code=2):
```

これは、組み合わせの問題で、他の組み合わせで試すといいです。

### シミュレーターが起動していない（落ちた）時のエラー

```
No devices are booted.
```

シミュレーターを再起動しましょう。

## help をみたい時

```
xcrun simctl io help
```
Windows Form アプリの表示サイズを固定する

# Windows Form アプリの表示サイズを固定する

VisualStudioで作成したアプリが実行環境によりサイズが変わってしまったりレイアウトが崩れうことがあります。
フォームにAutoScaleModeという列挙型のプロパティがあり、これがデフォルトでは1:Fontになっているため、システムフォントのサイズが変わると、画面のコントロールがリサイズされ、レイアウトが崩れる原因となります。

# デザイナでの対処方法
Visual Studioを開いた時の自動スケールはOFFします。
フォームの配置に関するプロパティのAutoScaleModeの値を0:Noneにします。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/82a11027-21d4-53a7-0472-499f1fc5d971.png)



# コードでの対処方法
InitializeComponent()内に

```C#
Me.AutoScaleMode = AutoScaleMode.None
```

を追加します。

#AutoScaleModeとは　 

AutoScaleModeは、名前空間System.Windows.Formsに定義されています。
アセンブリ:System.Windows.Forms.dll

Windowsフォームでサポートされている、さまざまな種類の自動スケーリング モードを指定します。
このプロパティは次の４つの値を持っています。

None	0	：自動スケーリングが無効になっています。
Font	1	：クラスが使用するフォント (通常はシステム フォント) のサイズに応じてスケールを制御します。
Dpi	2	：ディスプレイの解像度に応じてスケールを制御します。 一般的な解像度は 96 dpi と 120 dpi です。
Inherit	3	：クラスの親のスケーリング モードに従ってスケールを制御します。親が存在しない場合、自動スケーリングは無効になっています。
PRIORVALUE

[Answersで回答する時に使う情報のまとめに戻る](https://qiita.com/Keiji_otsubo/items/9e6e0e946826133eddc7)


# PRIORVALUEを使ったカウントアップ

へぇ、確かにこの方法はできるかもしれない。

PRIORVALUE

この関数は、次の場所でのみ使用できます。
1.割り当てルール
2.入力規則
3.項目自動更新
4.評価条件が [レコードが次の場合にルールを評価: 作成されたとき、および編集されるたび] に設定されている場合はワークフロールール。
5.プロセスビルダーでアクションを実行する数式条件。


[I am looking for a way to count the number of times the Active flag changes](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000BqLqwSAF)

# 選択リストでPRIORVALUEを使う

The formula expression is invalid: Incorrect argument type for function 'PRIORVALUE()'.

```
AND(
ISPICKVAL([Opportunity].StageName, "Closed Lost") ,
ISCHANGED([Opportunity].StageName ),
ISPICKVAL(PRIORVALUE([Opportunity].StageName), "Contract Signed") 
)
```

一瞬これと間違えるんですよね。

```
AND(
ISPICKVAL([Opportunity].StageName, "Closed Lost") ,
ISCHANGED([Opportunity].StageName ),
PRIORVALUE(ISPICKVAL([Opportunity].StageName, "Contract Signed"))
)
```

# PRIORVALUEを新規作成で使った時の注意

これまた意味が分からんかったけど、おそらく新規作成なのに PRIORVALUEを使っていたからエラーになったということだろう。

見た感じ構文的には問題なさそう。

```
AND ( 
NOT( ISNEW() ),
RecordType.Name = '5500 Support Request', 
ISPICKVAL( PRIORVALUE( Status ), 'New'), 
ISBLANK( Plan__c ) 
) 
```

結局これにしたらOKだったようです。

```
AND ( 
NOT ( ISNEW() ), 
RecordType.Name = '5500 Support Request', 
OR( 
ISPICKVAL( Status, 'In Progress'),
ISPICKVAL( Status, 'Review'),
ISPICKVAL( Status, 'Require Additional Info'),
ISPICKVAL( Status, 'Request Complete - Returned to RO'),
ISPICKVAL( Status, 'Closed')
), 
ISBLANK( Plan__c )
)
```

[Validation Rule for a lookup field on the Case object](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000GzjkU)
メンバ変数とローカル変数について

###メンバ変数について
メンバ変数とはクラス内に書かれた変数のことです。
クラス内のメソッドからは自由にアクセスすることができます。

```typescript
class SampleClass {
    // メンバ変数
    private score: number = 0;

    public setScore(num: number): void {
        this.score = num;
    }

    public getScore(): number {
        return this.score;
    }
}
```

###ローカル変数について
プログラムの一部分でしか、使用することができない変数のことです。

```typescript
class SampleClass {
    // メンバ変数
    private score: number = 0;

    private main(): void {
        // ローカル変数
        let num1 = 100;
        this.score = num1;

        console.log(this.score); // 100

        if (true) {
            const num2 = 200;
            // if文内は使用可能
            num1 += num2;

            this.score = num2;

            console.log(this.score); // 200
        }

        // num2はif文内のみ使用可能
        num1 += num2; // エラー
    }
}
```


###メンバ変数とローカル変数の違い
メンバ変数はクラス内のメソッドやコンストラクタからアクセスすることができ、クラス"状態を定義する変数になっています。
対して、ローカル変数は定義したメソッドやコンストラクタからしか、アクセスできなく、各メソッドやコンストラクタの状態を定義する変数になっています。


###まとめ
一見同じような変数ですが、メンバ変数とローカル変数の違いを理解し、使用する場合に最適な変数定義を選択してコードを書いていきましょう。

記事の投稿は初めてなので指摘やコメントなどいただけると助かります。これから色々な記事を投稿していき知識を高めていきたいと思っています。皆さまよろしくお願いします。
巡回群を使ったアート作品制作

群を使った作品を作る課題があったので，制作しました．

群は，m次巡回群だけを使っています．以下の作品は19次巡回群で描画したもので「巡回群の花束」と名付けました．

![巡回群の花束_B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210166/a8bf8d9d-4175-765d-dfb3-8f8a4a2940bb.png)

具体的に，どこにm次巡回群を使ったのかというと，以下の2点です．

- 1枚の花びらの描画
- 花びらの枚数

### 花びらを描くエージェント

1枚の花びらを描くエージェントの行動ルールは以下の3点です．

- 360[deg]の円をm等分した進行方向を持つ．
- 現在の進行方向に対して，ランダムに選択した数字だけ半時計回りに回転させて，次の方向を決定する．
- 足し合わせた結果として単位元になる，つまりは逆元をとった場合に描くことを終了する．

つぎに，花びらの枚数を決定するために，以下のルールを与えました．

- エージェントが行動した回数をm次巡回群に当てはめて，花びらの枚数を決定する．つまりは，1〜m枚の花びらの枚数で1つの花が構成される．

色合い，透明度，先の細さ，1ステップの移動量などの調整方法は省略します．

ざっと，50,000個の花を描くと完成です．

### 書いたコード

https://github.com/Dorebom/art_with_group_theory

### 参考

50個だけ描画した結果が以下です．微生物もしくは雪の結晶みたい．
![figure07 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210166/98d104ca-1129-660b-9942-f42e27cc6bb2.png)

違うパターンを2種類．

![figure19_01a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210166/cb878d89-5b2b-8d98-333f-168cb5176baa.png)

![figure19_02a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210166/8bc10b6b-45c9-f1c3-0d53-8113ff7403d7.png)
[Rails]1対1のアソシエーション has_oneの使用の仕方

# はじめに
プログラミング初心者が、勉強をしていく中で学んだことを整理して、アウトプットするためにまとめたものです。

# has_one(アソシエーション)とは
ある一つデータに別のテーブルのデータ一つしか紐つかない時の関連付けです。（1対1の関連付け）

# 記述例
親（A）と子（B）の関係性となり、記述は下記のようになります。
```A)  has_one :A 
 B)  belongs_to :B
```
「AはBに関連するデータがなくても存在できれば」→　親
「BはAのデータがないと存在できなければ」　→ 子
親が子に対してhas_oneのアソシエーションを持ちます。

#対象例
投稿に対してコメントが一つしか入れられない関係
親：投稿　　　子：コメント

注文に対しての発送先
親：注文　　 子：発送先

このような関係性がhas_oneを用いる時の関係性になります。
AWSでのMFA設定方法まとめ

#MFA(多要素認証）とは
MFAとは、本人確認のための要素を複数、ユーザーに要求する認証方式であるそうです。AWSにおいてもMFAを有効化することが推奨されているので今回設定方法をまとめました

#マネジメントコンソールからの設定
IAMユーザーのMFAを有効化するには、AWS上、IAMのサービスから自分のユーザーを選択し、認証情報タブの「MFAデバイスの割り当て」から「管理」を選択しMFAを設定します。
![スクリーンショット 2021-07-01 9.02.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80028/5560f715-654a-e726-9964-5c405a92ea48.png)

ここでは仮想MFAデバイスを選択します。YubiKeyなど物理的なデバイスを所有している場合はその他を選んでもOKです。仮想MFAデバイスとしてはGoogle Authenticatorなどのアプリをスマホ等にインストールして使用します
![スクリーンショット 2021-07-01 9.04.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80028/df02f6ea-f5f6-ba77-c6fe-a85c25dd0cf9.png)

QRコードを表示させてスマホアプリから認識させる、表示された6桁のコードを2つ入れると登録することができます
![スクリーンショット 2021-07-01 9.04.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80028/f9a83c5b-f5ca-05ca-506e-2211206c657f.png)


#CLI上でのMFAの設定

CLIを使ってAWSの操作をすることもあると思います。その場合にもMFAを有効にしたい場合、コマンドはコマンドラインから入力するので、その都度6桁のコードをいれなければならないの？と思いますが、そんなことはありません。この場合 `sts get-session-token"` のコマンドを用いて一時的な有効期限付きの認証情報を取得し（その際に6桁のコードを入力する）、その一時的な認証情報を環境変数に設定することでCLI上でもMFAを有効にします。

```
$ aws sts get-session-token --serial-number arn-of-the-mfa-device --token-code code-from-token
```
MFAのARNはマネジメントコンソールでMFAを設定した認証情報の画面から取得します。token-code に6桁のコードを入力します。結果、以下のような認証情報と有効期限 (デフォルトでは 12 時間) を含む出力が得られます。

```
{
    "Credentials": {
        "SecretAccessKey": "secret-access-key",
        "SessionToken": "temporary-session-token",
        "Expiration": "expiration-date-time",
        "AccessKeyId": "access-key-id"
    }
}
```

この情報を以下のように環境変数に設定する、もしくは`aws configure`でプロファイル設定を追加することで、一時的な認証情報を使ってAWSにアクセスすることができます。

```
export AWS_ACCESS_KEY_ID=example-access-key-as-in-previous-output
export AWS_SECRET_ACCESS_KEY=example-secret-access-key-as-in-previous-output
export AWS_SESSION_TOKEN=example-session-token-as-in-previous-output
```

永続的なIAM認証情報ではMFAによるアクセスはできないので、CLIでMFAを有効にする際は上記のような一時的な認証情報を使用する必要があります。
変数のスコープについて

###変数のスコープとは
定義した変数が使用可能な範囲（参照できる範囲）を指した言い方になります。
スコープがプログラム全体である変数をグローバル変数といい、関数やメソッド等の内部で宣言された範囲内で使用可能な変数をローカル変数といいます。

###変数宣言の種類
変数の宣言には以下のようなものがあります。

+ const宣言

一度、値を割り当てられると、以降値を変更できなくなる宣言方法になります。
また、宣言される前には、変数にアクセスできません。


```
// 宣言より前に使用することはできない
console.log(number); // エラー

const number = 10;

console.log(number); // 10

// 宣言後に値を変更することはできない
number = 0; // エラー
```

+ let宣言

一度、値を割り当てた後からでも、値の変更が可能な宣言方法になります。
また、宣言される前には、変数にアクセスできません。

```
// 宣言前に使用することはできない
console.log(number); // エラー

let number = 0;

for (let i = 0; i < 3; i++) {
    // 値は何度も変更可能
    number = i + 1;

    console.log(number); // 1,2,3
}
```

+ var宣言

一度、値を割り当てた後からでも、値の変更が可能な宣言方法になります。
また、宣言した前後に関わらず、関数やメソッド内でアクセス可能であり、同じ変数名何度も宣言できる変数になります。
関数スコープ:関数ごとに作られるスコープのことで関数内で使用可能な変数のことです。
※基本的には使用しないこと。

```
// 宣言前に使用可能
number = 20;
console.log(number); // 20

var number = 10;

for (let i = 0; i < 3; i++) {
    // 値は何度も変更可能
    number = i + 1;

    console.log(number); // 1,2,3
}
```

###constとletのスコープについて
先ほど紹介したconst宣言とlet宣言のスコープについて詳しく説明していきたいと思います。
2つの宣言のスコープは、『静的スコープ（レキシカルスコープ）』または『ブロックスコープ』と呼ばれていて、if文やfor文などのブロック内で宣言した物は、内部でしか使用できない作りになっています。

+ const宣言

```
const uModel = {
    name: "",
    id: 0
};

const uName = "ユーザー1";

if (true) {
    const uId = 1;
    console.log(uName); // ユーザー1
}

// 変数の内部情報のみ変更する場合は可能
uModel.name = uName;

// uIdのスコープはif文内なので使用不可
uModel.id = uId; // エラー
console.log(uModel); // { name: 'ユーザー1', id: 0 }
```


+ let宣言

```
let rankModel = {
    name: "",
    rank: 0
}

function letMethod(isExists: boolean): number {
    let score = 0;

    if (isExists) {
        score = 1;

        // 変数の内部情報のみ変更する場合は可能
        rankModel.name = `ランク${score}`;
        rankModel.rank = score;

        console.log(rankModel); // { name: 'ランク1', rank: 1 }

        return score;
    }

    console.log(rankModel); // { name: '', rank: 0 }

    return score;
}

let rank = letMethod(false);
rank = letMethod(true);
rank += 2;

// 変数の内部情報のみ変更する場合は可能
rankModel.rank = rank;
rankModel.name = `ランク${rankModel.rank}`;
console.log(rankModel); // { name: 'ランク3', rank: 3 }
```

###まとめ
varやletは使い勝手がいいが、意図しない値の変更や参照などを避けるために使用は必要最小限にすると良いでしょう。
なるべく、変数のスコープを小さくし、処理の流れや不用意な参照を避ける工夫をすることが大切です。

記事の投稿は初めてなので指摘やコメントなどいただけると助かります。これから色々な記事を投稿していき知識を高めていきたいと思っています。皆さまよろしくお願いします。
tailwindcss を purgecss するときに postcss-sort-media-queries を使ってはダメ

tailwindcss を postcss で purgecss しています。

tailwindcss の ```container``` をメディアクエリで書いていたのですが、
purgecss 後に挙動がおかしい。

``` html
<div class="lg:conteiner">test</div>
```
とかいた場合、1024px 以上のみ ```container``` クラスの指定が作用するのですが、
postcss-sort-media-queries を併用して postcss するとしてと 1024px 未満でも ```container``` の指定が作用しています。

これは、 tailwindcss が ```@media``` の順番で ```contianer``` の振る舞いを操作していたのに、
postcss-sort-media-queries で ```@media``` の指定順番を崩してしまったせいです。

ですので、tailwindcss を purgecss するときは postcss-sort-media-queries を使ってはダメなのです。
AWS Lambdaレイヤーを使ってPostgreSQLに接続する

# 目的
AWS LambdaからVPC内のRDS（PostgreSQL）に接続したい。
複数のAWS Lambda FunctionからDB接続が必要。（接続頻度は低い）

## 前提条件
- 月1回夜間に動作するバッチプログラムであるためコネクションプーリングは不要。
- 接続頻度が低いためAmazon RDS Proxyは利用なし（費用が地味にかかるため）
- 言語：Python 3.8
- DB：PostgreSQL 11
- Lambda FunctionのVPC・セキュリティグループ・IAMロールの設定の説明は割愛

## DB接続方法
DB接続用のライブラリは「psycopg2」を採用。
全てのLambda Functionにライブラリをアップロードするのは避けたい。
そこで、レイヤー機能を利用することにする。

## レイヤー作成
### ライブラリ用意
レイヤーにアップロードするライブラリを用意。
下記から取得できる。

https://github.com/jkehler/awslambda-psycopg2

「with_ssl_support」をダウンロードする。
今回は、「psycopg2-3.8」を利用する。

### ソースコード
DBコネクションを取得する共通プログラムを用意する。
接続情報はSSMパラメータから取得するようにした。

```python:db.py
import os
import json
import boto3
import psycopg2

from psycopg2.extras import DictCursor

ssm = boto3.client('ssm')

def db_connect():
    
    DB_HOST = ssm.get_parameter(
        Name = 'db.host',
        WithDecryption = False
    )['Parameter']['Value']
    DB_DBNAME = ssm.get_parameter(
        Name = 'db.dbname',
        WithDecryption = False
    )['Parameter']['Value']
    DB_PORT = ssm.get_parameter(
        Name = 'db.port',
        WithDecryption = False
    )['Parameter']['Value']
    DB_USER = ssm.get_parameter(
        Name = 'db.user',
        WithDecryption = False
    )['Parameter']['Value']
    DB_PASSWORD = ssm.get_parameter(
        Name = 'db.password',
        WithDecryption = True
    )['Parameter']['Value']
    
    conn = psycopg2.connect(
        host=DB_HOST,
        dbname=DB_DBNAME,
        port=DB_PORT,
        user=DB_USER,
        password=DB_PASSWORD
    )
    return conn
```

### デプロイパッケージ作成
ダウンロードしたライブラリと作成したソースファイルをzip化する。
ここで注意点としては、パッケージフォルダ名は「python」とすること。
また、ライブラリの「psycopg2-3.8」フォルダ名を「psycopg2」に変更する。

ディレクトリ構成

```
python/psycopg2
      /db.py
```
 
pythonフォルダをzip圧縮する。

### アップロード
AWS Lambda画面のメニューからレイヤーを選択
↓
「レイヤーの作成」を選択
↓

- 名前：db
- 「.zip ファイルをアップロード」を選択して用意したzipをアップロード。
- ランタイムは「python3.8」を選択。

「作成」ボタンを選択して完了。

## レイヤーの利用
作成したレイヤーを利用する場合は、実行するfunction内でimportする。

```python:test.py
import db # レイヤー化したライブラリ

def lambda_handler(event, context):

    try:
        conn = db.db_connect()

# 以下省略

```

## まとめ
RDSProxyを利用するまでも無いケースやコスト面で利用を避けたい場合などはライブラリを利用することで接続が可能となる。
複数のファンクションから共有したい場合は、レイヤー化すると便利。

ただし、DB接続が頻発する場合はコネクションプーリングを活用するためにRDSProxyを使うこと。
画面共有に備えて、Windows Terminal のフォントサイズを、すぐに変更できるように準備

# 経緯

- リモートワークで、ターミナルを画面共有するとき、「文字ちっさくてみえん」ってならないように
- フォントサイズを、すぐに変更できるように準備しておくのが、最近の「仕事できる人」だと思う

![ss.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083912/cc149252-06c8-491b-36e1-8df5519cadd7.gif)


# 環境

- Windows 10
  - 日本語キーボードを接続
  - ホイール付きマウスを接続
- Windows Terminal バージョン: 1.8.1521.0

# 操作

## マウスによる操作

- マウスのホイールを使う操作が一番高速に操作できそう

| 動作               | 操作                             |
| ------------------ | -------------------------------- |
| フォントサイズ縮小 | Ctrl 押しながら ホイール下(手前) |
| フォントサイズ拡大 | Ctrl 押しながら ホイール上(奥)   |

## 日本語キーボードによる操作

- リセットは、Ctrl + [0] で

| 動作                   | キー操作               |
| ---------------------- | ---------------------- |
| フォントサイズ縮小     | [Ctrl] + [-]           |
| フォントサイズ拡大     | [Ctrl] + [Shift] + [-] |
| フォントサイズリセット | [Ctrl] + [0]           |


## Numpadによる操作

- Ctrl + [numpad 0]はリセットにならないので注意

| 動作               | キー操作            |
| ------------------ | ------------------- |
| フォントサイズ縮小 | [Ctrl] + [numpad -] |
| フォントサイズ拡大 | [Ctrl] + [numpad +] |


# 拡大鏡 (おまけ)

- [Win] + [numpad +]
- Google Meetの場合、ウィンドウ共有では拡大せず、画面共有なら拡大する

![loupe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083912/4728c6d4-6f73-34ca-4015-bbcc6ba558d9.png)
CMSって　Redmine、Wordpress、还是什么？

https://qiita.com/EasyCording/items/44dd27c6b897b0d7d82b

ある程度、Ｒｅｄｍｉｎｅを使いこなす気になってきたので、すこしTOPICがずれるので
別タイトルの記事にした。

#背景
仕事の役割が少し変化してきて、最近はSDGS絡みの話の延長で、情報発信の仕方で
なんか知恵が無いかと考えている。

もちろん、このような情報発信に関しては、ランクがあって

* 社内発信（あくまで自部門）
* 社内発信（コーポレートとしての社内発信）
* 社外発信（ＷＥＢページ）

　自分としてはコンテンツの発信に当たり、やはり記事は使いまわしをしつつ、成長していく形としたい。つまり、最初からそう言う情報活用を視野に入れて、データの展開を計画しておかないといけない。特に、今回は自分が担当者レベルの解決で良いのか、それとも経営者か、それとも国際社会なのか・・・
　そこまで考えたうえで、仕事の範囲を定めていかなければならない。（こういうのを外注に頼るといけない。部分的な解など本質的には意味がないからである）

#問題
　今回の問題であるが、情報発信に当たり、サイト設計上求められている事としては、

* プロジェクト管理なのか？
* ＣＭＳなのか？
* ＷＥＢアプリなのか？

　いま現在は、自分のプロジェクトの範疇で、なんとなくであるがＲＥＤＭＩＮＥのＷＩＫＩページに情報を押し込んでいる。しかしながら、求められていることは最終的には、世の中の人の人眼につく、インターネットのホームページであろう。
　この流れで言うと、やはりWordpressのようなツールが最終的には理想である。データプレゼンテーションなどの、特殊なサービスを追加するのであれば、やはりWeb-App化が必須であろう。

#悩み
　現状の自分の立ち位置からして、立派なホームページデザインに行くには、いきなりWEB-APPの画面設計は荷が重い。（一番良いのは、それこそＪＳライブラリを駆使した、本格的な設計であるが、単なる企業のSDGS広報であれば、そこまではリソースがかけられない）
　今のところはVUE.JSで拡張しやすいようなフレームワークと、WEBパーツを組み込みつつ、WORDPRESSライクなソフトのモデルデータを使って、WEBに埋め込むのが良いように思われる。（あくまでREACTとAngularは使わない。企業とタッグしたＯＳＳは、最終的にはろくな方向には進まない）
　REDMINEのWIKI関係のデータベース構造と、WORDPRESSのCMS関係のデータベース構造を、うまく接続する仕組みが欲しい。
　しかしながら最終的に、一番負担になりうるのは、やはりツールの学習コストであろうと思われる。

#解決手段
　やはり残されるべく選択肢は、我らがEXCELに行きついてしまう。
　これまで右往左往して、いろいろ考えたのであるが、EXCELシートをエディタ代わりに使うのが
いまの日本人の90%合意と言ったところか・・・

　余談であるが、最近小学校でＩＰＡＤタブレットを配布しているらしい。
　これからの子供たちは、いったいどんなアプリを使って、成長していくのであろうか？
　真っ先にＥＸＣＥＬが使えないＩＰＡＤを使って、どうやってＤＸ人材を育成していくつもりなのか、文部科学省（はたまたデジタル庁なのか？）に問い合わせしたいレベルだ。

#最終方針
　これから次のことを検討する。

* REDMINEのWIKIデータ構造
　これは元々ＣＭＳツールではないから、あくまでredmineの日常使いの観点で、仕方なく使っている。
そもそもRedmineの中でWIKIを主に使うことを想定している人は、まず居ないのではないか？
（それなら、オンプレミスのWIKIペディアを自社で立ちあげたらいいやん？　と思う）

* WIKI、WORDPRESSの互換性調査
　データ仕様がそもそも異なるのではないか？　気分的にはwordpress側がWIKIに歩み寄ってほしい気がする。

* Office365,Teams
　現時点での最大の癌は、コーポーレートで採用しているOFFICE365および、それに付随するTEAMSとかいうクソッたれのアプリ群である。（本当のクソったれは、それに気が付かない情シス部門なのか、はたまた経営ＴＯＰなのかもしれないが）
　参考意見　https://deginzabi163.wordpress.com/2019/04/27/%E3%81%90%E3%81%A1sharepoint%E3%81%AF%E7%B3%9E%E3%81%A7%E3%80%81%E5%B0%8E%E5%85%A5%E3%81%97%E3%81%A6%E3%81%99%E3%81%90%E6%B0%97%E4%BB%98%E3%81%8F%E3%81%AE%E3%81%AB%E3%81%AA%E3%81%9C%E6%97%A5/

　今のところは、彼らの努力に忖度しつつ、いかにＯＳＳを使い込んでいくのかが課題である。
（しかし言うても、ユーザーに100%理解が得られるのはEXCELであって、入り口戦略と出口戦略はEXCELに落として、ファイルサーバーに保管するという業務フロー設計を忘れてはいけない）
　
　このことはＩＴベンダーさんにも言っとくが、大企業はEXCELしか興味が無いのである。（というか、異星人にはEXCELしか共通言語がないと考えた方が良い）
rspec init を実行したら LoadError:   cannot load such file が発生した

#問題

rspec init　を実行したら以下のエラーが発生しました。

```

rspec init

An error occurred while loading ./init.
Failure/Error: __send__(method, file)

LoadError:
  cannot load such file -- 　以下略

```


#解決策


gem がインストールされたいないみたいです。
そこで、gem をインストールしたら解決しました。

```
gem install rspec　
```

を実行した後、再度実行します。

```
rspec --init
  create   .rspec
  create   spec/spec_helper.rb
```

解決しました。
ファイルが作成されました。
"Chia" 正規プールのテストがPhaseー2 に入った！

https://www.chia.net/2021/06/30/pooling-protocol-phase-2.html

# ”Pooling Protocol Testing Entering Phase 2”　　
２０２１/０６/３０ 付　　　Bram Cohen がいるNY時間でしょおネ

ん〜〜、、　なになに、、、
###”我々は正規プール実施のための第２フェーズに入った、、”、、、、、、、👍  って　最初5月末リリースって言ってなかったっけ、、、信じてたのに、、、

”新たに９０００行のコードを書き加え、、、現時点最高のプールプロトコルだと思う”　　そりゃ凄そうだ、、

詳細はGitHub のpools.testnet9 を見てみよう

###しかーし、”アメリカは独立記念日のホリデーウイークなので、、、、、、”、、、しっかり祝日祝うのね、、、、　😅

早くとも1.2.0 のリリースは7月5日の週、、、、　　早くとも、、、、遅いといつだろ、、、、

ここポイントです！
###”プロットするなら1.2.0を待て”だそうです、、、、、😅


チーン　　　お後がよろしい様で、、、、、、　　To be continue,,,,,
Twitter経由でお誘いいただき、初めてQiitaさんとLightning Talkしてみたので、その感想

https://increments.connpass.com/event/216557/

【LTイベント】Qiita Night〜記事投稿イベントお疲れ様会〜 というものが昨晩ありまして、初めてそこでLightning Talk したのでその感想文です。慣れない場所で突然喋ってと言われた！でも興味は当然ある！などという開発者の参考になると嬉しい。



## 筆者スペック

- 2003年に新卒未経験で「ベンチャー」的企業に入社。顧客は大企業。
- パッケージソフトの開発、保守。途中で海外赴任したり、産休とったり育休とったり、のらりくらり生き延びてる。
- 最近になってようやく、わりとQiitaに雑記を書いている。会社の資産と言うより自分の資産を作りたい気持ちからかもしれない。色々手は動かしていたいし、世の中をみていたい。意欲だけはある。
- で、目に留まったと言ってくださっていた。



## 感想

### なぜ受けようと思ったか

本当は自社でもそういうイベントを外向けにやればいい。Qiita書いているのも半分は自分の資産、半分は本当に自社の知名度に貢献したら良いと思って書いている。しかし実際外向けに喋るという時、恥ずかしいクオリティの発表はできない。ましてや自分が会社内で企画とかそうとう骨折れ（略

いえ、お声掛けいただいて本当に有り難かったです。

もちろん個人として普通に、普段話す社内の開発者とは別のドメイン、ビジネスと関わる参加者にまじり、お話させていただけるなんてまたとないチャレンジの機会。刺激を受けたい。というか楽しそう。

### 心配だったこと

#### 1.「私で良いんでしょうか？」

...に尽きる。本当に私はどちら様？だと思っている。普段は社内で知れている顔だから偉そうに喋れるけど、私のバックグラウンド、名前すら不一致の状態でいいお土産を渡せるお話ができるだろうか。

#### 2. チビが絶対ウルサイ時間帯

私事ですが4歳娘、2歳息子が家におります。勉強会の類は聴衆として「ながら聴き」は何度かしているものの、この「晩ごはん～お風呂」の時間帯にましてや自分が人様の前で喋るなど成立するのだろうか。

### そんなことは杞憂で、結果、良かったこと

初めての世界との遭遇。
自分の場合は誘われてのラッキーなケースだったので、変に責任を進行各位に放り投げた気分で臨めたというか、変な表現だが、チヤホヤしてくださって恐縮した。嬉しかった。私に喋ってくれと言ったのは皆様ですよ～という無責任でいられた。2番目の心配についても最初の段階でお伝え済みだったので、それにも関わらず「ユルい雰囲気でよし」と言っていただけていたので、ヨシ！という気分でした。そういう事務的な懸念は先に取り除いておくのは大事ですよね。


### どういう準備をしたか

普段の社内でのプレゼン的な機会同様だが、聴衆に何を持ち帰らせるか。結果なんだか私の提供できるものは知識じゃないのです、経験とか、マインドみたいなものとかです。というかただの経験談です。結局私が書いたものによって声をかけていただけたわけなので、その記事タイトルをともかく紹介するなどにしました。

考えた挙げ句、以下に絞った。

- 自分がどちら様であるかを伝える。
- 会の趣旨に則り、「[新人プログラマ応援 - みんなで新人を育てよう！ - Qiita](https://qiita.com/official-events/63aa63fd921659fb3b5d)」にあやかって、自己紹介がてら、私の新人時代の話を振り返ってみたい、という方向。

リアルな現場ならどういった方々に語りかけることになるのかを想像。で、**参加者各位と目線が合ったら良いな**、というイメージで望んだ。難しいですがここに尽きますよね、せっかくなので「お土産」を渡したい。しかしどういったところに興味を持っていただいて参加されているのか。


### 参考にしたスライド等

参考にしていたらもうちょっとマシな見栄えのものができていたはず...なのだが、いえ皆、スライド作るの上手すぎるし、私は下手すぎる。しかし大事なのは見栄えというよりそのテキスト、という意味で、Markdownで**テキストに注力。** 以下ツールで仕上げた。

https://qiita.com/e99h2121/items/a115f8865a0dc21bb462

https://qiita.com/msp0310/items/0e54f69457f81bc64754

![slides.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/8ccfb657-cf18-b52e-6c32-0c6a529563c9.gif)


[![thumbnail](https://files.speakerdeck.com/presentations/f31111d9e0e04f4aa6172c63ca57d104/slide_2.jpg?18439828?17290372&quot)](https://speakerdeck.com/e99h2121/watasigaxin-ren-datutakoro)

内容はこの記事では触れずまた別の場で。ですが、リモートでのプレゼンは反応が見えづらいのがやはり難点、というか自身にとっての不安。進行各位に是非マイクONで反応して欲しい旨最初に伝達。


## まとめ

結果時間は簡単に、そして無事に経過。途中はチビを眺めながらイヤホンで聴いていました。緊張していない自己暗示をかけたいと思いながらやはり緊張はしていて、Twitter見たり社内Slack見たりしながらソワソワして各位の発表も聴いていた。最終的に、初めて記事というのは一方通行なのではなく相互作用までだなと実感した。

https://twitter.com/e99h2121/status/1410184815912001538?s=20

チャレンジの気持ちと冒険心、体力、自分の私生活、色々ありますが、お誘いくださった各位をリスペクトしつつ一緒に場と、業界を盛り上げることにつながっていたとしたら幸せな時間だったと言えると思います。

目線が偉そうになってしまいましたが、私の運の良さを差し引いても、ぜひ今後とも記事だけでなく人間として関わっていけたらなという経験でした。普通に、同じ業界に知り合いが増えるのは嬉しい。

## 補足

以上Twitterでお声掛けいただいて、初めて公共の場で「Lightning Talk」をした、という感想文。

https://zenn.dev/e99h2121/articles/0390fd45add338

タイトルは実は以前Zennの方に書いた上記記事の、姉妹記事的な感覚で書きました。
記事にするまでがLightning Talk。お粗末様でした。改めて大変ありがとうございました :bow:
windowsのgitコマンドのgithubマルチアカウント運用

## 環境
Windows10
git version 2.28.0.windows.1
wsl ubuntu git version 2.25.1

## 対象読者ではない人たちへ
git credential helperってなに？って人はこの記事を読む前に、[こちら](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%84%E3%83%BC%E3%83%AB-%E8%AA%8D%E8%A8%BC%E6%83%85%E5%A0%B1%E3%81%AE%E4%BF%9D%E5%AD%98)を読もう

この話と`git config user`,`git config email`は全く違う話で、これを混同してしまう人はこの記事を読む前に公式ドキュメントなどを読もう。

## 本題
windowsでgitを普通にinstallしたらおそらく標準で [Git-Credential-Manager-for-Windows](https://github.com/Microsoft/Git-Credential-Manager-for-Windows
)がcredential.helperに設定されている
`git config --system credential.helper`がmanagerになってたら多分そう。

※wslでUbuntuを入れている人でそのへんを統合したい人は、Ubuntuの中のgitには、`git config --system credential.helper '/mnt/c/Program\ Files/Git/mingw64/libexec/git-core/git-credential-manager.exe'`としてしておこう。

これは、windowsのkeychain的な存在である"資格情報マネージャー"アプリ(スタートの検索のところに打てば出てくる)の、Windows資格情報と連動している。
`git:https://github.com`と書かれている認証情報が、それだ。

で、このGit-Credential-Manager-for-Windowsにはnamespaceという機能があるらしい。

https://github.com/microsoft/Git-Credential-Manager-for-Windows/blob/master/Docs/Configuration.md#namespace

これは、git configで設定可能な項目で、標準では `git`で、前述の`git:https://github.com`のprefixにあたる。

だから、別のアカウントで運用したいフォルダで `git config --local credential.namespace name xxx` (xxxはgit以外の好きな文字列)とすれば、資格情報マネージャー上では、`xxx:https://github.com`と書かれている認証情報となり、複数管理が可能となるのである。

2021年にもなってやっとハックではないgithubマルチアカウント運用方法を見つけたのである。

### 手順

メインで使っているいつものgithubアカウントとは別のsubアカウントで登録済のprivate-repositoryをcloneする手順をまとめる

一応はwindowsでの話なので、PowerShellか、wsl上のlinuxかあたりでオペレーションすることを想定している

```
$ mkdir {repo} # cloneするのではなく先に空のディレクトリを作る
$ cd {repo}
repo/ $ git init
repo/ $ git config --local credential.namespace name xxx # xxxは"git"以外の好きな文字列だが、githubアカウント名などが妥当だろう
repo/ $ git remote add origin {repo_https_url}
repo/ $ git pull # ここでGUIかCUIでusername/passwordを尋ねられる (2faを有効にした人はpasswordのかわrにpersonal_access_tokenを入力すること)
```

これだ。
あとはWindowsの`資格情報マネージャー`を起動し、Windows資格情報に`xxx:https://github.com`が追加されていることを確認しよう。

認証情報を消したくなったら、`資格情報マネージャー`を起動し、Windows資格情報に`xxx:https://github.com`を削除しよう。次回のgit-pull時に再びusername/passwordが尋ねられるはずだ。

### vscode上において

vscodeで、Git-Credential-Manager-for-Windowsを使ったら、vscodeのgithub拡張機能が、vscodeのログインを求めてくる。平時、シングルアカウント運用をしている時は両方同じアカウントなので気にしないがこういうときはややこしい。
別にvscodeに認証情報を登録しなければgitコマンドが使えないわけでも、登録すれば使えるようになるわけでもない。これはvscodeがマルチデバイスで設定値動機をするとかLiveShareするときに使うってだけで、git credentialの動作には影響しない。

vscodeのにわたす認証情報と、Git-Credential-Manager-for-Windowsの(少なくとも)namespaceで管理する認証情報は、全く別物と割り切ろう。(たとえ設定値が同じでも)

- default account: いつも使うアカウント。vscodeにわたす。namespaceを指定しないで使う。
- sub account1: サブアカウント1。vscodeには渡さない。namespace "sub1"を指定して使う。
- sub account2

というような運用が良いだろう。
subの方をvscodeにわたす人も居ると思うのでそれもいいだろう。
ただしvscodeはシングルアカウント前提の設計らしい([出典](https://github.com/microsoft/vscode/issues/98448#issuecomment-720757652))ので注意。
git pushで急に403エラーが出た

## 見慣れないエラー
2021年6月30日。昨日まではちゃんとpushできていたのに、急にpushでエラーが出るようになった。GitHubがダウンしたのかと思ってTwitterを見ても、誰もそんなことは言っていない。

## エラーメッセージ
```
remote: Password authentication is temporarily disabled as part of a brownout. Please use a personal access token instead. 
remote: Please see https://github.blog/2020-07-30-token-authentication-requirements-for-api-and-git-operations/ for more information. 
fatal: unable to access 'reponame': The requested URL returned error: 403
```

## 解決方法
PCに保存されている資格情報を削除して、GitHubのPersonal Access Tokenでログインし直す。

## 解説
### もうパスワードは使えない
まず前提として、**GitHubへのpushやpullがパスワードで認証できなくなる**ということが公式で発表されている([参考](https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/))。これは2021年8月13日から実施される。

今回のエラーはこれが原因である。確かに自分はGit pushをパスワードで認証していた。少しフライングだったのは謎だが、もうパスワード認証は受け付けてくれないということだ。ではどのように認証すればいいのかというと、**Token**か**SSH Key**を使う必要がある。
Tokenの取得方法はこの記事に詳しく説明されている。

https://qiita.com/shiro01/items/e886aa1e4beb404f9038

### Tokenを登録するには
しかし、取得したTokenはどのように登録すればいいのかが探しても見つからなかった。既存のリポジトリで新しくTokenを登録するにはどうしたらいいのか？答えは、**PCの資格情報の削除**だった。

そもそも、今までgit pushをパスワード認証なしでできていたのは、Windwosであれば資格情報マネージャー、Macであればキーチェーンがパスワードを保存してくれていたからだ。あまりに当然すぎて忘れてしまっていたが、これらに深く感謝して**GitHubの認証情報を削除**することで、次回以降のpushでは認証を求められることになる。この時に、TokenかSSH keyを選べるので、Tokenを選んで認証すれば成功となる。

## まとめ
今までパスワード認証だった人がToken認証にする場合は、資格情報マネージャー/キーチェーンからパスワードを消しましょう。
2021年JetsonNano環境構築(画像検出用)

2021年6月現在のjetson環境構築方法を記載します。
個人的な備忘録が主なので読みにくい記事になっております。予めご了承ください。

対象はPytorchを使ったMobileNet,Yolov5です。
tensorflowやtensorrtも一応一緒に入ります。

##環境
* ハードウェア  
JetsonNano DeveloperKit

* python関係
pyenv等を使用しませんが、同じ方法でpyenvも使えます。
ただ、pythonのバージョンを変えたい場合は別途違うやり方が必要ですので、下記のバージョンでやる事を推奨します。
(依存の強いライブラリも一緒に書きます。何かあればバージョンの確認もして下さい。)
　　python：3.6.9
　　pytorch:1.8.0
　　torchvision:0.8.1
　　tensorrt:7.1.3.0
　　tensorflow:1.15.5
　　opencv:4.4.0
　　numpy:1.18.5

##何はともあれイメージ作り
まずは、イメージを作成します。
Nvidiaさんが下記のサイトに詳しく書いてありますので、Google先生に翻訳をしてもらいつつ書き込みましょう！
https://developer.nvidia.com/embedded/learn/get-started-jetson-nano-devkit#write

##セットアップ画面
Ubuntuと同じです。
ゾーン・言語・キーボードを日本（東京）にして、
名前とパスワードを設定しましょう。
後は、ディフォルトのままで良いと思います。
（SWAP領域は後程作成します。）

##アップデートと管理者パスワードの設定
管理者パスワードの設定は忘れがちですが、有事の際に困る事が多いので忘れずにやりましょう。

```
sudo apt update
sudo apt upgrade
pip3 install -U pip
sudo su -
passwd root
```

##リモートデスクトップ接続
```
sudo apt -y install xrdp
sudo apt install -y xfce4 xfce4-goodies
echo xfce4-session > ~/.xsession
startxfce4
```

##フルパワー化
USBコネクタからの給電をしている方は最初のコマンドは実行しないでください。どうやら、j48ピンのショートが必要らしいです。（試してはいないです。）

```
sudo nvpmodel -m 0
sudo jetson_clocks
```

##スワップ領域作成
```
git clone  https://github.com/JetsonHacksNano/installSwapfile
cd installSwapfile
./installSwapfile
sudo reboot
```

##Python環境１(基盤)
まずは、jetcardで基盤を整えます。

```
git clone https://github.com/NVIDIA-AI-IOT/jetcard
cd jetcard
./install.sh
```

##Python環境２（最新のPytorch）
出来るだけ最新のpytorchを使いたいので、
pytorch,torchvision,numpyを一度削除して、最新版をインストールします。

```
pip3 uninstall pytorch torchvision numpy
```

下記サイトのInstallationを参考にpytorchとtorchvisionをインストールします。
torchvisionの＜version＞にはv0.8.1の様に置き換えします。
バージョンに関しては、この記事の最初を確認して下さい。

https://forums.developer.nvidia.com/t/pytorch-for-jetson-version-1-9-0-now-available/72048


##python環境3(opencv)
numpyとopencv-pythonのインストールを行います。
バージョンは、記事の最初に記載した依存関係により入れています。

```
pip3 install numpy==1.18.5
pip3 install opencv-python==4.4.0.42
```

## 終わりに
修正された？かもしれませんが、yolov5は今のpythonバージョンだと古いというエラーがプログラムで出るようになっていますので、エラーをコメントアウトして下さい。
【TP転職市場PJ日記その8】新規機能「助っ人一斉通知」機能を実装

#ここまでのTPサービス
・リリースした。
・httpsできなかったけど後日出来るようになった！

#現在のユーザー数と登録データ数
41名!!!!　感謝です！！ですがまだまだ精進していこうと思います。
という訳現状の強み弱みを改めて整理して施策を実施していこうと思う。

#このサービスの強み（現時点）
・情報が閉じているので欲しいと意思表示しているユーザーには適切な情報は少なくとも渡せる。
・共通の興味（ここでいうとウイイレのTP）があるユーザー数等がある程度知れる。

#このサービスの弱み（現時点）
・利用ユーザー数が一定数以上ないとサービスの活性化が望めない
・利用用途や利用時期が限定的になっている。
（リーグのシーズンが終了しないと使いにくい）

#直近のTPチームの運営様のツイートをみてみると…
こんなツイートがちらほら…
![TP.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570502/5ac28a53-d53b-07ad-746d-023a01c01748.png)
![TP2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570502/5f75f286-6d93-3a05-240f-8f47beed8ae9.png)

という訳でこのツイートから要件を仮定で詰めてみる。

#要件
・突発的にＴＰやってくれる人が必要なケースがある。
・即効性、拡散性があるとしてTwitterを使って情報拡散している。
・返信の媒体は特に問わない。

#課題点
・この手の助っ人募集も情報が埋もれそう。

#という訳で追加機能として一先ず白羽の矢をたてましたスバリ…
・助っ人通知機能


#さぁ、もう設計していこ
　・今回はバッチ投入方式で行こうと思う
　・当機能はTP運営ユーザーが投稿、受信設定は全ユーザーで設定してもらう。
　・各TP運営ユーザーが投稿→メール送信という流れ
　・ユーザーは1日一回までの投稿の制限を設ける
　　→大体23時～という書き込みが多いから一日一回で十分と判断。
　・投稿して一定時間が経過すると通知を受け取るユーザーにメールが飛ぶ
　・投稿した日の24時を経過したらリセットされる。
　　→試合が終わって次の試合の登録も最短できるよ。という形を作っておく。
　・投稿から発射まで3分～5分待たせる（募集内容を間違えた等あった場合用に）
　　→いったん5分にする。
　・文面はユーザーが編集できるフリーテキストにする。
　　→件名は固定で本文は一部分をユーザーに編集させる。

#画面構成
・送信一覧画面（送ったか、送る予定の物が見れる一応過去に送った物も見れる）
・投稿画面、編集画面（これは募集画面をまんまパクる）


#これが出来たら
　・ＴＰチームの運営様に営業に行こうかと思う。営業したことないｗ　これも経験という事でがんばろ。
[tips]エイリアスの登録方法

こんばんは、プレイライフの熊崎です！
本日は、業務を効率的に進めていく上で欠かせないエイリアスの登録方法について記事を書いていきたいと思います！

## 登録方法（今回はzshでの登録を想定しています。）

ターミナルで以下のコマンドを入力します。

```
vi ~/.zshrc
```

```.zshrc
// alias エイリアス時のコマンド＝'エイリアスに指定したい、元のコマンド'
alias gc='git checkout'
```

入力後、`:wq`で上書き保存を行います。
その後ターミナルで以下のコマンドを入力します。

```
source ~/.zshrc
```

これで設定完了です。
あとは、実際にエイリアスに設定したコマンドを入力してコマンドがちゃんと動作すれば終了です！

## 最後に
たったこれだけの作業で、日々の業務が楽になるのでエイリアスを使用したことがない方は是非設定していただければと思います。
DockerのCentOSイメージで作ったコンテナでLinuxのコマンドの勉強してみた

# 1. 概要

- Linuxの学習をしているときに、実際にコマンドを入力して勉強したかったが、macOSでは微妙に異なる
- `Docker`で`CentOS`イメージを使用してコンテナを作成し、その中で勉強した

# 2. 前提条件

- `linux`のディレクトリ構成やコマンドがなんとなくわかる
- `Docker`を触ったことがある

# 3. Let's Try

## 3.1. 任意のディレクトリに`CentOS`イメージのコンテナを作成し、コンテナに接続する

`Docker Hub`などでイメージとタグも指定する場合は確認すること
イメージのみ指定する場合は自動で`:latest`タグを指定したことになる

```
$ docker pull centos #Docker Hubからcentosイメージをローカルにpull
$ docker run -it centos #centosイメージを用いてコンテナを作成し、コンテナに接続
```

`-it`オプション

- -i(interactive) コンテナの標準入力(STDIN)にアタッチ
- -t(tty) 疑似ターミナル(pseudo-TTY)を割り当てる

## 3.2. ユーザー情報の設定

### 3.2.1. 現在のユーザー情報を確認

```
# whom #現在のユーザーの表示
> root
# id #現在のユーザーのID情報
> uid=0(root) gid=0(root) groups=0(root)
# cat /etc/passwd #現在のユーザー一覧
> 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
systemd-coredump:x:999:997:systemd Core Dumper:/:/sbin/nologin
systemd-resolve:x:193:193:systemd Resolver:/:/sbin/nologin
```

### 3.2.2. ユーザー追加、確認

```
# useradd -D #ユーザー新規作成時のデフォルト値を確認
>
GROUP=100
HOME=/home
INACTIVE=-1
EXPIRE=
SHELL=/bin/bash
SKEL=/etc/skel
CREATE_MAIL_SPOOL=yes
# ueradd sampleuser #デフォルトの設定でユーザーを作成する
# id sampleuser
> uid=1000(sampleuser) gid=1000(sampleuser) groups=1000(sampleuser)
# cat etc/passwd | grep -n sampleuser #sampleuserが登録されているかを確認 
> 17:sampleuser:x:1000:1000::/home/sampleuser:/bin/bash
# ueradd sampleuser2
# cat etc/passwd | grep -n sampleuser
> 
17:sampleuser:x:1000:1000::/home/sampleuser:/bin/bash
18:sampleuser2:x:1001:1001::/home/sampleuser2:/bin/bash
```

### 3.2.3. ユーザーの設定変更

- 最初にしておくべきrootユーザーのパスワード変更など

```
# yum -y install sudo
> ...
# yum -y install passwd
> ...
# passwd sampleuser #パスワードを変更する
New password: 
Retype new password: 
passwd: all authentication tokens updated successfully.
# echo 'sampleuser ALL=(ALL) ALL' >> /etc/sudoers #sudo設定 
```

### 3.2.4. ファイル作成、権限変更

```
# su - sampleuser
> ... #sampleuserに変更

$ cd /home
$ sudo touch sample.txt
$ ll sample.txt #bashrcにaliasでll=ls -alを登録済みの場合のみllで指定
> -rw-r--r-- 1 root root 0 Jun 30 16:36 sample.txt
$ chmod 755 sample.txt #権限を数値形式で変更
$ ll sample.txt
> -rwxr-xr-x 1 root root 0 Jun 30 16:36 sample.txt
$ chmod u+s sample.txt #SUIDを設定
$ ll sample.txt
> -rwsr-xr-x 1 root root 0 Jun 30 16:36 sample.txt
$ chmod g+s sample.txt #GUIDを設定
$ ll sample.txt
> -rwsr-sr-x 1 root root 0 Jun 30 16:36 sample.txt
```

参考：[grep](https://eng-entrance.com/linux-command-grep)
参考２：[useradd](https://kazmax.zpp.jp/linux_beginner/useradd.html)
参考３：[sudoersの設定](https://qiita.com/progrhyme/items/6f936033b9d23efb1741)
参考４：[chmod](https://qiita.com/shisama/items/5f4c4fa768642aad9e06)
postcss で purgecss すると tailwindcss の breakpoint が消えてしまう

``` css:tailwind.css
  .lg\:bg-red-700 {
    --bg-opacity: 1;
    background-color: #c53030;
    background-color: rgba(197, 48, 48, var(--bg-opacity));
  }
```
というCSSがあり、

``` html:index.html
<div class="lg:bg-red-700">Hello</div>
```
という HTML があります。

purgecss の設定ファイルは以下のようになっており、

``` js:postcss.config.js
const purgecss = require("@fullhuman/postcss-purgecss")

module.exports = {
  plugins: [
    purgecss({
      content: ["./**/*.html"],
    }),
  ],
}
```

これで postcss を実行すると tailwind.css の ``` .lg\:bg-red-700 ``` が消えてしまいます。

おそらく ```:``` をエスケープしている ```\``` が入っているためヒットしないのだと思います。

なので、公式サイトを頼りに postcss.config.js の設定を書き換えます。
```defaultExtractor``` の行を追加します。


``` js:postcss.config.js
const purgecss = require("@fullhuman/postcss-purgecss")

module.exports = {
  plugins: [
    purgecss({
      content: ["./**/*.html"],
      defaultExtractor: (content) => content.match(/[\w-/:]+(?<!:)/g) || [],
    }),
  ],
}
```

これでうまくいきました。
systemd での シャットダウン・再起動時に、サービスの停止順序を指定するには

## systemd と SysVinit の シャットダウンフローの違い

SysVinit の場合は、単純にランレベルに応じた *rc.dフォルダ* にある **K** で始まるファイルを ファイル名の昇順で、**コマンドライン引数に stop を付けて** 順番に起動していくだけ でした。

systemd の場合は、**特別な指定をしない限りは、意図しない順**に**サービスを落とそうとする可能性**があるようです。
つまり、**必ずしも、起動した逆順で サービス停止されるわけではない**ということです。
その為、互いに依存性があり、**先に 別サービスを落とさないと 落とせないサービス**がある場合、**シャットダウン中にフリーズしてしまう** わけです。

## どうやって、依存する別サービスを 先に止めるか

やる事は単純。shutdown.target に、起動時と 同じように、依存性指定を入れておけばよい のです。

```sh:bash
# cp -p /usr/lib/systemd/system/shutdown.target /etc/systemd/system/
# vim /etc/systemd/system/shutdown.target
```
/etc/systemd/system/shutdown.target の **[Unit]** に **After指定**で、**シャットダウンプロセスに入る前に 事前に止めておかないといけない** Unit を指定します。

例えば、

```sh:shutdown.target
After=httpd.service postgresql.service rc-local.service
```
とすれば、これらの **依存サービスを先に止めた上で**、シャットダウンプロセスが 安全に始まります。
macOS で error: include location '/usr/local/include' is unsafe for cross-compilation [-Werror,-Wpoison-system-directories] の対処メモ

## 背景

基本 `-Weverything -Wall` で, コマンドラインで clang でコンパイルしている.

https://qiita.com/MitsutakaTakeda/items/6b9966f890cc9b944d75

しかし clang 12(Big Sur?)あたりから,

```
error: include location '/usr/local/include' is unsafe for cross-compilation [-Werror,-Wpoison-system-directories]
```

というエラーが出るようになってしまう.

https://stackoverflow.com/questions/64471930/getting-warning-include-location-usr-local-include-is-unsafe-for-cross-compi


## 対処

* `-Wno-poison-system-directories` をつける.
* `-isysroot` あたりで明示的にシステムのパスを設定する https://jira.mongodb.org/browse/WT-6834

## 原因

stackoverflow の URL によると, clang のデフォルト動作はクロスコンパイルになっている.

gcc 4.8 あたりから?


もともとは, gcc 4.8 くらいから, cross-compile 時に, よくある `/usr/include`, `/usr/local/include` などのシステムパスがあると warn するようになっていた.

https://reviews.llvm.org/D52524

それが最近 clang にも取り込まれたっぽい?(上のとは別のパッチ?)
pythonでimport時に、ModuleNotFoundError: No module namedが出た時の対処手順



仮想環境を使ってpythonの実行してるとしょっちゅう出てきて、その度にググるのが手間になってきたので自分用対処方法メモです。
細かい理由とかは書いてませんが、一番下に参考記事のリンクがありますのでそちらを見ていただけると理解が深まると思います。

## pythonファイル実行時に出現するエラーメッセージ

```python

# 処理を実行
> python xxxxxx.py

Traceback (most recent call last):
  File "/Users/XXXXXXXX/xxxxxx.py", line 1, in <module>
    import {モジュール名}
ModuleNotFoundError: No module named '{モジュール名}'

```


## 対処方法

### pipでモジュール情報を確認

```python

> pip show {モジュール名}

# ⬇️こんな情報が出てくる

Name: {モジュール名}
Version: 0.13
Summary: {モジュール名} cryptographic signature library (pure python)
Home-page: http://github.com/xxxxxx/xxxxxx
Author: xxxxx xxxxx
Author-email: xxxxx@xxxxx.com
License: XXXXX
Location: /opt/anaconda3/envs/xxxxxxxx/lib/pythonX.X/site-packages -> このPASSをコピーする
Requires: 
Required-by: 

```

上記の時点で、モジュールが存在してなかった場合は普通にinstallする（importのコード書いてる時点でinstall済みが大半なのであまりないはず）

```python

pip install {モジュール名}

```

### sys.pathをpythonの実行ファイルの一番頭に入れる

```python

import sys

# passの設定 (pip showで出てきた、LocationのPASSを以下に設定)
sys.path.append('/opt/anaconda3/envs/xxxxxxxx/lib/pythonX.X/site-packages')

# passの設定はimportするモジュールより前に設定
import xxxxxx

```

これで概ね解決。

## 参考記事
https://web.plus-idea.net/2017/05/python-import-error-no-module-name/

→上記手順について、さらに細かに説明書いてくれているので、背景理由知りたい方はこちらを読むと理解が深まると思います。
M1のMacでNuxtがreify:typescriptで止まって動かなくなってしまったときの対処

これは簡単な備忘録のような感じで残しておこうと思います。

```
⸨                  ⸩ ⠙ reify:typescript: timing reifyNode:node_modules/rxjs Completed in 4294ms
```

新しく買ったm1のmacbook proでnuxtを実行するためにnodeを導入し`npm i`を実行したところ、`reify:typescript`と表示されたまま固まってしまいました。

```
> node -v                                                                                              
v16.4.0
```

このときのnodeのバージョンは16.4.0でした。


## 解決
バージョンを落とすと解決しました。anyenvやnodebrewを最初は試しましたが、僕の環境ではその２つでパッケージをダウンロードすることができなかったのでnvmを使用しました。

v14.17.1をインストールし、バージョンを切り替えます。

```
> nvm use v14.17.1                                                                                     
Now using Node v14.17.1 (npm 6.14.13) ~/.local/share/nvm/v14.17.1/bin/node
```

この状態で`npm i`をすると、無事に実行されるかと思います。

```


                                     :-:
                                   .==-+:
                                  .==. :+- .-=-
                                 .==.   :==++-+=.
                                :==.     -**: :+=.
                               :+-      :*+++. .++.
                              :+-      -*= .++: .=+.
                             -+:      =*-   .+*: .=+:
                            -+:     .=*-     .=*-  =+:
                          .==:     .+*:        -*-  -+-
                         .=+:.....:+*-.........:=*=..=*-
                         .-=------=++============++====:

                         Thanks for installing nuxtjs 🙏
                 Please consider donating to our open collective
                        to help us maintain this package.

                            Number of contributors: 0
                              Number of backers: 429
                             Annual budget: $102,149
                             Current balance: $24,434
```
Fedora Workstation 34 でISOイメージをDVDに書き込む

## 実現したいこと

どういうわけか、Fedora Workstation 34に標準でインストールされているディスクイメージライターだとFedoraのisoイメージがDVDに書き込むことができないので、コマンドラインでISOイメージで書き込む

```
$ rpm -qf /usr/bin/gnome-disks 
gnome-disk-utility-40.0-1.fc34.x86_64
```
```
$ rpm -qi gnome-disk-utility 
Name        : gnome-disk-utility
Version     : 40.0
Release     : 1.fc34
Architecture: x86_64
Install Date: 2021年04月23日 19時58分17秒
Group       : Unspecified
Size        : 6638377
License     : GPLv2+
Signature   : RSA/SHA256, 2021年03月23日 08時38分41秒, Key ID 1161ae6945719a39
Source RPM  : gnome-disk-utility-40.0-1.fc34.src.rpm
Build Date  : 2021年03月19日 05時13分46秒
Build Host  : buildhw-x86-14.iad2.fedoraproject.org
Packager    : Fedora Project
Vendor      : Fedora Project
URL         : https://gitlab.gnome.org/GNOME/gnome-disk-utility
Bug URL     : https://bugz.fedoraproject.org/gnome-disk-utility
Summary     : Disks
Description :
This package contains the Disks and Disk Image Mounter applications.
Disks supports partitioning, file system creation, encryption,
fstab/crypttab editing, ATA SMART and other features
```


## 実行コマンド


### 必要なソフトウェアをインストールする

```
sudo yum -y install dvd+rw-tools
```

### DVD-RにISOイメージのデータを書き込む

```
growisofs -dvd-compat -Z /dev/sr0=Fedora-Server-dvd-x86_64-34-1.2.iso
```

## 補足

* 今回は、理由(ある調査のため)があってISOイメージをDVD-Rに書き込んでいますが、今時ISOイメージをダウンロードしてDVD-Rに書き込むなんて古いので、ISOイメージをUSBメモリに書き込み、USBブートするのがいいと思います。

## 情報源

* https://www.nslabs.jp/linux-burn-dvd.rhtml
* https://qiita.com/subretu/items/7ad8fd4649125de763e7
* https://xtech.nikkei.com/it/atcl/column/14/230520/082000006/
【覚書】パラメーターのチェックもしたいダウンロード処理


こういうパターンはどうだろう、というメモ以外のなにものでもない。

# 諸元

ユーザーが画面で指定した条件に基づいてデータ検索を行い、結果をCSVでダウンロードさせるWebアプリケーションの機能を作ることになったんだ。
え、めっちゃよくあるやつじゃん。朝飯前じゃん。
ああそうさ、めっちゃよくあるやつさ。***ピースオブケーク***さ。
だけどジョニィ？ちょっと待ってくれよ。
「CSVダウンロード」か「バリデーションエラー」かでサーバーのレスポンスを切り替えなきゃいけない。
おっと、オーケーオーケー、ジョニィ、君の言いたいことはわかる。わかるよ。
それだけなら
ちょっと複雑でサーバー側の挙動がわかりにくくなるけど
出来ないことはないさ。
問題は***「画面に表示しているけどサーバー側に送らない情報が存在」***しているうえ、***「それを共通機能で取得しているから独自で追加対応が必要」***なんだ。
例えばユーザーIDだけをサーバーに送っているけど名称は表示だけに使っている、そんな情報を想像してくれ。
それを（無駄だけど）リクエストに含めたとしても、バリデーションエラー時に状態復元をフックしなきゃいけない。

面倒くさい。

ジョニィ、きみはせっかちすぎる。君の悪い癖だぜ。
そう、表示だけ情報にまつわる部分、***3パターンもある***んだ…
いい加減面倒くさすぎる
。

# どうするか

***2段階に分けちゃえ。***

1. Ajaxで事前チェック
1. エラーがない場合にformをsubmit

問題は

- その気になればチェックした値をユーザーが書き換えてダウンロード要求だせちゃう
- Springを使ってるけどバリデーション(HibernateValidator)結果をどう反映するか
  - JSPなら`<form:errors>`で自動的にやってくれるけど…

前者はパラメーターとソルト値からハッシュを生成し、トークンとして返すことでパラメーター改竄を検出可能にして対応としました。
ダウンロードリクエスト時にトークンが無かったり、再生成したハッシュと異なっていたらNG。

後者は数年前に実装したけど使ってなかった共通部品を使い、Springの`BindingResult`からi18nの解決を行った上、パラメーター名と紐づけたJSONとして返却し、JavaScript側でゴリゴリDOM書き換えて対応しました:(

どうも`<form:errors path="target">`は`<span id="target.errors"/>`を生成するようなので同様のものをdisplay:noneのうえ用意し書き換える…。
このあたりはもっといいやり方がある気がする。


# 今日知った小ネタ

## lombokの@Dataで特定項目を`hashCode`（と`equals`）から除きたい！

```java
@EqualsAndHashCode(exclude = {"token"})
```

Ajaxリクエスト時はトークンがなく、ダウンロードリクエスト時はトークンがあるので差が出ちゃう。


## jQueryのセレクタはドットが含まれていると動かない！

このようにエスケープする

```javascript
$('#target\\.errors').text('〜');
```


なお、トークンをリクエストヘッダーにくっつけられないかな、と思ったけどどうもHTMLだけじゃ実現できない様子:(

`<meta>`タグにありそうだけどね。
Azure Blob Storage を Ubuntu 18.04 から NFS でマウントしようとするとエラーになる件の対応策

#はじめに
Azure Blob Storage のコンテナを NFS 3.0 で直接マウントする方法が遂に GA （本番運用）になりました！
[Mount Blob storage by using the Network File System (NFS) 3.0 protocol](https://docs.microsoft.com/en-us/azure/storage/blobs/network-file-system-protocol-support-how-to)

というわけで試してみたら、ドキュメント通りにやると上手くいかない場所があったのでシェアしときます。

# 手順
## NFS マウントをするためのコマンド
下記のような感じで、Blob をマウントしたい Linux マシンに適当なマウントポイントを作って mount コマンドを実行！

```bash
mkdir -p /mnt/test
mount -o sec=sys,vers=3,nolock,proto=tcp <storage-account-name>.blob.core.windows.net:/<storage-account-name>/<container-name>  /mnt/test
```

## エラー発生
Ubuntu 18.04 だと以下のエラーが出てマウントできず。

```
mount: /nfs/standard: bad option; for several filesystems (e.g. nfs, cifs) you might need a /sbin/mount.<type> helper program.
```

nfs や cifs など、幾つかのファイルシステムはヘルパープログラムが必要になりますよー、というエラーが出ている様子。

## 調べてみた
NFS でマウントをしようとしてこのエラーが出る場合には `nfs-common` のインストールが必要とのこと。
[NFSでマウントするときに出るエラーの対処( mount: wrong fs type, bad option, bad superblock on....)](https://qiita.com/Accent/items/0d99c4652e2101760b50)

ちなみに cifs の場合には、`cifs-utils` が必要。

## やってみよう
サクッと入れる。

```bash
sudo apt install nfs-common
```

その後マウントを再試行してみたら、余裕でマウントできた。

# まとめ
Azure Blob の価格で普通に Linux から NFS で読み書きできるストレージが使えるようになるので、場合によっては有用かもしれんです。
kaminariのページネーションにCSSを適用する

#はじめに
本記事では、BootstrapなどのCSSフレームワークを使用しないで、kaminariのページネーションにスタイルを適用する例をご紹介します。

#CSSを適用する
以下SCSS記法で記述しています。

```SCSS:app/aseets/stylesheets/application.scss
/* ページネーション */

.pagination{
    margin: 20px auto 0;
    width: 50%;
    display: flex;
    justify-content: center;
    span{
        text-align: center;
        width: 50px;
        :hover{
            background-color:#f3f3f3;
        }
        a{
            display: block;
            width: 100%;
            height: 100%;
            :hover{
                background-color: #f3f3f3;
              }
        }
    }
}

.current{
    color: #008CFF;
}

.gap{
    background-color: white !important;
}

```


#UIを整える
ここで「next」と表示されている箇所を「>」に変更するなど、直感的なUIにしていきます。

```yml:app/config/locales/devise.ja.yml
ja:
  views:
    pagination:
      first: "&laquo;"
      last: "&raquo;"
      previous: "&lsaquo;"
      next: "&rsaquo;"
      truncate: "..."
```

#設定ファイルを変更する
設定ファイルを作成します。

```terminal
$ rails g kaminari:config
```

config/initializer下に生成された設定ファイルを確認します。
コメントアウトでデフォルト値が記載されています。

```ruby:config/initializers/kaminari_config.rb
# frozen_string_literal: true

Kaminari.configure do |config|
  # config.default_per_page = 25
  # config.max_per_page = nil
  # config.window = 4
  # config.outer_window = 0
  # config.left = 0
  # config.right = 0
  # config.page_method_name = :page
  # config.param_name = :page
  # config.max_pages = nil
  # config.params_on_first_page = false
end
```

筆者は以下のように変更しました。

```ruby:config/initializers/kaminari_config.rb
# frozen_string_literal: true

Kaminari.configure do |config|
  config.default_per_page = 10
  # config.max_per_page = nil
  config.window = 2
  config.outer_window = 1
  # config.left = 0
  # config.right = 0
  # config.page_method_name = :page
  # config.param_name = :page
  # config.max_pages = nil
  # config.params_on_first_page = false
end
```

#完成したページネーション
![スクリーンショット 2021-06-30 23.52.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101177/828d0095-8031-8d5b-a59a-2805cfaac285.png)

このようなスタイルを適用することができました！
お好みで色や配置などを変更していただけたらと思います！
非エンジニアでもDBダンプできるようにしてあげる手順

#1. SSHでログインする環境整える

```:bash
% grep -A4 "hoge " ~/.ssh/bundle/core/config
Host hoge hoge.xxx-yyy.com
    HostName    11.222.333.444
    User        ec2-user
    Port        50381
    IdentityFile    ~/.ssh/bundle/core/hoge_core_prd.pem
```

#2. SSHポートフォワーディングで穴開ける
```:bash
% ssh -f -N -L 3307:hoge-prd-cluster.cluster-xxxxxxxx.ap-northeast-1.rds.amazonaws.com:3306 ec2-user@11.222.333.444 -i ~/.ssh/bundle/core/hoge_core_prd.pem -p 59039
```
#3. MySQLに接続する
```:bash
[N16LT052.local]% mysql -h 127.0.0.1 -D fuga -u readonly -P 3307 -p'readonly' -A
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 21520288
Server version: 5.6.10 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
```
#4. SQLを実行する
```:bash
SELECT
    DATE_FORMAT(dl.created_at, "%Y/%m/%d") AS '利用日',
    u.name AS '利用者氏名',
    '勉強' AS '利用用途',
    d.serial AS 'シリアルナンバー',
    ROUND(TIME_TO_SEC(TIMEDIFF(MAX(dl.created_at), mp.created_at)) / 60, 1) AS '時間(分)',
    ROUND(TIME_TO_SEC(TIMEDIFF(MAX(dl.created_at), mp.created_at)) / 60 * AVG(pt.distance), 1) AS '距離(m)',
    ROUND(MAX(pt.height), 1) AS '高度(m)'
FROM
    datelists dl
INNER JOIN
    mission_projects mp
ON
    dl.mission_project_id = mp.id
INNER JOIN
    users u
ON
    mp.user_id = u.id
INNER JOIN
    fugas d
ON
    dl.fuga_id = d.id
INNER JOIN
    pointables pt
ON
    mp.id = pt.pointable_id
WHERE pt.deleted_at IS NULL
AND pt.pointable_type = 'App\\MissionProject'
AND u.deleted_at IS NULL
AND u.company_id IN (SELECT id FROM companies WHERE deleted_at IS NULL AND name NOT LIKE '%test%' AND name NOT LIKE '%テスト%' AND name NOT LIKE '%アカウント%')
AND YEAR(CONVERT_TZ(dl.created_at, '+00:00', '+09:00')) = 2019
AND MONTH(CONVERT_TZ(dl.created_at, '+00:00', '+09:00')) = 2
GROUP BY dl.id;
```
#5. 実行結果をCSVに整形
そのままCSVファイルに出してもいい
 https://qiita.com/catatsuy/items/9fdf4423d5f4885b9bf9 
#6. そのファイルをsendmailで〇〇さんに送る
#7. 上記の手順をスケジューラ（crontab）に登録する

# 以上

こちらのイベントの一環で投稿しました！
https://qiita.com/official-events/d523df99d6479293ffa7