OmniAICreator/Qiita-1.07M huggingface dataset:
@Transactionalアノテーションにつけたクラスは何があった

# @Transactionalアノテーションにつけたクラス、プロキシクラスを作った

[掲示板サンプルアプリケーション](https://github.com/saladlam/spring-noticeboard)を見て、クラス*info.saladlam.example.spring.noticeboard.service.MessageServiceImpl*に**@Transactional**アノテーションがつけた。BeanFactoryはこのクラスを処理、*org.springframework.transaction.interceptor.TransactionInterceptor*がつけたプロキシクラスを作った。下の図はEclipseデバッガで本物の*MessageService*インスタンスが示された。

![eclipse_debug_messageservice.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232557/097f9cc7-f1e7-d13c-4315-2ef6b3243acd.png)

# TransactionInterceptorの役目

1. トランザクション開始と終了の意図がPlatformTransactionManagerインスタンスに伝えること
2. 例外処理

下のコードはメソード*org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(Method, Class<?>, InvocationCallback)*の一部。

```java
// ...
		// If the transaction attribute is null, the method is non-transactional.
		TransactionAttributeSource tas = getTransactionAttributeSource();
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		final org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(Method, Class<?>, InvocationCallback) tm = determineTransactionManager(txAttr);
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

		if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

			Object retVal;
			try {
				// This is an around advice: Invoke the next interceptor in the chain.
				// This will normally result in a target object being invoked.
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// target invocation exception
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				cleanupTransactionInfo(txInfo);
			}
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}
// ...
```

プログラムが

```java
retVal = invocation.proceedWithInvocation();
```

を実行するとき、*info.saladlam.example.spring.noticeboard.service.MessageServiceImpl*のメソードが呼ばれる。

# PlatformTransactionManagerの役目

Spring Frameworkのコンテキストのなかにシングルトン*PlatformTransactionManager*インスタンスがある。ここに示したサンプルアプリケーションは*org.springframework.jdbc.datasource.DataSourceTransactionManager*という実作。このインスタンスはすべてのトランザクションに関する請求を処理する。
[覚書] linux便利コマンド

* 検索に使えるコマンド
` (sudo) grep "文字列" ディレクトリパス | tail `

* 複数あるファイルの中から特定の文字列を検索したい。ファイル名だけ取り出す
` find ./ -type f -print | xargs grep 'hoge' `
`grep [検索したい文字列] -rl [検索対象フォルダのパス]`

* さらにその文字列を置換する
` grep '置換対象文字列' -rl ./ | xargs sed -i.bak -e 's/置換対象文字列/置換文字列/g' `
※-i でバックアップを取る。iの後ろに拡張子をつけてあげられる。

* サブディレクトリまでgrep
` grep -r ディレクトリパス/* `

* 探したいファイルがいるの
` find ./ -name ファイル名 `

* 探したいファイル。部分一致でもいいの
` find ./ | grep 名前 `

* ファイル数知りたい
` find ./ -type f | wc -l `

* ディレクトリ内のファイル数をカウント
` ls -U1 | wc -l `

* ゴミは表示しない
` 2>/dev/null `

* wget
` wget -q -O 設置するディレクトリパス http://取得元URL `

* 整形ファイルいい感じにチェック
` cat ファイル名 | awk -F"\t" '{print $37}' | sort | uniq `

* MySQL系の確認
`(rootUser) rpm -qa | grep mysql `

* インストールされているかどうか確認
` yum list installed 2>/dev/null | grep 検索対象名 `

* インストール
` sudo yum install -y インストール対象 `

* ファイル内文字列検索
` grep '文字列' ディレクトリパス `

* プロセス確認
` ps aux  | grep 検索対象名 | grep -v  grep `

* プロセスkill
` sudo kill -9 プロセスＩＤ `

* ファイルに共通行があれば抜き出す
` grep -x -f `

* 詳細に出すdiff
` diff -c `

* 行番号指定してcat
` cat -n ディレクトリパス | head -n 39 | tail -n 6 `

* 文字エンコードえくすぽーとする。
` export LANG=ja_JP.UTF-8 `

* 「2017/05/11」等の日付を抽出
` "^[0-9]\{4\}/[0-9]\{2\}/[0-9]\{2\}" `

* ファイルをsortしてからdiffをとる
` diff <(sort a.txt) <(sort b.txt) `

* 確認しながら置換 (vim)
` %s/hoge/fuga/gc `

* どこのサーバーが繋がっているか確認
` netstat -tan | grep "IPアドレス" | awk '{print $5}' | awk -F':' '{print $1}' | sort | uniq `

* エラーログ調査に役立ちそう。
` egrep "^ERROR" ディレクトリパス | grep "文字列" `

* ファイル比較
` md5sum ファイルパス　ファイルパス `

* 文字検出
` egrep -n "ERROR" ディレクトリパス `

* ファイル内文字列置換をfor文で
` for ((i=105; i<116; i++)); do echo ./ファイル名 | xargs sed -i.bak -e 's/置換対象文字列/置換後文字列-'$i'/g'; done `
※'$i'で回す分の数字を反映

* ファイルコピー。名前連番で変えつつ
` for ((i=104; i<=115; i++)); do cp コピー元ファイル名 コピー後ファイル名-$i; done `
※"$i"とダブルクォーテーションで囲むこと

* ファイル名一括置換
`rename 置換対象文字列 置換後文字列 ファイルパス`
※ワイルドカード使用可
ex) rename hoge fuga ./*.txt => 拡張子「.txt」のファイル名の「hoge」部分を「fuga」に変える
MacやWindowsのSlackをダークモードに簡単に対応する方法

# 目の負担を軽くするため、デスクトップSlackを無理やりダークモードにしてる奴がいたんですよ～

# ｢な～に～　やっちまったなぁ！｣

# 「男は黙って」
`git clone https://github.com/LanikSJ/slack-dark-mode && cd slack-dark-mode`


# 「Mac/Linuxなら黙って」
`./slack-dark-mode.sh`

# 「Windowsなら黙って」
`.\slack-dark-mode.ps1`

# 終わり
終
制作・著作
━━━━━
ⓃⒽⓀ
CStringに数値が含まれるかどうか判定する

前提：str.Getlength() != 0

```Validate.cpp
#include <cctype>

Cstring Validate(CString str)
{
    for(int i=0; i<str.GetLength(); i++) {
        if(!std::isdigit(str[i]))
            return _T("数値以外が含まれる");
    }
    return _T("数値のみ");
}
```

完全にメモです。
Qiitaに同じような記事がなかったので投稿しました。
EKSで"Insufficient pods"が出てPodがPendingになったときの対処法

## 状況

EKSクラスタに新しくPodをデプロイしたら、PodのStatusがPendingになってしまった。describeで確認すると、"pod insufficient"というメッセージがある。新しくたてたPodのみ全てこの症状で、以前からたっていたPodは問題なく動いている。

``` console
$ kubectl get pods       
NAME                                             READY   STATUS    RESTARTS   AGE
<pod-name>                                       0/1     Pending   0          14m

$ kubectl describe <pod-name>
Events:
  Type     Reason            Age                 From               Message
  ----     ------            ----                ----               -------
  Warning  FailedScheduling  57s (x26 over 15m)  default-scheduler  0/2 nodes are available: 2 Insufficient pods.
```

## 原因

原因は、EC2に割り当てられるセカンダリIP数の不足だった。この記事を見て知った。([EKS利用時に注意すべきポイント - Qiita](https://qiita.com/paper2/items/efa1083ce955c174c800#pod%E3%81%AE%E8%B5%B7%E5%8B%95%E5%8F%AF%E8%83%BD%E6%95%B0%E3%81%AFec2%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%97%E3%81%AB%E5%88%B6%E9%99%90%E3%81%95%E3%82%8C%E3%82%8B))EC2インスタンスは各タイプによって、ネットワークインターフェイスの最大数が決まっていて、その上限を超えてしまっていた。（具体的な上限数などはここを参照 [Elastic Network Interface - Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-eni.html)）

例えば、今回開発用に使用していたクラスタは、ワーカーノードに"m5.large"２つを使用していたため、クラスタ全体で、(3\*10-1)\*2=58 個しかセカンダリIPを使用することができない。つまりPodも58個までしか立てられない。

もちろん、Podの数を確認したら58個のPodがたっていて、それ以降スケジュールしたPodはPendingになっていた。

## 対処法

`eksctl`で作成したクラスタだったので、`eksctl scale`でワーカーノードを増やした。これで解決した。

``` console
// クラスタ名を確認
$ eksctl get cluster --profile <profile>
NAME            REGION
<cluster-name>  ap-northeast-1

// nodegroup名を確認
$ eksctl get nodegroup --cluster=<cluster-name> --profile <profile>
CLUSTER          NODEGROUP          CREATED                 MIN SIZE        MAX SIZE        DESIRED CAPACITY        INSTANCE TYPE   IMAGE ID
<cluster-name>   <nodegroup-name>   2019-07-30T00:31:09Z    2               2               2                       m5.large        ami-0fde798d17145fae1


// node数を3に増やす
$ eksctl scale nodegroup --cluster=<cluster-name> --nodes=3 --name=<nodegroup-name> --profile <profile>
[ℹ]  scaling nodegroup stack "eksctl-<cluster-name>-nodegroup-<nodegroup-name>" in cluster eksctl-<cluster-name>-cluster
[ℹ]  scaling nodegroup, desired capacity from 2 to 3, max size from 2 to 3
```


## 参考

- [EKS利用時に注意すべきポイント - Qiita](https://qiita.com/paper2/items/efa1083ce955c174c800#pod%E3%81%AE%E8%B5%B7%E5%8B%95%E5%8F%AF%E8%83%BD%E6%95%B0%E3%81%AFec2%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%97%E3%81%AB%E5%88%B6%E9%99%90%E3%81%95%E3%82%8C%E3%82%8B)
- [Elastic Network Interface - Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-eni.html)
【Rails】ActiveSupport::MessageEncryptor::InvalidMessage

## 理解してないのに安易にコマンドを叩くなって話

#### 本番環境にて環境変数を設定しようとあれこれしていると...


```terminal:ターミナル
$ rails s
・
・
・
/Users/hogetaro/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activesupport-5.2.3/lib/active_support/message_encryptor.rb:206:in `rescue in _decrypt': ActiveSupport::MessageEncryptor::InvalidMessage (ActiveSupport::MessageEncryptor::InvalidMessage)
```
`ActiveSupport::MessageEncryptor::InvalidMessage `見た事ないエラーでました...

#### 参考記事

>Rails 5.2 で ActiveSupport::MessageEncryptor::InvalidMessage
https://qiita.com/scivola/items/cc06ddbfd94d3118f693
Rails5.2から追加された credentials.yml.enc のキホン
https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39

## 何が起きたのか

#### rails credentials:editコマンド叩いたら勝手に鍵を生成して config/master.key に保存された...

新しく生成された鍵は既存の`config/credentials.yml.enc`の復号には使えない。

参考記事によると、`master.key`は`rails new`した際に作成されます。そしてこの`master.key`に記載されているキーを利用して`credentials.yml.enc`は暗号化・復号されているようだ。

このままでは、違う鍵を持っている私は`credentials.yml.enc`という名前の扉を開く事ができないらしい...

なぜこのコマンドを使ったかというと、よくコマンドの意味を理解せずにやってみたら何か変化するかも的な感じでコマンド使いました...反省


## 解決方法

#### credentials.yml.encファイルを削除してrails credentials:editコマンドもう一度

ただし**開発初期段階**で`rails new`した時に作成される`config/credentials.yml.enc`と内容に違いがなく問題にならない場合に限る

今の自分の状況ではこの方法はマズいような気が。既にデプロイされているのでawsの`secret_access_key`やら設定している。

#### やり方
`credentials.yml.enc`を右クリックでもいいのでゴミ箱へ

```terminal:ターミナル
$ sudo EDITOR=vim rails credentials:edit
New credentials encrypted and saved.
```
これで`config/master.key`は存在してなければ作られる。存在していればそれが使われる。あと`credentials.yml.enc`が新しく作り直されます。`rails s`できるようになります。

**新しい鍵と一緒に新しい扉に取り替える感じですかね**
**既存の鍵に合う錠前に付け替える感じですかね**

#### チームメンバーにキーを教えてもらう

`config/master.key`は`.gitignore`によってgit管理させないようにしている。なのでgithubからcloneしても`master.key`は分からないという事なので自分で`rails new`した環境の`master.key`の中身が分からない場合は教えてもらうしかない。

**扉を取り替えるのは大変なので家族の鍵借ります=>合鍵作ります**

## 結論

つまらぬエラーで時間を無駄にしないように、よくよく調べて理解してからコマンド使います。

間違いがあったらご指摘ください。

#### 終わり
英語弱者のためのarXivの論文翻訳


どうも初めましてマイメン！神戸とサッカーと乞食活動が大好きなエセAIエンジニアです！！
私は生まれてこの方英語弱者なのですが、仕事柄英語の論文を読む機会が増えてきたので困っており、会社の同僚にライフハックを教えて貰ったので、Qiitaの投稿の練習がてら書くことにしました。

##そもそもarXivって？

以下[Wikipedia](https://ja.wikipedia.org/wiki/ArXiv)より引用
>arXiv（アーカイヴ、archiveと同じ発音）は、物理学、数学、計算機科学、量的生物学、計量ファイナンス、統計学の、プレプリント（英語版）を含む様々な論文が保存・公開されているウェブサイトである。論文のアップロード（投稿）、ダウンロード（閲覧）ともに無料で、論文はPDF形式である。1991年にスタートして、プレプリント・サーバーの先駆けとなったウェブサイトである。大文字の X をギリシャ文字のカイ（Χ）にかけて archive と読ませている。

>現代（2012年）においてはこうした仕組みのサイトは特に珍しいものでもない[要出典]。しかし、arXivの設立当初（1990年代初頭）においては、学術出版社や大学図書館を介さずに研究者同士がインターネットを介して直接に論文をやりとりできる場として、学術出版関係者に大きな驚きをもって受けとめられた[2]。

>2015年8月現在106万報以上の論文が保存されている。毎月8,000報を超える論文が追加されている[3]。1991年、LANL preprint archiveという名称でロスアラモス国立研究所を運営元としてスタートし、1999年にarXiv.orgと改名。現在はコーネル大学図書館が運営元となっている。

だそうです。最近の論文（特に機械学習系）はほとんどこれに載っていると思います。気のせいかもしれませんが。

しかし、論文がPDFのため、Google翻訳に突っ込むのがめんどくさく、読むのをあきらめていたそこのあなた！今回ご紹介するのはとっておきの方法です！（テレビショッピング風に）

##arXiv Vanityを使ってLet's ライフハック！

全体の流れを説明すると、まず、[arXiv Vanity](https://www.arxiv-vanity.com/)という神サイトにarXivのPDFのURLをぶっこみます。するとPDFだったものがHTML化され、それをGoogle翻訳でページ翻訳すると、英語の論文が日本語で読めるという算段です。（詳しくは[こちらで](https://ideaatoz.com/arxiv-vanity/)）

###① arXivで論文を探す
![スクリーンショット 2019-09-12 10.48.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405328/1cda2e9a-e9a1-acc3-d2b4-3a3f29ac270d.png)

###② 右上のPDFボタンで論文を開く
![スクリーンショット 2019-09-12 10.49.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405328/58dd4f6e-82d9-b542-5684-a07998a7c4ef.png)

###③ URLをコピーする

###④ arXiv Vanityを開く
![スクリーンショット 2019-09-12 10.50.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405328/132e0927-328a-875e-1781-93f69baf0ba0.png)

###⑤ URLリンクを入れる
![スクリーンショット 2019-09-12 10.50.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405328/1a08b144-6124-bc50-b86f-bb0964a2e20d.png)

###⑥ Convert to web pageをクリック
![スクリーンショット 2019-09-12 10.50.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405328/0b1ad35a-ac63-8210-00dc-b35c77658f69.png)

###⑦ Google翻訳で日本語に
![スクリーンショット 2019-09-12 10.50.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405328/da61f0e8-fcd1-ecde-3334-040988de0c35.png)

###⑧ 論文を読んで圧倒的成長
![caricature-871836_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405328/7192d6f1-d24c-720f-a290-9e4cc8158201.jpeg)



流れはこんな感じです。Google ChromeだとWEBストアからページ右上部にGoogle翻訳ボタンを植え付けるとワンクリックで翻訳できるのでオススメです。

また、これを使えばスマホでも簡単に論文が翻訳しながら読めるので、まだ東京で消耗してる方々も、通勤・通学中に奴隷列車に揺られながら圧倒的成長できるのではないでしょうか。

##おわりに

今回はarXivの論文をarXiv Vanityを使って日本語訳を行いました。
ちなみに論文くらい英語で読めよっていう英語マウント取りマンの皆様の意見は現在受け付けておりません。
それにしてもGoogle翻訳ってすごいですよね。すごい能力を持ってるのに誰にでも平等だし、私もGoogle翻訳のような人間になれるように圧倒的成長したいと思います。



最後まで読んで下さった方に圧倒的感謝を！！！
git cloneする際にGithubのusernameとpasswardを入力したが失敗する

最近の勉強で学んだ事を、ノート代わりにまとめていきます。
主に自分の学習の流れを振り返りで残す形なので色々、省いてます。
Webエンジニアの諸先輩方からアドバイスやご指摘を頂けたらありがたいです！

#Githubのusernameとpasswardを入力したが失敗する
リモートリポジトリをgit cloneしようとした際にうまくできずに以下のエラーが発生しました。

```
$ git clone https://github.com/hoge/hoge.git
Cloning into 'hoge'...
Username for 'https://github.com': hoge
Password for 'https://hoge@github.com':
remote: Invalid username or password.
fatal: Authentication failed for 'https://github.com/hoge/hoge.git/'
```

GitHubへのアクセスを確認したところ

```
$ ssh -T git@github.com
Warning: Permanently added the RSA host key for IP address '52.74.223.119' to the list of known hosts.
git@github.com: Permission denied (publickey).
$ git remote -v
fatal: not a git repository (or any of the parent directories): .git
```

[Warning: Permanently added the RSA host key for IP address ‘52.74.223.119’ to the list of known hosts.
](http://www.xymiao.com/archives/953)この記事によると現在のgithubプロジェクトの問題部分にアクセスする権限がないのが原因と思われます。最初にpublickKeyを作成する必要があるみたいです。

一度、sshでgit cloneで行うと以下のような結果になりました。

```
$ git clone git@github.com:hoge/hoge.git
Cloning into 'hoge'...
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```

この問題のポイント
・対象のリモートリポジトリへのアクセス権限がなく失敗した。

解決策
・鍵認証周りを再設定し直す。
よって、解決までの流れは
１：鍵を作成する。
２：作成した鍵をコピーする。
３：gitghubに公開鍵を登録する。
４：configファイルを作成し直す。(接続確認）

こちらの記事を参考にし手順通り行うと問題なくgit cloneできました！

[【git エラー解決策】Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. が出た時の解決方法
](http://tusukuru.hatenablog.com/entry/2018/08/29/021651)
PlayCanvasのコードエディターでes6に対応する

### ※ 2023/03/23 追記 こちらは不要になりました。

PlayCanvasのコードエディターはデフォルトで`jshint`が入っているのですが、オンラインのエディターなので設定ファイルなどを簡単に変えることができませんなので対応をさせるためにコードエディターの１行目にインラインで

```
/*jshint esversion: 6, asi: true, laxbreak: true*/
```
と入れると`const`や`アローファンクション`などを使用してもエラーが出なくなります。

### そのままconstを使うと
![es6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257048/8d657ac0-9bb0-9fdb-e15e-8d6e9cf8a5a7.png)
warningが表示されてしまいます。

### コメントを追加する
```javascript

