OmniAICreator/Qiita-1.07M huggingface dataset:
[Rails][devise] devise + active_recordで画像を編集する

# やること
deviseを使用してログイン機能を実装していますが、
ActiveRecordを使用してUserに画像（avatar)を付与しようとした際に
新規登録では画像を付与できたのに編集ではできなかったので
解決方法を書いておこうと思います。

正しいやり方かは知りませんが、僕はこうしました。

# 前提

今回、Userに`image`を付与します。

```ruby:app/models/user.rb
has_one_attached :image
```

# deviseのStrong Parametersにimageを追加
まずはdeviseの`Strong Parameters`に`image`を追加します。

```ruby:users/registrations_controller
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: :image)
    devise_parameter_sanitizer.permit(:account_update, keys: :image)
  end
```

この時点で、画像を添付して`registrations#create`（新規登録）をすると画像が付与されますが、
<b>`registrations#update（編集）`を行っても画像は付与されず</b>困ってしまいました。


# Railsガイドを見てみると

`Active Storage - Railsガイド`を参照するとこう書いていました。
https://railsguides.jp/active_storage_overview.html#has-one-attached

<br> 

<b>`既存のuserにavatarを添付するにはavatar.attachを呼び出します。`</b>

```ruby:
Current.user.avatar.attach(params[:avatar])
```

なので、<b>update時にimage.attachを行う必要がある</b>、ということですね。


# deviseのStrong Parametersを取り出す

しかし、DeviseのStrongParametersってどうやって取り出すんだろう？と
戸惑ってしまいました。

調べたところ、こうしたらうまくいきました。

```ruby:users/registrations_controller
  def update
    self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
    prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
     
    #ここ
    resource.image.attach(account_update_params[:image])

    resource_updated = update_resource(resource, account_update_params)
    yield resource if block_given?
    if resource_updated

　　（以下略）

```

<br>

ちなみにこれ、`resource_updated`との順番が逆になると`RecordNotFound`の例外が発生してしまいます。

```ruby:
    resource_updated = update_resource(resource, account_update_params)
    resource.image.attach(account_update_params[:image])

    #この順番だとupdate時に例外が発生
```

なので、先程の順番で書くようにしてください。


終わり
【初心者向け】ベイズの定理とは？

AIや機械学習の勉強をしていると、「ベイズ推定」という言葉をよく見かけます。これを理解するためには「ベイズの定理」を理解すべきなのかと考えまして、「ベイズの定理」についてまとめました。

何かの実験で「結果」が観測されたとき、その背景にある「原因」の確率を求めたいときに、「ベイズの定理」が使われます。一般的に、原因 → 結果となる確率は求めやすいけど、結果 → 原因となる確率は見出しづらいのですが、こういうときに使われるんですね。

## ベイズの定理
### 事前確率と事後確率は違うもの？
10枚のカードから1枚をひく実験を考えます。
10枚には赤と青の二種類のカードがあり、それらのうち何枚かには「当」マークが書かれています。次の図のような感じを考えましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271244/39a951f3-3299-9700-072d-55d209f88944.png)

#### 問1-1: このとき、「当」が出る確率は？
以降の数式で関数Pは確率を表します。

```math
P(当) = \frac{3}{10}
```
#### 問1-2: では、「赤」かつ「当」の確率は？
```math
P(赤, 当) = \frac{2}{10}
```
このような「赤」と「当」が同時に生起する確率を__同時確率__と呼んでいます。

#### 問1-3: 引いたカードが「赤」だったとき、「当」の確率は？
既に「赤」であることまでは分かっているので、問1-1や問1-2とは異なります。

```math
P(当|赤) = \frac{2}{4}
```
問1-1のように「赤」であることが分かる前の確率を__事前確率__、問1-3のように「赤」であることが分かった後の確率を__事後確率__と呼びます。「|」を使っていて、問1-2とも式の書き方が違いますよね。__条件付き確率__ともいわれ、P(当|赤)と書かれていたら「赤」という条件が与えられたときに「当」である確率と読むことができます。「｜」の後に書かれるのが条件です。

### ベイズ統計における確率とは、確信度のこと！　
確率の考え方には、2種類あるそうです。先のカードの例における確率は、__主観確率__という考え方を理解すると、受け入れやすいです。
#### 客観確率（一般的に考えられる確率）
確率を相対頻度の極限として捉える立場を__頻度主義__と読んでいて、この考え方における確率を__客観確率__と呼んでいます。
例えば、サイコロの目が1である確率は無限回試行すれば1/6ですよね。

#### 主観確率（ベイズ統計学における確率）
確信度（degree of belief）をもとにした確率です。先のカードの例でいえば、当初は「当」が出る確率P(当)は30%だと思っていたのですが、カードが「赤」であると分かった瞬間に確率P(当|赤)は50%だと思うようになりました。新しい事実が発見されれば、確信度は異なるのですね。このようなベイズ統計学における確率は__主観確率__と呼ばれ、確率をこのように解釈する立場を__ベイズ主義__と呼びます。

### ベイズの定理
さて、ベイズの定理の勉強していて、最初につまづくのは次の式だと思います。この式で重要なのは__結果から原因の確率（逆確率）を求められる__ことにあります。
ある原因が起きた時にある結果が起きる確率P(結果|原因)から、ある結果が観測されたときに、それがある原因によるものである確率P(原因|結果)が分かるという式になっています。__結果は観測しやすいけどその原因が分からない__ような場合に、ベイズの定理が威力を発揮します。__確率P(原因|結果)が確率P(結果|原因)から導かれる式__になっていることを確認しましょう。（私のような初心者は）式の導出はさておいて、こういう式が成り立つのだと受け入れることにしました。

```math
P(原因|結果) = \frac{P(結果,原因)}{P(結果)}\\
             = \frac{P(結果|原因)}{P(結果)}・P(原因)\\
             = \frac{P(結果|原因)}{\sum_{原因} P(原因)P(結果|原因)}・P(S)
```

Sを原因、Xを結果として、もっと数式らしくなります。

```math
P(S|X) = \frac{P(X,S)}{P(X)}\\
             = \frac{P(X|S)}{P(X)}・P(S)\\
             = \frac{P(X|S)}{\sum_{S} P(S)P(X|S)}・P(S)
```


結果から原因を探る問題は一般的に__逆問題__と呼ばれていて、これが求められる個所は世の中で多いため、これだけベイズの定理が求められているんですね。


## 参考資料
主に、次の書籍を参考に勉強しました。

続・わかりやすい　パターン認識 －教師なし学習入門－
https://shop.ohmsha.co.jp/shopdetail/000000000574/

>　第１章　ベイズ統計学
>　　1・2　ベイズの定理
>　　1・3　頻度から確信度へ
>　　1・4　逆確率　－　結果から原因を　－
AWS Batch でコンテナストレージサイズを拡張する（起動テンプレート使用）

# 概要
次の手順を示します

- AWS Batchで起動されるコンテナのストレージ容量はデフォルトで10GBになっている
- 処理するデータ量が10GBを超える場合、ストレージ割当を増やしたい
- EC2の起動テンプレート(Launch Template)を使うことで（事前にAMIを作成せずに）対処する

### 補足
- AWS Batchの実態はAmazon ECSであり、ECSはDockerです
- Dockerが割り当てるストレージデフォルトが10GBなのでそういうことになるのだと思われます

# デフォルトストレージが10GBであることを確認
- AWS Batchは準備手順が少し複雑で、はじめての利用者には難しいと思います
- そういう背景からだと思うのですが、手順ウィザードが準備されています
- ウィザードに従って設定すれば busyboxイメージ（docker image）を起動して「hello world」を出力（CloudWatch Logsへ）することができます
- `hello world` を `df -h` に変更することでコンテナに割り当てられたストレージ容量を確認します

## ジョブ定義
コンテナプロパティ部分

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53115/7f3b08a0-6804-fa34-2bc2-ac33b7dcb4fb.png)

## 実行結果
CloudWatchLogsで確認（10GBといいつつ、9.8GBですが）
これを100GBにします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53115/27a7df9e-e169-14b6-9db7-f267ef9b4778.png)

# ストレージ拡張設定（起動テンプレート作成）
EC2ページの起動テンプレート→起動テンプレートの作成で、「Storage100G」というテンプレートを作成しました
設定箇所は２箇所で、他はデフォルトです

## 設定箇所（１）：ストレージ（ボリューム）
- Device Nameに `/dev/xvdcz` を指定します
- ECSで使用されるAMIがこのデバイス名なので、合わせる感じです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53115/07ebd9fb-b089-2f03-c82d-5789f31ba384.png)

## 設定箇所（２）：高度な詳細 → ユーザーデータ
ユーザーデータに下記を指定します
起動時（かつDockerd起動前）にストレージオプションを指示する、ということですね
（参考）https://aws.amazon.com/jp/premiumsupport/knowledge-center/increase-default-ecs-docker-limit/

