OmniAICreator/Qiita-1.07M huggingface dataset:
はじめてのVue.js

# 概要

社内の技術共有会で使用したもの。 
自分の勉強も兼ねつつ、Vueを触ったことない方向けに作成したものです。

# What's Vue.js ?

- jsのフレームワークのひとつ
    - 他だとAngular, Reactあたりが有名
- プログレッシブフレームワークである。
    - モノリシックではないので、開発レベルに合わせて段階的に導入することが可能
- ECMAScript5対応ブラウザで使用してね
    - 骨董品みたいなブラウザで使用するのは厳しいです
    - せめてIE9から ~~IE8以下? 知らない子ですね~~

# Hello World

```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title> わくわくVue </title>
<!-- 公式公開されているVue.js を読み込む -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>

    <div id="app">
        <p>{{ message }}</p>
        <button v-on:click="displayMsg">Click!!</button>
      </div>

<script>
const app = new Vue({
  el: '#app',
  data: {
    message: ''
  },
  methods: {
    displayMsg : function () {
      this.message = "Hello World!!";
    }
  }
})
</script>

</body>
</html>
```  
上記htmlを実行すると味気ないボタンが出ます。ボタン押下で「こんにちは世界」。

# 上記コードについて

```js
const app = new Vue({
  el: '#app', // 1
  data: {
    message: '' // 2
  },
  methods: {
    displayMsg : function () { // 3
      this.message = "Hello World!!";
    }
  }
})
```
### js側
- 1 : el
    - html上でVueインスタンスの管理下に置く要素。セレクタで指定。
- 2 : data
    - Vueインスタンスがもつプロパティ
    - v-bind, v-model等でバインディングされるデータを保持
- 3 : methods
    - Vueインスタンスが保持するメソッド
    - イベントのハンドリングを行う際に使用。
    - `methods`オブジェクト下に`メソッド名 : 関数`で定義。
    - **アロー関数**には気を付けろ、、、

```html
<div id="app"> // 1
<p>{{ message }}</p> // 2
<button v-on:click="displayMsg">Click!!</button> // 3
</div>
```
### html側
- 1 : id="app"
    - Vueインスタンスで管理下に置いた要素。
- 2 : {{ message }}
    - データバインディングの対象となる項目。今回はappインスタンスのmessageとバインディング。
    - Mustache構文(二重中括弧)で記載すること。
- 3 : v-on:click="displayMsg"
    - `v-`で始まる特別な記法をディレクティブと呼ぶ。属性値の変化があったときに作用する。
    - 今回の`v-on`はdomイベントの受け取りを実施。`:`の後に記述されたイベントに対しバインディングする。
        -`v-on:click`でクリックされた時に`displayMsg`メソッドを実行。
    - `v-on:click`は`@click`と略すことも可能。

# その他の主なVueのディレクティブ
### v-text
> 任意の文字列オブジェクトを指定要素に展開する  

```html 
<span v-text="msg"></span>
```
```html
<span>{{msg}}</span>
```
は両方同じ

### v-html
> `<span>hoge</span>`みたいな文字列を単なる文字列ではなく生htmlとして展開したいときに使用する  
> 脆弱性とかを生むものでもあるのでご利用は計画的に  

### v-show
> 評価式に応じて指定要素のCSSプロパティ`display`に作用する  

```html
<div v-show="hoge">ほげ</div> <!-- hogeがtrueなら表示 -->
```

### v-if, v-else, v-if-else
> 評価式に応じて指定要素を描画するか決定する  
**v-showと違って要素すら描画しない!!** 用途に合わせて使い分けるのが吉。  

```html
<div v-if="hoge">  <!-- hogeがtrueなら描画 -->
  ほげ
</div>
<div v-else-if="fuga">  <!-- fugaがtrueなら描画 -->
  ふが
</div>
<div v-else> <!-- hoge,fugaがfalseなら描画, v-if, v-else-ifの直後でない場合は認識されないです -->
  not ほげふが
</div>
```

### v-for
> 配列、オブジェクトを元にループを実行し要素を複数回描画する  

```html
<html>
<ul id="example">
  <li v-for="hoge in hoges">
    {{ hoge }} <!-- ほげ１、ほげ２がリスト形式で描画される -->
  </li>
</ul>
<script>
const hogeVue = new Vue({
  el: '#example',
  data: {
    hoges: ['ほげ１', 'ほげ２']
  }
})
</script>
</html>
```


# 所感
関わっている案件で使用していますが、ちゃんと使い分けとか考えてみると面白いと感じました。
次回の社内共有会ではコンポーネントやライフサイクルあたりを話そうかなあと思ってます。~~僕の知識が足りなくて今回の社内共有会でうまくまとめられなかったのは内緒~~
これからもぼちぼち頑張ろうと思います。

# 参考