/*jshint esversion: 6, asi: true, laxbreak: true*/
```
インラインでこちらを１行目に追加をすることでes2015に対してのエラーが出なくなります。

![era.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257048/b61cba55-61d3-5b51-f930-3643032c8441.png)


<font color="OrangeRed">
PlayCanvas開発で参考になりそうな記事の一覧です。
</font>
<font color="OrangeRed">
入門

- [PlayCanvas入門- モデルの作成～ゲームに入れ込むまで](https://qiita.com/yushimatenjin/items/2a2c35fe7b1d08f9e361)
- [JavaScriptでスロットを実装する。【PlayCanvas】](https://qiita.com/yushimatenjin/items/e84c42da74df1eb07386)
- [3Dモデルのビューワーを3分で作る【初めてのPlayCanvas】](https://qiita.com/yushimatenjin/items/4b09c9e2076a0b2a6933)
</font>
<font color="OrangeRed">
応用
</font>

- [PlayCanvasのコードエディターでes6に対応する](https://qiita.com/yushimatenjin/items/a61a21c64c1c1a550dd4)
- [Gulpのプラグインを書いたらPlayCanvasでの開発がめちゃくちゃ便利になった](https://qiita.com/yushimatenjin/items/5f0f178e8a4ba4a5ee57)
- [PlayCanvas Editorに外部スクリプトを読み込む新機能が追加されたので開発方法を考える。- Reduxを組み込む](https://qiita.com/yushimatenjin/items/7a64220cceac66843d7d)
</font>
<font color="OrangeRed">
その他の記事はこちらになります。

- [React Native + PlayCanvasを使ってスマートフォンゲームを爆速で生み出す](https://qiita.com/yushimatenjin/items/7c7ad5d35473c11f32f2)
- [PlayCanvasのエディター上でHTML, CSSを組み込む方法](https://qiita.com/yushimatenjin/items/814b4a32db53397219df)
- [【iOS13】新しくなったWebVRの使い方 ](https://qiita.com/yushimatenjin/items/344d86b3d193e0a88567)
</font>

<font color="OrangeRed">
その他関連
- [PlayCanvasタグの付いた記事一覧](https://qiita.com/tags/playcanvas)
</font>


### PlayCanvasのユーザー会のSlackを作りました！
少しでも興味がありましたら、ユーザー同士で解決・PlayCanvasを推進するためのSlackを作りましたので、もしよろしければご参加ください！

[日本PlayCanvasユーザー会 - Slack](https://t.co/IdSRIfJhN5?amp=1)
ロックされているファイル・フォルダの解除

# 操作対象は操作不能になった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188794/2052b2ee-6672-87e4-0971-cbebe20adb4a.png)

共有ファイルや共有フォルダで発生しやすいですが、時々、操作できない場合があります。
（他のメッセージを見たこともあります）

# ファイルやフォルダとの接続を検索
下記のコマンドをPowerShell（管理者権限）で実行すれば、開いてファイルの検索結果をCSVフォーマットで表示できます。

```powershell
#すべての接続を表示。他のコマンドとの組み合わせは可能
openfiles /query /fo CSV
```

## 実行例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188794/b22228c3-f055-32ff-b670-00d0721682e8.png)

# 接続を切断
検索結果のIDを用いて、下記コマンドを実行すれば、該当ファイルに対する、他の接続を切断することは可能で、自分の操作はできるようになります。

```powershell
#番号を指定して接続を切断
openfiles /disconnect /id [ID番号]
```

## 実行例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188794/e037dd15-0b1c-92cc-8f62-1134bda7a775.png)


# 参考
https://docs.microsoft.com/ja-jp/windows-server/administration/windows-commands/openfiles
SAP Portalのコンテンツ管理について

# はじめに
![cockpit1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486466/795f0ce6-d55e-8afc-ae67-aa103065676a.png)
SAP Portalのサイトのコックピッドにあるコンテンツ管理について、ざっくりまとめてみました。

# 各メニューについて
- カタログ：アプリを機能単位でまとめる
- グループ：アプリを見た目上の単位でまとめる
- ロール：利用可能なカタログとグループを紐付け、ここのロールをユーザとも紐付ける

# どう反映されるのか
ユーザはサイトにアクセスした際、自分のロールに登録されたカタログとグループの両方にあるアプリのみを閲覧することができます。
以下で図を元に説明します。

![cockpit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486466/d63bd826-0ce1-099e-3849-0f0d9f7ec559.png)

- アプリは全体で「アプリ1」から「アプリ8」まであります。

- **「ロールA」に、「カタログ1」と「グループ1」「グループ2」を紐付けた場合**
→「ロールA」のユーザは「アプリ1」「アプリ2」「アプリ5」「アプリ6」のみが表示されます

- **「ロールB」に、「カタログ2」と「グループ1」「グループ2」を紐付けた場合**
→「ロールB」のユーザは「アプリ3」「アプリ4」「アプリ7」「アプリ8」のみが表示されます

※アプリは詰めて表示されます。

# 最後に
今回はSAP Portalのコンテンツ管理の概要を紹介をさせていただきました。
具体的な手順についてはまた記載したいと思います。
2019夏・認証・認可ソリューションまとめ


昨今認証認可のニーズが高まってきている感じがします。

# 先に結論

これはあくまでも私の見解なので、参考としてご覧ください。
もしこれから比較される方おられれば、最新の一次情報を参照した上での判断が絶対に必要になります。

- スケジュール優先<br>
Auth0
- 機能優先<br>
Auth0<br>
authlete(+keycloak)
- コスト優先（短期<br>
cognito or authlete(+keycloak)
- コスト優先（長期<br>
congito or authlete(+keycloak)

#### 補足
※OpenAMに関してはOSSとして使いにくい状況なので選択肢から外しています。
※コストに関してはユーザ数次第なので、実際はケースバイケースかと思います。

# プロダクト比較


||cognito|auth0|keycloak|authlete|
|---|---|---|---|---|
|認証・認可方式|Oauth2.0<br>Open ID Connect|Oauth2.0<br>Open ID Connect|SAML2.0<br>Oauth2.0<br>Open ID Connect|Oauth2.0<br>Open ID Connect<br>※認可に特化|
|外部Idp認証連携<br>※line/google/yahooなど|〇|〇|〇|-|
|エンタープライズ認証連携<br>※AD/LDAP/SAMLなど|〇|〇|〇|-|
|実装コスト<br>サンプル・ドキュメントから判断|△|〇|△|〇|
|SLA|99.90%|99.90%|インフラ依存|?|
|スケーラビリティ|10tps<br>(認証)|100tps<br>(認証/エンタープライズの場合)|インフラ依存|?|
|機能|〇|◎|◎|〇|
|イニシャルコスト|やすい|？|OSS|？|

# プロダクト所感

* cognito
外部IDPとはOpen ID Connect話せるが、自身がOIDCのIDPになるには独自にいろいろ作りこみが必要
Implicit Flowはなんとか標準機能で作れるか？

* auth0
実装は一番楽だと思う
ただし、ユーザの属性情報に住所氏名とか追加しようとすると難しくなる

* authlete
OIDC準拠といった部分では随一
標準に完全に乗る場合はほぼ唯一の選択肢か？

* keycloak
OSSなので、自由にできるのがメリット
機能も豊富

# 実装例

* cognito
https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-user-identity-pools.html
※cognitoの説明だけはどうしてもわかりにくい・・・

* auth0
https://github.com/auth0-samples

* authlete
https://github.com/authlete

* keycloak
https://github.com/keycloak/keycloak/tree/master/examples

# 参考

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/limits.html
https://auth0.com/docs/policies/rate-limits
【初学者・初心者】そこの新人エンジニア！テストExcelを保存する前に一回見て！！

##読む前に
お願いします。
これを読み終えたらコメントに自分が気を付けていることを書き込んで下さい。
随時、私が読み必要ならばこの記事に加えていきたいと思います
。

#全体
1. 見る人が開いたときにセルを大きくしないでも、初見で内容が見えるようにしましょう。
2. セル選択はA1に設定して閉じる
3. 拡大・縮小のパーセントは100パーセントで合わせる


# 表について
##タイトル
タイトルは中央揃えにしましょう。一般的にタイトルは中央揃えで記載し、2行目以降のデータ行と区別するために、セルに色を塗るなど差別化しましょう。

##文字
文字列は一般的に文字は左詰めで記載します。
統一されていればいいとは思います。
デフォルトで文字は左詰めになっています。
追記する人は毎回統一させようとするのは面倒なのでデフォルトのままというのが一番でしょう

##数値
一般的に数値は右詰めで記載します。

たまに、タイトルも文字も数値も全て右寄せ、左寄せ、中央揃えで統一している表があります。統一すればいいというものではありませんので、それぞれを適切に設定しましょう。

##重要な値
表の中で強調したい値がある場合は強調しましょう。

##デザイン
資料で利用されているメインカラーに、表の色も合わせましょう。
表を選択して「デザイン」＞「表のスタイル」で、塗りつぶしや線、文字の色などを簡単に変更することができます。

このように、表を作成する上で、一般的なルールというものがあります。そのルールを守ることで見やすく、わかりやすい表となります。アナタもぜひルールを守って、見やすくわかりやすい表を作成しましょうね。


##最後に
細かいことかもしれませんが、きちんと考えられて作成しているものであれば文句をいわれることを言われて困ることないでしょう
Laravel Validation前にデータを加工する

# laravelのvalidation前にrequestデータを加工したい 
Laravelでvalidation前にデータを加工したい状況が生まれた。

今回アプリケーションは以下のように
フォーム1で入力した内容をフォーム2の`hidden field`に持たせて
フォーム2を`submit`した際に両方のフォームの内容をDBに保存する。

### 【validation前にデータを加工しないといけないケース】
* フォーム1は普通にvalidation
* フォーム2でエラーになったらform1の内容を復元してvalidationする
* ありがとうございましたページ

フォーム1のvalidationは普通に作成すれば良い


## 結論：FormRequestの prepareForValidation メソッドを使う。
prepareForValidation を利用することでvalidation前に request の値を変更することができる。
初めは middleware を使って実装していたが、こちらの方が圧倒的にシンプルに書くことができる。

HogePostと記載してある部分とvalidationルール部分を変更すればこのコードはそのまま使えるだろう。

```php5
<?php
namespace App\Http\Requests;
use Illuminate\Validation\Rule;
use Illuminate\Foundation\Http\FormRequest;
class HogePost extends FormRequest {
  // prepareForValidation は validation 処理の前に実行される
  protected function prepareForValidation() {
    if ($this->session()->has('errors')) {
      //$this->old()で1つ前のform入力値を取得できるので、今回の入力値に過去の入力値をマージ
      $this->merge($this->old()); 
    }
  }
  public function rules() {
    return [
      'name'        => 'required|string',
      'age'         => 'required|integer',
      'sex'         => 'required|integer',
    ];
  }
}
```


公式ドキュメントはこちら
https://laravel.com/api/5.6/Illuminate/Validation/ValidatesWhenResolvedTrait.html
What happen of a class annotated with @Transactional

# Proxy class is created when class is annotated with @Transactional

In my [notice board example application](https://github.com/saladlam/spring-noticeboard), class *info.saladlam.example.spring.noticeboard.service.MessageServiceImpl* is annotated with **@Transactional**. When bean factory processes this class, proxy instance of this class, with *org.springframework.transaction.interceptor.TransactionInterceptor* set is created. You may view the actual instance of *MessageService* from Eclipse's debugger.

![eclipse_debug_messageservice.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232557/41d37173-b92c-8387-94e2-a84ce2808c34.png)

# Function of TransactionInterceptor

1. Send begin transaction and commit signal to PlatformTransactionManager instance
2. Handling exception case

Below is code from method *org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(Method, Class<?>, InvocationCallback)*.

```java
// ...
		// If the transaction attribute is null, the method is non-transactional.
		TransactionAttributeSource tas = getTransactionAttributeSource();
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		final org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(Method, Class<?>, InvocationCallback) tm = determineTransactionManager(txAttr);
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

		if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

			Object retVal;
			try {
				// This is an around advice: Invoke the next interceptor in the chain.
				// This will normally result in a target object being invoked.
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// target invocation exception
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				cleanupTransactionInfo(txInfo);
			}
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}
// ...
```

When program executes to

```java
retVal = invocation.proceedWithInvocation();
```

method of *info.saladlam.example.spring.noticeboard.service.MessageServiceImpl* is called.

# Function of PlatformTransactionManager

In Spring Framework context there is a singleton *PlatformTransactionManager* instance. In this application, the implementation is *org.springframework.jdbc.datasource.DataSourceTransactionManager*. This class is for handle all transaction action happened.
「amplify publish」をした後、ブラウザに更新が反映されない時にCloudFrontでやること

#はじめに
「amplify publish」で、S3のホスティングバケットを更新したのに、ブラウザで確認するとその変更が反映されていない時がありました。
その時やって解消したことを、今後も忘れないように記録します。

#前提
s3に置いたコンテンツをcloudfrontで配信する構成にしていること。

#原因
cloudfrontで保持している過去のキャッシュが残っていることが原因でした。

#やること
cloudfrontのコンソール画面を開き、対象のIDをクリック。
![IMG_6318.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458187/3a68e1de-4d6b-1cb0-256e-c88a2d09ae03.jpeg)


Invalidationsタブをクリック
![IMG_6319.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458187/351c93fe-b424-1731-60ae-cac8d49af33e.jpeg)

Create Invalidationをクリック
![スクリーンショット 2019-09-12 7.01.51 2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458187/5a791795-b0bf-cef4-6e07-c1ae0e8c36d7.jpeg)


Object Pathsに「*」と入力し、Invalidateをクリック
![IMG_6320.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458187/c7492798-4c44-014b-d5ba-66bd2b81ea85.jpeg)

Statusが「Completed」になれば完了です。

#おわりに
問題の切り分け方法とかは特にチェックしていないので、局所的な問題解決かもしれませんが、何か気づきがあればアップデートしていきます。
これからの Fragment#onBackPressed(Backボタンイベント)

#　これからの Fragment#onBackPressed
これからのとは言いますが(2019/09/12)現在のものです。アップデートが入るかもしれませんので...

## 初めに
ここで紹介するのはFragmentにおける戻るボタンイベントのベストプラクティスです。

## 環境
| software / library |       version |
|:-------------------|--------------:|
| AndroidStudio      |           3.5 |
| Kotlin             |        1.3.50 |
| androidx.appcompat | [1.1.0](https://developer.android.com/jetpack/androidx/releases/appcompat#1.1.0) |
| androidx.activity  | [1.1.0](https://developer.android.com/jetpack/androidx/releases/activity#1.1.0-alpha03) |
| androidx.fragment  | [1.2.0-alpha03](https://developer.android.com/jetpack/androidx/releases/fragment#1.2.0-alpha03) |

## 実践
`androidx.appcompat.app.AppCompatActivity`と`androidx.fragment.app.Fragment`使ってください。

```kotlin:FirstFragment.kt
class FirsFragment: Fragment() {
  override fun onAttach(context: Context) {
    super.onAttach(context)
    requireActivity().onBackPressedDispatcher.addCallback(owner = this, enabled = true) {
      // 何か処理
    }
 }
}
```

### 解説
簡単に解説すると、`Activity`の`BackPressedDispatcher`に`OnBackPressedCallback`を追加します。
引数の`owner`はFragmentのLifecyleを監視して自動で開放するためのものです。
`enabled`は戻るボタンを押したときに他に伝播するかしないかです。

コールバック内で伝播するかしないかを決めたけば、`isEnabled`を使用すると良いです。

例えば、`ViewPagerで最初のページの時だけ今のFragmentを終了する`であれば、

```kotlin:FirstFragment.kt#addCallback
addCallback(this) {
  // viewModel.isFirstPageでViewPagerが最初のペーかどうか判定する帰り値はBoolean
  isEnabled = viewModel.isFirstPage
}
```

です。
ちなみに、引数`enabled`はデフォで`true`なので、省略できます。

## おわり
前までの`Fragment`にリスナーを実装して`Activivy`から呼び出すとか、
`View`に`OnKeyListener`をセットしてゴニョゴニョするめんどい実装がなくなっていい感じになりました。
Rails6 のちょい足しな新機能を試す78（Guard DNS rebiding attacks編）

# はじめに

Rails 6 に追加された新機能を試す第77段。 今回は、 `Guard DNS rebiding attacks` 編です。
Rails 6 では、 `Rails.application.config.hosts=` でアクセスを許可するサーバーを指定できるようになりました。
development 環境では、すべてのIPアドレス表記（`0.0.0.0/0`(IPv4) `::/0`(IPv6)) のサーバーと `localhost` のみがデフォルトで許可されています。
それ以外の環境では、デフォルトでは制限がありません。

Ruby 2.6.3, Rails 6.0.0, Rails 5.2.3 で確認しました。

```shell
$ rails --version
Rails 6.0.0
```

今回は、 [ngrok](https://dashboard.ngrok.com/signup) を使ってこの確認をしてみましょう。

# プロジェクトを作る

```shell
$ bin/rails new rails_sandbox
$ cd rails_sandbox
```

## rails server を起動する

```shell
$ bin/rails s
```

# ngrok を起動する

```shell
$ ngrok http 3000
```

# ngrok で表示された URL でアクセスする

https://xxxxxxxx.ngrok.io にアクセスしてみます。

ブラウザには、以下のようにブロックされたことが表示されます。

> blocked host: xxxxxxxx.ngrok.io
> To allow requests to xxxxxxxx.ngrok.io, add the following to your environment configuration:
> config.hosts << "xxxxxxxx.ngrok.io"


# config/environments/development.rb を編集する

ngrok を使ったアクセスを許可するように設定を変更します。
ngrok のサーバーは,起動するたびに毎回変わりますので、どれでも許可できるように `.ngrok.io` を追加します。

```ruby:config/environments/development.rb
Rails.application.configure do
  ...
  config.hosts << '.ngrok.io'