```
Content-Type: multipart/mixed; boundary="==BOUNDARY=="
MIME-Version: 1.0

--==BOUNDARY==
Content-Type: text/cloud-boothook; charset="us-ascii"

cloud-init-per once docker_options echo 'OPTIONS="${OPTIONS} --storage-opt dm.basesize=100G"' >> /etc/sysconfig/docker

--==BOUNDARY==--
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53115/bbce4328-da60-201e-1f7a-16cca0b0a44a.png)

# ストレージ拡張設定（AWS Batchの設定）
## コンピュート環境の作成
- コンピューティングリソースの設定→Launch templateに上記で設定した起動テンプレートを指定します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53115/f5717201-b37b-5425-562f-5973a5de3a1c.png)

## ジョブキューの編集
- ジョブキューを編集し、上記で作成したコンピュート環境を指定します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53115/99f39f2e-c335-c1d0-cedf-d1b4114a0334.png)

# ストレージ拡張した状態でジョブを投入して結果を確認

## ジョブ投入
- 最初に作成したジョブ( `df -h` を実行するジョブ）を投入します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53115/2d7e0359-fa5d-baa9-896c-799d71624d9d.png)


## 実行結果

- CloudWatchLogsで確認
- Sizeが97.9Gになっていることが確認できます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53115/42e62f34-75df-408d-2e4d-a70ccdaea613.png)

# まとめ
- かなり説明はハショったのでわかりにくいかもしれません
- うまく起動しなかったり、起動までに時間がかかるので検証シンドイ
- Fargateの場合はストレージ10GB制限は外せないですね（少なくとも現時点では）
    - https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/service_limits.html

# 参考にした記事
ありがとうございます　🙏

- https://qiita.com/horihiro/items/ac4f3cd68473bd2fba75
- https://qiita.com/sekitaka_1214/items/dbfc16d26168efc39900
- https://qiita.com/dempasong/items/fafa4b1fe1fc8d9f452d
- https://aws.amazon.com/jp/premiumsupport/knowledge-center/increase-default-ecs-docker-limit/
Androidアプリをリリースしてみた

Androidアプリをリリースしてみたので、その経緯をまとめたいと思います。

####リリースサービス

[タスクTODOスケジューラー](https://play.google.com/store/apps/details?id=com.kumaydevelop.todoreminder)

####アプリの詳細
リマインド機能の付いたシンプルなTodoリストです。

タスクを登録すると一覧に表示され、設定した時間に通知が来るという機能です。
タスクは登録、編集、削除ができます。
さらに、タスク名と、期限は入力必須にして、登録件数は5件までにしたので、その辺のバリデーションチェックを入れました。

![aaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239560/7c726cf8-b625-bd49-0b17-9f7292f683d8.png)
![aaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239560/1a46baf5-b1d5-2ef6-2831-edc4294475f4.png)
![aaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239560/06904a1f-9e65-be85-88b2-a7827f6df1eb.png)
![aaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239560/797376b2-2d43-baf0-ca36-7570805088bc.png)

####開発経緯
今まで、ローカルでアプリを作ったりは少ししていましたが、リリースはしたことがありませんでした。
なので、リリースしてみたら面白いかもと思いながら、作ってみることにしました。
あと、リリース作業って難しいのかなぁというのが知りたかったのもあります。

####使用環境
- **kotlin 1.2** 
**JDK 1.8**
Javaを使って今まで開発していたので、この機会にkotlin使ってみようと思い、選びました。
あと、コードどれくらい省略できるかなぁというのも気になりました。

- **AndroidStudio**
IntelliJとも迷いましたが、慣れているので、AndroidStudioにしました。


- **Realm**
データ関連にはRealmを使いました。SQLゴリゴリ書いて使うようなアプリではないのと、見てわかりやすいので選びました。

####開発過程
大体2～3週間で作りました。

**①画面イメージ作り(2日)**
画面を紙に書いてどういう風に遷移するとかのイメージを頭の中ではなく、見える化しました。
また、どういう機能を入れるかを決めました。
考えるといろいろ追加したくなりますが、段階的にリリースすることを想定して、どうしても入れたい機能だけに絞りました。

**②技術調査(2日)**
kotlinをそこまでやってなかったので、kotlinの調査と入れる機能の調査を行いました。

**③実装(6日) + バグ修正(3日)**
普通にコーディングしていました。
最初に画面を作ったり、アプリの設定を行ってから、バックグラウンドの実装をしました。
分からないときに調べると意外にkotlinの記事が少なかったです。
ただ、Javaの記事は結構あるので、そこからkotlinに置き換えることが多かったので、Javaやっててよかったと思うことは多かったです。(JavaのUtilも使えるので、わかりやすいというのはありました)

コーディングで詰まったところは下記に投稿しています。
特に、バグ修正が大変でした。
内部テストで見つかったバグで、デバックしながら再現するのに苦労してしまいました。。。

[FragmentのonAttach()はAPIレベルによって使い分けよう](https://qiita.com/kumas/items/8c88569e1f9645a21ac4)
[Textboxの入力制限について](https://qiita.com/kumas/items/bb7ffb2700167828bfd2)
[Andoridで背景を押して、キーボードを非表示にする方法](https://qiita.com/kumas/items/980a0a790da8d366be60)
[アラームを複数設定できるようにしよう](https://qiita.com/kumas/items/f21a55117d2a6cafa7c1)
[再起動をadbコマンドで実行する](https://qiita.com/kumas/items/e34c0d809ae9e5e4fda7)

**④テスト(3日)**
一応UIテストも兼ねて、Espressoを使い、テストしました。
(JUnitは今後拡充していきます)
あとは、PCを実機につないで、動作確認を行いました。

**⑤リリース作業(2日)**
思ってたより大変でした。。。。

apkファイル作るまでは楽でしたが、アプリの設定で時間がかかりました。
アイコンの設定やら、説明文、対象年齢やら、画面キャプチャなどなど、手間がかかるなあと思いながら進めました。
広告付けたり、有料にしたらもっと大変だろうなぁと思いました。
あと、本気で売る人は、ここで手を抜かないんだろうなあとも感じました。
また、アプリを更新するときにバージョンコード上げるのはリリースしないと気づかないと思いました。

**⑥リリース前テスト(2日)**
内部テスト、アルファー版テスト進めていき、動作確認を行いました。
驚きだったのがリリース前レポートでした。
テスト端末が自動的にアプリを起動して、アプリを数分間クロールしてくれます。
下記に詳細が載ってます。

[Firebase Test Lab for Android](https://firebase.google.com/docs/test-lab/)
>1 回のオペレーションで、さまざまなデバイス、さまざまなデバイス構成で Android アプリや iOS アプリをテストし、Firebase コンソールで結果（ログ、動画、スクリーンショットなど）を確認できます。

自動で何種類かの端末を使ってテストをしてくれて、バグがないか、パフォーマンスに問題ないか、画面のアクセシビリティに問題ないかなど計測してくれます。
画面のアクセシビリティはリリースしないと意識しないことだったので、とても有益でした。

####感想
リリース作業が意外と大変でしたが、スマホアプリ制作についてローカルで開発していた時より知れたので良かったです。
kotlinを使ってみて、findViewById書かなくていいのと(kotlin-android-extension)、無名関数とかNull許容型とかあって見やすくて、コンパイル時にエラーに気づけるのは使いやすかったです。
ただ、Javaをずっと使ってきて、型がないのが少し違和感でしたが、Javascriptもやってたので、すぐに慣れました。
今後は、機能追加や自動化、単体テストの拡充などを行っていきたいと思います。
Calendar.MONTH

備忘録です。

``` java

// 現在日時
private Calendar now = Calendar.getInstance();
year = now.get(Calendar.YEAR);
monthOfYear = now.get(Calendar.MONTH);
dayOfMonth = now.get(Calendar.DAY_OF_MONTH);

```

てやっても1か月前にさかのぼってしまいます

``` Calendar.MONTH ``` はどうやら0から始まるようです。

なので

``` java

// 現在日時
private Calendar now = Calendar.getInstance();
year = now.get(Calendar.YEAR);
monthOfYear = now.get(Calendar.MONTH) + 1;
dayOfMonth = now.get(Calendar.DAY_OF_MONTH);

