OmniAICreator/Qiita-1.07M huggingface dataset:
form_withでのmodelとurlの指定の違いは？

# はじめに
form_withを使用中に気になったので調べてまとめてみました。

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [urlの指定](#Chapter1)
1. [modelの指定](#Chapter2)
1. [modelとurlの指定の違い](#Chapter3)
1. [まとめ](#Chapter4)
1. [参考](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# urlの指定
**urlの書き方**
```form_with url: url_path``` 

例)
```<%= f.text_field :emai%>
<%= f.submit %> ```
urlでは指定したurlに対してPOSTメソッドを行う。

**:scope**
```scope```指定すると**「指定すると現在のURLに対応したメソッドにフォームを送信」**してくれる
つまり、loinフォームを作成していて```sessionController```を使っている場合は```sessionController```のnewメソッドに送信してくれることになる

**ストロングパラメーターの設定**
```params.permit(:email)```
urlの場合は構造階層を意識することなくストロングパラメーターを設定できる。
<a id="#Chapter2"></a>
# modeleの指定
**modelの書き方**
```form_with model: @model```

**新しく作られたオブジェクトの場合**
例）　```user = User.new```

**controller間の処理の流れ**
new => create
この場合は渡されたオブジェクトの値が空の場合Rallsが自動でcreateメソッドを呼び出してくれる。

**ストロングパラメーターの値指定**
urlを指定して値を渡した場合は直接値を指定しできたが
moelの場合は構造階層になるので指定方法が変わる
「Userモデルのemailを指定する」といった形に切り替える
```params.requitre(:user).permit(:email)```　となり、params```[:user][:email]```という構造階層での指定が必要になる。

<a id="#Chapter3"></a>
# modelとurlの指定の違い
- modelは中身が入っていると自動でeditメソッドを呼び出す
- ストロングパラメーターの指定方法が違う


<a id="#Chapter4"></a>
# まとめ
**個人的両方の使いどころ**

- ログインフォームはurl指定

- 登録フォームはmodel指定


 
<a id="#reference"></a>
# 参考
- [【Rails】form_with/form_forについて【入門】](https://qiita.com/snskOgata/items/44d32a06045e6a52d11c)
Your requirements could not be resolved to an installable set of packages.のエラーの対処について

laravelプロジェクトを作成した際に以下のエラーが出ました。
![c64ddb832c27395d5151d77310239b56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656039/59fc53ea-fd29-267c-a289-4c59375295bf.png)
翻訳

お客様のご要望を、インストール可能なパッケージのセットに解決できませんでした。

  問題1
    - laravel/framework[v5.5.0, ..., v5.5.50] require ext-mbstring * -> あなたのシステムにはありません。PHPのmbstring拡張をインストールするか、有効にする。
    - Root composer.json requires laravel/framework 5.5.* -> laravel/framework[v5.5.0, ..., v5.5.50]で満たすことができます。

拡張機能を有効にするには、.iniファイルで拡張機能が有効になっていることを確認します。

ファイルやホルダは作成されましたがターミナルでサーバーを立ち上げようとしてもエラーが出てしまいました。
一度作成したファイルを削除し、もう一度下記の方法でインストールしなおしました。

末尾に--ignore-platform-reqsを追加して再度laravel プロジェクトを作成
phpバージョンのチェックを一時的に回避するオプションとのこと。

エラーがなくなり、サーバーが立ち上がりました。
ECS＋FargateのAutoScaling設定をTerraformで定義する(スケジュール編)

# はじめに
ECS＋Fargate の AutoScaling は便利で、徐々にアクセス量が増えていくようなケースには対応できるものの、一気にトラフィックが3倍になるようなバーストケースは、仮に予見されるものであってもCPUリソースやアクセス量を監視しているだけでは対応しきれない。
そういったケースでは、予めスケジュールを組んでタスク量を調節しておくことで対応をしよう。
※予見できないバーストトラフィックはさすがに無理なので、そこはもうある程度余裕をもってリソースを用意しておくしかないだろう。

本記事では、ベースに[前回の記事](ECS＋FargateのAutoScaling設定をTerraformで定義する)の予備知識があることを前提とする。ECS＋Fargate や AutoScaling に関する基本的な設定は改めて説明はしないので悪しからず。
また、[クラスメソッド先生の記事](https://dev.classmethod.jp/articles/ecs-scheduled-autoscaling/)も参考に。

なお、EC2のスケジュールベースの AutoScaling はマネージメントコンソールで確認できるが、ECS＋Fargateの場合はどこを見ても確認できない。謎だが、ちゃんと動作はするので気にしないことにした。

# スケジュールベースの AutoScaling の Terraform での設定方法
Terraform では [```appautoscaling_scheduled_action```](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_scheduled_action) のリソースを使う。

対して難しいことはない。上記の例のように、時間帯でトラフィックが予期できる場合は、以下のように2つのスケジュールを組むことでリソース量をコントロール可能になる。

```HCL
resource "aws_appautoscaling_scheduled_action" "ecsfargate_peak" {
  name               = "ecsfargate_peak"
  service_namespace  = aws_appautoscaling_target.ecsfargate.service_namespace
  resource_id        = aws_appautoscaling_target.ecsfargate.resource_id
  scalable_dimension = aws_appautoscaling_target.ecsfargate.scalable_dimension
  schedule           = "cron(15 * * * ? *)"

  scalable_target_action {
    min_capacity = 20
    max_capacity = 40
  }
}

resource "aws_appautoscaling_scheduled_action" "ecsfargate_normal" {
  name               = "ecsfargate_normal"
  service_namespace  = aws_appautoscaling_target.ecsfargate.service_namespace
  resource_id        = aws_appautoscaling_target.ecsfargate.resource_id
  scalable_dimension = aws_appautoscaling_target.ecsfargate.scalable_dimension
  schedule           = "cron(20 * * * ? *)"

  scalable_target_action {
    min_capacity = 10
    max_capacity = 20
  }
}
```

```schedule``` のプロパティは、[ユーザーガイド](https://docs.aws.amazon.com/ja_jp/autoscaling/application/userguide/examples-scheduled-actions.html)に設定例が書かれている。```at``` で日時指定、```rate``` で間隔で定期的に動作させることができ、```cron``` で毎時何分に起動や、毎日何時何分に起動といったことができる。```cron``` は [CloudWatch
 Event の記載方法](https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html#CronExpressions)に従う。

上記の例では、毎時15分にピークトラフィックに備えてスケールアウトさせ、毎時20分に収まるのでスケールインする。当然ながらこれは例であって、ECS＋Fargate は課金単位が1時間なので、こういった設定をする意味はない。

# 実際に動作させる
上記の Terraform を apply した後の動作がこちら。

![キャプチャ1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/bf4ad905-a2e7-bcf2-c927-6307a5a98122.png)

多少のタイムラグはあるものの、16:16 に必要なタスク数が上がってタスク実行され、16:21 には下がって drain されている。
ECSのサービスのログでも、以下のように出力されていて、時間通りにスケジュールでタスク数の最大と最少が変更されていることが分かる。

![キャプチャ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/49325ec9-5d13-17e0-9e73-f7ed7d513076.png)

今回はCPU使用率によるスケールインのポリシーも設定しているため、スケジュールで MAX:4/MIN:2 になった後に、CPU使用率が低いためにタスク数が2まで推移する、といった動作だ。

これで、CPU使用率やトラフィック量だけでなく、時間でより細かくタスク数をコントロールできるようになった！
TypeScriptの基本の型６つをまとめてみました。

最近は慣れるためにもアプリを作る際に必ずTypeScript導入するようにしています。
しかし、導入してみたもののany型を多用してしまい、TypeScriptの恩恵を享受できていないです。
そこで思考整理のためにTypeScriptについてまとめてみようと思います。

今回はTypeScriptとは何かについてと基本的な型（６つ）をまとめてみました。
（Enumsを入れるか悩みましたがUnion Typesで代用できるのかなと思い割愛しました。）

#そもそもTypeScriptとは？

Microsoft社が開発した「型のあるJavaScript(JavaScriptの上位互換)」です。
そして、TypeScriptのコードをJavaScriptへコンパイルするコンパイラーでもあります。

この二つの言語にどのような違いがあるのか。それはJavaScriptが動的型付け言語であるのに対してTypeScriptは静的型付け言語という違いがあります。

- 動的型付け言語<br />
実行されるタイミングで自動的に型が設定される。
- 静的型付け言語<br />
開発時に予め型を定義できる。

では、TypeScriptを導入するメリットは何か？
私が感じたメリットは、開発時に型違いが起きるとエラーが出るので、圧倒的にバグを減らす事ができる事だと思います。
バグを減らせるということは、安全なアプリを開発できることに繋がるので、とても大切だと思います。

基本的な型を以下の６つについてまとめてみました。
1.number
2.string
3.boolean
4.object
5.Array
6.Tuple

##1.number
* 例）１、２,１００、２００...etc 
* 対象）整数や浮動小数を含む全ての数値

<br/>**実例**


```
const a:number = 1;

const b:number = "hoge";
//エラー　Type 'string' is not assignable to type 'number'
```
numberで型付けしている値に対して数値以外の値を入れるとエラーになります。


##2.string
* 例）”hoge”, "Japan","water"...etc
* 対象）全ての文字列

<br/>**実例**

```
const c:string = "hoge";

const d:string = 4;
//エラー　Type 'number' is not assignable to type 'string'
```

stringで型付けしている値に対して文字列以外の値を入れるとエラーになります。


##3.boolean
* 例）true,false
* 対象）trueまたはfalse

<br/>**実例**

```
const e:boolean = true;

const f:boolean = 4;
//エラー　Type 'number' is not assignable to type 'boolean'
const g:boolean = "hoge";
//エラー　Type 'string' is not assignable to type 'boolean'

```

booleanで型付けしている値に対してtrue,false以外の値を入れるとエラーになります。

##4.object
* 例） {country: "Japan"}, {hobby: "music"} ...etc
* 対象）JavaScriptの全てのobject

<br/>**実例**

```
const h: { country: string; isSingle: boolean; age: number } = {
  country: "Japan",
  isSingle: true,
  age: 20
};

```
分かりにくいかもしれませんがhの後に続いている部分がobjectの型定義になります。
対象の値に対して、{}をつけてkeyとtypeを記述します。

また以下のようにも記述できますが、上の例に比べて抽象度が高く、TypeScriptを使用している意味がありません。
また、以下のような書き方だとTypescriptが中身がわからずにエラーを出すこともあります。

```
const h: object = {
  country: "Japan",
  isSingle: true,
  age: 20
};

//もしくは

const i:{} = {
  country: "Japan",
  isSingle: true,
  age: 20
};

```

##５.Array
* 例） [1,2,3 ] ...etc
* 対象）JavaScriptの全てのArray

<br/>**実例**

```
const j: number[] = [1, 2, 3];

//もしくは下記のようにジェネリクスでも書けます。

const k: Array<number> = [1, 2, 3];

```

##6.Tuple
* 例） [1,2] ...etc
* 対象）長さ固定の配列

```
let l: [string, number] = ['hoge', 1];

l[0] = 2;
//Type 'number' is not assignable to type 'string'
l = ["hoge", 1, 2]
//Type '[string, number, number]' is not assignable to type '[string, number]'.
  Source has 3 element(s) but target allows only 2.
```

Tuple型はこの例だと二つの要素があり、なおかつstringとnumber型の配列だと判断します。
また、配列内の順番もstring→numberと型付けしています。

つまりはTupleはそれぞれの位置の要素を明示的にすることができます。

##最後に
typescriptはまだまだ色々な型や決まり事があります。
今回は本当に基礎の基礎の型を纏めてみました。今後もtypescriptについてはアウトプットしていきたいです。

色々なサイトを参考にしましたが、私が一番分かりやすかったのは下記のUdemy講座です。
https://www.udemy.com/course/understanding-typescript-jp/

他参考サイト
https://qiita.com/EBIHARA_kenji/items/4de2a1ee6e2a541246f6
自然言語処理（NLP）。多義語の翻訳を試してみた。

# 自然言語処理（NLP）。多義語の翻訳を試してみた

Google翻訳と、DeepLを試してみた。
英語の多義語　⇒　日本語
日本語の多義語（ひらがな）　⇒　英語
を試した。

後者は、ちょっと、反則かもしれません。

# 結果(2021/04/26)

| |文章 |結果|
|:--|:--|:--:|
|翻訳元|You are free to make this book free.||
|Google翻訳|この本は自由に無料で作成できます。|△|
|DeepL|この本を無料にするのは自由です。|〇|
|翻訳元|This is a story about a house of one story.||
|Google翻訳|これは一階建ての家の話です。|〇|
|DeepL|これは、1階建ての家の話です。|〇|
|翻訳元|私は、安全のため、真ん中は少し崩れかけているはしのはしを歩きました。||
|Google翻訳|For safety, I walked on a chopstick that was a little crumbled in the middle.|×|
|DeepL|I walked along the edge of the ladder, which was a little crumbling in the middle, for safety.|×（〇）※1|
|翻訳元|くもをつかまえて、青空にひとつだけ見える大きなくもに向かって、おもいっきり、投げました。||
|Google翻訳|I caught the spider and threw it all the way at the big spider that I could see in the blue sky.|×|
|DeepL|I grabbed a spider and threw it as hard as I could at the big spider, the only one visible in the blue sky.|×|
※なぜ、突然、橋でなく、梯子（はしご）のladderが出るのでしょうか？？
⇒<font color="orange">**ひらがなの多義語は、全く、ダメですね。。。簡単な漢字は、漢字必須かも。。。**</font>


# 結果２(2021/04/29)

| |文章 |結果|
|:--|:--|:--:|
|翻訳元|The person who cleared the steep bank for weeding was a young employee of the bank where my company has an account.||
|Google翻訳|急勾配の銀行を除草のために片付けたのは、私の会社が口座を持っている銀行の若い従業員でした。|×|
|DeepL|草取りのために険しい銀行をクリアしたのは、私の会社が口座を持っている銀行の若い社員だった。|×|
|翻訳元|私の体調は年々悪くなり、最近は特に首に強い痛みがある。そのため、仕事の効率が悪く、今年、会社を首になった。||
|Google翻訳|My physical condition is getting worse year by year, and recently I have a strong pain in my neck. As a result, my work was inefficient and I was fired from the company this year.|〇|
|DeepL|My health condition has been getting worse every year, and lately I have been experiencing a lot of pain, especially in my neck. Because of this, I am not able to work efficiently, and this year I was fired from my job.|〇|




# まとめ
特にありません。
もう少し文章的なもので試したかったが、翻訳元の文章の作成が、うまくいきませでした。
また、bankとか、、、有名どころでも試したいとは思います（↑一応、bankは、やってみました。NGでした。)。
日本語のひらがなは、少し、がっくりきました。
Pythonプロジェクトの開発環境の統一

# 概要
Pythonプロジェクトを開発する際、スタイルを揃えたい。特に複数人で開発するときにそれぞれ違う書き方をされると開発がしにくい。
そこでプロジェクトでフォーマッタなどを導入して、VSCodeでオートフォーマットしてもらう。

まだまだ発展途上なのでもっと良くしていきたい。

# プロジェクトの設定
poetryを使う想定。

開発環境にライブラリをインストール

```sh
poetry init
poetry add black flake8 mypy --dev
```

各種ファイルに設定を記述。
現状は一行の最大長を99文字で揃える設定のみ書いている。

pyproject.toml

```toml
...

[tool.black]
line-length = 99
```

.flake8

```
[flake8]
max-line-length = 99
```

# VSCodeの設定

Settingsメニューは `cmd`+`,` で開ける

### flake8 Linting
- Settingsで`python.linting.flake8`を検索
- `Whether to lint Python files using flake8`にチェックを入れる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193600/00d9c852-c984-1106-9143-fcba99c047a4.png)

### black auto formatting
- Settingsで`editor.formatOnSave`を検索
- `Editor: Format On Save`にチェック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193600/cd598d0c-fa60-4382-629c-926a220c8272.png)

- Settingsで`editor.formatting.provider`を検索
- `black`に設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193600/482dc1e1-7b25-b9f2-0021-add9db59d293.png)


### mypy static linting
- Settingsで`python.linting.mypyEnabled`を検索
- `Whether tot lint Python files using mypy`にチェック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193600/8ef779a8-ed8c-b33f-c252-e8bf77cfb749.png)


### VSCodeでVirtual Environmentの設定
- Settingsで`python.venvPath`を検索
- 自分のvirtualenvのパスを追加

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193600/4174d9df-f5df-a023-5163-27fb614c810a.png)


- プロジェクトを開発する際は左下のPython環境設定部分をクリックして適切な環境を選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193600/b99b8ba5-a045-729c-385e-d553a889c7f9.png)

