OmniAICreator/Qiita-1.07M huggingface dataset:
[py2rb] not

# はじめに
移植やってます
# not (Python)
```python
if not v:
```
`not v`が`True`か`False`

```python
>>> print(not 0)
True
>>> print(not 1)
False
>>> print(not None)
True
>>> print(not True)
False
>>> print(not False)
True
>>> print(not [])
True
>>> print(not {})
True
>>> print(not "")
True
```
`0`と`""`の否定で`True`になるんですね。
# ! (Ruby)
```ruby
> puts 0.!
false
> puts 1.!
false
> puts nil.!
true
> puts true.!
false
> puts false.!
true
> puts [].!
false
> puts {}.!

> puts ''.!
false
```
`slack`で知ったのですが、`.!`という書き方が好きですね。
`Python`の否定するオブジェクトによる返り値の変化に対応するのが大変そうです。
それ用の判定メソッドを別途作成するか、オブジェクトをあらかじめ調査しておいて決め打ちするかですよね。
**[追記]**

```ruby:
[0, nil, false].include?(obj).! && obj.empty?.!
```
これだと`Set`を含め、1行でいけそう。
# メモ
+ Python の not を学習した
+ 道のりは遠そう
UIButtonはUIScrollViewの下に配置するとき、isHighlightedを設定しても一瞬のタップでbackgroundColor変わらない問題


普通にこのカスタマイズを使ったらタップでもボタンの背景色が変わります

```
class CustomButton: UIButton {
    open override var isHighlighted: Bool {
        didSet {
            backgroundColor = isHighlighted ? .buttonActive : .buttonDefault
        }
    }
}
```

こういうView配置になると、長押す時だけ反応します。

```
- UIScrollVIew
    - UIButton
```

原因はUIScrollViewのDelay Touch Downを外さないといけないです。
![スクリーンショット 2021-12-08 13.23.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268623/8d3591ba-68e5-0215-ce5f-faf1ab8aec39.png)

あと、UIPageViewのsubviewsにUIScrollViewも存在するので、ご注意を。
対処方法はこちら！

```
public override func viewDidAppear(_ animated: Bool) {
    for view in self.view.subviews {
        if view is UIScrollView {
            (view as? UIScrollView)!.delaysContentTouches = false
        }
    }
}
```

## 参考
https://qiita.com/tetsuhama/items/e09446206dc13559802d
https://stackoverflow.com/questions/41371479/uibutton-only-looks-clicked-highlighted-on-longpress
https://stackoverflow.com/questions/49593158/how-to-fix-highlighted-state-uibutton-delay-in-uipageviewcontroller-page
【Ruby】with_object


##with_object
繰り返しの各要素にオブジェクトを添えてブロックを繰り返し、オブジェクトを返り値として返す。

```ruby
# 0,1,2 と呼びだす enumeratorを作る
to_three = Enumerator.new do |y|
  3.times do |x|
    y << x
  end
end

to_three_with_string = to_three.with_object("foo")
to_three_with_string.each do |x,string|
  puts "#{string}: #{x}"
end
# => foo:0
# => foo:1
# => foo:2
```

##参考

https://docs.ruby-lang.org/ja/latest/method/Enumerator/i/with_object.html
uasyncioによるマルチタスクの実現(micropython)