end
```

# 再起動してから試す

`rails server` と `ngrok` を再起動して試すと、今度は普通にアクセスできるようになります。

# Rails 5 では

Rails 5.2.3 ではブロックされることはありません。

# 試したソース

試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try078_guard_dns_rebiding_attack


# 参考情報

* [What is new in Rails 6.0](https://bogdanvlviv.com/posts/ruby/rails/what-is-new-in-rails-6_0.html)
* [Guard against DNS rebinding attacks by permitting hosts](https://github.com/rails/rails/pull/33145)
ソートアルゴリズム

#はじめに
ソートとは？とよく使われるソートの挙動を書いていこうと思います

#ソートとは？
入力として与えられた数字を小さい順に並べること
日本語では「整列」

```example.
numbers = [3,5,7,6,39,1]
ソートすると
numbers = [1,3,5,6,7,39]
```

##バブルソート
数列の中を右から左に向かって隣合う２つの数字を比較し、右の値のほうが小さければ入れ替える。

 ```example.
numbers = [4,8,2,6]

1:2と6を比較、6のほうが大きいから変更なしで次の比較に進む
2:8と2を比較、2ほうが小さいから入れ替える
numbers = [4,2,8,6]
3:４と2を比較、2のほうが小さいから入れ替える
numbers = [2,4,8,6]
左端まで進めば第一ラウンドが終了し、次のラウンドに進む
```
この操作を繰り返すことで最終的にはソートされた数列が還る

入力データが小さい順に並んでいれば入れ替えは一回も発生せず、逆に入力データが大きい順に並んでいれば毎回比較後に入れ替えをすることになる

##選択ソート
数列の中から最小値を検索し、左端の数字と入れ替える

```example.
numbers = [4,8,2,6]

