OmniAICreator/Qiita-1.07M huggingface dataset:
emacs 27.1のビルドでエラー

emacs 27.1のビルド(configuire)でエラー

## その1

```bash
$ ./configure 
...
checking for sys/inotify.h... yes
checking for inotify_init1... yes
checking for lcms2... no
checking for library containing inflateEnd... -lz
checking for dladdr... yes
checking for dlfunc... no
configure: error: The following required libraries were not found:
     gnutls
Maybe some development libraries/packages are missing?
To build anyway, give:
     --with-gnutls=ifavailable
as options to configure.
make: *** [Makefile] エラー 1

```

解決法

```bash
sudo yum -y install gnutls-devel
```

## その2

```bash
$ ./configure 
...
checking for library containing tputs... no
configure: error: The required function 'tputs' was not found in any library.
The following libraries were tried (in order):
  libtinfo, libncurses, libterminfo, libcurses, libtermcap
Please try installing whichever of these libraries is most appropriate
for your system, together with its header files.
For example, a libncurses-dev(el) or similar package.
```

解決法

```bash
$ sudo yum install  ncurses-devel
```
Flink　動かすときに必要だった参考文献のメモ

* クイックスタート　ガイド
http://mogile.web.fc2.com/flink/flink-docs-release-1.3/quickstart/setup_quickstart.html

* Set Up Flink on Mac OS X
https://www.flinkinpractice.com/2019/07/28/Set-Up-Flink-on-Mac-OS-X/

一番わかりやすかった．

* MacにJava(JDK)をインストール
https://qiita.com/ryo0301/items/3c9a02e03b4e9a41f576
* Javaのインストール(Mac, Homebrew, 複数バージョン管理)
https://qiita.com/aoyaman/items/fdbc1b35ce841f730afc
* スクラッチからApache Flinkアプリケーションを5分で構築する方法
https://qiita.com/KentOhwada_AlibabaCloudJapan/items/be4315b555ac31774e04

* CentOS7 
https://saw.hateblo.jp/entry/2019/04/13/160800

なんとか動いた．
Todo
1.サーバ上で動作させる．
2.ストリームアプリ　クライアント/サーバ nc利用でも可
3.IoTデバイス経由
4.KafkaまたはMQTT使う
備忘録：AWSのElastic Beanstalk でnginxの設定拡張 client_max_body_size 

## 環境
* Spring Boot + React
* Elastic BeanStalk
    * Corretto 11
    + Amazon Linux 2
    
## バグ
練習のため、Spring Boot + ReactのCRUDアプリをAWSのElastic BeanStalkにデプロイしたところ、ファイル容量の大きい画像投稿ができない。

 ```spring.servlet.multipart.max-file-size=10MB```の設定をSpring Boot側ではしており、ローカルでは投稿できるサイズの画像を投稿できず、```413 Request Entity Too Large```エラーが出ている。


**nginxのエラーログ(```var/log/nginx/error.log```)**

```
2020/11/03 10:42:27 [error] 31794#0: *108 client intended to send too large body: 3275907 bytes,...
```

エラー内容をググると、nginxはデフォルトで、リクエストボディのサイズに1MBまでという上限が設定されていることが分かった。この上限を変えるには、```client_max_body_size```を変更しなければいけないらしい。

**ソース**
https://stackoverflow.com/questions/44741514/nginx-error-client-intended-to-send-too-large-body

## Elastic Beanstalkでのnginx設定拡張方法
どうやらソースバンドルのルートに、以下のディレクトリ構造で.confファイルを作成し、```client_max_body_size 10M;```を記述すれば、ディプロイ時に設定を追加してくれるらしい。

```
├── .platform
│   └── nginx
│       └── conf.d
│           └── myconf.conf
└── myApp-0.0.1-SNAPSHOT.jar
```
####ソース
1. https://stackoverflow.com/questions/18908426/increasing-client-max-body-size-in-nginx-conf-on-aws-elastic-beanstalk
2. https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/platforms-linux-extend.html

注：上の記事では、 ```.ebextensions/nginx/conf.d/```以下となっているが、Amazon Linux2の場合、上記の```.platform/nginx/conf.d/```に追加するのが正しいようです（https://stackoverflow.com/questions/63430968/application-source-bundle-doesnt-work-when-uploaded-to-aws-elastic-beanstalk ）。

## 試してみた
フォルダーを作成し、その中にjarとconfファイルを含んだ.platformフォルダをzip化→アップロードするも、deployエラーが出る。。。下記、```eb-engine.log```のエラー。confファイルの書き方を変えてみたり色々したけど、デプロイできない。。

```
[ERROR] An error occurred during execution of command [app-deploy] - [CheckProcfileForJavaApplication]. 
Stop running the command. Error: there is no Procfile and no .jar file at root level of your source bundle 
```
## 原因
結果、下記の記事によって、アーカイブのフォルダ構成が正しくないことが分かった。
対象ファイル/フォルダ自体を圧縮せずに、新たなフォルダに入れて圧縮していたのが原因だった...

>解凍されたファイルが、新しい上位フォルダまたはディレクトリではなく、アーカイブ自体があるフォルダに表示されていることを確認します。

https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/applications-sourcebundle.html

## さらに試してみた
今度は無事、デプロイ成功！早速、画像投稿するも...

```
[error] 31794#0: *108 client intended to send too large body: 3275907 bytes,...
```
設定が変更されていない！！

## 原因

コマンドラインでzipコマンドを使うときに、-rオプションをつけていなかったため、```./platform```以下の中身が空っぽになっていた。。。

```
zip -r 圧縮後のファイル名.zip　圧縮したいファイル/フォルダ
```
上記が解決してやっと、設定が反映されました。

## まとめ
1. 同様環境下で、```client intended to send too large body (413 Request Entity Too Large) ```エラーが出たら、nginxの```client_max_body_size```を変更する。
2. Elastic Beanstalkだと、簡単な方法として、ソースバンドルに設定ファイルを含むことで変更可能。
2. ソースバンドルは、親フォルダまたは最上位ディレクトリを含まない（サブディレクトリを除く）。
3. zip コマンドを使う場合、フォルダを含むなら、-rを忘れない。
【Auto Scaling】Auto Scalingとは

## Auto Scaling とは
安定した予測可能なパフォーマンスを可能な限り低コストで維持するためにアプリケーションをモニタリングし、容量を自動で調整するサービス

- 複数AZにまたがって設定可能なことによる耐障害性の向上を実現可能（リージョンをまたぐことは不可）

## 起動設定
Auto Scalingを使ってスケールアウトする際の、EC2インスタンスの起動に必要な情報（AMI、インスタンスタイプ、ストレージ、セキュリティグループ、キーペアなど）を定義するもの

- 1つのAuto Scalingグループにつき1つの起動設定を指定可能

- グループ作成後の起動設定の変更は不可

- Auto Scalingグループの起動設定を変更するには、起動設定を作成後、その起動設定を使用してAuto Scalingグループを更新する

## 起動テンプレート
インスタンス設定情報を指定する起動設定と類似のもので、AMIのID、インスタンスタイプ、キーペア、セキュリティグループ、その他EC2インスタンスを起動するために使用するパラメータが含まれている

- バージョニングを使用することで、複数のバージョンのテンプレートを使用することが可能

- 専用ホスト（Dedicated Hosts）を使用するために必要

## Auto Scaling グループ
スケーリングに関する基本情報（起動するEC2インスタンス数、ネットワーク、連携するELB、スケーリングポリシー、通知設定など）を設定するもの

- 自動スケーリングと管理の目的で論理グループとして扱われるEC2インスタンスの集合が含まれる

- スケーリングポリシーを使用することで、状況の変化に合わせてグループのインスタンス数を動的に増減することが可能

- 作成の際には、起動設定・起動テンプレート・EC2インスタンスのいずれかを指定する必要がある

### 1. 起動設定を使用したAuto Scalingグループの作成
- コンソールを使用し、Auto Scalingグループ作成時に既存の起動設定を選択することで作成可能

### 2. 起動テンプレートを使用したAuto Scalingグループの作成
- スケールアウトイベントが発生した際に、起動テンプレートのデフォルトバージョンまたは最新バージョンのいずれかを選択するよう設定可能

- 起動テンプレートのインスタンスタイプを上書きすることで、スポットインスタンスとオンデマンドインスタンスの両方を起動するAuto Scalingグループを作成可能

### 3. EC2インスタンスを使用したAuto Scalingグループの作成
以下3つの方法で作成可能

- 既存のEC2インスタンスから起動テンプレートを作成
- コンソールを使用して、実行中のEC2インスタンスからAuto Scalingグループを作成
- Auto Scalingグループを作成するAPI呼び出しで既存のEC2インスタンスのIDを指定することで、Auto Scalingによって起動設定を作成し、 Auto Scalingグループに関連付ける

## スケーリングプラン
スケーリングを実行するためのトリガー

### 1. Auto Scaling グループのサイズの維持 （オートヒーリング）
EC2インスタンスに障害が発生した場合、そのインスタンスを終了し代わりのインスタンスを起動することで、Auto Scalingグループの設定で事前設定されたEC2インスタンスの起動数・最小数を維持する

### 2. 手動スケーリング
必要なEC2インスタンス数が明確な場合、手動でEC2インスタンス数を増減させることが可能

### 3. スケジュールに基づくスケーリング
Auto Scalingグループのオプションとして、スケーリングを実行するタイミングを時刻指定することが可能

### 4. 動的スケーリング
Auto Scalingグループの設定でスケーリングポリシーを定義することにより、CloudWatchが収集するメトリクスの値に応じてアラートを発生させ、アラートをトリガーにEC2インスタンスを増減させることが可能

