OmniAICreator/Qiita-1.07M huggingface dataset:
Adobe CCライブラリで管理しているアイコンをSVGで一括エクスポートしたい

# ベクターアイコンのデータ管理方法

サービス上で使われるアイコンなどのデザインデータをみなさんはどのように管理していますか？

ベクターアイコンなどの元データは大抵の場合、 Illustrator（.ai） ファイルであって、デザイナーのみなさんは Adobe Creative Cloud ライブラリ（以下CCライブラリと表記）を使って管理していることが多いかと思われます。

CCライブラリに登録して共有すればアイコンデータを一元管理でき、 Photoshop でも Illustrator でも XD でも呼びだすことができ、元データを編集すれば各アプリケーションの参照も自動で更新されるのでとても便利です。

# CCライブラリに登録されてるアイコンデータをSVGファイルで欲しい…！

フロントエンドエンジニア的には、デザインを実装に落とし込む段階でアイコンデータをSVGに変換します。Webで取り扱うベクターデータといえばSVGだから、ということもありますが、

- SVGファイルから iconfont を使ってWebフォントを生成
- SVGファイルから svgsprite を使ってスプライト画像ファイルを生成

のように、タスクランナーを使ってデータ処理をするときもソースファイルがSVGであった方が都合が良いからです。
なので、CCライブラリに登録されてるアイコン群をSVGで一括エクスポートしたいなぁ…と思いつつも、実はこの機能がどこにも見当たらない…！（2019年9月現在）

# CCライブラリに登録されてるベクターデータは余白情報を持たない

アイコンコンポーネントとしてSVGを取り扱う時、縦長や横長のデザインのアイコンであっても正方形グリッドの中に配置して処理されることが多いです。アイコンごとに縦横比が違うとコンポーネントとして取り扱いにくくなるためです。
つまり、正方形の縦横幅で余白を含めてSVGファイルとして出力する必要があります。

しかし、XDファイルに貼り付けられたCCライブラリを個別にSVGエクスポートすると、ベクターデータの実体の縦横幅で出力されます。
これはCCライブラリに登録されてるデータがアートボード情報を持っていても同様です。
SVGエクスポート後に毎回余白情報を手動で付与するのはちょっとメンドイ…

# フロントエンドエンジニア向けのアイコンセットファイルを作る

- フロントエンドエンジニアもデザイナーのCCライブラリ一元管理の恩恵に預かりたい
- アイコンデータをCCライブラリから一括でSVGファイル出力したい
- SVGファイルの余白情報はフロントエンドエンジニア側でコントロールしたい
- これらの設定をプロジェクトチームで共有したい
 
上記を同時に満たす方法として、フロントエンドエンジニアでWebサイト管理用のaiファイルを作るのが良さそうでした。ちなみに illustrator を使いますが、必要最低限の設定とSVGジェネレータとしての利用なので、illustrator スキルはほぼ不要です。
その作成手順を紹介していきます。

## 1. 新規作成 > 詳細設定 でテンプレート用のアートボードを設定する

設定は以下のような値を設定します。

- `アートボードの数` 40（設定するアイコンの数）
- `間隔` 4px （お好みで。縦横の1/8くらいがちょうど良いかも）
- `横列数` 10 （お好みで）
- `幅` `高さ` 32px （Webデザインの実寸に合わせておくと良い）
- `カラーモード` RGB

![illustrator-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99076/d41f3791-051e-09f4-4231-8e9a11bb4e94.png)

作成をすると以下のような画面になります
![illustrator-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99076/305e884c-ef9f-637f-29bf-cb35e6ce9a94.png)

## 2. CCライブラリから管理したいアイコンをアートボードに配置する

【注】事前にデザイナーから該当のアイコンが格納されているCCライブラリを共有してもらう必要があります。
CCライブラリからアイコンのデータをドラッグ＆ドロップで先ほどのアートボードに配置していきます。

![illustrator-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99076/810fe2b9-5d03-10e6-ca06-c7b1243f7542.png)

こうすることでデザイナー側でCCライブラリのアイコンを更新すると、このaiファイルにも自動で更新が反映されます。

## 3. アートボードに名前をつける

アートボードの名前は最終的に出力されるファイル名にもなるので、ファイル名＝タスクランナーを中継したclass名になることなども考慮して名前を入力します。

![illustrator-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99076/b2497519-1bdb-2d44-3626-0ca84feef90c.png)

## 4. 一括でSVGファイルを出力する

別名で保存を選択して、保存オプションを以下のようにして保存します。

- 出力対象のフォルダを指定
- `ファイル形式` SVG（svg）を選択
- `アートボードごとに作成` をチェック
- `範囲` 先ほど名前を追加したアートボードの範囲を指定

![illustrator-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99076/4f8dbde9-bdae-b897-a5fc-d5c016cfbfd4.png)

出力対象のフォルダ以下に範囲で指定したアートボード名前が付与されたSVGファイルたちが出力されます。

## 5. テンプレートaiファイルを共有する

プロジェクトの共有フォルダやCCファイル、リポジトリなどに作成したテンプレートaiファイルを格納してプロジェクトメンバーと共有することで、毎回XDファイルからSVGファイルをエクスポートしたり余白設定をやり直したりする必要がなくなり、再利用性が高まります。

# この手法のメリット

- CCライブラリのデータを一定のルールで一括SVGファイル出力できる
- XDファイルからアイコンを切り出す際のワークフローとして機能する
- テンプレートaiファイルを中間に置くことで、フロントエンドエンジニア側で必要とする情報を取捨選択した上で集約管理できる
- デザイナーは従来の管理方法を変えることなく、フロントエンドエンジニア側の管理方法に強制されない
- Webサイトで利用されるアイコンのカタログとしても機能する

といった点が挙げられます。
作業者ごとにXDファイルから個別にエクスポートされている方、ぜひ試してはいかがでしょうか。
bash も TDD が簡単に出来る

## TDD
テスト駆動飲み会で bash による テスト駆動 を体験して感動した

