OmniAICreator/Qiita-1.07M huggingface dataset:
Ubuntu で Rust の最新版を使う

Ubuntu 20.04 に Rust をインストールする手順です。公式サイトの通りです。
https://rustup.rs/

## Rust インストール
WSL2 内の Linux にインストールする場合は、下記コマンドで行います。

```bash
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

```
info: downloading installer

Welcome to Rust!

This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.

It will add the cargo, rustc, rustup and other commands to
Cargo's bin directory, located at:

  /home/tkondou/.cargo/bin

This can be modified with the CARGO_HOME environment variable.

Rustup metadata and toolchains will be installed into the Rustup
home directory, located at:

  /home/tkondou/.rustup

This can be modified with the RUSTUP_HOME environment variable.

This path will then be added to your PATH environment variable by
modifying the profile file located at:

  /home/tkondou/.profile

You can uninstall at any time with rustup self uninstall and
these changes will be reverted.

Current installation options:


   default host triple: x86_64-unknown-linux-gnu
     default toolchain: stable
               profile: default
  modify PATH variable: yes

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
>1
```

1 でインストールします。


## 再起動
インストール後、SHELLを再起動します。

```bash
$ exec $SHELL -l
````

## 確認
cargo、rustc 、rustup コマンドが使えました！

```bash
$ cargo --version
cargo 1.54.0 (5ae8d74b3 2021-06-22)

$ rustc --version
rustc 1.54.0 (a178d0322 2021-07-26)

$ rustup --version
rustup 1.24.3 (ce5817a94 2021-05-31)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.54.0 (a178d0322 2021-07-26)`

```

## rust の更新 (rustup update)

rustup update コマンドで rust を更新できます。

```bash
❯ rustup update
info: syncing channel updates for 'stable-x86_64-unknown-linux-gnu'
info: latest update on 2021-12-02, rust version 1.57.0 (f1edd0429 2021-11-29)
info: downloading component 'cargo'
info: downloading component 'clippy'
info: downloading component 'rust-docs'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: downloading component 'rustfmt'
info: removing previous version of component 'cargo'
info: removing previous version of component 'clippy'
info: removing previous version of component 'rust-docs'
info: removing previous version of component 'rust-std'
info: removing previous version of component 'rustc'
info: removing previous version of component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
 17.9 MiB /  17.9 MiB (100 %)  15.1 MiB/s in  1s ETA:  0s
info: installing component 'rust-std'
 24.9 MiB /  24.9 MiB (100 %)  19.1 MiB/s in  1s ETA:  0s
info: installing component 'rustc'
 53.9 MiB /  53.9 MiB (100 %)  21.2 MiB/s in  2s ETA:  0s
info: installing component 'rustfmt'
info: checking for self-updates

  stable-x86_64-unknown-linux-gnu updated - rustc 1.57.0 (f1edd0429 2021-11-29) (from rustc 1.56.1 (59eed8a2a 2021-11-01))

info: cleaning up downloads & tmp directories


```
py2exeを利用しようとして挫折した備忘録

#概要
pythonのsimplekmlを利用して、csvからkmlファイルを作成するソフトを作成して、それをC#から呼ぶ形のソフトを作成しようとした。
C#からpythonを呼ぶ方法として
[.NET (C#)からpythonを呼び出す](https://qiita.com/hogegex/items/3743225a7af13e93df78)
などもあるが、実行形式で出力して、引数を付けて呼ぶ方がとりあえず楽だと思ってその方向で進めることにした。

##結論
py2exeは軽量化しつつexe化できる可能性があるが、処理が煩雑になるので利用しないこととした。
仮想環境でpyinstallerを利用するか、pythonnetを利用する方が良い

#pyinstaller
実行形式で出力する方法としては

- pyinstaleller
- py2exe

があるが、とっつきやすそうなpyinstallerから手を付けることにした。

```python:python
pip install pyinstaller
python -m pyinstaller test.py --onefile
```

これだけで実行形式で出力できるので、非常に楽なのだが、めちゃくちゃファイルサイズがでかくなって30MBになってしまった。
仮想環境とか作ればもっと軽くなるらしいが、あんまり時間もかけたくないので、後回しにする。

pyinstallerについて詳しく知りたい場合は
[【悲報】PyInstallerさん、300MBのexeファイルを吐き出すようになる](https://lets-hack.tech/programming/languages/python/pyinstaller-issue/)
ここを参照する事を推奨する。

#py2exe
py2exeならそこまで重くならないような噂だったので、そちらに手を付けることにする
インストールについてはgitからwhlをダウンロードする方法しかないようなので、サクッとインストールする
[py2exeをpython 3.5 - 3.7で使う](https://note.com/noelrecords/n/n0dc600acf1c0)
[https://github.com/albertosottile/py2exe/releases](https://github.com/albertosottile/py2exe/releases)

setup.pyを書く必要があると言うのでそこらへんも作成する
[py2exeでPythonのスクリプトを実行ファイル(exe)にする【py2exe】](https://cocodrips.hateblo.jp/entry/2015/06/03/232419)

`python setup.py py2exe`で実行する

ここらへんからハマり始めるのだが
`'bundle_files': 2,`
だと出力できるのだが
`'bundle_files': 1,`
にするとnumpyのサブモジュールが見つからないとか言って出力できない。
じゃあなんで2だと通るんだよ、って話なんだが、2で出力したファイルを実行してみると
`SystemError: initialization of numpy.random.mtrand did not return an extension module`
とかいってnumpy周りで失敗する。

これについて調べてみると
[https://github.com/albertosottile/py2exe/issues/28](https://github.com/albertosottile/py2exe/issues/28)
なんかライブラリをいじったり、インポート周りで変な回り道をする必要があるみたい
なのでpy2exeは利用しない方がいいだろうと判断した

#締め
まぁとりあえず2時間くらいで調べた内容を15分くらいでまとめたような薄い内容ですが、備忘録ですので、見づらかったらすいません。
とりあえず、現状でもモノは動くので、30MBのまま使ってみて、時間が余れば(余らない)ほかの方法も試してみようかと思います。

以上です。
ABC170 E - Smart Infantsのmultisetを利用しない解き方

AtCoder Beginner ContestのE問題でmultisetを用いた解説が書いてありましたがpythonなどmutisetが用意されていない言語などもあると思うのでPriority Queue(heapq)を用いた代替アルゴリズムを紹介したいと思います。
問題自体の解説はしないのでそこは公式の解説を読んでください。

# 問題
ABC170 E - Smart Infants
https://atcoder.jp/contests/abc170/tasks/abc170_e

# 前提知識
#### multiset
内部的には[二分探索木](https://ja.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%8E%A2%E7%B4%A2%E6%9C%A8)が使われています。これによりデータの挿入で毎回O(logN)かかる代わりに常にソートされている状態が維持されています。そのため、削除や検索もO(logN)で行うことが可能です。
自分で二分探索木を実装しておくことで標準で提供されていない言語でも使用することはできますが平衡を保つのには工夫が必要です。(工夫例:[【木マスター養成講座】7-1. Splay木ってなに〜？説明編【競プロかつっぱ】](https://youtu.be/M6LcINhgXeM))

#### Priority Queue
GCCでは内部的に[二分ヒープ](https://ja.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E3%83%92%E3%83%BC%E3%83%97)が使用されています。
pythonのheapqでも内部的には同じデータ構造が用いられています。
データの挿入は二分探索木と同じく、毎回O(logN)かかります。ヒープ木なので内部は**ソートされておらず、検索や最大(最小)値以外の削除は高速にはできません**が、常に最大(最小)値を計算量O(1)で取得することはできます。二分探索木より勝っている点は、特に工夫をしなくても常に平衡が保たれているため計算量が安定するという点です。

# 解法
####要点
今回の問題では

1. 各幼稚園においてレートの最大値を取ってくること
-  レートの最大値の集合の最小値を取ってくること
- 入園するときに値をそれぞれの集合へ挿入すること
- 転園の際に値をそれぞれの集合から削除すること

が常に高速でできれば良いことになります。

公式の解説でも述べられているようにmultisetを用いることでそれぞれの処理は高速に行うことができますが、Priority Queueでは4番目の処理を高速で行うことができないため発想を変える必要があります。

今回の問題を解くに当たって、4番目の条件は、**1,2番目の条件の邪魔にならなければ必ずしも行わなければならない処理ではない**ことに着目しましょう。
つまり、実際にデータの中から削除されていなくても各幼稚園におけるレートの集合の最大値やレートの最大値の集合の最小値に影響が無い場合は構わないわけです。

####具体的なアルゴリズム
1,2番目の条件で実装は変わらない(最大最小がひっくり返るぐらいな)ので1番目の条件(集合の最大値の取得)を例に説明します。

ここで、Priority Queueを2本持つことを考えます。

1. 集合全体を管理するもの
2. 1のうち削除されたはずの要素を保持するもの

そして**入園した時には1に、転園したときは2に要素を挿入します。1と2の最大が同じ値の場合、両方から削除します。**
これにより、この幼稚園の最大値は1の最大値と常に同じになります。

なんとなくのコードを載せておきますがstdやincludeなど端折っているので環境によってはコピペしても動かないです。

```コード.cpp
priority_queue<int> in;
priority_queue<int> out;