# はじめに
micropythonは普段使っているwindowsやmacと違い, アイコンをダブルクリックだけで複数のウィンドウを同時に起動するようなことはできないので, 複数のプロセスを同時に実行するためにプログラムを並行/並列処理をやらなければならない. そこにmicropythonが提供しているライブラリは_threadが現れました. しかしながら, [micropythonドキュメント](https://docs.micropython.org/en/latest/library/_thread.html) には_threadについての説明はないので, その代わりに豊富な関数を持っている[uasyncio](https://micropython-docs-ja.readthedocs.io/ja/latest/library/uasyncio.html) が多くのプログラマの注目を集めています.

# マルチタスクとは?
マルチタスク(マルチプロセスも呼ばれる)は原則として並列/並行処理ではありません. 言い換えれば複数のプロセスを完璧な**同期処理**することはできません. CPUの構造によってシングルコアの場合はある瞬間に一つの処理しか実行できません. また, ESP32は二つのコア(デュアルコア)を持っていますが, デュアルコアによるマルチコア操作はサポートされていないらしいです. そしてマルチタスクはプログラマ処理の待ち時間の間にCPUを動作させ別の計算を行い, タスクの処理時間が短いなら並列/並行処理と同じような効果が期待されます. 代替品であるuasyncioはコルーチンを用いてマルチタスクを実現することができます.

# プログラム
ここではシンプルなuasyncioによるマルチタスク処理の例を紹介します.

```uasyncio.py
import uasyncio as asyncio
async def bar(x):
    #回数をカウント
    count = 0
    while True:
        count += 1
        print('Instance: {} count: {}'.format(x, count))
        #出力間隔
        await asyncio.sleep(1)  # Pause 1s

async def main():
    for x in range(3):
        #タスクを生成する
        asyncio.create_task(bar(x))
    #実行時間
    await asyncio.sleep(10)

asyncio.run(main())
```
# 実行結果
実行結果は下図の示す通りにインスタンスごとに出力が十回行われました.
実際にこれは1秒間隔でインスタンス1-3をそれぞれ出力するプログラムなので, 図だけでなかなかわかりにくいですね. もし時間があったら実行してみると多分すぐにわかると思います.
![uas実行結果.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/739847/66ff2cea-da55-a925-c4df-5bc7f4b247b5.jpeg)

# ソースコード：解説していくよ
## uasyncio
micropythonにはuasyncioを行うためのモジュールが標準的に組み込まれています. またasyncioはpythonに組み込まれています.
## async def
uasyncioを使う前提として関数を定義するときにasyncを前に書く必要があります.
## await asyncio.sleep()
前に述べたようにマルチタスク処理とは処理の待ち時間の間に別の処理を差し込むので, その間を定義する関数はawait asyncio.sleep()となります. 
## asyncio.create_task()
プロセスをタスクとして生成する関数です. 複数のプロセスを非同期処理する場合はこの関数を複数回呼び出す必要もあります. 
## asyncio.run(main())
main関数中に書いてあるuasyncio処理をすべて実行する関数です(main関数をあらかじめ定義する必要があります). 注意してほしいのはmain関数の中に記述されているawait asyncio.sleep()がuasyncioによる全体の実行時間となります. つまり先ほどのプログラムの実行時間は10秒となりますので, 実行結果から見るとも1秒間隔で10回出力されたことが見えます.

# 末尾
これでシンプルなマルチタスク処理ができました. プログラムはPeterさんのチュートリアルを一部参照して作りました. uasyncioは他の複雑な処理も提供しており, 詳細は[Github] (uasynciohttps://github.com/peterhinch/micropython-async/blob/master/v3/docs/TUTORIAL.md) に掲載されているので, 興味のある方は読み漁ろう.
git clone時に hostを切り替えて行う

## 背景
ユーザを一時的に使い分けてgit clone実行したい。
秘密鍵 id_rsaを変えずに 一時的に使い分けて指定したい。

## 秘密鍵を作成、公開鍵の登録
一時的に切り替えたいユーザ用の 秘密鍵を作成し、gitアカウントにて 公開鍵の登録

参考:
https://qiita.com/shizuma/items/2b2f873a0034839e47ce

## ~/.ssh/config の設定
```
$ cat ~/.ssh/config
Host [ホスト名]
  Hostname github.com
  User [ユーザ名]
  IdentityFile [秘密鍵の位置を指定]
```


## git clone時
git clone git@[ホスト名]:[アカウント名]/[リポジトリ名].git

できた:relaxed:
[Docker]DBコンテナの作成・起動までの流れ

# はじめに
現在、Web系自社開発企業への転職を目標にポートフォリオを作成中。
Dockerを活用してLEMP環境を構築し、Laravel+VuejsでWebアプリケーションの開発を行っております。

今回は、Dockerを活用したDBコンテナの作成・起動までの流れを記録として残します。

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [DBコンテナの作成・起動までの流れ](#Chapter1)
1. [DBコンテナ作成中に発生したエラー](#Chapter2)
1. [解決策](#Chapter3)
1. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# DBコンテナの作成・起動までの流れ
- docker-compose.ymlの作成

```
version: '3.8'

volumes:
  mysql-volume:

services:
  app:
    build:
      context: .
      dockerfile: ./docker/php/Dockerfile
    volumes:
      - ./src/:/var/www/html
    environment:
      - DB_CONNECTION=mysql
      - DB_HOST=db
      - DB_PORT=3306
      - DB_DATABASE=${DB_NAME}
      - DB_USERNAME=${DB_USER}
      - DB_PASSWORD=${DB_PASSWORD}

  web:
    build:
      context: .
      dockerfile: ./docker/nginx/Dockerfile
    ports:
      - ${WEB_PORT}:80
    depends_on:
      - app
    volumes:
      - ./src/:/var/www/html

  db:
    build:
      context: .
      dockerfile: ./docker/mysql/Dockerfile
    ports:
      - ${DB_PORT}:3306
    environment:
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      TZ: 'Asia/Tokyo'
    volumes:
      - mysql-volume:/var/lib/mysql
```
- .envの作成

```
WEB_PORT=80
DB_PORT=3306

DB_NAME=larasns
DB_USER=default
DB_PASSWORD=secret
DB_ROOT_PASSWORD=root
```
- docker-compose.ymlがあるディレクトリで以下コマンドを実行

イメージを作成

```
docker compose build
```
コンテナを作成、起動

```
docker compose up -d
```

<a id="#Chapter2"></a>
# DBコンテナ作成中に発生したエラー


```
Access denied for user 'root'@'172.18.0.5' (using password: YES)
```

<a id="#Chapter3"></a>
# 解決策
MySQLのデータを初期化した

```
docker-compose down --volumes
```

docker-compose.ymlがあるディレクトリで以下コマンドを実行

```
docker compose build
```

```
docker-compose up -d
```

<a id="#reference"></a>
# 参考文献
- [docker-compose MySQL8.0 のDBコンテナを作成する](https://www.notion.so/Docker-MySQL-Docker-MySQL-7a925e4ae79848909702adf3a36e6fa4#3c5ec637bd3f45f287976ded144ba1b8)
- [docker + mysql が接続できない... Access denied for user 'homestead'@'172.20.0.1' (using password: YES)](https://www.notion.so/Docker-MySQL-Docker-MySQL-7a925e4ae79848909702adf3a36e6fa4#86d74fe360434c2ea7b68f20bfc9dffa)
React Conf 2021まであと14時間です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63327/74c9b878-2638-554e-24e3-37fdac641ef3.png)

https://conf.reactjs.org/stage にスケジュールが公開されました。

日本時間だと木曜午後3時半からリプレイイベントもあります。
フリーランスの確定申告心得


![PAK86_kakuteishinkokusuru20140312_TP_V.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325691/49c68051-7526-a2af-7405-880a44c28476.jpeg)
皆さんそろそろ年の瀬ですが、確定申告の準備してますか？セコムしてますか？

そう、フリーランスの皆さんにとって年末が近づいてくると「ああ、今年も確定申告しなきゃいけないのか。全然何もしてないからまた3月になって忙しい中領収書探したり会計ソフトに入力しないといけないのか。ああ嫌だ嫌だ。」という夏休み最終日の小学生感を全身に感じてきますよね。

かくいう私も副業でフリーランスの仕事をしてますが、安心してください！何もしていません！

と叫んだところで何も安心できる材料が見つからないのは横に置いておいて、今回は「確定申告がウソのように簡単になるために必要なたった5つのこと」みたいな内容では全くなく（残念）、「まだ駆け込みで間に合うかもしれない確定申告のために出来る年末までのフリーランス心得」といった雑な投稿で参りたいと思います。

具体的にどういう事かと言いますと。どうせ確定申告には腰の重い皆さんのことですから、会計ソフトを起動するのは来年の2月に入ってからでしょう。それはそれで自己責任ですし、「自分は追い込まれないとやらないタイプなんで」みたいな群れた羊みたいなエクスキューズをするのもまあ良いでしょう。

だがしかし！

伝票入力していて結果を見ると「随分利益が出たんだなあ、そっか今年（去年か）は結構仕事も多くて売上も上がったもんな。オレもフリーランスとして生計が立ってきたじゃないか、ぐふふ」と悦に浸っていないだろうか。言語道断横断歩道！！なんだその感想は？？横断歩道みんなで渡れば怖くないってか！？

払ってるよ！税金を！追加で！！

まあそんなことはもちろんわかってますよって方が大半かとは思うのですが、別に脱税しろと言いたいわけではなく、「ちゃんとフリーランスの活動を余すところなく経費として上げ切っていますか？売上ばかりに気を取られて肝心の経費がタクシー代だけでしたとかになってませんか？」ってことを言いたいのです。もちろんネットで調べれば『これも経費にできる！個人事業主のためのほにゃらら！』とかたくさん記事があるので、そこに書いてあるようなことはここでは割愛しますが、もし今年は売上あがったし利益出そうだなということが予想できるようなら、ズバリ12月末までに使える経費は使っておきましょうというお話になります。

具体的にですが、例えば

・フリーランスの仕事でお世話になったあの人にお歳暮を贈っておこう
・来年からもっと良い結果を出せるように慰労も兼ねて温泉にいって自分を労おう
・新しくしたい機材があるので年末までに色々と購入して新調しよう
・プリンターのインクが切れそうだから追加発注してコピー用紙も買っておこう
・仕事で読みたいと思ってた書籍も年末年始もあることだしまとめて購入しておこう

みたいなことってすぐに考えつきますよね。1つ1つは大した金額になりませんが、こういうのはチリツモなので結構費用計上できたりします。ここで不安げなあの子から「でもそうやって利益が出るから期末に意図的に色々とお金を使うのってニュースとかでいうアレ的なまずいヤツになったりしないんですか…」という声がいかにも聞こえてきそうです。

喝！！大丈夫です！ビビりすぎです！ものすごい端的に言い切ってしまいますが、結局のところ「そのコストが自分の仕事にとって役に立つときちんと説明できるならどれも立派な稼ぐためのコストなんじゃい！」ということです。例に示した「一人温泉慰労旅」は税務署からすると「これは経費扱いなんですか？」と聞きたくなるかもしれませんが、あなたが「この仕事はデスクワークで持病で腰も痛めていることもあり湯治の意味もあっての温泉であり、自分にとっては対象は自分ではありますが個人事業主としての福利厚生的なものだと思っており、単に仕事と関係なく遊びにいったということでもなく、ちょうどプロジェクトが終わったタイミングでもあり仕事の慰労を目的とした経費として十分に認められ得るはずです！（キリッ）」と主張出来れば立派な経費なわけです。

もちろん税務調査で調査官が来ちゃったりした場合には、そのように主張しても「それは税務上容認できないです」と言われることもあるでしょう。それは結果として甘んじて受ければ良いわけで、引け目に感じる必要はありません。謝る必要ももちろんありません。音楽性の違いでバント解散したのと同じようなもんです（何が？）。正々堂々と主張すれば良いのです。ちょっと訳もなく興奮してきちゃいましたが、要は説明できると思えればそれは立派な経費という事です。

逆に「この間の地下アイドルカフェでの飲食代は仕事とは全然関係ないけど、カフェで仕事してるってことにすれば大丈夫だろう…推しのミミちゃんの食事代も指名料も含まれているから全然仕事とは関係ないけど…きっと大丈夫…大丈夫…」みたいな後ろめたい気持ちで経費にあげちゃったりすると、意外とそんなのは調査であっさり挙げられますのでやめた方がよいでしょう。

あと細かい話にはなりますが駆け込み購入もやりすぎは良くありません。「じゃあ向こう3年分のトナーカートリッジを購入しておいて今年の経費にしてしまおう」みたいな発想をすると、「それは経費として今年計上するのではなく将来の為なので在庫として持って使用する分を払い出す（経費として上げていく）ようにしてください」と言われることになります。でも黒と赤のインクを3本ずつ購入したからといって「じゃあ1本は今年分で」という話にはなりません。だって来月までに黒1本は使い切るとか3か月間で3本は消費するとか短期的な使用量なんてわからないですよね。

つまり「そこまで細かくしなくていいでしょ」が社会通念上認められる範囲であれば大丈夫ってことでしょうか。さっきの話の通りで「どうして3年分のトナーを今購入する必要性があったのですか？」と問われると「節税のため」という説明をするしかなくなってしまいますよね。節税するのは良いことですが、そこには理屈と主張が必要なのだということを今一度思い出して頂きたいと思います。

さあ、ずいぶん長い文章をしたためてしまいましたが、12月末は残りあと少しです。
こんな長文読んでる暇があったらAmazonでショッピングへレッツゴーです。今年の確定申告で利用できる領収書は今年の日付のものだけです。年が明けて「あー、これも経費にしておけばよかったな」と悔いても覆水盆に返らず、英語だとこぼれたミルクは戻らない。
（こんな内容書いててダイジョウブかな。。でも税理士さんに書けるような内容ではないので使命感をもって書いてみました　笑）

皆さんの最後の追い込みを期待して少し早いですがメリークリスマス！
M1 MacでのECRデプロイ

# はじめに
Mac M1にして、ECRにイメージデプロイしたら以下のエラーが出たのでメモしておきます。

```
standard_init_linux.go:228: exec user process caused: exec format error
```

# 対処法
build時にplatformを指定します。

```
docker build --platform amd64 -t [イメージ名]　.
```

これでエラーが解消しました。

Mac M1にすると、アーキの変更で所々つまづきます。
でも色々勉強になって面白いです。
Python3でCGIチャレンジ5　簡易ログイン機能

#作業フォルダ
ps5

#作業
html1つとpy1つ作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401158/3951b723-3cbb-2aec-bf4b-d9c222e09eba.png)

##index.htmlの作成

```html:index.html
<html>
<head><meta http-equiv="content-type" charset="UTF-8"></head>
<body>
  <form action="/cgi-bin/authentication.py" method="POST">
    ID:<input type="text" name="ID">
    PASS:<input type="text" name="PASS">
    <input type="submit" value="ログイン">
  </form>
</body>
</html>
```

##cgi-binフォルダの作成

##authentication.pyの作成。cgi-bin配下に作成。

```python:authentication.py
import cgi
import cgitb
import csv
cgitb.enable()

print("Content-Type: text/html")
print()   

form = cgi.FieldStorage()
id = form['ID'].value
password = form['PASS'].value

file_name = "password.txt"
fieldnames = ['ID', 'PASS']
try:
  with open(file_name, 'r', encoding='UTF-8', newline="") as f:

    reader = csv.DictReader(f, delimiter=",", quotechar='"')
    for row in reader:
      if row['ID'] == id:
        if row['PASS'] == password:
          print('ログインしました')
          break
        else:
          print('パスワードが間違ってます')
          break
    else:
      d = {'ID': id, 'PASS': password}

      with open(file_name, 'a', encoding='UTF-8', newline="") as f2:
        writer = csv.DictWriter(f2, fieldnames=fieldnames, delimiter=",", quotechar='"')
        writer.writerow(d)
        print('ID登録しました')

except Exception as e:
  print(e)
  with open(file_name, 'w', encoding='UTF-8', newline="") as f:
    writer = csv.DictWriter(f, fieldnames=fieldnames, delimiter=",", quotechar='"')

    # writeheaderでヘッダー出力
    writer.writeheader()

    d = {'ID': id, 'PASS': password}
    writer.writerow(d)
    print('ファイル生成とID登録しました')
```

##ターミナルでコマンド実行して、ローカルでCGIサーバーを起動する。

```
python -m http.server --cgi 8000
```

##ブラウザで確認

[http://localhost:8000]

#結果
index.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401158/16f45d82-5908-ffe2-b3c5-9f79a293348d.png)

IDにaaa、PASSに123入れてログイン
開くファイルがなくてエラーになるので、ヘッダーつけてファイルに書き込み
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401158/38f6807d-fe55-d3e0-809d-ced293bc902d.png)

ファイル生成される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401158/e548fd9f-5545-e8ac-7f4f-6733c1bad550.png)

もう一回ログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401158/0bfb6764-848e-9d2b-a45d-3a46e3ae4ee7.png)

違うID/PASS（bbb/111）でログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401158/9e866c78-1916-fe62-58a0-47660aa02c96.png)

PASS違い(bbb/222)でログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401158/a1cf4981-b476-406a-0e0c-0959472c7a67.png)