1:数列を線形探索し、最小値2を左端の4と交換する（第一ラウンド）
numbers = [2,8,4,6]
2:残る数列を再び線形探索し、最小値4と左端の8を交換する(第二ラウンド)
numbers = [2,4,6,8]
```
この操作を繰り返すことで最終的にはソートされた数列が還る

数字の入れ替えは各ラウンドで一回となる

##挿入ソート
数列の左側から順番にソートしていく
右側の未探索領域から数字を一つとってきてソート済みの領域の適正な場所に挿入する

```example.
numbers = [4,8,2,6]

1:左端の4をソート済みにする
2:未探索領域の左端である8を取り出し、ソート済みの4と比較する
3:8>4だから４の右に配置する
numbers = [4,8,2,6]
4:次に比較する2は8>4>2だから2を左端に配置する
numbers = [2,4,8,6]
```
この操作を繰り返すことで最終的にはソートされた数列が還る

入力データが大きい順に並んでいる場合は比較数が多くなってしまう

##ヒープソート
データ構造のヒープを利用することが特徴

![heap.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365406/be9db63a-47b2-89f4-e21d-a2c9d5e26bc5.gif)

[参照サイト](http://www.cc.kyoto-su.ac.jp/~mtkg/lecture/comp_B/2012/heapsort.html)

```
1:入力された数列を降順になるようヒープとして構築する
２：値の大きい順に取り出してソートする
3:ヒープを再構築する
 ```
この操作を繰り返すことで最終的にはソートされた数列が還る

バブルソート・選択ソート・挿入ソートに比べて高速だが、ヒープという複雑なデータ構造を利用するため実装が複雑になる

##マージソート
数列をほぼ同じ長さの2つの数列に分割していき、これ以上分割できなくなったところからグループ同士をマージしていく

![merge-sort-image.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365406/a17101d6-bd2a-cc55-8c54-2df2c375b287.gif)

[参考サイト](http://www.ics.kagoshima-u.ac.jp/~fuchida/edu/algorithm/sort-algorithm/merge-sort.html)

図の通り各グループの数が1つになれば、隣りあう数をソートしながらマージしていく
この操作を繰り返すことで最終的にはソートされた数列が還る

マージソートにおいて数字を分割していく部分に計算時間はかからない
２つのソート済み数列をマージする部分は先頭の数を比較して小さい方を配置していくような処理

##クイックソート
基準となる数（ピボット）を数列の中からランダムに一つ選び、ピボット以外の数を「ピボットより小さい数」と「ピボット以上の数」の２つのグループに分ける

```example.
numbers = [4,8,2,6,5,1]
1:ピボットを6とする
2:左端の4は4<6なので左側に配置する
3:8は8>6なので右側に配置する
4:繰り返すと「6より少ない数」、「6以上の数」に二分される
numbers = [[4,2,5,1],6,[8]]
5:グループ化した数列を1~4の操作にようにソートする
```

<img width="512" alt="20180420011652.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365406/ae5fa389-2562-622a-6718-2d9024d2bef9.png">
[参考サイト](https://to-bb.hatenablog.com/entry/2018/04/20/080000)
この操作を繰り返すことで最終的にはソートされた数列が還る

元の数列を二つの子問題（ピボットより小さい数、ピボット以上の数）に分割し、その子問題にもピボットを設定してソートしていく
このようにアルゴリズムの内部にそのアルゴリズム自身を使うことを「再帰」という

#参考図書
[アルゴリズム図鑑](https://www.amazon.co.jp/%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E5%9B%B3%E9%91%91-%E7%B5%B5%E3%81%A7%E8%A6%8B%E3%81%A6%E3%82%8F%E3%81%8B%E3%82%8B26%E3%81%AE%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0-%E7%9F%B3%E7%94%B0%E4%BF%9D%E8%BC%9D-ebook/dp/B07179Q3MJ)
(GHC 8.0.1以降では単にerrorを使えばすむ話でした)Haskellで「ソースコード上での位置」を取得する

Haskellで「ソースコード上での位置」を取得する
========================================

はじめにお読みください
--------------------

「エラーメッセージを表示するときに、ソースコード上での位置も出力できたら、かっこいいよね」という話でしたが、GHC 8.0.1からは、単にerror "foo"とするだけで、出力できるようです。GHC 8.0.1以降のGHCは「かっこいいよね」ということで、この話はおわりです。

TemplateHaskellの使用例として書いてみたのですが、「より良い方法がある」というか「そもそも必要ない」ということを、コメントいただきました。「限定共有」にしようかと思ったのですが、「一度公開した記事は限定公開にはできない」ということでした。削除しようかとも思ったのですが、いただいたコメントの内容が「有益」なものなので、迷っているところです。

以降の話は「とりあえずは、とっておいてある記事」とお考えください。

はじめに
-------

ちょっとしたチップス。「エラーメッセージを表示するときに、ソースコード上での位置も出力できたら、かっこいいよね」という話です。

エラーメッセージを表示するときに「ソースコード上での位置」を出力したいことがある。モジュール名とファイルの何行目の何文字目かを表示できれば、便利だ。

言語拡張TemplateHaskellを使えば、かんたんにできる。

ソースコード
----------

ソースコードは下記に置いてあります。

[try-get-position-th](https://github.com/YoshikuniJujo/test_haskell/tree/master/tribial/qiita/try-get-position-th)

問題提起
-------

つぎのような例を考える。

```hs:Foo.hs
module Foo where