[Vue公式様](https://jp.vuejs.org/v2/api/)
[とほほ様](http://www.tohoho-web.com/ex/vuejs.html#v-text)
ハードリンクとシンボリックリンク

ネストの深いディレクトリにアクセスしやすくなる。シンボリックリンクは最強最高！
# 最強最高lnコマンド!!!
Macだったらエイリアス、Windowsだったらショートカット。便利なこいつらをLinuxではリンクを貼るといい、`ln`コマンドで再現できます。
こんな感じ

```bash

~$ ls
Desktop  Documents
~$ touch Documents/test/test2/test3/hoge.txt
~$ ln Documents/test/test2/test3/ -s test3
~$ cd test3
~/test3$ ls
hoge.txt

```

無駄に深層にあるディレクトリの`test3`に簡単にアクセスできているのがわかります。
##lnコマンドでリンクをはろう
lnコマンドで貼れるリンクには以下の2種類があります。

- ハードリンク
- シンボリックリンク

###ハードリンク
エイリアスやショートカットと違い、一つのファイルに複数の名前を付けるようなイメージで扱われるのがハードリンクで,
オプション無しのlnコマンドで生成できます。

```bash
~$ ln file1 file2
```

file1とfile2は、名前違いで同じデータを参照しており、どちらもオリジナルデータです。最後の1つのハードリンクが消えて初めて参照しているデータが削除されます。

ちなみにディレクトリのハードリンクは作れない。
###シンボリックリンク
こいつは例でも見せた見慣れた挙動を見せます。`-s`オプションをつけたlnコマンドで生成できます。

```
~$ ln -s file1 file2
```
これでfile1のシンボリックリンクとしてfile2が作られました。シンボリックリンクは、lsコマンドを用いると水色にハイライトされます。(環境による)

ハードリンクと違いfile2にはfile1のアドレスが保存されているだけだので、file1が別のディレクトリに移動したり削除されたりすると使えなくなります。(リンクが壊れる)

シンボリックリンクはディレクトリでも作れてとても便利なので、ハードリンクよりよく使われるぞ

####あとがき
lsコマンドのハイライト機能は正確には`ls --color=auto`の機能なのでaliasに設定されていなければハイライト入らなかったりする。
いっちばん最初の例とか絶対見にくいってわかってるんだけどどうもこれ以上にいい例が浮かばなかった...
StandardShaderを含むVRMモデルをランタイムロードできない

#概要
StandardShaderを含むVRMモデルをランタイムロードできない例と対策を記載します。

#例
ビルドに含めたシーンにStandardShaderが使われているオブジェクトが一つも無いと、ビルド物にStandardShaderが含まれないようです。VRMを使ったツール的なアプリだと空シーンにモデルだけ読むといった作りになるので、忘れちゃうかもしれません。（私は忘れてました。

#確認
UniVRM的にはStandardShaderは「UniVRMで使えるシェーダー」だそうですので、対応しとくのが正解だと思われます。https://vrm.dev/univrm/shaders/univrm_shaders/

#対策
StandardShaderが付いたオブジェクトを追加して、非表示にしておきます。
※もっと良い方法がありそうです。

#参考
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ビルドするシーンにスタンダードシェーダのオブジェクトが一つも無いから、スタンダードシェーダがそもそも含まれて無くて？読み込めないという、「そりゃそうね……」という状態でした。（画像はスタンダードシェーダの箱を無駄に置いてビルドした状態で、手前から全std混std全MToon <a href="https://t.co/ZrrUKyOsEx">https://t.co/ZrrUKyOsEx</a> <a href="https://t.co/kPZzOc3cl5">pic.twitter.com/kPZzOc3cl5</a></p>&mdash; 120 (@120byte) <a href="https://twitter.com/120byte/status/1199279781079965696?ref_src=twsrc%5Etfw">November 26, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【Rails】provideとyieldを使ったページタイトルの設定【Rails Tutorial 3・4・5章まとめ】

##各ページのビューにprovideを記述
```app/views/static_pages/home.html.erb
<% provide(:title, "Home") %>
<h1>Sample App</h1>
```

##appilication.htmlのtitleにyieldを記述

```app/views/layouts/application.html.erb
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
  </head>
```

##ページタイトルに対するテスト
```test/controllers/static_pages_controller_test.rb
  def setup
    @base_title = "Ruby on Rails Tutorial Sample App"
  end

 test "should get home" do
    get static_pages_home_url
    assert_response :success
    assert_select "title", "Home | #{@base_title}"
  end
```

assert_selectを使って、titlesセレクタがページタイトルと一致することを確認する。
ページタイトルの重複部分はsetup内の変数@base_titleに入れておく。

~ここから4章~
##full_titleヘルパーを作成
rootであるhomeビューでは、アプリケーション名のみをタイトルに表示したい。
そのため、homeビューではprovideは不要である。
しかし、この場合タイトルが「 | Ruby on Rails Tutorial Sample App」となり、余計な｜が入る。
これを修正するためにページタイトルを返すfull_titleヘルパーを作成する。

```app/helpers/application_helper.rb
module ApplicationHelper

  # ページごとの完全なタイトルを返す。
  def full_title(page_title = "")
    base_title = "Ruby on Rails Tutorial Sample App"
    if page_title.empty?
      base_title
    else
      page_title + " | " + base_title
    end
  end

end
```

```app/views/layouts/application.html.erb
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
  </head>
```

変数page_titleの初期値を空にしておき、provideからくる引数yield(:title)が与えられなければ、base_titleのみを表示する。
与えられれば、｜を追加して、完全なタイトルを表示する。
(ちなみに、empty?メソッドの末尾の?は、論理値を返すメソッドであることを意味する)

homeビューからはprovideを消しておく。

```app/views/static_pages/home.html.erb
<h1>Sample App</h1>
```

「home」という文字はもうタイトルには無いので、テストを修正しておく。

```test/controllers/static_pages_controller_test.rb
  test "should get home" do
    get static_pages_home_url
    assert_response :success
    assert_select "title", @base_title
  end
```

〜ここから5章〜
##full_titleヘルパーのテスト
タイトルに誤字などがないか、正しく機能しているかどうかをテストする。

applicationヘルパーにあるfull_titleヘルパーはそのままではテストで使えないので、includeを使ってテストで使えるようにする。

```test/test_helper.rb
class ActiveSupport::TestCase
  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
  fixtures :all
  # Add more helper methods to be used by all tests here...
  include ApplicationHelper
end
```

```test/helpers/application_helper_test.rb
require 'test_helper'

class ApplicationHelperTest < ActionView::TestCase
  test "full title helper" do
    assert_equal full_title,         "Ruby on Rails Tutorial Sample App"
    assert_equal full_title("Help"), "Help | Ruby on Rails Tutorial Sample App"
  end
end
```

asseet_equalは第一引数と第二引数が等しいかどうかを確認するために使用する。

ところで、test/helpers/application_helper_test.rbは自動で生成されないようである。
:nth-of-type()をクラスに対して指定した時の挙動

めっちゃ特殊な動きをします。
例えば`.content:nth-of-type(2)`という指定をした場合、
`container`というクラスを持った要素と**同じ階層にある要素を全て洗い出し**、もし2番目の要素が`container`というクラスを**持っていたら**スタイルを適用する
という動きをします。

何を言ってるかわからないと思うので、以下に例を挙げます。

##例1
```html:html
<div>
  クラスなし
</div>
<div class="container">
  1つ目のcontainer
</div>
<div class="container">
  2つ目のcontainer
</div>
```
```css:css
.container:nth-of-type(2){
  background: yellow;
}
```
###出力
同階層の2番目の要素が`container`クラスなのでスタイルが適用されます。
<img width="503" alt=" 2019-11-26 20.06.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244893/a48be704-8601-a320-6b4c-0ab0c49330e3.png">

##例2
```html:html
<div>
  クラスなし
</div>
<div class="container">
  1つ目のcontainer
</div>
<div class="container">
  2つ目のcontainer
</div>
```
```css:css
/*  odd = 奇数 */
.container:nth-of-type(odd){
  background: yellow;
}
```
###出力
同階層の奇数番目の要素のうち、`container`クラスを持つのは3番目だけです。
<img width="503" alt=" 2019-11-26 20.09.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244893/0538d6a9-a828-8d9f-8c2b-2f190598babc.png">

##例3
```html:html
<p>同階層のP要素</p>
<div>
  クラスなし
</div>
<ul>
  <li>同階層のリストの子要素</li>
  <li>同階層のリストの子要素</li>
</ul>
<div class="container">
  1つ目のcontainer
</div>
<div class="container">
  2つ目のcontainer
</div>
```
```css:css
.container:nth-child(5){
  background: yellow;
}
```
###出力
同階層の5番目の要素が`container`クラスを持つので、スタイルが適用されます。
<img width="503" alt=" 2019-11-26 20.17.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244893/890e1bf3-0182-f5b2-d051-787b696dd19a.png">

##まとめ
変な動きをするので気をつけて！
[Azure] TerraformでのWindows OS設定(Custom Script Extension)記法メモ

[以前、TerraformでのLinux OS設定についてまとめましたが](https://qiita.com/VA_nakatsu/items/fa94c0c7c4763abd4ab6)、今回はWindows OSの設定手順です。Windowsの場合も、いくつかやり方はあるようですが、VM拡張機能(Custom Script Extension)を使うのが分かりやすいと思います。

# 1) インストーラとPowershellスクリプトの準備

インストールするアプリケーション(msiやexe)と、実際のインストールを行うPowershellをストレージアカウントに準備しておきます。ストレージアカウントの「ファイアーウォールと仮想ネットワーク」設定で、VM展開先のサブネットを設定しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/72a0ee3d-ee8f-a6d4-b0a5-55f3096dc087.png)

ストレージに適当なコンテナを作成し、インストーラとPowershellスクリプトを配置しておきます。インストーラはWebから直接取得しても構いませんが、ここでは例として、全てストレージアカウントに置いておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/6b503643-f2ae-7a02-d9c5-b74032e11c2f.png)

Powershellスクリプトには、アプリケーションをサイレントインストールする処理を並べておきます。

```powershell:init_test.ps1
msiexec.exe /i /passive node-v12.13.0-x64.msi
msiexec.exe /i /passive azure-cli-2.0.76.msi
.\WinMerge-2.16.4-x64-Setup.exe /VERYSILENT /ALLUSERS
```

サイレントインストールするためのオプションは、アプリケーションによって違う場合もあるのでそれぞれ調べる必要があります。ここで例にしているWinMergeの場合は `WinMerge-2.16.4-x64-Setup.exe /?` を実行すると表示されました。

# 2) terraformファイル(tfファイル)準備

VM拡張機能は、単独のリソースとして記載します。settings にファイル(準備したファイルのフルパス)と実行するPowershellを設定します。

```terraform
resource "azurerm_virtual_machine_extension" "tf_win_vm_extension" {
    name = "myWindowsVmExtension" # 拡張機能名(好きに付けてよい)
    location = "Japan East"       # リージョン(VMと同じにする)
    resource_group_name  = "${azurerm_resource_group.tf_name_resource_group.name}" # リソースグループ(名前で参照)
    virtual_machine_name = "${azurerm_virtual_machine.tf_name_vm1.name}"           # 仮想マシン(名前で参照)
    type = "CustomScriptExtension"  # 拡張機能の種類(Custom Script Extension)
    publisher = "Microsoft.Compute" # 拡張機能提供者(Microsoft)
    type_handler_version = "1.9"    # 拡張機能バージョン(実際にインストールしてみて最新バージョンを確認)

    # settings：VMにダウンロードするファイル(準備したファイルのフルパス)と実行するPowershellを設定
    settings = <<SETTINGS
    {
        "fileUris": [
            "https://xxxxxxdemo001.blob.core.windows.net/pstest1/init_test.ps1",
            "https://xxxxxxdemo001.blob.core.windows.net/pstest1/node-v12.13.0-x64.msi",
            "https://xxxxxxdemo001.blob.core.windows.net/pstest1/WinMerge-2.16.4-x64-Setup.exe",
            "https://xxxxxxdemo001.blob.core.windows.net/pstest1/azure-cli-2.0.76.msi"
        ],
        "commandToExecute": "powershell -ExecutionPolicy Unrestricted -File \"init_test.ps1\""
    }
    SETTINGS
}
```


# 3) 実行結果確認

terraform実行後、VMにログインし、インストールされていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/262e4986-6e67-a699-cbd5-d860cf0a041f.png)

azコマンドはスタートメニューに出てこないのでコマンドで確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/70ddbda4-b8ff-7b8c-ef8c-ac82d0a46e19.png)

拡張機能で実行されたファイルは `C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.9.5\Downloads\<数字>` に置かれているので、異常があった場合の確認で使えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/ee381a82-9f74-e327-1790-43119d381a81.png)

