OmniAICreator/Qiita-1.07M huggingface dataset:
３分間ネットワーク備忘録

## 概要

３分ネットワークのウェブサイトを多くの人が聞いたことがあると思う。
私も数年前に一度一回勉強したのだが、その時は読んでいただけで、全くアウトプットできていなかった。

改めて今回、今度はノートに要所をまとめながら全体を読んだので、備忘録的に纏めていく。
あくまでも備忘録として、自分の取ったノートから抜粋したものを簡単にまとめる。

今回は、[３分間ネットワーク](https://www.google.com/search?q=3%E3%83%97%E3%83%B3%E3%82%AB%E3%83%B3%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AD%E3%83%B3%E3%82%B0&rlz=1C5CHFA_enJP906JP906&oq=%EF%BC%93%E3%81%B7%E3%82%93%E3%81%8B%E3%82%93%E3%81%AD&aqs=chrome.1.69i57j0.8334j0j7&sourceid=chrome&ie=UTF-8)の概要についてまとめる。


## はじめに
### ３分間ネットワークを知らない人たちへ

#### 専門書を読める人はそっちの方がいいと思う、、
ネットワークについて勉強しようと思った時、特にコンピュータサイエンスのバックグラウンドがない私のようなエンジニアが、
少しでも知識になればと思い、ぐぐると、有名な「マスタリング　TCP/IP 」https://www.amazon.co.jp/%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0TCP-IP-%E5%85%A5%E9%96%80%E7%B7%A8-%E7%AC%AC5%E7%89%88-%E7%AB%B9%E4%B8%8B/dp/4274068765
の本が出てくるが、なかなか初学者には敷居が高いようである。


#### ちょっと敷居が高い、もしくは無料でいい参考書がないかな、と探している人

私は、そういう方には[３分間ネットワーク](https://www.google.com/search?q=3%E3%83%97%E3%83%B3%E3%82%AB%E3%83%B3%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AD%E3%83%B3%E3%82%B0&rlz=1C5CHFA_enJP906JP906&oq=%EF%BC%93%E3%81%B7%E3%82%93%E3%81%8B%E3%82%93%E3%81%AD&aqs=chrome.1.69i57j0.8334j0j7&sourceid=chrome&ie=UTF-8)がおすすめだと思う。


博士と生徒の対話形式で、ところどころボケとツッコミを交えながら、前８０回程度でネットワークの入門部分が学べるのがこのウェブサイトである。
一回がだいたい３分で読めるように構成されており（たぶん）、それが故に３分間ネットワークという題名が付けられているのだと思う。
ただし、実際にゆっくり読み進めると、１記事１０分くらい平気でかかることもある。

#### たぶん無理をしなければゆっくり読み終えられる
なかなか参考書を勉強し始めると、モチベーションが続かずに途中で挫折してしまうことも多いと思う。
その点、[３分間ネットワーク](https://www.google.com/search?q=3%E3%83%97%E3%83%B3%E3%82%AB%E3%83%B3%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AD%E3%83%B3%E3%82%B0&rlz=1C5CHFA_enJP906JP906&oq=%EF%BC%93%E3%81%B7%E3%82%93%E3%81%8B%E3%82%93%E3%81%AD&aqs=chrome.1.69i57j0.8334j0j7&sourceid=chrome&ie=UTF-8)　のいいところであり面白いところは、
ネット君（学生）の覚えが悪いところを博士が毒舌でけなしながら進めていくところであるが、
このときに自分も覚えてなかった、、、と反省しながら学んでいけるところだと思う、笑


#### 取り扱っている内容
この８０回程度の記事を通して、OSI参照モデルを第一層から、第７層まで学習していく、
実際は６０回くらいで７層まで学習し終え、そのあとの２０回くらいは有名なプロトコル（HTTPやDNSなど）についての学習になる。
また、これが終わると３０分ネットワークというものもあり、そちらはまだ読んでいないが、内容が気になるところである。

#### 注意点
結構古い記事なので、少し書いてある内容が現在に即していないところもある。
例えば telnet の話が長く出てきたり、ipv4中心に話が書いてあったりなど。
ただ、全体的にとてもまとまっているし、基礎を学ぶという意味ではあまりマイナスではないのではないかと思う。


#### どう読み進めたか
一度に集中的に読んでもなかなか記憶に埋め込まれないことを前回学んだので、
今回は１日３記事くらい読むのを地道に繰り返した。
結果、前回一気に読んだ時よりも理解が深まった気がする。

また、きちんと要点をノートにとりながら勉強してみた。
前回はざっと流し読みして、各記事の最後の要点だけをチェックしたりしていたのだが、
そうすると読むこと自体がただの作業になってしまい、あまり関心を持って学習できなかったので、その反省点を反映した。



というわけで、
次回から纏めていきたいと思います。
皆さんも興味があれば是非コツコツ読んでみてください。
python matplotlibを用いた複数の表描出に関する疑問

pythonでのmatplotlibを用いたグラフ表記について調べている中で、以下のエラーが発生しました。pandasのdataframeから、複数の表を同時に作成しようとしたところ、表が重なってしまいうまく描画できませんでした。
環境：Python 3.8.2, matplotlib 3.2.1
```
fig,axes = plt.subplots(nrows=14,ncols=3)
for column in df.columns:
　　i=0
　　try:
　  　　 axes[i].plot(df[column],df['Y'],alpha=0.3)
　　　　　i = i+1
    　　except:
       　　　　　pass
```
「表が重なっている」という理由から、nrows=3,nrows=1に変更したところ、表がうまく描出できました。複数の表（例えば、14行*3列）を一度に描出する方法はあるのでしょうか。

駆け出しで拙い質問で申し訳ございません。
原因または解決法をご存知の方はコメントいただけますと幸いです。
初心者向けcronの簡単な使い方

#対象の方
cronを使ったことないけど、簡単に体験してみたい人向け

#環境
macOS
ターミナル

#できること
定期的に設定したコマンドを自動実行できる
※今回はローカル環境下なのでmac起動中のみ動作します

リモート環境で使えば、常時自動処理できるのでwebサービスではかなり重宝する機能です

#手順

##1.test.shの作成・編集

今回はホームディレクトリで作成していきます。
※絶対パスを調べて記載するので操作しやすい場所で問題ありません

```:ターミナル画面
touch test.sh
open test.sh
```

```test.sh
date >> testlog.txt
echo 'hello'
```

sh test.shでターミナル画面でシェルスクリプトを実行することができます


##2.test.shの実行権限を変更

```:ターミナル画面
chmod 755 test.sh        //実行権限の変更　
pwd                      //絶対パスの確認
```

##3.crontab -eで実行コマンドを追加

```:ターミナル画面
crontab -e
```

cron編集画面では
　i   →編集モード
　esc →編集モード終わり
　:wq →設定保存
で編集できます

```:crontab画面
*/1 * * * * /pwdで確認した絶対パスを記載/test.sh
~
~
~
```

保存後に認証画面が表示されるのでOKを選択してください
crontab -l　で設定を確認できます

実行間隔はいろいろと変更できますが今回は1分ごとに実行するように設定します

保存後一定時間経過後testlog.txtに時間が追記されていたら成功です
<img width="242" alt="スクリーンショット 2020-06-29 21.06.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648324/fadcaeec-0056-b405-886d-c69c599fa9b6.png">

##4.実行ログを残す方法

crontab -eで下のように編集します

```:crontab画面
*/1 * * * * /pwdで確認した絶対パスを記載/test.sh >> /pwdで確認した絶対パスを記載/test.log 2>&1
~
~
~
```

test.logにhelloが出力されれば成功です
※「>」はファイルの上書き、「>>」はファイルに追記の違いがあります

ログを残すことでエラーが出た時に対処しやすくなるので是非活用してみてください
ソフトウェアテストの意義・目的

#はじめに
ソフトウェアテストというと、後工程で作ったものを動作させる認識が多い。
もちろん、出来上がったものを動作させるテストも重要である。

ただ、それだけで終わるのであれば、製造（コーディング）している人がテストしているのと大して変わらない。
そうなると残念なテストだと思う。

それぞれシラバスや本には書かれている通りではあるが「テスト」と「チェック」の作業（アクティビティ）とは違うということを念頭に、テストの目的を自分なりに考えて整理をしてみた。


#テストの目的
JSTQBのシラバス（JSTQBの本）には以下のように書かれている。

* 要件、ユーザーストーリー、設計、およびコードなどの作業成果物を評価
* 明確にしたすべての要件を満たしていること
* ユーザーやその他ステークホルダーの期待通りの動作内容であることの妥当性確認
* 品質に対する信頼を積み重ねて、所定のレベルにあることを確証
* 欠陥の作りこみ防止
* 故障や欠陥を発見
* 品質レベルについての十分な情報を提供しステークホルダーの意思決定を助ける
* ソフトウェア品質のリスクレベルを低減
* 契約上、法律上、または規制上の要件や標準を遵守




## 要件、ユーザーストーリー、設計、およびコードなどの作業成果物を評価
テストはモノだけをターゲットに実施する作業（アクティビティ）ではなく、要件、仕様（開発設計、テスト設計）、開発物全てに対して評価をすることが大切。

局所的にモノだけをみていると、そもそも要件と合わないという事態が発生する。
そうなると、時間をかけて実装した機能やモジュールなどは役に立たないものとなる。これではだれも幸せになれない。

こういうことを防ぐためにも、全ての成果物を評価する必要がある。

## 明確にしたすべての要件を満たしていること
要件を満たしていることも大切。
盲目的に成果物のみを評価することにもつながるが、局所的にテストしていたら要件を満たしているか見えなくなる。

##ユーザーやその他ステークホルダーの期待通りの動作内容であることの妥当性確認
要件を満たしているかどうかだけの場合、本当に必要だった機能かを判断することが難しい。
よくある [風刺画](https://dic.nicovideo.jp/a/%E9%A1%A7%E5%AE%A2%E3%81%8C%E6%9C%AC%E5%BD%93%E3%81%AB%E5%BF%85%E8%A6%81%E3%81%A0%E3%81%A3%E3%81%9F%E3%82%82%E3%81%AE)にあるが、そもそも期待していたものか判断しなければならない。

##欠陥の作りこみ防止
修正に伴って怖いのはデグレ。元の機能の動作が変わったり、動作しなくなったり。
これが発生すると、もぐらたたきの状態になり、あっち直したらこっちがおかしくなるなど手に負えなくなる。
これを防ぐためにどこに波及するかを考えてテストしなければならない。


また、「欠陥」とは「コンポーネントまたはシステムに要求された機能が実現できない原因となる、コンポーネントまたはシステムに含まれる不備」とある。
「欠陥」は「エラー」により発生するものであり、「エラー」とは、「間違った結果を生み出す人間の行為」である。

つまり、要件定義、仕様、製造（プログラム）において全てのエラーを防止することが大切でテストのアクティビティである。

##故障や欠陥を発見
テストのメインのアクティビティではあるが、故障や欠陥が「0」はないはずである。（テストの7原則の1つ）
故障や欠陥はあることを示してリスクを示すものとしなければならない。

欠陥はプログラムだけではなく、仕様などのドキュメントにも含まれている可能性はある。



##品質レベルについての十分な情報を提供しステークホルダーの意思決定を促す
リリース判定というと厳粛な感じがするが、リスクを示してステークホルダーの意思決定を促したり助けたりすることが大事である。
何もなし（テストしましたー、終わりましたー）では、どのような品質が保てているのか、リリースしてもいいのか、使っても大丈夫なのか判断ができない。


##ソフトウェア品質のリスクレベルを低減
「故障や欠陥を発見」にもあるが、リスクを示せないテスト（というアクティビティ）は、単なる確認作業である。

リスクを低減するだけはなく、リスクのあり方を考えてステークホルダーのリスクに対する以下の意思決定に役立つ情報を収集する必要がある

* 回避
* 低減
* 受容
* 転嫁

## 契約上、法律上、または規制上の要件や標準を遵守
製品によって安全性などの基準があったり、ライセンスなどの契約なども確認して、その基準に満たしているかを確認する必要がある。

便利だからといって利用していた環境やライブラリなどが商用では有償だったなどのライセンス違反をしていたなど、故意ではなかったとはいえ会社、組織などの信用は著しく低下する。（それぐらいの意識でしかないのかっと思われる）
このようなことが発生を防ぐこともテストの重要な役割である。

#まとめ
局所的にバグを修正したことだけ、その機能やモジュールの近しい周りを見ただけのテストで終わるのは、テスト（というアクティビティ）とは言えないということで、以下のようなことを考えないとテストとは言えないんじゃないかと考えた

* テストは単純作業（言われたことをやる）ではないこと
* テストはどうして、そのテストで問題ないか（どうしてそのテストをしようと思ったのか）を説明する重要なアクティビティであること
* バグがでたときは（なぜ挙げきれなかったのか）、どこでどうして漏れたのかフィードバックをして品質をよくするアクティビティ（の1つ）であること
* ステークホルダーの意思決定の情報を提供

#参考
http://jstqb.jp/dl/JSTQB-SyllabusFoundation_Ver%20sion2018.J01.pdf
http://testerchan.hatenadiary.com/entry/2020/06/29/080000
ゼロから始めるLeetCode Day71 「1496. Path Crossing」

# 概要

海外ではエンジニアの面接においてコーディングテストというものが行われるらしく、多くの場合、特定の関数やクラスをお題に沿って実装するという物がメインである。

どうやら多くのエンジニアはその対策としてLeetCodeなるサイトで対策を行うようだ。

早い話が本場でも行われているようなコーディングテストに耐えうるようなアルゴリズム力を鍛えるサイトであり、海外のテックカンパニーでのキャリアを積みたい方にとっては避けては通れない道である。

と、仰々しく書いてみましたが、私は今のところそういった面接を受ける予定はありません。

ただ、ITエンジニアとして人並みのアルゴリズム力くらいは持っておいた方がいいだろうということで不定期に問題を解いてその時に考えたやり方をメモ的に書いていこうかと思います。

[Leetcode](https://leetcode.com/)

Python3で解いています。

[ゼロから始めるLeetCode 目次](https://qiita.com/KueharX/items/6ee2502c3b620c795b70)

前回
[ゼロから始めるLeetCode Day70 「295. Find Median from Data Stream」](https://qiita.com/KueharX/items/a0c9a2527f21f5e27350)

今はTop 100 Liked QuestionsのMediumを優先的に解いています。
Easyは全て解いたので気になる方は目次の方へどうぞ。

[Twitter](https://twitter.com/kueharx)やってます。

**[技術ブログ](https://kueharx.blogspot.com/)始めました！！**
技術はLeetCode、Django、Nuxt、あたりについて書くと思います。**こちらの方が更新は早いので**、よければブクマよろしくお願いいたします！

# 問題
[1496. Path Crossing](https://leetcode.com/problems/path-crossing/)

難易度はEasy。
直近で一番新しく追加されたEasyの問題です。

問題としては、path[i] = 'N', 'S', 'E', 'W' のような文字列のパスが与えられたとき，それぞれ1単位の移動を表す．2 次元平面上の原点 (0, 0) を起点とし、path で指定されたパス上を歩きます。
パスが任意の点で交差している場合、つまり以前に訪れたことのある場所にいる場合はTrueを返します。それ以外の場合は False を返します。

画像の関係で例を貼れないので各自確認をよろしくお願いいたします。

# 解法

x,yで座標を管理して最初の座標をdictで管理する、という方法を取りました。
うーん。
あまりスマートではないと思うのですが、pathをfor文で回して各文字列と一致するならば座標を変更するというものです。
しかしこれでも回答数が少ないせいかスピード自体は上位なんですよね・・・
何とも言えませんがとりあえず今回はこれで。

```python
class Solution:
    def isPathCrossing(self, path: str) -> bool:
        x = y = 0
        isVisited = {(0,0):True}
        for i in path:
            if i == 'N':
                y += 1
            elif i == 'E':
                x += 1
            elif i == 'S':
                y -= 1
            else:
                x -= 1
            if isVisited.get((x,y)):
                return True
            isVisited[(x,y)] = True
        return False
# Runtime: 24 ms, faster than 96.92% of Python3 online submissions for Path Crossing.
# Memory Usage: 14 MB, less than 100.00% of Python3 online submissions for Path Crossing.
```


Javaとかだとswitch文とかで書くのがいいのでしょうか・・・？
今回は新しい問題という事でdiscussにも投稿してみました。
[Simple Python Solution](https://leetcode.com/problems/path-crossing/discuss/711518/Simple-Python-Solution)

緊張しますがこういうのやるともっと頭の良い人からアドバイスがもらえたりしていいですよね！

では今回はここまで。お疲れ様でした。
Pythonをctypesを使わずに1行でセグフォらせる

[pythonを三行でセグフォらせる](https://qiita.com/autotaker1984/items/a8ba955acdc81c907b3d)がすべての始まりで、これは知らなかったです。面白いです。
[pythonを2行でセグフォらせる](https://qiita.com/sh1ma/items/a6dd1bcca0d9725e7e67)など、ctypesを使うものも出ています。

それとは違うタイプの死に方を思いついたので投稿します。多分Linuxでしか動かないです。

```py:まさに自殺
import os; os.kill(os.getpid(), 11)
```
Dronecode 用語集

# この記事は
[Dronecode](https://www.dronecode.org/)や[PX4 Developer Guide](https://dev.px4.io/master/en/index.html)などに出てくる用語で、私が聞き慣れなかったものを記録しているものです。
随時追記していきます。

# A~G

### Arm/Armed
直訳すると「武装」ですが、ドローンのモーターなどにも電力供給され、
「今にも飛び立てる」 or 「飛行している」状態の事をさします。


### AUX
Auxiliary (補助という意味)
プロポで補助的な動作を割り当てるインターフェイスのことっぽい

### FMU
flight management unit
フライトコントローラなどが乗る基盤のことっぽい

### GCS
Ground Control Station
地上管制局、QGCSというソフトウェアの事を指したりもする。

### gimbal
カメラを安定したまま回転させる回転台のこと
参考：https://dronebangkok.live/2017/09/28/drone-english-word-book/


# H~N

# O~U
### Proportional Controller
コントローラのこと
日本語では**プロポ**(プロポーショナルコントローラ)という

参考：https://www.drone.jp/column/20190924150036.html
>プロポの語源はプロポーショナル（proportional）、日本語では比例するという意味から来ています。スティックを倒した量と比例してサーボモーターやアンプを動かせることから「比例」の部分のプロポが名称に残ったようです。不思議な由来ですね。

### RC
Radio Controlの略
R/Cと略すこともある。

### SITL
software in the loopの略
実機を用いずシミュレーションにより開発や動作確認を行う方法のこと

Dronecodeに限らず一般用語で、
SILS(Software-In-the-Loop-Simulation)や
SILなどと略されているケースも多い。

HIL(Hardware In the Loop)と対になるような概念。

### UAVCAN
Uncomplicated Application-level Vehicular Communication and Networking
車両通信用につくられた軽量プロトコル
もともとはCAN(Controller Area Network) busで通信を行っていたが、現在は様々なネットワークタイプを対象とするようになった。

# V~Z
在宅フレックスで退勤時刻がわからなくなるので、退勤時刻が近づいたらLINEで知らせることにした。

電車に乗って社会参加していたときは出勤時刻がほぼ一定だったのですが、在宅勤務が始まってから始業時間がめちゃくちゃ適当になってしまい、あれ？今日は何時に仕事終わりだっけ…？というのを毎日やっています。旦那さんのほうが私の退勤時刻を把握している。
絶対残業したくないのと、退勤時刻を夫婦で共有したいため、LINEのトークへ退勤20分前に通知を飛ばすことにします。
今回は、以下の記事で作った「出退勤ダッシュボタン（で動かしてる打刻スクリプト）」に追記して目的を達成しました。
[Wi\-Fiに繋がらないAmazon Dash Buttonを復旧させて出勤ダッシュボタンを作る。 \- Qiita](https://qiita.com/retrorocket/items/0a84d6e1f40ad3e11769)

## LINE Notifyのアクセストークン発行
トークに通知を飛ばすだけなら、LINE Messaging APIではなくLINE Notifyで十分です。
[LINE Notify](https://notify-bot.line.me/ja/)
マイページ -> アクセストークンの発行(開発者向け) で通知を飛ばしたいトークを選択すると、即トークンが発行できます。
以下のリクエストでトーク宛てに通知が飛ばせます。

```bash
curl -XPOST "https://notify-api.line.me/api/notify" -H "Authorization: Bearer ${YOUR_TOKEN}" --data "message=こんばんは"
```

## 退勤時刻20分前にメッセージを飛ばす
出勤でダッシュボタンを押したときに、「退勤時刻20分前」をタイマーにセットしてコマンドを実行できれば良さそうです。
今回の用途にぴったりなatコマンドを使います。
[atコマンドについて詳しくまとめました 【Linuxコマンド集】](https://eng-entrance.com/linux-command-at)

以下のコマンドを、出勤用の打刻スクリプトにセットします。

```bash
echo "curl -XPOST \"https://notify-api.line.me/api/notify\" -H \"Authorization: Bearer ${TOKEN}\" --data \"message=retrorocketさんはあと20分で退勤です。\"" | at now + ${勤務時間-20}min
```

atコマンドで、現在時刻から{(n時間*60)-20}分後にLINE NotifyのAPIを実行するようにセットしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321603/b5dbe0fc-18a6-883b-a8f3-1044b882b958.png)

目的が達成できました。出退勤だけでなく、スマート家電と合わせて使っても楽しそうですね。
(Python)複数のExcelファイル内における特定シート内特定列のデータを一括抽出し、各列内データを１行に納めるには

###背景
複数のExcelファイルの**特定シート**内の**特定列**のデータを**一括抽出**し、それぞれ１行に納めたい際に、pythonを用いて、さくっと処理することができたので、備忘録として、整理することにしました。

###１．複数のExcelファイルを読み込むには

- 今回は、前提として、約１５０個のファイルを同一フォルダに格納しています。
- 最初に、フォルダ内のファイル一覧を取得します。

```
import glob
files=glob.glob(r'/レビュー結果分析用/*.xlsx')
```

- 次に、**pandas.read_excel()**を使用して、ファイル一覧から一つづつファイル名を取得して、Excelファイルの**特定シート**を読み込みます。
- さらに、**values**を用いて、特定シート内の特定列のデータを抽出します。例では、特定列は１０項目（左から）になります。

```
import pandas as pd
for file in files:
    df = pd.read_excel(file, sheet_name='指摘事項一覧')
    for row in df.values:
      # １０列目のデータを抽出
      s_data = str(row[9]).strip().rstrip()
```

###２．後処理
- 取得したデータを１行にまとめたい場合
    - 取得した列データ内を１行に納めたい場合には、データ内の改行コードを取り除きます。これは、データ分析においては、よくあるケースと思われますので、載せておきます。
    `print(s_data.replace('\n',''))`

- 日付データが含まれる場合
    - pythonでExcelファイルを読み込むと、Excelファイル上で表示されていた日付が、41496 などの 5桁の数値に変換されてしまう、といった事象に出会すことがあるかと思います。これは、Excelでの日付は 1900年1月1日を起点 (1 日目) として、そこから日数を加算した数値で日付データを保持している、というのが原因のようです。（関連記事２参照）。
    - そこで、以下のような関数を作成して、変換する必要がありますので、実際に動いたコードを記載しておきます。
    

```
def excel_date(num):
    from datetime import datetime, timedelta
    return(datetime(1899, 12, 30) + timedelta(days=num))

print(pd.to_datetime(excel_date(row[11]), format='%Y年%m月%d日'))

```

以上になります。（もっと簡単な方法があるよ、というのがあれば、ぜひ、コメントください）

##関連記事
1. [Pythonでフォルダ内のファイルリストを取得する](https://qiita.com/amowwee/items/e63b3610ea750f7dba1b)
2. [エクセル日付の「数値」を python の datetime に変換する](https://qiita.com/nezumi/items/23c301c661f5e9653f19)
Buildspec.ymlでコマンド結果を変数として扱う

#curlコマンドの結果をymlの変数に格納して使う

##envには文字列しか入らない
buildspecのenv>variablesには文字列しか入らないです。

例えば、

```
https://hoge/fuga/version
```

のように何かしらのversionを取得するapiがあったときに

```
env:
  variables:
      VERSION: `curl https://hoge/fuga/version | jq '.[].version'`
```

として `VERSION` に入れようとしてもコマンドがそのまま変数に入ってしまう。

## `phases` で指定
以下のように `phases` の中で指定するとその後の処理で使えます。

```
phases:
  pre_build:
    commands:
      .........
  build:
    commands:
      - VERSION=`curl https://hoge/fuga/version | jq '.[].version'`
      - export VERSION
      - echo $VERSION
```
【Ruby on Rails】レイアウトテンプレートの備忘録

初稿です。不備がありましたらご指摘いただけると幸いです。

Ruby on Railsを勉強中です。ビューファイルでコーディングした内容が、なぜDOCTYPE宣言やHTMLタグで囲ってないのにブラウザできちんと表示されるか不明だったのですが、レイアウトテンプレートを理解してスッキリしたので備忘録として残しておきます。

# レイアウトテンプレートとは？
railsでアプリケーションを作成した際に、以下のディレクトリに自動で作成されるファイルです。
**app/views/layouts/application.html.erb**

通常、コントローラーで定義したアクションから、ビューファイルがある場合はそのファイルが呼ばれているように見えますが、実際はレイアウトテンプレートの中に作成したビューファイルが埋め込まれて返しているとのこと。

例）postsというコントローラーを作成した場合
app/controllers/posts_controller.rb

```ruby:posts_controller.rb
class PostsController < ApplicationController
  def index
  end
end
```

app/views/posts/index.html.erb

```erb:index.html.erb
<h1>トップページ</h1>
```

実際、レスポンスとして返しているのは、下記テンプレートファイルの<body>タグ内にある**<%= yield %>**に呼び出されたビューファイル**index.html.erb**が埋め込まれて返されているとのこと。

app/views/layouts/application.html.erb

```erb:application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>FirstApp</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>
```

![index.html](https://gyazo.com/c4043bb36dd26453b11dacdefbb2fa8f)
MicroK8sでArgoが動かない問題への対応方法

# 概要

MicroK8sにArgoをインストールしてWorkflowを動かした際に、下記のエラーが出て動かない問題の原因と対応方法です。

```
MountVolume.SetUp failed for volume "docker-sock" : hostPath type check failed: /var/run/docker.sock is not a socket file
```

# 原因と対応方法

原因は（エラーメッセージそのままですが）MicroK8sには /var/run/docker.sock がないことのようです。
https://github.com/kubeflow/kubeflow/issues/2347

リンク先のIssueにはパスを変更して対応する方法も書かれていますが、もう少しスマートな方法としてExecutorを変更する方法があるようです。

Argoでは下記のExecutorが選べるようになっており、デフォルトでは docker が設定されています

- docker
- k8sapi
- kubelet
- pns

これを docker 以外に変更することで /var/run/docker.sock も不要になってエラーが出なくなるようです。
それぞれの違いは良く分からなかった[^1]のですが、とりあえずk8sapiを利用してみたところ問題なく動いています。

Helmを利用してインストールする場合は `controller.containerRuntimeExecutor` でExecutorの指定が可能です。

```
helm install argo argo/argo --set "controller.containerRuntimeExecutor=k8sapi"
```

[^1]: 一応 https://argoproj.github.io/docs/argo/workflow-executors.html にPros/Consは記載されており、（docker以外を選ぶ必要があるなら）雰囲気的には安定したらpnsが良さそうな感じはします。ちなみに上記で利用したk8sapiはAPI経由だから遅いらしいです。
ビッグデータとユニクロの成功 | 市場の動きを把握！

元記事：https://jp.scrapestorm.com/tutorial/big-data-and-uniqlo-success-understand-market-movements/

ユニクロはカジュアルファッションを手掛ける日本のアパレルメーカーです。カジュアルファッションの中でも非常にベーシックなアイテムを豊富に手掛けています。赤いボックスに白抜きのブランド名が特徴的で、海外でも数多くの店舗を出店しています。また、サイズと色の展開が豊富なので、一見かわりばえしないアイテムでも自分に合ったデザインを見つけることができます。
![uniqlo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/2b664131-70e1-5884-ae4d-5e8ce09e299d.gif)
ユニクロは現在、最も成功しているファストファッションブランドの1つになるのは、ビッグデータテクノロジーは不可欠です。
安くて品質が良く、美しく、他のブランドとブランド合同活動するため、ほとんどの人がユニクロを喜んで選択します。 実際、さらなる分析により、ユニクロに以下の優れた点があることを確認することは難しくありません。
まず、価格はリーズナブルで、一般の消費者にも受け入れられます。ユニクロのほとんどの商品は約3回の値下げとなり、ついに50％または40％も値下げされます！もちろん、商品の値下がりには、その在庫数、人気によって影響を受けます。
![価格.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/5256e25f-91d6-d5b8-6a38-f1e870202312.png)
第二、製品のスタイルは主に基本的なスタイルに基づいており、ほとんどの年齢のほとんどの人々の日常のニーズに適しており、より大きな市場規模を形成しています。
![款式.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/caef0c30-cd6f-c858-e99a-3a22633535cf.png)
第三、ユニクロは製品の売上に応じて適切に出力を調整します。
時は命です。市場のダイナミクスに初めて反応できなければ、企業は活力を失います。長年にわたり、ユニクロは毎週の売上データ、スタイルの市場状況、各店舗の売上などのデータを収集しています。 そして、生産およびマーケティング戦略を対応して分析および定式化し、無駄なコストを削減し、フォールトトレランスを改善し、「ゼロインベントリ」を実現します。
![市场调查.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/4f2ab60e-69ed-02b5-2a9d-993f7f89f2d1.png)
最後、定期的に他のブランドとブランド合同活動を開催します。ブランドの合同活動を利用して製品の人気を高め、新しいユーザーを引き付けます。
![联名.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/1c646060-8dac-911d-f6cb-d7368d502c49.gif)
上記の特性は、ユニクロの体系的で高いフォールトトレランスと低いエラー率のビジネスモデルを示しています。 ユニクロの従業員は、ビッグデータの適用に非常に熟練している必要があります。

今日のユニクロの業績は、市場への熱意によるものであり、ブランドの確立以来、常に高い成長を維持し、アパレル業界に多くの奇跡を起こしてきました。市場の動きを把握にはビッグデータの収集と正確な分析が不可欠です。
docker-compose upの直後Yarnのエラーでコンテナが落ちる問題と解決


# 環境

MacOS Mojave: 10.14.6
Docker: 19.03.8
Ruby: 2.6.6
Rails: 6.0.0
PostgreSQL

# 問題

RailsチュートリアルのSample_appを
Docker環境に移行している途中で

`docker-compose up`のあとpumaが起動した後すぐに以下のエラーを吐いて落ちる現象に遭遇

```
warning Integrity check: System parameters don't match
app_1  | error Integrity check failed
app_1  | error Found 1 errors.
app_1  | 
app_1  | 
app_1  | ========================================
app_1  |   Your Yarn packages are out of date!
app_1  |   Please run `yarn install --check-files` to update.
app_1  | ========================================
app_1  | 
app_1  | 
app_1  | To disable this check, please change `check_yarn_integrity`
app_1  | to `false` in your webpacker config file (config/webpacker.yml).
app_1  | 
app_1  | 
app_1  | yarn check v1.22.4
app_1  | info Visit https://yarnpkg.com/en/docs/cli/check for documentation about this command.
```



config/webpacker.ymlを編集する解決方法が見つかったがこれでは解決せず
[yarnが原因でdocker-compose runが実行できないときの対処法 - Qiita](https://qiita.com/KenAra/items/2708ce3d5c80c4f24920)



# 解決

こちらを参考に`config/environments/development.rb`と`config/webpacker.yml`を編集して解決しました
[Running a Rails app with Webpacker and Docker - Dirk de Kok - Medium](https://medium.com/@dirkdk/running-a-rails-app-with-webpacker-and-docker-8d29153d3446)

> # Last configuration for Yarn and Webpacker
>
> Rails does a lot of checkups on Yarn, a bit too much. Best is to disable this:
>
> ```
> # config/environments/development.rb
> config.webpacker.check_yarn_integrity = false
> ```
>
> Also, we need to tell Rails that the webpacker server is running on the host webpacker and enable hot module reload. So set these values:
>
> ```
> # config/webpacker.yml
> development:
>   dev_server:
>     host: webpacker
>     hmr: true
> ```
>
> Last configuration for Yarn and Webpacker
【Flutter】画像で作ったボタンに対してリップルエフェクトを実装する

## 今回作るもの

画像で作ったボタンに対して、画像の前面に広がり、かつボタンの形に沿うようなようなリップルエフェクトを実装していきます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147934/1860e5d6-6093-1d1d-5949-07e07027340c.gif" width=20%></img>

# 実装

## ボタン作成
まず、ボタン自体を作ります。ここではContainerに対して、Boxdecorationを利用することで丸角の画像ボタンを作ります。

```sample.dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white60,
      appBar: AppBar(
        title: Text('ImageButtonRippleDemo'),
      ),
      body: Center(
        child: Container(
          width: 120,
          height: 120,
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(8.0),
            image: DecorationImage(
              image: AssetImage(
                'images/icon.jpg',
              ),
              fit: BoxFit.cover,
            ),
          ),
        ),
      ),
    );
  }
```

こんな感じになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147934/b81cc79c-05b2-1f29-50bf-5eefcd21f207.png" width=20%></img>

## MaterialウィジェットとInkWellウィジェットをContainerの子ウィジェットとして定義する

リップルエフェクトとして描画するためにはMaterialウィジェットがInkwellの親ウィジェットとして定義されている必要があります。
ただ、その二つをContainerの親として定義してしまうと、Containerの裏側でリップルエフェクトが描画されてしまい、以下のように想定した動作になりません。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147934/36781008-2e07-0968-05e5-5b207d9cc79f.gif" width=20%></img>

なので、まずMaterialをContainerの子ウィジェットとして定義します。ただ、Material自体に色を持たせてしまうとボタン自体が見えなくなってしまうので、colorはColors.transparentに指定します。

最後に、リップルエフェクトを描画するためにInkwellをMaterialの子ウィジェットとしておきます。
また、ここでボタンの形に合わせるためにborderRadiusを指定します。

```sample.dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white60,
      appBar: AppBar(
        title: Text('ImageButtonRippleDemo'),
      ),
      body: Center(
        child: Container(
          width: 120,
          height: 120,
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(8.0),
            image: DecorationImage(
              image: AssetImage(
                'images/icon.jpg',
              ),
              fit: BoxFit.cover,
            ),
          ),
          child: Material(
            color: Colors.transparent,
            child: InkWell(
              borderRadius: BorderRadius.circular(8.0),
              onTap: () { 
                // 押下時の処理を記述
              },
            ),
          ),
        ),
      ),
    );
  }
```

# 完成

このように画像ボタンに対してボタンの形に沿って適切にリップルエフェクトが描画することができました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147934/1860e5d6-6093-1d1d-5949-07e07027340c.gif" width=20%></img>

# まとめ

小ネタですが、画像ボタンの形に沿って適切にリップルエフェクトを実装することができました。
Inkwellでラップすればすぐできるっしょと思いがちですが、画像や背景色があるウィジェットに対しては、少し手間を加える必要があります。
他にももっと良い方法ありましたら教えていただけると嬉しいです。
最後までご覧いただきありがとうございました。
Python で タイムスタンプ局を操作するには

# Python+OpenSSLを使うには？
- pyOpensslが一番ハードルが低い。
    - CA局も作ろうと思えば作ることができる。
- import ssl 
    - 比較的低レイヤーのOpenSSLの機能を触ることができる。

## 今回やろうとしていることは、（オレオレ）タイムスタンプ局
### 事前情報として
- （オレオレ）CA局とは別物
- OpenSSLでいうと、version 1.1.0あたりから本流に組み込まれた「openssl ts」コマンド体系でできることをしたい。

### シェルでopensslコマンドを叩いてそもそも実現可能か？
色々調べるが、下記のサイトぐらいしか具体的な記事が見当たらない。
[Setting to create Timestamping Authority certificate signing request](https://sites.google.com/site/flashplustutorial/open-ssl/setting-to-create-timestamping-authority-certificate-signing-request?tmpl=%2Fsystem%2Fapp%2Ftemplates%2Fprint%2F)
このサイトの情報を見ると、設定ファイルopenssl.cfg全体が掲載されているので、それを元にコマンドレベルで実行できるのか確認してみる。

- 基本的には動作するようだが、色々とひっかかる部分があった。
- 設定ファイルの情報が全体的に少し古い。暗号化方式の設定にSHA-2が含まれていない等。
- 実行時にopensslのエラーが出るので、それを元に一つ一つエラーを解消していく。
- 最後の検証「openssl ts -verify」で、証明書が見つからないエラーになる。
- コマンドの最後「openssl ts -verify ・・・ -CAfile <CA局の証明書>」 の後に、「-untrusted <タイムスタンプ局の証明書>」オプションが必要）



### Pythonから同じようにできないのか？

- pyOpensslを調べるも、それらしい機能が見当たらない。
    - pyOpensslが依存関係にあるcryptography.hazmatにもなさそう。
    - 例えば、OpenSSLのts_main関数に含まれている TS_REQ_new()関数辺りが使えるようになっていない。
    - そもそも、pyOpensslはcryptographyに依存しており、cryptographyはopensslのversion 1.0.2までのように見える？

## 結局Pythonからシェル経由で駆動させるしかないのか？
```
$ openssl ts -query ・・・ 
$ openssl ts -reply ・・・
$ openssl ts -verify ・・・
```
上記のコマンドについてもう少し調べてみると、
①まずクライアント側、つまり署名を要求する側が-queryで署名要求ファイルを生成し、
②次にタイムスタンプ局が-replyで署名済みファイルを生成し、
③再びクライアント側が署名済みファイルの検証を行うようだ。
ということは、②の部分だけpythonで実装できればよいのではないか？

## RFC3161を実装しているpython用ライブラリはないのか？
TimestampについてはRFC3136に定義されているようだが、それに準拠したpythonライブラリがこれといって見つからない。さっと出てこないということは需要がない。ということか・・・
[Terraform] ECSクラスタでContainer Insightを有効化する方法

公式ドキュメントは非常にわかりづらく、世の中に情報がないので載せておきます。

```
resource "aws_ecs_cluster" "hoge" {
  name = "hoge"
  setting {
    name  = "containerInsights"
    value = "enabled"
  }
}
```
競プロで役立ちそうな自分の記事一覧

# 前書き

競プロで役立ちそうな自分の記事をシリーズごとに分けて一覧にしました。
# 競プロ問題解説

- [Competitive_Programming_Articles](https://github.com/daikisuyama/Competitive_Programming_Articles)
    - Qiitaにて投稿した解説記事はこちらのリポジトリに移動しました

# 競プロ用テンプレート

- [競プロ用テンプレート（C++）](https://qiita.com/DaikiSuyama/items/9dba963ba74396b9b7fd)
- [競プロ用テンプレート（Go）](https://qiita.com/DaikiSuyama/items/f82d26399a49eb121004)
- [競プロ用テンプレート（JavaScript）](https://qiita.com/DaikiSuyama/items/8038b646e29dc1050aa6)

# 競プロの基本事項確認

- [競プロの基本事項確認~累積和といもす法~](https://qiita.com/DaikiSuyama/items/67547e14b47cd6360252)
    - Pythonを用いた解説
- [競プロの基本事項確認~順列生成の方法~](https://qiita.com/DaikiSuyama/items/2483a1af0af38408317b)
    - PythonとC++を用いた解説
- [競プロの基本事項確認~コンテナ上の二分探索~](https://qiita.com/DaikiSuyama/items/2e3f1f6d76f68f6308e2)
    - PythonとC++を用いた解説
- [競プロの基本事項確認~gcdとlcm~](https://qiita.com/DaikiSuyama/items/a18405eb3f7a8e9834aa)
    - PythonとC++を用いた解説

# 競プロの応用事項確認

- [競プロの応用事項確認~包除原理~](https://qiita.com/DaikiSuyama/items/4d0388a3f68b60c3e5f3) 
    - C++を用いた解説
- [競プロの応用事項確認~ランレングス圧縮~](https://qiita.com/DaikiSuyama/items/07e237b7372e7c7b3432) 
    - Pythonを用いた解説

# 競プロのライブラリ整理

- [競プロのライブラリ整理~Union-Find木~](https://qiita.com/DaikiSuyama/items/444e409423bd1b4b83d7)
    - C++を用いたライブラリ
- [競プロのライブラリ整理~逆元による二項係数の計算~](https://qiita.com/DaikiSuyama/items/32706bc87c748edc301d)
    - C++を用いたライブラリ
- [競プロのライブラリ整理~約数の列挙~](https://qiita.com/DaikiSuyama/items/946fb4db8fb3cb04d27e)
    - PythonとC++を用いたライブラリ
- [競プロのライブラリ整理~素因数分解と素数判定~](https://qiita.com/DaikiSuyama/items/6462d8b167d6e1eb0cc9)
    - C++を用いたライブラリ
- [競プロのライブラリ整理~BIT(Binary Indexed Tree)~](https://qiita.com/DaikiSuyama/items/7295f5160a51684554a7)
    - C++を用いたライブラリ
- [競プロのライブラリ整理~modint~](https://qiita.com/DaikiSuyama/items/2dcc49932f2489292e44)
    - C++を用いたライブラリ
- [競プロのライブラリ整理~最小全域木~](https://qiita.com/DaikiSuyama/items/bac256aef114b7ade3d6)
    - C++を用いたライブラリ
- [競プロのライブラリ整理~サイコロ~](https://qiita.com/DaikiSuyama/items/fbc55b17c1dee38b61b8)
    - Pythonを用いたライブラリ
- [競プロのライブラリ整理~二分探索と三分探索~](https://qiita.com/DaikiSuyama/items/5ab08c1581af238de909)
    - Pythonを用いたライブラリ

# 競プロ関連ポエム

- [競プロを始めた初級者が感じたことをまとめてみる](https://qiita.com/DaikiSuyama/items/e22830dcff53bf5dbc67)
    - 初心者の時の感想です
- [だから僕は競プロをやめた](https://qiita.com/DaikiSuyama/items/ca5ccd40082cb9de5fcf)
    - 競プロの引退記事です
- [「だから僕は競プロをやめた」の批判への回答](https://note.com/daikisuyama/n/nac0543473eb1)
    - 上記の記事の関連記事です

# その他

- [Pythonで競プロするのに必要な機能をまとめてみた~itertools~](https://qiita.com/DaikiSuyama/items/11f63a94d63fa72e8bf4)
- [最短経路問題における三つのアルゴリズムの実行時間の比較](https://qiita.com/DaikiSuyama/items/663b3e91fd0cf411dd64)
- [二分探索と三分探索の数学的な解説とバグらせない実装方法](https://qiita.com/DaikiSuyama/items/84df26daad11cf7da453)
- - [Goによる競プロライブラリ~Union-Find木~](https://qiita.com/DaikiSuyama/items/dab3a70c3c104ca0ab01)
[Windowsキー] + [矢印キー] を Mac OS の標準機能だけで実現する方法

[Windowsキー] + [矢印キー] をMacでも使いたいがために、Magnet、Shiflt、Spectacle等のサードパーティ製ツールをインストールしている方は多いかと思いますが、それだけであれば Mac OS X の標準機能だけで実現できます。

# 手順
System Preferences > Keyboard > Shortcuts > App Shortcuts
から「+」ボタンで新しいショートカットを追加。

 -  Menu Title: `Move Window to Right Side of Screen`
 -  Keyboard Shortcut: `shift + 「→」`

を入力。

<img width="667" alt="Screen Shot 2020-06-29 at 7.51.24 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351392/81a2bd34-1d1e-712c-58d4-2905048d4e40.png">


Left Sideも同様にショートカット追加。

<img width="666" alt="Screen Shot 2020-06-29 at 7.48.01 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351392/c3441ec9-d2f8-1f5f-d15b-94a07c7e4192.png">

完成。

<img width="515" alt="Screen Shot 2020-06-29 at 7.56.56 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351392/3a282259-69b6-da66-005e-a44e251d5fbb.png">
Julia 1.4〜1.5のコンパイル済みバイナリがAMD E2では走らない件

# 要約

1. すぐ使えるバイナリについて、古いAMDチップはLLVMのライブラリが？非対応らしい。
2. ソースから再コンパイルすれば問題なく実行できる。

# 詳細

https://julialang.org/downloads/
からコンパイル済みバイナリをダウンロードして立ち上げるもversioninfo()でインストラクションエラー。
1.4の頃もSegmantaion errorとかでこけていて、ubuntu 16.04との問題なのか何かのバグかなと思って検索するも特にこれはというものを見つけられず、issueを出してみたら、

https://github.com/JuliaLang/julia/issues/35215

と同じだとのことでした。

AMDの古いチップがLLVMのバイナリの対象外、らしい。

スレッドの内容に従って、また、
https://github.com/JuliaLang/julia/blob/master/doc/build/build.md#required-build-tools-and-external-libraries
の説明も参考に、

```
git clone https://github.com/JuliaLang/julia.git
```

Make.userファイルを作成し、

```
USE_BINARYBUILDER=0
```
と記載してmakeしたところ、無事クラッシュしないjuliaができました。

```
versioninfo()

Julia Version 1.5.0-rc1.0
Commit 24f033c* (2020-06-26 20:13 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: AMD E2-3000M APU with Radeon(tm) HD Graphics
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-9.0.1 (ORCJIT, generic)
```

コンパイルには1晩かからないぐらいだったと思います。
【Rails】画像プレビュー機能の実装

# 目標
![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579893/1dd19b79-c7b2-21c0-b120-d4f9645018e6.gif)

# 開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

# 前提

下記実装済み。

・[Slim導入](https://qiita.com/matsubishi5/items/b639ffddecc626856039)
・[Bootstrap3導入](https://qiita.com/matsubishi5/items/b117c95f4dd71340cc80)
・[Font Awesome導入](https://qiita.com/matsubishi5/items/a4c72f436e64ad106ee8)
・[ログイン機能実装](https://qiita.com/matsubishi5/items/5bd8fdd45af955cf137d)
・[投稿機能実装](https://qiita.com/matsubishi5/items/1a5aeab651b5822d1f2c)

# 実装

## 1.ビューを編集

```slim:users/edit.html.slim
/ 追記
= f.file_field :profile_image, class: 'img_field', style: 'display:none;'
= attachment_image_tag @user, :profile_image, fallback: 'no-image.png', onClick: "$('.img_field').click()", class: 'center-block img-thumbnail img-responsive img_prev'
br
```

### 【解説】

#### ① `file_field`を`display:none`の非表示にし、クラスを付与する。

```slim
= f.file_field :profile_image, class: 'img_field', style: 'display:none;'
```

#### ② `①` で付与したクラスのHTML(file_field)がクリックされたらJavaScriptの処理を実行する。
```slim
onClick: "$('.img_field').click()"
```

## 2.`appliacation.scss`を編集

```scss:appliacation.scss
// 追記
.img_prev:hover {
  cursor: pointer; 
  opacity: 0.7;
  transform: scale(1.01, 1.01);
}
```

### 【解説】

#### ① 画像にマウスが乗っている時にCSSを反映させる。

```scss
.img_prev:hover {}
```

#### ② マウスカーソルをポインターに変更する。

```scss
cursor: pointer; 
```

#### ③ 不透明度を低くして、画像を少し白くする。

```scss
opacity: 0.7;
```

#### ④ 少しだけ画像を拡大する。

```scss
transform: scale(1.01, 1.01);
```

## 3.JavaScriptファイルを作成・編集

```terminal:ターミナル
$ touch app/assets/javascripts/image_preview.js
```

```js:image_preview.js
$(function () {
  function readURL(input) {
    if (input.files && input.files[0]) {
      var reader = new FileReader();
      reader.onload = function (e) {
        $('.img_prev').attr('src', e.target.result);
      }
      reader.readAsDataURL(input.files[0]);
    }
  }

  $('.img_field').change(function () {
    readURL(this);
  });
});
```

### 【解説】

#### ① `1.ビューを編集の②` で実行する処理。

```js
$('.img_field').change(function () {
  readURL(this);
});
```
【Flutter】ListViewやSingleChildScrollViewの端まで来た時の波紋を消す

# はじめに

AndroidでListViewを実装していて、スクロールの端まできた際に波のようなエフェクトが出ると思います。
これを取る方法について紹介します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147934/84a4b9cd-8c37-aacb-f7cf-07b2e86af04c.gif" width=20%>
</img>

# 波紋を非表示にするには

`NotificationListener`というウィジェットと`OverscrollIndicatorNotification`というNotificationクラスを使います。

この`NotificationListener<OverscrollIndicatorNotification>`でListViewやSingleChildScrollViewをラップします。
ここで、NotificationListenerのonNotificationのコールバック関数にて、`OverscrollIndicatorNotification`クラスのオブジェクトが取得できるのですが、`OverscrollIndicatorNotification#disallowGlow()`メソッドを呼び出します。

```overscroll_indicator_notification.dart
// NotificationListenerでラップし、ジェネリックにOverscrollIndicatorNotificationを指定する
NotificationListener<OverscrollIndicatorNotification>(
  child: SingleChildScrollView(
    controller: _scrollController,
    child: Column(
      children: _buildCards(),
    ),
  ),
  onNotification: (OverscrollIndicatorNotification notification) {
    notification.disallowGlow();  // disallowGlow()を呼ぶ
    return false;
  },
),
```

NotificationListenerについてはこちらの記事を書きましたので、よければどうぞ。
https://qiita.com/youmeee/items/6ca30bf66646b1639076

すると、このように波紋が表示されなくなります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147934/d6ea886e-dda9-bd3c-cd79-bf3eba0022b3.gif" width=20%>
</img>

# まとめ

今回はListViewなどのスクロール位置が端まで来た際の波紋を消す方法について解説しました。
プロパティとかで指定できたら便利なのになあ、、
最後までご覧いただきありがとうございました。
キャプチャリストにおいて複数の変数に対して weak, unowned キーワードを付ける際の注意点

今回はトレイリングクロージャにおけるキャプチャリストについての気づきをシェアします！
小ネタですが、意識しないと気づかずメモリリークを起こす原因になるような注意点です！

## 本題: 弱参照のつもりが、強参照に！？
ネットにあるコードを読んでいると、たまに、メモリリーク解消を目的とした弱参照を宣言するために、以下のような実装を見かけます。

```swift
alertController.addAction(UIAlertAction(title: "OK", style: .default) { [weak self, alertController] _ in
```

`[weak 変数1, 変数2]` のような実装になっていますね。
コードを読むと、どうやら `変数1` `変数2` ともに `weak` 属性にして弱参照にしたいようです。
が、この実装では **`変数2` が強参照になります**。

もう一度申し上げます。
**`変数2` は強参照です**。

## 対策
じゃあ、どうするか？？
`[weak 変数1, weak 変数2]` とそれぞれの変数の前に `weak` を宣言することで実現可能です。
先程の `UIAlertAction` のトレイリングクロージャの例だと、

```swift
alertController.addAction(UIAlertAction(title: "OK", style: .default) { [weak self, weak alertController] _ in
```

となります。

## おわり
メモリリークの原因になるので気をつけたいですね😵
【RSpec】stub_request(:post)でスタブ化したGoogle APIへのリクエストのレスポンスを実際と同一の形式にする

タイトルが長い

RailsアプリケーションからGoogle Calendar APIでカレンダー上のイベントに対して更新処理を行い、そのレスポンスから特定の属性を取り出して取り回すような処理を追加した。
レスポンスで受け取ったJSONをgoogle-api-ruby-clientがGoogle::API::V3::Eventクラスのオブジェクトに変換してしまうため、スタブリクエストのレスポンスもruby-clientで変換させるか同様の構造を持ったオブジェクトにする必要があった。

# TL;DR

- google-api-ruby-clientを利用してGoogleAPIにリクエストした場合、レスポンスはJSON形式で返ってきたあとgoogle-api-ruby-clientで変換される
- stub_requestからの戻り値のヘッダーに `'X-Goog-Upload-Status': 'final'` を加えると実際のAPIからのレスポンスと同様の形式になる

# スタブ化したリクエストと実際にAPIにリクエストした場合のレスポンスの違い

下記のコードはgoogle-api-ruby-clientを利用してリクエストし、レスポンスからイベントのIDを取得しようとしている

リクエスト

```ruby
service = Google::Apis::CalendarV3::CalendarService.new
service.authorization = access_token

response = service.update_event('primary', event_id, body)
event_id = response.id
```

このとき `response` は以下のようになっている。

```ruby
#<Google::Apis::CalendarV3::Event:0x000055c94da58f18
 @attachments=[],
 @attendees=[#<Google::Apis::CalendarV3::EventAttendee:xxxxxxxxxxxxxxxxxxx @email="hoge@gmail.com", @organizer=true, @self=true>],
 @created=Mon, 01 Jan 2020 00:00:00 +0000,
 @creator=#<Google::Apis::CalendarV3::Event::Creator:xxxxxxxxxxxxxxxxxxx @email="hoge@gmail.com", @self=true>,
 @description="",
 @end=#<Google::Apis::CalendarV3::EventDateTime:xxxxxxxxxxxxxxxxxxx>,
 @etag="xxxxxxxxxxxxxxxxxxx",
 @id="abcdefghijklmnopqrstu",
 @organizer=#<Google::Apis::CalendarV3::Event::Organizer:xxxxxxxxxxxxxxxxxxx @email="hoge@gmail.com">,
 @start=#<Google::Apis::CalendarV3::EventDateTime:xxxxxxxxxxxxxxxxxxx>,
 @updated=Mon, 01 Jan 2020 00:00:00 +0000>
```

このため、`response` オブジェクトから ゲッターメソッドの `id` で値を取得できる。

一方で大抵の場合、RSpec内でAPIレスポンスは下記のように定義されているだろう。

```ruby
let(:response) do
  {
    id: 'abcdefghijklmnopqrstu',
    start: { date_time: Time.zone.today },
    end: { date_time: Time.zone.today },
    html_link: 'https://www.google.com/calendar/event?eid=xxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    i_cal_uid: 'xxxxxxxxxxxxxxxxxxx@google.com',
    summary: 'event name',
    updated: Time.zone.today,

    ...

  }.to_json
end
```

この場合イベントIDを取得するためには `JSON.parse(response)['id']` のようにする必要があり、 `response.id` はNoMethodErrorとなる。

# 対応策

このJSON形式のレスポンスをEventクラスのオブジェクトとして返させるためには以下のように `'X-Goog-Upload-Status': 'final'` をレスポンスのヘッダーに付与する必要がある。

```ruby
stub_request(
  :put, url
).to_return(
  status: 201,
  body: response,
  headers: {
    content_type: 'application/json',
    'X-Goog-Upload-Status': 'final'
  }
)
```

google-api-ruby-clientのテストスペック内でも[レスポンスに同様のヘッダー情報が付与されている](https://github.com/googleapis/google-api-ruby-client/blob/29f9544b1497358888cd93175e5579cab83fd247/spec/google/apis/core/upload_spec.rb#L154)。

たまたま同僚がすぐに記事やGitHubのissueを見つけてくれたおかげで解決したけどそうじゃなかったら3日はハマってた気がする。

# 元ネタ

- [How to stub an Upload request to Google API using webmock](https://dev.to/jastkand/how-to-stub-an-upload-request-to-google-api-using-webmock-32oo)
- [Create file returns nil when using WebMock gem to stub_request](https://github.com/googleapis/google-api-ruby-client/issues/575)
【Salesforce】Web-to-ケース利用時の注意事項

SalesforceのHelpで記載していない注意事項を取りまとめてみたいと思います。
１．送信件数は24時間5000件の制限があるか、拡張は可能か
　→24時間あたりのWeb-to-ケース 要求数は、一次的な例外対応として、最長90日間、最大で50,000件までの依頼可能。ですが、
　Salesforce社の承認が必要です。
　業務要件や、reCAPTCHA等のスパム対策が講じているかはチェックされるとのこと。
２．Web-to-ケースでPOSTしたら、どんなレスポンスが返ってくるの？
　エラー処理とかしたい場合に必要な情報。
　①何らかの理由によりSalesforceサーバへリクスエトが到達しない場合は、HTTP ステータスコードとして 4XX, 5XX のステータスが返される
　②Salesforceサーバへリクエストが到達しさえすれば、ケースが作成されなかった場合でも200のステータスが返されます。
　③自動生成したHTMLコードの＜input type="hidden" name="debug" value=1＞のコメントを解除することで、ケース作成が成功した際に"Your request has been queued."というメッセージが含まれる。
　ステータスコードとメッセージ合わせて、ケース作成結果の確認ができる。
３．文字コード変更は下記に書いた
　https://qiita.com/zhtomoki/items/fbe1b8c2b117ecb1abbb
作成中の拡張機能（chrome）をスマホで試すメモ


スマホで拡張機能（chrome）を使いたくてメモ。

【１】chromeブラウザをベースにしている「Kiwi Browser」をスマホに入れる。
　　　下URL参照。簡単だ。

▼Androidアプリ「Kiwi Browser」でデスクトップ版Chromeの「拡張機能」（アドオン）が使用可能に
https://smartasw.com/archives/android%E3%82%A2%E3%83%97%E3%83%AA%E3%80%8Ckiwi-browser%E3%80%8D%E3%81%A7%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97%E7%89%88chrome%E3%81%AE%E3%80%8C%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD.html

【2】これだけでもchrome ウェブストアに登録されている拡張機能はDLできるようになる。
　　でもウェブストアにまだ登録されていない制作中の拡張機能をスマホに自分はいれたい。

　　①制作した拡張機能をデベロッパーモードでPCのブラウザで読み込む。
　　　（拡張機能の作成の仕方については初心者向けからいろいろネットに乗ってるのでそっち見る）

　　chrome://extensions/

　　右側のデベロッパーモードをON。左側に「パッケージ化されていない拡張機能を読み込む」ボタンがでてくるので、
　「1.0.1.0」とか適当に名前つけた拡張機能のフォルダ（未圧縮）を登録。
　
【３】登録できたら「拡張機能をパッケージ化」する。
　　　適当なフォルダにパッケージ化すると、「0.1.0.1.crx」と「0.1.0.1.pem」の二つのファイルができる。

【４】「0.1.0.1.crx」のファイルをスマホに読み込ませたいので、グーグルドライブに拡張子「crx」のファイルの方をUP。（共有できればどこでもよき）

【５】「Kiwi Browser」を立ち上げて、右上にある三点みたいなのをぽち。
　　　真ん中あたりに「拡張機能」という項目があるので、それをぽち。
　　　PCと同じく、右上でデベロッパーモードをONにする・
　　　「Load」というボタンがでてくるので、それを押して、グーグルドライブにあげておいた「0.1.0.1.crx」を読み込む。


　おわり。
【Salesforce】Web-to-ケースの文字コードをShift-JISへ変更する方法

SalesforcのWeb-to-ケースを利用する場合、自動生成されたHTMLコードの文字コードはUTF-8となります。
Shift-JIS対応したい場合、下記の修正で対応可能とのこと。

修正前：
\<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=UTF-8">
\<form action="https://xxxx.salesforce.com/servlet/servlet.WebToCase?encoding=UTF-8" method="POST">

修正前：
\<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=Shift-JIS">
\<form action="https://xxxx.salesforce.com/servlet/servlet.WebToCase?encoding=Shift-JIS" method="POST">

なお、encoding変更後、HTMLファイル自体の文字コードの変更も忘れず実施してください。
行わない場合、HTMLが文字化けする可能性があります。

Web-to-ケースのその他の注意事項は下記にまとめています。
https://qiita.com/zhtomoki/items/15edca2113fe9e8c9d0e
[Elm][ベストプラクティス] view関数でプリミティブな型の引数を複数渡さずにレコードで渡そう

Elmも徐々に新規参入者が増えてきた気がするので(?) 細かいベストプラクティスのようなものを投稿しようと思います。一意見に過ぎないので、こうした方が良いああした方が良いという意見があれば是非コメントをお願いします。

## view関数でプリミティブな型の引数を複数渡すのを避けよう

タイトルのままですが説明していきます。実際に[動くコード](https://ellie-app.com/9gRphQNb7TWa1)です。こちらのコード間違いがあることにお気づきでしょうか？ `userView`はStringの引数を二つ(userId, userName)を受け取りますが、呼び出しでは(userName, userId)の順で渡してしまっています。さらに`userView`は徐々に拡張していく予感もあります。特にString, Int, Boolなどのプリミティブな型が渡されやすく変動しやすいview関数は、可読性が低くなりメンテナンスしにくい関数となってしまいます。

```elm
type alias Model =
    { userList : List User }


type alias User =
    { userId : String, userName : String, groupName : String }

view : Model -> Html Msg
view model =
    div []
        [ userListView model.userList ]


userListView : List User -> Html Msg
userListView userList =
    ul [] <| List.map (\{ userId, userName } -> userView userName userId) userList


userView : String -> String -> Html Msg
userView userId userName =
    li []
        [ p [] [ text <| userId ++ ", " ++ userName ]
        ]
```

## 解決策

結論から言うと、個別のview関数に対して直前などに専用の型エイリアスを用意してあげてください。他の言語では**名前付き引数**なんて名前が付いていることがあります。マジックが少ないElmはショートハンドなどは用意されていないため、愚直にやります。実際に[動くコード](https://ellie-app.com/9gRphQNb7TWa1)です。

```elm 
userListView : List User -> Html Msg
userListView userList =
    ul [] <|
        List.map
            (\{ userId, userName } ->
                userView { userName = userName, userId = userId }
            )
            userList


type alias UserViewType =
    { userId : String, userName : String }


userView : UserViewType -> Html Msg
userView { userId, userName } =
    li []
        [ p [] [ text <| userId ++ ", " ++ userName ]
        ]
```

### 注意点

上記の解決策のコードの場合、userViewの呼び出し側でレコードのコンストラクタを利用するのは避けてください。意味がなくなってしまいます。

```elm
userView <| UserViewType userName userId
```

この回避策として、型をインラインに書いてしまうと言う手もあります。しかし、この場合、型注釈が無限に延びるため、可読性が落ちてしまう可能性もあります。、が戻り値は`Html Msg`確定なので、問題ないと言う見方もあります。ここはプロダクトでやる際にはチームの決め事としてポリシーを事前に決めていた方がいいかもしれませんね。

```elm
userView : { userId : String, userName : String } -> Html Msg
```

## おまけ

今回あえてview関数でさらにプリミティブな引数の場合という風に話のスコープを狭めました。例えば、以下のように型がしっかりしていて、尚且つUtilのような関数の場合 呼び出しミスする可能性が低く、カジュアルに使いたい場合、レコードで渡すのは少し煩わしいです。また、このような関数は一度作られたらインターフェースが変わる可能性も少ないため、頻繁に変更が起き尚且つ引数の数が増えやすいview関数に限定しました。

```elm
timeToText : Time.Zone -> Time.Posix -> String
```

また、レコードのコンストラクタを控えた方が良い文脈として、`init関数`のModel定義などがあります。以下はなかなか意味がわかりませんね？ そもそもレコードのコンストラクタは、使用を控えた方がいいかもしれません。

```elm
init = ( Model 1 2 "abc" "def", Cmd.none) 
```
連想配列を指定した順番に並び替える

名前順でも日付順でもなくてこの順番でソートしたい！
って時やりかたわかんなくてちょっと困っちゃったので忘備録。

例えば、干支。

```javascript
const HogeItem = [
  { eto: '卯', ...hogehoge },
  { eto: '丑', ...hogehoge },
  { eto: '子', ...hogehoge },
  { eto: '辰', ...hogehoge },
  { eto: '寅', ...hogehoge },
];
```

のような連想配列があって、これを干支順に並び替えたいと。
以下のコードで解決です。

```javascript
const etoIndex = ['子', '丑', '寅', '卯', '辰'];
HogeItem.sort((a, b) =>
  etoIndex.indexOf(a.eto) - etoIndex.indexOf(b.eto),
);
```

sort()は1か-1を返す使い方しか知りませんでした!

参考：[Array.prototype.sort() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)
SQLSTATE[42000]: Syntax error or access violation: 1102 Incorrect database name '#mysql50#.rocksdb'


# 現象

AWS EC2 にて mariadb を起動し、CakePHP4から接続した際、下記のメッセージが出る。

```
SQLSTATE[42000]: Syntax error or access violation: 1102 Incorrect database name '#mysql50#.rocksdb'
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75451/90be3a14-4ae1-781d-f2cb-d50a431e5a42.png)



# 対策

EC2にて下記を実施。


vi /etc/my.cnf.d/mariadb-server.cnf

```


[mysqld]
ignore-db-dir=.rocksdb
```

```
systemctl restart mariadb
```
Selenium x GeckoDriverでダウンロードができなかったのを解決した関数

# Chromeが使えないPCが存在した
今回のはこれが原因でFirefox利用になりました。
https://forest.watch.impress.co.jp/docs/news/1226294.html

# ダウンロード処理の際にダイアログが出てきてしまって詰まった
ざっくりと調べたところ、`result.set_preference("browser.helperApps.neverAsk.saveToDisk", mimetypes)`
でしっかりとMIMEタイプを指定できれば良いようです。今回ダウンロードしたいファイルはtxtなので、`text/plain`でいいと思ったのですがそれではうまくいかない....

# MIMEタイプを調べる方法
解決にはこのページが役に立ちました。
https://stackoverflow.com/questions/39519518/python-selenium-firefox-neverask-savetodisk-when-downloading-from-blob-url
実際は上記のサイトとは微妙に異なっていました。
バージョンの関係なのか、`mimetypes.rdf`ではなく`handlers.json`の中にありました。
`"mimeTypes"`の中に`"application/x-download"`ってのがあったのでうまく解決しました。

# 解決したコード（関数）
ある程度MIMEタイプの種類をそろえたので、結構対応幅はあるのではないのでしょうか。

```python

# 一時的なダウンロードフォルダ。相対パスで指定するのがうまくいかなかったために暫定処理として
DOWNLOAD_DIR = os.environ["USERPROFILE"] + r'\Desktop'

def open_browser(headless=True, width=0, height=0):
    print('\nブラウザを開く処理の開始')

    options = webdriver.FirefoxOptions()
    if(headless):
        options.add_argument('-headless')
    options.add_argument('--ignore-certificate-errors')

    profile = profile_for_download()
    driver = webdriver.Firefox(options=options, firefox_profile=profile)

    if (width > 0 and height > 0):
        driver.set_window_size(width, height)
    return driver

def profile_for_download():
    mimetypes = mimetypes_for_download()
    result = webdriver.FirefoxProfile()
    result.set_preference("browser.download.folderList", 2)
    result.set_preference("browser.download.dir", DOWNLOAD_DIR)
    result.set_preference(
        "browser.helperApps.neverAsk.saveToDisk", mimetypes)
    return result

def mimetypes_for_download():
    # ダウンロードのダイアログが出た場合はここを調整する。
    # 多分、プロファイルのフォルダのhandlers.jsonを見ればわかる。
    # プロファイルのフォルダは、設定 -> ヘルプ→ -> ラブルシューティング -> プロファイルフォルダーでわかる。
    result = ["text/xml","text/csv","text/plain",
    "image/png","image/jpeg","image/gif","audio/mpeg",
    "video/mpeg","video.mp4",
    "application/pdf","application/zip",
    "application/force-download","application/octet-stream","application/x-download"]
    return ",".join(result)

```
matplotlibにおけるdisplay errorの抑制方法

githubなどで公開されているコードでディスプレイがある前提のコードのとき、display errorが出て動かない！といった時の対処法についてメモ書き。

いずれの方法もmatplotlibがバックグラウンド処理になり、エラーを抑制できます。

###コード内で抑制しよう
pythonのコード内で以下のように記載する。

```python
import matplotlib
matplotlib.use("Agg")
```


###ユーザ単位で抑制しよう
ファイル名：matplotlibrc
というテキストファイル（拡張子なし）を作成し、以下の文字列をファイルに記載する。
`backend:Agg`

このファイルをローカルの以下に保存する(ない場合は作成する）
Linuxの場合
`home/usename/.matplotlib`


###終わりに
CUIしか使えない環境だったので、回避策を数年前に調査。
後者の方法は設定を忘れて事故が起きることがあるので、前者の方法を推奨。
plt.show()に頼るのはやめよう。やめてほしい。
Windows bat の書き方

# copy files
xcopy .\UIBattle.prefab ..\Unity\Assets\Bundles\UI\UIBattle.prefab

#copy folders &&file
xcopy .\git_synced\folder\* .\dev\folder /s /i
PAUSE

#copy with out asking
xcopy .\Release.txt ..\Config\StartConfig /Y

##サンプル
```bat
xcopy .\AppInfo.cs ..\Unity\Assets\Model /Y
xcopy .\Release.txt ..\Config\StartConfig /Y
xcopy .\ServerConfigLocale.json ..\Bundle /Y

start "FileServer_Win" /min cmd /k call FileServer_Win.bat
start "redis-server" /min cmd /k redis-server
start "Server" /min cmd /k pm2 start ../apps_win_all.json
```

```bat
xcopy .\UIBattle.prefab ..\Unity\Assets\Bundles\UI\UIBattle.prefab
xcopy .\UIBattleComponent.cs ..\Unity\Assets\Hotfix\Module\UI\UIBattle\Component\UIBattleComponent.cs
xcopy .\Plugins\Android\* ..\Unity\Assets\Plugins\Android
xcopy .\Plugins\iOS\* ..\Unity\Assets\Plugins\iOS
xcopy .\Editor\* ....\Unity\Assets\Editor
xcopy .\SocialConnector\* ..\Unity\Assets\ThirdParty\SocialConnector /s /i
```
弱参照を使う

Pythonでなんらかのクラスのコレクションのようなものを作るとき、親になっているオブジェクトの参照を持っておきたい ということはあると思います。

そんなとき、他の言語などだとときどき、`owner`という変数を作って親オブジェクトの参照を持っておく などと言うことがあるのですが、そのまま実装すると循環参照となり、取得したメモリが意図したタイミングで解放されなくなることがあります。

```py:循環参照が起こりうるコード
class ParentClass:
  def __init__(self):
    self.child = []

class ChildClass:
  def __init__(self, owner):
    self._owner = owner

p = ParentClass()
p.child.append(ChildClass(p))
# ... 
```

こんなときのために、オブジェクトを参照する際に参照カウンタを増やさない、**弱参照(weakrefモジュール)**というものがあります。

* [weakref \-\-\- 弱参照 — Python 3\.8\.3 ドキュメント](https://docs.python.org/ja/3/library/weakref.html)

```py:弱参照を使ったコード
import weakref

class ParentClass:
  def __init__(self):
    self.child = []

class ChildClass:
  def __init__(self, owner):
    self._owner = weakref.ref(owner)

p = ParentClass()
p.child.append(ChildClass(p))
# ... 
```

なお、このweakrefオブジェクトで作った参照を辿りたいときは、メソッドのように()をつけて呼び出します。

```py:弱参照を使ったコード
import weakref

class ParentClass:
  def __init__(self):
    self.child = []

  def message(self):
    print("called")

class ChildClass:
  def __init__(self, owner):
    self._owner = weakref.ref(owner)

  def message(self): 
    self._owner().message()

p = ParentClass()
p.child.append(ChildClass(p))
p.child[0].message()
# ... 
```