OmniAICreator/Qiita-1.07M huggingface dataset:
【Ansible】uriモジュールでFastAPIにPOSTしたい

### はじめに
<バージョン>
ansible: 2.9.7
fastapi: 0.65.2
Python: 3.6.8
uvicorn: 0.14.0

　FastAPIとは、Python 3.6 以降でAPI を構築するためのWeb フレームワークです。
今回はFastAPIに対して、AnsibleのuriモジュールでPOSTしてみます。

### 1. 前準備

　まずはFastAPIとuvicornをインストールしましょう。

```text
pip install fastapi uvicorn
```

### 2. Pythonコード作成
　
　実際に作成したコードが以下です。Ansibleからnumberという値をもらい、
その2倍の値を戻すコードを作成しました。

- ポイント
  - @app.post("/calculate")のように、使用するメソッドとアクセス先を記載
     - /calculateとすると、アクセスするURLはhttp://127.0.0.1:8000/calculateになる
  - return {"calculate_result": return_value}のように、戻り値の変数を記載
     - Ansibleでの戻り値は、``register変数.json.calculate_result``になる

```python:test_calculate.py
from pydantic import BaseModel
from fastapi import FastAPI

app = FastAPI()


class main_dict(BaseModel):

    number: int


# url is http://127.0.0.1:8000/calculate
@app.post("/calculate")
async def declare_nested_request_body(data: main_dict):
    return_value = data.number * 2
    return {"calculate_result": return_value}
```

### 3. Playbook作成

　実際に作成したplaybookが以下です。FastAPIに変数number(=10)を渡します。

- ポイント
  - uriモジュール
     - FastAPIに渡す変数はbodyに記載
     - 実行結果はregisterで変数resultに格納する
  - debugモジュール
     - ``result.json.calculate_result``で実行結果が確認可能

```yaml:post_fastapi.yml
---
- hosts: localhost
  gather_facts: false
  tasks:
    - name: "post number"
      uri:
        url: "http://127.0.0.1:8000/calculate"
        method: "POST"
        body_format: "json"
        body:
          number: 10   
      register: result
    
    - name: "debug calculate result"
      debug:
        var: result.json.calculate_result
```

### 4. サーバー起動

　作成したコード(test_calculate.py)のあるディレクトリに移動して、
サーバを起動させましょう。以下のように、uvicornコマンドで実行するコードを指定しましょう。

```text
uvicorn test_calculate:app --reload
```

### 5. 実行結果
　想定通り、渡した変数number(=10)の2倍の値が戻ってきました。

```text:出力
(venv) [centos@ip-<ip-addr> python]$ ansible-playbook post_fastapi.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] ******************************************************************************************************************

TASK [post number] ****************************************************************************************************************
ok: [localhost]

TASK [debug calculate result] *****************************************************************************************************
ok: [localhost] => {
    "result.json.calculate_result": "20"
}

PLAY RECAP ************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
```


### 参考記事
[チュートリアル - FastAPI](https://fastapi.tiangolo.com/ja/)
[[FastAPI] Python製のASGI Web フレームワーク FastAPIに入門する](https://qiita.com/bee2/items/75d9c0d7ba20e7a4a0e9#deployment)
[Ansible Documentation - uri](https://docs.ansible.com/ansible/2.9/modules/uri_module.html)
VSCodeでGo言語の実行環境構築

#VSCodeでGo言語の実行環境構築

Visual Studio Codeはオープンソースソフトウェアのコードエディターです。
今回は、Go言語の拡張機能のインストール手順を記載します。

#環境

- Windows 10 Pro.64bit
- GO : 1.15.6
- VScode : 1.57.1

#GOのインストール

公式サイトよりGOをダウンロードしてインストールします。

https://golang.org/dl/

インストールが完了したら、PowerShellを開き、以下のコマンドでバージョンを確認します。
バージョンが表示されたらインストール完了です。

```
code --version
```

#VSCodeのインストール

公式サイトよりVSCodeをダウンロードしてのインストールします。

https://code.visualstudio.com/download

インストールが完了したら、PowerShellを開き、以下のコマンドでバージョンを確認します。
バージョンが表示されたらインストール完了です。

```
go version
```

#GO拡張機能のインストール

マーケットプレイスの検索窓に「GO」と入力して「Go for Visual Studio Code」でインストールします。

![0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/5d623136-7302-f1fd-3d0f-f381c8712400.png)

Ctrl + Shift + P キーを同時に押下して、検索窓より「Go:Install/Update Tools」をインストールします。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/d40c3639-52f4-c06b-ceab-09c8a9ecbfd3.png)

左側にあるチェックボックスを選択し、「OK」ボタンをクリックします。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/cdb0328f-a22a-2d4b-cf57-58319916a065.png)

「All tools successfully installed.」と表示されれば完了です。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/5fab4f29-605f-c805-3bdb-ce3803f5789f.png)

続けて、マーケットプレイスで「code-run」を検索しインストールします。
code-runを使用すると、様々な言語の実行結果をVCCodeのターミナルに出力することが出来ます。

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/7f7993b0-49b5-6208-be85-f35ba8a30038.png)

インストールが完了したら、PowerShellを開き、以下のコマンドでtest用のGoプログラムを開きます。

```go:hello.go
 code hello.go
```

続けて、下記をコピペして、Ctrl + B　キーを押下で実行します。

```go:hello.go
package main

import (
	"fmt"
)

func main() {
	fmt.Println("Hello, World!")
}
```

ターミナルに実行結果が表示されます。

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/2336e8bf-d939-2121-ebf7-d2e5f4e16e29.png)






#「command ‘code-runner.run’ not found」が表示され実行出来ないとき

マーケットプレイスで「code-run」を検索しアンインストールします。

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/8bf1a15f-7101-1fa7-75e4-5a51002c6224.png)

さらに、Windowsであればエクスプローラで隠しファイルやフォルダを表示する設定した上で「C:\Users\<ﾕｰｻﾞｰ名>\.vscode」という隠しフォルダをフォルダごと削除します。

再度、「code-run」をインストールすると実行出来るようになります。
Linux at command 時刻を指定してコマンドを実行


```shell
$ more shell_content.sh
                    
ls -l /path/to/my/directory/* |  mail -s "content of a directory" my-email@example.com 

$ more shell_send_status.sh

at now + 1   hours   -f shell_content.sh 
at now + 2   hours   -f shell_content.sh 
at now + 180 minutes -f shell_content.sh 
at 14:00Jul2         -f shell_content.sh
```

のようなファイルを用意しておいて

```shell
$ sh shell_send_status.sh
```

とすればよい。

上記の例では、１時間後、２時間後、３時間後（180分後）、「7月2日の14:00」にメールが送信される。

メールのタイトルは「content of a directory」

メールの本文は　```ls -l /path/to/my/directory/*``` 　の内容となる。

計算が進んでアウトプットファイルが増える様子を定期的にメールでチェックできるので便利。

```shell
$ at -l
```
でどんな予定になっているか調べられる。


mail を送る際のmailコマンドのために、
```mailutil```
のようなものをインストールした気がする。

Reference　
https://askubuntu.com/questions/481816/why-my-at-clause-command-execute-the-shell-immediately-and-ignored-the-time-li

# at のインストール
```shell
sudo apt install at
```

# mailutils のインストール
```shell
sudo apt-get install mailutils
```
[プリンシプルオブプログラミング] プログラマーの見る視点

# プログラマーのコードを見る視点

## 凝集度
モジュールは純粋に保ちましょう。
純粋なモジュールとは、独立性の高いこと、凝集度が高いものになります。
コードはモジュール化することによって管理しやすくなります。
分割したモジュールは独立性を保つことによって、コード複雑さを減少させ保守しやすくなります。

モジュールが純粋ではなく、凝集度が低いものになると以下の弊害が起きます。

- コードが理解しにくい
- コードが保守しにくい
- コードが再利用しにくい
- コードが脆弱で、変更による影響を絶えず受け続ける

一方、凝集度の高いモジュールは適度に細分化されたものなので、限定された目的に特化されています。
以下のような利点があります。

- コードの設計の明確さと理解のしやすさ
- コードの保守と拡張が容易
- コードの再利用性が高い
- モジュール間の疎結合が促進する

## 結合度
モジュール間の関係の密接さを表すのが結合度です。
結合度は疎結合であれば、それゆえに独立性が高いコードになるので、いいコードになります。
逆に結合が密なコードは互いに依存しあい、独立性が低いモジュールになります。また、密な結合をしているので、コードの変更があった場合、互いに影響しあう可能性があります。
モジュールはなるべく疎結合で独立性の高いものを目指しましょう。

## 直行性
直行性を満たすコードを作りましょう。
直行性とは、独立性と分離性が高いコードのことを言います。
直行性が高いコードは以下の利点があります。

- 生産性の向上
    - 独立性が高いので変更に強くなります。また独立性が高いということは疎結合なコードになるので、コードの再利用が容易になります。
- リスクの軽減
    - 分離性が高いので、コードが堅牢になります。問題があった場合、コードの変更が他で行われ手入れもその分離性のおかげで影響が少ないまたは無い状態になります。