## ヘルスチェック
### 1. EC2ヘルスチェック
- 1分間隔でEC2インスタンスのステータスをチェック
- 1つ以上のステータスチェックに失敗した場合、当該EC2インスタンスを異常ありとみなす

### 2. ELBヘルスチェック
- Auto ScalingグループにELBをアタッチした場合、ELBヘルスチェックを設定可能
- ELBによるヘルスチェックを行い、EC3インスタンスの状態確認が可能

## 終了ポリシー
- **Default**: デフォルトの終了ポリシー（以下）に従って、インスタンスを終了する

1. Auto Scalingグループが複数のAZにまたがる場合、起動しているEC2インスタンス数が最も多いAZのインスタンス
2. 起動設定が最も古いインスタンス
3. 次の課金タイミングが最も近いインスタンス

- **AllocationStrategy**：Auto Scalingグループのインスタンスを終了して、残りのインスタンスを、終了するインスタンスのタイプ (スポットインスタンスまたはオンデマンドインスタンス) の配分戦略に合わせる

- **OldestLaunchTemplate**：最も古い起動テンプレートを使用するインスタンスを終了する

- **OldestLaunchConfiguration**：最も古い起動設定のインスタンスを終了する

- **ClosestToNextInstanceHour**：グループ内の最も新しいインスタンスを終了する

- **OldestInstance**：グループ内の最も古いインスタンスを終了する

## ELB と Auto Scaling
- Auto ScalingグループでELBを使用するには、ロードバランサーをAuto Scalingグループにアタッチし、このグループをロードバランサーに登録する

- Auto ScalingグループでELBを使用する場合、スケーリングによって起動・終了されたインスタンスは自動でロードバランサーに登録・解除される
NoCloud network-config

cloud-init NoCloud の local-init で network を設定させたい場合、`cloud-localds` の `--network-config` で netplan の設定ファイルを指定できることになっている。指定の通りに netplan の yaml ファイルを作って実行する。

```
cloud-localds -N network.yaml guest.iso guset.user-data
```

すると、こんなエラーがでて困っていた。

```py
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/cloudinit/cmd/main.py", line 653, in sta>
    ret = functor(name, args)
  File "/usr/lib/python3/dist-packages/cloudinit/cmd/main.py", line 362, in mai>
    init.apply_network_config(bring_up=bool(mode != sources.DSMODE_LOCAL))
  File "/usr/lib/python3/dist-packages/cloudinit/stages.py", line 699, in apply>
    self.distro.networking.wait_for_physdevs(netcfg)
  File "/usr/lib/python3/dist-packages/cloudinit/distros/networking.py", line 1>
    physdevs = self.extract_physdevs(netcfg)
  File "/usr/lib/python3/dist-packages/cloudinit/distros/networking.py", line 4>
    return net.extract_physdevs(netcfg)
  File "/usr/lib/python3/dist-packages/cloudinit/net/__init__.py", line 493, in>
    raise RuntimeError('Unknown network config version: %s' % version)
RuntimeError: Unknown network config version: None
```

デバッグしてよーくよく見てみると、`network.yaml` は次のようになっていないといけない。`version` はトップレベル。`network` をトップレベルにしてはいけないということだった。netplan のドキュメントみながら書くとはまってしまった。

```yaml
---
# DO THIS
version: 2
ethernets: {}
---
# NOT DO THIS
network:
  version: 2
  ethernets: {}
```
【kintone】標準機能だけで２次方程式を解くアプリ

kintoneを使っていて思いませんか？
あ～、2次方程式が解けたらなぁ・・・（´-`）.｡oO

思いませんよね？

今回は前回の平方根を求めるアプリを流用して、
2次方程式の解を求めるアプリを作ってみたいと思います。

前回の記事↓
[【kintone】標準機能だけで平方根の計算をしてみる](https://qiita.com/juri_don/items/dd7b2d6ab4fb045990b6)

# アプリを作る
では2次方程式を解くアプリを作っていきましょう。

## 前回作成した平方根アプリを再利用して作成
前回作成した平方根アプリを再利用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/77e3a71e-caf6-233a-0d6a-593a8b6b2c26.png)

（１）フィールドA（数値）を削除します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/54fa7f02-187c-a4c9-e6f7-09a9d87e70e6.png)

（２）計算フィールド持ってきて、フィールドコードをAにして一旦保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/0e61d015-55b7-33d2-ec3d-340d52c119ca.png)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/27cdd366-7a71-92e2-875f-b21516656c76.png" width="400">


（３）今変更したフィールドコードAをDに変更します。そうです、これが判別式Dになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/b199a6d1-7e95-08b1-6dc7-7ec2fb1a9d93.png" width="400">

フィールドDの計算式は

```
b*b - 4*a*c
```

とします。解の公式にでてくる、判別式$D=b^2-4ac$というやつです。

※解の公式ってこういうやつです。→　　　$x = \frac{-b \pm \sqrt{b^2-4ac} }{2a}$


（４）x0～x9フィールドの計算式のAだったところがDに変わっていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/74d0b8e0-21ef-67e1-2685-ab3c42dd2a2b.png)

（５）下図＆下表のようにフィールドを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/84e8ce23-271f-9bb0-cb8e-e8f22c63f1ac.png)


| フィールド種類 | フィールドコード | 計算式 | 備考 |
|:-:|:-:|:-:|:-:|
| 数値  | a  | なし  |   |
|  数値 | b  | なし  |   |
|  数値 | c  | なし  |   |
|  文字列(1行) | 求める方程式  | この表の下に書いてます |   |
| 文字列(1行)  | 解  | IF(a=0,"X = " & X1,IF( rD>=0, "X1 = " & X1 & " / X2 = " & X2 , "解無し")) & IF(D=0,"(重解)","")  |   |
|計算|D|b*b - 4*a*c|作成済|
| 計算  | rD  | IF(D>0, x9,IF(D=0,0,-1))  | Aの平方根フィールドを書き換えるとよいです。  |
| 計算  | X1  | IF(a=0,-c/b, IF(D>=0, (-b+rD)/(2*a),0))  | 解の公式による。フィールドコードのXは大文字  |
| 計算  | X2  | IF(a=0,0,IF(D>=0, (-b-rD)/(2*a),0))  |  解の公式による。フィールドコードのXは大文字 |

↓求める方程式フィールドの計算式（このフィールド自体、なくても良いんだけどせっかくなので）

```
IF(a=1, "x^2" , IF(a=0,"", IF(a=-1, "-x^2", a & "x^2") ) )
 & IF(a=0,IF(b=1, "x" , IF(b=0,"", IF(b=-1, "x", b & "x") ) )  ,
IF(b=1, " +x" , IF(b=0,"", IF(b=-1, " -x",IF(b>0, " +" & b & "x"," " & b & "x")) ) ))
& IF(AND(a=0,b=0),"aとb両方0にしちゃだめ"  ,IF(c=0, "", IF(c>0, " +"&c , " "&c))& "= 0")
```

# できた＆まとめ
これで、アプリを公開！（保存？）して試してみると、ほら！
方程式を解くことができます。（誰得）

![2jihou.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/796e593b-e0bd-522a-a4b6-0624937f3f4b.gif)

ここからちょっといじって虚数解にも対応させてみました。
もしかしたらいつか記事にするかもしれません・・・。

![2jihoukyo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/e0ad1a55-f51f-e720-a072-65241f307546.gif)
SNIとは？

## SNIとは

Server Name Indication の略
1台のサーバのvhostsの設定で複数ドメインでの複数のSSL証明書を使えるようにする という方法。
え？vhostsにSSL証明書置くのって普通できるんじゃ・・・？って言うのは少し思ったけど、元々出来なかったらしい。
元々、1つのサーバにドメイン名を複数設定できても、SSL証明書は１つしか設定できなかった。
Apacheが2.2.12以降対応なので2011年以前だと思う...

## ブラウザ対応状況

| ブラウザ名 | バージョン |
|:-:|:-:|
| IE | 7以降 |
| Chrome | 6以降 |
| Safari | 2.1以降 |

ブラウザとOSでの組み合わせもあるが大体上記。
実は結構最近まで使えないところ多かったのかな？

## メリット

SNIを入れるメリットとしては以下

### 1. 独自ドメインと証明書のドメイン名が同じになる

従来だと、SSLを必要な通信のページはサイトを見たユーザからするとアドレスが突然変わり、違和感が出ます。
しかしSNIを導入することによってその違和感をなくすことが出来ます。
ショッピングだと、購入にページだけ共有SSLのドメインに変わることがよくあったとか？

### 2. サーバで複数のサイトを運用することが出来る

複数ドメイン・複数SSL証明書を設定することが出来ると、
従来であれば、ドメインごとにwebサーバが必要なところ、1つのwebサーバでvhostsを使って運用できるので
手間やコストの削減が可能になります。

## デメリット

### 1. ブラウザで対応出来ない場合がある

デメリットと書きましたが、「ブラウザ対応状況」 を見る限り古いOSやブラウザのバージョンなのでそこまで気にしなくてもいいのでは？
と思ったりもする...

## 勉強後イメージ

そもそも出来ないって知らなかった....
けど、こうしてみるとvhostsにSSL証明書入れれなかったらめっちゃめんどくさいんやろなぁと。
クラウドとかも普及してなくて、オンプレに仮想立ててとか今だったらめんどくさい...

## 参考

- [1つのサーバーで複数の証明書が使える、SNIって？](https://www.idcf.jp/rentalserver/user-support/knowledge/ssl/sni.html)
- [注目の集まるSNI（Server Name Indication）導入の必要性とは](https://jp.globalsign.com/blog/articles/server_name_indication.html)
- [ApacheのSNIについて](https://e-garakuta.net/techinfo/doku.php/linux/apache-sni)
実家の会社の日報表をwebアプリ化した。（スマホ用）

#はじめに
実家の会社が未だに紙ベースでやりとりをしているので、実際に使ってほしいという気持ちを持ちつつ作ってみました。（スマホ用）
#概要と背景
- 営業マンがその日行った営業を日報表にまとめてその日の終わりに提出する。
- 紙面でのやりとりなので、事前に報告ができない、過去の営業記録をいちいち紙で探す必要がある、など不便なことが多い。
- 日報表の項目は、訪問先住所・訪問先氏名・会見者・訪問結果・内容・日付の6項目。
- 社員の管理は社員用テーブルで管理し、訪問履歴はセールス記録テーブルで管理する。
- 訪問履歴は社員に個別に与えられた社員番号で個別に管理する。

#開発環境
- サーバーサイド
    - java
    - java EE
- フロントサイド
    - javascript
    - html
    - css
- データベース
    - MySQL
- その他
    - bootstrap

#基本機能
- ログイン機能
    - 社員名と社員ごとに与えられたパスワードで管理
    - セッションによるログイン管理
- ログアウト機能
    - セッションを削除
- 日報表の入力・送信機能
    - 項目は概要の通り
    - 営業記録の入力の際に、社員番号を入力せずにセッション情報から社員番号を取得し、サーバーサイドで自動的に入力
- 入力の際のチェック機能、送信の際の再確認機能
- 入力した日報の一覧表示
    - 社員が自分の日報のみ見られる（他の社員の日報は見れない）ように設定
    - 今日、今週、今月、全て、から選ぶことが可能
- 訪問履歴の検索機能
    - 訪問先氏名または郵便番号による検索が可能
    
#できたもの
- ログイン画面
![日報表ログイン.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784464/ff18aa8d-1c7d-fb25-5907-d1a4337e29e2.jpeg)


- 日報入力画面 
![日報表入力.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784464/c3cf38a8-ff6a-2a2b-a36b-b8e308ed6f8b.jpeg)

- 営業記録一覧を表示した例
一覧は横スクロールで対応
![input.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784464/9e6713f3-a8ac-a807-aa28-c9466231c2be.gif)


- 検索例
![input2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784464/ac030ac6-de36-a9c7-8b4d-5417fd4c6ebf.gif)

#工夫した点
- 社員は結構年を取っている人が多いのでUIをなるべく大きめに設定した。
- ajaxを使って郵便番号を入力すると該当する都道府県市区まで自動入力されるようにした。
- 日報を入力し、送信を押したときに再確認するよう入力された情報をアラートで表示し、OKか確認するよう設計した。
- 名前別の検索だけだと別の住所であっても重複する可能性があるため、より確実な郵便番号による検索を設けた。

#作った感想
日報表をwebアプリ化してみて、紙でのやりとりより圧倒的に役立つと確信できた。（まだ使ってくれてない）

#最後に
この日報表の他にも、紙でやりとりされていて、かつアプリ化できるものがたくさんあるので、これからアプリ化してどんどん実家の会社の業務効率をよくしたい。（使ってくれるかは分かりませんが。）
※追記
実際に使ってくれることになりました。
概ね好評です。
Laravel:Auth認証の設定

#【概要】

<b>1.[手順](#1手順)</b>

<b>2.[どのようにコーディングするか](#2どのようにコーディングするか)</b>

<b>3.[開発環境](#3開発環境)</b>


#1.手順
備忘録も兼ねてアウトプットしておきます。

❶<a href="https://nodejs.org/ja/">Node.jsをダウンロード</a>
❷`laravel/ui`をインストール
❸Auth関連ファイルの生成
❹作成されたusersをマイグレーション
❺Controllerにコーディング

#2.どのようにコーディングするか
❶<a href="https://nodejs.org/ja/">Node.jsをダウンロード</a>
ここからNode.jsをインストールします。

❷`laravel/ui`をインストール
ターミナルで下記を記述してインストールします。

```terminal
$ composer require laravel/ui
```

❸Auth関連ファイルの生成
同じくターミナルで下記を記述して実行します。

```terminal
$ php artisan ui vue --auth
$ npm install && npm run dev
```
すると`user.php`と`users`テーブルが作成されます。

❹作成されたusersをマイグレーション
下記の通りマイグレーションを実行します。

```terminal
$ php artisan migrate
```
するとDBにuserテーブルが作成されます。

❺Controllerにコーディング
`use Illuminate\Support\Facades\Auth;`
`$user = Auth::user();`
を記述して完了です。

```php:app/Http/Controllers/xxxxController.php
use Illuminate\Support\Facades\Auth;