```

と書きましょう。
静的ルーティング(static routing)をsystemdのservice unitで設定してみた

#概要
[「Firewall内のサーバ・プライベートネットワークにVPN接続」](https://www.lapidem.pw/linux/73/firewall-private-network-vpn/)により、２つのprivate network（自宅と職場）をvpn常時接続した。その際に、相手方のprivate networkへのstatic routeを設定してあげる必要があり、/etc/network/if-up.d/でルーティング設定を行うと、問題なく設定されるが、networking.serviceがfailedとなってしまう。実行のタイミングの問題のようだが、コントロールできないため気持ち悪いのでsystemdで設定した。慣れれば?、systemdは便利。

#環境
- vpn接続したDebian server (stretch)
- private networkは、192.168.1.0/24と192.168.32.0/24
- 以下の例は、192.168.1.0/24側のサーバ設定。
- gatewayはvps上の仮想ルータに設定している（詳細はここでは述べません）。

#やっていること
192.168.1.0/24のマシンから192.168.32.0/24のマシンに接続するために、

```
sudo /sbin/route add -net 192.168.32.0/24 gw 192.168.1.200
```
を起動時にしているだけなんですが。。。vpnbridge.serviceが立ち上がってから自動的に実行するとなると、タイミングの問題があり、結構ハマりました。


#systemd unitの設定


```:/etc/systemd/system/static-route.service
[Unit]
Description=static route to target network
After=network.target network-online.target vpnbridge.service
[Service]
Type=oneshot
ExecStart=/root/static-route start
ExecStop=/root/static-route stop
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
```
- vpnbridgeが起動していなければ、ルーティングしても意味がないので、vpnbridge.serviceをAfterに設定。
- Type=oneshot, RemainAfterExit=yesとしないと、起動時にstopされます。daemonではないので、一回だけstartを実行してactiveとする必要があります。
- Execを/root/に置くのはどうかとも思いましたが、汎用性に劣るスクリプトなのでとりあえず。/usr/local/等に置くほどのものでもないので。


#static routingの起動・停止スクリプト


``` /root/static-route.conf例
NAME_TARGET='target_domain_name'
TARGET='192.168.32.0/24'
GATEWAY='192.168.1.200'
```

```
#!/bin/sh -e
# static routing to NAME_TARGET of TARGET
SCRIPT='static-route'

. /root/static-route.conf

help(){
        echo "$SCRIPT start, stop: routing to $NAME_TARGET"
}

case $1 in
        'start') CMD='add';;
        'stop' ) CMD='delete';;
        *) help; exit;;
esac

### routing to TARGET
ROUTE="/sbin/route ${CMD} -net ${TARGET} gw ${GATEWAY}"
echo $ROUTE
$ROUTE

```
- journalctlでの確認のために、echo $ROUTEで実行コマンドを記録していますが、コメントアウトしても可。

```
root@altair:~# journalctl -u static-route
-- Logs begin at Wed 2019-05-01 08:57:21 JST, end at Wed 
 5月 01 11:32:12 altair systemd[1]: Starting static route to target...
 5月 01 11:32:12 altair static-route[2359]: /sbin/route add -net 192.168.32.0/24 
 5月 01 11:32:12 altair systemd[1]: Started static route to target.

```
今日から令和です。

#参考
[第10章 SYSTEMD によるサービス管理](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/chap-managing_services_with_systemd)
CloudRunで使用する秘匿情報をberglasで管理する

#概要

SecretManagerが発表されたため、今後はSecretManagerが標準になると思われます。
SecretManagerを使ってみた記事は下記に記載。

[CloudRunの秘匿情報をSecretManagerで扱ってみる
](https://qiita.com/yamaneko_usg3/items/299d8077d317daf59041)

CloudRunでは環境変数くらいしかないため（Kubernetesのsecretに該当するものがない）、DB接続情報とか秘匿情報を安全に管理するためにberglasを使用しました。

# berglasの特徴

- サーバーレス環境などで使用する秘匿情報（DB接続情報など）を安全に管理するためのツール。
- KMSとCloudStrageを使用して、暗号化した情報をストレージ管理する。
- 管理している情報は環境変数から読み込むことができる。
- 令和初日時点でバージョンは0.1.0

令和２年でもうバージョンが0.5.1まで上がっていたので、資料を更新。

# 公式ドキュメント

```
https://github.com/GoogleCloudPlatform/berglas
```

#インストール

### 公式サイトからバイナリをインストール（2020/2/2）

公式サイトのReadme.mdにWindows/Linuxのバイナリへのリンクがあります。
Macはbrewでのインストールが記載されています。

### ソースコード、Dockerからのインストール

#### Goがインストールされている場合

```
go get github.com/GoogleCloudPlatform/berglas/...
go install github.com/GoogleCloudPlatform/berglas
```

#### Dockerがインストールされている場合

```
docker pull gcr.io/berglas/berglas:latest
```

#### GoもDockerもインストールされていない場合

どっちかいれましょう。
（CloudRunをやる時点でDockerは必須ですし）

## 初期設定

### クレデンシャルの発行

```
gcloud auth application-default login
```

### プロジェクトIDとCloudStrageのバケット名を設定

####バケットのロケーション設定を追加（2020/2/2）

```
export PROJECT_ID=<プロジェクトID>
export BUCKET_ID=<バケット名>
export BUCKET_LOCATION=asia-northeast1
```

補足：バケット名は未使用のものを環境変数で設定すること。実際にバケットを作成するのは後述のbootstrapなので、先に作るとbootstrapでエラーが出ます。

### APIの有効化

#####version0.5.0からSecretManagerに対応したとあるので、secretmanager.googleapis.comを追加（2020/2/2）

```
gcloud services enable --project ${PROJECT_ID} \
  cloudkms.googleapis.com \
  secretmanager.googleapis.com \
  storage-api.googleapis.com \
  storage-component.googleapis.com
```

### bootstrap

```
berglas bootstrap --project $PROJECT_ID --bucket $BUCKET_ID
```

ロケーションを指定する場合（大阪リージョンを指定した例）

```
berglas bootstrap --project $PROJECT_ID --bucket $BUCKET_ID --bucket-location asia-northeast2 --kms-location asia-northeast2
```

## シークレットの作成

```
berglas create ${BUCKET_ID}/foo my-secret-data \
  --key projects/${PROJECT_ID}/locations/global/keyRings/berglas/cryptoKeys/berglas-key
```

成功すると、Google管理のオブジェクトがストレージに作成されます。
この時点ではアカウントオーナーでも内容は見れません。

### 特定ユーザーにオブジェクトの参照権限付与

```
berglas grant ${BUCKET_ID}/<オブジェクト名> --member user:user@mydomain.com
```

### 参照

```
berglas access ${BUCKET_ID}/<オブジェクト名>
```

なお、権限を付与することでブラウザでクラウドストレージを見ても内容を開くことはできますが、暗号化された状態のため、見ても意味はわかりません。

## CloudRunから使用する

### CloudRunに権限を付与する

```
PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format 'value(projectNumber)')
export SA_EMAIL=${PROJECT_NUMBER}-compute@developer.gserviceaccount.com
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member serviceAccount:${SA_EMAIL} \
  --role roles/run.viewer