## 可逆性
可逆的な決定を行いましょう。可逆とは、変更を加えても元の状態に戻ることができるという性質です。
コードにおいての仕様は、確定することはめったにありません。
プログラマが全てを制御下に置いているコードであれば良いのですが、外部の要因(仕様変更、ライセンス、セキュリティ)で変わることがあります。可逆的な決定をしておけば、これらの要因で変更になったとしても柔軟に対応が出来ます。

##
[プリンシプルオブプログラミング] プログラマの三大美徳と法則

# プログラマの三大美徳

## プログラマは怠慢、短気、傲慢であれ

### 怠慢
楽をするのであれば、手間を惜しまない気質のことです。
コードやテストの自動化など、めんどくさいことはコードで行います。
業務やプロジェクトでは、めんどくさいと思う何回も繰り返すものがあります。そういったものを自動化して怠惰であれるようになりましょう。

### 短気
上手く動かなかったらコードをかき直したりする気質です。
また、今ある問題に着目せず、今後起こりうる問題を想定したコードを書きます。
コードの動作が遅い、動作がおかしいなどの面で短気となり、すぐに修正しましょう。それらのコードを残すのは負債となりえます。

### 傲慢
高いプライドを持つ気質です。
レビューされても指摘する場所が無いほどのコードを書きます。
プロフェッショナルの意識を持ちましょう。コードは時として汚いものになりますが、意識をすることで常にキレイな状態に保てます。

## エゴレスプログラミング
プログラミングでエゴを捨てます。
うぬぼれやプライドを捨てて、仲間にコードを見せる、コードを見る時に、自分のほうが優れているという考えを捨てより良い物を作るということに価値観を置きましょう。
エゴレスプログラミングには十戒があります。

- 自分自身も間違いを犯すということを理解し、受け入れる
- 書いたコードは自分自身ではない
- どれほど極めても、上には上がいる
- 相談をせずにコードを修正しない
- 自分よりスキルが劣る人にも尊敬と敬意と忍耐を
- 世界で唯一変わらないものは、変わるということだけ
- 権威は地位ではなく知識から生じる
- 信じるもののために戦い、負けを正直に認める
- 部屋に籠もりきりではダメ
- 人にやさしく、コードに厳しく

# 手法
## 曳光弾
骨格コードを作りましょう。
これは、最初に動作する土台を作るということです。
土台をつくっておけば、骨格のコードに肉付けをしていくだけになり、開発が進んでいく時の指標となります。
また、動作する土台なので、ユーザーからのフィードバックも得られます。
土台を作っておけばテストやデバックもやりやすくなります。

##　防御的プログラミング
こうなるかもしれないという意識を持ってプログラミングをします。
プログラミングでは外部から関数の値を渡されたり、外部ソースからデータを取得したりします。そうなった場合、不正な値がもし入ってきたときにはソフトウェアはエラーを出すかもしれません。
そうならないように、不正なデータが入ってきても大丈夫なように初めからバリデーションなどを使って値を精査するような仕組みを作りましょう。

## ドッグフーディング
自分で開発したソフトウェアを、自分で使いましょう。
ソフトウェアを開発するということは必ずユーザーが存在します。ソフトウェアが使いにくいものであった場合、ユーザーは使ってくれなくなります。そうならないためにも自分自身がユーザーの視点に立ち、ユーザー目線で開発をしましょう。

## ラバーダッキング
プログラミングでバグや不具合、上手くいかないことが起きたら、誰かに説明してみましょう。
話すということは、相手にわかりやすくするために現在の状況を整理しなければなりません、それが自己解決に繋がります。

## コンテキスト
文脈を上手く使いましょう。

- コードの読み書きに使用する
    - コードには、書く人と読む人が居ます。書く人は、変数名や関数名やコメントで読む人にコンテキストを構成します。そうすることでコードの責務、何をしているのかがわかりやすくなります。

コードを書く時にコンテキストを与えると、思考が迷子になりにくいです。ソフトウェアではたくさんのコード、モジュールが複雑に絡み合って作られています。コンテキストがあることによってその複雑に絡み合ったコードやモジュールを読み解くことが出来ます。

# 法則
## コンウェイの法則
アーキテクチャを設計してから組織を編成しましょう。
組織を編成してからアーキテクチャを設計すると、人に偏った設計となり、属人性が高くなること。小ミュニケーションにズレが生じる可能性があります。
アーキテクチャを設計し、プロセスを作ってから、組織をそれに当てはめましょう。

## 割れた窓の法則
悪いコードは許してはいけません。
悪いコードが一つでもあれば、そこから悪いコードが増えます。
「あの部分はこう書いてたからこれでいいか」や「とりあえず動くから処理は遅いけどいいか」などを許すことになります。
そうなった場合、ソフトウェアの品質は地の底に落ちます。
悪いコードは、常に修正し残さないようにしましょう。

## 80-10-10の法則
高水準のツールやソフトウェアは開発するとユーザーの求める80％を実現することができます。しかし、100％を満たすように開発をすると、とたんに開発が立ち行かなくなります。
ソフトウェアの問題解決を狭いものにしましょう。狭くすることにより、問題を的確に捉えることができ、狭くしたことによってソフトウェアの開発も比較的短くすることが出来ます。

## ジョシュアツリーの法則
チームの共通言語を作り、使用していきましょう。
チームの言っていることが、例えばスマートフォンであれば「iPhone」「アンドロイド」「スマホ」「携帯」など様々な言葉でスマートフォンを説明されると、混乱をきたします。
こういったように、チーム内でよく使用する単語などは共通化し、コミュニケーションを円滑に進むようにしましょう。

## ヤクの毛刈り
問題の本質を見極めます。
問題というのは芋づる式で出てきます。
〇〇が動かない -> ライブラリを入れてない -> バージョンが古くて入れられない -> OSのアップデート -> 〇〇がOSに対応していないので動かない
という風に、問題を芋づる式に解決していこうとすると、問題の本質を解決出来ず、時間だけが浪費していきます。
こうなった場合には早々に切り上げましょう。別のツールで動くかもしれませんし、互換性のあるライブラリがあるかもしれません。
もし、問題に立ち向かう場合は、一つ一つ丁寧に精査していくことです。今行った作業はなんなのか、作業をしたことで何が解決して何が問題になったのかを、書き留めたりしながら一歩づつ行うことで、やがて問題の本質が見極められます。
JavaScriptファイルの読み込み失敗時に表示されるFailed to load resourceエラーの解決方法

#目的
私が独学で行き詰った箇所を備忘録として残していることを目的としています。

#概要
ネットから拾ったサンプルのJavascriptファイルを一部改良してHTML上で読み込みを試みたのですが、chromeのDevToolsでFailed to load resourceのエラーが表示されてしまい.jsファイルを読み込むことが出来ませんでした。
![jsエラー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/ac9fbf14-320c-9f6b-25a3-6d60664bde8d.png)


#原因
ネットから拾ったjavascriptファイル名をそのままHTMLに記述してしまったことによりファイルがうまく読み込まれませんでした。

- ネットから拾ったファイル名…js/signin.js
- 保存したファイル名…sign.js

#解決策
HTMLファイル上に正しいjavaScriptファイル名に変更。

#あとがき
経験者からすると初歩的なエラーかもしれませんが、JavaScriptを触って2日目だったのでエラー解決までに30分くらいかかりました。
ネットから拾ったJavaScriptのファイルを使うときは、保存したファイル名とHTML上に記述するファイル名に気を付けるよう心掛けます。
direct definition ― J 言語入門

explicit definition の欠点の一つは、入れ子にできないことです。それを補うために direct definition という構文があります [^1]。

# 構文

**direct definition** (直接的な定義) は、`{{` と `}}` で定義部を囲う構文です。

```j
   average=: {{
      sum=. +/y
      count=. #y
      sum % count
   }}
```

一行で書くこともできます。

```j
   average=: {{ (+/y) % (#y) }}
```

explicit definition とは異なり、最後の `}}` の直後に式を続けられます。また、入れ子にして使うこともできます。

```j
   1 {{
      f=. {{ x , y }}
      y f x
   }} 2
2 1
```

## direct definition と explicit definition

direct definition の実体は explicit definition で、両者には構文上の違いしかありません。

```j
   {{ x + y }}
4 : 'x + y '
```

explicit definition は ほとんど direct definition で置き換え可能です。ただし、`Note` でコメントアウトする方法は direct definition では使えません。(そのため、グローバルな変数の定義では explicit definition を使った方が便利かもしれません。)

# 種類の指定

direct definition は、monad, dyad 等の種類を指定しなくても使われている変数名から自動で決定してくれます。具体的には以下のように決定されます。

1. `v` か `n` が使われていれば conjunction
2. そうでなく `u` か `m` が使われていれば adverb
3. そうでなく `x` が使われていれば dyad か dual-valence
4. そうでなければ monad

明示的に何を定義するのか指定することもできますが、少し変わった構文になります。`{{`　の直後に閉じ括弧 `)` と次の表の 1 文字を続けます。

|文字|種類|
|---|---|
|`*`|デフォルト (何も指定しないのと同じ)|
|`m`|monad|
|`d`|dyad|
|`v`|verb|
|`a`|adverb|
|`c`|conjunction|
|`n`|noun|