public function index(Request $requsest)
{
 $user = Auth::user();
 return view('xxx.index'); //(i)
}
```
(i)は、`$param = []`を記述している際は`return view('xxx.index', $param);` と記述してデータを渡してください。

以上のことをすると、`localhost:8000/register`,`localhost:8000/login`で新規登録機能・ログイン機能を実装できます。

#3.開発環境
PHP 7.4.10
Laravel 8.9
Apache 2.4.41
Mysql 5.6.47
Sequl Pro 1.1.2
✟【Bash】dateの-dにプラス・マイナスで期間指定した時のそれぞれの挙動


## やりたいこと

bashのdate関数に-dオプションで期間指定をし、
現在から任意の日付を取得したかったが挙動を勘違いしてちょっとはまったのでメモ

## 環境
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)

## やったこと

1か月前の日付を取得しようとdateの-dオプションに「"-1 months ago"」を指定していたが
これがマイナスのマイナスでプラスになり1か月未来の日付を取得していた
今回の場合、正しくは「"1 months ago"」とすべきであった

### 現在の日付

```bash
TIME_ZONE='Asia/Tokyo'
CURRENT_DATE=$(TZ=${TIME_ZONE} date '+%Y%m%d')
# ↓本日の日付
echo $CURRENT_DATE
+ echo 20201104
```

タイムゾーンを東京にしてdateを取得した結果、投稿日の`2020/11/04`となる

### -d を正の値(1 months ago)で指定
```bash
PLUS_DATE=$(TZ=${TIME_ZONE} date '+%Y%m%d' -d "1 months ago")

# ↓指定した期間より前の日付
echo $PLUS_DATE
+ echo 20201004
```

単純に1か月前の`2020/10/04`となっている

###  -d を負の値("-1" months ago)で指定
```bash
MINUS_DATE=$(TZ=${TIME_ZONE} date '+%Y%m%d' -d "-1 months ago")

# ↓指定した期間より後の日付
echo $MINUS_DATE
+ echo 20201204
```

-dにマイナスの値を渡すと-1か月前となり「負×負=正」なので1か月後の`2020/12/04`となった
Redhat7でFlask/MySql/Apache/mod_wsgi/virtualenvの環境構築（Python2.7）2020年11月

# 検証環境
- Red Hat Enterprise Linux Server release 7.9 (Maipo)
- Python 2.7.5
- Apache/2.4.6 (Red Hat Enterprise Linux)
- Flask 1.1.2
- MySql mysql  Ver 8.0.22 for Linux on x86_64 (MySQL Community Server - GPL)
- pip 20.2.4
- virtualenv 20.1.0

# インストールとアプリケーションファイルの作成
## Apache/mod_wsgiのインストール

```sh

$ sudo su
$ yum install httpd
$ chkconfig httpd on
$ service httpd start
$ service httpd status # 確認
$ yum install mod_wsgi # mod_wsgiのインストール
```

## pipのインストール

```sh

$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
$ python get-pip.py
```

## virtualenvのインストール

```sh

$ pip install virtualenv
```

## アプリケーションのディレクトリを作成

```sh

$ mkdir /var/www/myapp
$ cd /var/www/myapp
$ virtualenv venv # virtualenv環境の構築
$ source venv/bin/activate # virtualenv有効化
$ pip install flask # flaskのインストール
$ touch app.py # アプリケーションのファイルを作成
$ touch app.wsgi # アプリケーションのファイルを作成
```

```py:app.py
from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/")
def hello():
    return jsonify("Hello World!"), 201


if __name__ == "__main__":
    app.run()
```

```py:app.wsgi
import os
import sys

DIR=os.path.dirname(__file__)
sys.path.append(DIR)
activate_this = os.path.join(DIR, 'venv/bin/activate_this.py')
execfile(activate_this, dict(__file__=activate_this))

from app import app as application
```

最終的に下記の様なファイル構成になる

```sh
$ tree -L 2
.
├── app.py
├── app.wsgi
└── venv
    ├── bin
    ├── lib
    ├── lib64
    └── pyvenv.cfg
```


# Apache/mod_wsgiの設定

```
$ vi /etc/httpd/conf/httpd.conf
```

下記の行を追加

```
Listen 8888
```

port 8888を加えて、apacheを再起動すると下記のようにエラーが出る

```error_log
(13)Permission denied: AH00072: make_sock: could not bind to address [::]:8888
(13)Permission denied: AH00072: make_sock: could not bind to address 0.0.0.0:8888
```

selinuxでポートを追加する
参考 http://hetarena.com/archives/495

```
$ semanage port -a -t http_port_t -p tcp 8888
```

# アプリケーション用の環境を構築

```
$ vi /etc/httpd/conf.d/myenv.conf
```

```myenv.conf
<VirtualHost *:8888>
    WSGIDaemonProcess wsgi_flask user=apache group=apache threads=10
    WSGIScriptAlias / /var/www/myapp/app.wsgi

    WSGIScriptReloading On

    <Directory "/var/www/myapp">
	WSGIProcessGroup wsgi_flask
	WSGIApplicationGroup %{GLOBAL}
        Order deny,allow
        Allow from all
    </Directory>