berglas grant ${BUCKET_ID}/db_key --member serviceAccount:${SA_EMAIL}
```

### ソースコードのサンプル

各言語のサンプルは下記。

```
https://github.com/GoogleCloudPlatform/berglas/tree/master/examples/cloudrun
```

私はPythonで試しましたが、Pythonの場合、ポイントはDockerファイルになります。
マルチステージデプロイでberglasのモジュールを持ってきて、berglasからPythonを起動しています。

### デプロイ

環境変数設定で環境変数とシークレットのオブジェクトを紐づける。
これで、アプリ上では環境変数へのアクセスで利用できるようになる。

```
gcloud beta run deploy <アプリ名> --allow-unauthenticated --memory 128Mi --region us-central1 --timeout 30 --image <イメージ> --set-env-vars "<環境変数>=berglas://${BUCKET_ID}/<オブジェクト名>"
```
ERC865（手数料をトークンで払う）をカタパルトでやるには

# はじめに

NEM2のSlackに、ERC865のようなことができるか？という投稿があったので考えてみます。

簡単にいうと、トークンを送信する際に、手数料としてETHではなくトークンで払うものです。これを1回のトランザクションで済ますものになります。

内部的には、第三者がETHで手数料を払ってトランザクションを送信します。同時に、トークン送信者がその第三者に手数料としてトークンを払います。

# ERC865

まず、ERC865: 『Pay transfers in tokens instead of gas, in one transaction』について

https://github.com/ethereum/EIPs/issues/865

2018年1月30日に書かれたものなので、1年以上経過してますね。

# カタパルト

## 概念

Aliceはトークンを送りたい人。Bobはそれを受け取る人。

Davidはトランザクションを送るための手数料を払ってくれる人。（トランザクションに署名してくれる人）

AliceがBobに送るトークンは`T`で、量は`X`。

AliceはDavidに手数料を支払う。トークン`T`で、量は`Y`。



![ERC865 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/89f4377c-8ca7-dab3-6087-c54ddf99ec9a.png)

## パターン１

Aggregate Bondedパターン。

![ERC865 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/8e099e03-8388-def2-1854-cafb5c6b8620.png)

## パターン２

Aggregate Completeパターン。


![ERC865 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/be09bfc2-a663-22c3-52e2-ded10a2fb43d.png)

これの3で、トランザクションそのものを送って、Aliceが署名付けてアナウンスするパターンも考えられます。どちらがよいかはアプリの設計次第だと思います。

# おわりに

- トークン手数料は、送信者負担にしていますが、受信者負担にすることもできそうです。その場合は、AliceからDavideではなく、BobからDavidに送るトランザクションにして、Bobのcosignも必要な形にすると、全員の合意があったことの証拠になりそうな感じですね。
- Ethereumの方は、手数料を肩代わりする方法として、meta taransactionが普及しそうな気配がしています。
ログファイルの最大値指定機能を試す（Oracle Database 19c)

# テキスト形式のログ
Oracle Database 11g以降、ログ出力先はADR (Automatic Diagnostic Repository) に統合されました。出力フォーマットは新しいXML形式と、従来のテキスト形式が両方出力されていました。テキスト形式のログファイルのうち、特にlistener.oraファイルはサイズが大きくなるにもかかわらず、自動ローテーションされないため管理が面倒なファイルでした。

# Oracle Database 19cの新機能
Oracle Database 19cでは、ネットワーク系のテキスト形式ログファイルに自動ローテーション機能が加わりました。リスナー、CMAN、GSMなどが対象になります。[Oracle Database 19c New Features Guide](https://docs.oracle.com/en/database/oracle/oracle-database/19/newft/new-features.html#GUID-751E407F-B871-4ADB-8800-6D71BA78FC15) に簡単な説明が記載されています。
なぜか、Database Net Services Reference マニュアルの [Changes in This Release for Oracle Database Net Services Reference](https://docs.oracle.com/en/database/oracle/oracle-database/19/netrf/changes-in-this-release.html) 項目には新機能の説明がありません。

# リスナー・ログの最大値
リスナー・ログ（listener.log）ファイルの最大値を決めるパラメーターは以下の二つです。

- [LOG_FILE_NUM_{listener}](https://docs.oracle.com/en/database/oracle/oracle-database/19/netrf/oracle-net-listener-parameters-in-listener-ora.html#GUID-812F2A7E-A31C-4581-804F-A4AE692C960D)
  ログファイルの最大個数を決定します。デフォルト値は設定されておらず、個数制限はありません。

- [LOG_FILE_SIZE_{listener}](https://docs.oracle.com/en/database/oracle/oracle-database/19/netrf/oracle-net-listener-parameters-in-listener-ora.html#GUID-FF94A234-A29C-46AA-8770-4CA1BFB5C27C)
  単一のログファイルの最大サイズをメガバイト単位で指定します。デフォルト値は300MBです。

下記の設定例では、ファイルの個数を3個、最大サイズを1MBにしています。

```
LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = dbsrv-1)(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
    )
  )

LOG_FILE_NUM_LISTENER = 3
LOG_FILE_SIZE_LISTENER = 1
```

# 実験
実際にどのように動作するのか試してみました。ある程度負荷をかけてログファイルの様子を見てみます。ログファイル名として、listener_{n}.log ファイルが作成されています。古いファイルには数字を付けて別ファイルとして管理するようです。
最大サイズを1MBと設定しているにも関わらず、半分のサイズでローテーションされる理由はわかりません。

```
$ cd $ORACLE_BASE/diag/tnslsnr/dbsrv-1/listener/trace
$ ls -li
total 2028
5796100 -rw-r-----. 1 oracle oinstall 529985 May  1 10:34 listener_1.log
6092293 -rw-r-----. 1 oracle oinstall 540743 May  1 10:38 listener_2.log
6092294 -rw-r-----. 1 oracle oinstall 540155 May  1 10:41 listener_3.log
6092295 -rw-r-----. 1 oracle oinstall 347884 May  1 10:43 listener.log
```

さらに負荷をかけると、数字付きのログファイル個数が最大値（LOG_FILE_NUM_listener）を越え、古いファイルが自動的に削除されていることがわかります。もっとも古いファイルが無くなっていますが、消えたもっとも古いファイルと書き込み中の最新ファイルはiノード番号が同じ（5796100）です。ローテーションを行う際はもっとも古いファイルを切り詰めてファイル名を変更することでローテーションしていることが予想されます。

```
$ ls -li
total 2468
6092293 -rw-r-----. 1 oracle oinstall 540743 May  1 10:38 listener_2.log
6092294 -rw-r-----. 1 oracle oinstall 540155 May  1 10:41 listener_3.log
6092295 -rw-r-----. 1 oracle oinstall 539689 May  1 10:45 listener_4.log
5796100 -rw-r-----. 1 oracle oinstall 240644 May  1 10:46 listener.log
```

ログファイルの数字が9を越えると単純に10が作られます。

```
$ ls -li
total 2468
6092293 -rw-r-----. 1 oracle oinstall 540297 May  1 11:13 listener_10.log
6092295 -rw-r-----. 1 oracle oinstall 540796 May  1 11:06 listener_8.log
5796100 -rw-r-----. 1 oracle oinstall 540291 May  1 11:09 listener_9.log
6092294 -rw-r-----. 1 oracle oinstall 283151 May  1 11:14 listener.log
```
Rubyのirbを超絶使いやすくする「irbtools」のススメ

Rubyのコードをちょっと試したい時に便利なirbを超絶使いやすくする[irbtools](https://github.com/janlelis/irbtools)の紹介です。

以下のように、カラー表示やindentで見やすく、さらにlinuxのコマンド、内部でvimの起動など様々なことが出来ます。

![all3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114396/b4b9d6ec-1627-ede3-3eb3-8cb89b32378b.gif)


# インストール
irbtools, irbtools-moreをinstallします。

```zsh
$ gem install irbtools irbtools-more
```

そして、irbの設定ファイルを作成し、以下の一行を記述します

```zsh
$ vi ~/.irbrc
```

```~/.irbrc
require 'irbtools/more'
```

これで完了です。
irbを開くと以下のようにプロンプトが「>>」に変わるはずです。

```
Welcome to IRB. You are using ruby 2.6.1p33 (2019-01-30 revision 66950) [x86_64-darwin18]. Have fun ;)
>>
```

（もし起動時にlibreadlineのエラーが出たら、[こちらの記事](https://qiita.com/koshilife/items/f47bcc2a3b3de756f5c9#%E3%82%A8%E3%83%A9%E3%83%BC%E5%86%85%E5%AE%B9) を参考にlibreadline.7.dylibにシンボリックリンクを設定して見て下さい）


# irbtoolsのここが良い
## カラー、インデントが効いて見やすい
以下簡単なeach分なのですが、自動でインデントが効いて見やすいです。
また結果がカラーで表示されます
![May-01-2019 06-57-41.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114396/699179a3-485f-bd94-95de-163c6cf6418a.gif)


## 補完が効く
メソッド、変数の補完が聞きます。
また「mof クラス、オブジェクト」で対象のメソッド一覧も出力可能です。
![May-01-2019 07-10-26.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114396/6a399880-b2e3-e07f-03c2-6ca37d38caa1.gif)


## linuxコマンドが使える
例えば、ls、cat、mkdir、cpなどなど色々使えます。
~~その他、terminalライクに↑↓の矢印キーでコマンド履歴を遡れます。~~ 
~~これも地味に便利です。~~(コマンド履歴は通常でも使えました）
![ls.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114396/f3e73501-3e1c-204a-ad9d-e93e967485f1.gif)


## 内部でvimが開ける
なんとirb上でvimが開けます。
ちょっとイメージし難いと思うのでデモを。（デモはnvimです）
![nvim.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114396/9fd3b209-fc1c-d913-0ad0-315914360105.gif)

このように、irb上でvimを開き、そこで作成したクラス、メソッドをirb側で実行できます！
こちらはメモリに保持されるので、途中で再度編集も可能です。
もうirb駆動開発？もできそうですね。

## 他にも色々

他にもかなり多くの機能があります。
詳しくは、[こちらのREADME.md](https://github.com/janlelis/irbtools)を。
(WIP)2019年のJavaScriptエコシステムについていけていないので勉強する

JavaScriptエコシステムがわからなさすぎるので勉強することにした。
さすがにそろそろ逃げていられない。。

# わかること/知っていること

- JavaScript文法
    - サイ本を通読した程度

# わからないこと

- ES6
- ES2015
- node
- webpack
- react
- import, from, export

# わかったこと

## ES2015(ES6)

- ES2015 == ES6
- スコープあり変数
    - `let` => 再代入可能
    - `const` => 定数
- クラスの導入
    - `class Klass {}`
    - `class Klass extends BaseKlass {}`
    - コンストラクタは `constructor(arg1, arg2)`
    - `this` で自インスタンス参照
    - `super` で親クラス参照
- テンプレート文字列
    - `` でくくる
    - 例: `title: ${title}, author: ${author}`
- アロー関数
    - `(args)=>{}`
    - `this` のスコープが変わらない
- Promise
    - 非同期処理ライブラリ
    - `asyncFunc().then().catch()` のように実行できる

## webpack

- module bundler
- 似たソフトウェア: `grunt`, `gulp`
- `--mode` オプションでdev/productionモードを切り替えられる
- https://webpack.js.org/configuration/mode/
- 設定ファイルは `webpack.config.js`
- Entry
    - ソースファイルの場所
- Output
    - 作られたbundleの出力先
- Loaders
    - ソースファイルの処理方法
    - `test` の正規表現にマッチしたファイルを処理する
    - `use` で指定したloaderを適用する
- Plugins
- webpack4
    - `webpack-cli` が分離された

### HTMLとload

- `src/index.html` などを用意する
- HTMLファイル内で `<script src="app.js"></script>` などとJSファイルpathを指定する
- `app.js` をwebpackで生成する
Flutterで顔認証/指紋認証を簡単に実装する

[Flutter | GW アドベントカレンダー](https://gw-advent.9wick.com/calendars/28)の5日目の記事です。

顔認証/指紋認証を実装するために、Flutter公式の[local_auth](https://pub.dartlang.org/packages/local_auth)プラグインを使用します。

## 完成形
以下のような感じで、顔認証/指紋認証を実装します。

#### 顔認証
<img width="314" alt="face.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396229/a9a4bac5-81b9-e056-f3b8-0ebcdeb84298.png">

#### 指紋認証
<img width="314" alt="touch.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396229/2957ca46-40d9-30a3-d703-a90b2e12c9c1.png">

##### Android
<img width="314" alt="android_touch.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396229/ce89ff4e-e99a-5a7d-e0bc-92eade1cef03.png">

## 顔認証/指紋認証の実装
### 1. プラグインとの紐付け
```pubspec.yaml
dependencies:
  local_auth: ^0.4.0+1    // 追加