```j
   NB. monad と dyad を : で区切るのは explicit definition と同じ
   {{)v
      <y
   :
      x ; y
   }}
3 : 0
      <y
:
      x ; y
   
)
```

`{{)` を書いた行には、それより後に書いてもよいのはコメントとスペースだけです。

# noun

noun の direct definition は特殊な構文になっています。`{{)n` の直後から文字列が始まり、2 種類の書き方ができます。

## 一行

`{{)n` のある行に `}}` がある場合、そこまでが文字列になります。`'` (シングルクォーテーション) を含む文字列リテラルを書くのに便利です [^2]。

```j
   {{)nText '...'}}
Text '...'
```

`{{)n` の後に**スペースは要らない**ことに注意してください。

## 複数行

`{{)n` がその行で終わらない場合、次に**行の先頭**に `}}` が現れるまで文字列が続きます。他の位置にある `}}` は単に文字列の一部になります。

```j
   {{)nabcde
12345
... }}
}}
abcde
12345
... }}

```

最後の改行は文字列に**含まれます**。`{{)n` の次の文字が改行の場合は、その改行は文字列に**含まれません**。

---

\[ 前 : [define の実体](https://qiita.com/unsigned-wrong-wrong-int/items/968640fb004867c9dcce) \] \[ [目次](https://qiita.com/unsigned-wrong-wrong-int/items/e15a87999cedfc6b9ced) \] \[ 次 : [制御構文](https://qiita.com/unsigned-wrong-wrong-int/items/c376a7ea5b58e6bdbf0f) \]

[^1]: J902 で追加された新しい機能です。そのため、シンタックスハイライトが まだ対応していません (2021 年 7 月現在)。
[^2]: ただし、`}}` をエスケープする方法はありません。
【使わないと損！？】Figmaオススメプラグイン

# はじめに
今回は私が実際に使用しているfigmaのプラグインの紹介をしていこうと思います。
# おすすめプラグイン
## [1. Font Preview](https://www.figma.com/community/plugin/890494567122693015/Font-Preview)

手持ちのフォントをリアルタイムでプレビューできます。フォント選びに困っている人にオススメです。

![スクリーンショット 2021-07-02 19.03.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1716526/8fcac12b-fcc6-f785-c34a-9950eea0fa76.png)


## [2. Blush](https://www.figma.com/community/plugin/838959511417581040/Blush)

デザインにイラストを手軽に追加できます。お好みのイラストを選び、構図するだけの簡単操作で、イラストのバリエーションの変更、カスタマイズも可能。

![スクリーンショット 2021-06-26 14.52.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1716526/7493aad6-0fba-7d64-f9cd-272c454cda9a.png)


## [3. Avatars](https://www.figma.com/community/plugin/739659977030056719/Avatars)

AIが作り出した架空の人物写真をアバターとして追加できます。トプ画のデザインにオススメです。

![スクリーンショット 2021-06-26 14.55.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1716526/149d576e-c07a-26e3-b585-8cf04fcbbb93.png)


## [4. Iconify](https://www.figma.com/community/plugin/735098390272716381/Iconify)

マテリアルデザイン・アイコンやFontAwesome、Twitter絵文字など60を超えるアイコンセット、合計5万個以上の素材をベクターシェイプとして追加できます。

![スクリーンショット 2021-06-26 14.59.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1716526/473c2a9a-6f56-93ed-158d-a8ad7280aa5c.png)


## [5. Unsplash](https://www.figma.com/community/plugin/738454987945972471/Unsplash)

Unsplash内に掲載されている画像をfigma内で検索し挿入できます。簡単に画像を挿入することができるのでオススメです。

![スクリーンショット 2021-06-26 15.01.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1716526/697ce076-50bc-e6e2-883e-f68b25ef52e6.png)


## [6. LottieFiles](https://www.figma.com/community/plugin/809860933081065308/LottieFiles)

簡単にアニメーションを追加することができるので非常にオススメです。SVGとしても挿入することができます。

![スクリーンショット 2021-06-26 15.13.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1716526/40213c4a-aa07-fc0e-2b9a-3aa1986fb65d.png)


# おわりに
どうだったでしょうか？今回のまとめが皆さんのweb開発をする際にお役に立てれば幸いです。
これからもオススメのプラグインを紹介していこうと思いますので、応援お願いいたします！
Markdown記法 特殊文字をエスケープする

# 目的

- Markdown記法にて特殊文字をエスケープする方法をメモ的にまとめる

# 方法

- 特殊文字の前にバックスラッシュ`\`を設置することで特殊文字をエスケープすることができる
- 例えばコードブロック？（```で囲むもの）やコードハイライト？（`で囲むもの）以外で「<br>タグ」などを単体で表現したい時は下記の様に記載する。

    ```
    \<br\>
    ```
【Rails】他人の編集画面に遷移しないようにするには

#####My Profile
 プログラミング学習歴②ヶ月目のアカウントです！
プログラミングスクールで学んだ内容や自分が躓いた箇所等のアウトプットの為に発信しています。
また、プログラミング初学者の方にわかりやすいように簡潔にまとめて情報共有できればと考えています。
もし、投稿した記事の中に誤り等ございましたら、コメント欄でご教授いただけると幸いです。　



#対象者

・deviseの設定をしている方
・画面の遷移先を指定したい方

#手順目次
1.before_actionとauthenticate_user!を設定する

2.correct userについてストロングパラメーターの下で定義する


#実際の手順と実例
###1.before_actionを設定する

対象のコントローラーに入力する（今回はBooks controllerを例に上げてます）

```
class BooksController < ApplicationController
  before_action :correct_user, only: [:edit, :update]
:
:
end
```
・before_actionは各アクションが実行される前に呼ばれます。
・今回は後ろのonlyで呼び出す前にアクションをeditとupdateで限定しています。


このあとcorrect_userを定義していきます。

###2.correct userについてストロングパラメーターの下で定義する

入力方法は以下の通り

```
 def edit
  :
 end

 def update
  :
 end

  private

  def book_params
    params.require(:book).permit(:title, :body)
  end

  def correct_user
    @book = Book.find(params[:id])
    @user = @book.user
    redirect_to(books_path) unless @user == current_user
  end

````

一番下に注目です。
まず、
　①@book = Book.find(params[:id])でidのついた本を１つ選びます。
　②@user = @book.userで①で選んだ本をもってるUserであると定義（Userモデルと関連付けています）
　③redirect_to(books_path) unless @user == current_user ②で定義したuserと現在ログインしているuserが一致していなければ、一覧ページにリダイレクトされます。


上記の１、２を両方設定すると他人の編集画面にURL直打ちでは遷移できなくなります！
【mockito-kotlin】関数の引数に設定されたラムダを、当該関数の呼び出しに合わせて実行する

# やりたいこと
以下のように、引数にラムダを取る関数が有ったとします。

```kotlin
interface Interface {
    // lambdaはこの中で必ず呼び出される
    fun target(id: Int, lambda: () -> Unit)
}
```

これを呼び出す関数は以下のようになります。

```kotlin
class Component(
    private val instance: Interface,
    private val something: Something
) {
    fun func() {

        /* ... */

        instance.target(1) { something.doSomething(/* ... */) }

        /* ... */
    }
}
```

規約的には`target`関数が`lambda`を実行するため、結合すれば`something.doSomething`は実行されます。
一方、単体テスト時に`Interface`を`mock`していると、設定なしでは`lambda`が実行されず、`something.doSomething`の呼出テストができません。

そこで、`mockito-kotlin`で、`instance.target`の呼び出しに合わせて`something.doSomething`関数を実行する設定を行います。

## 注意点
利用している`mockito-kotlin`は`1.6.0`で、これは現時点でかなり古いバージョンです。
基本的な`API`は変化していないと思われますが、動かない可能性が有る点をご了承ください。

# やり方
以下のように設定することで、`target`の実行時に`lambda`も呼び出すことができます。

```kotlin
val mock: Interface = mock()
// lambdaに対応するキャプチャを宣言
val captor: KArgumentCaptor<() -> Unit> = argumentCaptor()
// mockの`target`関数が呼ばれた際、lambdaを実行する
whenever(mock.target(id = any(), lambda = captor.capture()))
    .then { captor.lastValue.invoke() }
```
React×TypeScriptのAPI通信をRepositoryFactoryで書く


## これは何
フロント(React)からAPIと何か通信をする時、通信ロジックが冗長になったり、axiosなんかの設定が分散したりするのを解決しちゃいたい！を記事にしました。

## ReposiotryFactoryってなんだろ
[ReposiotryFactory](https://docs.microsoft.com/en-gb/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design#the-repository-pattern)とはソフトウェアデザインパターンの一つで

- リポジトリパターンを使用して、データを返す以外のロジックを使用せずに、分離された方法でリソースにアクセスできる
- ファクトリパターンを使用して、必要なリポジトリと、環境のロジックをインスタンス化する

という設計で、API通信における冗長をなくし可読性が高くすることができると考え、私は採用しています。

## 実際にかいてみる

ToDoアプリのToDo機能(Get,Post)を実装する程で以下にサンプルを示します。

- todoResourceへのGet  →Todo一覧の取得
- todoResourceへのPost →Todo新規作成

### ReposiotryFactoryの定義

axiosインスタンス作成を行う。ドメイン変更時・設定変更等を一括で行えるようになる。
[React でAxios を使用する方法](https://www.digitalocean.com/community/tutorials/react-axios-react-ja)


```typescript:Repository.ts
import axios from "axios";
const baseDomein: string = "http://localhost:3000";
export default axios.create({
    baseURL: baseDomein,
    withCredentials: true,
});
```

使用するRepositoryをrepositoriesに格納していき、
getでrepositoryが取得できるようにしています。

```typescript:RepositoryFactory.ts
import UserRepository from "./userRepository";
import SessionRepository from "./sessionRepository";
import todoRepository from "./todoRepository";
const repositories = {
    users: UserRepository,
    session: SessionRepository,
    todo: todoRepository,
};

export const RepositoryFactory = {
    get: (name: string) => repositories[name],
};

```

次にリソースごとにRepositoryを作成し、axiosのインスタンスを返してあげるようなメソッドを作成してあげます。
新しくAPIを叩きたい場合はどんどんここに追加していくイメージです。

```typescript:todoRepository.ts
import Repository from "./Repository";
const resource: string = "/todos";
export default {
    get() {
        return Repository.get(`${resource}`);
    },
    post(payload: Object) {
        return Repository.post(`${resource}`, payload);
    },
};

```


### 実際の通信部

[axios、async/awaitを使ったHTTPリクエスト(Web APIを実行)](https://qiita.com/shisama/items/61cdcc09dc69fd8d3127)

```typescript:todoResourceへのPost

    import { RepositoryFactory } from "../../repositories/RepositoryFactory";
    const todoRepository = RepositoryFactory.get("todo");
    async function handleClick() {
        try {
            const res = await todoRepository.post({
                todo: {
                    title: todoData.title,
                    user_id: loginUserId,
                },
            });
            console.log(res);
        } catch (error) {
            console.log(err);
        }
    }

    return (
        
    <Button variant="contained" color="primary" size="large" onClick={handleClick}>
                投稿！
    </Button>
    );
```

## まとめ
コンポーネントごとにインスタンスを作成してしまいがちでしたが、デザインパターンを利用することでDRYを守ることができます。
今回のケースが全てのプロダクトに当てはまるわけではないと考えますが、API通信関係の処理に不満があった方、初学者の参考になれば幸いです。
macOS版 PowerPointで、新規プレゼンテーション作成時のデフォルトのデザインや書式を変更する方法

毎回やり方がわからなくなるので、備忘録を兼ねて記事にします。

仕様書などをPowerPointで書くことが多いのですが、何も設定していないと、新規プレゼンテーションを作成すると以下のようなそっけないデザインのものが作られます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41616/7604b1e5-e4d2-dcf6-b075-86f59af814a5.png)

しかし、

* 16:9ではなく 4:3にしたい
* 配色をオリジナルのものにしたい
* よく使うスライドマスタが最初から入っている状態にしたい
* Copyrightも最初から入れておきたい

などを実現したい方も多いと思います。

手動で行う場合は、「デザイン」メニューに並んでいるデザインの下に出てくる三角(▼)を開いて、「テーマの参照...」を使うと、過去に作ったスライドのデザインを取り込むことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41616/6ed36a5b-62a9-21e1-3940-f6ac2989fdb0.png)

しかし、この方法だと上記の要求のうち、以下の２つが達成できません。


* 16:9ではなく 4:3にしたい → テーマ適用前のまま
* Copyrightも最初から入れておきたい → テーマ適用前のまま

なので結局ブランクの .pptx ファイルをわかりやすいところに置いておいて、それをコピーして使う、ということに行きつきやすいです。

そこで、 **「macOS版 PowerPointで新規作成時に作られるプレゼンテーションのデザインや書式を好みのものに変更する」** ことで上記問題を解決します。

# 設定手順

前置きが長くなりましたが、具体的な設定手順に入ります。

## 0. 事前準備

まずは、新規作成時に適用したい状態になったスライドを作り、 `.pptx` 形式で保存しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41616/df2e890a-e648-b804-6b69-fd84e50017d5.png)

僕は 4:3が好きなのでページ設定でサイズを4:3にしています。また、いくつかよく使うレイアウトをスライドマスタにも作ってあります。フッターには Copyright表記も入れてあります。

## 1. テーマを保存

準備したPowerPointのファイルを開いた状態で、「デザイン」メニューで出てきた下三角(▼)を開いて「現在のテーマを保存...」を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41616/db7fe10e-94fd-4b39-e4f6-e002bb3454b2.png)

すると、以下のように「テーマ」というフォルダが自動で開きますので、好きな名前をつけて保存します。僕は「Default-Theme」という名前にしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41616/5489d2e1-9f2d-0cb6-9a82-de357a91a853.png)