// 入園するときの処理
void infant_in(int i){
    in.push(i);
}

// 転園するときの処理
void infant_out(int i){
    out.push(i);
    while(!out.empty() && in.top() == out.top()){
        in.pop();
        out.pop();
    }
}

// 最大値の取得
int get_max(){
    return in.top();
}
```

具体例を見ましょう。幼稚園にレートが3,5,8の園児が入園してきてその後レートが5,8の園児がこの順に転園していくことを考えます。

```c++

> 3人の園児たちが入園
実際の幼稚園 = {3,5,8}
in = [3,5,8] out = []   //この時点での最大値はもちろん8

> レートが5の園児が転園
実際の幼稚園 = {3,8}
in = [3,5,8] out = [5]  //最大値は8で合っている

> レートが8の園児が転園
実際の幼稚園 = {3}
in = [3,5,8] out = [5,8]
in = [3,5]   out = [5]
in = [3]     out = []   //最大値は3で合っている
```

こんな感じで、最大値を取得する上では問題ないことがわかります。

#### 計算量
気になる計算量なのですが、今回の問題においてネックになりそうなinとoutから値を削除する回数は最大Q回なので単独でボトルネックになることはなく、計算量は値の挿入時にかかるO((N+Q)logN)になります。
これは十分に高速と言えます。
*(6/17 計算量が正しくなかったので修正しました)*
Elasticsearch-PHP で [terms] query does not support エラーが出る

## 事象
Elasticsearch (Version 6.8.5) に対して、
Elasticsearch-PHP で terms 句を含む query を作って検索(_search)を行ったところ、以下のエラーが出た。
`[terms] query does not support [0] within lookup element`

## あるべき姿
以下のような配列を Elasticsearch の terms 句に渡した場合、
`$accounts = ["aaa", "ccc"]`

Elasticsearch で以下の様に扱われること。

```
"terms": {
  "account": ["aaa", "ccc"]
}
```

## 今回のエラーが出た状況
まず、PHP で配列の真ん中を削り、添え字を歯抜けにする。

```
$accounts = ["aaa", "bbb", "ccc"];
unset($accounts[1]);　　◆"bbb" を削る
print_r($accounts);

* 配列の添え字はこんな感じになる
Array
(
    [0] => aaa
    [2] => ccc
)
```

この配列を PHP で Elasticsearch に渡す。

```
$client = Elasticsearch\ClientBuilder::create()
	->setHosts(["localhost:9200"])->build();

$client->search([
	"index"	=> "test_index",
	"body"	=> [
		"query" => [
			"terms" => ["account" => $accounts]
		]
	]
]);
```

すると、Elasticsearch の query としては以下の様に扱われてしまう。

```
"terms": {
  "account": {
    "0": "aaa",
    "2": "bbb"
  }
}
```

"0" などという key は terms 句の中に存在しないためエラーになっていた。
`[terms] query does not support [0] within lookup element`


## 原因まとめ
Elasticsearch-PHP を利用する場合、
body 内の配列（例：terms 句の検索値）の添え字が0から始まらない、
または途中の数字が抜けている場合、
Elasticsearch 側で Object として認識されてしまい、予期せぬエラーを産む。


## 解決方法
(1) おすすめの方法
Elasticsearch-PHP の body 内で配列を指定したい場合、
array_values などで配列の添え字を **0から始まる歯抜けのない数列** に揃えること。
個人的には配列利用箇所で array_values するのが楽。

(2) body には JSON 文字列を渡すこともできるので、
直接 JSON 文字列として配列を定義して渡す。

ただ、この方法を PHP で使うのはかなりめんどくさい。
Pytohn と違って {} が配列ではないためベタで query を書く必要がある。
変数展開もピリオド（.）がたくさん出てきて見づらくなる。。。

あと、json_encode でも歯抜けの配列が Object に変わってしまうので注意が必要。
読書メモ_プログラマーの人生マニュアル『SOFT SKILLS (ソフトスキル)』

話題になっていたので気になって、これからのキャリアを考えるためにも購入。
色々ためになることが書いてあったのでメモしていきます。
技術面だけでなく、色々書いていて面白かったです。

[SOFT SKILLS　ソフトウェア開発者の人生マニュアル|ジョン・ソンメズ (著), 長尾 高弘 (翻訳), まつもとゆきひろ (監修)](https://www.amazon.co.jp/SOFT-SKILLS-%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA%E8%80%85%E3%81%AE%E4%BA%BA%E7%94%9F%E3%83%9E%E3%83%8B%E3%83%A5%E3%82%A2%E3%83%AB-%E3%82%B8%E3%83%A7%E3%83%B3%E3%83%BB%E3%82%BD%E3%83%B3%E3%83%A1%E3%82%BA-ebook/dp/B01GDS0994)

# 第3部 学ぶことを学ぼう
- メンター探しのチェックリスト
 - あなたがしたいことをした人か
 - あなたがしたい事を他人がしたときに、それを後押しした人か。
 - その人はのどのような結果を残しているのか
 - その人とうまくやっていけるか 
- 苦手な個所のチェック方法
 - もっとも時間を使っているのはどこか
 -  改善できるはずの繰り返し作業
 -  完全に理解しているとは言えない事項
 -  答えられない採用面接の質問

(気づき)
メンターを探すためにまずしたい事を整理しようと思います。
苦手な個所については、確かに忙しいのを言い訳に毎回無駄にしている作業はありそうです。
それに少し時間を割いて、これからのために改善してみようと思います。

# 第4部 生産性を高めよう
- 生産性向上＝集中する事
- 生産性向上策
 - 四半期の計画＞月次計画＞週次計画(毎週月曜日にチェック)＞日時計画(毎朝確認) 
 - 割り込みを遮断する(本当に緊急なの以外(電話など))
     - メール(時間を決めて1度にまとめて見る)
     - チャット(気が散る原因になるので、集中するときは見ない) 
 - 適度に休暇をとる
- ポモドーロテクニック
  - 1ポモドーロ ₌ 25分集中(極力割り込みをなくす)、5分休憩  
    ※4ポロモードごとに15分休憩をとる
  - 1日に何ポロモードを実行したか計測するのが大事。見積もり力が上がる。  
    ※筆者で1日10ポモドーロほど

(気づき)
メールの話や、チャットの話は確かに思い当たる節があるので、
時間を決めて対応してみようと思います。
また、ポモドーロテクニックを実践してみようと思います。

#第5部 お金に強くなろう
- 資産と負債
  - 資産＝維持費よりも利用価値が高いもの(ex) 配当を生む株式、貸しに出している不動産)
  - 負債＝提供する価値よりも維持の方がかかるもの(ex) 持ち家(必要以上のものなら)、自動車(必要以上のものなら)、月極サービス)
- 給与交渉しよう
  - 力量を上げるために、名前を売っておこう(ブログポスト、ポッドキャスト、本や雑誌記事など) 

#第6部 やっぱり、体が大事
- 明確な目標を選ぶ
- マイルストーンを作る
- 進捗の度合いを計測する
  - 変動が低い方法で計測する 
- 消費カロリーを計算する  
(気づき)   
実際に行ってみた。  
現体重：63kg ⇒ 目標：12月までに58kg  
1kg/1か月減少させる。  
毎週日曜日に体重を測定する。  
BMR = 1,554カロリー/日  
活動レベルに基づく毎日のカロリー必要量：2,136カロリー  
1ポンド(0.45kg)減らすのにかかるカロリー₌3500キロカロリー  
[BMR計算方法](https://www.calculator.net/bmr-calculator.html?ctype=metric&cage=28&csex=m&cheightfeet=5&cheightinch=10&cpound=160&cheightmeter=170&ckg=62.6&cmop=0&coutunit=c&cformula=m&cfatpct=20&x=62&y=21)

活動レベルに基づく毎日のカロリー必要量

#第7部 負けない心を鍛えよう
- プラス思考になるために
  - 思考を変える
  - 瞑想する
  - 遊ぶ
  - 本を読んでノウハウを活用する
- 私の成功本リスト(気になったの抜粋)
  -  デール・カーネギー 「人を動かす」
  -  Clean Code 「アジャイルソフトウェア達人の技」
- 失敗を恐れずに受け入れよう。成長の糧になる 
(気づき)   
マインドの部分も仕事にかなり影響を及ぼすことを改めて感じた。
よく遊び、プラス思考で失敗を恐れずにチャレンジしていきます。
紹介に合った本はとても面白そうなので読んでみようと思います。
SpringBoot_エラー画面と404画面を表示切替(スマホ版も)

# ErrorViewResolverで切り替える
ErrorViewResolverで簡単に切り替え可能
さらにintercepterでPCかスマホか判定していれば対応した画面に飛ばしてくれる

```java:SampleErrorViewResolver

    @Component
    public class SampleErrorViewResolver implements ErrorViewResolver {

        /**
         * 表示決定
         *
         * @param request
         * @param status
         * @param model
         * @return ModelAndView or null
         */
        @Override
        public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
            boolean mobile = (boolean) request.getAttribute("mobile");
            ModelAndView modelAndView = new ModelAndView();
            mav.addAllObjects(model);

            if (status == HttpStatus.NOT_FOUND) {
                // 404
                if (!mobile) {
                    modelAndView.setViewName("/404");
                } else {
                    modelAndView.setViewName("/mobile/404");
                }

            } else {
                // 404 以外はエラー画面へ
                if (!mobile) {
                    modelAndView.setViewName("/error");
                } else {
                    modelAndView.setViewName("/mobile/error");
                }
            }
            return modelAndView;
        }
    }