foo :: [String] -> IO ()
foo [] = error "foo: The argument should not be empty."
foo strs = putStrLn `mapM_` strs
```

「Data.List.NonEmpty.NonEmptyを使えばいい」とか、「部分関数を定義するのは、いかがなものか」などの意見もあるかもしれないけれど、そういった話は置いておくことにする。これを呼び出す。

```hs:Main.hs
module Main where

import Foo

main :: IO ()
main = foo []
```

コンパイル・実行するとつぎのようになる。

```
try-get-position-th-exe: foo: The argument should not be empty.
CallStack (from HasCallStack):
  error, ...
```

たとえば、(「そんなコードを書くな」という話かもしれないが)モジュールFooが数千行あって、fooの定義がつぎのようになっていたとする。

```
foo :: Bar -> Baz -> ...
foo ... = error ...
foo ... = error ...
.
.
.
foo ... = error ...
.
.
.
```

「どの行のエラーを見ればいいの?」となる。そんなとき、エラーメッセージに「ソースコード上での位置」が表示されていると親切だ。

ソースコード上での位置を出力すればいい
---------------------------------

こんなとき、エラーメッセージに「かんたんに」ソースコード上での位置を表示できる。言語拡張TemplateHaskellを使う。

パッケージtemplate-haskellを使用するので、Stackを使っているなら、packate.yamlにつぎのように追加する。

```package.yaml
dependencies:
- base >= 4.7 && < 5
- template-haskell
- ...
```

Foo.hsをつぎのように書きかえる。

```Foo.hs
{-# LANGUAGE TemplateHaskell #-}

module Foo where

import Language.Haskell.TH

foo :: [String] -> IO ()
foo [] = error $
        "\n" ++ $(litE =<< stringL . pprint <$> location) ++
        "\nfoo: The argument should not be empty."
foo strs = putStrLn `mapM_` strs
```

言語拡張を使用することをコンパイルにつたえる。ここではプラグマを使用する。先頭の`{-# LANGUAGE TemplateHaskell #-}`だ。モジュールLanguage.Haskell.THを導入する(`import Language.Haskell.TH`)。`$(litE =<< stringL . pprint <$> location)`が「ソースコード上での位置」を取得している部分だ。

Main.hsはそのままでいい。コンパイル・実行すると、つぎのようになる。

```
try-get-position-th-exe:
try-get-position-th-0.1.0.0-...:Foo:(10,19)-(10,57)
foo: The argument should not be empty.
CallStack (from HasCallStack):
  error, called at ...
```

「モジュールFooの10行19文字目から10行57文字目まで」を見れば、エラーがどこで起きているかがわかる。

位置を取得している部分の説明
-------------------------

TemplateHaskellではIOモナドと似ているQモナドというものが使われている。位置を取得している部分をdo記法で書くと、つぎのようになる。

```hs
getPos = do
        loc <- location
        sl <- stringL (pprint loc)
        litE sl
```

locationで位置を表すデータ構造を取り出し、それをpprintによって「人間が読みやすい文字列」に変換。stringLで「文字列リテラル」に変換してから、litEで、その文字列リテラルを「値」に変換している。

まとめ
-----

「エラーメッセージを出力するとき、ソースコード上での位置も表示できたら、かっこいいよね」という話。ちょっとしたチップスですが、「言語拡張TemplateHaskellで、こんなこともできるよ」という話でもあり、興味を持っていただけるきっかけになれば、と。
AWS LambdaでPythonの実行を自動化しよう

## AWS Lambdaとは

AWS(Amazon Web Service)が提供しているクラウドコンピューティングサービスのことです。<br>
ある条件で発火して任意のコードを立ち上げるだけなのでサーバーコストがかからず手軽にコードを自動化することができめちゃくちゃ便利です。<br>

<br>

## AWS LambdaでPythonコードを自動化

それでは試しにAWS LambdaでPythonを立ち上げてみましょう。

<br>

### 1. functionを生成する

#### i. [AWS Lambdaホーム画面](https://us-east-2.console.aws.amazon.com/lambda/home)からCreate Functionを選択

![Screen Shot 2019-09-12 at 11.04.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243995/2ef4622d-26fa-87b1-0a45-e3a2c2cfb912.png)


<br>

#### ii. Auther from ScratchからPythonを選択してfunctionを生成

![Screen Shot 2019-09-12 at 11.08.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243995/f972a987-7402-1830-8cd6-45225d9af9ce.png)


<br>

### 2. 外部モジュールをアップロードする

Pythonの外部モジュールをimportするにはモジュールのzipファイルをアップロードする必要があります。

#### i. 任意のディレクトリでモジュールをインストール

以下のコードでカレントディレクトリにモジュールをインストールすることができます

```
$ pip install <module> -t .
```

<br>

#### ii. インストールしたモジュールをzip化

以下のコードですべてのファイルを`upload.zip`という一つのファイルに閉じ込めることができます

```
zip -r upload.zip *
```

<br>

#### iii. zipをアップロード

Function CodeからCode entry typeで`upload a zip file`を選択しzip化したファイルをアップロードします
*ファイルサイズが大きい場合、functionを複数に切り分けるなどをおこなわないといけません

![Screen Shot 2019-09-12 at 11.20.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243995/c24bedd6-f839-7179-efda-2fe11ba4e898.png)

<br>

### 3. 関数を記述する

`lambda_function.lambda_handler`にHandlerをセットしているので、lambda_function.pyというファイルを生成し、lambda_handler()関数を書き、実行させたい処理をその関数内に記述します。完了したらsaveしてください。


![Screen Shot 2019-09-12 at 11.53.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243995/6732d2ee-a50d-8514-3ea2-bd1e1daf8723.png)

<br>

### 4. タイムトリガーをセットする

毎時実行したいので、「Add Trigger」から「CloudWatch Events」を選択してスケジューリングします
`cron()`や`rate()`の書き方は[こちら](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/tutorial-scheduled-events-schedule-expressions.html)。

![Screen Shot 2019-09-12 at 11.54.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243995/0572e92a-48b7-9115-bc45-1769037d33fb.png)


<br>

これで完了です。Triggerに他のAWS Lambda FunctionやEC2, S3などを設定することによって他のクラウドのアクションを発火条件に設定することもできます。

## 最後に

kerasやscikit-learnのモジュールの容量がバカみたいに大きいので、AWS Lambdaだけで機械学習モデルを回すのは無理そうです。
やはりSageMakerと繋ぐのがベストプラクティスな気がする。
Vuetifyでprepend-inner-iconで指定したFont Awesomeのアイコンだけ小さくしたい

Vuetifyでv-text-fieldにprepend-inner-iconを設定すると、material designのアイコンだとちょうどいいのにFont Awesomeだとバカでかいアイコンになってしまう現象がある。

標準がコレ

![2019-09-12 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44464/3ad90bdd-2d86-3ce7-0e81-f667fb01c895.png)

特に両者を併用したい場合などは目立ちすぎて仕方がない。
Font Awesomeのみ小さくしてみよう。

```html
<style>
.v-input__icon--prepend-inner .fas {
  font-size:18px;
}
</style>
```

これでだいたい同じくらいの大きさになる。

![2019-09-12 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44464/7bb5f9e3-eb75-9c73-5855-ccd5e6685072.png)
【React+TypeScript】Unstatedで管理する状態の個数を動的に変えたい

## Unstatedとは
Reactではglobalなstateを管理するためにContext APIが用意されています。
Unstatedはそれをラップして使いやすくしてくれたものです。
UnstatedやContext APIに関する説明は下記のエントリをご覧ください。

https://qiita.com/kaba/items/50126e874b24ff984471
https://qiita.com/kaba/items/b05f680f850dd46548f3

## 環境
- Windows10
- Node.js(v10.14.1)

## サンプル
### 作るもの
カウンターボタンを複数個画面に設置したサンプルアプリで説明します。
`create-react-app`で初期化してあります。

### Unstatedインストール

```
npm install unstated
```

### Containerクラス作成
状態管理するUnstatedの`Container`クラスを継承して`CounterContainer`を作成します。
カウンターの初期値をコンストラクタで指定できるようにしておきました。

```typescript:CounterContainer.ts
import { Container } from "unstated";

interface CounterState {
  count: number,
}

export class CounterContainer extends Container<CounterState> {
  constructor(initialvalue: number) {
    super();
    
    this.state = {
      count: initialvalue,
    }
  }

  increment() {
    this.setState({ count: this.state.count + 1 });
  }

  decrement() {
    this.setState({ count: this.state.count - 1 });
  }
}
```

### 状態変化するコンポーネント側作成
今回はただのnumber配列`numbers`からカウンターを生成しますが、実際にはDBやAPIから取得された配列になると思います。

```tsx:Counters.tsx
import React from "react";
import { Subscribe } from "unstated";
import { CounterContainer } from "./CounterContainer";
import './Counter.css'; // marginで配置の調整をしているだけなので省略

export function Counters() {
  const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
  const containers = numbers.map(num => new CounterContainer(num));

  return (
    <Subscribe to={containers}>
      {(...counters: CounterContainer[]) => (
        <div>
          {counters.map((counter, index) => (
            <div key={index} className="counter">
              <button onClick={() => counter.decrement()}>-</button>
              <span> {counter.state.count} </span>
              <button onClick={() => counter.increment()}>+</button>
            </div>
          ))}
        </div>
      )}
    </Subscribe>
  );
}
```

`Subscribe`の`to`プロパティには`Container`のリストを渡してあげます。
`Subscribe`の`children`にはCounterContainerクラスの可変長引数を受け取り`ReactNode`を返却するような関数を記述します。

### コンポーネントを利用する

`Subscribe`で括ったコンポーネントはさらに`Provider`で括られる必要があります。
`Provider`で括ってレンダリングして完成です。

```tsx:index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { Provider } from 'unstated';
import { Counters } from './Counter';

const App: React.FC = () => {
  return (
    <Provider>
      <Counters />
    </Provider>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));

```

### 動かしてみる

![sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299625/91a8563d-7253-f398-71a0-f50dd08827a8.gif)

ちゃんと初期値が連番になっており、各状態が独立しているのがわかります。

## 最後に

TypeScriptを使っていることもあって`Subscribe`のプロパティに与える型に苦戦したのでこのエントリを書くに至りました。
分かっている人にはできて当然なのかもしれませんが、だれかの足掛かりになればと思います。
GoogleAppScriptでDriveに保存されている画像をSlackに送信

GASを使って SlackのBotを開発しているときに、ふとインターネットに公開されていない 画像付の投稿をしたくなるときがあるのでメモ

<h2>Bot版</h2>
前提
`token発行済`

要件
`GoogleDriveに保存されている画像を投稿する（インターネットに公開されていなくてOK）`

file.uploadを使う
https://api.slack.com/methods/files.upload

```javascript
var file = DriveApp.getFileById('GoogleDriveのファイルID');
var options = {
    "payload": {
      token: "slack access token.",
      as_user: true,
      file: file.getBlob(),
      filename: file.getName(),
      channels: channel,
  }
}
var result = UrlFetchApp.fetch("https://slack.com/api/files.upload", options);
```
ojichatをAPI化しました

# ojichat-apiを開発しました

https://ojichat-api.tokyo

## ojichatとは

https://github.com/greymd/ojichat

>おじさんがLINEやメールで送ってきそうな文を生成するコマンド。

Go製のcliなんですが、かなり話題になりました。

https://togetter.com/li/1387648

しかしこのojichatはcliなので欲しい時すぐ使えなかったりします。

そこでAPI化しました。

## ojichat-apiの実装

リポジトリはこちらになります。

https://github.com/konojunya/ojichat-api

今回はginというフレームワークを使いました。

https://github.com/gin-gonic/gin

めんどくさい処理は書きたくないので使い慣れてるものを採用しただけです。

今回は単純にquery stringをパースして

```golang
targetName := c.DefaultQuery("name", "")
emojiNumStr := c.DefaultQuery("e", "4")
punctuationLabelStr := c.DefaultQuery("p", "0")
```

それから `ojichat/generator.Config` を作成します。

```golang
config := generator.Config{
  TargetName:        targetName,
  EmojiNum:          emojiNum,
  PunctiuationLebel: punctuationLabel,
}
```

この  `config` を `ojichat/generator.Start` へ渡すだけでおじさん風のテキストを作成してくれます。

## インフラ

ojichat-apiは https://ojichat-api.tokyo へホストしています。このサーバーは最近Google Cloud PlatformからでたCloud Runというdockerのコンテナをサーバーレスで動かしてくれるものに載せています。

https://cloud.google.com/run/?hl=ja

Cloud Runが色んな記事でも使い方が載せられていますが、結構簡単にデプロイまで出来るので趣味程度のAPIを開発するのであればかなりよいなと思いました。

料金もリクエスト数以外にサーバーのリソースによってかかりますが、ojichat-apiみたいな軽いものだと結構リクエストがきてもお小遣い程度で運用できそうです。

デプロイの方法などはその他の記事をご覧ください。

[Cloud Runを最速で触ってみる](https://medium.com/google-cloud-jp/cloud-run-を最速で触ってみる-6e42021307d4)

[GCP版のFargate?Cloud Runを触ってみた](https://qiita.com/EastResident/items/28d98abfba00a973e5e1)

[Cloud Runで動かすGo + Echo Framework](https://qiita.com/nkumag/items/90a24c87330bfb503e29)

デプロイ自体をCDなどは行なっていませんがmakefileにまとめてあるのでみてみるとよいです。

https://github.com/konojunya/ojichat-api/blob/master/Makefile

## Author

Twitter: [@konojunya](https://twitter.com/konojunya)
GitHub: [konojunya](https://github.com/konojunya)
iotopコマンドまとめ

#できること
プロセス毎のI/O情報をtopコマンドのように監視できる

#実行結果
実行にはroot権限が必要

```
# iotop 

Total DISK READ :      50.92 M/s | Total DISK WRITE :       0.00 B/s
Actual DISK READ:      50.92 M/s | Actual DISK WRITE:      15.17 M/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
 3559 be/4 root       22.89 M/s    0.00 B/s  0.00 % 12.63 % python /sbin/iotop
 3179 be/4 root        2.17 M/s    0.00 B/s  0.00 %  8.26 % python2 -Es /usr/sbin/tuned -l -P
 3168 be/4 mysql       0.00 B/s    0.00 B/s  0.00 %  6.14 % mysqld --basedir=/
git push heroku masterからの卒業（Herokuパイプラインへ）

# 記事の目的
* 備忘

# 環境
* Django
    * localhostではsqlite
    * herokuではpostgres
* Python3
* Heroku
    * Production appのみ
        * dynoとpostgresのみ有料
* DjangoのWebアプリケーションは個人で実装・運用しています。

# Before
* ソースコードのホスト
    * Bitbucket（当時はGithubのPrivateが有料でした）
* Productionアプリケーションのリリース（アップデート）

```bash 
$ git push heroku master
```
* アプリケーションのテスト(Staging)
    * 開発環境（ローカル）でpython manage.py runserverをし、localhostでテスト

* ![Qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473617/70d6c3cf-cd55-78d4-393e-6a1842932709.png)



## After
* Heroku Pipelineを使ってみたいとは思いつつもBitbucketだからなぁという思いから停滞していましたが、やってみて良かった。

* ソースコードのホスト
    * GitHub
* Productionアプリケーションのリリース（アップデート）
    * Heroku PipelineのPromote to productionボタンクリック
    * ![スクリーンショット 2019-09-12 11.06.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473617/91f901f9-3371-4df6-7a9d-eb5058618c57.png)

* アプリケーションのテスト(Staging)
    * Review（masterへのPR）を受けてGit HubのmasterへマージするとStagingアプリが自動Deployされる
    * 自動DeployされたStaging Appでテスト

* レビュー（Review）
    * Heroku PipelineによりGithubのmasterにPull Requestをすると、Pull RequestをトリガーにStaging AppのHeroku:Addon、Staging AppのConfig Vars（環境変数）を参照し自動DeployされるReview Appsによりレビュー

* ![Qiita (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473617/e54bf102-2a37-81be-befb-7b4bd76d6763.png)


# Afterまでの手順

1. GithubにソースをPushしておく
2. Herokuで新たにStaging用のAppを新規作成する
   * (Review AppsはHeroku Pipelineにより自動で作成されるため、手動で作成する必要なし)
3. Heroku:Pipelineを新規作成する。
   * 画面遷移含めてQiita（Web）上に分かりやすい情報が大量あるので[そちら](https://qiita.com/G-awa/items/c1286fed0575aaa05b34)を参照。
   * 今回はProduction AppのリリースはHeroku PipelineのPromote to productionボタン押下で実行する事とし、Staging AppをGitHubの該当ブランチのmasterと同期。
   * Review AppはStaging AppをParent Appとし、Githubの該当ブランチのmasterにPull Requestをすると自動でDeployされるようにします。
4. Review appsの設定時にReview appsの振る舞いを決定するapp.jsonをHerokuが作成し、GithubのmasterにPushするので、ローカルの開発環境でfetch/mergeを忘れずに実施。
5. Githubに新たなbranchを作成し、変更をPushする。
6. Github上でmasterに対するPull Reuqestを作成する。
7. Review Appが自動でDeployされる。
8. 問題がなければ、Github上で該当のPull Requestをmergeする。
9. masterの更新に伴いStaging Appが自動でDeployされる。
10. Staging Appの動作に問題がなければ、Heroku:Pipeline上でPromote to productionボタンを押下し、Productionにリリースする。

# Pipeline作成時に気にした事・分かった事
* Staging App、Review Appはdyno、postgresのプラン制約をケアすれば無料でイケる。
    * Production Appが有料dyno、有料Addonだったのでミラーリングかと誤解していた。
    * ミラーリングは出来るが本アプリの場合、用途として不要なのでやらない。
* （考えれば当然だったが）Staging App、Review Appは振る舞いを意識しないと個別のpostgresエンドポイントを生成する。（After絵の通り）
* Review AppはParent App（Staging App）のAddonをコピーする（設定に出来る）
* Promote to productionではスラグのコピーのみでdbのmigrateは別途実施する必要がある。
    * Promote to productionした後に、``` $ heroku run python manage.py migrate```が必要になる。

以上
iostatコマンドまとめ

#できること
CPU使用状況とディスクIOの監視

#実行結果

使い方： `iostat [オプション] [表示間隔秒] [回数]`

最初の行：システムが起動してからの平均値が記載される。
２回目以降の行：前回の表示との差分

オプション|説明
---|-----
-c|CPU情報(2,3行目)のみ表示
-d|IO情報（４,５行目）のみ表示
-m|MB単位で表示（デフォルトはKB単位）
-t|時間を表示

```
$ iostat 1 3
Linux 3.10.0-957.12.2.el7.x86_64 (bench) 	2019年09月11日 	_x86_64_	(1 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           1.09    0.00    1.09    0.02    0.00   97.80

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               1.36        30.10         7.67     735163     187402

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.00    0.00    0.00    0.00    0.00  100.00

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               0.00         0.00         0.00          0          0

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.00    0.00    0.00    0.00    0.00  100.00

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               0.00         0.00         0.00          0          0
```

２,3行目
`avg-cpu:  %user   %nice %system %iowait  %steal   %idle`

cpuの表示項目については[topコマンド](https://qiita.com/s_suzaku/items/5a2e1602ab800b76a49a)と同じ

4,5行目
`Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn`

項目|説明
----|---
tps    |I/O転送リクエスト数
kB_read/s    |ディスクからの読み出し量（KB/秒）
kB_wrtn/s    |ディスクへの書き込み量（KB/秒）
kB_read    |ディスクからの読み出し量（KB）
kB_wrtn`|ディスクへの書き込み量（KB）
自前でホスティングしている Redash のQueryを公式の Redash に移す

自前でホスティングしている Redash(v1.0.3) を公式（SaaS）のRedash(v7) に移しましたまとめです。
いくつかの方法が見つかるのですが、SaaSなのでDBダンプなどの方法は取れませんでした。
フォーラムで聞いてみたところ、マイグレーション用のスクリプトを教えてもらいました。


[How to migrate self hosted redash queries to official redash service?](https://discuss.redash.io/t/how-to-migrate-self-hosted-redash-queries-to-official-redash-service-app-redash-io-xxxx/4412)

[Migration script for V4](https://gist.github.com/arikfr/e1c01f6c04d8348da52f33393b5bf65d)

ただ、移行したいのが Query のみ && `import_users()` メソッドがうまく動かなかったため、以下のように一部書き換えました。
全て meta で定義した 1番目のユーザーが作成したクエリとして登録されます。

<img width="1433" alt="2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63855/057fe8a0-e3bf-6fb8-9c58-538dba331dd2.png">