</VirtualHost>
```

- 設定ファイルの確認

```
$ apachectl configtest
```

https://deep-blog.jp/engineer/12317/

```
$ service httpd graceful
```


# mysqlのインストール

```
$ sudo su
$ rpm -Uvh https://repo.mysql.com/mysql80-community-release-el7-3.noarch.rpm
$ yum install mysql-community-server
$ service mysqld start
$ service mysqld status # 確認
```

# mysqlのログイン

```
$ sudo su
$ tail /var/log/mysqld.log # パスワードをログから確認
$ mysql -uroot
$ mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'YQM3rCyae8Ft?';
```

参考 https://dev.classmethod.jp/articles/how-to-serve-flask-with-apache-mod_wsgi-virtualenv-on-ec2/
Rustの構造体に継承のようなものを適用する

# 疑問

[rustcのソースコード](https://github.com/rust-lang/rust)を読んでいたら、~~初見殺し~~テクニカルだと思う書き方に遭遇しました。例えばこんな感じ。

```rust:compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
...
    pub fn local_ty(&self, span: Span, nid: hir::HirId) -> LocalTy<'tcx> {
        self.locals.borrow().get(&nid).cloned().unwrap_or_else(|| {
            span_bug!(span, "no type for local variable {}", self.tcx.hir().node_to_string(nid))
        })
    }
...
}
```

`self`のメンバである`locals`にアクセスして、そこからメソッドをつないでいっている普通の書き方に見えますね。でも、ここで`self`の型となっている構造体`FnCtxt`には`locals`なんてメンバは存在しないのです。

周辺のソースを探っていると、この`locals`は`Inherited`という構造体のメンバのようでした。

```rust:compiler/rustc_typeck/src/check/inherited.rs
pub struct Inherited<'a, 'tcx> {
...
    pub(super) locals: RefCell<HirIdMap<super::LocalTy<'tcx>>>,
...
}
```

それを踏まえて構造体`FnCtxt`のメンバを見てみると、`FnCtxt`は`Inherited`の参照をメンバとして持っていることが分かります。

```rust:compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
pub struct FnCtxt<'a, 'tcx> {
...
    pub(super) inh: &'a Inherited<'a, 'tcx>,
}
```

とはいえ、普通に考えたら`FnCtxt`から`Inherited`のメンバにアクセスするには、`self.inh.locals`のように`inh`をかませる必要がある気がします。どうなっているのでしょうか？

# 回答

実は、`FnCtxt`に実装されているトレイト`Deref`に秘密があります。

```rust:compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> {
    type Target = Inherited<'a, 'tcx>;
    fn deref(&self) -> &Self::Target {
        &self.inh
    }
}
```

`FnCtxt`の参照を外すと、`inh`が返されるように実装されていました。この実装により`inh`の記述は省略され、`FnCtxt`から直接`Inherited`のメンバにアクセスできるようになっています。

これは見方を変えれば、`FnCtxt`が`Inherited`を**継承している**と言うこともできるでしょう。（型の名前からして、そのような実装を意図していそうな感じです。）このやり方を使うことで、データ構造の継承機能を持たないRustに、構造体の継承のようなものを適用することができます。

# 注意

ただし、上記のような実装は推奨されていないようです。実際、[`Deref`のリファレンス](https://doc.rust-lang.org/std/ops/trait.Deref.html)にも`Deref`はスマートポインタに対してのみ実装するべきとの記述があります。~~rustcで使っておいてひどい。~~

> Because of this, Deref should only be implemented for smart pointers to avoid confusion.

ここでは、`Deref`はもともとスマートポインタ用に設計されたので、という文脈ではありますが、そうでなくとも今回紹介した書き方は読みづらいかなと思います。

# 余談

ここまでの説明を読んで、「`Deref`で`inh`を返すことは分かったけど、参照外しなんてしてなくない？」という疑問を持った方がいるかもしれません。

これにはRustの**型強制**（Type Coercion）の仕組みが効いています。Rustでは、ある型のメンバやメソッドにアクセスする際、指定された型そのものに実装がない場合には参照を外した型でそれらが見つかるかを調べます。

つまり、冒頭の例は以下のような流れでメンバを探していくことになります。

```rust
self.locals... // selfにlocalsは見つからない
(*self).locals... // 参照を外して見つかるか調べる
(self.deref()).locals... // 参照外しはderefに置き換えられる
(self.inh).locals... // inhの中にlocalsが見つかる
```

違和感を感じるかもしれませんが、このような動作はおそらく普段も目にしていると思います。例えば、絶対値を求める単純なコードを考えてみます。

```rust
let a = -3_i32;
let b = &a;
assert_eq!(b.abs(), 3);
```

`b`の型は明らかに`&i32`です。にもかかわらず`i32`のメソッドである`abs()`を呼び出すことができているのは、自動的に参照を外してメソッドを探しているためで、結果として以下のコードと同じことになります。

```rust
let a = -3_i32;
let b = &a;
assert_eq!((*b).abs(), 3);
```

このような型強制はRustを書きやすくしている一方で、深く考え始めると少しややこしいかもしれませんね。冒頭の例はこの機能をひねった使い方と言えそうです。
GCP Cloud Vision APIでテキスト抽出やーる（Python3.6）

# はじめに
GCP Cloud Vision APIで画像からテキスト抽出やってみました

# 開発環境
- Windows 10
- Anaconda
- Python 3.6
- OpenCV 4.4.0

# 導入
[画像内のテキストを検出する](https://cloud.google.com/vision/docs/ocr)を参考にします。

1．Cloud Consoleからプロジェクトを作成します。
2．課金が有効になっていることを確認します。
3．Vision API を有効にします。
4．認証の設定をし、JSONファイルがPCにダウンロードされます。
5．環境変数 GOOGLE_APPLICATION_CREDENTIALS にJSONファイルのパスを設定します。
6．anaconda promptを開き、Python 3.6環境を作成します。

~~~console
$ conda create -n py36 python=3.6
$ conda activate py36
~~~

7．ライブラリをインストールします

~~~console
$ pip install numpy
$ pip install pillow
$ pip install opencv-python
$ pip install --upgrade google-cloud-vision
~~~

8．下記のコードを実行してみましょう

~~~python 
from google.cloud import vision
import io
import os
import cv2
import numpy as np
from PIL import ImageFont, ImageDraw, Image

def detect_text(image):
    """Detects text in the file."""
    client = vision.ImageAnnotatorClient()

    content = cv2.imencode(".png", image)[1].tostring()
    tmp = vision.Image(content=content)
    response = client.text_detection(image=tmp)
    texts = response.text_annotations
    if response.error.message:
        raise Exception(
            '{}\nFor more info on error messages, check: '
            'https://cloud.google.com/apis/design/errors'.format(
                response.error.message))
    return texts

filename = "338px-Atomist_quote_from_Democritus.png"
root, ext = os.path.splitext(filename)
image = cv2.imread(filename, cv2.IMREAD_COLOR)
texts = detect_text(image)
fontpath ='C:\Windows\Fonts\meiryo.ttc'
font = ImageFont.truetype(fontpath, 10)
image_pil = Image.fromarray(image)
for text in texts:
    print(text.description)
    vertices = [(vertex.x, vertex.y) for vertex in text.bounding_poly.vertices]
    # cv2.putText(image, text.description, vertices[0], cv2.FONT_HERSHEY_PLAIN, 1, (255, 255, 255), 1, cv2.LINE_AA)
    # cv2.rectangle(image, vertices[0], vertices[2], (0, 255, 0))
    draw = ImageDraw.Draw(image_pil)
    w, h = draw.textsize(text.description, font = font)
    draw.text((vertices[0][0], vertices[0][1]-h), text.description, font=font, fill=(255, 255, 255, 0))
    # draw.text(vertices[0], text.description, font=font, fill=(255, 255, 255, 0))
    draw.rectangle((vertices[0], vertices[2]), outline=(0, 255, 0))
image = np.array(image_pil)
cv2.imshow("image", image)
cv2.imwrite(root+"_ocr"+ext, image)
cv2.waitKey(0)
~~~

|input|PIL|PIL(OpenCV風)|OpenCV|
|:--|:--|:--|:--|
|![338px-Atomist_quote_from_Democritus.png](https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Atomist_quote_from_Democritus.png/338px-Atomist_quote_from_Democritus.png)|![338px-Atomist_quote_from_Democritus_ocr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/fb830bac-8ced-6513-0183-f3fda104e522.png)|![338px-Atomist_quote_from_Democritus_ocr_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/b6b8eaa9-3a59-0b28-af60-9171f8a1c645.png)|![338px-Atomist_quote_from_Democritus_ocr_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/2e970f98-625c-b9d8-8118-202295e5d40a.png)|

OpenCVだと全角英語（日本語）が文字化けするのでPILを用いてテキスト表示しました。
お疲れ様でした。
ライブラリの導入

前回の記事でアプリを作成したらライブラリを導入する。
ライブラリとはGemの事で、開発を迅速に進めるための拡張機能。備忘録として残す。

Gemfileの中にアプリで使う名前、バージョンを管理。

ファイルに記載したらターミナルにて bundle install をする。

```
Gemfile

# Use mysql as the database for Active Record
gem 'mysql2', '0.5.3'　　追加
.
.
.
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

gem 'pry-rails'　　追加