```
Nuxt&Django REST Frameworkを使って遊ぶ

# 概要

今までNuxt.jsとDjango REST Frameworkを使って色んなことをやってきたのですが、[ゼロから始めるLeetCode](https://qiita.com/KueharX/items/6ee2502c3b620c795b70)という毎日更新の記事を書いているせいで自身の投稿履歴から見直す時にいちいち見辛い・・・

ということでハブ的なまとめページを作りました。

# リンク

- [djoserを使ったDjango REST Frameworkでの認証機能の実装](https://qiita.com/KueharX/items/eef29ae0c5c238cbf61c)

- [djoserを使ったDjango REST FrameworkでのJWT認証機能の実装](https://qiita.com/KueharX/items/3568b27213cdbd1cf261)

- [djoserを使ったDjango REST Frameworkでのカスタムユーザーモデル認証機能の実装](https://qiita.com/KueharX/items/009687407fa0c542839a)

- [Nuxt&Django REST FrameworkでCRUD GET編①](https://qiita.com/KueharX/items/836e25a718712fe0a54d)
- [Nuxt&Django REST FrameworkでCRUD GET編②](https://qiita.com/KueharX/items/48d44db339e4a2fbaa71)
- [Nuxt&Django REST FrameworkでCRUD POST編](https://qiita.com/KueharX/items/66117493b1a74fab943a)
- [Nuxt&Django REST FrameworkでCRUD PUT,DELETE編](https://qiita.com/KueharX/items/1c12e5f850cd8eeb875e)
- [NuxtでボタンをクリックしたときにToastが出てURLをコピーする機能の実装](https://qiita.com/KueharX/items/0e7731de1f6faeb6e3de)
- [Nuxt.jsを短期間でFirebaseにデプロイしてCircleCIで自動デプロイをするところまでを設定するマニュアル①デプロイまで](https://qiita.com/KueharX/items/b2636c07e127514e4e39)
- [Nuxt.jsを短期間でFirebaseにデプロイしてCircleCIで自動デプロイをするところまでを設定するマニュアル②自動デプロイの設定](https://qiita.com/KueharX/items/ed73d209e51a37bf5246)
【Android】RecyclerViewでスマートにコレクション画面の実装をする

コレクション画面(=なにかしらの一覧画面)を実装する際にRecyclerViewをよく使うと思います。
僕としては複雑なViewTypeを比較的簡単に作り分けるために、[Epoxy](https://github.com/airbnb/epoxy)のような便利なライブラリを使うことが多いのですが、弊社の新人研修の課題で久しぶりにAdapterを書く機会があったので、その時の実装をメモ程度に残しておきます。

## 差分を比較する
どの値を比較して、差分とみなすかを定義します。
下記では単に比較対象の `equals` に従って比較しています。

```MyDiffable.kt
interface Diffable {
    // otherと同じIDを持つかどうか
    fun isTheSame(other: Diffable) = equals(other)

    // otherと完全一致するかどうか
    fun isContentsTheSame(other: Diffable) = equals(other)
}

private class Callback(
    val old: List<Diffable>,
    val new: List<Diffable>
) : DiffUtil.Callback() {

    override fun getOldListSize() = old.size
    override fun getNewListSize() = new.size

    override fun areItemsTheSame(
        oldItemPosition: Int,
        newItemPosition: Int
    ) = old[oldItemPosition].isTheSame(new[newItemPosition])

    override fun areContentsTheSame(
        oldItemPosition: Int,
        newItemPosition: Int
    ) = old[oldItemPosition].isContentsTheSame(new[newItemPosition])
}

fun calculateDiff(
    old: List<Diffable>,
    new: List<Diffable>,
    detectMoves: Boolean = false
): DiffUtil.DiffResult = DiffUtil.calculateDiff(Callback(old, new), detectMoves)
```

## Entityの実装
Diffableを継承したEntityをつくります。
data classにはDiffableの差分計算に必要なequalsメソッドが既に定義されているので、それをそのまま使います。

```HogeItem.kt
data class HogeItem(
    val id,
    val name
) : Diffable
```

## Adapterの実装
Viewの余計な更新が行われるのを防ぐために、デリゲートで差分を計算してから更新を伝えるようにします。

```HogeAdapter.kt
class HogeAdapter(
    lifecycleOwner: LifecycleOwner,
    private val viewModel: HogeViewModel
) : RecyclerView.Adapter<HogeAdapter.ViewHolder>() {

    private var items: List<HogeItem> by Delegates.observable(emptyList()) { _, o, n ->
        calculateDiff(o, n).dispatchUpdatesTo(this)
    }

    init {
        viewModel.hogeList.observe(lifecycleOwner) { items = it }
    }

    override fun getItemCount() : Int { /* ... */ }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { /* ... */ }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) { /* ... */ }

    class ViewHolder(val binding: HogeItemBinding) : RecyclerView.ViewHolder(binding.root)
}
```

## 利用側の実装
LiveDataの監視はAdapter側で行っているので、ViewではRecyclerViewにAdapterを設定するだけでよくなります。

```HogeActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding.hogeRecyclerView.adapter = HogeAdapter(this, viewModel)
}
```
```HogeFragment.kt
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    binding.hogeRecyclerView.adapter = HogeAdapter(viewLifecycleOwner, viewModel)
}
```

## まとめ
APIで取得したデータを必要最低限のViewの更新で反映できるので、大規模なコレクションではパフォーマンスの向上やUXの改善に繋がります。
catalinaでmampのパスが通らない場合について

macOSをcatalinaの環境下でphpをデフォルトからMAMPへ~/.bash_profileでPATHを通し切り替えを行ってもターミナル再起動後反映しなかったので解決方法をまとめました。


#結&nbsp;&nbsp;論
catalinaにOSをアップデートするとデフォルトシェルが「bach」から「zsh」へ変更になり、デフォルトのphpをMAMPのphpに切り替え~/.bash_profileに設定してもターミナル再起動後はPATHは通らない。

シェルを【bash】に切り替えればターミナルを再起動しても設定したものが反映される。

###環境 

* macOS 10.15 (catalina) 
* MAMP　version5.5


######今までの.bash_profileへの設定方法<br>
基本的な操作は下記の記事参照
https://qiita.com/kurosu93/items/6cf23669d718fc6e0adb


##一連の流れに沿っても.bash_profileを書き換えてもcatalina以降シェルが【zsh】のままだとPATHが通らない
今までのmacOSのデフォルトシェルは【bach】だったので上記の記事の通りに**.bash_profile**へ設定してあげればPATHが反映しましたが**catalina**からデフォルトのシェルがzshになってしまったので.bash_profileへPATHを設定すれば一時的には反映はしますが、
ターミナルを再起動するとPATHはうまく反映しなくなる
<br>
<br>
再起動後のターミナルでPATHの確認

```
# php -v
-bash: php: command not found
```

上記のようにターミナル再起動後はPATHが見つからないoｒ元に戻るなど設定したものが反映しなくなる
(phpをMAMP切り替えたいのに…）
<br><br>



####解決方法　シェルを【zsh】から【bash】へ切り替える

シェルの切り替え方法は下記の記事参照

https://qiita.com/___xxx_/items/c9a30e78196998f4160c



catalinaでMAMPのパスを変更したい場合は

１　シェルを【zsh】から【bach】に変更する

２　シェル変更後に~/.bash_profileのPATHを書き換える

上記の順番で設定するとパスが通るようになります


##なぜシェルが【zsh】だと~/.bash_profileへ反映しないのか？
それはそもそも.bash_profileはシェルがbash用の設定ファイルだから。

.bach_profileはbach用のシェルスクリプトなので設定されているシェルがzshなのでどんなに設定しても再起動するとシェルがzshに戻ってしまい何度やってもbashのPATHは読み込まれないようです。
<br><br>



####どうしてcatalinaからシェルがzshに変わったのか興味がある人は下記の記事を参考にしてください
（どうやらライセンスの関係のようです）

参考記事

https://www.softantenna.com/wp/mac/macos-catalina-zsh-default/
AmazonLinuxに作業用ユーザを追加するTeraTermマクロ

# Amazon LinuxをLaunchして最初にやりたい作業用ユーザの追加をTeraTermマクロでやる
## TeraTermマクロを用意する
"USERID" のところに、作りたいユーザ名を入れて、拡張子 ".ttl" で保存

```
USERID = 'hirohiro-kun'