# 参考Links

https://flake8.pycqa.org/en/latest/

https://black.readthedocs.io/en/stable/

https://mypy.readthedocs.io/en/stable/

https://farr.ai/vs-code-python-setup.html
nslcd.conf オプションメモ

これを書いた背景
=========================

OSは、ubuntu18.04だが、理由あって、libnss_ldap.so からlibnss-ldapd.soに変更している。その結果、LDAP Serverに対して、通信はできているが、syslogに下記のようなメッセージが頻繁にでるようになった。

```bash:syslog
Apr 21 02:00:11 my_workbench nslcd[1521]: [39dc03] <passwd="daikumatan"> ldap_result() timed out
```

これが原因かわからないが、Slurmの `srun` のジョブが失敗するという問題がでた。LDAPなしにすると、`srun` は完全に機能する。何かしら関係はありそうである。


```
srun: error: Task launch for 28.0 failed on node debug-dy-t2micro-4: Communication connection failure
srun: error: Application launch failed:
Communication connection failure srun:
Job step aborted:
Waiting up to 182 seconds for job step to finish.
srun: error: Timed out waiting for job step to complete FALSE
```

また、LDAP Serverは on-premで LDAP Client はAWS、途中は Direct Connect でつながれているという環境である。
(本当はLDAPサーバのレプリカがAWS上にもほしいところであるが、これも現状ルール上難しい)