## 2. 保存されたテーマが認識されていることを確認

ここにテーマを保存すると、先程の「デザイン」メニューの三角を開いたところに新たに「ユーザー定義」というセクションが増えているのがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41616/e14a2507-2c72-741f-85c1-b9d04834ee4f.png)

見た目ではわかりづらいのですが、マウスをホバーしてみると、自分がつけたテーマの名前(僕の場合は `Default-Theme`) が浮かび上がってくるのがわかると思います。

## 3. デフォルトテーマを自分の作ったものに変更する

その状態で右クリックをすると以下のようなメニューが出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41616/743cacae-1c81-b1ae-49fb-551e54efd7d5.png)

ここで **「既定のテーマとして設定」** を選択します。

設定は以上です。

## 4. 動作確認

早速動作確認をしてみましょう。念のため PowerPointを一度終了して、立ち上げ直します。

そして「新しいプレゼンテーション」を選んだり、「⌘-N」で新規作成すると……

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41616/63976204-75da-ebc1-ca90-3c974102fad9.png)


以下のように、好みの設定が全て適用されたプレゼンテーションが作られます!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41616/87556cde-7f5f-7fa7-4786-12ee00374417.png)


# 雑感

## Windows版とのちがい

Windows版で行う方法はググると色々出てくるのですが、Windows版と macOS版はメニュー構成が若干異なります。特にこういった設定系は結構違っていて、Windows版の情報が役に立たないことが多いです(レジストリ変更とか）。

とくに、Windows版だと **テーマの保存ではなくテンプレートの保存を行なって blank.potx というファイル名で保存する** という情報が出てきますが、macOS版ではうまくいきません。

上記の通り macOS版はテンプレートではなくテーマの方を使います。

こういった違いがありますので macOS版をいじるときはそれらの情報をすべて忘れましょう。

# デザイン？テンプレート？テーマ？

そもそも、今自分が変えようとしている設定はデザインなのでしょうか？テンプレートなのでしょうか？それともテーマなのでしょうか？

Windows版は blank.potx というテンプレートを変えるという情報があったり、一方で macOS版はテーマだったり、そもそもテーマを変えるメニューは「デザイン」だったり……。

PowerPointの中ではこれらの用語が入り混じっていて、自分が何をいじっているのかよくわからなくなります。なんとなく概念がぶれている感じがしますね。。。。
[Ruby] 正規表現を利用するメソッド2選

##はじめに
前回の続きで、正規表現です。
今回はRubyで正規表現を実現するために重要なメソッド二つ紹介したいと思います。

よろしくお願いします。


##subメソッド
subメソッドを使うと、文字列の中のある特定(指定した）部分を任意の文字列に置き換えることができます。

第一引数に置き換えられる対象（変換前）を指定し、第二引数に置き換える（変換後）文字列を指定することで任意の文字列に置き換えることが可能です。

irbを使って、例を見てみましょう。

```terminal:ターミナル
irb(main):001:0> str = "パンを食べる"
=> "パンを食べる"

irb(main):002:0> str.sub(/パン/,"ご飯")
=> "ご飯を食べる"
```

どうでしょう、イメージつかめたでしょうか。
続いて二つ目、matchです。

##matchメソッド
matchメソッドはある文字列の中から、指定した文字列が含まれているかどうかをチェックしてくれるメソッドです。

指定した文字列が含まれているなら**MatchData**という戻り値で返します。もし、指定した文字列が含まれていなかったら、nilを返します。

また、MatchDataから、マッチした文字列を取り出すには、配列から取り出すみたいに変数に[数字]を指定してあげると取り出せます。

例を見た方が早いですね。↓

```irb:ターミナル
irb(main):001:0> str = "Hello, World"
=> "Hello, World"

irb(main):002:0> md = str.match(/Hello/)
=> #<MatchData "Hello">

irb(main):003:0> md[0]
=> "Hello"
```

##最後に
今回はsubとmatchメソッドを紹介しました。
次回はさらにそれらを深めて、実践で使えるような使い方を紹介します。
②やっっとrailsサーバ動いた！！

背景
rails tutorial内で
https://railstutorial.jp/chapters/beginning?version=6.0#fig-ide_anatomy
AWS cloud9

この記事を読んで解決
tuchiya２さんの回答
https://ja.stackoverflow.com/questions/68194/rails-tutorial%E3%82%92%E3%81%97%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99-aws%E3%81%A7-blocked-host-%E3%81%A8%E3%81%84%E3%81%86%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E5%87%BA%E3%81%BE%E3%81%97%E3%81%9F

症状
①AWSメッセ"oops”②host blocked
この繰り返し
①⇨サーバが動いてなかった。toturialの文章
②budle updateされていなかった？

解決方法
budle update  →  install

本文
やっと動きますた。１８時間続けてaws5回目のenviromentで。
自走します。


学んだこと
cmand + s 上書き　※都度やること
terminal ＄が出ない時はterminalが稼働中。※よく読んで待ちましょう
詰まった時の対処方法は簡単にできそうなものから実施。　※作業コスト少ないものから試しましょう
コピペミスのままterminal実施　※ペースト後必ず確認しましょう
右手が疲れる　※左手も使いましょう
unity5.2の作法 その19 スタート画面

#概要

unity5.2の作法、調べてみた。
スタート画面を作った。

#makefile

- menu->file->new sceneする。
- menu->file->save sceneでstartとする。
- menu->gameobject->create emptyする。
- menu->assetes->creates->c# scriptでstart.csつくる。
- ダブルクリックして、コードを書く。
- ヒエラルキーのgameobjectに、コードを重ねる。
- 三角で実行。

#サンプルコード

```
using UnityEngine;
using System.Collections;

public class start : MonoBehaviour {
    void Start() {
    }
    void Update() {
    }
    private void OnGUI() {
        float CenterX = Screen.width / 2;
        float CenterY = Screen.height / 2;
        _DrawGameOpen(CenterX, CenterY);
        if (_DrawRetryButton(CenterX, CenterY))
        {
            Application.LoadLevel("game");
        }
    }
    bool _DrawRetryButton(float CenterX, float CenterY) {
        float ofsY = 40;
        float w = 64;
        float h = 64;
        Rect rect = new Rect(CenterX - w / 2, CenterY + ofsY, w, h);
        if (GUI.Button(rect, "start"))
        {
            return true;
        }
        return false;
    }
    void _DrawGameOpen(float CenterX, float CenterY) {
        GUI.skin.label.alignment = TextAnchor.MiddleCenter;
        float w = 400;
        float h = 100;
        Rect position = new Rect(CenterX - w / 2, CenterY - h / 2, w, h);
        GUI.Label(position, "TestFlappyBird");
    }
}


```


以上。
問い合わせフォームの確認画面で「戻る」ボタンをクリックして入力画面に戻ると、入力データが消えている (Firefoxのみ)

### 環境
JQuery 1.12.4
PHP 7.4
### 経緯
問い合わせフォームで入力したデータが確認画面から戻る際に、消えていることがあったので。メモです。
ボタン自体は下記のようなもので、ここでは入力画面へ戻った際のデータの保持は `history.back()` でしています。

```
# 確認画面
<?php
session_start();
以下、session処理
?>
<dl>
  <dt>氏名</dt>
  <dd><?=htmlspecialchars($post['name'])?></dd>
</dl>

<div class="btn>
  <button type="button" onclick="history.back()">入力画面へ戻るボタン</button>
</div>
```

```
# 入力画面
<?php session_start();?>
<dl>
  <dt><label for="name">氏名</label></dt>
  <dd><input id="name" type="text" name="name" required></dd>
</dl>
```
テストしたところ、Chrome、Edgeは問題なく、Firefoxの場合のみで入力画面へ戻った際に入力データが消失していました。

### 解決
下記のように、入力画面で使用していなかった不要な `session_start()` を削除後、キャッシュ削除して閲覧するとFireFoxも問題なく動作しました。

```
# 入力画面
<?php ?>
<dl>
  <dt><label for="name">氏名</label></dt>
  <dd><input id="name" type="text" name="name" required></dd>
</dl>
```
恐らくですが、ブラウザによってキャッシュを読み込む順番が違うのかと思います。
皆さんも不要なコードは削除しましよう。
Vercelへのデプロイ時にModule Not Found Error

## 問題の概要

Next.jsプロジェクトをVercelにデプロイをかけたところ、`Module Not Found Error`が発生し、ビルドに失敗した。

```
00:00:00  	Failed to compile.
00:00:00  	ModuleNotFoundError: Module not found: Error: Can't resolve 'chart.js/auto' in '/vercel/path0/node_modules/react-chartjs-2/dist'
00:00:00  	> Build error occurred
00:00:00  	Error: > Build failed because of webpack errors
00:00:00  	    at /vercel/path0/node_modules/next/dist/build/index.js:15:924
00:00:00  	    at async Span.traceAsyncFn (/vercel/path0/node_modules/next/dist/telemetry/trace/trace.js:6:584)
```

なお、エラーが発生したNext.jsプロジェクトは、[Chart.js](https://misc.0o0o.org/chartjs-doc-ja/)を使用しアプリ内でグラフ表示を行っていた。

## 解決

プロジェクト内の`package.json`を確認したところ、`chart.js`ではなく`chart`パッケージがインストールされていた。

下記コマンドで`chart.js`パッケージをインストールしたところ、エラーは解消されました。

```shell
npm uninstall chart react-chartjs-2
npm install --save chart.js react-chartjs-2
```
[UE4] Network Profilerの各種パラメータ

#概要
Network Profilerを使用してネットワークのパフォーマンスを調べる事ができます。
https://docs.unrealengine.com/4.26/ja/InteractiveExperiences/Networking/NetworkProfiler/

Network Profilerでキャプチャしたパラメータの内容は以下の通りです。

[Network Profilerの各プロパティ詳細]
詳細は**\Engine\Source\Programs\NetworkProfiler\NetworkProfiler\PartialNetworkStream.cs**を参照。

|項目|説明|
|:--|:--|
|Outgoing Bandwidth Bytes|送信帯域伝送量 (Byte) <br> 送信するパケットの総バイト数|
|Outgoing Bandwidth Bytes/s|送信帯域速度 (Byte/s) <br> 1sあたりの送信バイト数、つまり送信速度を示す<br>送信帯域量に1/フレーム時間を掛けた値|
|Outgoing Bandwidth Avg/s|平均送信帯域速度 (Byte/s)<br>30f毎の送信速度の平均値|
|Actor Count|Replicate Actor数 <br> パケット情報に含まれるReplicateが有効になっているActorの総数
|Property Bytes|Replicate Property伝送量 (Byte)|シリアライズされたプロパティの総バイト数、Replicate Actorが所有するプロパティの伝送量でもある|
|Property Bytes/s|Replicate Property送信速度 (Byte/s)<br>上記の総バイト数に、1/フレーム時間を掛けた値|
|RPC Bytes|RPC送信伝送量 (Byte)<br> 送信パケットに含まれるRPCパケットのバイト数 <br>この値が大きい場合は1pkt内のRPC送信量が多い|
|RPC Bytes/s|RPC送信速度 (Byte/s)<br>上記の総バイト数に、1/フレーム時間を掛けた値|
|Events|送信イベント<br>現在未使用|
|Actor Count/s|Replicate Actor送信速度<br>1sあたりに送信するActor数|
|Property Count|Replicate Property数<br>シリアライズされたプロパティの数、<br>Replicate Actorが所有するプロパティ伝送数でもある|
|Property Count/s|Replicate Property伝送速度 (個/s)<br>シリアライズされたプロパティの総数|
|RPC Count|RPC伝送数<br>送信パケットに含まれるRPCパケットの数|
|RPC Count/s|RPC伝送速度 (個/s)<br>送信パケットに含まれるRPCパケットの伝送速度|
|Export Bunch Count|GUID 送信数<br>Export Bounchで送信するGUIDの送信数|
|Export Bunch Count/s|GUID 送信量<br>Export Bounchで送信するGUIDの送信バイト数|
|Must Be Mapped Guid Count|マッピングされたGUID伝送数<br>現在未使用|
|Must Be Mapped Guid Bytes|マッピングされたGUID伝送量<br>現在未使用|
|Send Ack Count|Ack送信数<br>1fあたりのAck送信回数|
|Send Ack Count/s|Ack送信速度<br>1sあたりのAck送信回数|
|Content Block Header Bytes|RPC コンテンツブロックヘッダー量<br>RPCに含まれるコンテンツのヘッダー送信量|
|Content Block Footer Bytes|RPC コンテンツブロックフッター量<br>RPCに含まれるコンテンツのフッター送信量|
|Property Handle Bytes|Replicate Property Handler伝送量 (Byte)<br>Handlerの送信サイズ、Replicate Propertyと同期する傾向になる|
|Send Bunch Count|Send Bunch伝送数<br>送信パケットに含まれるSend Bunchの数量|
|Send Bunch Count/s|Send Bunch伝送速度<br>送信パケットに含まれるSend Bunchの送信速度|
|Send Bunch Bytes|Send Bunch送信量<br>送信パケットに含まれるSend Bunchの総伝送量|
|Send Bunch Bytes/s|Send Bunch送信速度<br>1sあたりのSend Bunchの伝送量|
|Send Bunch Header Bytes|Send Bunchヘッダー送信量<br>送信パケットに含まれるSend Bunchヘッダーの伝送量|
|Game Socket Send Bytes|ソケット送信量|
|Game Socket Send Bytes/s|ソケット送信速度|
|Game Socket Send Count|ソケット送信数|
|Game Socket Send Count/s|ソケット伝送速度|
|Actor Replicate Time In MS|Replicate 処理時間 (ms)<br>このActorのReplicate処理に要した時間|

#速度調整の目安
　**Outgoing Bandwidth Bytes/s**を有効にすると、そのタイミングでのパケットの送信量から送信に必要な速度が出てきます。
![2021-07-02_18h19_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/03d4b864-4eba-4120-d87e-4b4d00fe683a.png)

#占有率の高いパケット
　**Stacked bunch size**を有効にすると、そのタイミングでのパケットの送信量から送信に必要な速度が出てくるので、許容できる値を設定しておくとよいです。
![2021-07-02_18h20_28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/6a0f798a-2ca8-df06-bc2b-748b114eea54.png)

#通信速度の調整
デフォルト値が元々低いので環境に併せて調整することもできます。
・UPlayer::ConfiguredInternetSpeed (10000)
・UPlayer::ConfiguredLanSpeed (20000)
・UNetDriver::MaxClientRate (15000)
・UNetDriver::MaxInternetClientRate (10000)
WebApp開発環境(AlmaLinux) on Docker

Dockerを使ってAlmaLinuxでLAMP環境を構築する！
下記の記事を実行するにはDockerを予めインストールしておく必要があります。

---

# 構築する環境情報

| 項目 | 名称 | バージョン |
|:---:|:----:|:----:|
| OS | AlmaLinux | 8.9 |
| DB | MariaDB | 10.2.11 |
| Webサーバ | Apache | 2.4.x |
| アプリ言語 | PHP | 7.4 |

本記事で作成する環境は上記の通り。

---

# Dockerfileの内容

``` Docker:Dockerfile
# almalinuxのイメージを利用する
FROM almalinux/almalinux
LABEL maintainer=Takemi

SHELL ["/bin/bash", "-o", "pipefail", "-c"]"

# 累積アップデートの実行
RUN dnf -y upgrade

#ROOTパスワード
RUN echo "root:docker123" | chpasswd;

#takemiユーザが存在していない場合ユーザ追加する
RUN echo 'make user takemi'
RUN adduser -m takemi;echo "takemi:takemi123" | chpasswd;

#sshのインストール
RUN dnf install -y openssh-server
RUN systemctl enable sshd
#これが実行できない

#Apacheのインストール
RUN dnf install -y httpd
RUN systemctl enable httpd

#MariaDBのインストール
RUN dnf install -y mariadb-server mariadb
RUN systemctl enable mariadb

#PHP 7.4
# https://www.tsuda1.com/blog/2020/09/08/php%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/
RUN dnf -y install https://rpms.remirepo.net/enterprise/remi-release-8.rpm
RUN dnf -y module install php:remi-7.4
RUN	yum -y install php php-mbstring php-xml php-xmlrpc php-gd php-pdo php-pecl-mcrypt php-mysqlnd php-pecl-mysql

#DocumentRoot作成
RUN mkdir /var/www/webapp
RUN chown takemi /var/www/webapp
RUN chgrp takemi /var/www/webapp
RUN chmod 774 /var/www/webapp
RUN gpasswd -a apache takemi

```

上記の内容をローカルの作業フォルダにdockerfileというファイル名で保存。(※拡張子は無し)

---

# 構築の実行

下記のコマンドを実行して自動構築！

```
> docker build . -t webapp:almalinux
```

---

# イメージの実行

下記コマンドでイメージを実行!

```
> docker run --privileged -d -p 22:22 -p 80:80 -p 8080:8080 -p 443:443 --name webapp_alma webapp:almalinux /sbin/init
```

実行が成したら、Apacheの設定を行ってドキュメントルートなどの設定をお好きにどうぞ！

---

# Apacheの設定
下記コマンドでApacheの設定を編集

```
root > vi /etc/httpd/conf/httpd.conf
```

下記の設定項目を変更する

```config:httpd.conf
		DocumentRoot=/var/www/html		→	 DocumentRoot=/var/www/webapp
		<Directory “/var/www/html”>		→	<Directory “/var/www/webapp”>
		Options	Indexes FollowSymLinks		→	Options	Indexes FollowSymLinks	ExecCGI
		AllowOverride None			→	AllowOverride All
````

Apache再起動して設定を反映。
※再起動しないと設定は反映されません

```
 > systemctl restart httpd
```

ブラウザでhttp://localhostにアクセスして結果を確認！
Seleniumでデータを集めたい

## 背景
javaのSeleniumを使って競馬のデータをスクレイピングを行なっており、今は各馬の戦績を収集しています。
[収集元URL](https://db.netkeiba.com/horse/result/2016106606/)

## 現状
[URL](https://db.netkeiba.com/horse/result/2016106606/)を見てみてください。
各試合ごとのデータを取得したいです。
イメージはこんな感じ

```
String[] eachRecode1 = {"2021/06/06","3東京2","曇","11".....};
String[] eachRecode2 = {"2021/02/07","1東京4",.....};
String[] eachRecode3 = {"2021/01/10",.....};
List<String[]> recodes = new ArrayList<String[]>();
recodes.add(eachRecode1);
recodes.add(eachRecode2);
recodes.add(eachRecode3);
//本当はfor文を使ってうまくやります。
```
具体的には
`//table[@summary="カラテの競走戦績"]/tbody`にある`tr`をeachRecodeに対応させて
`td`をeachRecodesの要素として取得します。

これを行うためのプログラムの一部が下記です。

```
for(int i = 0; i < recodeListsElement.size(); i++) {
	List<WebElement> we = dri.findElements(By.xpath("//table[@summary=\""+hoseName+"の競走戦績\"]/tbody/tr["+i+"]"));
	for(WebElement e: we) {
		System.out.println(e.getText());
		recode[i] = e.getText();
	}
	System.out.println("***********************:");
	recodeList.add(recode);
}
```

## 問題点
上記のプログラムを実行すると下記のように表示されます。
自分は`td`の要素が`System.out.println(e.getText());`で表示されると思って記述しました。
ですが、どう工夫してもできません。

```
***********************:
2021/06/06 3東京2 曇 11 安田記念(G1)
14 3 4 77.5 10 13 菅原明良 58 芝1600 良
**
1:33.0 1.3
**
12-12 34.9-33.9 34.1 526(-4)
ダノンキングリー  
***********************:
2021/02/07 1東京4 晴 11 東京新聞杯(G3)
16 5 10 11.6 5 1 菅原明良 56 芝1600 良
**
1:32.4 0.0
**
5-4 34.9-34.3 34.0 530(+2)
  (カテドラル) 3,957.4
***********************:
```
理想系↓

```
2021/06/06
***********************:
3東京2
***********************:
.
.
.
```

## 取り組み
Xpathの指定に問題があるのかと思い調べました。`following-sibling::td[1]`などを使い色々工夫ひてみたのですがうまくできません。
【Laravel】マイグレーションで既存のカラムをnullableに変更する

Migrationファイルを用いて、既存のテーブルのカラムにnullable属性を付与する方法を整理してメモ。

## 状況
- 既存の申し込みフォームにおいて、必須項目だったものが任意入力項目になった。
- DB(今回はMySQLを使用)のカラムはnullを許可しない設定になっていたため、このままではエラーになる。
- そのため、当該カラムをMigrationを用いてnullableに変更したい。

## まずは下準備

動作要件として、Laravel公式より..

https://readouble.com/laravel/6.x/ja/migrations.html


>カラムを変更する前に、composer.jsonファイルでdoctrine/dbalを確実に追加してください。Doctrine DBALライブラリーは現在のカラムの状態を決め、必要な調整を行うSQLクエリを生成するために、使用しています。

ということで、`doctrine/dbal`ライブラリーを導入しておきます。
(すでに導入してあればcomposer.lockなどを確認しておけばOK)

```
$ composer require doctrine/dbal
```

## Migrationファイルの作成
ではさっそくMigrationファイルを作成していきます。
今回の例では`customers`というテーブルの`company_name`カラムをnullableに変更していきます。

```
$ php artisan make:migration change_company_name_to_nullable --table=customers
```
こんな感じで作成。(名前はもうちょっと良い感じにできるかもですが)

### upメソッドの記述
マイグレーションファイルを作成したら、まずは`up()`メソッドにスキーマを記述していきます。

```xxx_change_company_name_to_nullable.php
public function up()
{
    Schema::table('customers', function (Blueprint $table) {
        $table->string('company_name')->nullable(true)->change();
    });
}
```
こんな感じで記述します。
まず、`string('カラム名')`の部分は既存のカラム名とデータ型に合わせます。
そして`nullable()`で引数にtrueを指定し、`change()`とすると既存のカラムを変更できます。
(この引数のtrueは省略できるかもしれないけど明示的に`true`と指定すると分かりやすいと思います)

### downメソッドの記述
次に、rollbackで必要なdownメソッドも記述していきます。

```xxx_change_company_name_to_nullable.php
public function down()
{
    Schema::table('customers', function (Blueprint $table) {
        $table->string('company_name')->nullable(false)->change();
    });
}
```
内容はupメソッドとほとんど同じですが、こちらはnullable()の引数は`false`とします。
(引数を省略するとrollback実行してもnullableになったまま戻らないので留意)

## Migrate実行
あとは説明不要で、普通に

```
$ php artisan migrate
```
を実行すればOKです。
これでクライアントツールやターミナルで、指定のカラムが`nullable`になっていることが確認できると思います。
<br>
以上、最後までお読みいただきありがとうございました〜。
nodebrewを消してanyenvとnodenvを入れる。

###概要
nodebrewだとローカルリポジトリー単位で使うバージョンを指定できないので
それが出来るnodenvが良いんじゃないか思い立ったが吉日
もしかしたら今のnodebrewでも自動切り替え出来るかもしれないけど
そもそもpyenvはanyenvで管理してたのでいい機会だった。

自動切り替え云々の話は以下を参照
https://qiita.com/tonkotsuboy_com/items/5322d226b6783d25b5df

###nodebrew滅殺
消す手順

```
rm -rf /Users/myName/.nodebrew
```
こんな物理的に消して大丈夫なのかと不安になったけどこれ以外で調べた方法でうまく行かなかった。。。
ついでにパスも消しときましょう。

zshrcとかbashrcとかあたりに以下の文章があると思うので消します。
nodebrewっぽいやつは消します。

```shell
export PATH=/Users/myName/.nodebrew/current/bin:$PATH
```

nodeが完全に消えたと思ったら残ってた。
brew経由で入れてる人は

``` bash
$brew uninstall node
```
で消しておこう。
僕は上記のコマンドを実行しようとした際にtwilioって物が邪魔してたのでignoreして無理やり消しました。

###wellcome anyenv

```
brew install anyenv
$echo 'eval "$(anyenv init -)"' >> ~/.zshrc
```



###wellCome nodenv

```
$anyenv install nodenv
$exec $SHELL -l
```

完了！！！
STM32F767と秋月シリアル7セグで3分タイマー GPIO


x Mbedでのボード設定は、NUCLEO-F767ZI
x 赤色７セグメントＬＥＤシリアルドライバモジュール　完成品
x OSL10564-74HC595-R M-12642

説明
文字を文字パターンに変換する
64は、@の開始位置です。
7セグメントの文字パターンに変換
変換範囲は、32文字で5ビット分




```c++


#include <Arduino.h>

//*          *****  *****  
//*         *       *    * 
//*         ******  *    *
//*         *       *    *
//*         *       *    *
//********   *****  *****

#define DW   digitalWrite

//031
// //#define swdclk   PA14 // 8pin
// //#define swdio    PA13 // 7pin
// #define swdclk   PA12 // 6pin
// #define swdio    PA11 // 5pin
// //#define t_led1   PA12 // 6pin
// //#define t_led2   PA11 // 5pin
// #define en       PA0  // 4pin
// #define in7      PB7  // 1pin

//767
#define swdclk   13 // 
#define swdio    11 // 
#define en       10 // 
#define in7      A0 // 


char seg[32] = {
   0x00 , //0 @ -> ' '
   0x77 , //1 A  o
   0x7c , //2 B     　combined use "6"
   0x39 , //3 C
   0x5e , //4 D
   0x79 , //5 E  o
   0x71 , //6 F
   0x3d , //7 G

   0x76 , //8 H  o
   0x06 , //9 I    　combined use "1"
   0x1e , //10 J
   0x75 , //11 K 
   0x38 , //12 L  o
   0x15 , //13 M
   0x37 , //14 N  o
   0x3f , //15 O  o　combined use "0"

   0x73  , //16 P
   0x67  , //17 Q　combined use "9"
   0x50  , //18 R
   0x6d  , //19 S　combined use "5"
   0x78  , //20 T
   0x3e  , //21 U
   0x1c  , //22 V
   0x2a  , //23 W  o
   0x64  , //24 X

   0x6e  , //25 Y
   0x5b  , //26 Z　combined use "2"
   0x4f  , //27 [  --> "3"
   0x66  , //28 \  --> "4"
   0x27  , //29 ]  --> "7"
   0x7f  , //26 ^  --> "8"
   0x08    //31 _
};

//             12345678   12345678   12345678   12345678
char b8[8] = {0b10000000,0b01000000,0b00100000,0b00010000,
              0b00001000,0b00000100,0b00000010,0b00000001 };

void seg1(char v)
{
    v=seg[v-64];
    for(int jj=0;jj<8;jj++){
        if( (v & b8[jj]) == 0 ){
                DW(swdio,0); //ビットが0
        } else {
                DW(swdio,1); //ビットが1
        }//endif
        DW(swdclk,1);
        DW(swdclk,0);
    }//for
    DW(en,1);
    DW(en,0);
}//seg1

//初期化
void setup() {

    delay(3000); //not Delete

    //7セグの初期化
    pinMode(swdclk,OUTPUT);
    pinMode(swdio,OUTPUT);
    pinMode(en,OUTPUT);
    pinMode(in7,INPUT_PULLUP);
    DW(en,0);
    DW(swdclk,0);
    
}//setup

int ii; //ループカウンター
//ループ
void loop() {

  seg1('O');

  for(ii = 0;ii < 60;ii++){
    delay(1000);
  }

  seg1('I');

  for(ii = 0;ii < 60;ii++){
    delay(1000);
  }

  seg1('Z');

  for(ii = 0;ii < 60;ii++){
    delay(1000);
  }

  seg1('[');

  while(1){} //無限ループ
}//loop




```

![h_con28.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/e6089c10-4b3b-3f6c-0863-41bada405eb0.jpeg)
GitLab13 => 14アップデート（docker-compose）

今回は13.0.0から14.0.1へのアップデートを行った際の備忘録を残しておきます

なお、最新のバージョンについてはDockerHubを確認してください
[gitlab/gitlab-ce](https://hub.docker.com/r/gitlab/gitlab-ce/tags?page=1&ordering=last_updated)
[gitlab/gitlab-runner](https://hub.docker.com/r/gitlab/gitlab-runner/tags?page=1&ordering=last_updated)


※アップデート実行前には必ずバックアップを取りましょう


追記)12 => 13へのバージョンアップは以前書いた記事を参照ください

https://qiita.com/teracy55/items/c2749dace4c794930397


# とりあえずdockerイメージのバージョンを14にしてコンテナを作り直してみる

```docker-compose.yml
version: '2'
services:
  gitlab:
    image: 'gitlab/gitlab-ce:14.0.1-ce.0'
    ・・・
  gitlab-runner:
    image: gitlab/gitlab-runner:v14.0.1

```

これで`docker-compose down`してv13のコンテナを削除した後、`docker-compose up`してみましたが、gitlabコンテナが異常終了してしまい、ダメでした。。。
ログを見ると以下のようなメッセージがありました。

```
 It seems you are upgrading from major version 13 to major version 14.
 It is required to upgrade to the latest 13.12.x version first before proceeding.
```


# いったん13.12.0にアップデート

gitlabおよびgitlab-runnerコンテナを13.12.0にアップデートします

```docker-compose.yml
version: '2'
services:
  gitlab:
    image: 'gitlab/gitlab-ce:13.12.0-ce.0'
    ・・・
  gitlab-runner:
    image: gitlab/gitlab-runner:v13.12.0

```

`docker-compose up`するだけで無事にアップデートできました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/a99ac193-5a0b-effc-e1d9-f884542d0174.png)


確認出来たら`docker-compose down`でコンテナを削除します

# 14へアップデート

冒頭で記載した内容にdocker-compose.ymlを更新して、`docker-compose up`します

### またエラーが。。。

またGitlabコンテナが異常終了してしまいました。
ログを見ると以下のようなメッセージが出ていました。

```
 Removals:
* unicorn['worker_processes'] has been deprecated since 13.10 and was removed in 14.0. Starting with GitLab 14.0, Unicorn is no longer supported and users must switch to Puma, following https://docs.gitlab.com/ee/administration/operations/puma.html.
```

GitLab14からはunicornからPumaに切り替わったのでunicornのパラメータを消せという内容みたいです。

docker-compose.ymlのenvironmentで指定していたのですが、Pumaの場合`puma['worker_processes']`と指定すれば良いそうなので、修正して再度`docker-compose up`してみます
参考：https://docs.gitlab.com/ee/administration/operations/puma.html

unicorn関連の設定はすべて置き換える必要があります。
※docker-compose.ymlで指定してない場合はgitlab.rbを編集してください



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/34b8f0a8-5078-bbe2-1246-0e4d850ed59d.png)


無事立ち上がりました！！！
コミット履歴をまとめたくてハマった時の備忘録

今までgitはGUIツールに頼ってコマンドラインでの操作はサボっており、

大きめのプロジェクトに入り、

コミット履歴多くなってるからまとめてくれる？と言われ、

GUIツールでまとめようとしたら上手くいかず(自分の操作が悪いかもですが)

コマンドラインでやってみたものの全然上手くいかず、

ハマり倒すことになったのでまとめておきます。


# Commit履歴をまとめる

- 直近のコミットに更新したコミットをまとめる

```
git commit --amend
```

- amendしたコミットをリモートにpushする

```
git push --force-with-lease
```

※amendしたコミットはforce pushなりなんなりしないとアップすることができない。

しかし調べてみると**force pushは悪**とのことだったので、

ローカルが最新かどうかを判定して最新でなければ失敗する

**git push --force-with-lease**

こちらを使おうねということみたいです。

git push --force-with-leaseに関しては[こちらの記事](https://qiita.com/wMETAw/items/5f47dcc7cf57af8e449f)を参考にさせて頂きました。

# リモートに複数commitしてしまっていた場合

```
git rebase -i HEAD~
// ~の後にまとめたい数値を入れる
// 例:二件まとめたい場合はgit rebase -i HEAD~2
```
こちらの方法でsquashしてまとめる。

[こちらの記事](https://qiita.com/takke/items/3400b55becfd72769214)を参考にさせて頂きましたので、

詳しい方法に関してはこちら参考にしてみてください。

ただgit push -fより

git push --force-with-leaseでpushする方が良さそうです。
Python 仮想環境 手順

## 作成
フォルダ階層

```
projectdir
   ├── venv
   │     └── venvの諸々のファイル
   ├── main.py
   └── requirements.txt
```

作成からアクティベートまで

```:たーみなる
$ mkdir projectdir
$ cd projectdir
$ python3 -m venv venv
$ source venv/bin/activate 
```



## requirements.txt
ここに書かれているのを元にpip installしてくれる凄いやつ
名前はなんでもいいらしいけど

- 元の環境でいろいろ入れている人は**pip freeze**コマンド打って出てきたやつから入れたいの選んでをコピペでOK
- 元の環境と全て同じにしたいのであれば**pip freeze > requirements.txt**でOK

```:たーみなる
$ pip freeze
or 
$ pip freeze > requirements.txt
```


例

```:requirements.txt
Flask==1.1.2
pandas==1.2.4
```

書けたらインストールしてpip freezeで確認

```:たーみなる
$ pip install -r requirements.txt

$ pip freeze
```
django-webpack-loader + vue-cli での最小限の設定

# はじめに
[django-webpack-loader](https://github.com/django-webpack/django-webpack-loader) + [vue-cli](https://cli.vuejs.org/) の構成で、起動から Heroku での公開までを試した際の備忘録です。

`django-webpack-loader` の django 側の設定は基本的には [README.md#configuration](https://github.com/django-webpack/django-webpack-loader#configuration) に書いてある通りなんですが、webpack 側は `webpack.config.js` での設定しかありません。

この記事では `vue-cli` で動作させるために `vue.config.js` の設定を紹介します。

#### バージョン
```sh:terminal
$ python --version
Python 3.7.11
$ vue --version
@vue/cli 4.5.13
```

```toml:pyproject.toml
Django = "^3.2.4"
django-webpack-loader = "^1.1.0"
```

```json:package.json
"vue": "^3.0.0"
"webpack-bundle-tracker": "^1.1.0"
```

# 最小限の設定
```js:vue.config.js
var BundleTracker = require('webpack-bundle-tracker');

module.exports = {
  publicPath: process.env.NODE_ENV === 'production'
            ? '/static/dist/'
            : 'http://localhost:8080/',
  outputDir: 'static/dist',
  configureWebpack: {
    plugins: [
      new BundleTracker({filename: './webpack-stats.json'}),
    ],
  },
  css: {
    sourceMap: true,
  },
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
}

```

# 項目別の説明
## publicPath
```js
publicPath: process.env.NODE_ENV === 'production' 
          ? '/static/dist/'
          : 'http://localhost:8080/'
```
本番以外は `http://localhost:8080/` になります。
`localhost:8080` は devServer のデフォルトです。

##### なぜ '/' じゃダメなのか
`publicPath` で HOST:PORT を省略すると、django の静的ファイルへの URL が 以下のようになります。
`http://localhost:8000/<file>`
`localhost:8000` は runserver のデフォルトです。

つまり django 側からファイルを探そうとします。
開発中は `build` で静的ファイルを生成する訳ではないので、 vue の devServer にファイルを取りにいく必要があります。そのため設定値は `http://localhost:8080/` となります。

## outputDir
```js
outputDir: 'static/dist'
```

django 側で `settings.STATICFILES_DIRS` に指定したディレクトリ下の値にします。

今回は `settings.STATICFILES_DIRS=['static']` を指定しておいたので、
`yarn build` では `static/` 下に `dist` として出力されるようにしました。

## configureWebpack
```js
configureWebpack: {
    plugins: [
      new BundleTracker({filename: './webpack-stats.json'}),
    ],
  }
```
`django-webpack-loader` は `webpack-bundle-tracker` と一緒に使うことになります。
ここはその設定です。

django 側の `settings.WEBPACK_LOADER["default"]["STATS_FILE"]` で参照するファイルをどこに出力するかを指定します。

## css.sourceMap
```js
css: {
  sourceMap: true,
}
```
`django-webpack-loader` が `filename.css.map` を探そうとするのですが、`vue-cli` ではデフォルトが無効になっているので、そのままだとエラーになってしまいます。

## devServer.headers
```js
devServer: {
  headers: {
    'Access-Control-Allow-Origin': '*',
  },
}
```
ホットリロードを有効にするために必要です。
vue 側のソースコードに変更があった場合 `localhost:8000(django)` から `localhost:8080(vue)` の `hot-update.json` にアクセスしようとするのですが、その際に CORS にひっかかります。それを回避するために devServer では `'Access-Control-Allow-Origin': '*'` を指定しています。

# さいごに
今回の試したソースコードを載せておきます。
あくまで `django-webpack-loader + vue-cli` のお試しなので、django/vue のプロジェクトは生成しただけになってます。

Github
[https://github.com/tsukachu/django_vue](https://github.com/tsukachu/django_vue)
EC2環境内でWebpackerが動作しない際の対応の記録[Rails][Unicorn]

RailsアプリのEC2の本番環境において、Webpackerを動作させる際に出会った、エラー対応を記します。
Rack専用Webサーバーとして、Unicornを採用しています。

## 参考

https://morizyun.github.io/ruby/rails-troubleshoot-no-route-match-assets.html

https://qiita.com/328/items/775ef8e47fc9ec9274e3

## 結論

### エラー内容

```ruby
アプリ名/log/production.log
[56c395e9-87c3-4c60-b32d-6e407387d208] ActionController::RoutingError (No route matches [GET] "/packs/js/application-7b3203a2b398f48e7cc4.js"):
[56c395e9-87c3-4c60-b32d-6e407387d208
```

### 解決に至ったコード

```ruby
:アプリ名/config/environments/production.rb
config.public_file_server.enabled = true
```

## 解決方法

解決方法は以下の流れになりました。

1. 開発環境では正常に動作していることを確認
2. .node_modlueを削除（別にしなくてもいいかも
3. yarn（2をやった場合
4. rails webpacker:compile RAILS_ENV=production（やっていなかったら
5. ログを確認
6. 対応

上記の5・6の流れに関しましてご説明させて頂きます。
自分の場合、同じくUnicornを用いた開発環境において、動作しないことを確認致しましたので、環境依存によることが原因であることが分かりました。
その後、webpackerを再起動させるために、2 ~4の作業を行いました。この部分は恐らく必要なかったかもしれません。

### 5. ログを確認

Unicornのログを確認します。私の場合は以下のデイレクトリで確認できます。

```ruby
アプリ名/log/production.log
[56c395e9-87c3-4c60-b32d-6e407387d208] ActionController::RoutingError (No route matches [GET] "/packs/js/application-7b3203a2b398f48e7cc4.js"):
[56c395e9-87c3-4c60-b32d-6e407387d208
```

もしこのエラーと同様なエラーが表示される場合には、この後の対応策が活用できるかもしれません。

### 6. 対応

冒頭に記載しましたが、以下のコードをRailsの設定ファイルに記載致しました。

```ruby
:アプリ名/config/environments/production.rb
config.public_file_server.enabled = true
```

これで動作を確認することが出来ました。

## まとめ

今回得た学びは以下の通りです。

1. まずはログをちゃんと確認すること。
2. 開発環境で動作した場合は、環境依存を疑うこと。

以上です。直接的なエラーの原因などを記載せず申し訳ございませんが、解決にお力になれれば幸いです。
Groovy でドットを区切り文字として使用して文字列を分割する

久々の投稿。
ぐぐってもいまいちヒットせず、Groovyでドットを区切り文字として使用して文字列を分割する方法がわからず、ちょっとハマったので覚書を残しておく。

こんな感じで記述してみたら・・・

```Groovy: 
def str = "str.split"
def dst = str.split(".")
println("dst[1] = "+dst[1]
```

失敗

```
Caught: java.lang.ArrayIndexOutOfBoundsException: 1
```

で、このように書いた。

```Groovy: 
def str = "str.split"
def dst = str.split("\\.")
println("dst[1] = "+dst[1]
```

実行結果

```
dst[1] = split
```

区切り文字は　\\\\. って書かないとダメなのね・・・