sendln 'sudo su'

wait 'root'
sendln 'adduser 'USERID

wait 'root'
sendln 'usermod -G wheel 'USERID

wait 'root'
var3a = 'echo "'
var3b = ' ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers'
sendln var3a USERID var3b

wait 'root'
sendln 'su - 'USERID

wait USERID
sendln 'mkdir .ssh && chmod 700 .ssh && touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys'

wait USERID
sendln 'ssh-keygen -t rsa'
wait 'Enter file in which to save the key'
sendln
wait 'Enter passphrase'
sendln
wait 'Enter same passphrase again'
sendln

wait USERID
sendln 'cat .ssh/id_rsa.pub >> .ssh/authorized_keys'

wait USERID
sendln 'exit'

wait 'root'
var1a = 'cp /home/'
var1b = '/.ssh/id_rsa /home/ec2-user/'
var1c = '.pem && exit'
sendln var1a USERID var1b USERID var1c

wait 'ec2-user'
var2a = 'sudo chmod 644 '
var2b = '.pem && ls'
sendln var2a USERID var2b

end
```

## ec2-userでAmazon Linuxにログインする
いつもどおりの方法でログイン

## マクロを実行する
TeraTermメニューの[コントロール → マクロ] をクリックして、作っておいた .ttl ファイルを開く

## 秘密鍵をダウンロード
ec2-user の home directory に USERID.pem ファイルが出来るので、ダウンロード

## 秘密鍵を使ってログイン
ec2-user ではなく USERID と USERID.pem を使って、いつもどおりの方法でログイン
javascript超入門(2020/06/12)

###JavaScriotとは
javascriptはブラウザ操作するためのプログラミング言語で、HTMLやCSSだけではできないことをするために使う。

- ブラウザで実行され、ブラウザを操作することができる -
- HTMLやCSSにはできないことをするために使う
- HTMLやCSSをリアルタイムに書き換えることができる

###javascriptファイルを読み込む


```html:sample.html
<script src="script.js"></script>
```
###ストリクトモード
```javascript:sample.js
'use strict';
```
プログラムの冒頭に書いて、ブラウザで新しいjavascriptを実行するモードであるストリクトモードにする。


###コメント文
```javascript:sample.js
//単一行コメント

/*
複数行にまたがる
コメント
*/
```


###console.log()
console.log()は（）内に指定したテキストや数式に計算結果などをコンソールにアウトプットする機能


###オブジェクト、メソッド、パラメータ
console.log('テキスト')において、
consoleはオブジェクト、log()はメソッド、'テキスト'はパラメータ
という。

###アラートダイアログボックス
```javascript:sample.js
window.alert('テキスト');
```
アラートダイアログボックスを表示し、そこに()内の文字列を出力する。


###要素の取得
```javascript:sample.js
document.getElementById('id名');
```
（）内のID名を持つ要素を取得する



###要素のコンテンツを書き換える
```javascript:sample.js
document.getElementById('id名').textContent = '書き換えたい文字列';
```
取得したHTMLの要素のコンテンツを書き換える



###確認ダイアログボックスを表示する
```javascript:sample.js
window.confirm('テキスト');
```
確認ダイアログボックスを表示し、()内の文字列をダイアログウィンドウに表示する。
OKをクリックしたときはtrue、キャンセルをクリックしたときはfalseという値を返す。
true,falseはブール値という。


###if文
```javascript:sample.js
if(条件式)　{
　　条件式がtrueになるときに実行する処理
} else {
　　条件式がfalseになるときに実行する処理
};
```

if文は()内がtrueのときその次の｛｝に書かれたプログラムを実行する。また、falseのときelse以降の｛｝に書かれたプログラムを実行する。
else以降は省略可。その場合はfalseのとき何も起こらない。


###変数
ある行で得られたデータを次の行以降でも使いたい場合はそのデータを保存する必要がある。その保存のために使うのが変数。
以下のパターンで使う。
　1.変数を定義する
　2.変数にデータを代入する。
　3-1.変数からデータを読み取る
　3-2.変数のデータを書き換える
3-1,3-2は順序が入れ替わることがあり、3-2は一度もしないようなプログラムもある。


1.変数を定義する

```javascript:sample.js
let answer
```
これはanswerという名前の変数を定義している。letに続けて半角スペース、その後に変数の名前を書けばその変数名を持つ変数が定義できる。

2.変数にデータを代入する
データを入れることを代入するという。
代入するときは変数名に続けて＝、さらにその右側に保存しておきたいデータを書く。

```javascript:sample.js
let answer = window.prompt('テキスト');
```
この場合は変数answerに、winsow.prompt('テキスト')が代入される。promptメソッドにはリターンがあるので、結果的に変数answerには、プロンプトに入力されたテキストが代入される。

3-1.変数からデータを読み取る
変数に保存したデータを読み取るときは、定義した変数名をそのまま書く。

```javascript:sample.js
console.log(answer);
```
3-2.変数のデータを書き換える
変数のデータを書き換えるには 2. の代入する と同じことをする。



###代入演算子（＝）
＝は右側のデータを左側の変数やプロパティなそに代入する役割をする記号。


###定数
定数とは定義したときに代入したデータを後から書き換えることができない、変数の一種。定数を定義するときはletの代わりにconstを使う。
あとからデータを書き換えられないため、定数は定義する同時に代入する。

```javascript:sample.js
const answer =window.prompt('テキスト');
```

###===
===は左右が同じであれば評価結果がtrue
Black Lives Matter (BLM) に言及したオープンソースプロジェクト一覧

# Angular
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/a333e06d-31e6-0564-9e2c-e08757909f76.png)

# Django
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/b8c7c089-0bf3-fe97-d500-e61b88f70f76.png)

# Electron
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/6ad184a6-f1aa-2699-c3f0-7a732d560762.png)

# Express
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/ff6fd29b-05f7-87fc-14c8-7eed34995955.png)

# Fastify
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/18ac29ec-41d7-bcd4-f7a0-c374cefe682d.png)

# Flutter
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/740d319c-656a-0174-0b86-d446b9d3f867.png)

# Go
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/451e5632-3fda-776f-4992-0290089624f1.png)

# jQuery
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/be156c97-2088-61e6-9ebe-e3a717e0998e.png)

# kubernetes (k8s)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/7808197d-6e52-19ec-ded2-62931b62a7cd.png)

# NodeJS
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/4d3a7d52-ab1d-7ddc-8ac0-ff79c1ed6deb.png)
中略
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/28b866b9-f265-149d-4d61-52e470b4fb79.png)

# React
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/85bf6b73-42ec-fb02-e5a6-b53041cb3e9f.png)

# Selenium
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/2fc9197a-c057-5e7f-a391-151911e14a16.png)

# TypeScript
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/805f0281-b042-5632-0145-c25266917de6.png)

# Vue.js
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/b8d9233d-a2b4-8725-1b94-a5c1512f1db5.png)

# Webpack
![EZgGHtgVAAA5-qH.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19148/bbb1c60d-c4cf-4044-777b-d2964e823e37.jpeg)

その他
https://github.com/stackshareio/dev-tools-for-blm
Perl のライブラリーがインストールされているか確認するプログラム

Perl のライブラリーがインストールされているか確認するサンプルプログラムです。
Raspberry Pi で確認しました。

Jcode

```pl:jcode_check.pl
#!/usr/bin/perl
#
use Jcode;

$val1 = Jcode->new("秋葉原UDX")->utf8;
print "$val1\n";

$val2 = Jcode->new("秋葉原UDX","utf8")->utf8;
print "$val2\n";

$val3 = Jcode->new("秋葉原")->utf8;
print "$val3\n";
```

実行結果

```text
$ ./jcode_check.pl 
遘玖痩蜴欟DX
秋葉原UDX
秋葉原
```

Image::Magick

```pl:image_magick_check.pl
#! /usr/bin/perl
#  
use Image::Magick;
 