そこで、nslcdの `Timing/reconnect options` に関してまずは調査した。

nslcd Options
=========================



Timing/reconnect options
---------------------------


### `bind_timelimit <sec>`

ディレクトリサーバーに接続するときに使用する制限時間（秒単位）を指定します。

- デフォルト値: 10 [sec]
- これは、`timelimit` で指定された時間制限とは異なり、接続のセットアップにのみ影響します。
- すべてのLDAPクライアントライブラリが接続タイムアウトの設定をサポートしているわけではないことに注意してください。


### `timelimit <sec>`

LDAPサーバーからの応答を待機する時間制限（秒単位）を指定します。

- デフォルト値: 0 [sec]
- デフォルト値の0は検索が完了するまで無期限に待機します。


### `idle_timelimit <sec>`

LDAPサーバーへの接続が閉じられるまでの非アクティブ期間（秒単位）を指定します。

- デフォルトでは、接続がタイムアウトしません。

### `reconnect_sleeptime <sec>`

すべてのLDAPサーバーへの接続が失敗したときにスリープする秒数を指定します。

- デフォルト値: 1 [sec]
- デフォルト値の1は、最初の失敗と最初の再試行の間の待機時間です。

### `reconnect_retrytime <sec>`

LDAPサーバーが永続的に使用不可であると見なされるまでの時間を指定します。

- デフォルト値: 10 [sec]
- この時間に達すると、再試行はこの期間に1回だけ実行されます。


上記の再接続ロジックは、nslcdとLDAPサーバーの間で使用されるメカニズムであることに注意してください。一方の端のNSSおよびPAMクライアントライブラリともう一方のnslcdの間のメカニズムは単純で、nslcdへの書き込みの場合は10秒、回答の読み取りの場合は60秒の固定コンパイル時間です。 nslcd自体の読み取り時間は0.5秒、書き込み時間は60秒です。

テスト結果
==========================

まずは上記まとめまで。
テスト結果は今後、記載しますー

Note
=================================

下記、参考3

> If you set nslcd's idle_timelimit less than timeout client for haproxy, you shouldn't get these messages.


下記、参考4

> 調べてみると、LDAP サーバ／クライアントの idle_timelimit の値がサーバの方が小さいためのようである。
> クライアントがサーバから強制切断されると、何故に固まるようである、、、バグ？
> ちなみに、Leopard Server のOpen Directory の idle_timelimit が 300 秒がデフォルトになっており、新しめのCentOS/Fedoraのauthconfig が勝手に 3600秒に設定してくれる。



参考
=======================

1. https://arthurdejong.org/nss-pam-ldapd/nslcd.conf.5
2. https://bugs.launchpad.net/ubuntu/+source/nss-pam-ldapd/+bug/1074213
3. https://serverfault.com/questions/920675/openldap-with-haproxy-ldap-result-failed-cant-contact-ldap-server
4. https://moimoitei.blogspot.com/2007/11/ldap-idletimelimit-missmatch.html
【個人開発】自分用にDjangoベースのCMS：Wagtailを用いて技術ブログを構築した話

# はじめに
こんなサイトを作りました。
https://ho-memo.com/
![スクリーンショット 2021-04-25 15.46.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296013/13354a29-2e03-92b6-b2c9-9548759e2f81.png)

技術ブログなどで色々アウトプットしていきたいと思いつつ、なかなか投稿できないでいたので、自分用の技術ブログを作れば積極的にアウトプットするのではと思い、2020年10月ごろに作成しました（そして半年後にようやくこの記事を投稿しているということは、、、）

# 環境は？
* Python
* Wagtail
* jQuery
* Bootstrap Material Design
* SQLite
* GCP

なぜWagtailかというと、もともとDjangoを勉強していて何か作りたいなーと思っていたことと、WordPressだとテーマが豊富で自分で作らなくても、、という気持ちになりそうだったのでDjangoベースのCMSであるWagtailを採用しました。

# 製作期間
* 1か月

以前にもWagtailで遊んだことがあり少し知見があったため、当ブログの作成だけでしたらこの期間で完成できました

# 苦労したところ
下記に、苦労した点と参考にさせていただいたものをまとめます。

## Wagtailをどう学習するか
あまり日本では使われていないためか、日本語情報があまりありません。そのため英語から情報を取得するのが必須でした。

今回作成したブログ作成を始める前、Wagtailの基本を学ぶため、まずYoutubeから下記シリーズを日本語字幕で見ていました。
細かく説明されているためとても分かりやすかったです。  
<iframe width="560" height="315" src="https://www.youtube.com/embed/1_yA25ZmNkA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
  