```
バージョンについては、[local_auth](https://pub.dartlang.org/packages/local_auth)を参照してください。

### 2. 生体認証設定
iOSとAndroid側で以下を追加して、生体認証を行えるようにします。

#### iOS

```info.plist
<key>NSFaceIDUsageDescription</key>
<string>Why is my app authenticating using face id?</string>
```

#### Android

```AndroidManifest.xml
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
```

## 顔認証/指紋認証の実装

```main.dart
  import 'package:local_auth/local_auth.dart';
```

##### 端末の可能な生体認証タイプを取得

```main.dart
  LocalAuthentication _localAuth = LocalAuthentication();

  Future<List<BiometricType>> _getAvailableBiometricTypes() async {
    List<BiometricType> availableBiometricTypes;
    try {
      availableBiometricTypes = await _localAuth.getAvailableBiometrics();
    } on PlatformException catch (e) {
      // TODO
    }
    return availableBiometricTypes;
  }
```

##### 生体認証を要求

```main.dart
  Future<bool> _authenticate() async {
    bool result = false;

    List<BiometricType> availableBiometricTypes = await _getAvailableBiometricTypes();

    try {
      if (availableBiometricTypes.contains(BiometricType.face)
          || availableBiometricTypes.contains(BiometricType.fingerprint)) {
        result = await _localAuth.authenticateWithBiometrics(localizedReason: "認証してください");
      }
    } on PlatformException catch (e) {
      // TODO
    }
    return result;
  }
```

## 指紋/顔を登録していない場合の挙動は？
以下のように、登録を促すダイアログを自動的に表示してくれます。
ここで、顔や指紋を登録せずに「OK」ボタンを押された際には、認証結果がfalseで返ってきます。

<img width="314" alt="touch_setting.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396229/7bc9ca42-0073-3839-c5ff-2335ac87086c.png">

#### Android
![android_touch_setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396229/5bea9538-9b5d-c80c-5fd9-f385c527d8d5.png)

## まとめ
[local_auth](https://pub.dartlang.org/packages/local_auth)プラグインを実装しているだけです。
指紋認証も顔認証もかなり簡単に実装できてしまいます。
念のため、[githubにプロジェクトおいています](https://github.com/coka01/auth_app/blob/master/lib/auth.dart)。
Flutterつよし！！！！
【Oracle】木構造を持つテーブルの深さを求めるSQL

# 木構造を持つテーブルの深さを求めるSQL
例えばこの図のような木構造を持つテーブルがあるとする。
![IDTree.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403042/69770d4b-853a-9bb6-fbe5-f60ec396504e.png)
この木はレコードとして、一意のIDと親となるIDを表すPARENT_IDをセットで持つ。
テーブルとしてはこのようになる。

| ID | PARENT_ID |
|----:|----:|
| 0 | (null) |
| 1 | 0 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 4 |
| 6 | 4 |
| 7 | 4 |
| 8 | 7 |
| 9 | 7 |
| 10 | 8 |
| 11 | 8 |
| 12 | 4 |

このとき、この木における各IDの深さは下記のようなSQLで求めることができる。

```sql
SELECT ID, PARENT_ID, LEVEL
FROM IDTABLE
START WITH PARENT_ID IS NULL
CONNECT BY PRIOR ID = PARENT_ID;
```
出力結果はこうなる

| ID | PARENT_ID | LEVEL |
|----:|----:|----:|
| 0 | (null) | 1 |
| 1 | 0 | 2 |
| 2 | 1 | 3 |
| 3 | 1 | 3 |
| 4 | 1 | 3 |
| 5 | 4 | 4 |
| 6 | 4 | 4 |
| 7 | 4 | 4 |
| 8 | 7 | 5 |
| 9 | 7 | 6 |
| 10 | 8 | 6 |
| 11 | 8 | 6 |
| 12 | 4 | 4 |

# どんなときに使うのか
自分が使った例としてはArcSDEの更新履歴ツリーの深さ管理がある。
ArcSDEはユーザが接続したバージョン（更新履歴のタグ）に対して木の根からの更新履歴をたどるようにして画面にそのバージョンの状態を描画する。
このとき更新履歴ツリーが深いと読み込みの回数が増え、描画や追加の更新が遅くなる。
そのようなときはマージ処理をして途中の更新履歴をタグに集約し、木を浅くする。
目安として「木の深さがいくつ以上になったらマージする」という判断に使える。

# Oracle公式技術記事
こちらも参照すると良い。

[津島博士のパフォーマンス講座 - 第31回 再帰的問合せについて](https://www.oracle.com/technetwork/jp/database/articles/tsushima/tsushima-31-2026080-ja.html)
Visual Studio Code で Go 言語を引数付きでデバッグする方法

1. [デバッグ]→[構成を開く]を選択する。
2. `lanuch.json` が起動する
3. 以下のように `"args"` というパラメータを設定する。String 型の配列として記述する。

```json
{
    "version": "0.2.0",
    "configurations": [

        {
            "name": "Launch",
            "type": "go",
            "request": "launch",
            "mode": "auto",
            "program": "${fileDirname}",
            "env": {},
            "args": ["-logdir", ".\\log", "choice.exe", "hoge2", "hoge3" ,"hoge4"]
        }
    ]
}
```
WSL上でUbuntuを使うには、当たり前だがWSLを有効にする必要がありますよ

以前から個人開発の時は、WSL(Windows Subsystem for Linux) + Ubuntu + VSCodeで開発していたのだが、ちょっとノートPCの調子が悪くなってきたので[リフレッシュ](https://support.microsoft.com/ja-jp/help/17085/windows-8-restore-refresh-reset-pc)することにした。

再度環境を構築しなおしていたのだが、WindowsのアプリストアからUbuntuをダウンロードして起動したら、こんなエラーが出てきた。

```
Installing, this may take a few minutes...
WslRegisterDistribution failed with error: 0x8007019e
The Windows Subsystem for Linux optional component is not enabled. Please enable it and try again.
See https://aka.ms/wslinstall for details.
Press any key to continue...  
```

当たり前だけど、Ubuntu動かすにはWSLが必要で、それはデフォルトでは有効でないので有効化してあげる必要がある。当たり前だけど、忘れていた。恥ずかし

手順としては、以下の2つの記事を参考にしていけばすぐ終わる。

[Windows Subsystem for Linuxをインストールしてみよう！](https://qiita.com/Aruneko/items/c79810b0b015bebf30bb)
↓
[VSCode + WSL](https://qiita.com/remin/items/b764036e95a13075ee98)
styled-components で production ビルド時でも devtool から CSSいじれるようにする

2020/06/25 追記
Chrome 85でこちら解消される模様です。
https://developers.google.com/web/updates/2020/06/devtools

-----


ステージング環境で production ビルドしつつ、CSSはこまかい修正確認する時にいじれるといいなあ、ということがあったので対応した際のメモ。

中身としては、こちらの記事の `SC_DISABLE_SPEEDY` を補強する感じになる。
https://terrier.dev/blog/2019/20190224165710-production-styled-components-chrome-devtool/

まず事象として Production ビルドした時に devtool から要素のスタイルを見るとこんな感じになっていじれない。
<img width="275" alt="スクリーンショット 2019-05-01 9.49.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150569/803a1515-fbbd-7940-5819-803bfa43f1ec.png">

これは styled-components がプロダクションビルド時に CSSOM API なるものからCSSを追加しており、その際にいじれなくなるchromiumのバグ(仕様？)らしい。
https://stackoverflow.com/questions/51544215/styled-component-styles-are-disabled-in-chrome-devtools
https://bugs.chromium.org/p/chromium/issues/detail?id=387952

この最適化を止めるためには `SC_DISABLE_SPEEDY` というフラグをグローバル変数として定義してあげれば良い。

まず今回の方法を試すためには styled-components のバージョン 4.1.0 以上が必要になる。リリースノートを見る限りこのバージョンから追加されたっぽいからだ。
https://www.styled-components.com/releases#v4.1.0

次に指定の仕方だが、entryファイルに直接書いておいてもいいらしいが、私は webpack の DefinePlugin を使った。pluginsの中に次のように指定した。

```js
new webpack.DefinePlugin({
  SC_DISABLE_SPEEDY: isStaging
}),
```

これで devtool からいじれるようになった

<img width="295" alt="スクリーンショット 2019-05-01 10.23.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150569/bddde8b2-6aa8-55c2-a0d8-bef6e029017e.png">
Jupyter Notebookでのディレクトリ操作

#はじめに
Jupyter Notebookを使っていると、作業をしているディレクトリ（カレントディレクトリ）を変更したり、カレントディレクトリの確認をしたくなることがあります。このための操作方法に関するメモです。ざっくり言うと”%+コマンド”で実現することができます。

#カレントディレクトリの取得
カレントディレクトリの取得は**%pwd**で行えます。戻り値は文字列なので、Pythonの変数に戻り値を代入することが可能です。

```
%pwd　　　　　　　　　#カレントディレクトリ名の取得
current_dir = %pwd # カレントディレクトリ名を変数current_dirに代入
```

#ファイルリストの取得
ファイルリストの取得（表示）は**%ls**コマンドで行えます。引数を付けないとカレントディレクトリ内のファイルリストの取得ができます。引数としてディレクトリ名を指定すると、指定したディレクトリ内のファイルリストが取得できます。また、`-l`オプションなどを指定することができます。

```
%ls　　　　　　　 #カレントディレクトリ内にあるファイル名の表示
%ls /anaconda3  #ディレクトリ名を指定して実行、この場合は/anacoda3内のファイルリストを表示
%ls ~　　　　　　 # ホームディレクト内のファイルリストを表示
%ls ..　　　　　　# カレントディレクトリの親ディレクトリ内のファイルリストの表示
%ls -l 　　　　　 # ファイル情報の詳細表示
%ls -a　　　　　  # 先頭が.で始まるファイル名のファイルも含めて表示する
```

#カレントディレクトリの移動
カレントディレクトリの移動は**%cd**コマンドで行えます。
```
%cd /anaconda3　# /anaconda3ディレクトに移動
%cd　　　　　　　 # ホームディレクトリに移動
```

#ディレクトリの作成と削除
ディレクトリの作成は**%mkdir**コマンド、ディレクトリの削除は**%rmdir**で行うことができます。
```
%mkdir new_dir　　　　　　# new_dirディレクトリを作成
%rmdir unnecessary_dir　# unnecessary_dirの削除 
```

#おわりに
ざっくり言うと、ディレクトリ操作は`%コマンド`で行うことができます。初期ディレクトの変更は[Jupyter Notebookの初期ディレクトリを変更する](https://qiita.com/nigimitama/items/a8129e50afcc462e02d6) などを参考にして下さい。
初のnpmパッケージ公開で行ったこと

はじめまして！
@Leopard0505で活動しているものです。
初めての投稿で分かりにくい点があると思いますが、指摘してもらえるとありがたいです。

# 完成物
こちらが今回作成したnpmパッケージです。
[@leopard0505/payment-request](https://www.npmjs.com/package/@leopard0505/payment-request)
随時アップグレードしていきますので、よろしくお願いします。

# 公開までの手順
[こちら](https://qiita.com/hoshimado/items/c6f1484297d974f44f19#%E5%85%AC%E9%96%8B%E3%81%BE%E3%81%A7%E3%81%AE%E6%93%8D%E4%BD%9C%E6%89%8B%E9%A0%86)が大変参考になりました。

## npmアカウント作成
まずは、```npm set``` コマンドを使って登録します。

```bash:author情報を作成
$ npm set init.author.name "Leopard0505"
$ npm set init.author.email "Leopard0505@example.com"
$ npm set init.author.url "https://qiita.com/Leopard0505"
```

次に ```npm adduser``` コマンドを使ってユーザを登録します。

```bash:npmユーザの登録
$ npm adduser
## まだユーザが登録されていない場合は、npm に登録する新規ユーザ情報を入力する。
## 既にnpm ユーザが作成されている場合はそのユーザの情報を入れて、ログインする。
```

## ローカルからnpmにログイン
Webページ上（npm公式＞signup）でアカウントを作成したら、続いてローカル環境のnpmコマンドから作成したアカウントにログインする。

ログイン自体は簡単で、以下のコマンドを実行すればよい。

```bash:npmにログイン
$ npm login
```

ユーザー名とパスワードとメールアドレスを聞かれるので、アカウント作成時に入力した値を入れる。

## ファイルの準備
次に、公開するファイルを準備します。

```bash:最小限のディレクトリ構造
srcDir/
  +-- index.js
  +-- package.json
  +-- LICENSE.txt
  +-- README.me
  +-- .gitignore
  +-- .npmignore