$filename = "sample01.jpg";
my $image = Image::Magick->new;
$image->Read("$filename");

my ($width, $height) = $image->Get('width', 'height'); 

print "width = " . $width . "\n";
print "height = " . $height . "\n";

undef $image; 
exit();
```

実行結果

```text
$ ./image_magick_check.pl 
width = 270
height = 180
```

LWP::Simple

```pl:lwp_simple01.pl
#! /usr/bin/perl

use LWP::Simple;
 $content = get("https://ekzemplaro.org/");
 die "Couldn't get it!" unless defined $content;

 print $content;
```

実行結果

```text
$ ./lwp_simple01.pl 
Wide character in print at ./lwp_simple01.pl line 7.
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="Pragma" content="no-cache" />
（省略）
```


Raspbian でのライブラリーのインストール方法

```bash
sudo apt install libjcode-pm-perl
```

```bash
sudo apt install libimage-magick-perl
```

```bash
sudo apt install libwww-perl
```
Rails Tutorial　第4章完了

#2020/6/10 0.5時間
6/8-9は会社なのでこの勉強はお休みです。

とはいえ、土日だけでは前回を思いだすだけでも時間がかかるので、毎日少しでもいいのでやることにしました。

実は始めからそのつもりでしたが、平日は時間が全く取れずやれていませんでした。

平日の朝、出社前の30分でちょっとだけやりました。
4.1まで完了です。
#2020/6/11 0.5時間
夕食後にやったのですが、途中で寝てしまいました。
””と''などについてやりました。
#2020/6/12 0.5時間
夕食後にやったのですが、途中で寝てしまいました。
Objectなどについてやりました。
#2020/6/13 2時間
土日は朝にやれるので進みました。
#2020/6/14 2時間
4.3まで完了しました。
#2020/6/15 2時間
この日は有休をとったので、朝にやれました。

これで4章を完了しました。
所要時間は7.5時間です。

感想ですが、RUBYは直前にドットインストールをやったので理解が速かったです。
演習も無事できました。

consoleで試しながら書けるのは、結果がすぐに分かるので楽しいです。これがコンパイルして実行するやり方だと、結果が出て間違っていたときの、やり直すのに必要なパワーが1回1回は少しなのですが、だんだん疲れがたまっていくように感じます。

##演習4.4.5の自分の答えがネットの答えと違っていた

自分の答え

```ruby:example_user.rb
 def full_name
    "#{@first_name} #{@last_name}"
  end

  def formatted_email
    "#{full_name} <#{@email}>"
  end
```

ネットにあった他の答え

```ruby:example_user.rb
 def full_name
  @full_name = "#{@first_name} #{@last_name}"
 end

 def formatted_email
  "#{@full_name} <#{@email}>"
 end
```

他に、full_nameをself.full_nameにした答えもありました。自分の答えで動いたので、とりあえずよしとしました。
さくっとDaggerをHiltに対応する

# GradlePluginを追加

```gradle:build.gradle
buildscript {
    ext.hilt_version = '2.28-alpha'
    repositories {
        ...
        google()
    }
    dependencies {
        ...
        classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
    }
}
```

# Dependencyを追加

```gradle:app/build.gradle
...
apply plugin: 'dagger.hilt.android.plugin'

android {
  ...
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

dependencies {
    ...
     kapt "com.google.dagger:dagger-compiler:$versions.dagger2"
     implementation "com.google.dagger:hilt-android:$hilt_version"
     kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
}
```

# Annotationを追加

```kotlin:App.kt
@HiltAndroidApp
class App : MultiDexApplication() {
    ...
}
```

```kotlin:AppComponent.kt
@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
    @Component.Factory
    interface Factory {
        fun create(@BindsInstance context: Context): AppComponent
    }
}
```

```kotlin:AppModule.kt
@Module
@InstallIn(ApplicationComponent::class)
open class AppModule {
    ...
}
```

```kotlin:MainActivity.kt
@AndroidEntryPoint
public class MainActivity: AppCompatActivity() {
    ...
}
```

```kotlin:MainModel.kt
@Singleton
class MainModel @Inject constructor(
    @ApplicationContext context: Context
) {
    ...
}
```
AntとMavenは知っている人のためのGradle

## Gradleとは

公式: [Gradle](https://gradle.org/)
[いまさら Gradle を使ってみた](https://qiita.com/kazu_coeur/items/16e7f5c2fea54eb5eebf) の説明が分かりやすい。

### 簡単にサマリ

#### Ant 

[【超初心者向け】Ant超入門 - Qiita](https://qiita.com/tarosa0001/items/93c19155bc803f10cea0)

功績: ビルドツールのデファクト

が、結果 `ビルド職人にしか読めない build.xml が横行。ライブラリーの依存関係、プロジェクト毎に異なるディレクトリー構成` 等が問題になった。


#### Maven 

[【超初心者向け】Maven超入門 - Qiita](https://qiita.com/tarosa0001/items/e5667cfa857529900216)

功績: 「規約」という概念でこれらの問題を解決した。

しかし `XML の限界`に差し掛かる。`自身が持つ強い規約を XML とプラグインだけで解決しようとしているので、ちょっとだけ手を加えるということが非常に苦手。プラグイン開発の敷居の高さもあって、ほとんどの場合は「Maven で出来ることをやる」と言ったビルドツール支配型になった。`

そこで

#### Gradle 登場

Gradle は Maven がもたらした規約を尊重しつつも、XML ではなくスクリプトを導入することでビルド周辺の諸問題を解決しようとするもの。


## 参考

[多分わかりやすいGradle入門](https://tech-lab.sios.jp/archives/9500)
[Gradle入門](https://qiita.com/vvakame/items/83366fbfa47562fafbf4)
[MavenとGradleを比べてGradleがいいんじゃないかなって思う理由](http://sassembla.github.io/Public/12:05:27%2018-03-20/12:05:27%2018-03-20.html)
Windows10環境にEmacs+howmを設定する方法

##モチベーション
Windows版Emacsへのhowm設定を環境が変わるたびに何度も行っている。
その都度Google検索しながら設定しているが、最近はhowmユーザが減っているのか該当の記事がどんどん無くなっている。
そのため、備忘のために一旦自身でまとめておくことにした。
かなりニッチな情報なので、このページが他の誰かの役に立つかは未知数。
表現が正しくない部分があるかもしれませんがご了承を。

##ソフトバージョン
以下のソフトバージョンを利用した。

- emacs-26.3-x86_64
http://ftp.jaist.ac.jp/pub/GNU/emacs/windows/emacs-26/

- howm-1.4.6
https://howm.osdn.jp/

Emacsは解凍後、Cドライブ直下に配置した→`C:\emacs-26.3-x86_64`
howmは解凍後、こちらに配置した→`C:\emacs-26.3-x86_64\share\emacs\site-lisp\howm-1.4.6`

##設定方法

###1. 環境変数の設定
WindowsのEmacsのホームはWindowsの環境変数「HOME」の値になる。

デフォルトでは（環境変数「HOME」未設定の場合）Emacsのホームは
`C:\Users\<Winユーザ名>\AppData\Roaming\`になる（変な場所...）
そのため、初回にRunEmacs.exeを実行すると
`C:\Users\<Winユーザ名>\AppData\Roaming\.emacs.d`が自動作成される。

###2. init.elにhowmの設定を記載
`~/.emacs.d/init.el`に以下を記載する。
howm-directory は**howmのメモの置き場所**であり、howmの本体のPathではない。
Pathの記載はWindows風とLinux風どちらも可能。

- Linux風： `~/.emacs.d/howm`
- Windows風：`c:\\emacs\\howm` ※バックスラッシュ2つ！

```emacs-lisp