# 参考資料

-[Terraform - azurerm_virtual_machine_extension](https://www.terraform.io/docs/providers/azurerm/r/virtual_machine_extension.html)
【Docker／Kubernetes】今夜勝ちたいKubernetes概要

この投稿ではインストールを求めたりばかげた呪文を入力させたりはしない。

コンテナオーケストレーションシステムである"Kubernetes"。
dockerを覚えたうえでなぜそんなものまで覚えなければならないのか、
現在まで勉強した結果を私なりにまとめよう。

（途上につき、間違いなどあれば申し訳ありません。ご指摘いただけると幸いです）

# なぜKubernetesが必要か
一言でいえば、**運用、特に複数台のホストにまたがるサービス運用において課題が出るから**と言えます。

dokcer-composeによる複数コンテナを管理でローカルの開発環境についてはほぼ問題はないと思います。
しかし、これらは基本的に開発マシンなどといった1つのホスト内での話です。

実運用においては例えば以下のような課題を考慮し、複数ホスト間での連携も必要となってきます。

- ロードバランシング
- デプロイ時のダウンタイム
- オートスケーリング
- 死活監視（ホスト内のコンテナについて）

しかし、その構築は非常に複雑なものとなります。

こういった複数ホスト、コンテナ間の連携や、サービス実運用に必要な機能をもたらすのがKubernetesとなります。

### 読み飛ばしてもいいところ
>例えばオートスケーリングについて考えてみます。
nginx、phpアプリ、mysqlコンテナが一つずつ稼働しているホストがあり、そのスケールが必要になったとします。
このホストそのものを単純にスケールしてよいものでしょうか？

>効率的な運用を考えれば、ホストを増やしたうえでそれぞれのホストにどうコンテナをデプロイするか考える必要が出てきそうです。

>死活監視についてもそうです。ホストそのものならまだしも、
ホスト内で動いているコンテナすべての死活監視、および必要に応じた自動起動を自前で構築しようとすると難しいのではないでしょうか。

# 構成
以下大体の構成。デプロイメントあたりから脳が若干受付拒否をしだす。

- クラスタ：以下に挙げるdockerホストなどのリソース集合体
    - マスターノード：管理サーバ
    - ノード（Node）：実際にコンテナがデプロイされるホスト
    - ネームスペース（NameSpace）：クラスタ内の仮想的なクラスタ
    - ポッド（Pod）：コンテナの集合（同一ポッド内のコンテナはノードを跨がない）
    - レプリカセット（ReplicaSet）：ポッドの複製・管理
    - デプロイメント（Deployment）：レプリカセットの世代管理
    - サービス（Service）：ポッドの集合＆ポートなどの通信規約（書いて字の如くこの単位で一つのサービス）
    - イングレス（Ingress）：サービスの公開＆ルーティング

という感じです。フワッと理解できたら今日はもう優勝して大丈夫です。
python 継承について

##継承
継承とはあるクラスを元にして新たなクラスを作ること
**class 新しいクラス名(元となるクラス名):**と書く事で他のクラスを継承して新しいクラスを定義することができる
このときの元となるクラスを**親クラス**、新たなクラスを**子クラス**と呼ぶ
継承すると、子クラスは親クラスのインスタンスメソッドを引き継ぐ
子クラスは「親クラス内に定義されているメソッド」と「独自に定義したメソッド」の両方が使える
親クラスと同名のメソッドを子クラスで定義するとメソッドを上書きできる。これをメソッドの**オーバーライド**という
オーバーライドすると子クラスで定義したメソッドが優先される
オーバーライドしたメソッドの中で**super()**とすることで、親クラスを呼び出すことができる
**super().メソッド名()**とすることで、親クラス内に定義されたインスタンスメソッドをそのまま利用することが可能
【Rails】generateとdbの元に戻し方【Rails Tutorial 3章まとめ】

##generate

```
  $ rails generate controller StaticPages home help
  $ rails destroy  controller StaticPages home help

  $ rails generate model User name:string email:string
  $ rails destroy model User
```
コントローラーの場合、コントローラー名のみでなくアクション名も指定する。
モデルの場合は不要。

##db
```
  $ rails db:migrate
  $ rails db:rollback
  $ rails db:migrate VERSION=0
```

rollbackで一つ前の状態に戻す。
VERSION=0で最初の状態に戻す。

##キャメルケースでコントローラーを生成

```
$ rails generate controller StaticPages home help
      create  app/controllers/static_pages_controller.rb
```

コントローラー名をキャメルケースで指定すると、自動でスネークケース（アンダーバーで繋がれた名前）になる。
UnityからVRChatが立ち上がらない時

#UnityからVRChatが立ち上がらない時にやること
UnityからVRChatへavatarやworldをアップロードする際にエラーが出たとき
この方法で解決できました．
###キャッシュとレジストリの削除
これだけで直りました．

①コマンドプロントを開く
　・windowsの検索欄に「cmd」と入力し「コマンドプロンプト」を右クリック
　・「管理者として実行」をクリック

②下記のコマンドを「enter」で実行する

```
rmdir /S /Q %USERPROFILE%\AppData\LocalLow\VRChat\vrchat && rmdir /S /Q %TEMP%\VRChat && REG DELETE HKCU\Software\VRChat\vrchat /va
```

③YESなので「y」を入力

これでダメだったときは他の方法を試す
参考URLへ

#参考
[VRChatが起動しない/SDKが動かない場合]
(https://vrchatjp.playing.wiki/d/VRChat%A4%AC%B5%AF%C6%B0%A4%B7%A4%CA%A4%A4/SDK%A4%AC%C6%B0%A4%AB%A4%CA%A4%A4%BE%EC%B9%E7)
TerraformとSAMでAWSリソースを用意する人のための実行環境をdockerで作るよ

下記をDockerfileとしてLinux上に用意してください。

```Dockerfile
FROM python:3.8 as baseimage

RUN pip install \
      awscli \
      aws-sam-cli

# terraformバージョン指定
ARG terraform_version="0.12.16"

WORKDIR /root/
ADD https://releases.hashicorp.com/terraform/${terraform_version}/terraform_${terraform_version}_linux_amd64.zip ./
RUN unzip /root/terraform_${terraform_version}_linux_amd64.zip -d /usr/bin/ \
&& chmod +x /usr/bin/terraform

# --------------------------------------------------
FROM python:3.8-alpine3.10

# pip installed commands
COPY --from=baseimage /usr/local/bin/aws* /usr/local/bin/
COPY --from=baseimage /usr/local/bin/sam /usr/local/bin/
COPY --from=baseimage /usr/local/lib/python3.8/site-packages /usr/local/lib/python3.8/site-packages
# terraform
COPY --from=baseimage /usr/bin/terraform /usr/bin/

USER root

RUN apk upgrade

## 使用コマンド
RUN apk add \
      vim \
      less \
      jq \
      git \
      groff

# JST化
RUN apk --no-cache add tzdata \
&&  cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
&&  apk del tzdata
```

下記コマンドでビルドします。
`docker build -t awssamterraform . --no-cache`

下記コマンドでコンテナの中に入ります。
`docker run -it awssamterraform ash`
Ajax通信で403エラーになる

Ajax通信が403エラーで返ってきていた原因の調査にとても時間を取られたので、備忘録として残します。

## 環境
- php: 7.1.30
- Laravel: 5.4.36
- Webサーバー: Apache 2.4

## 返ってきていたエラー
Ajaxでデータを更新するフォームで、送信したのにうまく更新されていない
->Laravelのログを見てみる
->ログには何も出ていない
->Chromeのコンソールで確認した結果、以下のエラーが返ってきていました。

```
PUT https://xxx/yyy/zzz 403 (Forbidden)
```

Ajax通信が403エラーでうまく動作していません。なぜかアクセス禁止の扱いを受けてしまっています。

## 調査
- Apacheのエラーログの確認

Laravelのログに何も出ていない->そこまで処理が来ていないということなので、Apacheのエラーログを確認することにしました。(ここまでに結構な時間がかかってしまいました)

Apacheのエラーログを確認すると、以下のエラーが出ていました。

```
[Thu Nov 21 19:42:57.735794 2019] [authz_core:error] [pid 22270] [client xx.yyy.zzz.nn:12345] AH01630: client denied by server configuration: /home/xxx/public_html/public/xxxxxx, referer: https://xxx/yyy/zzz
```

とりあえず

```
AH01630: client denied by server configuration
```
のエラー文言で検索してみるも、"アクセス制限の記述方法がApache2.2と2.4で変わっている"系の記事ばかりで、解決に繋がるようなめぼしい情報は見つかりませんでした。
とりあえずApacheの設定をどこか変更するのだろうと、闇雲に設定ファイルの中を覗き回っているうちに、1日が終わってしまいました。

---
ところで、最初にChromeのコンソールで確認したエラー文言は

- PUTで送信して403のエラー

というものでした。
もしかしてPUTメソッドが禁止されているのでは??
と自分で思いついたわけではなくヒントをいただいたので、該当箇所を確認することに。

```
 /etc/httpd/conf.d/userdir.conf

<Directory "/home/*/public_html">
    AllowOverride FileInfo AuthConfig Limit Indexes
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
    Require method GET POST OPTIONS
</Directory>

```

↓これ

```
Require method GET POST OPTIONS
```

**PUTは許可されていませんでした。**

## 解決
PUTではなくPOSTを使えばいいということがわかったので、Apacheの設定を変更せずともエラーを解消することができました。

- ルーティングのメソッド変更

```php
Route::put('/xx/{xxx}/xx/{xxx}', 'SomethingApiController@somethingUpdate')
```
↓

```php
Route::post('/xx/{xxx}/xx/{xxx}', 'SomethingApiController@somethingUpdate')
```
---
- Ajax時のメソッド変更

```javascript
type: "PUT",
```
↓

```javascript
type: "POST",
```
CodeBuildのチュートリアルをやったまとめ


CodeBuildのtutorialをやったまとめ。

## やってることはこんなこと。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406130/10e61c1b-3a2d-490a-169a-ee9e729bf5ef.png)


## buildspec.ymlを作成する。

* buildspec.ymlはCodeDeployのappspec.ymlファイルと同じくビルドの設定を記述するファイル。
* S3に限らず、リポジトリのソースディレクトリのルートに配置する。
* S3以外ではzipにしてはいけない。

参考）[buildspec.ymlの書き方](https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-spec-ref.html#build-spec-ref-syntax)

```yaml:buildspec.yml
version: 0.2

phases:
  install:
    runtime-versions:
      java: corretto11
  pre_build:
    commands:
      - echo Nothing to do in the pre_build phase...
  build:
    commands:
      - echo Build started on `date`
      - mvn install
  post_build:
    commands:
      - echo Build completed on `date`
artifacts:
  files:
    - target/messageUtil-1.0.jar
```

`artifacts`はビルド結果をどこに何て名前で保存するかを指定している。
ABC146 感想

#AtCoder Beginner Contest 146 に参加しました
普段はコンテストに参加→復習で終わってしまいますが、コンテスト中の考察を記録に残したいと思い、記事を書くことにしました。（いつまで続くかは不明）

##問題A - Can't Wait for Holiday
愚直に実装しました。

```A.py
S = input()

if S == "SUN":
    print(7)
elif S == "MON":
    print(6)
elif S == "TUE":
    print(5)
elif S == "WED":
    print(4)
elif S == "THU":
    print(3)
elif S == "FRI":
    print(2)
else:
    print(1)
```

##問題B - ROT N
文字をアスキーコードに変換する方法を知らなかったので、
Google先生に聞いて`ord()`と`chr()`を知りました。

対象の文字を`0～25`で表し、N回ずらすためNを加え、26で割った余りを求めます。
最後に `ord("A")` を加えることで大文字のアルファベットのアスキーコードに戻します。
これを各文字に対して行うことで答えが求まりました。

```B.py
N = int(input())
S = input()

new_s = []
for c in S:
    new_s.append(chr((ord(c) - ord("A") + N) % 26 + ord("A")))

print("".join(new_s))
```

##問題C - Buy an Integer
初めにNについて全探索を行いましたが、TLEでした。（そりゃそう）
PyPyなら通るのでは(?)と思いさらにTLEを重ねてしまいました。
途中で「条件を満たす中の最大値」を求めるには二分探索が使えると気づき、
通すことができました。

1つの方法に固執し過ぎて二分探索に至るまでに30分を掛けてしまったのは反省。

```C.py
a,b,x = map(int, input().split())

left = 0
right = 10**9 + 1
while right > left + 1:
    n = (left + right) // 2
    if a * n + b * len(str(n)) <= x:
        left = n
    else:
        right = n

print(left)
```

##問題D - Coloring Edges on Tree
全くダメでした。
グラフ問題は見た瞬間に拒否反応が出てしまうので、どこかでしっかり勉強したいと思いつつ中々手を付けられていません...

何か良い学習教材ありませんかね？？

## まとめ
早く緑になりたい！
文字が入った画像をpythonで作る（日本語）

# 背景
そんなにない

# 作業
- fontファイルの場所を調べる

```command
$ fc-match -f "%{file}\n" FreeMono 
/System/Library/Fonts/ヒラギノ丸ゴ ProN W4.ttc
```

- 画像作る

```python
from PIL import Image, ImageDraw, ImageFont

font = ImageFont.truetype("/System/Library/Fonts/ヒラギノ丸ゴ ProN W4.ttc", size=60)

def make_image(n):
    im = Image.new("RGB",(300,100),"blue")
    draw = ImageDraw.Draw(im)# im上のImageDrawインスタンスを作る
    draw.text((10,20), f"自由記述欄{n}", font=font)
    im.save(f"./freetext{n}.jpg")

for i in range(0,50):
    make_image(i)
```

- jupyter notebookで表示したかったら

```
from IPython.display import Image, display_png
display_png(Image('./name1.jpg'))
```

# 成果物
![name46.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223104/d3426506-1434-f260-f788-4c6eb5bb2913.jpeg)

![freetext1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223104/315dc6f2-c9d8-59fc-12bf-fbd01c37e87a.jpeg)

# 参考
- https://qiita.com/agajo/items/90a29627e7c9a06ec24a
- https://qiita.com/knknkn1162/items/77999450c59db915ab87
- https://github.com/python-pillow/Pillow/pull/682
pre-commit時にphp-cs-fixierを走らせる

作業者それぞれ書き方にブレがあるとウガーってなりますよね。
コミット時にphp-cs-fixierを走らせて強制的にfixするようにします。


## pre-commitのファイルを作成します

リポジトリの.gitディレクトリの中にあるpre-commit.sampleファイルをリネームコピーします。

```bash
cp .git/hooks/pre-commit.sample .git/hooks/pre-commit
```

## pre-commitファイル

pre-commitファイルに下記を記述します。

```sh
#!/bin/sh

# php-cs-fixerを適用してからコミットします

if git rev-parse --verify HEAD >/dev/null 2>&1
then
  against=HEAD
else
  # Initial commit: diff against an empty tree object
  against=$(git hash-object -t tree /dev/null)
fi

# If you want to allow non-ASCII filenames set this variable to true.
allownonascii=$(git config --bool hooks.allownonascii)

# Redirect output to stderr.
exec 1>&2

# 終了コード
IS_ERROR=0

# 区切り文字を改行のみにする
IFS=$'\n'

for FILE in `git diff --cached --name-only --diff-filter=d | grep .php`; do
  if php -l $FILE; then
    php-cs-fixer fix $FILE
    git add $FILE
  else
    IS_ERROR=1
  fi
done

if [ $IS_ERROR -eq 1 ] ; then
  echo syntax error was detected. please correct.
fi

exit $IS_ERROR
```

fixする対象は作業した(差分のある)ファイルです。
phpのsyntaxなどでエラーが出た場合は別途メッセージが表示されます。
GitHubのアカウント名を変更した後のcommitまで

# GitHubのアカウント名を変更した
makkimakiに変更しました．

## 当然，プッシュできなくなった
github上にリポジトリを作成し

git remote add origin https://github.com/[変更前アカウント名]/intro_git.git

などとターミナルに打ち込み，

```
$ git push -u origin master
```
としたところ
```
remote: Invalid username or password.
```
となりました．

よって参考記事にある通り

```
$ git remote set-url origin https://github.com/makkimaki/intro_git.git
$ git push -u origin master
```

と連続し，

```
Username for 'https://github.com': makkimaki
Password for 'https://makkimaki@github.com': 
```
と立て続けに聞かれるので，上から「アカウント名」，「GitHubパスワード」を入力．

```
Enumerating objects: 42, done.
Counting objects: 100% (42/42), done.
Delta compression using up to 4 threads
Compressing objects: 100% (36/36), done.
Writing objects: 100% (42/42), 15.36 KiB | 2.19 MiB/s, done.
Total 42 (delta 13), reused 0 (delta 0)
remote: Resolving deltas: 100% (13/13), done.
To https://github.com/makkimaki/intro_git.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
```
となり無事解決．プッシュされました！



### 参考記事
【意外と簡単】Githubのアカウント名を変更する手順まとめ【やり方】
https://blogenist.jp/2018/03/06/2548/#i-4
(webpack)"contains invalid source map"の原因


```
WARNING in hoge.js contains invalid source map
```
の原因について。

`{terser,uglifyjs}-webpack-plugin`のオプションでsource mapが有効化されていない時に発生するので

```diff
const TerserPlugin = require("terser-webpack-plugin");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
  ...
  plugins: [
    new TerserPlugin({
+     sourceMap: true,
      ...
    }),
    // もしくは
    new UglifyJsPlugin({
+     sourceMap: true,
      ...
    })
  ],
  ...
};

```

とすることでこの問題が解決します。
[UE4]ナビメッシュの自動更新を抑える

普段エディタで作業中、アクターを動かすとナビメッシュは自動で更新されます。
![nav600.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/14452dd6-9cdb-ecd5-f036-3ada51c1f80f.gif)
更新忘れを防げるのでありがたい機能ではあるのですが、
レベルが広くなってきてナビメッシュが複雑になってくると、
右下にBuilding Navigationがずっと出てPCは重くなるし、困ることがありますよね。
<img width="289" alt="2019-11-26_19h21_55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/8ccb6dae-d691-4d46-eb67-fcdc1ad9a921.png">
そこで、エディター設定「Update Navigation Automatically」のチェックを外すことでナビメッシュの自動更新を切ることができます。
<img width="951" alt="2019-11-26_19h22_34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/9c20639d-49e6-70f3-9c85-d638551f494d.png">
#####やったー！快適！
![nav2600.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/f35ba2bf-dc63-d187-00d8-cd67c114633b.gif)

レベル編集後は、手動でナビメッシュをビルドするのをお忘れなく。
<img width="912" alt="2019-11-26_19h32_26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/085396b0-2382-aac4-046d-dc14a358a072.png">
docker-composeを使って3分でDjangoをデプロイ

既に作成されたプロジェクトの場合でも対応可能な形のdocker-composeを作成しましたので、仕様を記事にまとめます。

**GitHub上にHowtoUseを書いておりますのでどうぞ→[GitHub](https://github.com/tken2039/django-nginx-gunicorn-docker)**

（DBをデフォルトのsqliteから変更してる場合はまた別の設定が必要になると思います・・・ごめんなさい）

デプロイ環境はDjango＋Nginx＋Gunicornとなります。

## 概要
使い方は上記にリンクを用意しておりますGitHubのREADMEを参照ください。

簡単なデプロイを実現させるために、次のようなディレクトリ構成で動作するDjangoデプロイ用のdocker-composeを作りました。

```
django-nginx-gunicorn-docker/
      ├ nginx/
      │　└ project.conf
      ├ django/
      │  ├ Dockerfile
      │  ├ requirements.txt
      │  └ [DJANGOPROJECT]
      │     ├ manage.py
      │     ├ …
      │     └ [PROJECTNAME]
      └ docker-compose.yml
```

コンテナでプロジェクトを丸ごとマウントして動作させます。
では設定ファイルをみていきます。

## docker-compose
利用するコンテナはDjangoアプリケーション用のもの（Gunicornもこの中で動作）と、リバースプロキシの役割を果たすNginxのコンテナです。

```docker-compose.yml
version: '3'
services:
    django:
        build: ./django
        expose:
            - "8000"
        networks:
            - nginx_network
        volumes:
            - ./django:/code
        hostname: django-server
        restart: always
    nginx:
        image: nginx
        ports:
            - "80:80"
        networks:
            - nginx_network
        depends_on:
            - django
        volumes:
            - ./nginx/project.conf:/etc/nginx/conf.d/default.conf
        restart: always
networks:
    nginx_network:
        driver: bridge
```

djangoのvolumesのところで、プロジェクト環境をマウントしています。もしコンテナ起動後に編集を行なっても、コンテナをrestartさせることで反映されます。

また、nginxコンテナの方では80:80でポートフォワーディングをしているので、ローカルホストの80番ポートにアクセスが来た際はnginxコンテナの方に受け渡されます。

特段トリッキーなことはしていませんので、composeの説明は終わりです。

## Dockerfile
djangoディレクトリにあるDockerfileの説明です。

```
FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/
WORKDIR /code/MYPROJECT
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "MYPROJECT.wsgi:application"]
```

python3系のイメージを利用します。6行目のRUNでDjangoとGunicornをダウンロードしています。（あとついでにPostgres用のライブラリもダウンロードしていますが使っていません。ごめんなさい）

```requirements.txt
Django==2.2.7
gunicorn==19.9.0
psycopg2
```

ちなみにDjangoのバージョンですが、当初2.0を指定してGithubにあげた所くっそ怒られました。（セキュリティ警告がいっぱい来た。GitHubのBotから怒りのプルリクもきた。）

## project.conf
nginxの設定ファイルです。

```project.conf
upstream django {
  server django:8000;
}

server {
    listen  80;
    server_name :localhost;

    location / {
        proxy_pass http://django;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

upstreamでリクエストの送信先を指定します。送信先はコンテナのlocalhostとなっています。また、ここで命名したものをプロキシパスの設定で用います。

serverのほうではlistenするポートとプロキシの設定を行なっています。


## さいごに
ポートの設定でどはまりしました。。。
みなさんも気をつけましょう；；
Rで「ひらがな」を「カタカナ」に変換する関数を作った。

# はじめに
##注意
`base`に`chartr`という関数があるみたいです。これを用いれば簡単に変換できます。詳しくは返信欄まで。情報ありがとうございました！
##要旨
　~~探しても見つけられなかったので関数を作りました。~~注意にあるように既に関数があります。ということで車輪の再開発になりますが、メモのため残しておきます。題名にある通り、ある「ひらがな」を引数として渡すと、その「カタカナ」を返してくれる関数です。といってもその中身は単純で、入力された文字を文字コードに直して、値をいじり、その文字コードを文字に直しているだけです。単語や文章に対して使う場合は、`str_replace_all`関数と一緒に使います。一文字ずつ読み取るので遅いと思います。
# 方法
## 実行環境
- Rstudio version 1.2.1335
- R version 3.5.3
- Windows 10

## 関数概要
まず、入力された文字(ひらがな一文字)を文字コードに変換します。そして、その文字コードを10進数に変換して96を足して対応するカタカナの文字コードにします。最後に、文字に変換してリターンします。
## コード
``` .R
# ライブラリ
library(stringr)
library(stringi)

# 関数
hira2kata <- function(hira){
  kata_code <- 
    hira %>%
    stri_escape_unicode() %>% 
    str_replace(fixed("\\u"), "0x") %>% 
    strtoi() %>% 
    "+"(96) %>% 
    as.hexmode()
  
  kata <- 
    str_c("\\u", kata_code) %>% 
    stri_unescape_unicode()
  return(kata)
}

# 使用例
hira2kata("あ")
# 単語での使用例
str_replace_all("あいうえお", "\\p{Hiragana}" ,hira2kata)

```
## コード説明
コードを順番に説明していきます。
###ライブラリ
　使用するライブラリは、`stringr`と`stringi`です。
###文字から文字コードへの変換
　まず、`stri_escape_unicode()`で文字列を文字コードに変換しています。この関数は、先頭に`\\u`を伴ったUTF-16文字コードを文字列で返します。
###文字コード（16進数）から10進数への変換
　次に、`str_replace(fixed("\\u"), "0x")`で、`\\u`にマッチしなかった部分をそのままに、マッチした部分を`0x`に置換します。これは次の10進数への変換のための処理です。数字列先頭の文字列を`0x`とすることにより、16進数であることを明示できます。
　そして、`strtoi()`で16進数を10進数に変換します。
###10進数での計算
　次に、`"+"(96)`で96を足します。その理由は、UTF-16文字コード対応表を見てみると分かります。「あ」の文字コード`3042`「ア」の文字コードは`30A2`です。つまり、16進数で60を足せば、ひらがなからカタカナに変換できるということです。16進数で60は、10進数では96です。
###10進数から16進数への変換
　`as.hexmode()`で16進数に戻します。
###文字コードから文字への変換
　ここでパイプ処理を切って新たなオブジェクトを使用していますが、次の`str_c()`を使うにあたって第一引数にオブジェクトを入れる方法が思いつかなかったので、断腸の思いでこうしています。
　`str_c("\\u", kata_code)`でUTF-16文字コードに`\\u`を結合させます。そして、`stri_unescape_unicode()`で文字コードを文字列に変換します。

以上です。

## 使い方
　この関数だけでは一文字しか処理できないので、`str_replace_all()`のような置換メソッドを使います。パターンにひらがなの正規表現を、置換する部分に作った関数を渡せば、単語や文章に対して「ひらがな」を「カタカナ」に変換することができます。

# 注意点
一文字ずつ読み取るので、とても遅いと思います。
# 最後に
こうすればもっと効率的に分かりやすくかけるよ。こうすればもっと早くなるよ。このメソッドを使ったほうがいいよ。この類のライブラリが既にあるよ。などがあったらご一報いただけたら幸いです。
macアドレスをランダムに変える方法

#前提条件
homebrewが使えること。

#インストール
homebrewを使ってインストールする。
```
brew install acrogenesis/macchanger/macchanger
```

#macアドレスをランダムに変える。
```
macchanger -r en0
```

#注意
最初はwifiが繋がりにくくなりますが、しばらく経つと繋がります。

この方法で変更したmacアドレスは、再起動すると元に戻ってしまいます。
その場合は、もう一度上記のコマンドを行ってください。
【JavaScript】画像のファイルタイプをバイナリレベルで判別する方法

# リンク
[こちらを参考](https://kinsentansa.blogspot.com/2013/04/javascript.html)
すごく勉強になりました。

## 概要
1. readAsArrayBufferでバイナリに変更
2. Uint8Arrayを使って変換 `new Uint8Array(binary)`
3. 初めの10個分を読む
4. 1文字ずつ16進数列に変換 `toString(16)`
5. 変換した文字列がどの画像形式か判別する
(小ネタ) emotion (emotion-js) + TypeScript で型安全にテーマ付きの styled.** を使いたくなったら

## 解決したいこと

下記のような、自前のテーマを持っていたとして、

```typescript
export type OurTheme = {
  ourSuperAwesomeColor: string
}
```

emotionで、下記のようなstyled-componentなコードを書きたい場合、型エラーでコンパイルが通りません。

```typescript
// TypeScript「 `({theme})` の型がわかりましぇ〜ん！」
const AwesomeHeading = styled.h1`
  color: ${ ({theme}) => theme.ourSuperAwesomeColor };
`
```

さて、どうすればいいでしょうか。

## キャストは嫌だ

もちろん、下記のようなダサいことをすれば通るんですが、コードのそこかしこに同じような ~~ゴミ~~ キャストを撒き散らすと考えると微妙です。

```typescript
const AwesomeHeading = styled.h1`
  color: ${ ({theme}) => (theme as OurTheme).ourSuperAwesomeColor };
`
```

## あなた知らないの？ `styled.**` は実は省略可能な型変数を持っていて、省略されている型変数の2番目をきちんと指定すればテーマの型を指定できるよ？

なるほど…？？

```typescript
const AwesomeHeading = styled.h1<ここに入れる型がわからない, OurTheme>`
  color: ${ ({theme}) => theme.ourSuperAwesomeColor };
`
```

`ここに入れる型がわからない` の型変数（本来はpropsの型を示すところでした）の記載を省略したいのですが、[**TypeScriptでは残念なことに今のところは省略可能な任意の位置の型変数を省略したままにする術がありません。**](https://github.com/microsoft/TypeScript/issues/10571)

あー困った困った…

（ちなみに型がわからないからといって `any` とか入れると、一気に型チェック無しの世界に入るので、やめたほうがいいです。）

## 仕方ないので、自前で `styled` を用意する

ということで、私は自前で `styled` を用意することにしました。

```typescript
// `@emotion/styled-base` から import しないように注意
import styled, { CreateStyled } from "@emotion/styled";

// 既存の `styled` をそのまま別の型として見るだけの変数を宣言。
export const ourStyled: CreateStyled<OurTheme> = styled;
```

上記のようなものを用意しておくと、下記のように書けます。

```typescript
const AwesomeHeading = ourStyled.h1`
  color: ${ ({theme}) => theme.ourSuperAwesomeColor };
`
```

これでスッキリ！
Tkinterのfiledialogでキャンセルするとエラーになる対策

# 動作環境
Windows10
PyCharm
Python3


# 起こった現象
tkinter.filedialog.askopenfilename でダイアログを開いた際に、キャンセルを押すとエラーになって、そのままPyCharmが不安定になってします。OSの再起動を何度かやりました。


## コード
``` python3
import tkinter.filedialog
import os
import sys

root = tkinter.Tk()
file_type = [("", "*")]
current_dir = os.getcwd()
root.withdraw()
file_name = tkinter.filedialog.askopenfilename(filetypes=file_type, initialdir=current_dir)
if file_name == "":
    sys.exit(1)
current_dir = current_dir.rsplit("\\", 1)[1]
file = "." + file_name.split(current_dir)[1]
print(file)
```
キャンセルした際に、if file_name == "" の条件に一致して、sys.exit(1)が実行されます。
これをやらないと、キャンセルをした際に、エラーになります。if文をコメントアウトして確認してみて下さい。

追記）半年ぶりにこのページを見て↑のコードを何故載せたのか分からなくなりましたが、↓のコードで書いているように return "break" をすれば、エラーは出なくなります

## インスタンスメソッドの場合の例
``` python3
    # クラス内のインスタンスメソッドです。
    # ボタンを押した際に、ファイルダイアログが開くメソッドの例です。
    def button_action_hoge(self, event):
        file_type = [("", "*")]
        current_dir = os.getcwd()
        file_name = tkinter.filedialog.askopenfilename(
            filetypes=file_type, initialdir=current_dir)
        if file_name == "":
            return "break"
        current_dir = current_dir.rsplit("\\", 1)[1]
        # file = fileName.split(current_dir)[1]

        # file = g_init_data.pathImageFolder + fileName.split(currentDir)[1]
        file = "." + file_name.split(current_dir)[1]
        return "break"
```
return "break"の""はボタンの表示が元の状態に戻る魔法のおまじないです。
if file_name == "" のところがないと、PyCharmが固まってしまうくらいの状態になります。
【リベンジ】全員登壇！FlashTalk大会 #1 に行く前日の話

# 目的

- 題名の登壇イベントに行く前夜でワクワク感と緊張感がすごいので文字にする。

# 参加させていただくイベントの内容

- 参加者全員が登壇するイベントである。
- 一般参加枠だとイベント中に「自己紹介」と「技術的な話題」の二つについて１分で話す。
- １分をすぎたら強制終了されるが、短いなら1分経つまで告知などをしてもOKである。
- 発信力を鍛えるためのイベントである。

# 参加させていただくイベントの詳細ページ

- connpassのリンクを下記に記載する。  
[【リベンジ】全員登壇！FlashTalk大会 #1](https://engineers.connpass.com/event/153594/)

# エンジニアの登壇を応援する会って？？

- エンジニアにアウトプットによって成長することを伝え、支援を行うコミュニティである。
- 主に「勉強会やカンファレンスに登壇すること」「ブログや技術書を執筆すること」などの内容の支援を行なっている。
- エンジニアの登壇を応援する会の各リンクを下記に記載する。  
connpasグループ: [エンジニアの登壇を応援する会](https://engineers.connpass.com/)  
Twitter: [エンジニアの登壇を応援する会](https://twitter.com/engineers_lt)  
参加ガイド: [README](https://esa-pages.io/p/sharing/10407/posts/320/0bb2faf43a53b3226482.html)  

# 登壇の準備

- イベント参加者は事前にGoogleスライドに自分のスライドを追加する。
- 「自己紹介」と「技術的な話題」についてスライドを作成した。
- 話す内容の心の準備をした。
- 「技術的な話題」とあるが、難しいことを話すわけではなく「発信者が技術と思えばそれは技術的な話題になる」ということなのでハードルは低かった。

# 筆者がなぜこのイベントに参加する気持ちになったのか(ほぼ自分用メモ、すいません)

- 転職が完了したら体験談などを登壇してお話したいのでその時までの経験や練習のため。
- そもそも登壇することに興味があった。
- 誰がおっしゃったか忘れたが、「2択の選択を迫られた時にメンタル的にリスクがある方をあえて選ぶべき(経験や技術的な話に限る)」にしたがって参加を決めた。
- 1分なら自分にもできそうだった。
LinuxでHDDの温度を計る

#はじめに
ubuntuでcpuの温度を取得する方法を調べていたらhddの温度も
取得できるらしいことを知った

環境は Ubuntu18.0.4だがCentOS系や他ディストリも基本的にやり方は同じ

#hddtempを使う
```
$ apt install hddtemp
(省略)
$ hddtemp /dev/sda
/dev/sda: HGST HTS545025A7E380: 35°C
```
hddtemp の引数でドライブを指定。*ドライブを指定しないと使えない
/dev/以下は環境により読み替えが必要。

#inxiを使う
```
$ apt install inxi
(省略)
$ inxi -xD
Drives:    HDD Total Size: 250.1GB (16.8% used)
           ID-1: /dev/sda model: HGST_HTS545025A7 size: 250.1GB temp: 35C
```

#psensorを使う(GUI)
これはCPUの温度計測でつかったものと同じやつ

```
$ apt install psensor
(省略)
$ psensor
```
![Screenshot from 2019-11-26 18-55-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367760/fdca4799-ef27-3fcb-07e0-bdbb02f8c42e.png)

#参考にしたサイト
https://linuxconfig.org/obtain-hard-drive-temperature-information-using-linux
https://www.2daygeek.com/view-check-cpu-hard-disk-temperature-linux/
cronでpipenv環境上ジョブを実行する

# 背景
動作確認などで、pipenv環境上のジョブをcron経由で実行する

# やり方

対象の環境で pipenv shell を打った時の以下の出力をコピペしておく

```sh

$ pipenv shell
> Launching subshell in virtual environment…
> . /<path>/<to>/<virtualenv>/bin/activate
```

上記の `. /<path>/<to>/<virtualenv>/bin/activate` を含めた以下のようなcronで動く

```
42 * * * * cd /path/to/project/;. /<path>/<to>/<virtualenv>/bin/activate;python main.py
```

# 参考

[How to run a cron job with pipenv?](https://stackoverflow.com/questions/48990067/how-to-run-a-cron-job-with-pipenv)
iTerm2 ことはじめ for fish

まっさらな iTerm2 があります。

最初に iTerm2 の設定をしましょう。

Preferences->General->Window とすすみ Adjust window when changing font size をオフにします。
Preferences->Profiles->General の Working Directory で Reuse previous session's directory にします。


つぎに brew をいれます。 それ経由で fish いれます。

```
$ brew install fish
```

```
$ chsh -s /usr/local/bin/fish
```

したいのですが、non-standard などのエラーがでるので、 `/etc/shells` に `/usr/local/bin/fish` を追記してから chsh をうちます。

これで、シェルの変更まで出来ました。

次に色を変えます。

```
$ fish_config
```

でテーマを選んだり。

iTerm の設定から、color を import したりしましょう。

背景は `232323` で color preset は Tomorrow Night を選びがちです。

その次は prompt を変えましょう。これも `fish_config` でいけます。ほんとうに :fish: って便利です。

ぼくは好みにの形があるので、以下のように書いておきます。

```bash:.config/fish/functions/fish_prompt.fish
function fish_prompt
    set prompt (set_color green)(prompt_pwd)
    set git (set_color blue)(__fish_git_prompt)
    set symbol (set_color normal)"\$ "
    echo -n $prompt
    echo $git
    echo $symbol
end
```

このあとは、fisher を入れてそれ経由で z をいれます。

```
$ curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish
$ fisher add jethrokuan/z
```

z 便利すぎます。

fzf をいれます。

```
$ brew install fzf
$ fisher add jethrokuan/fzf
```

つぎにターミナル立ち上げ時に表示される

```
Last login: Tue Nov 26 19:15:44 on ttys001
Welcome to fish, the friendly interactive shell
```

を消します。

```
$ touch .hushlogin
$ set fish_greeting
```

あとは fish Awesome なやつを眺めてカスタマイズしてみてください。
https://github.com/jorgebucaran/awesome-fish

:fish: :fish: :fish: :beer: thanks!
docker でwordpress環境構築

忘れないように覚書。
【参考サイト】https://tech.recruit-mp.co.jp/infrastructure/post-11266/

## docker-composeを準備
https://docs.docker.com/compose/wordpress/
こちらの公式のdocker-composeを利用します。

リポジトリを任意の名前で作成し、その中で
docker-compose.ymlを作成します。

```docker:docker-compose.yml
version: '3.3'

services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
       WORDPRESS_DB_NAME: wordpress
volumes:
    db_data: {}
```
中を上記のように編集します。

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

で起動します。そうすれば
http://localhost:8000 でログインできます。

##　テーマを作る

```
docker exec -it ドッカー名 /bin/bash 
```
上記のコマンドでdockerの中に入り、
作りたいテーマのファイルを用意。
exitでdockerから抜ける。

```
cd /var/www/html/wp-content/themes/
mkdir mytheme
exit
```

リポジトリにもテーマ用のファイルを用意。

```
mkdir mytheme
```

そしてdocker-composeの中にvolumesの記述を以下のように書き足せばOK！
これでホストマシンのテーマファイルがドッカー内のテーマファイルにマウントされます。

```
    wordpress:
        image: wordpress:latest
        ports:
            - "9000:80"
        depends_on:
            - db
        environment:
            WORDPRESS_DB_HOST: "db:3306"
        env_file: .env
        volumes:
            - ./mytheme:/var/www/html/wp-content/themes/mytheme
```

{ホスト側の相対パス}:{コンテナ側の絶対パス}　という書き方になっています。


書き換えた後に再度`docker-compose up`すれば、テーマの中を自由にいじることができるようになります！


##　おまけ　操作上必要になるコマンド

ドッカーの停止

```
docker-compose stop
```
Rails Deviseでユーザー編集を現在のパスワードを入力しないで更新する


個人の備忘録


 #背景
railsでユーザー登録のためにdeviseを使った簡単なプリを作成中に編集画面で
現在のパスワードを入れないで更新できないかと考えたため。


#環境

rails 5.2.3
ruby 2.6.3


#まずdeviseを用いた際のルーティングを確認

```rails:config/routes.rb
devise_for :users, controllers: {
        registrations: 'users/registrations',
        sessions: 'users/sessions'
      }
```

特に問題なさそう


#registrations_controller.rbに下記を記載

```rails:registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  before_action :authenticate_user!
 
  protected

  ＊この部分を記載
  def update_resource(resource, params)
    resource.update_without_current_password(params)
  end

  (省略)

end
```

受けとったリソースを、update_without_current_passwordメソッド(Userモデルに後で実装します)で
パスワード抜きで更新できるようにし、引数にparamsを指定してリソースの中身を更新しています。



#User モデルに update_without_current_password を実装

一個前でregistration_controllerに自力で定義したメソッドを使えるようにモデルに定義していく



```rails:models/user.rb
def update_without_current_password(params, *options)
    params.delete(:current_password)　　　＊params.delete(:current_password) で current_password のパラメータを削除。

    if params[:password].blank? && params[:password_confirmation].blank?　　　＊パスワード変更のためのパスワード入力フィールドとその確認フィールドの両者とも空の場合のみ、パスワードなしで更新できるようにするためです。

      params.delete(:password)
      params.delete(:password_confirmation)
    end

    result = update_attributes(params, *options)
    clean_up_passwords
    result
  end
```


#あとはビューのフォームを消すだけ

パスワードのフォームを削除して終了






参考にしたサイト
[Devise でユーザーがパスワードなしでアカウント情報を変更するのを許可](https://easyramble.com/user-account-update-without-password-on-devise.html)
[Deviseでパスワードの入力無しでユーザー情報の更新をする方法](https://kossy-web-engineer.hatenablog.com/entry/2018/11/06/102047)
「 LoadError: dlopen(〜): Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib」と表示された場合の解決法

railsで新しいアプリのDBを作成するべく`rake db:create`をしたところ、以下のエラーメッセージが表示。

```
LoadError: dlopen(/Users/（ユーザー名）/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/mysql2.bundle, 9): Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib
  Referenced from: /usr/local/opt/mysql@5.6/lib/libmysqlclient.18.dylib
  Reason: image not found - /Users/（ユーザー名）/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/mysql2.bundle
/Users/（ユーザー名）/projects/（アプリ名）/config/application.rb:7:in `<top (required)>'
/Users/（ユーザー名）/projects/（アプリ名）/Rakefile:4:in `require_relative'
/Users/（ユーザー名）/projects/（アプリ名）/Rakefile:4:in `<top (required)>'
/Users/（ユーザー名）/.rbenv/versions/2.5.1/bin/bundle:23:in `load'
/Users/（ユーザー名）/.rbenv/versions/2.5.1/bin/bundle:23:in `<main>'
(See full trace by running task with --trace)
```
`rake routes`などのコマンドでも同様のエラーが出るため、ニッチもサッチも行かず困った事態に。

`bundle doctor`を行いエラーが出たgemを再インストールしたり、 `openssl`を再インストールしてもダメ。

色々と探した結果、最終的にはこちらの記事の対処法で上手く行きました。
https://github.com/kelaberetiv/TagUI/issues/86

```
brew update && brew upgrade
```
でHomebrewとインストールしたパッケージ（Formula）のアップデートを実施。

改めて`rake db:create`をしたところDB作成に成功しました。他のコマンドもちゃんと実行できます。

直前にHomebrewで色々と入れたので、それが問題だったのかもしれません（node.jsが怪しい）。

同様のエラーが出た場合はご参考までにどうぞ。

----
参考にさせていただいた記事：brewのupdateとupgradeの違い
https://qiita.com/okhrn/items/aa71b066a525456550c0
（こちらの記事によれば`brew upgrade`だけで大丈夫かもしれません。)
SQL GROUP_BY ORDER_BY DATE_FORMATで日付を比較

```sql
記事数デイリー推移
select genre, DATE_FORMAT(`published_at`, '%Y-%m-%d') as date, count(id) from news where published_at>="2017-09-01 00:00:00" and status=10 GROUP BY date, genre ORDER BY genre, date
記事数マンスリー推移
select genre, DATE_FORMAT(`published_at`, '%Y-%m') as month, count(id) from news where published_at>="2015-01-01 00:00:00" and status=10 GROUP BY month, genre ORDER BY genre, month desc
```

####解説
[DATE_FORMAT]
format 文字列に従って、date 値を書式設定します。
次の指定子が format 文字列で使用されている場合があります。書式指定子文字の前には、「%」 文字を付ける必要があります。
データ復旧、デジタルフォレンジック手法の体験談（Android編）

前のCTF記事https://qiita.com/55momotara55/items/03ccd0e111b38061e6fc
はすごく簡単なADBサービスを利用してAndroidデバイスを侵入する手法なんです。
昨日も会社のインターンシップの同年生から「俺のスマホでやってみる？」聞いて、経済的な方面から考えると諦めしました（弁償の可能性無限大）。


ですから今日朝もう一度この模擬Androidをチェックする時、この中に面白いサービスを発見しました。
/system/xbinの中に**busybox**というツールが入ってます：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526362/46073b1f-347a-1bdc-a3d6-45f125bfd367.png)

**busyboxはLINUXの常用コマンドをAndroidデバイスに実行できるようなツールです。**

**フォレンジック原理**：busyboxをインストールしているANDROIDデバイスを**dd**コマンドを実行し、今後のデジタルフォレンジックの解析するため、現時点でのAndroidデバイスの**イメージファイル**を作り、遠隔OSにこのイメージファイルを転送します。

まずrootを取ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526362/7bf60264-15ed-58cc-bb80-72a305b2dae4.png)

mount命令を使い、誰かsystemを【mount】しているか、確認しましょう：（/dev/block/sda1です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526362/cfcbbf47-31e1-3098-fcb7-d3a0ded639ec.png)