```

## npmに公開
公開用のファイルの準備まで終えたら、後は「公開」する。
「npm login」済みの環境で、以下を実行するだけ。

```
$ npm publish
```

これで、npmパッケージの公開は完了です。
任意のフォルダ上のコマンドラインから、npm install 「公開したパッケージ名」 を打ち込んでライブラリがインストールされるか確認しましょう。

お疲れ様でした！


# 今回の感想
初めてのnpmパッケージ公開でしたが、意外と簡単でした。
それよりも何を作るかで結構悩みました。
そんな感じで行き当りばったりで公開までしてみましたがなんとかなるもんですね。

10連休に入ってやりたいことをやれたので一先ず落ち着けました。
これからも積極的にアウトプットを行っていきたいと思います。

# 参考リンク
以下のリンクが大変参考になりました。
ありがとうございました。

@TsutomuNakamuraさん [初めてのnpm パッケージ公開](https://qiita.com/TsutomuNakamura/items/f943e0490d509f128ae2#%E5%B1%A5%E6%AD%B4)
@hoshimadoさん [npmでパッケージを公開してみた手順の記録](https://qiita.com/hoshimado/items/c6f1484297d974f44f19#%E6%A6%82%E8%A6%81)
NAT・NAPTについて


![image.png](https://qiita-image-store.s3.amazonaws.com/0/257568/e50ae24e-5954-bcfb-0e3d-e1187ee3f996.png)

こちらの本を読んでまとめ

## NATとは
Network Address Translator

- ローカルなネットワークでプライベートIPアドレスを使用し、インターネットへ接続するときにグローバルIPアドレスへ変換する技術
- 通信を同時に処理することができる

## 登場背景
IPv4のアドレスが枯渇しているため

## NAPTとは
Network Address Port Translator

- ローカルなネットワークで**ポートを含めた**プライベートIPアドレスを使用し、インターネットへ接続するときにグローバルIPアドレスへ変換する技術
- 通信を同時に処理することができる

## ポイント
NAPTは広義のNATであり、ハイコンテクストな会話上ではNATということも多い

## 書籍情報
竹下 隆史,村山 公保,荒井 透,苅田 幸雄. マスタリングTCP/IP 入門編
https://amzn.to/2UShr5Y

## 雑感
iPhone、iPhoneXとかあるけど会話上では普通にiPhoneて呼ぶような感じだと思う
既存の CKA 体験記に書いてなかったこと

2019/4/30 に受けた Certified Kubernetes Administrator (CKA) に合格しました。
<img width="300" alt="5e2bba00ef69935e2c338d5e9eedd075.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10374/b9e3d4d9-c881-a499-05c5-106539d9f5c2.jpeg">

CKA の合格体験記はすでに色々出回っていますが、
いざやってみると新たな気づきがあったのでメモしておきます。

## 準備したこと

- 他の人の体験記をいろいろ読んだ
- Linux Academy の [CKA](https://linuxacademy.com/cp/coursescheduler/view/id/263473) コースをかじってみた
- Linux Academy の [Kubernetes The Hard Way](https://linuxacademy.com/cp/modules/view/id/221) コースをやった

あと仕事で k8s クラスタ管理ツールの開発を行っているので、そこで得られた知識が大きく役に立ちました。
👉 https://github.com/cybozu-go/cke

## 気づき

### 試験前にサポートチャットで色々質問できる

受験者要綱みたいなpdfが英語なのでいろいろ不安になるかと思いますが、
サポートチャットがあるので気になることはそこで聞くことができます。体験記を読み漁る必要は実はありません。

自分の場合だと、知らないレンタル会議室では会場がうるさかったりWiFiが遅かったりする恐れがあるかなという心配から自宅で受験をすることにしたのですが、
万が一にでも部屋にあるテレビや本棚が不正行為だと見なされたら困るなと思いサポートチャットで質問しました。
どちらも部屋にあってOKとのことでした。

気になることは試験当日になる前にチャットで聞いておくと安心です。（ただし英語）


### 試験環境にはあらかじめ慣れといたほうが良い

試験の時はブラウザ上のターミナルで頑張ることになります。
なので IntelliJ や VSCode の Kubernetes 拡張は使えません。
あとターミナルのよくあるショートカット(例えばMacだと `Ctrl+W` で1単語削除)は使えるようになっといたほうが良いです。
ただブラウザのショートカットとのコンフリクトは確認しておいたほうがいいでしょう。ブラウザタブが閉じられたら困るので。

Vimium を有効化しているとブラウザターミナル内の Vim とキーバインドがコンフリクトしてしまうので、
試験が始まる前に Vimium を無効化しておきましょう。(超重要)

このような縛りに近い環境に慣れるには、後述する Linux Academy の講義を受けるという手があります。

### Linux Academy の [CKA](https://linuxacademy.com/cp/coursescheduler/view/id/263473) コースが微妙

Linux Academy という Webinar のサブスクリプションサービスがあって、
その中に [Cloud Native Certified Kubernetes Administrator (CKA)](https://linuxacademy.com/cp/coursescheduler/view/id/263473) という
そのものズバリなコースがあるのですが、これは正直履修しなくてもいいかなと思いました。

というのもCKA取得の役に立たない話が入っているからです。
たとえばこのコースのクラスタ構築は kubeadm なのですが、CKA には kubeadm はおそらく出てきません。
あとどのセクションも本当に初歩の話から始まるのですが、
動画メディアだとそういうパートをスキップしながら進めるのが難しいのでだるいです。
全部真面目にやると16時間くらいかかるらしく、ちょっと時間の無駄かもな〜と思ったので、
各セクションのハンズオンと最後の模試だけ受けてやめてしまいました。

じゃあやめて何をしたのかというと [Linux Academy の Kubernetes The Hard Way コース](https://linuxacademy.com/cp/modules/view/id/221)を履修していました。
これは[本家の Kubernetes The Hard Way](https://github.com/kelseyhightower/kubernetes-the-hard-way/)とほぼ同じ内容なのですが、
いくつか本家よりも良いところがあります。

- ビデオ解説がある。
- Linux Academy の Playground を使えるので GCP に課金せずに済む。
    - この Playground は Linux Academy の定額料金で使える。

ただし最近 Linux Academy の Playground の仕様が変わったらしく、
Kubernetes The Hard Way コースの動画内に出てくる環境と色々違うのは注意ポイントです。
ちょっと困ったのですが、Nginx サーバのインスタンスを小さくしたら
合計 9 unit にギリ収まったのでなんとかなりました。

ちなみに Linux Academy は月49ドルとまあまあ高いので、
資格試験の教材購入を支援してくれる会社の従業員なら一ヶ月だけ会社に買ってもらうのが良いでしょう。
(本家だとGCPを使うことになり、どこからどこまでが教材費なのかわかりづらくて会社に費用申請しにくそう…。


### 試験途中から kube-apiserver のレスポンスが遅くなった

正常動作している k8s クラスタ上で `kubectl` を駆使しながら解く問題がたくさん出題されるのですが、
その k8s クラスタの kube-apiserver のレスポンスが途中から鈍重になったので焦りました。
正確には覚えていませんが、`kubectl get` に 10秒 とかかかっていたような気がする。
しかし試験の最後の方では遅延が解消されていたので謎。

一応試験中に Live Chat で試験監督に相談したのですが、特に助けてはくれませんでした。
APIリクエストに失敗するような障害は起きていなかったので問題を解くことができましたが、
レスポンスが遅くなっても動揺してしまわないように覚悟をしておきましょう。

というか k8s admin としてのスキルを問う試験なのだからこの問題も解決するのが理想的と言えるかもしれませんが、
試験時間がタイトなので試験中に原因究明はしませんでした。

以上です。
herokuにデプロイするときのまとめ

[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしているryota_miraidenshiです。

今回は、djangoアプリケーションをデプロイするときに色々な場面で起きたエラーから、気をつけたいところをまとめておきたいと思います。

#プロジェクト名/urls.pyのimportに関するエラー
これはdjangoのバージョンがdjango2.xを使っていたのにも関わらず、requirementesでdjango1.xになっていたことが原因でした。
つまりdjangoのバージョンの違いで書き方が違ってくるということです。

#プロジェクト名/wsgi.pyに関するエラー
これはwhitenoseに関するものです。
https://qiita.com/ymhr1121/items/344c4eb300ab9972d0c2
このサイトを参考にしてください。

#Procfileに関するエラー
これはデプロイしてもサイトが表示されないときに詰まったとこです。
サイトによっては、

web:gunicorn django_journal.wsgi
web: gunicorn django_journal.wsgi --logfile-

など書いているのもありますが、自分ができたのは

**web: gunicorn django_journal.wsgi**

「web:」の後に半角スペース、「--logfile-」なしでした。


#requirements.txtに関するエラー
pip freeze>requirementes.txt
で現在の環境にインストールされたパッケージとバージョンを書き出すことができますが、いらないものも一緒に含まれてしまってエラーとなってしまいました。
厳選するか、いらないものは消すようにしましょう。

#おわりに
プログラム初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正しますのでどんどん指摘してください。
サブドメインだけが管理下にある状態でLet's Encryptの証明書は取得できるのか？

# 結論
### できる（できた）

# 具体的には
さくらのVPSで```xxxx.vs.sakura.ne.jp```というドメインが与えられますが
この証明書を取得しました。

「サブドメインだけが管理下」と言っているのは、```xxxx.vs.sakura.ne.jp```は自分のサーバーですが
ルートドメイン```sakura.ne.jp```はもちろん自分のものではありません。
言ってしまえば自分が所有していないドメインの証明書が取得できるのかということです。

Let's Encryptで使用しているACMEプロトコルの仕様上は取得したい（サブ）ドメインとLet's Encrypt側が80ポートと443ポートで通信できればいいはずなので、取得できてしまうのではないかと思いましたが、できました。

# エビデンス
テストには[Caddy](https://caddyserver.com/)を使用しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149348/ff4a5d37-87b0-13a0-40f0-29d735ef6163.png)

```
Apr 28 08:14:46 myvps caddy[26121]: 2019/04/28 08:14:46 [INFO] [xxxxxx.vs.sakura.ne.jp] acme: Obtaining bundled SAN certificate
Apr 28 08:14:47 myvps caddy[26121]: 2019/04/28 08:14:47 [INFO] [xxxxxx.vs.sakura.ne.jp] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz/xxxxxxxxxxxxxxxxxxxxxxxx
Apr 28 08:14:47 myvps caddy[26121]: 2019/04/28 08:14:47 [INFO] [xxxxxx.vs.sakura.ne.jp] acme: use tls-alpn-01 solver
Apr 28 08:14:47 myvps caddy[26121]: 2019/04/28 08:14:47 [INFO] [xxxxxx.vs.sakura.ne.jp] acme: Trying to solve TLS-ALPN-01
Apr 28 08:14:53 myvps caddy[26121]: 2019/04/28 08:14:53 [INFO] [xxxxxx.vs.sakura.ne.jp] The server validated our request
Apr 28 08:14:53 myvps caddy[26121]: 2019/04/28 08:14:53 [INFO] [xxxxxx.vs.sakura.ne.jp] acme: Validations succeeded; requesting certificates
Apr 28 08:14:55 myvps caddy[26121]: 2019/04/28 08:14:55 [INFO] [xxxxxx.vs.sakura.ne.jp] Server responded with a certificate.
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149348/84e57a03-3dc3-f4ac-b580-365e79aae034.png)