#理解したこと

-ファイルオープンを'r'にしないとreaderが読めない。
-読めないとExceptionになる
-rでファイルオープン中でも、aで同じファイルをオープンできる。
-for文のelse（Python独特な構文）の使い方
execa を試してみた

## 背景

Node.js の CLI ツールを作っていて、CLI ツールの E2E テストをしたかった。テスト内でコマンドを実行するツール調べていたら `execa` というものがあったので触ってみた。

（ちなみに `execa` は [netlify cli](https://github.com/netlify/cli) や [create-react-app](https://github.com/facebook/create-react-app)　の E2E テストでも使われています）

https://github.com/sindresorhus/execa

## 使い方

```javascript
import {execa} from 'execa';

const test = async () => {
  const res = await execa('echo', ['unicorns']);
  console.log(res);
}

test()
```

出力結果

```javascript
$ node index.js 
{
  command: 'echo unicorns',
  escapedCommand: 'echo unicorns',
  exitCode: 0,
  stdout: 'unicorns',
  stderr: '',
  all: undefined,
  failed: false,
  timedOut: false,
  isCanceled: false,
  killed: false
}
```

標準出力や、標準エラー出力、ステータスコード何かを返してくれるので、CLI ツールの E2E テストには便利ですね。
【Ruby】配列の要素の平均値をちょっと簡単に出す

Rubyには```average```メソッドがないため、
配列の要素の平均を出すときは今まではこうしていた。
独学の頃はいちいち```to_f```するの面倒だなと思ってたけどこういうものだと思ってた。

(RailsのActive Recordには```average```メソッドがある。)


```ruby
array = [4, 5]
array.sum.to_f / array.size.to_f
#=> 4.5
```

ちなみにまとめて```to_f```すると正しい値が返らない。

```ruby
array = [4, 5]
(array.sum / array.size).to_f
#=> 4.0
```

##fdivメソッド
self を other で割った商を Float で返すので、ひとつひとつ```to_f```しなくていい。
今までの方法よりちょっとだけ楽に平均を出せることがわかった。

```ruby
array = [4, 5]
array.sum.fdiv(array.size)
#=> 4.5
```

##参考

https://docs.ruby-lang.org/ja/latest/method/Numeric/i/fdiv.html

https://qiita.com/kodai_0122/items/7019a6bc2944444185f8
AWS初心者がNodejsで作ったLineBotのインフラを構築してみた

# AWS初心者がNodejsで作ったLineBotのインフラを構築してみた

## 概要
専門学生1年生なので大目にみてください...。
今回は、ApiGatewayをトリガーにLambdaを動かしてその結果をApiGatewayに返してくれるという単純なものです。

## インフラ構築
### Lambda作成
linebotという名前で関数を作ります。
![eb4f8059-38e4-467e-98a3-b3f28c195817.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286850/d58e184f-3845-ad54-e768-0d1a45c260d4.jpeg)

作成できたら、LineBotのプログラムをzipファイルにして上げます。
ちなみに作成した初期の呼び出す関数は、indexのhandlerになっているので適切に設定する必要があります。

### ApiGateway作成
ApiGatewayのHTTP APIを作成します。
名前はLineBotApiにしました。
![e097c36a-2ee8-4823-8de0-8c66726b2584.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286850/33ed389e-4b2d-335d-300b-278380128e0d.jpeg)
次に、ルートの作成をします。
![Screenshot from 2021-12-08 11-27-09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286850/54aac01c-8ed8-b546-c1f3-8c3cb86b88d1.png)
Lambda関数と先ほど作成したルートを結合させます。
![27c81c82-0871-45a4-b54a-ab718fc2eeb5.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286850/59c623bf-5547-82ce-1e91-0218762c847f.jpeg)
LambdaのトリガーにApiGatewayが表示されていたら成功です！![6171c678-748b-4279-9bc9-487cac0215ee.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286850/cc5f4c78-4b78-c675-b984-199a45af7450.jpeg)
ApiGatewayの$defaultにあるurlをlinebotのwebhookに貼り付けてあげれば動くはずです。

## 終わりに
これらのインフラを元にEvent Bridgeで定期的にメッセージを送ったり、
DBと接続することでユーザーによって質問内容を変えたりもできたので、「AWS楽しい！」ってなってました。
ローカル環境でPythonスクレイピング、スプレッドシートへの接続、操作まで（備忘録）

# ローカルにPythonの仮想環境を構築してスクレイピングした時の備忘録

## 参考元
https://qiita.com/thatbin/items/3ebdfc415d0c30d2f8f6
https://qiita.com/m-masaki72/items/7ba34e31d9f08662f1ee
https://qiita.com/t-yama-3/items/a21999a7f5b3debf3ec7
https://tanuhack.com/operate-spreadsheet/
https://tanuhack.com/library-gspread/
https://www-creators.com/archives/1662


## 本題
スクレイピング案件やるたびに忘れてググり直しているので、Python環境の構築からスクレイピング、取得データをスプレッドシートへ自動送受信操作まで行うために、どの記事をどの順番で読めばいいかまとめる。
いつもは google colaboratory でやっていたが、GitHub での管理のしやすさから始めてローカルに仮想環境を構築して行ってみた。

## 仮想環境の構築

https://qiita.com/thatbin/items/3ebdfc415d0c30d2f8f6
この通りにvirtualenvをインストールしてPython用の仮想環境を構築

https://qiita.com/m-masaki72/items/7ba34e31d9f08662f1ee
virtualenvはgitで管理すると便利なので、この記事通りに設定

## スクレイピング設定
https://qiita.com/t-yama-3/items/a21999a7f5b3debf3ec7

この記事に従って必要なライブラリをインポートしドライバーをダウンロード

### 注意
この記事の **3. ソースコードの記述**の以下のコードは、Chrome()の引数に相対パスを記述しないとエラーをはく

```
driver = webdriver.Chrome() # WebDriverのインスタンスを作成
```

ドライバーが同階層にあるならこんな感じ

```
driver = webdriver.Chrome('./chromedriver') # WebDriverのインスタンスを作成
```


## Pythonでスプレッドシートに読み書きする初期設定まとめ

https://tanuhack.com/operate-spreadsheet/

### 注意
この記事の**1-4. 認証情報を設定する**で生成した秘密鍵をGit管理から外す

[gitignoreについて](https://www-creators.com/archives/1662)

keyフォルダを作成し、その中に秘密鍵を入れる 
.gitignoreファイルに以下を記述

```
key/
```

リモートリポジトリにプッシュした時にkeyフォルダが反映されていなければOK
ひとまずここまでで環境構築は終了
コーディングへ

## gspreadライブラリの使い方まとめ

https://tanuhack.com/library-gspread/

最初慣れないうちはこういう２次情報（ブログ記事など）見ながら実装してみて、詰まったらその部分限定で1次情報（[公式ドキュメント](https://docs.gspread.org/en/v5.0.0/)）を見て仕様を確認するのがおすすめ。
1次情報は強い。
EDCW ワークショップ

# 概要

2012年に開催された [誤り検出・訂正ワークショップ 2012](https://sites.google.com/site/edcw2012/) について紹介します。

# 経緯

2011年ごろ言語学習者の誤り訂正の研究に取り組み始めたということと、2012年からは NLP 若手の会シンポジウム（YANS）の共同プログラム委員長になるということがあり、YANS で新しい取り組みを始めたい、という意図があり、英作文の誤り検出・訂正に関する共通タスクの可能性について甲南大の永田さんに相談してみたところ、ちょうど永田さんもそういう共通タスクに興味があったそうで、教育測定研究所（KJ コーパスは甲南大と教育測定研究所で作ったコーパスなので）とも話をつないでいただき、実現に漕ぎ着けた、というものです。

いま英語文法誤り訂正の共通タスクというと、英語学習者コーパスにアノテートされている全ての誤りを対象とする CoNLL 2013, CoNLL 2014 や BEA 2019 が有名ですが、2011年から2012年にかけては [HOO: Helping Our Own](https://www.mq.edu.au/research/research-centres-groups-and-facilities/innovative-technologies/centres/centre-for-language-technology-clt/research/projects/hoo-helping-our-own) という共通タスクが開催されていて、冠詞や前置詞のように誤りの種類を限定した誤り検出・訂正の研究がされており、むしろ全ての誤りを対象とするような研究はどちらかというと異端でした。一方、自分たちは Lang-8 のデータを使えば全ての誤りを（精度がそんなに出るとは正直思っていなかったですが）対象とすることができることが分かっていたので、共通タスクとして全ての誤りを対象とするトラックも設けたい、という下心もありました。

最終的には4チームの参加があり、YANS の中でのイベントとして開催してもらったこともあり、YANS の中で表彰式を開催したりもしました。予稿集は Google Sites、ソースコードは GitHub にて全て公開されており、システム出力についてもその後のバージョンの KJ コーパスに含まれています。（このワークショップ開催の経緯についての論文も執筆・国際会議に投稿しましたが、現在のところお蔵入りになっています）

# 感想

共通タスクをオーガナイズするのは初めてで、やってみるとものすごくたくさんのことを（相当前から）準備する必要があり、参加するのとオーガナイズするのは全然別物だなあ、と思いました。それ以降、ときどき参加した共通タスクの運営がグダグダだったりすることにしばしば遭遇しても、「まあスケジュール通り動くのは大変だよね」と広い心で見ることができるようになりました（永田さんがしっかりスケジュールの線表を引いてくださっていたので、EDCW 2012 についてはグダグダになるところはなかったです）。

あと、NAIST 松本研では松本先生も乾先生も共通タスクに参加することに関してはあまりポジティブな反応はなく（自分は学生時代には IWSLT とか NTCIR とか共通タスクには1-2年に1回参加していました）、共通タスクの参加者は他の人が作った問題を解くだけで、本当に偉いのは問題を提起する共通タスクの提案者の方だ（あるいは、できたコーパスを使って手法の研究をするのもいいが、そもそもコーパスを作ること自体がどういう問題を解くかを決めていることなので、重要である）、ということを（特に乾先生が）何回かおっしゃっていたのを覚えていますが、自分がオーガナイズする側になってみて初めて、これはそういう意味だったのか、ということが分かりました。論文を読むのと論文を書くのは漫画を読むのと漫画を描くのくらい違う、とは思うのですが、誰かが作ったコーパスを使って研究するのと、自分でコーパスを作って研究するのも、同じくらい違います。

ちなみに、共通タスクについてよくある誤解は、共通タスクをすればいろんな手法が登場して最強の手法が分かる（各チームは SoTA を目指す）、みたいなのがありますが、それはそこまで重要ではなく、同じデータ・同じ評価尺度で研究をする基盤が作られる、というのが共通タスクにおける一番の意義で、二番目の意義はそれを前提とした（このデータ、この評価尺度には問題がある、という問題提起も含め）いろいろな議論ができる、というものです。共通タスクを開催するとそのたびにテストデータが作成される（場合によってはシステム出力が収集・公開される）、というのもコミュニティにとっては重要で、開催するたびに言語資源が増えるのです（スケジュールやタグ付け、取りまとめをどうやるかという運営が大変ですが）。

EDCW ワークショップについては2回目の開催を検討し、やめようかという話になったので以降は開催されていませんが、ここで参加した NAIST チームを率いていた水本さんが 2014年から2015年にかけての [Project Next NLP](https://sites.google.com/site/projectnextnlp/) の英文校正タスクのタスクリーダーとなってくれ、（いまは国内で複数のグループが取り組んでいますが）その後の日本国内での文法誤り訂正研究につなげることができたかなと思います。

最後になりますが、その後 YANS でもハッカソンがときどき開催される（参加者もかなりの人数がいる）ようになったので、せっかく手が動く人がたくさん参加しているイベントだし、交流できる機会を活用できるようになった、というのはよかったと思っています。こういうイベントが対面で開催できるようになるといいのになあ、と思ったりしています。
laravel6.x以降で ddd()関数で簡単にデバッグする

# 目的

- PHPで`ddd()`関数を用いて簡単にデバッグする方法をまとめる

# 環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Big Sur(11.6) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.11 | Homebrewを用いてこちらの方法で導入→[Mac HomebrewでPHPをインストールする](https://qiita.com/miriwo/items/cd54077aad7e139cf518) |
| Laravel バージョン | 8.X | commposerを用いてこちらの方法で導入→[Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08) |
| MySQLバージョン | 8.0.21 for osx10.13 on x86_64 | Homwbrewを用いてこちらの方法で導入→[Mac HomebrewでMySQLをインストールする](https://qiita.com/miriwo/items/ef6a064bc545fbea29d9) |

# 概要

- 下記の記事で紹介した内容が記載されている前提でlaravelのコントローラークラスに`ddd()`関数を記載してデバッグしてみることにする。
    - [laravel8 超絶簡単なCRUD処理を作る](https://qiita.com/miriwo/items/fa6e7904f82251434afd)
- 今回記載したコードは下記のリポジトリにアップする。
    - [https://github.com/miriwo0104/laravel8_easy_crud/tree/ddd](https://github.com/miriwo0104/laravel8_easy_crud/tree/ddd)

# 方法

1. `ContentController.php`を開き`list()`関数の中を下記のように修正する。

    ```/Users/okawashun/workspase/study/laravel8_easy_crud/app/Http/Controllers/ContentController.php
    /**
     * 投稿一覧ページの表示
     *
     * @return view
     */
    public function list()
    {
        $content_infos = $this->contentService->getAllContentList();
        ddd($content_infos);
        return view('contents.list', ['content_infos' => $content_infos]);
    }
    ```

1. laravelのローカルサーバーを起動して[contents/list](http://127.0.0.1:8000/contents/list)にアクセスする。
1. 下記の様に`ddd()`関数の引数に指定した`$content_infos`の内容が表示される。

    ![🧨_Dump__Die__Debug.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/60a915b3-8d12-02fd-6875-3d28bf6e8011.png)

1. グレーの三角形をクリックするといろいろ情報を確認する事ができる。今は`$content_infos`に格納されている配列のインデックス番号0のoriginal（DBから取得した値）を表示している。

    ![🧨_Dump__Die__Debug.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/6eaa8ae1-8f5a-e7a2-f32e-e58c8ea7d549.png)

1. ここまでは`dd()`関数と同じであるが、`ddd()`関数は更にどのようなRequestが送られたか、Userはだれかなどの情報を表示する事ができる。

    ![🧨_Dump__Die__Debug.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/a5645e4b-63a9-574a-fe94-aa339ae3e0dc.png)

1. laravel6以上ならほしい情報により`dd()`関数と`ddd()`関数を使い分けることが重要そう。

# 参考文献

- [https://zenn.dev/shimotaroo/articles/738d8e01796bc9](https://zenn.dev/shimotaroo/articles/738d8e01796bc9)
- [https://laravel-news.com/ddd-helper](https://laravel-news.com/ddd-helper)
2021年版 levmarをmacで動かす方法

levmar は　Levenberg_Marquardt法がシンプルに実行できるパッケージです．
http://users.ics.forth.gr/~lourakis/levmar/

gfortran　のインストール

```
brew install gfortran
```

いろいろインストール
バージョンが最新か注意すること

http://www.netlib.org/blas/blas.tgz
http://www.netlib.org/lapack/lapack-3.10.0.tgz
http://www.netlib.org/f2c/libf2c.zip
http://www.ics.forth.gr/~lourakis/levmar/levmar-2.5.tgz

好きなところに移動させてmake 筆者は/use/local/Cellar以下に移動させた

blasをmake -> blas_LINUX.a
lapackをmake -> lapack_LINUX.a
libf2cをmake -> libf2c.a
levmarをmake -> liblevmar.a

sudo ln -s /もとパス/xxx.a /usr/local/gfortran/lib/libXXX.a でblas，lapack，f2c，levmarのシンボリックリンクを/usr/local/gfortran/libに作る。リンク先の命名規則はlibXXX.aで統一する

```
sudo ln -s /usr/local/Cellar/BLAS-3.10.0/blas_LINUX.a /usr/local/gfortran/lib/libblas.a
sudo ln -s /usr/local/Cellar/levmar-2.6-build/liblevmar.a /usr/local/gfortran/lib/liblevmar.a
sudo ln -s /usr/local/Cellar/lapack-3.10.0/liblapack.a /usr/local/gfortran/lib/liblapack.a
sudo ln -s /usr/local/Cellar/libf2c/libf2c.a /usr/local/gfortran/lib/libf2c.a
```

- コンパイル

```
g++ main.cpp -llevmar -llapack -lblas -lgfortran
```


参考 サンプルコードを載せてらっしゃるので動作確認にどうぞ
https://sites.google.com/view/higamemo/memo/levmar-on-mac
PHP laravel dd()関数で簡単にデバッグする

# 目的

- PHPで`dd()`関数を用いて簡単にデバッグする方法をまとめる

# 環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Big Sur(11.6) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.11 | Homebrewを用いてこちらの方法で導入→[Mac HomebrewでPHPをインストールする](https://qiita.com/miriwo/items/cd54077aad7e139cf518) |
| Laravel バージョン | 8.X | commposerを用いてこちらの方法で導入→[Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08) |
| MySQLバージョン | 8.0.21 for osx10.13 on x86_64 | Homwbrewを用いてこちらの方法で導入→[Mac HomebrewでMySQLをインストールする](https://qiita.com/miriwo/items/ef6a064bc545fbea29d9) |

# 概要

- 下記の記事で紹介した内容が記載されている前提でlaravelのコントローラークラスに`dd()`関数を記載してデバッグしてみることにする。
    - [laravel8 超絶簡単なCRUD処理を作る](https://qiita.com/miriwo/items/fa6e7904f82251434afd)
- 今回記載したコードは下記のリポジトリにアップする。
    - [https://github.com/miriwo0104/laravel8_easy_crud/tree/dd](https://github.com/miriwo0104/laravel8_easy_crud/tree/dd)

# 方法

1. `ContentController.php`を開き`list()`関数の中を下記のように修正する。

    ```/Users/okawashun/workspase/study/laravel8_easy_crud/app/Http/Controllers/ContentController.php
    /**
     * 投稿一覧ページの表示
     *
     * @return view
     */
    public function list()
    {
        $content_infos = $this->contentService->getAllContentList();
        dd($content_infos);
        return view('contents.list', ['content_infos' => $content_infos]);
    }
    ```

1. laravelのローカルサーバーを起動して[contents/list](http://127.0.0.1:8000/contents/list)にアクセスする。
1. 下記の様に`dd()`関数の引数に指定した`$content_infos`の内容が表示される。

    ![127_0_0_1_8000_contents_list.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/1623a373-b021-8050-e68f-f8561eae6a4d.png)

1. グレーの三角形をクリックするといろいろ情報を確認する事ができる。今は`$content_infos`に格納されている配列のインデックス番号0のoriginal（DBから取得した値）を表示している。

    ![127_0_0_1_8000_contents_list.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/bf8af5d8-5e6d-32a0-dbf6-82370f07a327.png)

#
WordPress と AWSSSO を「WP SAML Auth」で連携する

#前提条件
- EC2 に WordPress をインストール済み
- WordPress にプラグイン WP SAML Auth 追加済み
- AWSSSO でユーザー作成済み

#手順
##AWS SSO の設定
以下の記事を参考に AWS SSO の設定を完了させる。
アプリケーションのプロパティの以下の欄は後で設定するので空欄にしておく。

- アプリケーション開始URL
- アプリケーション ACS URL
- アプリケーション SAML 対象者

https://qiita.com/gorooe/items/5e662de306dc94068aac

##Wordpress saml の設定

AWS SSO 証明書をダウンロードして、 WordPress のサーバにアップロードしておく。
ドキュメントルート(公開領域)に置かないよう気を付ける。

設定内容

- Auto Provision : チェック
- Permit WordPress login : チェック
- Get User By : email
- Entity Id (Required) : AWSSSO 設定のアプリケーション SAML 対象者にコピペ
- Assertion Consumer Service URL (Required) : AWSSSO 設定のアプリケーション開始 URL と アプリケーション ACS URL にコピペ
- Entity Id (Required) : AWS SSO 発行者 URL
- Single SignOn Service URL (Required) : AWS SSO サインイン URL
- Single Logout Service URL : AWS SSO サインアウト URL
- x509 Cerificate Path : サーバにアップロードした SSO 証明書のパスを設定
- user_login : username
- use_email : email
- display_name : nickname
- first_name : firstname
- last_name : lastname

![スクリーンショット 2021-12-08 10.35.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1488939/bd41c7e3-9d5e-e6ec-ee99-650d9c022101.png)
![スクリーンショット 2021-12-08 10.42.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1488939/45fa3189-f04b-0d57-2a29-bfb91d94e536.png)
![スクリーンショット 2021-12-08 10.43.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1488939/a5410187-9278-ff95-a07b-23a1678aac61.png)
![スクリーンショット 2021-12-08 10.46.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1488939/0a9db1f5-1278-969b-7a3e-c390d2bb2e7d.png)

#ログイン
##AWS SSO からログイン
AWSSSO のスタートページに WordPress が追加されているのでクリックし、 AWSSSO アカウントでログインする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1488939/098bbb12-de2e-a1b6-e1b1-3dc7d5815aae.png)

##WordPress のログイン画面からログイン
WordPress の画面からもログイン可能。
SAML Login をクリックして AWSSSO アカウントでログイン。
Sign In ボタンのリンクをコピーして AWSSSO 設定のアプリケーション開始 URL に設定すると AWSSSO からログインした時に WordPress のログイン画面を経由しなくなる。
![スクリーンショット 2021-12-08 11.38.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1488939/16ee0a15-9791-9680-d014-b806be4c7a6c.png)
Workato：レシピや関連するアセットをGitでバージョン管理するには

Workatoよりエクスポートされるレシピは、ZIPファイルとしてダウンロードすることが出来ます。また、そのZIPファイルには、レシピやアセットが定義されたJSONファイルが含まれています。つまり、そのZIPファイルを展開し、展開された内容をGit等のバージョン管理システムを利用してバージョン管理することが可能です。

バージョン管理システムを利用することで、Gitを例にすると、いつ誰がどのような変更をレシピや関連するアセットに対して行ったか変更を追跡したり、Pull requestによるレビューおよび承認・マージの仕組みを、Workato開発において実現することができます。

# 手順
## Workatoのワークスペースからレシピをエクスポートし、GitリポジトリへCommitする
### １．Recipe Lifecycle Management で、レシピおよび関連するアセットをエクスポートします
以下の投稿を参照ください

https://qiita.com/tabimoba/items/d696b3937a56c1b5142d

### ２．ダウンロードしたファイルを展開します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/efe7b429-4139-fcbf-2a01-522fef3766d2.png)

### ３．Gitリポジトリの準備あるいは更新を行います
#### 【１】リポジトリが未作成の場合
##### １）ローカルリポジトリとなるフォルダを作成し、コマンドプロンプトで そのフォルダへ移動し、`git init` コマンドを実行します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/17ba8823-5b06-e54e-740b-bbde57faf544.png)

##### ２）上記フォルダへファイルをコピーします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/c589fb74-bc57-f213-e7d4-21c0a752e81a.png)

#### 【２】リポジトリが作成済である場合
所定のフォルダへファイルをコピーし、既存ファイルを上書きします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/d783c612-474b-0015-263a-018b4f9fb6cc.png)

### ４． `git add` コマンドおよび `git commit` コマンドを実行し、ローカルリポジトリに対して変更内容をコミットします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/0c05f1d7-8692-ad45-dbe6-8ca96bbc4091.png)

### ５．GithubやGitLab, Bitbucket等のリモートリポジトリが存在する場合は、必要に応じて `git push` でリモートリポジトリへ変更内容を反映します

## Gitリポジトリで管理されたレシピを、Workatoのワークスペースへインポートする
### １．レシピを管理しているフォルダ（ローカルリポジトリとなるフォルダ）を暗号化されていないZIPファイルとして圧縮します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/537d0ef8-e121-d996-db40-44be75997e83.png)

なお、.gitフォルダが含まれた状態でも問題なくレシピはインポート可能ですが、セキュリティ等を考慮して避けたい場合は、事前に.gitフォルダを除外したうえでZIPファイルを作成ください。

### ２．以下の内容を参考に、レシピのインポートを進めます

https://qiita.com/tabimoba/items/d696b3937a56c1b5142d

なお、Import packageでは、１で圧縮して生成されたZIPファイルを指定します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/06dc690d-6b11-ce8d-8e8e-fa0b2d103131.png)

# 参考

https://docs.workato.com/recipe-development-lifecycle/rdlc-guide-source-control.html
[wordpress]WP_Queryで、後から追加した、オブジェクトがまだ存在しないカスタムフィールドを検索条件にする

カスタムフィールドを後で追加した場合、追加前の記事は「そのカスタムフィールドは存在しない」という状態になっている。
NULLでも空白でもなく「存在しない」という状態。

NULLか空白にする場合は、記事を一つずつ開いて更新する必要がある。

追加したカスタムフィールドを検索条件にしたい場合、存在しない状態だとNULLや空白を取得条件にしても弾かれてしまう。
その場合は"NOT EXISTS"で検索すると吉。

```
$args = array(
    'post_type'     => 'post',
    'post_status'   => 'publish',
    'meta_query'    => array(
    array(
        'key'     => 'sample_field',
        'compare' => 'NOT EXISTS'
        )
    )
);
$query = new WP_Query( $args );
```

こちらのサイトを参考にさせていただきました。
https://ippaiattena.co.jp/blog/job/3996/
[py2rb] basestring

# はじめに
移植やってます
# basestring (Python)
```python
try:
    basestring
    PY2 = True
except NameError:
    basestring = (str, bytes)
    PY2 = False
```
`basestring`って型というかオブジェクトで、`ver2.7`くらいまで使用されていた様子。
[basestringという抽象クラスが削除 - Qiita](https://qiita.com/cstoku/items/353fd4b0fd9ed17dc152#basestring%E3%81%A8%E3%81%84%E3%81%86%E6%8A%BD%E8%B1%A1%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%8C%E5%89%8A%E9%99%A4)

`bytes`型も曲者です。

```python
data = 'こんにちは'
>>> encoded = data.encode('sjis')
>>> print(encoded)
b'\x82\xb1\x82\xf1\x82\xc9\x82\xbf\x82\xcd'
```
プログラム上、読み込んだデータが文字列かどうかを判定するのに使用されています。

```python
if isinstance(args[0], basestring):
```
# String (Ruby)
```ruby
if args[0].instance_of?(String)
```
比較する対象次第ですが、`String`で代用しようかなと考えております。
# メモ
+ Python の basestring を学習した
+ 道のりは遠そう
moonlanderのキー配置を晒す

この記事は Ateam Lifestyle Inc. Advent Calendar 2021 9日目の記事です。

2年ほど前から左右分離キーボードを使用しています。最初はキー配置に慣れず作業効率が落ちていましたが、３ヶ月ほど使うと普通のキーボードに戻れなくなってきました。
使用しているキーボードは「moonlander」です。このキーボードはプログラミング可能なためキー配置を自分好みに変更できます。
この記事では、設定しているキー配置を紹介できればと思います。

## キー配置の変更方法
「moonlander」キーボードの販売元のサイトからボタンをポチポチするだけでキーの配置を変更できます。
プログラミングが出来ない人でも簡単に変更出来るのでおすすめです。

https://configure.zsa.io/moonlander/layouts/rDg5n/latest/0

以下のサイトから、他人の作ったキー配置を探せます。良さそうなものがあればコピーして試してみても良いと思います。

https://configure.zsa.io/moonlander/search

## キー配置のコンセプト

キー配置を作っていく上で意識していることは以下になります。

* なるべくMacの標準にキー配置に寄せる
* 手首に負担をかけないようになるべくホームポジションを崩さないようにする
* 親指に仕事をさせる


## 各レイヤーについて

### Layer１
メインで使用しているLayerです。
ホームポジションに特殊キーを集めることにより、ほぼ全てのショートカットをホームポジションから動くことなく入力できます。
このキー配置にしてから長時間のタイピングで指が痛くなることがなくなりました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60815/0d11e3b8-2d76-fca2-a4d3-667288245f71.png)


### Layer２
数字や記号をまとめたLayerです。
理想はホームポジションのまま記号や数字を入力するようにしたかったですが、まだ使いこなすこなせていません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60815/e4cba9a5-2c69-5f8f-3bd6-012368ba2fe1.png)


### Layer３
遊びのLayerです。時々マウスカーソルをキーボードから動かして遊ぶ事があるのでカーソルを動かすための設定です。
遊ぶだけなのでマウスカーソルは動かしても効率は上がりません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60815/10d6feb9-ed3a-eb9f-8be4-0b6d00d2337c.png)


### Layer４
Macの画面切り替えのためのLayerとなります。
右手小指でLayer切り替えボタンを押し、左手の「Ctrl+数字キー」で画面を切り替えています。
私は画面ごとにアプリケーションの割当をし、画面を切り替えることでアプリケーションが切り替わるようにしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60815/06cf6e48-fdfc-c56c-6ffd-3190a0a1b494.png)


画面の切り替えについてはこの記事に詳しく書かれています。

https://qiita.com/saboyutaka/items/d6cfd2a2b60f1a374d60

### Layer５
主にWindowsで使用するためのLayerです。
業務ではMacを使っているためLayer１だと特殊キーがWindowsに対応出来ていません。Windows用に特殊キーを変更しています。
また、左手の長押しで特殊キーになる設定はゲームをするときに邪魔になるため外しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60815/24701a60-6117-8052-7923-200eeb44bf91.png)

# まとめ

分割キーボードを使うようになってから、自分好みのキー配置を模索しています。
公式サイトでは自分以外の人のキー配置を見ることで、色々な人のキー配置をみて良いところを取り入れていきたいです。
Flutter開発を4ヶ月ほどやっての振り返り

# はじめに

7月から4ヶ月間Flutterでアプリ開発を行いました。
リリースが終わり、振り返りを含めて良かったこと、大変だったことをまとめようと思います。
うまくいったとは言えないので、未だに困っていることやダメだよってところの指摘とかあったら嬉しいです。

これからFlutter開発しようと思う人で、自分のケースだとどんなことが活かせたかとかもサンプルとして参考にしていただけたら幸いです。

## チーム体制

不動産系のスマホアプリで、チームとしてはテスターさん含めて7人くらいの構成です。
チームメンバー全員、はじめて触るFlutterということで調べながら試行錯誤、手探りで行っていました。

## iOSエンジニア→Flutterで活かせたこと

自分は元々iOSのモバイルエンジニアで5年ほど経験がありました。
スクラッチでの開発やリリース経験はあったのでその点はFlutterでのモバイル開発でも活かせるなと感じました。

あと前提知識として活かせたものは
・プッシュ通知（リモート）
・Firebase関連
・アプリ起動時のアプリ全体（システムの）ライフサイクルの理解
・MVVMの知識（今回の場合）
etc....

### プッシュ通知
プッシュ通知はFirebaseのCloud Messagingを使いました。
CloudFunctionsで、CloudFireStoreに保存や削除がかかったタイミングや新しくユーザー作成したタイミングに通知を飛ばしています。

リモート通知の導入のための各OSごとの設定やinfo.plistのような必要なファイルは同じなのでここも良かったです。

ただ、後述しますがもちろん違って新しい作業もあります。

## Firebase

ここは案件によって違うと思いますが、今回の場合はAnalyticsや上記のプッシュ通知、DBやテストアプリ配信などもFirebaseを利用したのですが、今までのモバイルアプリ開発とここも同じでした。
なんだか書いてると当たり前だよなと思いつつ、実装前は不安なところでした。

## ライフサイクル

ライフサイクルは画面ごとのものと、システムのライフサイクルがあって、呼ばれる回数が違うものなどはありましたが、概念は一緒というか同じスマホなのでそこはすんなりいけました。（すんなりと言いつつ最後らへんに手間取られました。。）


#### 2021/12/16 追記

iOS側のだけとりあえず簡単に記事にしました。
[FlutterでシステムのアプリライフサイクルをSwiftで書いた](https://qiita.com/repepe2en/items/3e2c2f97108987b009e1)

## MVVM

アーキテクチャは今回MVVM　＋　Clean　Architectureを目指して開発しました。
Riverpodがええぞ（ハナホジ）ということだったので脳死で利用することにしましたが、やりたいことはわかりました。
もう一度言います。やりたいことは。笑
後々になって、共通のproviderにしておいた方が良かったなど反省点や改修が必要になりました。

Rx系やったことある人とかAndroidエンジニアの方は比較的入りやすいのかなと思います。

## その他
あとはAtomic Designも取り入れてUIパーツを作成とかもしようと努力した（結局最初に決めきれずうまく利用できていない）のですが、概念自体はiOSだとXibファイルにボタンなどのパーツを切り出していくことがあるのでそこもとっつきやすやはありました。

## 利用ライブラリ

実際に利用したライブラリとこれ良かったなっていうのを補足していきます。（ちょっと後で）


```yaml

  cupertino_icons
  # Firebase関連
  firebase_core
  firebase_auth
  firebase_messaging
  firebase_analytics
  cloud_firestore
  firebase_remote_configRemote Config
　　
  flutter_svg # fluttergen　使ってるから必要なかった
  carousel_slider 
  http
  http_interceptor
  flutter_riverpod
  shared_preferences
  freezed_annotation
  flutter_sliding_tutorial
  url_launcher
  auto_size_text
  flutter_inappwebview
  package_info
  uni_links
  expandable
  flutter_dotenv
  dotted_line
  google_fonts
  flutter_local_notifications
  flutter_localizations

  intl
  flutter_native_splash
  clock
  logger
  tuple
  in_app_review
  adjust_sdk
  app_tracking_transparency
  flutter_launcher_icons
  share
  maps_launcher
  google_maps_flutter
  flutter_typeahead
  scrollable_positioned_list

  lint
  mockito
  build_runner
  freezed
  json_serializable

```

## 良かったこと
個人のモチベーションとしては、Flutterに興味があり、だいぶ好きなように作らせてもらったのでよかったです。
開発的には、クロスプラットフォームの恩恵はあったと思います。
Cordova＋Angularの開発もしたことがありますが、意外とSafariやChromeのブラウザによるバグの影響や、HTML,CSS、javascriptによるOS差分があったりしました。
Flutterの場合、natveプラグイン以外で大きな差分みたいのはなかった印象です。（プロジェクトの規模とかも違うので比較対象にならないといえばならないですが。。）

## 大変だったこと
かなりドキュメントや不具合に対する記事が多くなっとはいえ、当時SwiftやKotlinに比べると手探り感はありました。
あとは、自分含めてFlutter経験者が０だったので、進めていく上での妥当性を考えたり本当に良いのか不安になりながらやったところが大変でした。


## 最後に

すみません、いつものようにギリギリになって投稿を思い出して中途半端な状態で出すことをお許しください。。

Flutter、dart楽しいからやっていけたとこはあります。
また自分は業務的には離れてしまいそうですが、個人でも続けて勉強していけたらなと思います。
引用リツイートを自動的に引用リツイートで返す

# 引用RTに引用RTで返す
- 引用RTとは「会話」ではなく「攻撃」である
  - つまり攻撃に対する防衛である
  - 闇のプログラミングではあるが、闇の魔術に対する防衛術である

## 仕様
- 前提としてアカウント名にアンスコが入ってると出来ない
  - 検索クエリを検索APIで叩いているだけなので、API経由でもこれは同じである

https://www.stray-scrapbook.work/entry/twitterSearchRetweetWithComment

## コード
- auth_api(tweetUtil.py)は[前回の記事](https://qiita.com/dialoguedaisuki/items/a6cb28d0105e94f38bf9)にあるのでそちらを参照

```python:quoteRtReply.py
import sys
from tweetUtil import auth_api
import csv

def main():
    # 引用RTに添える文字列
    text = "やはり。あからさま。"
    # get args
    envName = sys.argv[1]
    # Twitter auth
    api = auth_api(envName)
    # search query
    userName = api.me().screen_name
    word = "twitter.com/" + userName + ' /-from:' + userName
    # search
    set_count = "100"
    results = api.search(q=word, count=set_count)
    csvname = envName + "_quotedIds.csv"
    mentionedIds = []
    with open(csvname) as f:
        quotedIds = [int(s.strip()) for s in f.readlines()]
    print(quotedIds)
    for i in results:
        if i.is_quote_status == True and i.id not in quotedIds:
            print([i.id, i.user.screen_name, i.text, i.created_at])
            qrturl = "https://twitter.com/" + \
                str(i.user.screen_name) + "/status/" + str(i.id)
            print(qrturl)
            api.update_status(status=text + " " + qrturl)
            mentionedIds.append([i.id])
        else:
            pass
    # write csv
    with open(csvname, 'a', newline='', encoding='utf-8') as f:
        writer = csv.writer(f, lineterminator='\n')
        writer.writerows(mentionedIds)
    pass


if __name__ == "__main__":
    main()

```

## 実行

```bash
touch nogaslighting_quotedIds.csv
python quoteRtReply.py nogaslighting
```

## 今後
- cronで動かしているが、Stateファイル(csv)をS3に置けばLambda+S3のサーバレスアーキテクチャになるので検討
MacでEclipse環境にlombokをインストールする

備忘録です。

# lombok.jarをダウンロード

https://projectlombok.org/download

ここから最新をダウンロードします。

# lombokをEclipseにインストールする

lombokがダウンロードフォルダにあると仮定して

```bash
$ java -jar ~/Downloads/lombok.jar 
```

起動するとこんな画面が出てくるので自分がインストールしたいIDEのみチェックをつけて`install/update`を実行します。

![スクリーンショット 2021-12-08 11.19.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493116/6a9fa971-42a2-6951-3b61-d4bb2fd99c8b.png)



その後、一度Eclipseを`⌘Q`で終了して起動しなおしエラーが出ているプロジェクトをビルドすれば通るはずです。
PowerVS IBM i 日記(41): Redbook「IBM Power Systems Virtual Server Guide for IBM i」公開

# Redbook「IBM Power Systems Virtual Server Guide for IBM i」公開
まだ、ドラフトですが、Redbook「IBM Power Systems Virtual Server Guide for IBM i」が公開されました。

* [https://www.redbooks.ibm.com/Redbooks.nsf/RedpieceAbstracts/sg248513.html?Open](https://www.redbooks.ibm.com/Redbooks.nsf/RedpieceAbstracts/sg248513.html?Open)

> Chapter 1. IBM Power Systems Virtual Server.
Chapter 2. Migration to Cloud with IBM Power Systems Virtual Server.
Chapter 3. IBM Power Systems Virtual Server in IBM Cloud Network.
Chapter 4. Backup IBM i on IBM Power Systems Virtual Server.
Chapter 5. Hints and tips for IBM i deployments on IBM Power Systems Virtual Server.
Chapter 6. Disaster recovery with IBM Power Systems Virtual Server.
Chapter 7. Reference architectural decisions to migrate IBM i on-premises to IBM Power Systems Virtual Server.
Appendix A. IBM i licensing considerations.
Appendix B. Frequently Asked Questions about IBM i on IBM Power Systems Virtual Server.

英文なのが残念ですが、基本的な操作から、ネットワーク、VTL の利用を含んだバックアップ、オンプレのからの移行など、広範囲な内容になっています。
PowerVS IBM i に関心があるなら、ぜひ読んでいただきたい内容になっています。

(私は Watson 翻訳の「[Translate document](https://cloud.ibm.com/apidocs/language-translator#translatedocument)」の機能で PDF を日本語に翻訳しました:sweat_smile:)

---
2021/12/08 作成

---
当日記のIndexは[こちら](https://qiita.com/6onoda/items/f146c78c0c1bbe905a42)です。

---
許可の無い転載を禁じます。
この記事は筆者の個人的な責任で無保証で提供しています。
当記事に関してIBMやビジネスパートナーに問い合わせることは、固くお断りします。
npm scriptのwatchで複数タスクを実行する方法

## 概要
npm-run-allを使わない方法。
watchでビルドした後に自動でデプロイしたい。


## 方法

`watch-deploy`でwatchして、複数の処理を&&で繋いでワンライナーで実行する。

; でコマンドを連結する場合、コマンド1がエラーであっても、次のコマンドが実行されるが、
&& で連結した場合はエラーが起きた時点で動作が停止する。

&&の代わりに&にすると並列処理になるらしい。

```　package.json
  "scripts": {
    "build": "【ビルド処理】",
    "deploy": "【デプロイ処理】",
   　　"watch-deploy": "watch 'npm run build && npm run　deploy' ./components",
   }
```
ZOOM APIを利用してミーティングのスケジュールを編集する (準備編)

<h2>前書き</h2>
社内のシステムからZOOMでスケジュールを編集する必要があったため調査内容をまとめておきます。
執筆時点(2021-11-23)ではこの内容で実現できました。
(スケジュールを編集する部分は<a href="https://qiita.com/dioh09/items/cffea5ab74f9373943a1">こちら</a>)

<h2>事前準備</h2>
<h3>APIキーを取得する</h3>
ZOOMのマーケットプレイスからAPIキーを有効にします。
有効にする手順等は以下の記事が詳しいです。

https://qiita.com/nanbuwks/items/ed74a76a0f294c0bf4ed

有効にした後、APIKeyやAPISecretが表示されるので保存しておきます。
![zoom.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2314585/74fd2796-42e2-4f48-9b6e-98897c9d3f58.png)


<h2>JWTの用意</h2>
ZOOMAPIでは認証情報とパラメータを含めてHTTPリクエストを送信して利用します。
認証はJWTという形式の文字列にする必要があります。

<h3>JWT</h3>

以下のようなjson文字列をBase64エンコードする。(ヘッダ部)

```
{
	alg : “HS256”,
	typ : “JWT”
}
```

以下のようなjson文字列をBase64エンコードする。(ペイロード)

```
{
	iss : APIキー,
	exp : 生存時間(UNIXタイムスタンプ形式)
}
```

大まかにはヘッダ部とペイロードを 「.(ピリオド)」で連結し、その文字列に対して秘密鍵(ZOOMのAPISecret)を用いSHA256形式で暗号化します。(署名部)
できた文字列をヘッダ部、ペイロード、署名部の順にそれぞれ「.(ピリオド)」連結したものがJWT文字列となります。

作成したJWT文字列は<a href="https://jwt.io/">ここから</a>正しく作成できたかデコードして確かめられます。

今回はライブラリに任せてしまいます、PHP用にcomposerから入れました。
`composer require firebase/php-jwt`

<h2>ZOOM APIを利用する</h2>
ZOOMでは上記のように作成したトークンをヘッダに書いて送信します。
具体的にはこのようになります。
`Authorization: Bearer トークン文字列;`

<h3>ユーザの情報を取得する</h3>
https://api.zoom.us/v2/users/ にGETでリクエストすると使用しているZOOMアカウントの情報をjson形式で取得できます。
ヘッダにはトークンを入れましょう。

PHPのCURLでAPIを叩いたときのソースは下記のようになります。

```php
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "https://api.zoom.us/v2/users/");
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
	"Authorization: Bearer ".$jwt.";",
	"Content-type: application/json; charset=UTF-8;"
));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
curl_close($curl);
```

レスポンスはjson形式で使用したアカウントのメールアドレスや名前などユーザ情報が取得できます。
このjsonのidに書かれている文字列を使用してスケジュール編集に関するAPIを叩くので記録しておきましょう。

```php
{
	"page_count": 1,
	//省略
	"next_page_token": "",
	"users": [
		{
			"id": "XXXXXXXXXXX", //これ
		}
	]
}
```

<h2>まとめ</h2>
今回はZOOMAPIの利用のための準備を行いました。ユーザの情報を取得できていればZOOM公式に書いてあるようなAPIは利用できると思います。
スケジュール操作のAPIはパラメータの説明などで長くなるため別の記事にします。

<h2>参考文献</h2>
https://qiita.com/nanbuwks/items/ed74a76a0f294c0bf4ed
https://marketplace.zoom.us/
https://qiita.com/nanbuwks/items/ed74a76a0f294c0bf4ed
https://marketplace.zoom.us/docs/api-reference/zoom-api/meetings/meetings
https://qiita.com/Naoto9282/items/8427918564400968bd2b
https://jwt.io/
https://openid-foundation-japan.github.io/draft-ietf-oauth-json-web-token-11.ja.html
https://github.com/firebase/php-jwt
企業HPソースコードの面白コメントをコマンドライン上で表示

# 問題

企業のHPの中にはソースコードに面白いコメントを記述しているところがあるので、それをコマンドライン上で抽出して表示してみたい。

## ルール

- `curl`, `grep`のみ使用
- `-A`, `-B`など行数指定や行番号ではなくパターンで抽出
- 出来るだけ短く

## 対象

- [Abema](https://abema.tv)
- [ロリポップ！レンタルサーバー](https://lolipop.jp)
- [日本・コカコーラ](https://cocacola.co.jp)
- [富士そば](https://fujisoba.co.jp)
- [食べログ](https://tabelog.com)
- [任天堂ニュース](https://nintendo.co.jp/nintendo_news)
- [日本アマゾン](https://amazon.co.jp)
- [ドットインストール](https://dotinstall.com)

---

下に自分の解答とスクリーンショットを列挙しています。
自分で腕試ししたい方はここで止めてやってみてください。

---

## 自分の解答

## 実行環境

- macOS 12.0.1
- iTerm2 3.4.14
- zsh 5.8
- curl 7.77.0
- grep (GNU grep) 3.7
- 2021/12/08時点アクセス

### Abema

```bash
curl -sL abema.tv | grep -o ';;.*;'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278919/b28c3e65-a8ec-9f21-989f-fb2d15a61b91.png)

### ロリポップ！レンタルサーバー

```bash
curl -sL lolipop.jp | grep -ozE '\s+_.*_/.'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278919/26daece5-9411-0477-7f63-557ddccb96d2.png)

### 日本・コカコーラ

```bash
curl -sL cocacola.co.jp | grep -ozE ' +__.*eux....'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278919/cfab08e7-216c-6e06-762b-3b474b078d41.png)

### 富士そば

```bash
curl -s fujisoba.co.jp | grep -ozE '.　 ,.*￣..'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278919/14587380-ea7c-d9ae-4ed1-63f21b5b7fa8.png)

### 食べログ

```bash
curl -sL tabelog.com | grep -ozE '\s+z.*t/\s'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278919/d43c211c-6802-c301-8149-5444163c68a5.png)

### 任天堂ニュース

```bash
curl -sL nintendo.co.jp/nintendo_news | grep -ozE '<!---.*--->.'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278919/878c3d39-2d3b-2be2-a55f-02f18a7c7f22.png)

### 日本アマゾン

```bash
curl -sL amazon.co.jp -A '' | grep -ozE '<!--\s+_.*~-->.'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278919/25c21df0-7ecd-6aed-2fbd-46691eafd7b8.png)

### ドットインストール

```bash
curl -sL dotinstall.com | grep -ozE '\s\[エ.*い。..'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278919/a9dc2a08-52fb-3649-4389-505ca4d8783f.png)

更新毎にコメント内メッセージが変化する。以下は1秒ごとに画面を更新して取得したコメントを表示するやつ。

```bash
while :;　do
　　echo '\033[2J\033[3J\033[H'
　　curl -sL dotinstall.com | grep -ozE '\s\[エ.*い。..'
　　sleep 1s
done
```

GIF↓

![_.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278919/9721e243-864f-1ea8-09e9-0752a6116368.gif)

## まとめ

いかがでしたか？笑 `grep -ozE`、便利です。
DockerでPHP/laravelの環境を作る時によく使われるコマンド pecl install や docker-php-ext-install について

`pecl install` も `docker-php-ext-install` も拡張モジュールをインストールするコマンド。
インストールできる拡張モジュールの種類が違う。

## pecl install

### PECLとは

>PHP Extension Community Libraryの略。
PHP言語を拡張するためのモジュールレポジトリ。C言語で記述されており、PEARよりも高速に動作する。ネットワーク経由でライブラリをインストールすることができる。

https://www.weblio.jp/content/PECL

C言語で記述されているPHP拡張モジュールがPECL

Dockerfile に記述する時は下記のように記述

```Dockerfile
RUN pecl install xdebug && \ #インストール
    docker-php-ext-enable xdebug #有効化
```

`pecl install`した拡張モジュールは有効化する必要があります。
有効化で一般的な方法は２つあります
① php.ini に設定
extension = モジュール名 の形式で記述
>モジュールを読み込むには、 php.ini ファイルに extension ディレクティブを追加
https://www.php.net/manual/ja/install.pecl.intro.php

② `docker-php-ext-enable` を使用する
docker-php-ext-enable モジュール名 の形式で記述

## docker-php-ext-install

### こちらは？
このコマンドは、PHPの標準の拡張モジュールをインストール & 有効化する

https://www.php.net/manual/ja/extensions.alphabetical.php

```Dockerfile
RUN docker-php-ext-install intl pdo_mysql zip bcmath #インストールと有効化
```
こちらは`docker-php-ext-install`コマンドで、インストールと有効化をしてくれるので有効化のコマンドは不要です。

## 実際に拡張モジュールはどう選んだらいいのか？
Dockerでlaravelの環境を構築する時などには、要件としてPHPの拡張モジュールが指定されていたりするので、
最低限そのような拡張モジュールはインストールするようにDockerfileを書く必要がありそうです。
>Laravelフレームワークにはいくつかのシステム要件があります。Webサーバへ確実に以下のPHP最低バージョンと拡張機能を用意してください。
BCMath PHP 拡張
Ctype PHP 拡張
Fileinfo PHP 拡張
JSON PHP 拡張
Mbstring PHP 拡張
OpenSSL PHP 拡張
PDO PHP 拡張
Tokenizer PHP 拡張
XML PHP 拡張


https://readouble.com/laravel/8.x/ja/deployment.html

あとは実装、使用したい機能などが、既に拡張モジュールとして提供されているかどうか確認して必要に応じて選択していけば良さそうです。

PECL拡張は下記から検索できます

https://pecl.php.net/package-search.php

## 参考にさせていただいた記事
https://qiita.com/ucan-lab/items/56c9dc3cf2e6762672f4
rust でシステムコマンドを実行

`rust`のプログラムからlinuxのコマンドや自作のスクリプトファイルを実行する場合の備忘録


```rust
use std::process::Command;

fn main() {
    match std::env::current_dir() { // カレントディレクトリを取得
        Ok(x) => 
            {
                let output = Command::new("./user.sh") // 実行したいコマンド
                    .current_dir(x) // カレントディレクトリで実行
                    .output()
                    .expect("failed to execute process");
                let hello = output.stdout;
                println!("{}", std::str::from_utf8(&hello).unwrap());
            },
        Err(err) => {
            eprintln!("{:?}", err);
        },
    }
}
```

- パスが通っているコマンドなら `.current_dir` の設定は要らないし、実行コマンドの頭に`./` も要らない
- パスは通ってるけど `ls` みたいにカレントディレクトリの状態が欲しい場合は必要。、(実行コマンドの頭に`./` 不要)
- パスは通っていないけど、設置場所が決まっているなら 実行コマンドをフルパスで指定すればＯＫ