```
追加後、bundle update
今回はすでにあるバージョンの更新のため update

rails s をし起動すればOK
iPhoneから写真を簡単に復元

 スマートフォンの分野の最新技術、特にカメラの優れた表現力により、Appleは2020年も多くのユーザーに愛され続けます。現在、iPhoneは市場で最高の品質と鮮明な写真の1つです。


 ただし、iPhoneは写真を撮るだけではないため、電話、ゲーム、情報の照会、ファイルの表示、通信の実装などの機能も統合します。残念ながら、iPhoneにはより多くの情報を保存するためのメモリスペースがあまりないため、電話のストレージスペースを節約するには、不要な写真やデータを削除する必要があります。質問は、誤ってiPhoneの写真を削除した場合はどうなるのでしょうか？ <a href="https://jp.bitwar.net/course/iphone/2698.html">iPhoneから写真を簡単に復元</a>する方法は？ <a href="https://jp.bitwar.net/course/iphone/2698.html"> iphone 写真 ゴミ箱 復元</a>


 この場合、バックアップがある場合、バックアップがコンピューター、外付けハードドライブ、またはフラッシュドライブに保存されているかどうかは、素晴らしいことです。 iTunesまたはiCloudバックアップを使用して、失われた重要な写真を取り戻すことができます。


 しかし、何度も時間内にバックアップしませんでした。これは非常にイライラします。心配しないでください。ここでは、iPhoneから削除された写真を復元するための簡単で簡単な方法を紹介します。


 最も基本的な：iPhoneで最近削除したアルバムから削除した写真を復元する


 写真とビデオが復元されると、これらのアイテムは[すべての写真]アルバムに戻ります。


  1.写真アプリを開き、[アルバム]タブに移動します。

  2.「最近削除した項目」アルバムを開き、「選択」をタップします。

  3.復元する各写真またはビデオをタップします。

  4.写真またはビデオを選択 >「復元」をタップします。写真またはビデオを紛失した場合は、上記の手順を再度実行して、[最近削除した項目]の[選択]と[元に戻す]を行ってください。


 時々、30日経過しても最近削除したアルバムを空にしておらず、携帯電話のハードドライブに十分なストレージがある場合。削除された写真はリストから消えますが、これはそれらが永久に失われるという意味ではありません。これらの失われた写真はまだ復元することができます。


 これらの削除された写真はまだハードディスクストレージスペースのどこかにあり、システムはメモリスペースにアクセスできませんが、写真が画面から消えた後、サードパーティのiPhone写真復元ソフトウェアを使用してそれらを復元しない限り、そうしないと、「元に戻す」オプションがなくなります。


iPhoneから削除された写真を永久に復元する方法


 Bitwar iPhone Data Recoveryは、iPhoneから削除された写真を永久に復元するのに役立ちます。これは、インターネットで見つけることができる最高のサードパーティ製iPhoneプロファイルの1つです。 WindowsとMacのバージョンをサポートできます。何よりも、iPhone 5、6、7、8、XR以降など、iPhoneのすべてのバージョンをサポートします。また、最新バージョンのiOS、iOS 12および13もサポートしています。


   詳しくは、「<a href="https://jp.bitwar.net/course/iphone/2698.html">iPhoneから写真を簡単に復元</a>」をご参照ください。
Qiitaに初投稿する際に調べたこと

## 概要
プログラミングスクールに通い**卒業まであと12日**の時点で、
知識を言語化する重要性にやっと気づいたのでQiitaを利用し言語化することにしました！
まずQiitaに投稿する際に調べたことをまとめてみます！(関西出身です)

## 一、　「なにを書いたら良いんやろ」
[Qiita投稿ガイドライン](https://help.qiita.com/ja/articles/qiita-article-guideline)を確認したうえで私なりの解釈を一言でいうと、
**"見た人に役立つ記事を書く"**です！ 

記事投稿を思い立つまでの私は完全なる**見る専**で、
「こんな上手にまとめる(言語化する)なんか自分にはできひん」と決め付けてました。  

ですが、スクールでなにをしたか言語化できない自分に気付き、
とりあえずやってみよう！でQiitaに登録、そして投稿ガイドラインを見た私は、  
「**自分が作ってるアプリケーションの機能実装の内容を説明する記事を書く、
そしたら同じような実装をしたい人が見た時に役立つことになるやん！**」  
と考えました:grinning:

## 一、　「どうやって書いたら良いんやろ」
ずばり、、、**"Markdown（マークダウン）記法を用いて書く"**です！  

マークダウン記法にはいろんな種類の書き方があり、自分の表現したいものに合った書き方を調べる必要があります！
参考:[Markdown記法 チートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d#links---%E3%83%AA%E3%83%B3%E3%82%AF)

###### 本記事で使用したマークダウン
- 強調
- 見出し
- 改行
- リスト
- リンク

## 最後に
ご覧いただきありがとうございます！
つたない文章だったかと思いますが、初投稿に悩んでいる方の役に立てば良いなと思います！

## 参照記事まとめ
[Qiitaとは](https://qiita.com/Qiita/items/c686397e4a0f4f11683d#links---%E3%83%AA%E3%83%B3%E3%82%AF)
[Qiita投稿ガイドライン](https://help.qiita.com/ja/articles/qiita-article-guideline)
[Markdown記法 チートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d#links---%E3%83%AA%E3%83%B3%E3%82%AF)
学習アウトプット〜11/3〜

##生成したコードを元に戻す方法

「ああ、あの頃に戻れればなあと」自分の人生のある地点の後悔を引きずっている人は多いと思います。私にもそのような後悔はあります。

でも人生は元には戻れません。今に目を向けましょう。周りにいる人を見てみてください。その人たちと一緒に今を必死に生きていきましょう。

ということで、人生は元には戻せませんが、プログラミングは別です。
何か間違いがあれば何度でもやり直せます。笑

###コントローラ

```terminal
$ rails geneate controllar motipuyo
```
というようにmotipuyoという名前のコントローラを作成したけど、無かったことにしたいよって時は

```terminal
$ rails destroy controllar motipuyo
```
で削除されます。

コントローラは学校で言うとクラスの担任です。
modelやviewに指示を出すことで各クラスをまとめ、アプリケーションという一つの学校を成り立たせる。
今のところはこのようなイメージです笑。


###データベース

```terminal
$ rails db:migrate
```
上記はrailsのデータベースをマイグレイト(移行する、新しく更新する的な意味)するコマンドですが、それを取り消したい時は、

```terminal
$ rails db:rollback
```

```terminal
$ rails db:migrate VERSION=0
```
というコマンドを使うと削除できます。

上の"rollback""コマンドは一つ前に戻したい時、
下の"VERSION=0"のコマンドは最初の状態に戻したい時に使用します。

今は理解が難しいですが、
データベースを"migrate"で更新していくのを"rollback"で戻ることができる、
という程度に理解しておきます。
Railsのenumで範囲外の値を渡すとバリデーションするより先にArgumentErrorが発生してしまう。

例えば、次のようなユーザーモデルがあるとします。

```ruby:user.rb
class User < ApplicationRecord
  enum gender: { male: 1, female: 2, other: 3}
  validates :gender, inclusion: { in: User.genders.keys }
end
```

このユーザーモデルに対して、enumで指定していない値(今回はunknown)を渡すと、**バリデーションエラーより先にArgumentErrorが発生してしまいます**。

```ruby
user = User.new(gender: 'unknown') # ArgumentError ('unknown' is not a valid gender)
```

Railsのissueをみると、これは仕様のようです。
参考：https://github.com/rails/rails/issues/13971

> 現在のAR enumsの焦点は、パフォーマンス上の理由から、状態のセット（ラベル）を整数にマッピングすることです。**現在のところ、間違った状態の割り当てはアプリケーションレベルのエラーとみなされ、ユーザー入力のエラーではありません。これが ArgumentError を取得する理由です。**

issueを見ていくと解決策として、gem(ex. enumerize gem、enum_attributes_validation)の導入でも解消できそうです(実際にgemの検証はしていません)。

> 私の経験では、ARの列挙型は使用に直面する属性として多く使われています。**コミュニティにはenumの問題を解決するいくつかのジェムがあります（例：enumerize gemや上記のenum_attributes_validation）**。しかし、私はrailsがこれらの問題を解決し、箱から出してより良い経験を提供すべきだと考えています。喜んでその問題に協力します。

ですが、今回解消したいRailsプロジェクトでは初期段階からRailsのデフォルト機能のActiveRecord::Enumを使っているため、影響範囲等を考えgemは使わずに別の方法で解消していきたいと思います。

### 解決策
先ほどと同じissueにあった方法です。
Rails6で試して正常に動きました。
参考：https://github.com/rails/rails/issues/13971#issuecomment-542757073

```ruby:user.rb
# app/models/user.rb
class User < ApplicationRecord
  include LiberalEnum # ← 追加

  enum gender: { male: 1, female: 2, other: 3}
  liberal_enum :gender # ← 追加
  
  validates :gender, inclusion: { in: User.genders.keys }
end
```

```ruby:liberal_enum.rb
# app/models/concerns/liberal_enum.rb
module LiberalEnum
  extend ActiveSupport::Concern

  class_methods do
    def liberal_enum(attribute)
      decorate_attribute_type(attribute, :enum) do |subtype|
        LiberalEnumType.new(attribute, public_send(attribute.to_s.pluralize), subtype)
      end
    end
  end
end
```

```ruby:liberal_enum.rb
# app/types/liberal_enum.rb
class LiberalEnumType < ActiveRecord::Enum::EnumType
  # suppress <ArgumentError>
  # returns a value to be able to use +inclusion+ validation
  def assert_valid_value(value)
    value
  end