+ [イベントページ](https://tddrinking.connpass.com/)
  + [makowさんによる体験記](https://makow.hatenablog.com/entry/2019/08/27/000235)

## 飲み会が始まって
[cyber-dojo](https://cyber-dojo.org/) を見て **bash, bats** の選択肢にわくわく！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244948/0d9e2e6f-5469-cf91-ff87-a28eb3083443.png)

## Fizz Buzz やってみた
ここからは 記憶を頼りにした再現してみる 感動を追体験できるかな

### 1 のとき 1

```bash:test
@test "1 is 1" {
  local actual=$(answer 1)
  [ "$actual" == "1" ]
}
```

```bash:product
answer()
{
  echo 1
}
```


### 3 のとき Fizz

```bash:test
@test "3 is Fizz" {
  local actual=$(answer 3)
  [ "$actual" == "Fizz" ]
}
```

```bash:product
answer()
{
  if [ $1 == 3 ]
  then
    echo Fizz
  else
    echo 1
  fi
}
```

### 3 の倍数のとき Fizz

```bash:test
@test "6 is Fizz" {
  local actual=$(answer 6)
  [ "$actual" == "Fizz" ]
}
```

```bash:product
answer()
{
  if [ $(($1 % 3)) == 0 ]
  then
    echo Fizz
  else
    echo 1
  fi
}
```

### 5 の倍数のとき Buzz

```bash:test
@test "5 is Buzz" {
  local actual=$(answer 5)
  [ "$actual" == "Buzz" ]
}
```

```bash:product
answer()
{
  if [ $(($1 % 3)) == 0 ]
  then
    echo Fizz
  elif [ $(($1 % 5)) == 0 ]
  then
    echo Buzz
  else
    echo 1
  fi
}
```

### 15 の倍数のとき FizzBuzz

```bash:test
@test "15 is FizzBuzz" {
  local actual=$(answer 15)
  [ "$actual" == "FizzBuzz" ]
}
```

```bash:product
answer()
{
  if [ $(($1 % 3 + $1 % 5)) == 0 ]
  then
    echo FizzBuzz
  elif [ $(($1 % 3)) == 0 ]
  then
    echo Fizz
  elif [ $(($1 % 5)) == 0 ]
  then
    echo Buzz
  else
    echo 1
  fi
}
```

### 後略

- このままだと 2 のとき 1 が返ってくるとか
- 1 から 100 までのループとか
- 0 や 101 の考慮とか

## 飲み会が終わって
- 沢山飲んだ、コーラをコップで１０杯くらい貰いました
  - 飲めない人に強要する人もいないし良い飲み会ですよー
- 今回使ったテストフレームワーク
  [Bats: Bash Automated Testing System](https://github.com/sstephenson/bats)
  - 結構直感でテストの書き方が想像ついた
  - 皆が知ってる言語なのにテストを書いた経験者ゼロだった
  - 今後は bash も安心してリファクタリングできる
- たのしい

おしまい
aspellがHigh Sierraで動かない

# 失敗の状況
high sierraにbrew installでaspellを入れたが，aspellで起動すると，

```
> aspell
dyld: Library not loaded: /usr/local/lib/libaspell.15.dylib
  Referenced from: /usr/local/bin/aspell
  Reason: image not found
fish: 'aspell' terminated by signal SIGABRT (Abort)
```
なるエラー．直接symbolic linkで入れようとしたら，

```
> aspell
dyld: Library not loaded: /usr/local/lib/libaspell.15.dylib
  Referenced from: /usr/local/bin/aspell
  Reason: no suitable image found.  Did find:
	/usr/local/lib/libaspell.15.dylib: mach-o, but wrong architecture
	/usr/local/lib/libaspell.15.dylib: stat() failed with errno=1
	/usr/local/lib/libaspell.15.dylib: mach-o, but wrong architecture
	/usr/local/Cellar/aspell/0.60.7/lib/libaspell.15.dylib: mach-o, but wrong architecture
	/usr/local/Cellar/aspell/0.60.7/lib/libaspell.15.dylib: mach-o, but wrong architecture
fish: 'aspell' terminated by signal SIGABRT (Abort)
```
でなんか，dylibのtargetがあってなさそうなエラー．

portで入れようとしたが，proxyの関係でlistが取れない．

Excalliburも古すぎてだめ．皆さんはどうしてられるのでしょう．

まわりに今はmentarがいないんで，仕方がないんで，compile.

# compileは辞書もね
```
http://aspell.net
```
からaspell-0.60.7.tarとaspell6-en-2018.04.16-0.tar.bz2をDL.

それぞれのdirectoryで

```
> ./configure
> make
> make install
```
したら/usr/local/に入れてくれる．
dictionary dirでもcompileしないとだめ．

```
> aspell dump dicts  
en
en-variant_0
en-variant_1
en-variant_2
en-w_accents
...
```

で確認できる．

en_USは

```
> cat ~/.aspell.conf 
lang en_US
```
です．

# 役に立った参考サイト
- https://nanasi.jp/articles/others/aspell.html#download-mac

# おまけの使い方
久しぶりに使ったら全く忘れてた．

```
r: 修正を自分で入力する．
i: スペルミスとされた単語を正しい単語として個人辞書に登録する．
a: スペルミスとされた単語をそのセッション中のみ正しい単語として通す．
x: スペルチェックを終了する．
X: スペルチェックを中断する．この場合，M-x ispell-continue で再開できる．
q: スペルチェッカを kill する．
space: 特に何もせずに通過する．
```

候補を選ぶときは数字でね．

# personal user dictionary
emacsからうまく自動登録できないね．
ispellの終わりに保存してくれたはずなんやけど．．．

init.elに

```
;; ispell or aspell                                                                                                     
(setq ispell-personal-dictionary "~/.aspell.en_US.pws")
```
と書いたが，自動読み込みも，保存もしてくれない．
aspellでの設定かと思い，色々試して見て．．．
以下は一応動いている．

```
> aspell -p ~/.aspell.en_US.pws  --lang=en -t list < README_e.org
```

```
> aspell --lang=en dump config personal
.aspell.en.pws
```
となっているんやけどね．
Linuxにおける基礎的理解

LinuxはOSである。

OSの有名どころだとwindowsとか、それの一種。どんな役割かっていうとハードウェアとソフトウェアをつなげる存在として認識すればよろしい。つまるところカーネルである。体と筋肉だけあってもなんにも作用しないけど脳があれば自由に動かせるみたいな認識で覚えた。
ちなみに、OSの例としてWindowsを挙げたがLinuxはオープンソフトウェア。つまり有料でなかったりする。ネットに存在するイロイロを組み合わせて作ったって解釈している（合ってるかは微妙？）

カーネルについて
先述したカーネルとはソフトウェアで、ハードウェアを動かしているソフトウェアである。
ソフトウェアを筋肉や臓器と捉えると、カーネルは脳に近く、肉体であるハードウェアを脳であるカーネルが各筋肉各臓器各器官に命令し、動かしている。みたいなイメージで考えている。
![images.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488176/dfd6f4a0-8cfe-3dd3-9287-94557a1d964a.jpeg)
![images (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488176/b3d6adb9-bc56-3737-8096-d925715f6e72.jpeg)

じゃあどんなのを動かしているかっていうと、以下に大まかにまとめてみる。
・CPU
PCにおける脳みたいなもの。
・メモリ
メモリ、つまるところCPUが動作をするための命令だったりデータを管理をしている。これは電源が落ちるとその記憶がなくなったりする。そのため以下のモノもある。
・ディスク
消えたりしたら困るものを記憶しておくモノ。つまりデータの二次記憶装置。これのコントロールもカーネルの仕事。

・タスク管理
タスクマネージャーのタスク。
システム機能の管理も仕事。

今日はここまで
MacOS MojaveでAllenNLPのインストールを失敗した話

## はじめに
**AllenNLP**はいいぞ、、、 と聞いたので早速使ってみよう！としたらインストールに詰まったので原因と解決法です。インストール時に必要となる <u>jsonnetをビルドする際に失敗する</u> という問題ですが、結論から言うと、

* **低いバージョン(High Sierra等)からのMacOS Mojaveへのアップグレードする際のC++ヘッダーの自動インストール漏れ**

が原因です(元からMojaveがインストール済のMacBookの友人はすんなりインストールできたらしい、、、)。限定的な想定ですが、**今後のMac OS Xのメジャーアップデートでも似た問題が発生する可能性はある**ので、また調べ直さないように記事にします。
※OSの仕様による問題なのでMacの人向けです

## 問題
いろいろな導入方法があるのですがAnacondaを使ったやり方にします。

```shell
$ conda create -n allennlp python=3.6
# 3.6系最終版である3.6.9が勝手に指定されてインストールされます
$ conda activate allennlp
# 環境を切り替え
(allennlp) $ pip install allennlp
```

[AllenNLP公式github](https://github.com/allenai/allennlp)の説明では、「まっさらなPython3.6の環境を作って`pip install`すればいいよ！！」って書いてあるので実行します。

```
...
Building wheel for jsonnet (setup.py) ... error
ERROR: Complete output from command //anaconda3/bin/python -u -c 'import setuptools, tokenize;__file__='"'"'/private/var/folders/q3/t9f6dwcd7qbfwhp4h3tn4ffm0000gn/T/pip-install-7bksxwcr/jsonnet/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /private/var/folders/q3/t9f6dwcd7qbfwhp4h3tn4ffm0000gn/T/pip-wheel-ab5wiufe --python-tag cp37:
ERROR: running bdist_wheel
running build
running build_ext
c++ -c -g -O3 -Wall -Wextra -Woverloaded-virtual -pedantic -std=c++0x -fPIC -Iinclude -Ithird_party/md5 -Ithird_party/json core/desugarer.cpp -o core/desugarer.o
c++ -c -g -O3 -Wall -Wextra -Woverloaded-virtual -pedantic -std=c++0x -fPIC -Iinclude -Ithird_party/md5 -Ithird_party/json core/formatter.cpp -o core/formatter.o
...
```
**失敗します。** なんかC++周りでエラーが出てる？？？Pythonなのに？？？(情弱並感)

## 解決法
ググって見るとこの問題は割とよく起こっているみたいで、[AllenNLPのGithub Issue](https://github.com/allenai/allennlp/issues/2779)でも話題に上がっています。このIssueによると[GoogleのjsonnetのIssue](https://github.com/google/jsonnet/issues/570)が参考になるよ!って書いてあります。さらにこの記事では[このStackOverflow](https://stackoverflow.com/questions/52509602/cant-compile-c-program-on-a-mac-after-upgrade-to-mojave)が役に立つよ！って書いてありました。~~たらい回しにしないで答えを書いて♡~~

どうやら**Mojave向けのC++のヘッダーがインストールされていない**ために参照エラーが発生しているらしく、

```shell
$ open /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg
```

でヘッダーをインストールすれば解決するそうです。パッケージインストーラーが起動して指示通りに進めればOKです。自分はこの方法で解決しました。
インストールが終わって仮想環境内で`pip install allennlp`すれば晴れてAllenNLP導入完了です！！

## 余談
もしヘッダーのパッケージ(macOS_SDK_headers_for_macOS_10.14.pkg)が見つからない場合はDLする必要があるみたいですが、その方法は次の記事で紹介されています。

* [【macOS Mojave】macOS MojaveにアプデしたらCのヘッダーファイルが読み込まれなくなった件-空飛ぶセロ弾き](http://kane-please.hatenablog.com/entry/2018/11/07/001823)

こちらの記事によると、
>そもそも，macではCやC++のコンパイラはXCode由来のようで，OSアプデをした後にXCodeもアプデをしたのですが，そのアプデ内容に 「Mojave用のmacOS SDK headerがデフォルトで入っていないのが原因」みたいです．

普段からC++を書いてる人は気づきそうですがC++環境が元からインストールされている環境をバックエンド的に使ってると気づきませんね、、、

## まとめ
* C++によるパッケージビルド時のヘッダー参照エラーが原因
* この問題はMojaveでC++を使ってビルドする他のパッケージでも起こりうる
* 手動でヘッダーをインストールすれば解決
* アップグレード時に自動でされるはずのパッケージインストールがされていないのが根本の原因
* 今後のメジャーアップデート時にも似た問題が起こるかもしれない
Azure KeyVaultを使って秘密情報を扱う

# はじめに

コンテナを起動するときに、環境変数で振る舞いを与えるわけですがCOSMOSDBのキーとかContainerレジストリのパスワードなどを渡す場合もあるかと思います。

AzureContainerInstances(ACI)だとこんな感じで色々秘密のものを指定しないといけません。

```
az container create -g myResourceGroup \
   --name poc-web \
   --image test.azurecr.io/web \
   --ip-address public \
   --registry-username [秘密秘密]\
   --registry-password [秘密秘密] \
   --ports 80 \
   --dns-name-label poc \
   --environment-variables SPRING_PROFILES_ACTIVE=development \
   COSMOSDB_KEY=[秘密秘密] \
   COSMOSDB_URI=https://test.documents.azure.com:443/ \
   COSMOSDB_DATABASE=test
```

これをKeyVaultというサービスを使って解決しましょう。
AWSでいうとKMSに似てますね。

# KeyVaultの作成

これだけです。KEYVAULTの名前を環境変数に入れているのはこの後たくさん指定するからというだけです。

```
export KEYVAULT=mykeyvault
az keyvault create -g myResourceGroup -n $KEYVAULT
```

# KeyVaultに秘密情報を隠す

たとえばregistryのパスワードを隠すときはこんな感じです(値はダミーです）

```
az keyvault secret set --vault-name $KEYVAULT \
                       --name registry-password \
                       --value 1234567890
```

ちゃんと確認できたかはshowコマンドで確認しましょう

```
az keyvault secret show --vault-name $KEYVAULT -n registry-password --query value -o tsv
1234567890
```

# ACIのコマンドに組み込む

```
az container create -g myResourceGroup \
   --name poc-web \
   --image test.azurecr.io/web \
   --ip-address public \
   --registry-username $(az keyvault secret show --vault-name $KEYVAULT -n registry-username --query value -o tsv) \
   --registry-password $(az keyvault secret show --vault-name $KEYVAULT -n registry-password --query value -o tsv) \
   --ports 80 \
   --dns-name-label poc \
   --environment-variables SPRING_PROFILES_ACTIVE=development \
   COSMOSDB_KEY=$(az keyvault secret show --vault-name $KEYVAULT -n cosmosdb-key --query value -o tsv) \
   COSMOSDB_URI=https://phrdb.documents.azure.com:443/ \
   COSMOSDB_DATABASE=phrdb
```

# その他のコマンド

## KeyVaultに格納された値一覧

```
az keyvault secret list --vault-name $KEYVAULT --query [].id
```

## 値を消す

```
az keyvault secret delete --vault-name $KEYVAULT -n registry-username
```

# さいごに

* ACIで秘密情報を扱うだけであればYaml形式でデプロイするときにsecureValueを使えばできます。こちらは無料です
    * https://docs.microsoft.com/ja-jp/azure/container-instances/container-instances-environment-variables#secure-values
* KeyVaultはどこにでも組み込むことができるのであえて紹介してみました。


# 参考

* [KeyVaultの料金](https://azure.microsoft.com/ja-jp/pricing/details/key-vault/)
【初心者】pythonで０から Project Euler を解いてみた 18,67

おはこんばんにちわ！！
夏休み終わりました。地元の花火大会の日私はコンビニでカップルのレジをピッピピッピやってましたよ（泣）:rage:
今回はeuler18と67を解くわよ！
問題文はここみなさい！！
18問目
http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2018
67問目
http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2067
今回はアルゴリズムが同じなので一緒に作っちゃう💛
####アルゴリズム
まずはこれぇ！
![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452390/ab0a6727-6977-bc1b-87e6-5b2829243b0c.png)
まず、スカートをめくるようにしたから見ていくわよっ！！
2と4を比べて大きいほうを一つ上のものに足していくわ！
少し難しく書くとlist使って
list[2][0]とlist[2][1]をくらべるのよ
ちなみに今回二次元配列を使ってくわ❕
![無題3png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452390/435277a7-24f4-b592-c1d5-75f07410deb3.png)
次に青のところを比べて大きいのを上に足すわ！！
そしたら7と4が11と10になったの、わかるぅ？？
![無題4png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452390/ed9ed42f-8997-e82e-a41f-f4fc124d7d10.png)
そしたら私のだいすきなピンクちゃんの11,10を比べて大きいのを足して完成だわ！！:kissing_heart:
####コード:kiss:
```python
pro = """75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23"""
pro = pro.strip().split("\n")
for i in range(len(pro)):
    pro[i] = pro[i].strip().split(" ")
    pro[i] = [int(x) for x in pro[i]]
num = []
ne_num = 0
for x in range(len(pro)-1,0,-1):
    for y in range(len(pro[x])- 1):
        pro[x-1][y] += max(pro[x][y],pro[x][y+1])
print(pro[0])
```

```python
pro = pro.strip().split("\n")
for i in range(len(pro)):
    pro[i] = pro[i].strip().split(" ")
    pro[i] = [int(x) for x in pro[i]]
```
ここで一つ一つをリストの要素にして二次元配列にするわ！！
ここ大切💛私ここで一日悩んで結局調べてしまったわ(泣)

```python
num = []
ne_num = 0
for x in range(len(pro)-1,0,-1):
    for y in range(len(pro[x])- 1):
        pro[x-1][y] += max(pro[x][y],pro[x][y+1])
print(pro[0])
```
ここでさっきのアルゴリズムの登場だわっ！
range(len(pro)-1,0,-1): で赤い矢印の役目をはたしているわっ！！！
二重ループ使ってガンガンゴリゴリ計算していくわっ！！！
そして最後にlist[0]が答えになるってわけ💛:kiss:
どぉ？？みんな分かったぁ？？
67問目コードも載せ解くわ💛

```python
txet_deta = open("triangle.txt")
txet = txet_deta.read()
txet = txet.strip().split("\n")
for x in range(len(txet)):
    txet[x] = txet[x].strip().split(" ")
    txet[x] = [int(y) for y in txet[x]]
#print(txet)
for i in range(len(txet)-1,0,-1):
    for n in range(0,i):
        txet[i-1][n] += max(txet[i][n],txet[i][n+1])
print(txet[0])
```
やり方は一緒よ💛
みんな頑張のよ💛
###みんなも暑さには気を付けるのよ！
####水分補給しなさいね！！
python Bottle chrome icon エラーが出たとき!

# python Bottle chrome icon エラーが出たとき!

>Failed to load resource: the server responded with a status of 404 (Not Found)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274715/6e637672-6f4b-b44a-c0c9-f9d16c235b6d.png)

なんとも気分の悪いエラーである。
「icoファイルがないというエラー」
icoファイルを作ったけどどこに入れればいいの!
解決方法いろいろあるが、Bottleの立場に立って考えよう。

```bottle.py
from bottle import *
@route('/favicon.ico')
def favcon():
    return static_file('favicon.ico', root='./static')
```
favicon.icoを呼びに来た時にstaticフォルダの下に置いたicoをロードしてあげよう。

```
C:.
│  app.py
│  bottle4j_ico.pyproj
│  bottle4j_ico.pyproj.user
│  requirements.txt
│  routes.py
├─static
│  │  favicon.ico ### ここにICOファイルを配置
│  ├─content
│  │      bootstrap-grid.css
│  │      bootstrap-grid.css.map
│  │      bootstrap-grid.min.css
│  │      bootstrap-grid.min.css.map
│  │      bootstrap-reboot.css
│  │      bootstrap-reboot.css.map
│  │      bootstrap-reboot.min.css
│  │      bootstrap-reboot.min.css.map
│  │      bootstrap.css
│  │      bootstrap.css.map
│  │      bootstrap.min.css
│  │      bootstrap.min.css.map
│  │      jumbotron.css
│  │      site.css
│  │
│  ├─fonts
│  │      glyphicons-halflings-regular.eot
│  │      glyphicons-halflings-regular.svg
│  │      glyphicons-halflings-regular.ttf
│  │      glyphicons-halflings-regular.woff
│  │
│  └─scripts
│          bootstrap.bundle.js
│          bootstrap.bundle.js.map
│          bootstrap.bundle.min.js
│          bootstrap.bundle.min.js.map
│          bootstrap.js
│          bootstrap.js.map
│          bootstrap.min.js
│          bootstrap.min.js.map
│          jquery-1.10.2.intellisense.js
│          jquery-1.10.2.js
│          jquery-1.10.2.min.js
│          jquery-1.10.2.min.map
│          jquery.validate-vsdoc.js
│          jquery.validate.js
│          jquery.validate.min.js
│          jquery.validate.unobtrusive.js
│          jquery.validate.unobtrusive.min.js
│          modernizr-2.6.2.js
│          respond.js
│          respond.min.js
│          _references.js
│
├─views
│      about.tpl
│      contact.tpl
│      index.tpl
│      layout.tpl
│

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274715/ed70505b-c2fc-b099-d4ad-cae7f24fc3d4.png)

はい消えたよ!
「いいよね」してね。
JIRA フィールドに値が入ったら別のフィールドに値を自動セット


##あるフィールドに値がセットされたら別のフィールドに指定した値を自動セットする

あるフィールドAにXXXと入れたら、別のフィールドBにyyyと自動でセットしたい場合、JIRAのワークフロートランジションの事後操作で、「Set field as a function of other fields」を使うとよい。

① Field to be checked for matching with type 1 setting rules:
　に元となるフィールドAを指定する。

②Target field to be set:
　に反映先のフィールドBをセットする。

③Setting rules:
　で反映ルールを記述する。
　　　(フィールドAの値)フィールドBの値
　　例：XXXと入れたらyyyをセット、YYYと入れたらzzzをセット
　　　(XXX)yyy
　　　(YYY)zzz
　　　　:
  ※Setting ruleではStringだけでなくNumericも扱えます。簡単な演算も入れられるようです。

④更新ボタンを押下、ワークフローの発行を行って反映する。


*JIRA Softwareバージョンは7.12.1*
Databindingで下に重なっているViewにタッチイベントを送らないようにする

タイトル以上でも以下でもないので、早速本題に

### BindingAdapterの定義

```kotlin:ViewBinding.kt
@BindingAdapter("app:touch_block")
fun setTouchBlock(view: View, isBlock: Boolean) {
    view.setOnTouchListener { _, _ -> isBlock }
}
```
*onTouch* の戻り値をレイアウトから指定できるようにする

### レイアウトでの指定方法
```layout.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <android.support.constraint.ConstraintLayout
        android:id="@+id/upper_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:touch_block="@{true}"    // ← ココ
        ...
```
これで *id/upper_layout* の下に重なっているViewにタッチイベントが送られなくなりました。
細かい条件は指定できないので割り切りでタッチイベントを送りたくないという場合には使えそう。

`app:touch_block="@{true}"` を `app:touch_block="@{viewModel.touchBlock}"` とすればアプリの状態に応じてタッチイベントを *送る/送らない* くらいの制御はできそうです。

```layout.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="viewModel"
            type="com.hoge.SampleViewModel" />
    </data>

    ...

    <android.support.constraint.ConstraintLayout
        android:id="@+id/upper_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:touch_block="@{viewModel.touchBlock}"    // ← ココ
        ...
```
```SampleViewModel.kt
SampleViewModel : ViewModel() {
    val touchBlock = ObservableBoolean(true)

...
}
```
SQL Developper ストアド　作成

### 環境
Microsoft SQL ServerManagementStusio 18

###書き方
```  insert用.sql
CREATE PROCEDURE [dbo].[テーブル名_insert]
 @ID AS nvarchar (20),
 @Time AS numeric (6)
AS
INSERT INTO テーブル名(
 ID,
 Time
)
SELECT
 @ID,
 @Time
```

```  update用.sql
CREATE PROCEDURE [dbo].[テーブル名_update]
 @ID AS nvarchar (20),
 @Time AS numeric (6)
AS
UPDATE テーブル名
SET
 ID = @ID,
 Time = @Time

WHERE ID = @ID
``` 
### 手順
1. 新しいクエリ(Ctrl+N)作成
2. insert or update　ペーストして実行
3. [データベース]/プログラミング/ストアド プロシージャ に作成されている

### 参考

[SQL Server ストアドプロシージャの書き方](https://qiita.com/RollSystems/items/d32073cd8965db9cf765)
[Swift] Arrayに入ったstructの特定のプロパティの重複を削除したい distinct 

例えば

```swift
struct Receipt {
   let buyer: String
   let product: String
   let date: Date
   let price: Int
}
```

というデータの配列があった時、buyerプロパティだけ重複を取り除くという時に使います。

Arrayのextensionとして実装しました。

```swift
extension Array {
    func distinct<Value: Hashable>(keyPath: KeyPath<Element, Value>) -> Array {
        var set = Set<Value>()
        return filter { set.insert($0[keyPath: keyPath]).inserted }
    }
}
```

使い方は単純に

```swift

let receipts: [Receipt] = // ここに入ってる

receipts.distinct(keyPath: \.buyer)
```
とするだけです。
簡単ですね。

ちょっと複雑に「各々の人について最も高い買い物の商品名順リスト」を取得するには

```swift
let receipts: [Receipt] = // ここに入ってる

let expensiveList = receipts
    .sorted { $0.price > $1.price }
    .distinct(keyPath: \.buyer)
    .sorted { $0.product < $1.product }
```
という感じになります。

すっきり。
Oracle で 新規USER を作成し、impdp するまでの手順、メモ書き

Oracleを使った開発環境構築時に良く忘れて、手間がかかるのでメモ書き。

Oracle SQL Developerを使用して実行を想定。impdpだけコンソールから実行している。

## ユーザー作成
まずはユーザー作成。

```sql
CREATE USER [USER_NAME] IDENTIFIED BY "password";

--実際の入力例
CREATE USER TARO IDENTIFIED BY "TAROpassword";

--（おまけ）パスワード間違ってしまい変更したいときは以下を実施
--ALTER USER TARO IDENTIFIED BY "TAROpassword";

```

## 権限の付与
以下、必要最低限の権限をGRNT文で付与する。

```sql
--テーブル作成権限
GRANT CREATE TABLE TO [USER_NAME];
--データベースインポート（フル）権限
GRANT IMP_FULL_DATABASE TO [USER_NAME];
GRANT CREATE_ANY_DIRECTORY
--ディレクトリオブジェクト読書権限
GRANT READ,WRITE ON DIRECTORY [DIR_OBJECT_NAME] TO [USER_NAME];
--DB接続権限（よく忘れる）
GRANT CONNECT TO [USER_NAME];

--実際の入力例
GRANT CREATE TABLE TO TARO;
GRANT IMP_FULL_DATABASE TO TARO;
GRANT READ,WRITE ON DIRECTORY TARO_IMPORT_DIR TO TARO;
GRANT CONNECT TO TARO;

```

## ユーザーの表領域に対する使用量の制限の設定

たまに、この設定が定義されていない状態だとエラーが出るため定義。
特に制限がない場合には無制限にしているが、問題がありそうな場合には数百MBなどで制限を付けて定義する。

```sql
--無制限設定にする場合
ALTER USER [USER_NAME] QUOTA UNLIMITED ON USERS;
--制限を設ける場合
ALTER USER [USER_NAME] QUOTA [任意の数値](M|K) ON USERS;

--実際の入力例
ALTER USER TARO QUOTA UNLIMITED ON USERS; --無制限
ALTER USER TARO QUOTA 100M ON USERS; --100MB

```

## impdpの実行

ついでに記載。よくimpdbと打ち間違える。

```sql
--impdpの実行
impdp [USER_NAME]/[Password] directory=[DIR_OBJECT_NAME] dumpfile=[IMPORT_FILE_NAME] VERSION=[VERSION]

--実際の入力例
impdp TARO/TAROpassword directory=TARO_IMPORT_DIR dumpfile=IMPORT.DMP VERSION=12.2.0
```


またどんづまったらここに追記。
研究室サーバをSSH経由で自宅からjupyter

# 概要

組織のネットワークを利用している場合は外部から接続できる方が珍しいですよね．
遠隔操作ツールは脆弱性が指摘されていたりするし，やっぱりsshしたいけど直接はできない状況はあると思います．

研究室サーバからデータは持ち出せないけど，外部でもいじりたい．
更にはjupyterなんかも使いたいし．．．そんなあなたへ．


# 研究室サーバをSSH経由で自宅からjupyterいじる

## 研究室サーバからさくらVPSへSSHポートフォワーディング

とりあえず研究室から研究室サーバへ接続して，さくらサーバへSSHポートフォワーディングしましょう．

* jupyterで使用するポート番号(他ユーザとかぶらないように変更)：8080


* ssh -f -N -R
  * -f：バックグラウンド実行
  * -N：なにもコマンドを実行しない
  * -R：ややこしいがssh元(研究室サーバ)からのポートフォワードを受け流す設定．受信設定．


* nohupコマンド
  * sshが途切れてもバックグラウンドでプロセスを立ち上げておくコマンド
  * いらなくなったらkillコマンドでプロセスを殺す

```sh
MyMacbook:~ username$ ssh user@mylabo_address

Last login: Mon Aug 26 14:55:14 2019 from mypc_address
[user@mylabo ~]$ ssh -f -N -R 8080:localhost:8080 user@sakura_address
[user@mylabo ~]$ nohup jupyter-lab --port 10080 >> ~/jupyter.log 2>&1 &
[user@mylabo ~]$ exit
ログアウト
Connection to mylabo_address closed.
```

## 自宅PCからさくらVPSへSSHポートフォワーディング

自宅からさくらサーバへSSHポートフォワーディングしましょう．

* ssh -L
  * -L：-Rの逆で，ポートフォワードを送りつける設定．送信設定．

```sh
MyMacbook:~ username$ ssh -L 8080:localhost:8080 user@sakura_address
```

## 自宅からjupyterを使う

[localhost:8080](http://localhost:8080)へアクセス


# だけど研究室サーバからさくらVPSへSSHが切れたらダメじゃん！

全くそのとおりです．
このままだとネットワークの安定性が担保されず，「家に帰って使えない」ってことに実際なります．

これでは悲しいことになるのでSSHが途切れないように工夫しましょう！


## 研究室サーバからさくらVPSへ自動再接続SSHポートフォワーディング

切断されたsshの自動再接続をしてくれるツールでautosshというのがあります．
CUDAサーバにautosshを導入する or スクリプトを書いて再接続することをおすすめします．

* autossh
  * -M：autosshで設定する番号．指定したポートに`ssh -N -L 50000:127.0.0.1:50000 -R 50000:127.0.0.1:50001`を施す
  * 仕様上-Mオプションはやっておく必要があるので適当に

```sh
MyMacbook:~ username$ ssh user@mylabo_address

Last login: Mon Aug 26 14:55:14 2019 from mypc_address
[user@mylabo ~]$ autossh -f -N -M 50000 -R 8080:localhost:8080 user@sakura_address
[user@mylabo ~]$ nohup jupyter-lab --port 10080 >> ~/jupyter.log 2>&1 &
[user@mylabo ~]$ exit
ログアウト
Connection to mylabo_address closed.
```


# これであなたも夢のどこでも研究ライフ!!

今回が初投稿でした

内容が微妙だったので一度削除し付け足しました
サクラエディタでよく使うもの

# 目的
サクラエディタでよく使うものをメモ

# grep
Ctr + G

# 上検索
F3

# 下検索
shift + F3

# 重複行削除
下記のショートカットキーを順番に実行
Ctrl + A　　(全選択)
Alt + A　　(ソート)
Alt + M　　(マージ)

#　行削除
Ctr + Shift + E

# 最後に
重複行削除をやりたいときに忘れがち。
【TypeScript】node_modulesでnoImplicitAnyのエラーが出てた場合の対処法

npm パッケージの [exceljs](https://github.com/exceljs/exceljs) というものを使っていて、
公開されている `node_modules/exceljs/index.d.ts` で `protect(...)` , `unprotect()` の戻り値の型が指定されていなくてnoImplicitAnyエラーが出ていた（excludeでnode_modulesは除外されると思っていたので原因はよくわからない）。
[実際エラーが出ていた箇所](https://github.com/exceljs/exceljs/blob/f50693b344c938d4384208a9ead8bdfa9da17600/index.d.ts#L1154)

自分で `d.ts` 型定義で上書きできるか試してみたりしたがエラーは消えず。
noImplitAnyのチェックを `true` にしたかったので困ったが以下の対応で解決。

# 解決方法
`tsconfig.json` の `skipLibCheck` に `true` を指定するだけ。

```json:tsconfig.json
{
    "skipLibCheck": true
}
```


d.tsで宣言されている型定義ファイルの型チェックをしなくなる。
型情報は生きているので今回はこれで対応。

一応最近exceljs側の方でPRが出てるっぽいhttps://github.com/exceljs/exceljs/pull/930。
こっちが治れば問題ない。
Jenkins PipelineでSlave PC側のファイル内容を読みこむ

Jenkins Pipelineを使って、Slave PCの成果物の一部から、内容を引っぱりたいというニッチな問題。
普通にGroovyで引っ張ろうとすると、Jenkins側のMaster PCのパスを引っぱってきてしまうので、一工夫します。

``` groovy:jenkinsfile.groovy
//returnStdout: trueとすると、echoの実行結果がreturnされる
def CONTENTS = bat returnStdout: true, script: '@echo off && for /f "delims=" %%a in ( contents.txt ) do ( echo %%a )'

```
**echoは必ずOFFにしないと、実行コードまで引っ張ってきてしまいますのでご注意ください。**

これで、テキストの戻り値を見れば引っぱれます。一応複数行も対応したコードにはなっています。
htmlファイルとかもいけますので、お試しあれー。
【Python】プロジェクトオイラー　Problem 9

####ピタゴラス数(ピタゴラスの定理を満たす自然数)とは a < b < c で以下の式を満たす数の組である.

####a<sup>2</sup> + b<sup>2</sup> = c<sup>2</sup>

#####例えば, 3<sup>2</sup> + 4<sup>2</sup> = 9 + 16 = 25 = 52 である.

####a + b + c = 1000 となるピタゴラスの三つ組が一つだけ存在する.
####これらの積 abc を計算しなさい.

problem8は**[こちら](https://qiita.com/projecteuler/items/bcbbda987d8225fee04f)**から

つまり、**a*a + b*b == c*c and a + b + c == 1000**ということのはず

a,b,cはそれぞれ1000以下のはずだからrange(1000)でいいはず

かつ、a + b + c == 1000だということは

```python
kotae = 0
for a in range(1,1000):
    for b in range(a,1000):
        for c in range(b,1000):
            if a*a + b*b == c*c and a + b + c == 1000:
                kotae = a*b*c
print(kotae)   

31875000
```

正解---
wordpress Gutenbergの投稿画面で「更新に失敗しました」と出てしまう

#現象
新規記事登録ができない。
既存記事の編集もできないが、一覧画面からクイック編集できる部分は更新できた。


#解決方法
該当ドメインに関するcookieを全部削除したら登録できるようになった。

原因はよくわからないけど、私はこれで小一時間悩んで作業が止まってしまった。
簡単な方法で解決できたので同じ現象でお悩みの方の参考になれば。
GCPに音声テキスト化アプリを作成した日[GAE,GCS](python環境構築/GCE設定/GCS設定)

#GCP上にサービス立ち上げ

##GoogleCoputeEngine立ち上げ
ここを参考にした
https://www.topgate.co.jp/gcp03-google-compute-engine-launch-instance


##python環境を整える(公式docを読む)
https://cloud.google.com/python/setup?hl=ja

###venvをやっていく
project dir直下で

```
sudo apt-get install python3-venv
python3 -m venv venv(*任意の文字列)
```

####起動
```
source venv(*任意の文字列)/bin/activate
```

####パッケージ入れていく
```
pip install --upgrade pip(まずpipをupgrade)
pip install hogehoge
            fugafuga
```

###ffmpegも入れた
```
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
```

##静的IPの設定
VMインスタンス→ネットワークインターフェース→外部IP
エフェメラル(動的)から固定に変える

##ファイアウォール設定




参考
[venv: Python 仮想環境管理](https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e)
[【2】GCP(GCE)で無料のVMインスタンスを作る(Always Free無料枠、外部IPアドレス取得、SSH接続、22番ポート対応)](https://sakura-bird1.hatenablog.com/entry/2019/03/12/034009#533-%E3%83%95%E3%82%A1%E3%82%A4%E3%82%A2%E3%82%A6%E3%82%A9%E3%83%BC%E3%83%AB%E3%83%AB%E3%83%BC%E3%83%AB)
[これから始めるGCP（GCE）　安全に無料枠を使い倒せ](https://qiita.com/Brutus/items/22dfd31a681b67837a74)
[Google Compute Engineのファイヤーウォールを理解する #gcpja](https://dev.classmethod.jp/cloud/gce-firewall/)
[How to Install FFmpeg in Linux](https://www.tecmint.com/install-ffmpeg-in-linux/)
ログ出力について


ログ出力について考えたので、まとめてみました。

### Twelve-Factor App
---

https://12factor.net/ja/logs

ざっくり言うと、

「ログは標準出力に出すと良いよ。」

しかし、ログをファイルに書き出したりする場合、環境によってはログの肥大化が問題になる。

ログの肥大化が問題になる場合、ログをローテートするのが良いが、標準出力のものをファイルに書き出す場合、うまいことやらないとロストしたり、そもそもローテート出来なかったりするのでどうしようか？というのがお題。

### 標準出力に時間を出すワンライナーで考える
---

```bash
/bin/sh -c 'while true;do date;sleep 1; done'
```

↑のワンライナーの標準出力を、ロスト無くロートテートすることを考えてみる。

ログの肥大化を考えない場合、下記で終了となる。

```bash
/bin/sh -c 'while true;do date;sleep 1; done' >> /tmp/hoge.log 2>&1
```

しかし、本番環境ではログ量が多かったりするので、やりたいことを下記に列挙する。

### やりたいこと
---

- ログファイルの肥大化を防ぐため、ログローテートが出来ること
- ログ出力した情報にロストが無いこと（全部出力されること）
- cloudのオートスケーリング機能を使うと縮小時にログが失われるため、ログをどこかに集めたい
- デイリーでログローテートしたい（日付が変わったらローテートする）
- ログ処理にあまりサーバリソースを割きたくない（低コストでやりたい）

cloudの部分だけ僕の都合ですが、ログを集めたいという要件はcloudじゃなくてもあるはず。

### 環境
---

- オープンクラウド使う
- linuxOS上で動くシステム
- Webサーバ

### ログをファイルに出力する場合のローテートについて
---

下記を見ると全体的に書いてあって、今回の話とかぶる部分も多いが、わかりやすい記事なので共有。

[logrotateの設定とファイルのアクセスモードについて](https://medium.com/@catatsuy/logrotate%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%81%A8%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%83%A2%E3%83%BC%E3%83%89%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6-f9719352dada)

上記リンクの引用

> ちゃんとローテートをしたい場合は以下のいずれかにすることが考えられます。 
>
> ・ファイルに書き込む度にファイルをopenして書き込み後にcloseする
> ・ファイル名が変更されたタイミングを教えてもらい、元のファイル名でopenし直す
> ・ファイル名が変更されたタイミングを自力で検知して、元のファイル名でopenし直す

つまり、お題のワンライナーだと再起動する以外、ローテート不可能となる。

しかし、実際には「お題のワンライナー」Webサーバが動く。

Webサーバの場合、ログローテートのために再起動は辛いので、選択肢としては下記となる。

1. Webサーバでログをローテートする（12factorから外れる）
1. Webサーバに元のファイル名でopenし直す処理を入れる（これも微妙に12factorから外れる）
1. ログを管理するプログラムを作って標準出力をそのプログラムに渡す

このうち、2だと日またぎでローテートした場合、標準出力しか見ていないので、少しだけ次の日のログが出てしまう場合がある。

3の場合は日付でマッチングしてローテートなど、小細工すれば分けられるが、サーバの処理コストが掛かる。

ファイルに出力する場合は、12factorから外れるが、1が良いかと思う。

### ログをファイルに出力しない
---

1. Webサーバの標準出力をfluentdなどのログ収集エージェントに渡す（ファイルに書かない）
1. 標準出力をログ収集エージェントが用意したunix domain socketに書き込む

[やりたいこと](#やりたいこと) で書いたものを全部満たす場合、1か2の方法になる。

ディスク不良なども考慮すると、メモリで完結する1の方法がベスト。

### まとめ
---

ログの出力は、標準出力とログ収集エージェントを組み合わせるのが良さそう。
TypeScriptでConnpassイベントの参加者を取得する

本稿ではTypeScriptでConnpassイベントの参加者を取得する方法を説明する。

## get-connpass-applicantsモジュールをインストールする

```
yarn add @suin/get-connpass-applicants
```

このモジュールは、ConnpassイベントのURLを渡すと、そのイベントの申込者情報を返してくれるもの。

## 実装

上記のモジュールを使って、任意のConnpassイベントの参加者を取得してみる。

```typescript:main.ts
import { getConnpassApplicants, Applicants } from '@suin/get-connpass-applicants'

(async () => {
  const url = 'https://yyts.connpass.com/event/144568/'
  const applicants = await getConnpassApplicants(url)
  console.log(JSON.stringify(applicants, null, '  '))
})()
```

実行結果

```json
{
  "participants": [
    {
      "url": "https://connpass.com/user/OkinaKahiro/",
      "name": "kahirokunn",
      "participationType": "現地参加"
    },
    {
      "url": "https://connpass.com/user/suin/",
      "name": "suin",
      "participationType": "主催者・スタッフ枠"
    },
    {
      "url": "https://connpass.com/user/picric/",
      "name": "kakiuchi",
      "participationType": "現地参加"
    },
    {
      "url": "https://connpass.com/user/zima_gen/",
      "name": "zima",
      "participationType": "現地参加"
    }
  ],
  "waitlist": [],
  "cancelled": []
}
```

`participantsByParticipationType`プロパティを参照すれば、申込み枠ごとにグルーピングした参加者リストも取得できる。戻り値はES6の`Map`で返ってくる。

```typescript
console.log(applicants.participantsByParticipationType)
```

実行結果

```js
Map {
  '現地参加' => [ Applicant {
      url: 'https://connpass.com/user/OkinaKahiro/',
      name: 'kahirokunn',
      participationType: '現地参加' },
    Applicant {
      url: 'https://connpass.com/user/picric/',
      name: 'kakiuchi',
      participationType: '現地参加' },
    Applicant {
      url: 'https://connpass.com/user/zima_gen/',
      name: 'zima',
      participationType: '現地参加' } ],
  '主催者・スタッフ枠' => [ Applicant {
      url: 'https://connpass.com/user/suin/',
      name: 'suin',
      participationType: '主催者・スタッフ枠' } ] }
```
AVR ISPいろいろ

Arduinoでスケッチを焼くのはシリアル経由ですが、Bootを焼くのにISPが必要でいろいろあります。コネクタは6ピンか10ピンになります。

ISPではBootなどのプログラムとFuseが焼けます。Fuseは間違ったクロックを指定したり、リセットを無効にすると、再度焼くことができなくなってしまうので、注意が必要です。

# USBtinyISP

[オリジナル](https://learn.adafruit.com/usbtinyisp)はATTiny2313を使ったモジュールです。元はオープンソースだったのですが、製品になったようです。[ATTiny85](https://www.instructables.com/id/VUSBTiny-AVR-SPI-Programmer/)を使ったものや[ATTiny44](http://fab.cba.mit.edu/content/archive/projects/fabisp/)を使ったものもあります。Amazonなどでも入手できるようです。自作するにはISPが必要です。

![写真（2019-08-28 12.28）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/d406d94c-82ac-9214-8ca6-748f6a134fae.jpeg)


# USBasp

ATMega8を使ったモジュールです。私はAitendoで買ったモジュールを[焼き直して](https://flying-engineer.blogspot.com/2014/08/bootavr-usb-isp.html)USBaspにしました。自作するにはISPが必要です。

# Arduino as ISP

Arduinoにスケッチを書いてISPにする方法です。最初のUSBtinyISPはこの方法で焼きました。ISPを作るためのISPの問題はありません。

ISPがいくつもあっても仕方ないので、以下は自分では試していません。
# AVRISP mkII

AT90USB162などを使ってクローンが作れるようです。dfuでプログラムが書けるので、ISPを作るためのISPの問題はありません。

# FTDI MPSSE

FT2232DやFT232HなどでサポートされているMPSSEを使って書き込む方法です。avrdude　Version 5.11からサポートされていて、Arduino 1.0.6に入っていたのも5.11でしたが、「書込装置」メニューにはありません。Mac OSの場合AppleまたはFTDIのVCP(シリアルポート)ドライバがloadされていると使えません。kextunloadしてください。ISPを作るためのISPの問題はありません。

# FTDI BitBang

以前はパッチで提供されていたものがavrdude　Version 6.2でマージされています。Mac OSの場合AppleまたはFTDIのVCP(シリアルポート)ドライバがloadされていると使えません。kextunloadしてください。ISPを作るためのISPの問題はありません。
【疑問解決】Python __init__.pyってなに？

## tl;dr

Pythonのソースコードのディレクトリの下に`__init__.py`というファイルがあります。
このファイルの役割をまとめます。

## 用意するもの・環境

- macOS Mojave 10.14.6
- Python 3.7(ANACONDA3)
- PyCharm 2019.2

開発環境の構築は下記の記事を参考にしてください。

【これさえ読めばOK】MacでPythonを使って開発するための準備
https://qiita.com/ryoichiro001/items/35a232a430c41dd512fa

## ディレクトリ(フォルダ)をパッケージとして利用できる

このようなディレクトリ構成があったとします。

```zsh

.
├── README.md
├── inputs_files
│   └── urls.txt
├── main.py
├── outputs_files
│   └── out_csv.txt
└── scripts
    ├── __init__.py
    └── file_utils.py
```

そうすると下記のようにして利用できます。

```python

from scripts import file_utils
```

この場合、`__init__.py`の中身は空(0KB)で構いません。


## インポートした際に実行されるプログラムを実行

外部のプログラムからimportされた際に実行されるプログラムを書いておくことができます。
必ず動かす初期処理を記述しておくと便利です。


## Python3.3以降では `__init__.py` がなくてもフォルダをパッケージとして認識してくれる

~~ここまで書いておいてアレですが、Python3.3以降では、`__init__.py`ファイルがなくてもパッケージとして利用できます。~~

~~Python公式ドキュメント
https://docs.python.org/ja/dev/whatsnew/3.3.html#pep-420-implicit-namespace-packages~~

こちらの情報、間違いです。
詳しくは下記を参照ください。
https://qiita.com/methane/items/ed1e5b74747f3ffe9324


## 参考URL

Python `__init__.py` の機能について
https://www.kangetsu121.work/entry/2018/09/16/004008
リモートワークして1年経ちました

昨年5月末に2回目の育休から復帰して１年、週２で在宅作業やってみて感じたこと。

# リモートワーク導入してもらった経緯

2年前、二人目の産休に入る直前に、
・オフィス移転で通勤時間+15分追加
・自宅に隣接した保育園の入園予約消滅。他の園だと送迎片道+10分以上追加
の事情が重なり、
＝ 自宅-保育園-職場の三角形が大きくなりすぎて、1日のタイムスケジュールが破綻することに。

タイミング的に動くことができず、突然の失職危機になりました。
 **リモートワークなら破綻しないで解決できるんじゃ！？**と思い至った経緯は覚えてません。

# リモートワーク制度化嘆願で私がやったこと

- 当時の上長だった事業部長と人事担当者に泣きついた。
    - めちゃくちゃ真剣に対応してくれた。
- 
嘆願書
制度提案資料いくつか作ってばらまいた
<img width="406" alt="38118a9e-f993-e253-8e30-a03c3e997d24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54497/332c4c5d-542d-471c-edc5-8ee7c7c5feef.png">
こんなのとかこんなのとか
<img width="391" alt="d7efce70-e3a2-7825-c3e7-4d7b4ddffb27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54497/67da0349-cee6-a3b2-c5bb-d510c023738e.png">


- 産休に入っても、厚労省のテレワーク普及促進関連事業ページと補足資料読みまくって追い打ち提案メールだしてた。

並行して2歳差兄弟同一園チャレンジという無理ゲー保活もしてたせいか、
二人目はギリ正期産・低出生体重児（すぐ太った）で生まれるしと、色々ひどかった。
トラウマすぎて曖昧にしか覚えてない。

## 意外なところで助けてくれた人
Twitterで育児アカを持っていた私は、鍵つけて悩みを吐き出していた。
そうしたらリモートワークで働いてるワーキングマザーのフォロワーさんが「うちはこうしてる」「これ問題だった」「この制度もある」と経験上のノウハウを教えてくれた。なかには人事労務の管理職の人もいて、世界の広さを感じた。

# 在宅作業で出来てること
- 社内ネットワークにアクセス（共有フォルダ、github、社内システム等々）
- メール、カレンダー、slack、chatwork
- ビデオ会議@appear.inでの朝会参加
	- 長時間大人数は聞くだけになってしまうので不参加、リアルタイム議事録で流れ把握
- 出社時はmtgや調整、在宅時はログがとりやすいタスクを寄せる方針

# 在宅作業でできないこと
- センシティブな話し合い

# 勤務状況
出社→ 火・水・金　10:00-15:00（最大15:30）休憩1H
在宅→ 月・木 8:30-17:30 休憩1H
※育児時短制度利用中（月の標準労働時間120時間）
※できるだけ120時間ぴったりに出退勤きってる。

## スポットで在宅作業日の追加・変更
→ 所属部署の上長の許可のみでOK＠人事部
→ 要事前相談。上長の許可がでたら管理部へメール連絡
→ 変更実績：インフルエンザ等で長期外出禁止時、保育園行事で出社できない日に半休と組み合わせて等

## 在宅時の勤怠フロー
1. 始業・終業時に出退勤メール送信（to上長、管理部）
2. 始業・終業時にchatworkに出社メッセージ
3. 休憩時にchatworkに休憩開始と戻り時間のメッセージ
4. 遅刻・早退時はチャット・メール・電話で連絡
※子供の通院等で9:30-10:00に電話連絡できないときは、メール/chatで１次連絡しさせてもらってます


# 思ってたんと違ったこと

## 第1位：仕事の合間に家事は無理
昼休みに部屋の片付けや夕食の仕込みできるかな？
→ 無理。休みたい。午後のパフォーマンス維持のためにも休憩大切。休憩大切。

宅配便や設備点検の応対くらいはできる。

## 第2位：子守しながら仕事は無理

子供が熱で保育園行けなくても、看病しながら仕事できるかな？
→ 無理。知ってた。
熱あっても寝ない。むしろ体調不良でメンタルも不安定だから、普段よりべったり。

```
ここ解決したいなら、有給の看護休暇拡充や、病児保育利用補助等を求めるべきだよなあ…
```

## 第3位：通勤時間は自分だけの時間
→つらく無駄な通勤時間だとおもってた。
でも、SNSチェックや新着記事読みこんだりタスクの事前調査したり、それなりに有意義に使ってた。
家にいると始業ギリギリまで掃除洗濯片付け…と家事してるから、準備運動なしに仕事モードになるのつらい。

# モヤモヤしてること
- 「詳しくは出社したときに話します」
    - アジェンダを事前にチャット等で伝えてほしい。スタックして作業が止まりがちになる。
- 在宅勤務制度がすべての最適解にはならない
    - 上に挙げた有給の看護休暇拡充や、病児保育利用補助等を考えるべきだとおもう
    - 特に「子供生まれたばかりだから家にいたい（意訳）」なら育休取得して。手取り相当額が給付金でもらえるから経済的に負担はなし。
- 制度利用条件の緩和
    - 私は仕事を失わないために必死だったけど、ほかにどのような需要があるのか想像がつかない。
- 信頼関係の築きにくさ【深刻】
    - 人となりが伝わるような世間話が減るので、「どんな人なのかいまいちわからない」状態になりやすい。
- 評価軸【深刻】
    - 出席点の重要さが身に染みる
- なぜこんな茨道すすんでるのはわからない。もっと楽に生きたい。

# 次にやること
この「モヤモヤしてること」の問題を分解して解決する
mysqlの使い方

###起動
`mysql -u mysqlユーザ名 -p[password] DB名`

`Ctrl + r で履歴を遡れる`

###データベースを確認
`show databases;`

### DB使用

`use [データベース名]`

### テーブル閲覧・しよう

`show tables;`
`select ~~ from [テーブル名];`

### 更新
`update [テーブル名] set [カラム名]　= [変更後の値] (where [カラム名] = ~~);`


###ページをスタイリッシュに
`pager less -n -i -S`
Android Studioに同梱されているKotlin Pluginをバージョンアップする方法

## 概要
先日kotlinの新バージョン 1.3.50がリリースされました
それに伴ってKotlin Pluginも1.3.50に対応したのですが、Android Studioにはもともと同梱されており、
Pluginからはバージョンアップできなくて少し手こずったので方法を残しておきます

## 方法
preferencesの下記の場所に新しいバージョンをinstallできる
Preferences | Languages & Frameworks | Kotlin
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44174/782e5ea7-c105-5a5f-9282-90f56ed7722e.png)

もしくは、Android Studioを起動した時に右下にインストールを促すサジェストが出るのでそれにしたがってインストールする
Message:Cannot read property 'bindings' of null  | gulp-babel

#エラーメッセージ

```error.sh

TypeError in plugin "gulp-babel"
Message:Cannot read property 'bindings' of null

```

#状況
npmからyarnに移行している状況で
gulpのパッケージが一通りインストール完了し
gulpコマンドを実行した時にエラーがでた。

#参考情報
エラーメッセージでググったらそのまま出てきました。
[＞＞参考情報stackoverflow](https://stackoverflow.com/questions/52092739/upgrade-to-babel-7-cannot-read-property-bindings-of-null)

#対応作業ログ
参考URLでは.babelrcの記述を以下のように直しなさいとあります。

```error.babelrc

{ "presets": ["env"] } 

```

↓

```ok.babelrc

{ "presets": ["@babel/preset-env"] }

```

が私の環境ではgulp.jsに"presets": ["env"]の記述があったのでそこを直しました。

いざ! yarn -s run gulp

```error.sh

Cannot find module '@babel/preset-env' from '/Users/mygulpdirectory'

```

モジュールがないと言われた。
バージョンが上がって使用するモジュールも変わったのかな。。。

yarnのサイトで検索するとありましたので

```install.sh

yarn add @babel/preset-env

```

して再度yarn -s run gulpしたら無事実行できました。
（メモ）Java for文

#for文での繰り返し処理
ループ処理・繰り返し処理と呼ばれる処理をまとめます。
Javaでは次の３つが用意されています。

- for文
- while文
- do文(do while)

#記述式

- **for(<font color="MediumBlue">初期値の設定</font>;<font color="MediumBlue">継続条件</font>;<font color="MediumBlue">値の操作</font>){<font color="LimeGreen">処理</font>}**

- **while(<font color="LimeGreen">条件</font>){<font color="LimeGreen">処理</font>}**

- **do{<font color="MediumBlue">処理</font>}while(<font color="MediumBlue">条件</font>);**

#コードを書いてみよう

数字を入力し、その個数だけ*を表示するプログラム

```java
 
import java.util.Scanner;
 
class PutKome {
 
  public static void main(String[] args) {
    Scanner stdIn = new Scanner(System.in);
 
    System.out.print("何個お米を表示しますか：");
    int n = stdIn.nextInt();
 
    for (int i = 0; i < n; i++) {
      System.out.print('*');
    }
    System.out.println();
  }
}
```

【結果】

```
何個*を表示しますか：5
*****
```

#解説

1. nの入力値を受け取る
2. [初期値]iに0を代入する
3. [継続条件]iがn未満？
4. Yes：*を出力、[操作]i+1…Noになるまで繰り返す/No:改行


![1566876503855.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434899/e5253be5-eaf7-f190-5728-d69274ec224c.jpeg)
Rails6でknockを導入してload関連のエラーが発生したときの対処法

Ruby on Rails 6.0.0 で作成したアプリケーションに、JWTトークンの発行・認証を行う目的で [knock](https://github.com/nsarno/knock) をインストールしようとしたところ、loadに関するエラーが発生したので対処法をまとめます。

## 発生したエラー

### 現象1
`rails generate knock:install` を実行するとwarningとerrorが出力される。
`config/initializers/knock.rb` の生成自体はできている。

```bash
$ rails generate knock:install                                                                                                                                                               
Running via Spring preloader in process 14337
[WARNING] Could not load generator "generators/knock/install_generator". Error: expected file /home/user/.rbenv/versions
```

### 現象2

`ApplicationController` にて `Knock::Authenticable` をincludeさせると、railsが起動できない。

```
$ rails c                                                                                                                                                                                     
/home/user/Documents/develop/knock_test/app/controllers/application_controller.rb:2:in `<class:ApplicationController>': uninitialized constant Knock::Authenticable (NameError)
```

## 原因
Rails6でのautoloadがzeitwerkモードに変更となったことで、autoloadの挙動がRails5以前と変わったことに起因しています。

[Rails 6 zeitwerk autoload problem with gem](https://github.com/rails/rails/issues/36381)

## 対処法

### 対処法1. 明示的にrequireする[推奨]

上記issueにある通り、明示的にソースをrequireすることでエラーを回避できます。

```ruby:config/initializers/eager_load_knock.rb
require 'knock/version'
require 'knock/authenticable'
```

### 対処法2. autoloadをclassicモードに戻す[非推奨]

Rails5以前と同じ方法でautoloadさせることでもエラーを回避できます。
基本的には新しいバージョンに追従すべきなので非推奨ですが、他のgemで同様のエラーが発生する場合などはこちらの方が手っ取り早いかもしれません。

```ruby:config/application.rb
require_relative 'boot'

require "rails"
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_mailbox/engine"
require "action_text/engine"
require "action_view/railtie"
require "action_cable/engine"
require "rails/test_unit/railtie"

Bundler.require(*Rails.groups)

module KnockTest
  class Application < Rails::Application
    config.load_defaults 6.0
    config.api_only = true
    config.autoloader = :classic # ★追記
  end
end

```

## まとめ
こちらの [issue](https://github.com/nsarno/knock/issues/240)で何かしら修正が入ることに期待しつつ、まずは上記のような対策でエラーを回避するしかなさそうです。
Laravel環境構築 チートシート

Laravel 6.0 リリースおめででとうございます！！
さっそく今までのVagrant環境で動かせるか検証してみました。

※Docker環境で動かす場合は記事が上がっていましたので
ご紹介しておきます。[Hello Laravel 6 !!!](https://qiita.com/ucan-lab/items/998160a9cecca78e7e0a)

Step 1　Vagrant と VirtualBox のダウンロードとインストール
Step 2　Homestead vagrant box のダウンロード

上記stepは[【Laravel 5.5 or latest】Homestead で mac に Laravel 開発環境を構築](https://qiita.com/7968/items/68b3566d92d2b007038e)を参照

Step 3　Homestead のダウンロード

```bash
$ cd
$ mkdir laravel-xxxx
$ cd laravel-xxxx
$ mkdir code
$ git clone https://github.com/laravel/homestead.git Homestead
$ cd Homestead
$ git checkout v7.0.1
$ bash init.sh
```
Homestead.yaml が生成/修正
ホームディレクトリのlaravel-xxxxフォルダなら以下のようになる
（「- map」の「-はマイナスという意味ではないので消さないように」）

```yaml
folders:
    - map: ~/laravel-xxxx/code
```

scripts/homestead.rb内修正
homestead-7と記載のある場所を全て任意の名称に変更（一括で変更すると楽）
ここが仮想サーバー名になる
（注）仮想サーバー名がかぶるとvagrant up時エラーになる

```bash
$ vagrant up
$ vagrant ssh
vagrant@homestead:~$ cd code

vagrant@homestead:~$ laravel new
or
vagrant@homestead:~$ composer create-project --prefer-dist laravel/laravel blog "5.7.*"
or
vagrant@homestead:~$ composer create-project --prefer-dist laravel/laravel blog "5.8.*"

```
【laravel newの場合】
常に最新版が出てきます
.env一部修正

```
中略
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
中略
```

【composer create-project --prefer-dist laravel/laravel blog "5.7.*"の場合】
code内にblogフォルダでダウンロードされるので
blog内データをcode直下に移動。その後blogフォルダ削除

構築完了

timezoneを日本時間に変更

```php:config/app
'timezone' => 'Asia/Tokyo',
```
ハノイの塔のアルゴリズムをやってみた

会社でアルゴリズムの話題でハノイの塔のアルゴリズム考える話を聞いて、ちょっと前にやったのでQiitaの記事にしてみようかなと

## ハノイの塔とは
wiki
https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%8E%E3%82%A4%E3%81%AE%E5%A1%94

ピラミッド状に重なってるものを、小さいものの上に大きいものは乗せてはいけないってルールで最初の一から別の位置へ、三つの位置を移動させながら移し替えるパズルです。
以下では言葉を統一するために移動させるものを円盤、円盤を置ける場所を杭とします

### 円盤の数によらず三つの杭で移し替えることは可能なのか

数学的帰納法的な論理展開で証明できます。

(1) 円盤が一枚の時
自明

(2) 円盤が1..n-1枚の時、移し替えることが可能だと仮定(n>=2)
円盤がn枚の時
n枚目以外のn-1枚の円盤は別の杭に移動させることは仮定より可能
n-1枚を別の杭に移動させたのちに、n枚目の円盤を残る空いている杭に移し替え、再度n枚目の円盤の上にn-1枚の円盤を移し替えればn枚の円盤を三つの杭でうつしかえることができる。

以上より三つで移し替えることができる。

## アルゴリズムを考えてみた
アルゴリズムを考える際に、上記の円盤の塊を別の杭に移し替えるイメージがあって何となく再帰関数を用いてうまいことやれそうだなって思って考えてました。
ただ、n枚の円盤の塊を動かす関数をうまく定義できずにうまくいかずに悩むこと半日。1枚目の円盤の上には何も置けないのでそいつの動きに注目してみようと思い、円盤3枚とか4枚とかで動きを確認したところ何やら規則的な動きをしてるような感じがあり、他の円盤に対しても確認してみたところ、他も同様の規則性が！！
このあたりの規則性に関しては実際にお手を動かして確認された方が感動するかと思います。

で、私がそこから導いたアルゴリズムは以下のような感じです。
円盤を塊で見るのではなく、円盤一つ一つを規則的にうごかす形式です。

![hanoi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280324/5a02b3ab-d22a-135e-144c-fb7589a079bc.png)

書き方悪いので補足します。
routってあるのは何枚の円盤を動かすかって話です。
input:n-1ってあるのは、この関数をinput:n-1で実行させろってことです。

で、これをpythonで記述したのが以下のコードになります

```py

import sys
pos = [0]*int(sys.argv[1])
pole = [list(range(1,int(sys.argv[1])+1)),[],[]]
print(pole)
def move(n,m):
  if n!=1 : move(n-1,m)
  next = (pos[n-1]+2)%3 if (m-n)%2==0 else (pos[n-1]+1)%3
  pole[next].insert(0,pole[pos[n-1]].pop(0))
  pos[n-1]=next
  print(pole)
  if n!=1 : move(n-1,m)
move(int(sys.argv[1]),int(sys.argv[1]))
```

できる限り短く書いてやろうと頑張りましたが、自分にはこれが限界でした...
そもそも円盤の位置を保持する配列が必要なのかどうか、個人的には疑問だったのですが、その配列なしでうまくやる方法を思いつかなかったので...そのあたりまだまだ改良できそうです。

## まとめ
Pythonの勉強がてらハノイの塔のアルゴリズムに挑戦しましたが、Pythonの勉強よりも頭の体操になった感じでした。
Rails6 のちょい足しな新機能を試す70（ActiveModel::Errors#slice! 編）

# はじめに

（多分）Rails 6 に追加された新機能を試す第70段。 今回は、 `ActiveModel::Errors#slice!` 編です。
Rails 6 では、 `ActiveModel::Errors` に インスタンスメソッド `slice!` が追加されました。

Ruby 2.6.3, Rails 6.0.0.rc2 で確認しました。Rails 6.0.0.rc2 は `gem install rails -v 6.0.0rc2 --prerelease` でインストールできます。
（Rails 6.0.0 がリリースされましたが、動作確認当時の最新版は、Rails 6.0.0.rc2 でした。悪しからず :bow:)

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

今回は適切な例を思いつかなかったので、 `rails console` を使って確認します。

# プロジェクトを作る

```shell
rails new rails_sandbox
cd rails_sandbox
```

# User モデルを作る

4つの属性 `name`, `email`, `country`, `city` を持つ User モデルを作ります。

```shell
bin/rails g model User name email country city
```

# ヴァリデーションを追加する

単純に必須入力のヴァリデーションを4つの項目に追加します。

```ruby:app/models/user.rb
class User < ApplicationRecord
  validates :name, presence: true
  validates :email, presence: true
  validates :country, presence: true
  validates :city, presence: true
end
```

# マイグレーションを実行する

```shell
bin/rails db:create db:migrate
```

# rails console で確認する

`rails console` で確認します。
User モデルのインスタンスを作って、 `validate` メソッドを呼び出します。

```irb
irb(main):001:0> user = User.new
=> #<User id: nil, name: nil, email: nil, country: nil, city: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user.validate
=> false
```

`slice!` メソッドで、 `country` と `city` のメッセージだけ残します。

```irb
irb(main):003:0> errors = user.errors.slice!(:country, :city)
=> {:name=>["can't be blank"], :email=>["can't be blank"]}
```

`full_messages` でエラーメッセージを確認すると `country` と `city` のエラーメッセージだけになっていることがわかります。

```irb
irb(main):004:0> user.errors.full_messages
=> ["Country can't be blank", "City can't be blank"]
```

なお、 `ActiveModel::Errors#slice!` の戻り値は `Hash` オブジェクトのため、 戻り値に対して `full_messages` は使えません。

```irb
irb(main):005:0> errors.full_messages
Traceback (most recent call last):
        1: from (irb):5
        NoMethodError (undefined method `full_messages' for {:name=>["can't be blank"], :email=>["can't be blank"]}:Hash)`)
```

# 試したソース

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


# 参考情報

* [What is new in Rails 6.0](https://bogdanvlviv.com/posts/ruby/rails/what-is-new-in-rails-6_0.html)
* [Add slice! method to ActiveModel::Errors](https://github.com/rails/rails/pull/34489)