;howmの設定：はじめて C-c , , した時に読み込む
(setq howm-menu-lang 'ja)
(global-set-key "\C-c,," 'howm-menu)
(autoload 'howm-menu "howm" "Hitori Otegaru Wiki Modoki" t)
(setq howm-directory "~/.emacs.d/howm" );メモを置く場所
```

場合によっては、以下のケースがあるので注意。

- `~/.emacs.d/init.el`が生成されていない時は自分で作成する。
- ホーム直下に`~/.emacs`が自動生成されている場合はそちらに設定しても良い。

###3. howmの本体をsite-lispに置く
**[ソフトバージョン](#ソフトバージョン)に記載した通り**、howmの本体「howm-1.4.7」を`site-lisp`フォルダ配下に置く。
Windows版Emacsでは、site-lispは以下にある
`C:\emacs-26.3-x86_64\share\emacs\site-lisp`
  
init.elに設定することで、site-lispの場所を指定することも可能（わざわざしないけど）
以下は`C:\Users\<Winユーザ名>\AppData\Roaming\.emacs.d\site-lisp`としたい場合の例

```emacs-lisp

;site-lispの場所をカスタマイズする場合
(let ( (default-directory
         (file-name-as-directory (concat user-emacs-directory "~/.emacs.d/site-lisp")))
       )
  (add-to-list 'load-path default-directory)
  (normal-top-level-add-subdirs-to-load-path)
  )
```

###4. いざ実行
`C:\emacs-26.3-x86_64\bin\runemacs.exe`を実行し、
Emacs上で `Ctrl-c ,,` を実行する。howmの画面が表示されたら完了。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655928/99ea6559-5935-f0d1-c087-aba97afdcf7b.png)
[エラー]An error occurred while installing pg (1.2.3), and Bundler cannot continue.の解決法

# 背景
タイトルのエラーが発生し、路頭に迷い込んでいましたが、意外と簡単に解決したので一応記事にしておこうかなと思います。

## 解決策
結論、postgresql本体は入っていたが、develが入っていなかったよう。

```
$ sudo yum install postgresql-devel
```

## 最後に
自分の状況としては、本番環境のDBをpgにして、バージョン等を新しくしたので色々とごちゃごちゃしてややこしくなった結果、develを入れ忘れていたというような感じです。。
もし、同じ人がいたときように書いたんで参考までに。
`derive_class_name': stack level too deep (SystemStackError) にハマった

#stack level too deep エラーの解決について

今回上記エラーによりrails s およびrail c（というか多分全railsコマンド）ができなくなり、その解決方法を備忘録的に記載しておきたい。


##症状


```ruby:console
rails  s
```

とすると

```ruby:console
=> Booting Puma
=> Rails 5.2.0 application starting in development 
=> Run `rails server -h` for more startup options
Exiting
Traceback (most recent call last):
        11639: from bin/rails:4:in `<main>'
        11638: from bin/rails:4:in `require'
        11637: from /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/railties-5.2.0/lib/rails/commands.rb:18:in `<top (required)>'
        11636: from /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/railties-5.2.0/lib/rails/command.rb:46:in `invoke'
        11635: from /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/railties-5.2.0/lib/rails/command/base.rb:65:in `perform'
        11634: from /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/thor-0.20.0/lib/thor.rb:387:in `dispatch'
        11633: from /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/thor-0.20.0/lib/thor/invocation.rb:126:in `invoke_command'
        11632: from /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/thor-0.20.0/lib/thor/command.rb:27:in `run'
         ... 11627 levels...
            4: from /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.0/lib/active_record/reflection.rb:991:in `derive_class_name'
            3: from /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.0/lib/active_record/reflection.rb:790:in `source_reflection'
            2: from /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.0/lib/active_record/reflection.rb:769:in `klass'
            1: from /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.0/lib/active_record/reflection.rb:162:in `class_name'
/home/ec2-user/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.0/lib/active_record/reflection.rb:991:in `derive_class_name': stack level too deep (SystemStackError)
```

となった。

##原因

開発中のアプリにテーブルを３つ追加したタイミングで発生したため、どのテーブル（モデル）に問題があったのかを調べるため、１つずつSchemaに記述していき、洗い出した。（ちなみにridgepole gem使用環境下である）

その後、testsテーブルを該当テーブルと同一内容で作成していき、どのタイミングでエラーが起こるようになるか調べた。

するとtest.rb（modelファイル）に該当テーブルと同じアソシエーション記述をしたタイミングでrails sができなくなったため、アソシエーション記述に問題があると判明。

よく見ると以下のように記述されていた。

```ruby:test.rb
#hogesは中間テーブル名
has_many: hoges, through: :hoges
```


中間テーブル経由で中間テーブルとN:Nの関係を記述していたことが判明。

下の記事の回答でもあるが、再帰の問題でエラーを起こしていたっぽい（ケースは異なるが）。
https://teratail.com/questions/56653


##解決策
コードを以下のように修正。

```ruby:hoge.rb
#fugasはアソシエーション持ちたいテーブル
has_many: fugas, through: :hoges
```

すると問題なくrails sできるように復活。
再帰の問題についてはもっと詳しく学ぶ必要性がありそう。
CSSで複数行下線が正しく表示されないとき

CSSで複数行の下線を引く場合、以下のサイトを参考に実装してみました。

https://wemo.tech/270

やり方としては下線を引きたい箇所に以下のクラスを付与したspanタグなどで囲うことで実現できます。

```css
.under_line {
  background: linear-gradient(transparent 70%, #eb4034 0%);
  display: inline;
}
```

しかし、どうしたことかうまく適応されませんでした。

### 親要素のdisplayに注目
親要素のdisplayがflexだった場合、このCSSがうまく適用されないことがわかりました。
ですので、例えば以下のようなHTMLの場合

```html
<h1>
  <span class="under_line">
    複数行になる文章
  </span>
</h1>
```

`h1`に`display: flex;`が適用されていると複数行に渡った下線になりません。

```html
<h1>
  <div class="headline-inner">
    <span class="under_line">
      複数行になる文章
    </span>
  </div>
</h1>
```

この様に`headline-inner`というクラスを付与した要素をはさみ、これを`display: block;`にすることで正しく下線が引かれます。
セマンティックかどうか微妙なので、`h1`や`p`などの要素に`display: flex;`を適用せずに、親要素を作ってそちらに`flex`をつけたほうが良いかなと思います。

DEMO
https://jsfiddle.net/kubotak/42L1y9mr/1/
AdMobをiOSに組み込んでみよう（環境設定編）

AdMobをiosに組み込んでみようという事で覚書
元にした内容
https://developers.google.com/admob/ios/quick-start?hl=ja
■Step1：必要なToolのインストール
---
・CocoaPodsのインストール
まずは、必要なToolをインストールするために「CocoaPods」をインストールします。
https://guides.cocoapods.org/using/getting-started
を参考にしてください。
■Step2：プロジェクト作成
---
・プロジェクトを作成
OSはiOSですね
Application：Single View App
を選択し「Next」を
![image0001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/088937b6-6bf1-f9a4-4328-934814dc04f6.png)
・プロジェクト名その他設定
今回はProduct Nameは「AdMob01」にしました
Language：Objectiv-C
User Inteface：Storybord
を設定したら「Next」でそのまま、流れでプロジェクトを作成します。
![image0002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/497130bc-1e5a-d6f1-d986-f7111d047413.png)
■Step3：プロジェクトにAdMobをインストール
---
・AdMobインストール前に
まずはXcodeを閉じてください。
・プロジェクトに移動
ターミナルでプロジェクトまで移動します。
![image0003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/aea1dfef-4dfd-7f4f-00ff-837f48baa54c.png)
・podの初期化

```text:
$ pod init
```
実行すると「Podfile」ファイルが作成されたのがわかると思います。
（「pod」命令を使うのですが、Setp1のToolがインストールされていないと動作しません）
![image0005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/52181096-da51-0887-8ed6-a3e94988156f.png)
・Podfile編集
作られた「Podfile」をテキストエディターで編集し

```text:
  pod 'Google-Mobile-Ads-SDK'
```
を追加してください（ToolはViでも好きなのでOKですね）
![image0006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/cd1d3024-d01d-3276-0b9d-7e4caedfb84f.png)
・podアップデート

```text:
$ pod install --repo-update
```
を実行し、Xcodeの環境に合わせた最新のAdMobを自動で更新します。
![image0008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/38cc6124-689d-79ef-2a30-7ed9c1f69a00.png)
これでインストール完了です。
■Step4：プロジェクト設定
---
・Xcode起動
起動するのは「AdMob01.xcodeproj」ではなく「AdMob01.xcworkspace」なので注意してください
![image0112.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/520685af-0145-654f-d9a3-7c73b0fe701d.png)
・Info.plistの設定
Info.pListに
Key:GADApplicationIdentifier
String:ca-app-pub-3940256099942544~1458002511
を追加。（Stringはデモ用なので、本番は正式なものにしてください）
![image0009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/ff392656-fb97-2a16-9982-87db1dca953f.png)
・AppDelegate.mを編集
「AppDelegate.m」に

```objective_c:
@import GoogleMobileAds;
```
と

```objective_c:
[[GADMobileAds sharedInstance] startWithCompletionHandler:nil];
```
を追加します。
![image0010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/468788ab-9efa-1dbb-600b-0517c6924381.png)
これで準備完了です。
■Setp5：広告
広告にはいくつかのパターンがあるのでそれに合わせて分岐します
・AdMobをiOSに組み込んでみよう（バナー広告編）
  https://qiita.com/sanoh/items/3ae4ca52f6155ac8bbaa
・AdMobをiOSに組み込んでみよう（全画面広告編）
  https://qiita.com/sanoh/items/d4b9fe265e8b28a7ae0b
・AdMobをiOSに組み込んでみよう（Video広告編）
  https://qiita.com/sanoh/items/098a4183dffc4ff82929
composerのscriptsからコマンドを実行する

composerにはnpmと同じようにscriptsを設定しておくと、composerのスクリプトとして実行できる機能があります。

npmのスクリプトに比べるとそんなに使われていないような気がしますが便利ですよ。

```json:composer.json
{
    "scripts": {
        "test-unit": [
            "@php vendor/bin/phpunit --testsuite Unit"
        ],
        "test-feature": [
            "@php artisan migrate:fresh --seed",
            "@php vendor/bin/phpunit --testsuite Feature"
        ]
    }
}
```
[簡単]Rubyとbundlerのバージョンアップ法

# 背景
rubyとbundlerのバージョンが古くて、デプロイ時にエラーが出まくってかなり苦労したんで、備忘録として書き残そうと思います。。

## Rubyのバージョンアップ
0.今回はRubyの2.6.3が無いこととする。

1.最新版をインストールする。

```
$ brew upgrade ruby-build
```

2.インストール可能なバージョンリストを表示して確認する。

```
Available versions:
  1.8.5-p52
  1.8.5-p113
  1.8.5-p114
  1.8.5-p115
  1.8.5-p231
  ---中略---
  2.5.4
  2.5.5
  2.6.0-dev
  2.6.0-preview1
  2.6.0-preview2
  2.6.0-preview3
  2.6.0-rc1
  2.6.0-rc2
  2.6.0
  2.6.1
  2.6.3
```

3.rbenvをインストールする。

```
$ rbenv install 2.6.3
```

4.インストールしたバージョンを使用するように設定する。
以下コマンド実行して、2.6.3に設定されていれば特に何もしなくて良い。

```
$ rbenv versions
  system
  2.4.1
  2.5.1
  2.5.3
* 2.6.3 (set by /Users/user_name/hoge/.ruby-version)
```

※環境全体のRubyバージョンを指定したい場合

```
 $ rbenv global 2.6.3
```

※特定のプロジェクトだけで指定したい場合(以下のコマンドを適用したいプロジェクトで実行)

```
$ rbenv local 2.6.3
```

5.bundlerをインストールする。

```
$ gem install bundler
```

6.Rubyのバージョンを最新安定版の2.6.3にupdateする。
※もしエラーが出た場合は、前ステップのbundlerのインストールをバージョン指定してみる。

```
$ bundle install --path=vendor/bundle
```
macOS Catalina で GeoIP を使う

# macOS Catalina で GeoIP を使う

 macOS Catalina になってからセキュアボリュームになったために、色々ツールが使えなくなって不便しているので、それらを少しづつ解消しようとゴチャゴチャやってる備忘録です。

## geoiplookup をセットアップ

brew が無い人だけ以下のコマンドを実行。（お約束ですね）

```bash
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" < /dev/null 2> /dev/null
```

まずは geoip と geoipupdate をインストール。

```bash
$ brew install geoip
$ brew install geoipupdate
```

GeoLite が使えなくなっているので、以下のリンクから GeoLite2 のデータダウンロードができるようにアカウントを登録。
[MaxMind User Registration](https://www.maxmind.com/en/geolite2/signup)

登録が完了したら以下の3つをダウンロード。（解凍しなくてOK）

```
GeoLite2-Country-CSV_20200609.zip
GeoLite2-City-CSV_20200609.zip
GeoLite2-ASN-CSV_20200609.zip
```

変換ツールをゲットしてダウンロードデータを変換。（*** 部分は自分のユーザ名に）

```bash
$ cd
$ git clone https://github.com/sherpya/geolite2legacy.git
$ cd geolite2legacy/
$ pip install -r requirements.txt
$ ./geolite2legacy.py -i /Users/****/Downloads/GeoLite2-Country-CSV_20200609.zip -f geoname2fips.csv -o GeoIP.dat
$ ./geolite2legacy.py -i /Users/****/Downloads/GeoLite2-ASN-CSV_20200609.zip -o GeoIPASNum.dat
$ ./geolite2legacy.py -i /Users/****/Downloads/GeoLite2-City-CSV_20200609.zip -f geoname2fips.csv -o GeoIPCity.dat
$ sudo cp ./GeoIPCity.dat /usr/local/var/GeoIP/GeoLiteCity.dat
$ sudo cp ./GeoIP.dat /usr/local/var/GeoIP/GeoLiteCountry.dat
$ sudo cp ./GeoIPASNum.dat /usr/local/var/GeoIP/GeoIPASNum.dat
```

テストしてみましょう。

```bash

Mac-mini $ geoiplookup www.metro.tokyo.lg.jp
GeoIP Country Edition: JP, Japan
GeoIP City Edition, Rev 1: JP, 40, Tokyo, Katsushika, 124-0021, 35.739498, 139.867203, 0, 0
GeoIP ASNum Edition: AS10021 KVH Co.,Ltd
```

OK そうですね！！ それではまた！！

c u
ルービックキューブを解くロボットを作ろう！1 概要編

# 前書き
こんにちは、Nyanyan(読み方は一応「にゃにゃん」)です。今回から何回かにわたって、私が作ったSoltvvo(そるゔぉー): 2x2x2のルービックキューブを解くロボットの解説をしていきます。記事の構成は
1. 概要編(本記事)
2. [アルゴリズム編](https://qiita.com/Nyanyan_Cube/items/60f3699db96dba4a4bf5)
3. [ソフトウェア編](https://qiita.com/Nyanyan_Cube/items/94bfa7b56c8ff69d94cd)
4. [ハードウェア編](https://qiita.com/Nyanyan_Cube/items/8bb5555497e745697412)
とします。
なるべく平易には書きますが、内容はかなり詳しく書く予定ですので、気になるところをつまみ食いしてくださっても結構です。なお、記事が完成し次第YouTubeにこの記事に関連する動画集を上げる予定です。この動画集では細かいところは伏せて、大雑把に概略を説明します。各記事の冒頭に動画を紹介しますので、よろしければご覧ください。

GitHubは[こちら](https://github.com/Nyanyan/soltvvo)。

# 想定された読者
* アルゴリズム(全探索)に興味がある方
* ロボットづくりに興味がある方
* ルービックキューブに興味がある方

# プロモーションビデオ
プロモーションビデオは[こちら](https://youtu.be/Fok7bAn-NSs)です。
[![Soltvvo](http://img.youtube.com/vi/Fok7bAn-NSs/0.jpg)](https://youtu.be/Fok7bAn-NSs)

# この記事に関連する動画集
プレイリストは[こちら](http://www.youtube.com/watch?v=9wuyo1KsjrM&list=PLwkf5JRsfk8OEn085444C6q4WWcrxCFgA)です。
[![ルービックキューブを解くロボットを作ろう！](http://img.youtube.com/vi/xl9qaEfAsIs/0.jpg)](http://www.youtube.com/watch?v=9wuyo1KsjrM&list=PLwkf5JRsfk8OEn085444C6q4WWcrxCFgA)

# プロジェクトのきっかけ
あの、ほら、暇じゃないですか。何か作りたいなと思ってとりあえず2x2x2を最短手数で解くプログラムを書いてみたら思いの外楽しくて、実際にこの手順を使って2x2x2を解くロボットを作れないかと思ったわけです。

# 前提知識
アルゴリズム編では平易に書くことを心がけるため、(所詮記事を書くのはAtCoder水色の人というのもあり)特に前提知識は想定していません。
ソフトウェア編ではPythonとC++(Arduino)を用います。これらの最低限の知識は必要だと思います。
ハードウェア編では、ところどころ専門用語が出てくるかもしれませんが、ググっていただければわかるものばかりだと思います。よって前提知識はいりません。
その他に、記事全体を通してルービックキューブに関する基礎知識が必要ですのでここで紹介します。

## ルービックキューブに関する基礎知識

### ルービックキューブの仕組み
ルービックキューブはよく「色を揃えるパズル」と言われがちですが、実際は**パーツの場所と向きを揃えるパズル**です。まず普通の3x3x3を分解した写真を載せましょう。
![分解.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494375/6746b80b-aff8-4bc4-7d1d-1bb0fd8edf57.png)
ルービックキューブの動くパーツにはエッジとコーナーの2種類があり、それぞれ形が違う(例えばエッジパーツには2つのステッカーが、コーナーパーツには3つのステッカーがついています)ため、エッジパーツがコーナーの位置に来る、またはその逆のことは起こりません。
2x2x2キューブの場合、構造は3x3x3と同様なものの、外見ではエッジパーツは内部に埋もれていてコーナーパーツのみ見える状態です。

### 回転記号
ルービックキューブの回転を表す記号として、回転記号というものが使われます。これは、キューブをある基準の向きで持った時に、
* 上の面を回す: U (Up)
* 下の面を回す: D (Down)
* 前の面を回す: F (Front)
* 後ろの面を回す: B (Back)
* 右の面を回す: R (Right)
* 左の面を回す: L (Left)
と表され、それぞれの文字(仮にXとします)について、「X」なら面を正面かあら見て時計回りに90度、「X'」は反時計回りに90度、「X2」なら180度回転させます。
参考として[triboxという会社のページ](https://tribox.com/3x3x3/solution/notation/)を載せておきます。

実は2x2x2キューブで使う回転記号の種類(回転させる面)はU, F, Rのみです。よく考えてみてください。Rを回すこととLを回すことは(キューブの向きが変わることを無視すれば)同値ですね。よって6面あるうちの3種類の面を回すだけですべてのぐちゃぐちゃ状態(スクランブル)を作り出せるのです。

# 最後に
では、長い記事集になると思いますが、楽しんで読んでいただければ幸いです！
[cx_Oracle入門](第5回) 日本語データの取り扱い

# 検証環境
- Oracle Cloud利用
- Oracle Linux 7.7 (VM.Standard2.1)
- Python 3.6
- cx_Oracle 7.3
- Oracle Database 19.5 (ATP, 1OCPU)
- Oracle Instant Client 18.5

# はじめに
過去の連載では日本語データを取り扱わない形で進めていました。ですが、この連載をご覧になるほとんどの方は、日本語環境で仕事をしていて、日本語データのOracle Databaseをご利用されていると思われます。今回は日本語が格納されているテーブルのSELECTを文字化けさせずに取り扱う方法を解説します。

# 事前準備
SQL*Plus, SQL Developer等を使用して、以下のスクリプトを流してください。日本語データの入っている、既存のテーブルを代用いただいても構いません。

```SQL:sample05a.sql
create table sample05a (col1 varchar2(50));
insert into sample05a values('日本オラクル株式会社');
commit;
```

# NLS_LANG
サンプルとして以下のアプリケーションを用意しました。
事前準備で別のテーブルを用意された方は、1列目に日本語データの列が指定される形でSELECT文を変更して実行してください。その場合、このサンプルアプリケーションは1行しか表示しないので、WHERE句で主キー指定で1件に絞り込むなり、最初の1行に行数制限するなりの措置も実施していただけると、余計な処理時間を取りません。

```python:sample05b.py
import cx_Oracle

USERID = "admin"
PASSWORD = "FooBar"
DESTINATION = "atp1_low"
SQL = "select * from sample05a"

with cx_Oracle.connect(USERID, PASSWORD, DESTINATION) as connection:
        with connection.cursor() as cursor:
                print((cursor.execute(SQL).fetchone())[0])
```

一般的にOracle Databaseにアクセスするアプリケーションを稼働させる際に日本語への対応が必要な場合、大抵の環境では環境変数NLS_LANGを設定する必要があります。cx_Oracleにおいても、バージョン7.3まではNLS_LANGは有効です。バージョン8以降については後述します。上記アプリケーションをNLS_LANGの有無で比較したのが以下になります。

```
$ echo $LANG
en_US.UTF-8
$ echo $NLS_LANG

$ python sample05b.py
??????????
$ export NLS_LANG=japanese_japan.al32utf8
$ python sample05b.py
日本オラクル株式会社
```

NLS_LANG設定前は「??????????」と、データが正しく表示できていません。
Oracle Databaseでは、DBとクライアント間の文字コード変換ができない場合は「?」を表示します。NLS_LANGを設定した後は正しく表示できています。

# encoding引数
cx_Oracleには、NLS_LANGとは別に、接続時(cx_Oracleのconnect()メソッド)の引数encodingに、文字エンコーディングの指定が可能です。encoding引数のデフォルトはバージョン7.3まではNoneで、何も設定されていません。バージョン8からはUTF-8がデフォルトとなり、環境変数NLS_LANGのキャラクタセットの指定は無視されます。なお、バージョン8以降においても、キャラクタセット以外の設定は有効です。
Python3においてはUTF-8が標準なので、バージョン7.3まではencodingにUTF-8を指定して接続すれば(バージョン8以降はエンコーディングの指定なしで)、NLS_LANGの設定がなくとも日本語データの表示が可能です。とはいえ、例えばOracle Databaseのエラーメッセージを日本語で受け取りたい場合はNLS_LANGが必要です。また、SQL*PlusなどPython以外のアプリケーションへの考慮も必要です。

```python:sample05c.py(抜粋)
with cx_Oracle.connect(USERID, PASSWORD, DESTINATION, encoding="UTF-8") as connection:
```

# 変更履歴
- 2020/6/28 バージョン8での仕様変更を含んだ形に改定
【環境変数】 rails 環境変数とは

##【ゴール】
環境変数を使用して、アプリケーショへの情報を埋め込む

##【メリット】
■　漏れたくない情報をアプリケーション内で使用できる
■　セキュリティ向上
■　各種APIに使用できる

##【開発環境】
■ Mac OS catalina
■ Ruby on Rails (5.2.4.2)
■ Virtual Box:6.1
■ Vagrant: 2.2.7

##【実装】

## gem 'dotenv-rails'をインストール

```アプリケーション.Gemfile
gem 'dotenv-rails'
```

```mac.terminal
bundle install
```

##app直下に「.env」を作成する
※こんな感じになるように。（真ん中あたりにあります。）
![スクリーンショット 2020-06-15 12.06.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620689/d48777b2-8134-063e-ff43-f96058a3dcb3.png)

##.envに記述していく

```アプリケーション内.env
#google omniauth 2.0用
GOOGLE_APP_ID='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
GOOGLE_APP_SECRET='xxxxxxxxxxxxxxxxxxxxxxxxxx'

#デプロイ設定
DB_USERNAME='xxxxxxxx'
DB_PASSWORD="xxxxxxxxx"
DB_HOST="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
DB_DATABASE="xxxxxxxxxx"

#メール機能実装
USER_NAME="txxxxxxxxxxxx"
USER_PASSWORD="xxxxxxxxxxx"
```

以上
後は使いたいサービスや、アプリケーションによってコードを増やしていく。
初めての投稿２、マークダウン記法練習

#具体的で簡潔なタイトルをつける
記事のタイトルは、記事のページだけでなくQiitaのフィードやGoogleの検索結果にも表示されます。タイトルを見ただけで記事の中身を想像できるようにしましょう。

##具体的なタイトルをつけることで、特定の情報を探している人が記事を見つけやすくなります。

例：

1.「Rubyメモ」→「Rubyの定数探索はスコープと継承関係のどちらが優先されるか」
2.「正規表現でハマった」→「RubyとJavaScriptの正規表現では複数行モードの意味が違う」
3.「OpenSSLのバグ」→「CentOS 6.5でOpenSSLのHeartbleedバグにパッチを当てた」
#環境や前提条件を説明する
記事で取り上げたソフトウェアのバージョンは何か、記事中のコードを実行するためにはどんな手順が必要かを書いておくと、自分の環境に当てはまるかどうかを後から読む人が判断しやすくなります。

例：

この記事ではCentOS 6.5にインストールしたRuby 2.2を使っています。
コードを実行するためには http://... で紹介されている設定ファイルが必要です。
コマンドライン引数に与えるユーザー名は適宜読み替えてください。
また、適切なタグをつけることで記事を見つけやすくなります。ある言語やライブラリの特定のバージョンについて話をするときは、タグにバージョンをつけてみましょう。例： Ruby:2.2

----------------------------------------------

#引用元や参考元へのリンクを書く
> url
[株式会社アーティス](http://www.asobou.co.jp/)の運営サイト
[名刺工房](http://meishi.artisj.com/index.html)

-------------------------------------------------

`var moge = 100;`

---------------------------------------------------
    var fuga = 1000;
    var fizz = 2000;
--------------------------------------------------------
```php
class Sample()
{
	private int $a;
	
	public function __construct(int $a)
	{
		$this->a = $a;
	}
	
	public function hoge(int $x, int $y):int
	{
		return ($x + $y) * $this->a;
	}
}
```
pythonのnumpyにおける行列の積

#numpyで行列積


```python:mat_multi.py

import numpy as np

a=np.array([[1,2], [3,4]])
b=np.array([[5,6], [7,8]])

#a.*b in MATLAB
x=a*b
print (x)
#[[ 5 12]
# [21 32]]

#a*b in MATLAB
y=np.dot(a,b)
print (y)
#[[19 22]
# [43 50]]

####################
#ご指摘頂きました．
y=a@b
でもいけるそうです．

```

MATLABとは逆なので要注意．