# おわりに
ACMEプロトコルの仕様上当たり前といえば当たり前なのですが、
明確にできたと書いてる記事が見つからなかったので書きました。
便利ではあるのですが、所有していないルートドメインに対するサブドメインの証明書が取れてしまうのは仕様上想定内なのか気になります。

また、以下の記事ではレートリミットで取得できなかったケースも有るようなので、絶対とは言えませんのでご了承ください。
https://teratail.com/questions/170551
clusterで撮った写真を一括DLする

本日clusterで行われた「さよなら平成カウントダウンライブ UNiON WAVE - clear -」に参加して、いっぱい写真を撮ったのですが、それらをDLする際に、いちいちボタンを押すのがめんどくさかったのでスクレイピングして一括DLするプログラムを作りました。

## 注意
1. 現時点(2019/5/1)で公式に一括DLするシステムが無いためスクレイピングしています。公式に出てきたらそちらを使いましょう。
2. clusterのアカウントをtwitterでログインしている方のみ使えます。そうでない方はプログラムを書き換える必要があります。
3. プログラムを書き換える際はサーバーに配慮したリクエストになるようにしましょう。

## 環境
- Python 3.6

## 使い方
ソースコードを持ってきます

```bash
git clone https://github.com/meihei3/PicDL_cluster.git
cd PicDL_cluster
```