**LISTENモード**を使います、**このAndroidデバイスは遠隔OSのコマンドを受け次第に8888ポートから/dev/block/sda1のイメージファイルを転送します：**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526362/3ec28218-deec-b8d8-b76d-69d433543696.png)


遠隔OSではターミナルを使い、8888ポートからのイメージファイルの転送を受けます：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526362/212616ae-4a9c-3131-fa74-b551717a05ac.png)
結果を確認します：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526362/ae680738-e8bc-eaee-856e-479b2c02f74f.png)


#このまま記事終えることではない
リアルな使用環境を考えると、Androidデバイスにbusyboxを入れる一般人は少ないでしょう。問題点は：
**１，なんのコマンド使ったら捜査対象デバイスにbusyboxを入れる？**
**２，コマンド嫌だから、どうすれば簡単に捜査対象デバイスのメモリを読み取る？**
**３，捜査対象デバイスを電源入り次第にデバッグモードを変更したい方法？**
２番の答えは（電子系出身）：
**物理手段：chip-off法：**ヒートガンを使い、フラッシュメモリをデバイスのマザーボードから取ります
、するとフラッシュメモリ読みとり専用設備を使います。
**要注意**：フラッシュメモリの耐熱温暖はほとんど低い（１００－１５０度以内？）、ヒートガンの使い方が下手したら破損の可能性が非常に高いです。
３番の答えは：**JTAG：**直接マザーボードで配線し、強制的にデバイスをデバッグモードに変更させます（メーカーの設計図あれば助かります）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526362/5a59ec7c-17e4-c36a-bee0-bb92384fd462.png)