end
```

コードを追加した後は、サーバーを再起動する必要があります。

new時にArgumentErrorが発生せずにバリデーションを実行してくれるようになりました！

```ruby
user = User.new(gender: 'unknown')
user.save! # ActiveRecord::RecordInvalid (バリデーションに失敗しました:  性別は一覧にありません)
```

### まとめ
* enumで範囲外の値を渡すとArgumentErrorが発生するのはRailsの仕様
* API等で何でも値を渡せる状況の場合は、プロジェクト初期段階からgem(ex. enumerize gem、enum_attributes_validation)を導入しておくとこういう問題で悩まなくてよさそう ※実際にgemの検証はしていません。
検索を行うメソッド

# はじめに
検索機能をrailsで実装する際に、必要なメソッドについて解説しています。

## 1.whereメソッド
モデルが使用できる、ActiveRecordメソッドの1つです。
このメソッドにより、引数に記述した条件に一致するデータを取り出すことが出来ます。

```
モデル.where('検索対象となるカラムを含む条件式')
```
## 2.LIKE句
LIKE句は、曖昧（あいまい）な文字列の検索をするときに使用するもので、whereメソッドと一緒に使います。

cが含まれる名前を取り出す際の記述

```
where('name LIKE(?)', "%c%")	
```

%・・・任意の文字列

## 3.検索を行う際のコード
ここで、実際にコードを記述する場面を考えてみましょう。
例えば、ツイートテーブルのnameカラムに太郎という文字を含むデータを取り出す場合は、どんなコードとなるでしょうか？
もし、時間がある方は、自分で考えてみてください。

実際に記述は以下となります。

```
Tweet.where('name LIKE(?)', "%太郎%")
```

以上の記述により、検索を行えるメソッドを作成することが出来ました。
カラムやどんな値を含んだものを取り出したいのかを考えて実際に使用してみてください！

# 最後に
最後までお読みいただきありがとうございます！
同じ悩みや課題を抱えている方のお役に立てれば幸いです！
【AIアルゴリズム】次元削減（t-SNE）について

今回は機械学習の教師なし学習、「次元削減(t-SNE)」のアルゴリズムについて記事を書いていきます。
次元削減にはいくつかの有名なアルゴリズムがありますが、ここでは多次元データに適した手法のt-SNEについて書いていきたいと思います。

次元削減とは入力データの説明変数を少なくする変換のことで、元の入力データの情報を保ちつつも少ない変数で元のデータの特徴を説明できるようにすることです。

例えば、Aさんの年齢(目的変数y)を予想したいと考えた時にAさんの情報として身長(説明変数x1)、体重(説明変数x2)のみ与えられているものとします。大人になると子供よりも身長、体重がともに高くなっていくのである程度年齢と相関がありそうです。この時の身長、体重という2つの変数を次元削減しようとするとこの2つの変数の情報をある程度保ちつつも変数を1つにすることを考えます。そうすると、身長、体重の関係から「体格」という一つの変数を作れそうです。そして、その体格という変数を用いて年齢を予想することもできそうです。このように、いくつかある変数を一つにまとめることを次元削減といいます。

通常は変数が何十何百とある多変数データを2つ、3つの変数までに削減することが一般的です。

では、なぜわざわざ次元削減を行うかというと理由は大きく２つあります。1つ目は多次元データを視覚化するためです。視覚化することによってパッとみよくわからないデータでも人間の頭の中で把握しやすくなります。データの傾向をとらえやすくなれば、EDAや分析結果の評価などでもより説明しやすくなります。2つ目は「次元の呪い」を防ぐことです。次元の呪いとはおおまかにいうとデータの持つ変数の数が多すぎる(次元数が多い)と機械学習の色々なアルゴリズムにおいて性能が低下してしまうことです。私も次元の呪いについてさほど詳しくないのですが、全データの持つ情報は変わらないとして、変数が多いよりも変数が少なく、一つの変数あたりの情報量が多いほうがアルゴリズムの性能が高まりやすいそうです。

では、t-SNEのアルゴリズムについて考えていきたいと思います。改めて、PCAのようないくつかある次元削減手法の中でt-SNEは使い勝手がいいです。t-SNEの特徴は、多様体空間(部分的に多次元空間でも2点間の距離が表せるような空間)に分布したデータを次元圧縮して可視化できることです。ちなみにPCAは線形のデータ全体をみて次元削減することが得意ですが、t-SNEは非線形データを局所的(2点間)をみて削減するのが得意です。つまり、t-SNEは多次元の構造を極力残してデータ間の距離の着目することで2~3次元へ削減します。

t-SNEのベースはSNEというアルゴリズムなのでまずこちらから説明します。
SNEは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/806741/db74ceae-90ce-d317-f801-12faf8b90168.png)の数式です。
これは、与えられたiという条件におけるjの条件付確率です。あくまでも表しているのは確率ですが、これにより、高次元空間のデータ間の近さを表現します。
その中身はそっくりそのまま多変量でのガウス分布の式になっています。3次元以上で扱われる正規分布のようなものだと理解していますが、詳しくは別記事を参照ください。
重要なのはxとは圧縮前のデータ集合Xの中の一つのデータ点です。
プログラミングスクールに通って正直に思ったこと

#まず初めに

初めての投稿です。
「こうやってエラーを解決した！」とかよく忘れがちなこととかを書こうと思ったのですが、
私自身プログラミングスクールに通っていたこともあり、なんとなくなのですが、

世界中・日本で予期できないパンデミックが起こっている
→「会社の経営状況が微妙…仕事もないし…自分で稼ぐ力が必要なのかも…」
（YouTubeとかでプログラミングスクールの広告を見て）
→「**エンジニア！？**
　手に職をつけられて、将来性もあっていいかも！フリーランスもいけるみたいだし！」
→「プログラミングスクールに通ってみたいな～
でも調べたらいっぱい出てきた…どれにすればいいのか分からない…」
という方が増えている気がするのです。（個人的な見解）

という訳でプログラミングスクールに通って正直に思ったことを書いていきます。
・プログラミングスクールに通おうか迷っている方
・現在プログラミングスクールに通っている方
の参考になればと思います。

#プログラミングスクールに通おうと思った理由

**独学で勉強するのに限界を感じた**
progateなどを使って勉強をしていたのですが、
「ここが分からない！」と思っても誰も教えてくれる人はいません。
（メンターを探せるサービスもあるみたいなので、それを使ってもいいかもしれません。https://menta.work/）
「ここが分からない！」状態になっている時と仕事が忙しい時が被ってしまうと、
いくらプログラミングの勉強をしようと思っていても
「まあ今日は仕事疲れたし、勉強せんでいいやろ～」と思ってしまうことがあり、
なかなか勉強が進まない時期がありました…

**お金をかけることで勉強しようと思えるタイプだった**
これは私の性格上の部分でもあるのですが、お金をかける(=自分に投資をする)ことでその分頑張ろうと思えるタイプだったので、お金をかける=その分本気で頑張ることでプログラミングが理解できるのでは？と思ったので、プログラミングスクールを検討するようになりました。

#プログラミングスクールについて

私が選んだプログラミングスクールでは、HTML,CSS,JavaScript,Rubyについて学びました。
地方住みなので近くにスクールもなかったので、完全オンラインのスクールに通っていました。
費用はだいたい30万円ほどだったと思います。
当時貯金もあまりなかったので、費用を安く抑えられるスクールを選びました。
(プログラミングスクールってなんであんなに高いんですかね？)

#スクールに通ってよかったこと
**モチベーションは下がりながらも継続して勉強できた**
スクールに通っていた時もたくさんの壁にぶつかりました。勉強をしない時期もありました。
しかし、講師の方が分かりやすく優しく教えてくださったので、前向きに継続して勉強ができたと思っています。

**独学よりも理解度が深まった**
「分からない！」という部分があっても、講師の方が噛み砕いて教えてくださったり、テキストも分かりやすく作られていたので独学よりはきちんと理解できたと思います。

**自分で解決する方法（＝自走する方法）を身に付けられた**
(講師の方にもよると思うのですが)
私が通っていたスクールでは、答えをそのまま教えてくれるというよりは解き方を教えてくれることが多く、たくさんヒントをいただきながら、勉強を進めていった印象があります。
そのおかげもあって、スクールのカリキュラムが終わって、分からない部分が出てきても自分でググって解決できるようになりました。

#スクールに通った感想
**スクールに通っただけで満足してはいけない**
スクールに通って学んだことでも人間の記憶だと一瞬で忘れてしまいます。
なので学んだことを定着させたいのであれば、プログラミング学習を継続する必要があるなと思いました。

**エンジニアとして働けるかどうかは分からない**
私の通っていたスクールでは転職保証がなかったので、「エンジニアとして働きたい！」と思った時に1から自分で転職活動を始めることになりました。
（エンジニアとして働くためにスクールを検討している場合は、転職保証のあるスクールを選んだ方がいいと思いますが、実態がどうなのかは私には分からないので、その点も考えてスクールを選ぶのをおすすめします。）

#もっと早くやっておけばよかったこと（※重要）

**Twitterで勉強垢を作る**
勉強仲間を作るのは重要です。
私が通っていたスクールは全てオンラインで完結するスクールだったので、1人で勉強をしているとモチベーションを保つのが難しかったです。
今はなかなか集まって勉強をするのも難しい時期ですし、プログラミングの勉強を始めたら、勉強垢を作って勉強したこと・疑問点などをつぶやくのがおすすめです。

**勉強会に参加する**
私はいつもconnpass(https://connpass.com)
で探しています。初心者OKの勉強だと参加しやすいと思います。
最近はオンライン開催の勉強会も多いので、いろんな勉強会に参加できて嬉しいです。

**オリジナルポートフォリオを作成する**
スクールで作ったポートフォリオはだいたいどこのスクールも作っているので、きっと採用担当者の方も見飽きているような気がするのです。
そのため、自分が作りたいと思ったもので構わないので、オリジナルのポートフォリオを作るのをおすすめします。


**技術本を読んでみる**
スクールで教えていただいたことはWebサービスの作り方みたいなことが中心で、その裏でパソコン内では何が起こっているのか？が分からずにいました。
技術本にはデータの流れだったり、パソコン内部で行われていることが詳しく書かれてあったので、技術本を読むことでより理解度が深まったと思います。

#最後に
読んでいただき、ありがとうございました！
滅びの呪文 rm -rf /* が意図せず発動するケース（初心者＆レビュア向け）

`rm -r`コマンドはディレクトリ配下のサブディレクトリやファイルを一気に削除してくれます。
バッチ処理などで警告を無視して削除したいケースでは`-f`オプションをつければ可能です。
「潔さ」さえ感じる`rm`コマンドですが、それを見ただけで滅びの呪文を連想する人も多いはず。

『ルートディレクトリ配下を全て消してしまった』（通称：バルス）

という嘘のような誰かの経験談を耳にしたことはあっても、
自身で経験したことのある人はそう多くないと思います。

経験を積んだエンジニアなら「自分は大丈夫」と思うでしょう、
初心者であっても「まさかそんな間違いはしないだろう」と思うことでしょう。
私もそうでした。

油断しているとそのまさかの事態に陥りかねない、注意すべきケースがあったので共有します。

<font color="Red">※以下のサンプルコードは危ないので実行しないでください</font>
<font color="Red">（試す場合はDockerコンテナ上などで行ってください）</font>
- - -
### 未定義の環境変数を使用してバルス

```shell:sample1.csh
#! /bin/csh
# 変数設定
set HOGE_DIR = "/home/user1/test"
# 対象ディレクトリ配下削除（バルス例）
rm -rf ${HOGE_DIL}/*  
```
- `rm`のところでHOGE_DIR ではなく HOGE_DI<font color="Red">L</font>としてしまっている
- これにより`rm -rf /*`となりルートからの削除が実行されてしまう
- 環境変数のタイポには注意が必要

### コマンドを引数で渡すときの不正な文字列囲いによるバルス
```shell:sample2.csh
#! /bin/csh
# 変数設定
set RHOST = "svr1"
set RUSER = "svr1_user"
set HOGE_DIR = "/home/svr1_user/test"
# 対象ディレクトリ配下削除（バルス例）
rsh ${RHOST} -l ${RUSER} 'rm -rf ${HOGE_DIR}/*' 
```
- `rsh`はネットワーク経由で別のコンピュータ上で処理を実行するためのコマンド
- シングルクォーテーションで囲われた環境変数は文字列としてそのまま解釈される
- `rm -rf ${HOGE_DIR}/*`が接続先で実行されるため、接続先に環境変数`${HOGE_DIR}`が定義されていない場合、`rm -rf /*`となりルートからの削除が実行されてしまう
- ダブルクォーテーションで囲った場合は環境変数の読替えがなされ、`rm -rf /home/svr1_user/test/*`が接続先で実行されるため、この場合はダブルクォーテーションで囲うのが正解
- `rsh`以外でも文字列の囲い方には注意が必要
 
- - -

滅びの呪文の犠牲者が増えないことを祈ります。
（safe-rmというrmコマンドをラッピングした安全なコマンドを導入するのも手です）
【C#】リフレクションで静的プロパティにアクセスするのはめんどくさい

# はじめに

リフレクションを利用して静的プロパティにアクセスしたいときってありますよね?
(`public`ではないプロパティを触りたいときなど)
ググるとやり方はいくらでも出てきますが，それにもかかわらず実際に書いてみると躓いてしまったので，記事として残しておこうと思います。

# やり方

ダラダラ書いてもしょうがないので例を示します。
ここでは，別アセンブリ内の静的クラス`Qiita.MyClass`に定義されている`Prop`の値を取得します。
当然ですが，`Qiita.MyClass`が定義されているアセンブリが参照に追加されている必要があります。

```C#
// using System;
// using System.Reflection;

// 別アセンブリ内のクラスは`Type.GetType`では取得できないので，`Assembly.GetType`を利用する。
Type MyClass;
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())  // 読み込まれているアセンブリを取得
{
  var T = asm.GetType("Qiita.MyClass");  // 目的の型を取得しようとしてみる。

  if (T != null)  // 取得できなかったら`null`になる。
  {
    MyClass = T;
    break;
  }
}

// StaticとNonPublicを両方指定しないといけない。
var info = MyClass.GetProperty("Prop", BindingFlags.Static | BindingFlags.NonPublic);

// ここでも`BindingFlags.Static`が必要。
dynamic val = info.GetValue(MyClass, BindingFlags.Static, null, null, null);

// 取得した`val`で何かする
```
最後の`PropertyInfo.GetValue`の呼び出し時に`BindingFlags.Static`を渡さないと`ArgumentException`になってしまいます。
これがわからなかったので時間を溶かしてしまいました。
~~調べても書いてなかったんだもん~~

`PropertyInfo.GetValue`の戻り値は`object`ですが，`dynamic`で受けると適当な型として扱えます。怖いですが……。

# まとめ

`public`ではないということには理由があるので，リフレクションで強引にアクセスしようとするのはやめましょう。
(パフォーマンス的にもよろしくない)
【Ruby】投稿したものを日付の新しい順に表示したい

何かしらの投稿機能、例えばTwitterのような新しい投稿が先に表示される機能を実装していたところ、考え方が凝り固まっていた部分があったので備忘として記載します。

私がやりそうになったのは以下です。
`ハッシュを含む配列に対し、受け取ったビューファイル側で降順ソートして表示しようとした`

しかしよく考えると、これは保守性が高くないことに気付きました。
表示は表示という機能に集中することなど、各機能はそれぞれに特化すべきです。メソッドも同様です。
そのため、`受け渡す際にソートした状態で受け渡す`、これを行う必要がありました。

以下は例です。
Itemテーブルに存在するデータを@itemsに格納する際、「.order('created_at DESC')」というオプションを追加しました。

```java:controller
  def index
    @items = Item.includes(:user).order('created_at DESC')
  end
```
こうすることで、ビューファイルの表示、という機能に手を加えることなく制御することができました。
Windows ServerをWinRMでリモート操作する

# 背景
ユーザ先設置のWindowsサーバでリモートデスクトップが禁止されたときのために。そういう時もあるかもしれないので。

・接続される側→ホスト
・接続する側→クライアント
とします。

※　2020/12/08追記
クライアント側で設定が必要な旨を追記しました。
信頼済みホストへの登録が必要です。

## WinRM
いまのところこれが気に入っています。というかこれしか知りません。sshはサーバ側でインストールが必要なので、デフォルトで使えるのが便利かなーって。

クライアントがWindows10 1903、ホストがWindows Server 2019の環境で試しました。

通信経路のNW機器(ルータ等)で、ホスト宛てTCPの5985宛て通信がブロックされていないことを前提で話を進めます。

### 手順
1.ホストで設定

```powershell
Enable-PSRemoting
```
コマンドレット1発で設定されるのは便利ですが、結構な設定変更が行われます。中身を確認して、運用ポリシーに違反するものがないか確認したほうが良いです。
ただ、 Windows Server 2019で確認したときはファイアウォールのみオフにした状態のほかはホスト側なんもせずに接続できたので、デフォルトで接続できるように設定されてるんじゃないかなと思いますが…

>
The Enable-PSRemoting cmdlet performs the following operations:
Runs the Set-WSManQuickConfig cmdlet, which performs the following tasks:
Starts the WinRM service.
Sets the startup type on the WinRM service to Automatic.
Creates a listener to accept requests on any IP address.
Enables a firewall exception for WS-Management communications.
Creates the simple and long name session endpoint configurations if needed.
Enables all session configurations.
Changes the security descriptor of all session configurations to allow remote access.
Restarts the WinRM service to make the preceding changes effective.

[Enable-PSRemoting](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/enable-psremoting?view=powershell-7)

2.クライアントで設定

```powershell
Start-Service -Name WinRM
```
-Nameはなくてもいける。

信頼済みホストを登録する

```powershell
Set-Item WSMan:\localhost\Client\TrustedHosts -Value <接続先ホストのIPアドレス>
```

信頼済みホストを確認するときは下記、

```powershell
Get-Item WSMan:\localhost\Client\TrustedHosts
```

信頼済みホストを削除するときは下記です。

```powershell
Clear-Item WSMan:\localhost\Client\Trustedhosts
```
3.接続する

```powershell
Enter-PSSession -Computername <接続先ホストのIPアドレス or ホスト名> -Credential <接続先ホストで有効なアカウント名>
```

パスワードの入力ダイアログが表示されたら、パスワードを入力します。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581105/477855db-08d3-df6a-1a45-49fd2ebd6186.png)

接続できたらプロンプト の表示が変わります。
![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581105/ebca7d61-82b4-c45e-59f1-3c2aa312890a.png)

接続さえできてしまえば、あとはいろいろできますね。
Basic認証導入時、Heroku上でログインができない。

![スクリーンショット 2020-11-04 17.42.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/770386/5f165b05-3cd3-1667-920e-d68b989a8951.png)

## 背景
Basic認証を導入して、必要最低限のセキュリティを設けたい。
過去に２度Basic認証の練習として導入したことがあり、その時はスムーズにできたため、今回も導入したいと考えた。
しかし、実際に導入してみると、ローカル環境では正常に動作しログインできるものの、本番環境では正しいユーザー名とパスワードでも弾かれてしまった。

## 行ったこと
まず、現状を確認するため、もう一度git push heroku masterでどう表示されるかを確認した。

```terminal
% git push heroku master
Everything up-to-date
```

全て最新の状態であることから環境変数を設定する前に、github上でコミットしてしまったり、git push heroku masterなどのコマンドを実行したと仮説を立てた。空のコミットをしてから、再度git push heroku masterをする必要があると考え、実行した。

```terminal
% git commit --allow-empty -m "コミット名"

% git push heroku master
```

######しかし、ログインできませんでした。

#原因
application_controller.rbに記述している、private内の記述と、heroku上に設けた環境変数の名前が一致していなかった。



```ruby:app/controllers/application_controller.rb
  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV["BASIC_AUTH_USER"] && password == ENV["BASIC_AUTH_PASSWORD"]
    end
  end
```

```terminal
% heroku config

=== アプリ名 Config Vars
BASIC_AUTH_PASSWORD:      *****
BASIC_AUTH_USERNAME:      *****
```

#対処法
双方の環境変数が紐付くように、同じ名前に変えてあげれば良い。
今回の場合はUSERNAMEかUSERに統一させてHerokuに上げれば、正常にログインできました。
30代　IT業界未経験者の方向性

面接でなかなか楽しい話を聞けたので忘備録。
小規模ながら29年続いている社長さんの話。

<h1>PG（プログラマー）の寿命</h1>
35歳定年説など短寿命のイメージがある。
どんな人が長期的にPGをやっているのか。

* 元々プログラムが好きで好きで楽しんでいる人
* プライベートもプログラム三昧でも苦じゃない人
* 新卒入社で勤続年数もありPGしか選択肢がない人
* スクール卒業からPGとして長く続く人は29年やっていて見たことがない
* フリーランスエンージェントから毎日のように単価60〜80万円（50歳付近）のPG人材案件が多く送られてくる（高単価は使えないので単価が安い方に需要）
* スクール卒程度の中途半端なPG需要はないので大量に人が余っている（現場とのギャップ）
* 技術について行けずに心身を病んで去っていく人、地元へ帰る人、異業種転職（年齢問わず）
* ベンチャー企業など数年後残っている会社は少ない（事業リスクヘッジ、経営手腕が問われる）
* リーマンショック、コロナなど経済的な打撃時の大量リストラ（あまり報道されない）

<h1>空いているポジション</h1>
* PM（プロジェクトマネージャー）などIT知識もありマネジメントが出来てコミュニケーションが得意な人材
* 需要が高く100万近くで募集もある
* サーバー、ネットワーク、DB系なら年齢的に可能性があるかも

<h1>なぜPMが足りないと分かっているのに補充されないのか</h1>
* プロジェクトがトラブったときの責任者（矢面に立たなければならない）
* クライアントと現場、会社に板挟み（中間管理職）
* 燃えている中に自ら進んで飛び込みたい人はいない
* IT業界で上記の風潮があり必然的に少なくなった（コミュニケーションが苦手な人が多く残った）

<h1>30代未経験でどう動けば需要が高まるか</h1>
理想は働きながら勉強が出来ることが証明できると雇いやすい

* 資格はあった方が良い
　LPIC101
　OSS-DB
ここら辺を皮切りに専門的な高度資格へ派生していくイメージ

* 継続的なアウトプットがあると安心
* IT業界ではなく勉強したことを前職業界でPRしてIT系部署を狙う

<h1>感想</h1>
華やかなイメージで仕事を辞めてスクールへ通う人はたくさんいて、今も増え続けている。
しかし、現場とのギャップが大きく、就職してもすぐに辞めてしまう人もいる。
SE、PGを長期的に育てるなら20台前半がいい。
働きながら継続的な技術の吸収意欲が高く、資格取得やポートフォリオがある人は評価できる。
必ずこのポジションになりたいとはっきりしている人は、若ければ有利。
自分の価値を上げやすい需要あるポジションを狙うなど年齢、時間と相談して現実的なキャリア設計をしたい。
インフラ系の仕事ははっきりした形がイメージしにくいのでさらに知識を深めたい。

一企業の社長さんの話が響いたので書きました。
こんな意見もあるんだと参考になれば良いと思います。

追記、Twitterで知ったmasa-lab氏のエンジニアブログです。
https://masa-lab.hateblo.jp/entry/2019/12/25/180021
今回の社長の意見と通じるものを感じました。

感想、意見があればコメントいただければ幸いです。
iPhoneのウィジェットでGitHubの草を確認する

# はじめに
GitHubにはコントリビューションカレンダーという、GitHubでの活動量（通称「草」）を図で表したモノがあります。

この草によってある程度活動量が可視化されるため、***「最近学習できていないなぁ」***、***「最近結構勉強出来ているから引き続き頑張ろう」***など感じることは様々です。

私自身、日頃学習していて草が増えていくのを見てもっと頑張ろうと思っています。
このGitHub上の草が、手軽にiPhoneで確認できたら毎日やる気が出そうな気がします！笑

今回は、なにやらGitHubコントリビューションのカレンダーグラフをios14でサポートされたウィジェットで表示することが出来るアプリがあるらしいので実際に使用しつつご紹介させていただきます。

# アプリのインストール
アプリ名は、***「Contribution Graphs for GitHub」***です。
こちらからアプリのインストールができます。[App Storeページ](https://apps.apple.com/jp/app/contribution-graphs-for-github/id1537192731?ign-mpt=uo%3D2)
アプリサイズは、3.1MBと軽量です。

# 使ってみる
使い方はとても簡単でした。

まずはアプリのインストール。

インストールしたら、ホーム画面上にウィジェットを作成します。
ウィジェットの作成方法は、ホーム画面を長押しすると右上に＋ボタンが出てくるのでそちらを押します。
<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/508d0cab-8f4d-de36-f2c6-5a4e56afd465.jpeg">

そして、こちらのContributionsを押します。
<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/502c1286-8239-36a9-1065-de3ee31e5538.png">

そうすると、こちらの画面になります。
ホーム画面に表示するウィジェットのサイズを選択します。サイズは2種類あります。
<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/fe9940db-468b-c98d-cc36-7deefa4f3470.png">

<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/b045a868-6b9f-ebbf-5ac2-bfe72b35bf3f.png">

好きなサイズのものを選択するとこちらのように、ホーム画面にウィジェットが表示されます。この状態ではまだ、アカウントの選択がされていないため草は表示されません。
そのため、「Set a GitHub username」を押し、自分のアカウントの指定します。

<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/05c07215-9f65-2eb3-1844-a7c92c318dc0.jpeg">

<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/fadfbd04-8ef1-9eef-906b-1d870d332e2a.png">

上記画面で、Username箇所に自分のGitHubアカウント名を記載するだけでOK。
テーマは3種類あって、草の色を変えることが出来ます。これで完了

こんな感じになります。
<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/3dd57477-6279-c284-119e-776e3cf22cb5.jpeg">

# まとめ
今回は、ウィジェット上でGitHubの草を表示させるアプリ「Contribution Graphs for GitHub」のご紹介をさせていただきました。

日常的に自分のGitHub上での活動量が確認できることで学習意欲が増すかもしれないです！
おすすめなので、是非入れてみてはいかがでしょうか？
Mendix に決済処理を組み込む

# はじめに

Mendix でさくさくアプリを開発している時、商品・サービス販売のページにクレジットカード決済を組み込みたいことがあります。PAY.JPを利用して簡単に決済を組み込んでみましょう。

# PAY.JP

PAY.JPは決済代行のクラウドサービスです。

[こちら](https://payjp.hatenablog.com/entry/2017/11/10/111841) のページのシーケンス図のように、カード情報のトークン化はクライアントとPAY.JP間で行われ、カード情報をサーバーには送信せずにセキュアにクレジットカード決済を行うことができます。

![シーケンス図](https://cdn-ak.f.st-hatena.com/images/fotolife/g/goofmint/20171108/20171108144326.png)

# Mendixでの利用

PAY.JPのCheckoutをMendixに埋め込むため、[PayjpWidget](https://github.com/naofum/Mendix-PayjpWidget/releases/download/v1.0.0/PayjpWidget.mpk) を使用します。

![PayjpWidget4.png](https://github.com/naofum/Mendix-PayjpWidget/blob/main/Screenshots/PayjpWidget4.png?raw=true)

ウィジェットの設定では、トークン化されたトークンをセットするエンティティの属性を指定します。これは画面に表示する必要はありませんが、今回はテストのため表示させています。
また、今回はテストのため、公開鍵はテスト用のものを使用します。

![PayjpWidget5.png](https://github.com/naofum/Mendix-PayjpWidget/blob/main/Screenshots/PayjpWidget5.png?raw=true)

商品・サービスの購入画面の例です。

![PayjpWidget1.png](https://github.com/naofum/Mendix-PayjpWidget/blob/main/Screenshots/PayjpWidget1.png?raw=true)

ウィジェットの場所に表示されたボタンを押すと、クレジットカード情報を入力する画面が表示します。入力されたクレジットカード情報の通信はクライアントとPAY.JP間で行われ、カード情報をサーバーには送信しません。

![PayjpWidget2.png](https://github.com/naofum/Mendix-PayjpWidget/blob/main/Screenshots/PayjpWidget2.png?raw=true)

カード情報を入力すると、ボタンの色が変わり、取得したトークンが表示されます。

![PayjpWidget3.png](https://github.com/naofum/Mendix-PayjpWidget/blob/main/Screenshots/PayjpWidget3.png?raw=true)

# 後処理

トークンを取得した後は、マイクロフローでPAY.JPのREST APIを呼び出して支払いなどの処理を行います。
トークンは１回しか使うことができないので、１回限り利用のサイトを作っているのであればこのトークンを使用して支払い処理を行います。通常はトークンで顧客を作成して、PAY.JPの顧客情報と、アプリケーションの顧客情報を紐付けて管理することになります。

APIについてはこちらのドキュメントを参照してください。

- [PAYJP API利用ガイド](https://pay.jp/docs/started) 
- [PAYJP APIリファレンス](https://pay.jp/docs/api/)