twitterでのログイン情報を入れた`keys.py`を作る

```bash
echo -e "username='your username'\npassword='your password'" > keys.py
```

画像を保存するディレクトリ`img/`を作る

```bash
mkdir img
```

必要な環境のインストール

```bash
pip install -r requirements.txt
```

ダウンローダーの実行

```bash
python downloader.py
```

実行したらこんな感じ↓にchromeで開かれてスクロールすると思います。
![スクリーンショット 2019-05-01 4.57.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280373/c5d9db2c-58d7-3b28-999a-aaba7b1d6385.png)


## プログラムの説明
### やってること
1. selenium driverの設定
2. clusterにログイン
3. ページをスクロールしながら読み込んでDL用のリストの作成
4. ダウンロード

### 1. selenium driverの設定
ChromeDriverを使うための設定をします。（chromeを使う理由はなんとなくです）

```python
from selenium import webdriver
import chromedriver_binary

chromedriver_binary.add_chromedriver_to_path()
driver = webdriver.Chrome()
```

参考：[Python + Selenium で Chrome の自動操作を一通り](https://qiita.com/memakura/items/20a02161fa7e18d8a693)

### 2. clusterにログイン
1.ログインボタンを押す

```python
    driver.find_element_by_class_name('Header__login').click()
```

2.twitterでログインを押す

```python
    driver.find_element_by_class_name('LoginModalDialog__twitter').click()
```

3.twitterにログインする
作成したkeys.pyから`username`と`password`をインポートしてログインします。

```python
from keys import username, password

    # send username
    driver.find_element_by_id('username_or_email').send_keys(username)

    # send password
    driver.find_element_by_id('password').send_keys(password)

    # send submit
    driver.find_element_by_class_name('buttons').submit()
```

4.待つ
ログイン処理に時間がかかるので、適当に待ちます。

```python
    time.sleep(10)
```

clusterにtwitter以外のログイン方法をしている方は2,3を書き換えると良いと思います。

### 3. ページをスクロールしながら読み込んでDL用のリストの作成
cluster内で撮った写真の一覧が見れるページ（https://cluster.mu/account/photos ）に移動します。
このページは表示が必要になるまで画像を読み込まないので、そのままソースコードを取り出してもほぼからです。
なので、forループの中で

```python
driver.execute_script("window.scrollTo(0, {});".format(i * 60))
```
を使ってページをスクロールします。

そして、imgタグからsrcを取り出すと、ほしい画像のサムネイルが取れます。
ほしい画像のurlと、そのサムネイルのurlは`files`が`updated`になり、`/thumbnail.png`が`.png`になる程度の違いなのでreplaceしていきます。

```python
def thumbnail_to_large_img(url_text: str) -> str:
    return url_text.replace("files", "uploads")[:-14]+".png"
```

### 4. ダウンロード
先程のurlをリスト化してforループでダウンロードしていきます。
この時、time.sleepでちょっと待ちながらダウンロードしていきましょう。

```python
def download_img(url: str):
    r = requests.get(url, stream=True)
    if r.status_code == 200:
        with open("img/"+url.split('/')[-1], 'wb') as f:
            f.write(r.content)

for url in tqdm(dl_list):
    download_img(url)
    time.sleep(1)
```

この時`img`を指定のパスにすれば保存したい場所に保存することが可能です。
参考：[python3のrequestsを使って画像を保存](https://qiita.com/pollenjp/items/0c39c35120cd60575647)

## ソースコード
[こちら](https://github.com/meihei3/PicDL_cluster)
VueでKonva.jsとcanvasを使ってお絵描き（その2）

[その1はこちら](https://qiita.com/Butterthon/items/2b3f4608a9f07c099c77)

# キャンバスに画像を表示する
親のCallCanvas.vueから、子のFreeDrawing.vueに画像ファイルパスを渡して、それをキャンバスに表示してみます。

まず、親のCallCanvas.vue。
親のテンプレートに記載したFreeDrawingタグに、子のpropsに定義した「backgroundImage」を追記し、
そこに値を指定します。
今回は算出プロパティ「imageFile」を用意し、それを値に指定してます。
（require()を使って渡さないと画像を表示できないとこでハマりました。。。）

```src/paint.CallCanvas.vue
<template>
    <div>
        ...
        ..
        .
        <FreeDrawing 
          :backgroundImage="imageFile"
        />
    </div>
</template>

<script>
import FreeDrawing from './FreeDrawing.vue'

export default {
  name: 'CallCanvas',
  ...
  ..
  .
  computed: {
    imageFile: function () {
      return require('../assets/reiwa.png');
    }
  }
}
...
..
.
```
  
  
次に子のFreeDrawing.vue

```FreeDrawing.vue
<template>
  <div>
    <div ref="container">
      <canvas
        :width="width/2"
        :height="height/2"
        ref="canvas">
      </canvas>
    </div>
  </div>
</template>

<script>
import Konva from 'konva'

export default {
  ...
  ..
  .
  data: () => ({
    ...
    ..
    .
    /** 追加 */
    imageObj: null,
    backgroundLayer: null,
    backgroundImageScope: null
  }),
  mounted: function () {
    ...
    ..
    .
    /** 追加 */
    this.imageObj = new Image()
    this.imageObj.addEventListener('load', this.imageOnload)
    this.imageObj.src = this.backgroundImage
  },
  methods: {
    ...
    ..
    .
    /** 追加 */
    imageOnload: function () {
      // 背景レイヤ
      this.backgroundLayer = new Konva.Layer()

      // 背景イメージ（xとy座標はthis.drawingScopeと同じにする）
      this.backgroundImageScope = new Konva.Image({
        image: this.imageObj,
        x: this.width / 4,
        y: 5,
        width: this.canvas.width,
        height: this.canvas.height
      })
      
      // 背景レイヤに背景イメージを追加
      this.backgroundLayer.add(this.backgroundImageScope)
      this.stage.add(this.backgroundLayer)

      // 背景イメージを最背面に移動。これをしないとペンの描画が画像の下に潜ってしまう。
      this.backgroundLayer.moveToBottom()
    }
  },
  ...
  ..
  .
}
</script>
```
  
サーバー起動して確かめます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357470/e9e676a4-6577-ee8a-8778-edff9d0d57bd.png)

表示できました、描画もできます。
また、画像がキャンバスサイズより大きい場合は、キャンバスサイズに縮小されますし、
小さい場合は拡大されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357470/e6cf1ed7-30e6-b550-4fe2-7af780f54973.png)
  
  
その3はモードをペンと消しゴムで切り替えられるようにしてみます。
[その3：モード および ペンの色切り替え、キャンバスのクリア](https://qiita.com/Butterthon/items/c6a9084711444aed0458)
Apollo Clientで__typenameの自動生成を無効にする方法について

AngularでApllo Clientを使っていて、__typenameが意図しないものになる事があります。
こうなるとGraphqlQLの呼び出しが失敗します。
意図した__typenameを付ける方法を調べたのですが分かりませんでした。

# 対象のコード
Angular側では、graphql-tagを使って以下のように定義しています。

```typescript:sample.ts
  private readonly saveSiteConfigMutation = gql`
    mutation savesiteconfig($savesiteconfig: SaveSiteConfig!) {
      savesiteconfig(savesiteconfig: $savesiteconfig) {
        result
        message
      }
    }
  `;
```

期待としては、__typenameにはSaveSiteConfigが設定されて欲しいのですが、何故だかSiteConfigとなってしまいます。

# 回避方法
そもそも__typenameは必要ないんだよなということで調べて見たら、https://github.com/apollographql/apollo-client/issues/1913 を見つけました。
希望通り、__typenameを付けない方法です。

```typescript:sample.ts
    apollo.create({
      link,
      cache: new InMemoryCache({
        addTypename: false
      })
    });
```

これが正解なのか分かりませんが、問題は解決しました。

令和最初のQiita投稿でした。
令和元年🎉 JavaScript International Date フォーマットで和暦を表示させるには

この記事はこちらのページに移動しました。
https://qiita.com/girlie_mac/items/484ca063cf547b4a61fd

---
さようなら Slack。でも　Slack 関連の記事は残しておきたいのでアカウントを変えました。なので一般の記事は新しいアカウントに移動しました。