１番の考え方：
**目標：busyboxを/system/xbinに書き込みます。**
１，従来、【READ-ONLY】のsystemファイルを書き込み状態にします。ここで```mount -o remount```を使います。非rootアカウントは```chmod```コマンドを使い、/system/xbinを読める状態にします。（非ROOTアカウントはxbinファイルを読めないから）
２，続いて、busyboxファイルをadb shellの```push```命令を使い、xbinに書き込みます。
３，現在、/system/xbin/busyboxというルートが作られ、Androidのターミナルで```busybox-install```というコマンドを使い、Androidにインストールします。
４，busyboxすでに捜査対象デバイスにインストールされ、以後の流れはこの記事の一番上からやるでしょう。

今後YOUTUBEでビデオを作って詳しい操作方法を紹介したいと思います。
測域センサ UST-10/20LXの電源の入れ方

喜び勇んで北陽電機さんの測域センサ（[UST-10/20LX](https://www.hokuyo-aut.co.jp/search/single.php?serial=16)）を買ったものの、箱を開けて取り出した本体にはコードを束ねた端子とEthernetの端子がついているだけ。
![IMG_6095.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31194/addfb095-76d4-c886-50b0-80e224ee805c.png)

どうしたもんかと言うところで、タイミングよく北陽電機さんに電源の入れ方を教えていただいたのでその方法を残しておきます。

ちなみに「測域センサ」という言葉は北陽電機さんでの呼称で、一般的には「LiDAR（Light Detection and Ranging）」と言うそうです。

###本体以外に準備するもの
そもそも電源が必要です。
日本の家庭用電源の電圧は***交流100V***です。それに対してUST-10/20LXは***直流12Vか24V***なので、それに対応した変換アダプタを用意します。
それとワニ口クリップからアダプタに接続できるコードが必要で、今回はせんごく電子商会さんで下記を購入しました。

1. [SG21-MC φ2.1DCジャック・ミノムシクリップ付きケーブル](https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=3DRK-TFEL#)
2. [Li Tone Electronics co.ltd. (L.T.E)　LTE10UW-S2-BS01 ACアダプター 12V1Aφ2.1センタープラス](https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-5FVK#)

![IMG_6093.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31194/be60f56f-5115-f588-9d60-a17a0814a06a.png)
中身はこんな感じです。
![IMG_6094.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31194/eeb42fa5-5c61-04b8-c171-331929802d9a.png)


### 本体と電源の接続
まずは下図の緑の破線部分をハサミで切ってしまいます。
白い端子部分に対応した部品もあるそうなんですが、簡易的なもののようなので切り取ります。
![IMG_6096.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31194/e11cd41b-d90d-8a17-5f7e-5685cf800ead.png)

電源として使用するのは***青と茶色のコード***です。
青と茶色のコード以外は太いケーブルにテープで固定しちゃいましょう。
青と茶色のコードは先端のカバーだけを2cmくらい切って中の***金属線の束を出して捻り固めて***おきます。
![IMG_6099.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31194/7acae631-fd82-08ba-1d80-98bec61f6279.png)

そして***青いコードを黒のクリップ（ー）、茶色のコードを赤のクリップ（＋）***で挟みます。これ間違えると大変です。
さらに***赤と黒のクリップの金属部分同士が触れるとアダプタやセンサが故障する***らしいので、しっかりとカバーしておきましょう。
![IMG_6100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31194/1fcd2cd9-d575-6f08-e383-1430c5c4d962.png)

電源アダプタを電源プラグに差し込むと本体前面のLEDが青く光ります。これで電源の接続は完了です。

![IMG_6102.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31194/91e8dfbb-0d66-357f-7f44-527ec82c6bc5.jpeg)

### PCと本体との接続
最終的にEthernetの端子をPCに接続してセンサーの視覚化ツール（ダウンロードには会員登録が必要）を起動します。
視覚化ツールでセンサのIPアドレス（デフォルト192.168.0.10:10940）を指定して接続、下記の様に緑色のエリアが表示されれば接続成功です。

![cap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31194/55c3ed5d-1bc6-4e56-7265-96f3319b25ce.png)


これで素敵な測域センサライフを送れますね😀
【laravel】 DBの存在するテーブルとカラムとカラムの型を取得するあとdoctrine/dbalでjson型が扱えない件

## 環境

MySQL 5.7
Laravel 5.8

## 存在するテーブル

```php
tableNames = [];
foreach (DB::select('SHOW TABLES') as $table) {
	$dbName = config('database.connections.mysql.database');
	$tableNames[] = $table->{'Tables_in_' . $dbName};
}
```

## 存在するカラムとその型
### 型を取得

```php

// 存在するカラムを取得
$columns = Schema::connection('mysql')->getColumnListing($tableName);

$columnTypes = [];
foreach ($columns as $column) {
	// カラムタイプを取得
	$columnTypes[$column] = Schema::connection('mysql')->getConnection()->getDoctrineColumn($tableName, $column)->toArray()['type'];
}
```

`int` の場合 `Doctrine\DBAL\Types\IntegerType` のようにとれる。
これはSQLの型とPHPの型をマッピングするクラス。

### 型判定

```php
if ($type instanceof Doctrine\DBAL\Types\StringType) {
	// ごにょごにょ
}
```

### json型でエラー

Doctrine DBALが2.4以下だとjson型がサポート外とのこと。
エラーが出るので以下のようにjson_arrayにマッピングさせると扱えるようになる。

```php

DB::getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('json', 'json_array');
```