今回作成を始めるとき、できるだけ時間をかけたくなかったため下記チュートリアルを通してWagtailについて復習しました。
[Wagtail Tutorial Series](https://www.accordbox.com/blog/wagtail-tutorials/)



## エラーが起こったとき
作成時に色々エラーが出たりしましたがWagtailベースで調べるよりも、Djangoとして調べた方が解決することが多かったです。


# 教訓
本来の目的としては自分で作成したブログを通してどんどん記事を書くことでしたが、半年たった今でもあまりアウトプットできていません。
自分のようにQiitaの方でも書くのが続かない人は、自分でブログを作成したところで続かない可能性が高いのかなーと思いました。

# おわりに
いろいろ書きましたが、ぜひ見てみてください！
https://ho-memo.com/
C++:listとiteratorで弾の管理をしてみる

シューティングゲームの弾の管理をlistとiteratorを使った可変長配列で管理してみた。

```C++

//BulletManager.h

#include<list>
#include<iostream>

class Bullet;

class BulletManager
{
private:

    std::list<Bullet*>mpBullet;//listを使って弾を作る

public:

    BulletManager();//コンストラクタ
    ~BulletManager();//デストラクタ

    void Initialize();//初期化

    void Update();//弾の更新

    void Draw();//弾の描画

    void Finalize();//弾の終了処理

    void Shot();//弾を発射する

private:

    void DeleteBullet();//画面外に出た弾を削除する
};
```


```C++

//BulletManager.cpp

#include"Bullet"

BulletManager::BulletManager()
    :mpBullet()
{
}

BulletManager::~BulletManager()
{
}

void BulletManager::Initialize()
{
}

void BulletManager::Update()
{
    //for文をiteratorで回す
    for(std::list<Bullet*>::iterator itr = mpBullet.begin(); itr != mpBullet.end(); itr++)
    {
        if((*itr)  !=  nullptr)
        {
            (*itr)->Update();
        }
    }

    DeleteBullet();
}

void BulletManager::Draw()
{
    for(std::list<Bullet*>::iterator itr = mpBullet.begin(); itr != mpBullet.end(); itr++)
    {
        if((*itr)  !=  nullptr)
        {
            (*itr)->Draw();
        }
    }
}

void BulletManager::Finalize()
{
    for(std::list<Bullet*>::iterator itr = mpBullet.begin(); itr != mpBullet.end(); itr++)
    {
        if((*itr) == nullptr)
        {
            continue;
        }

        (*itr)->Finalize();
        delete  (*itr);
    }

    mpBullet.clear();
}

void BulletManager::Shot()
{
    mpBullet.push_back(new  Bullet());
    std::list<Bullet*>::iterator itr = mpBullet.end();
    itr--; 
    (*itr)->Initialize();
}

void BulletManager::DeleteBullet()
{
    for (std::list<Bullet*>::iterator itr = mpBullet.begin(); itr != mpBullet.end();)
    {
        if ((*itr) == nullptr)
        {
            itr++;
            continue;
        }

        //画面外に出たら削除
        if (
            (*itr)->GetPos().mX < -50 ||
            (*itr)->GetPos().mX > 690 ||
            (*itr)->GetPos().mY < -50 ||
            (*itr)->GetPos().mY > 530)
        {
            (*itr)->Finalize();       
            delete (*itr);
            (*itr) = nullptr;
            itr = mpBullet.erase(itr);
            continue;
        }
        itr++;
    }
}

```




今回は練習のためにnewを使ってますが実際に作るときはゲームループ中にnewするのはやめようね！
【Swift5】pickerViewの1行目が選択されているのに、デバックエリアに文字が表示されない

#はじめに
pikerViewを使用し、ボタンを押すと選択された「文字が表示」されるようにしたいと思いました。
pikerViewは動かすと文字を選択できますが、起動直後の状態ではhogeList[0]を呼び出す事が出来なくて調べました。

そうしたところ思いのほか調べるのに時間が掛かったので、忘却録として残しておこうと思います。

もし間違いがある場合は優しく教えていただけると嬉しいです。

#環境
Xcode12.3
Swift5.3.2
macOS Catalina 10.15.4

#didSelectRowの1行目が呼ばれない
下記画像のようにボタンを押した場合「コアラ」とデバッグエリアに表示したいところ「初期値」と表示されてしまいました。
![スクリーンショット 2021-04-25 15.11.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683624/10e65128-724f-7b8f-97d0-7e08c054835a.png)
↓デバッグエリア
![スクリーンショット 2021-04-25 15.11.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683624/280be16d-c573-c120-969c-08d379af2aea.png)




#原因
ブレークポイントで調べてみたところ、didSelectRowが呼ばれていませんでした。
![スクリーンショット 2021-04-25 15.40.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683624/db6f8e11-cd32-9b6e-332a-46771606c3a8.png)



#対処
[参考サイト](https://stackoverflow.com/questions/788357/uipickerview-1st-row-selection-does-not-call-didselectrow?lq=1)を参考にdidSelectRowを呼び出したところ無事に表示されました。


```Swift
 override func viewDidLoad() {
        super.viewDidLoad()

        hogePickerView.delegate = self
        hogePickerView.dataSource = self

        //didSelectRowの1行目を呼び出す
        pickerView(hogePickerView, didSelectRow: 0, inComponent: 0)
    }
```

#対処後
![スクリーンショット 2021-04-25 15.11.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683624/b2e8ac12-c55a-dd66-ca7e-caa98d1c51be.png)

↓デバッグエリア

![スクリーンショット 2021-04-25 15.38.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683624/dd91c732-6857-6488-85a9-e35aca57025a.png)

#全コード

```swift
import UIKit

class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

    @IBOutlet weak var hogePickerView: UIPickerView!

    var hogeString = "初期値"

    let hogeList = ["コアラ", "カンガルー", "ネコ", "イヌ", "ライオン"]

    override func viewDidLoad() {
        super.viewDidLoad()

        hogePickerView.delegate = self
        hogePickerView.dataSource = self

        //didSelectRowの1行目を呼び出す
        pickerView(hogePickerView, didSelectRow: 0, inComponent: 0)
    }

    @IBAction func hogeActionButton(_ sender: UIButton) {
        print("\(hogeString)")
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
       return hogeList.count
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return hogeList[row]
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

        hogeString = hogeList[row]
    }
}
```


#参照サイト
https://developer.apple.com/documentation/uikit/uipickerviewdelegate/1614371-pickerview
https://stackoverflow.com/questions/788357/uipickerview-1st-row-selection-does-not-call-didselectrow?lq=1
[Python] DFS ABC199D

#[ABC199D](https://atcoder.jp/contests/abc199/tasks/abc199_d)

$3^N$ 通りの塗り方を全部探索する方法では実行時間制限に間に合わせるのは困難です。
ある頂点iの色を決めた時、iと辺で繋がっている頂点の色の探索候補は2通りしかないから、グラフが連結なら$3×2^{N-1}$通りの塗り方だけ探索すればよい。
今回グラフは連結とは限りませんが、連結成分ごとの塗り方の数の積が全体の塗り方の数となるので連結成分ごとに処理すればグラフが連結な場合に帰着することができます。

```python:サンプルコード
import copy
n,m=map(int,input().split())
G=[[] for _ in range(n)]
# 隣接グラフ設定
for i  in range(m):
    a,b=map(int,input().split())
    a,b=a-1,b-1
    G[a].append(b)
    G[b].append(a)

done=[False]*n   # 頂点のグラフ作成済みフラグ

# 再帰で連結グラフ作成
def make_union(p,ret):
    done[p]=True
    ret.append(p)
    for q in G[p]:
        if done[q]: continue
        make_union(q,ret)
    return ret

"""
連結グラフの頂点iから再帰DFSで色を塗り、塗り方が何通りか返す
stateは色塗状況、lstは連結グラフ
"""
def dfs(i,state,lst):
    ret=0
    # 終端処理
    if i+1==len(lst):
        for c in range(3):
            for q in G[lst[i]]:
                if state[q]==c: break
            else: ret+=1
        return ret
    for c in range(3):
        state[lst[i]]=c
        for q in G[lst[i]]:
            if state[q]==c: break
        else:
            ret+=dfs(i+1,copy.copy(state),lst)
    return ret

ans=1
for p in range(n):
    if done[p]: continue # 数え済みならパス
    lst=make_union(p,[])
    ans*=dfs(0,[-1]*n,lst)
print(ans)
```
is out of range for ActiveModel::Type::Integer with limit 4 bytesエラー(ActiveRecordのint型項目の最大値超過エラー)

![20210425-143446.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/edb49e40-5c74-47a6-27f1-23fb90a7797e.png)


ActiveRecordでinteger型の項目をマイグレして、int型の最大値以上の数を入れて保存しようとすると、モデル側で以下のエラーが出ます。

09077778888で電話番号に設定した数字が大きすぎるって怒られてます。

電話番号(ハイフンなし10桁)
/\A\d{10}\z/

携帯番号(ハイフンなし11桁)
/\A\d{11}\z/

携帯番号(ハイフンなし10桁or11桁)
/\A\d{10,11}\z/

さらにデータカラムの設定ミス
-

```rb:20210424083812_create_addresses.rb
class CreateAddresses < ActiveRecord::Migration[6.0]
  def change
    create_table :addresses do |t|
      t.string       :postal_code             ,null:false
      t.integer      :prefecture_id           ,null:false
      t.string       :town                    ,null:false
      t.string       :address                 ,null:false
      t.string       :building
      t.integer       :phone_number            ,null:false
      t.references   :purchase                ,null:false, foreign_key: true 
      t.timestamps
    end
  end
end
```

電話番号の欄がintegerになっていたので入りませんでした。

###バリデーションの設定が数値設定になっていたので直したのですが、マイグレーションファイルも数値型になっていたのでどうしても保存か不可能でした。ファイグレーションファイルをロールバックして修正してのち再度、string型に変更して直りました。
JSONコードをPHPに読み込み・変換するまで


初歩的な理解ながら、エラーで苦戦したJSONコードをPHPに変換するまでをまとめてみました。
同じ箇所で詰まっている人のヒントになれれば幸いです。

#実際のコードの書き方
以下が、PHP変換するまでの処理です。
今回は、「sample.json」というJSONコードで書かれたファイルを用い、
このデータをindex.phpに読み込んでいきます。


```PHP：index.php
$filename = "http://sample.com/sample.json";
$file = file_get_contents($filename);
$prevention = mb_convert_encoding($file, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');
$json = json_decode($prevention, true);
```


それぞれを見ていきます。

###JSONコードの代入

```
$filename = "http://sample.com/sample.json";
```
ここでsample.jsonを”http://”を用いてhttp://sample.com/sample.json
として変数$filenameに代入します。
最初この代入をせずに

```
$file = file_get_contents(”sample.json”);
```

と、次のコードでsample.jsonを直接書いて見ましたがこれはできませんでした。

###file_get_contents関数とその代入
```
$file = file_get_contents($filename);
```

file_get_contents関数とは、ファイルの内容を全て文字列に読み込む関数です。
詳細：https://www.php.net/manual/ja/function.file-get-contents.php
この関数を用いて（）内に先程の$filenameを入れsample.json内の内容を文字列化し、
さらにそれを変数＄fileへ代入します。

###文字化けの防止
```
$prevention = mb_convert_encoding($file, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');
```
JSONファイルを文字列に読み込んだ状態のみでは、場合によって文字化けを起こす危険があります。
その場合の変換する関数として、mb_convert_encoding()というのを使います。
これは（）内にある、ASCII,JIS,UTF-8,EUC-JP,SJIS-WINの順番で自動検出し、UTF8に変換するということです。
その後、この処理を変数$preventionへ代入します。

###デコード
```
$json = json_decode($prevention, true);
```
json_decode関数を用いて変数$preventionを第一引数とし、デコードします。
デコードとは、エンコード（データを他の形式に書き込むこと）されたものを再び元の状態に戻すことを指します。
デコード内容を連想配列とする場合、第二引数ではtrueとします。


これで、JSONコードをPHPに変換するまでの処理は完了です。

これは自分が行った時の解決した方法であり深い理解まで至っていないため、
もし、これに説明不備・間違った解釈などありましたら、ご教授のほどお願いします。

#参考文献

https://qiita.com/fantm21/items/603cbabf2e78cb08133e
https://www.php.net/manual/ja/function.file-get-contents.php
https://www.php.net/manual/ja/function.json-decode.php
TypeORMでattributeを指定して階層構造データを取得する

# 目的
```sql
SELECT u.id, u.name, p.name
FROM users u
INNER JOIN posts p
ON u.id = p.user_id
WHERE p.id = 1;
```

というsqlを発行して、JS実行時に以下のようなオブジェクトを取得したい。

```TypeScript
{
  id: 1,
  name: 'Yamada Taro',
  posts: [
    { name: '記事1' },
  ],
}
```

# Partial Selection
https://github.com/typeorm/typeorm/blob/master/docs/select-query-builder.md#partial-selection

```ts
import {getRepository} from "typeorm";

const user = await getRepository(User)
    .createQueryBuilder('user')
    .select([
      'user.id',
      'user.name',
      'post.name',
    ])
    .innerJoin('posts', 'post')
    .where('post.id = :id', { id: 1 })
    .getOne();
```

によって、attributeを指定しつつ階層構造を保持したobjectを取得できる。
ProtonVPNで、403 ERRORとなってしまった時の対処法

セキュリティーが相当高いことで知られている[ProtonVPN](https://protonvpn.com/)ですが、なぜかページが表示されなくなった時の対処法をメモしました。

# 結論

日本サーバではなく**海外サーバ**を使ってみる。(自分の場合は韓国サーバでいけました！)

![ScreenShot 2021-04-25 15.31.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136124/9e0d2a98-4ce0-9d76-96e0-41aa3227a2c1.png)

# 表示されない状態はどんな状況か？

例えば、ProtonVPNを使っている状態で[note.com](https://note.com)にアクセスすると、以下のような表示になってしまいます。(2021年4月25日現在)

![ScreenShot 2021-04-25 15.25.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136124/58973f1e-6a05-36dd-9300-afb7f970f0b8.png)

どうやらサイトによっては、VPNフレンドリーでないサイトがあるようです。。

参考：https://www.reddit.com/r/ProtonVPN/comments/hrekil/access_denied/

# 参考

- [ProtonVPN](https://protonvpn.com/)
- https://www.reddit.com/r/ProtonVPN/comments/hrekil/access_denied/
Dockerだいたいの理解


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517773/6a7a3c24-5c99-30e6-0965-834024a518ae.png)

参考サイト
https://tech-blog.rakus.co.jp/entry/20180926/microservice

Dockerを利用することで
エンジニアが開発するバージョンや環境を管理することができる。

このサービスをマイクロサービスというらしい。

####CircleCI
今は、Github　Actionといサービスになってる。
Githun上でビルドできるかテストするサービス。

参考
https://qiita.com/zomaphone/items/7e6c3db6b3670f10e23d

これはCI/CDという。

以下参考
https://codezine.jp/article/detail/11083

https://phpunit.readthedocs.io/ja/latest/writing-tests-for-phpunit.html

https://qiita.com/jintz/items/61af86a12b53b24ef121
【ギリ初心者向け】Laravel Docker AWS(EC2) Webアプリ（PHP)を0から簡単にデプロイする方法（無料）③　ーEC2にデプロイ編ー

#※内容はこちらのサイトに移動しました！

https://sg-report.com/laravel-docker-awsec2-web3/
YAMLファイル内の配列をソートしたい

## 背景
flutterの静的解析の設定ファイルはYAMLで書かれています．僕の使っているその設定ファイルの中身が名前順に並んでいなかったので，ソートしようと考えたのですが，YAMLに含まれている配列までソートしてくれるツールが見つかりませんでした．なのでPythonをつかってソートをしました．本記事はそのときのメモです．

## ソートしたいファイルの中身

ソートしたいyamlのリスト部分はこんな感じです
![yaml.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542224/34d39321-1165-acd6-ce06-617d3618bd31.png)

## ツール
環境構築が面倒なのでGoogle Colabを使います

## コード

```python
# ファイルのアップロード
from google.colab import files
uploaded_file = files.upload()
uploaded_file_name = next(iter(uploaded_file))
print(uploaded_file_name)

# ソート
import yaml

with open(uploaded_file_name) as file:
    obj = yaml.safe_load(file)
    print(obj['linter']['rules'])
    obj['linter']['rules'] = sorted(obj['linter']['rules'])
    print(obj['linter']['rules'])

# 出力
output_file_name = 'analysis_options.yaml'
with open(output_file_name, 'w') as file:
    yaml.dump(obj, file)

files.download(output_file_name)

```

あとはエディタ上でフォーマットを整えると完成です
【Laravel】@csrf ←コイツの存在について

#はじめに
現場では主にモバイルアプリ開発(React Native, TypeScript)を行っているのですが、WEBアプリ開発(Laravel)にも3割くらい携わっています。
これまでなんとなくやってこれたのですが、振り返ってみるとよく理解せずに実装してきたところがいろいろありました。
例えば、タイトルの`@csrf`などformを書く際のおまじない的な感じで書いてきましたが、何のための記述なのかよくわかっていませんでした。

言語のスキルをいくら高めてようとしても、基礎理解がおろそかなままだとレベルの上限があります。
ということで、これまで理解がふわふわだったところを一個ずつまとめていくことにしました。

#この記事の対象読者
- CSRFについて知りたい方
- Laravelの`@csrf`が何を行っているのかを知りたい方

#Cross Site Request Forgery (CSRF)
Cross Site Request Forgery(CSRF)は、WEBアプリケーションが偽装されたリクエストを正規のものとして受信してしまう脆弱性、または攻撃手法を意味します。

例えば、とあるWEBアプリでパスワードを変更するためのフォームがあったとします。
CSRFの対策がされていないと、以下の流れでそのアプリにログインするためのパスワードが書き換えられてしまう恐れがあります。

1. 見知らぬリンクが記載されたメールが送られてくる
2. メールを開いてリンクをクリックしてしまう
3. リンクにパスワード変更のフォームが組み込まれており、WEBアプリにリクエストが送られてしまう
4. WEBアプリのログインパスワードが変更されてしまう

![スクリーンショット 2021-04-25 13.44.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/11be8146-24e1-a433-4e5d-52e736bfae9f.png)

**ユーザの気が付かないうちに偽装されて送信されたパスワード更新のリクエストが、そのままWEBアプリ側で受け付けてしまうのが問題だということですね。**

つまり、**CSRF対策というのは、このようなリクエストがブロックされるような仕組みをつくることと同義ということになります。**

https://www.ipa.go.jp/security/vuln/vuln_contents/csrf.html

https://yamory.io/blog/about-csrf/

#`@csrf`って何？
`@csrf`というのは、CSRFトークンを利用したLaravelにおけるCSRF対策の一つです。

Laravelでは、アプリケーションによって管理されているアクティブなユーザーの各セッションごとに、CSRFトークンを自動的に生成します。
**`@csrf`をformに加えることで、リクエストが送信されたときにCSRFトークンが生成され、セッションに保存されたトークンと一致するかどうかを`VerifyCsrfToken`ミドルウェアが確認してくれます。**

トークンが一致しない場合にはリクエストをブロックするため、このようにして悪意のあるリクエストからアプリを守ってくれるようになっています。

```php
<form method="POST" action="{{ route('login') }}">
  @csrf //CSRFトークンを付与
  ...      
</form>
```

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

https://qiita.com/Eryushidate/items/1b29b84e554360f1294d

#おわりに
これからLaravelのアウトプットもやっていきます。
Synology の nginx について

Synology の Web サーバーについて分かったことです。
 (DS220j で調べました。)
Default の Webサーバーは nginx です。

```text
$ nginx -V
nginx version: nginx/1.16.1
TLS SNI support enabled
```

root は /volume1/web です。
nginx の設定ファイルは、/etc/nginx にあります。

```text
$ ls /etc/nginx
app.d         fastcgi_params  mime.types          proxy.conf     uwsgi_params
conf.d        koi-utf         nginx.conf          scgi_params    win-utf
fastcgi.conf  koi-win         nginx.conf.default  sites-enabled
```

nginx の再起動は次のように行います。

```bash
sudo synoservicecfg --restart nginx
```

再起動すると /etc/nginx/nginx.conf は上書きされます。

再起動時の nginx.conf は、次の mustache ファイルから生成されます。

```text
$ ls /usr/syno/share/nginx
Alias_v2.mustache           DSM.mustache          open_file_cache.mustache
avahi.mustache              error.html            optimization.mustache
cgi.mustache                error_page.mustache   Portal.mustache
cgi.pass.mustache           Firewall.mustache     server.mustache
conf.d                      gzip.mustache         SSLProfile.mustache
deny.mustache               HSTS.mustache         SynoSharing.mustache
deny.PhotoStation.mustache  LetsEncrypt.mustache  WWW_Main.mustache
deny.synoman.mustache       logo.jpg              WWWService.mustache
DSM_Main.mustache           nginx.mustache        X-Accel.mustache
```
git pushしてもリモートレポジトリに届かずEverything up-to-dateと返される

git pushしてもリモートレポジトリに届かずEverything up-to-dateと返されて
なかなかgithubに反映されなかったです

調べた結果コミットできてないと言う記事が多かったのですが
自分の場合コミットしてgit pushしてもEverything up-to-dateと出るだけでした

```
$ git commit -m"コメント"
$ git push

```

そこで
ssh://git@github.com/◯◯◯.gitに接続し、ローカルのmasterブランチをリモートのmasterブランチにpushするというやり方で

```
$ git push ssh://git@github.com/◯◯◯.git master:master
```
行いました。しかしながら
Everything up-to-date継続のままです。

そこで次の手段

```
$ git add -A
$ git commit -m "recommit" -v
$ git push
```

これでうまくリモートレポジトリに届きました。
sketchupでruby その13

# 概要

sketchupでrubyやってみた。
練習問題やってみた。

# 練習問題

コップを描け。


# 写真

![glass.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/a8e0b2ef-bc82-0f70-1342-a4c2a2a73977.png)


# サンプルコード

```
def glass
   model = Sketchup.active_model
   entities = model.active_entities
   x = 0
   y = 0
   z = 0
   r = 30
   n = 24
   pts = []
   pts[0] = [20, 0, 50]
   pts[1] = [15, 0, 5]
   pts[2] = [15, 0, 0]
   pts[3] = [13, 0, 0]
   pts[4] = [13, 0, 5]
   pts[5] = [18, 0, 50]
   base = entities.add_face pts
   circle1 = entities.add_circle(Geom::Point3d.new(x, y, z), Z_AXIS, r, n)
   status = base.followme(circle1)
   entities.erase_entities circle1
end



```

以上。
FreeBSD composerのインストール

サクラのレンタルサーバにcomposerをインストールした際の忘備録
環境はFreeBSD 11.2-RELEASE-p14

公式：Download Composer
https://getcomposer.org/download/

インストールしたいディレクトリにて以下のコマンドを実行
<pre>php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"</pre>

次に以下のコマンドを実行し、インストーラーが改竄されていないことを確認する。
<pre>php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"</pre>

問題なければ以下が出力される。
<pre>Installer verified</pre>

以下のコマンドを実行しcomposerをインストールする。
<pre>php composer-setup.php</pre>

インストーラーを削除
<pre>php -r "unlink('composer-setup.php');"</pre>

以下のファイルが作成されていればOK！
<pre>% ll
total 2208
-rwxr-xr-x  1 hoge  huga  2213444 Apr 25 14:00 composer.phar
</pre>

＜補足＞
インストーラー検証のhash値はバージョンによって異なる。
最新バージョンのhash値は公式サイトを参照。
[EC-CUBE4]「商品レビュー管理プラグイン」の総合評価を公開のみの平均に修正する

## まずはじめに

<dl>
  <dt>何してる人？</dt>
  <dd>受託開発で飯食ってます。<br>
      EC-CUBEはパートナーさんから下請けでお仕事もらってたり、<br>
      直請けでお客様にECサイトを構築、提供する際に利用してます。
  </dd>
  <dt>EC-CUBE4</dt>
  <dd>オリジナルECサイトが作れるパッケージ</dd>
  <dt>プラグイン</dt>
  <dd>EC-CUBEを簡単に拡張ができるやつ</dd>
  <dt>商品レビュー管理プラグイン</dt>
  <dd>公式が配布しているプラグイン。よくある商品へのレビュー機能を実現。</dd>
</dl>

プラグイン詳細はプラグインのダウンロードページから
[商品レビュー管理プラグイン](https://www.ec-cube.net/products/detail.php?product_id=1756)

## 事の経緯
ある案件で商品レビュー管理プラグインを利用したところ、
「非公開のレビューが総合評価の星に反映される」と指摘を受けました。

冷静に考えると、「非公開なんだから総合評価に反映するのはおかしい」と考える人も多いかと思います。

ちなみに私はそれまでは気にしてなかったけど、言われてからは気になって仕方がない。
見えてない内容が反映されるのは気持ち悪い。


## 修正内容
プラグイン内をちょろちょろっと修正します

```php:app/Plugin/ProductReview4/Repository/ProductReviewRepository.php
   〜前省略〜

    public function getAvgAll(Product $Product)
    {
        $defaults = [
            'recommend_avg' => 0,
            'review_count' => 0,
        ];
        try {
            // 表示ステータスを「表示中」のみに変更
            $psrep = $this->getEntityManager()->getRepository(ProductReviewStatus::class);
            $Status = $psrep->find(ProductReviewStatus::SHOW);

            $qb = $this->createQueryBuilder('r')
                ->select('avg(r.recommend_level) as recommend_avg, count(r.id) as review_count')
                ->leftJoin('r.Product', 'p')
                ->where('r.Product = :Product')
                ->setParameter('Product', $Product)
                // ステータスを条件に追加
                ->andWhere('r.Status = :Status')
                ->setParameter('Status', $Status)
                ->groupBy('r.Product');

            return $qb->getQuery()->getSingleResult();
        } catch (\Exception $exception) {
            return $defaults;
        }
    }
```

## 最後に
総合評価をに非表示のレビューの星を含めるか含めないかは考え方しだいなのかなと。
そう考えると、プラグインでは設定で切り替えができるようにするほうが望ましいのかなと思ったりします。
テックキャンプのログイン画面を見失った...

テックキャンプを受講していた時にこんなことがありました。

「ログイン画面が見失った...」

どこにあるんだろう...

と悩んでいた時に１つの記事に助けられました。


https://prowaku.com/where-login-or-register/


このサイトでは分かりやすく、ログイン画面や新規登録画面についての解説がありました。

また、テックキャンプ受講中に作業スピードを爆上げする方法もあったので助かりました。

ぜひ皆さんも見てみて下さい！
Laravelでページネーション実装

## 前提
| PHP | Laravel | 
| ---- |  ----- |
| 7.1.19 | 5.6.27 |

## 使用方法
LaravelのペジネータはクエリビルダとEloquent ORMに統合されている。
今回はpagenateメソッドを用いることとする。
### クエリビルダ
下記のように、paginateに一つだけ引数を渡しており、今回はページごとに10アイテムを表示するように指定している。

```php:
<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    const PER_PAGE = 10;
    /**
     * アプリケーションの全ユーザー表示
     *
     * @return Response
     */
    public function index()
    {
        $users = DB::table('users')->paginate(self::PER_PAGE);

        return view('user.index', compact('users');
    }
}
```

### Eloquent
Eloquentモデルも同様にpagenateメソッドを用いる。

```php:
$users = App\User::paginate(10);

$users = User::where('name', '太郎')->paginate(10);

$users = User::orderBy('created_at', 'desc')->paginate(10);
```

## ページネーション表示
pagenateメソッドはIlluminate\Pagination\LengthAwarePaginatorインスタンスを返すので
、その結果をBladeに渡して、結果を表示する。

```php:
{{ $users->appends(request()->query())->links() }}
```

### ・appends
ペジネーションリンクにクエリ文字列を付加する。
クエリ文字列は「https:// ○△×□.jp/?hoge=hogehoge」の「?hoge=hogehoge」の部分

### ・request
現在のリクエストインスタンス（Illuminate\Http\Request）を返す。

### ・query
request()->query()でクエリ文字列を取得する。

### ・links
　検索結果の残りのページヘのリンクを付加する。各リンクにはpageクエリ文字列変数が含まれている。

## 参考
[https://readouble.com/laravel/5.8/ja/pagination.html](https://readouble.com/laravel/5.8/ja/pagination.html)
Athenaで曜日を番号で取得する

# Athenaで日付から曜日を取得したい
Athenaのprestoベースなのでdate_formatのprestoのドキュメントを参照すると
>%w Day of the week (0 .. 6), where Sunday is the first day of the week 3

とあるためたとえば2021/04/25の日曜日の番号を取得するには

```sql
select date_format(timestamp '2021-04-25', '%w')
```
で取得可能と思われる。
しかし、実際に実行してみると

```
INVALID_FUNCTION_ARGUMENT: %w not supported in date format string
```

とエラーが発生される。Athenaでは%wがサポートされていないようです。

## day_of_weekの利用
day_of_weekを利用すると曜日番号が取得可能です。

```sql
select day_of_week(timestamp '2021-04-25') 
```

これで番号が取得可能なのですが、day_of_weekは
>Returns the ISO day of the week from x. The value ranges from 1 (Monday) to 7 (Sunday).

とあるため月曜から土曜日は1~6でdate_formatと同じなのですが、日曜日だけ0ではなく7が返ってきてしまいます。
従って0~6で取得したい場合は

```sql
select if (day_of_week(timestamp '2021-04-25')  = 7, 0, day_of_week(timestamp '2021-04-25'))
```

とif文で7の場合に0に置き換えます。

他にいいやり方あったら教えて下さい！
VBA on Libre Calc - シート操作・文字列編集・ファイル出力 - 


## ためしてガッテン！！
LibreOffice CalcでVBAが使えるという記事をいくつか見かけてテンションがあがりました。
と同時に「ここができないと」と気になったのが以下の3点です。

* シートの操作
* 文字列編集
* ファイル出力

これらが扱えるとVBAの知識を活かしてCalcをCSVなどのデータ作成・生成ツールとして活用しやすいです。
Calcで実験 ⇒ Excelで実用なんてことにも応用できます。

## 結論
1時間程度のお試しですが、実用性はあると感じました。LibreOfficeの人たちすごい。
環境を記載したあと、試した関数等をご紹介します。

## 環境
Windows 10
LibreOffice 6.4

## シートの操作

```vb

    ' アクティブなシートのセルに値を設定
    activesheet.cells(1,1) = "Good"

    ' シート名を指定して値を設定
    worksheets("Sheet2").cells(2,5) = "Weldone"

    ' シートの追加
    worksheets.add

    ' シート数の取得
    worksheets.count

    ' 指定のシートをアクティブに
    worksheets("Sheet1").activate

```

## 文字列編集

```vb

orgStr = "てくのぽりす"

' left
print #1, left(orgStr,3)

' mid
print #1, mid(orgStr,3,2)

' right
print #1, right(orgStr,3)

' len
print #1, len(orgStr)


spacedStr = " VBA "

' trim
print #1, trim(spacedStr)


```

```
てくの
のぽ
ぽりす
6
VBA
```

## ファイル出力

```vb

' オープン
Open "E:\test.txt" For Output As #1

' 出力
print #1, "Marvelous"

' クローズ
close #1

```

※出力先には注意して下さい。"C:\test.txt"　等は通常アプリから書けないので「デバイスI/Oエラー」になります。

## 最後に
まだまだ確認すべきものはありますが、「試していこう」と感じられるほどに動いてくれました。

参考になればこれ幸いというところです。
Railsのアップグレード方法

# 概要
- あるプロジェクトで`5.2.3` → `5.2.5`のアップグレードをする必要あり
- メジャーバージョンは変わらずだったので今回は大きな問題なく終えたが手順をまとめておく

# 手順

基本的には[Rails アップグレードガイド - Railsガイド](https://railsguides.jp/upgrading_ruby_on_rails.html)の通り作業をすれば良い

### 1. Gemのアップデート

GemfileのRailsバージョンを`5.2.5`に修正後、以下のコマンドを実行

```sh
bundle update
```

失敗した場合は、該当Gemのバージョンを固定し依存を解決する
  
### 2. Railsのconfigファイル群のアップデート

```sh
bundle exec rails app:update
```

configファイルの内、Railsアップグレードに伴う変更があるものについて`conflict`するはず

```sh
identical  config/boot.rb
       exist  config
    conflict  config/routes.rb
Overwrite /Users/your_name/project_root/config/routes.rb? (enter "h" for help) [Ynaqdhm]
```

helpを見てみると

```
Y - yes, overwrite
n - no, do not overwrite
a - all, overwrite this and all others
q - quit, abort
d - diff, show the differences between the old and the new
h - help, show this help
m - merge, run merge tool
```

`d`でdiffをみることができるので、もし修正すべきところがあれば修正する。なければ`n`で進んでOK

ちなみに、以下のように`THOR_DIFF`を設定するとnvimでdiffを開くことができる。

```sh
export THOR_DIFF="nvim -d "  # vimの場合は `export THOR_DIFF=vimdiff`
bundle exec rails app:update
```

nvimでファイルを開いて、古い方のファイルを編集する（新しいファイルから移植すべきところがあれば移植する）。その後、`n`を選択すれば古いファイルが残る。（新しいファイルを編集してから`Y`を押しても最初に提示された新ファイルで上書かれるのでやらないように）

また、`THOR_MERGE`変数を設定することによって、`m`で編集することもできる（こっちが正統派？今回は上でやってしまった）

```sh
export THOR_MERGE="code -d $1 $2"
```

https://stackoverflow.com/questions/60661494/rails-5-how-do-i-set-up-a-merge-tool-to-use-for-rails-appupdate


### 3. 設定の変更を順次適用していく

上記の手順で`config/application.rb`ファイルに`config.load_defaults 5.0`のような記述を加えた場合、Railsは古いバージョン（この場合は`5.0`）の設定で動く。

`config/initializers/new_framework_defaults.rb`には新しいバージョンの設定が書かれていて、この設定を一行ずつアンコメントしていくことで新しいバージョンの設定を順に適用していくことができる。

例として、以下のような記述があり、これの一番下の行をアンコメントするとこの項目についてアップグレード後の設定が適用されるようになるので、その状態でテストを行う。（テストがなければ手動で動作の確認を行う。）

```
# Make Active Record use stable #cache_key alongside new #cache_version method.
# This is needed for recyclable cache keys.
# Rails.application.config.active_record.cache_versioning = true
```

この手順を全設定に対して行い、全てクリアしたらこのファイルは削除して良い。

また`config/application.rb`内の`config.load_defaults 5.0`も削除する。

### 4. その他の作業

3まででバージョンバップは完了。

あとはデプロイするなどして動作確認していき、本番環境で無事動けばOK


# 参考Links
- [Rails アップグレードガイド - Railsガイド](https://railsguides.jp/upgrading_ruby_on_rails.html)
- [vimdiff を neovimでやるには - それマグで！](https://takuya-1st.hatenablog.jp/entry/2018/09/02/155622)
- [bin/rails app:update の diff を vim で見る方法 - Qiita](https://qiita.com/ma2ge/items/a838864f059fc9b931b2)
Expo React native tailwind-rn 導入


tailwindscssを使ってみたい！

ということで、React-nativeにtailwind-rnを導入してみました。

まずはInstallから。
`yarn add tailwind-rn`

で、次に
`npx tailwindcss init`
これで、tailwind.config.jsが作成されます。
この中で、色々カスタマイズ出来る感じなんですかね。
[tailwindの公式ドキュメントへのリンク](https://tailwindcss.com/docs/configuration)

その次は、
`npx create-tailwind-rn`
このコマンドで、customした内容も含めて、適用されたstyles.jsonが作成されます。

導入自体は、これで終了。
あとは使用したいコンポーネントで、こうして
`import tailwind from 'tailwind-rn';`
こう
`<Text style={tailwind('text-red-500')}>`

tailwindを使用するファイルで初期化するのは、利便性が悪いから、tailwind.jsというのを作成して、どこからでもimportするだけで使えるように設定することをオススメしてくれてるので、おとなしくそうしときましょう。
その内容については、リンク先のドキュメント参照してみてください。
[https://github.com/vadimdemedes/tailwind-rn](https://github.com/vadimdemedes/tailwind-rn)


参照ドキュメント
>https://github.com/vadimdemedes/tailwind-rn
>https://tailwindcss.com/
Kotlin > ktlint > プルリク時にktlintチェックを行う


Github Actionsを使ってプルリク時にktlintチェックを行います。



`ScaCap/action-ktlint` を使います。
[ScaCap/action-ktlint: Run Ktlint with reviewdog](https://github.com/ScaCap/action-ktlint)




Readmeに書いてあるExample usageをコピーしてもそのまま動作します。

[ScaCap/action-ktlint: Run Ktlint with reviewdog](https://github.com/ScaCap/action-ktlint#example-usage)


Actionsのフォルダにreviewdog.ymlを作成（ファイル名はなんでもOK）

```:.github/workflows/reviewdog.yml
name: reviewdog
on: [pull_request]
jobs:
  ktlint:
    name: Check Code Quality
    runs-on: ubuntu-latest

    steps:
      - name: Clone repo
        uses: actions/checkout@master
        with:
          fetch-depth: 1
      - name: ktlint
        uses: ScaCap/action-ktlint@master
        with:
          github_token: ${{ secrets.github_token }}
          reporter: github-pr-review # Change reporter
```


reviewdog.ymlをGithubにPUSHしたのち、プルリクを作成するたびにActionsが実行されます。

![スクリーンショット 2021-04-25 13.27.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/eb9879e4-3844-79f2-55ee-62acc604cedb.png "スクリーンショット 2021-04-25 13.27.03.png")


Ktlintチェックにひっかると、プルリクのコメントに指摘が自動で入ります。

![スクリーンショット 2021-04-25 10.29.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/135e5239-985b-6e6b-2750-97468321049f.png "スクリーンショット 2021-04-25 10.29.02.png")
FormObjectの場合はカラムリネームではない

Formオブジェクトを使用している時はの下記のエラーは


![20210425-125358.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/1b3ec2f4-0a9f-d433-f715-540f8c5d62a1.png)


###リネームするのではなくて

###attr_accessor許可しないと使えないという意味です
Seleniumをローカルで動かす (Node.js)

記載日：2021/4/25
ローカルにSeleniumをインストールしブラウザ操作する手順を、忘れないように記載します。

[関連]
[Seleniumサーバでリモートのブラウザを操作する](https://qiita.com/middle_aged_rookie_programmer/items/5b6f2fb9800845eb4b2f)
[SeleniumをEXEで動かす](https://qiita.com/middle_aged_rookie_programmer/items/dd82febac13072ec148e)

#### 目標
　SeleniumをUbuntuにインストールし、ブラウザを操作すること。

#### バージョン情報
　・マシン：Ubuntu20.04
　・Node js：10.19.0（npm：6.14.4）
　・Selenium：3.141.0

#### 流れ
１．Seleniumをインストール。
２．WebDriverをダウンロード。
　　注意：WebDriverのバージョンは、ブラウザのバージョンと合わせること。
３．テストファイル作成。
４．テスト実行。

#### 作業
０．事前準備
　・UbuntuマシンにNode js、npmをインストールする。

１．Seleniumのインストール
　　プロジェクトディレクトリを作成する。以下では、「selenium」というプロジェクトディレクトリを作成している。
　　プロジェクトディレクトリへ移動する。
　　　`mkdir ~/Desktop/selenium`
　　　`cd ~/Desktop/selenium`
　・Seleniumをインストールする。以下コマンドを実行する。
　　　`npm install selenium-webdriver`

２．WebDriverのダウンロード
　　WebDriverをダウンロードする。

３．テストファイル作成
　　テストファイル：test.jsを作成する。
　　ディレクトリ構成は以下のようになる。
　　　selenium
　　　　　|-　test.js
　　　　　|-　webdriver
　　test.jsに以下を記述する。

```Python
const {Builder} = require('selenium-webdriver');
const assert = require("assert");
(async function myFunction() {
  let driver = await new Builder().forBrowser('chrome').build();
  await driver.get('https://[IPやドメイン]');
})();
```

４．テスト実行
　　test.jsを実行する。
　　　`node test.js`

#### 参考にさせて頂いたサイト
https://www.selenium.dev/documentation/ja/
Kotlin > KtlintをCommit前にチェックする


## 事前設定

### command line版のktlintを入れる

```
brew install ktlint
ktlint --version
```

### pre-commitを導入

```
brew install pre-commit
pre-commit --versionß
```


以下のように表示されたら `xcode-select --install`を行う

```
Error: python@3.9: the bottle needs the Apple Command Line Tools to be installed.
  You can install them, if desired, with:
    xcode-select --install
```

xcode

```
xcode-select --install
```


## pre-commit-hookの作成

プロジェクトRootで以下を実行する

```
ktlint --install-git-pre-commit-hook
```


`.git/hooks/` 配下に `pre-commit`が作成される


```:pre-commit
#!/bin/sh
# https://github.com/shyiko/ktlint pre-commit hook
git diff --name-only --cached --relative | grep '\.kt[s"]\?$' | xargs ktlint --relative .
if [ $? -ne 0 ]; then exit 1; fi
```


これでCommitのたびにktlintが走ります。
namespace付きのXMLファイルをpythonで読み取る方法

## 概要

PythonでXMLファイルの内容をXpathを使って読み取る場合にnamespace付きの場合は読み込むためにちょっとコツが必要だったのでその方法を記載します。
[こちら](https://jhalfmoon.com/dbc/2019/10/20/%E3%83%88%E3%83%9B%E3%83%9B%E3%81%AA%E7%96%91%E5%95%8F13-python%E3%80%81lxml%E3%80%81%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E5%90%8D%E5%89%8D%E7%A9%BA%E9%96%93%E3%81%A8xpath/)のページを参考にやってみた内容を記載しています。

## 環境

* Python 3.7.9
* lxml 4.3.0
    * lxmlについてはpipなどでインストールする必要があります。

## 処理方法

### NameSpace付きのXML

[特定検診・特定保健指導データ](https://www.ssk.or.jp/jigyonaiyo/tokuteikenshin/tokuteijoho/tokuteijoho_01_h30.html)の `特定健診（人間ドック）` のXMLを参考にやってみます。
こちらのXMLファイルの最初の部分に以下のような記述があります。

```xml
<ClinicalDocument xmlns="urn:hl7-org:v3"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="urn:hl7-org:v3 ../XSD/hc08_V08.xsd">
```
このような `xmlns～` のような部分があるとXpathを指定しただけでは読み取ることができません。
以下のコードを実行すると

```python
from lxml import etree
tree = etree.parse('kensin_dokku_tokutei.xml')
root = tree.getroot()
root.tag
```

`{urn:hl7-org:v3}ClinicalDocument`

のように`{urn:hl7-org:v3}` のnamespaceが設定されていることが確認できます。
この部分が邪魔をしてXpathを指定しただけでは取得できなくなっています。
一方[MicrosoftのサンプルXML](https://docs.microsoft.com/ja-jp/dotnet/standard/linq/sample-xml-file-typical-purchase-order)のxmlを読み込んでみると

`PurchaseOrder`
とnamespaceの部分がないことが確認できます。

### XMLの読み方

`lxml` を使って `xpath` を読むときにnamespaceを設定することで読み込むことができます。
以下のようにnamespaceを確認して

```python
tree = etree.parse('kensin_dokku_tokutei.xml')
root = tree.getroot()
root.nsmap
```

`{None: 'urn:hl7-org:v3', 'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}`

デフォルトのnamespaceに適当な値を設定します。
ここでは `x` としています。

```python
mynsmap={}
mynsmap['x'] = root.nsmap[None]
mynsmap['xsi'] = root.nsmap['xsi']
```
`mynsmap` のdictを引数に渡すことで以下のように結果を確認できます。

```python
tree.xpath("/x:ClinicalDocument/x:participant/x:associatedEntity/x:id/@extension", namespaces=mynsmap)
```
`['18100001001']`

Attribute を読むときは上記のように `@` で属性を指定することで取得できます。
テキストの情報を取る時は `text`を指定することで取得できます。

```python
result=tree.xpath("/x:ClinicalDocument/x:component/x:structuredBody/x:component[1]/x:section/x:text/x:list/x:item[1]", namespaces=mynsmap)
result[0].text
```

`'身長 162.3 cm'`

### XMLPathの確認方法

余談ですがXMLファイルのXpathの確認方法も記載しておきます。

1. FireFoxでXMLファイルを開き `右クリック→調査` をクリックして調査用のウィンドウを開きます。
1. Xpathを確認したい項目を探して `右クリック→コピー→Xpath` をクリックすることでクリップボードにコピーされます。
1. `/` の部分を↑で指定したnamespaceの値に変更します。(上の例では `/x:` )
1. attributeの部分は `/` のみにしておきます。