OmniAICreator/Qiita-1.07M huggingface dataset:
Sequel Pro リモートDBへのSSH接続

# はじめに

Sequel Proを使用してWordPressなどのリモートDBへSSH接続する際のメモです。

DBクライアントが内部でどういった動きをしているのかを把握して
実際にCLIで確認しながら設定をします。

# SSHホストの内容を確認

```console
$ ssh ${ユーザー名}@52.196.***.** -i ~/.ssh/hoge.pem
```

もしくは

```console
$ cat ~/.ssh/config 
```

```config:~/.ssh/config
Host hoge-server
  HostName 52.196.***.**
  User ${ユーザー名}
```

```console
$ ssh hoge-server
```

# MySQLホストの内容を確認 (MySQLへログイン)

サーバーへログイン後..

```console
$ mysql -u ${ユーザー名} -h 127.0.0.1 -D ${データベース名} -p
Enter password:🔑
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/7e261f01-ff1b-428f-7cf7-2427daf3f802.png)

接続が成功しました👏

# 解説

## リモートサーバー内のMySQL情報

項目|内容
---|---
MySQLホスト|リモートサーバー内のMySQLホスト名を入力します※
ユーザー名|MySQLのユーザー名を入力します
パスワード|MySQLのパスワードを入力します
データベース|指定する場合はデータベース名を入力します
ポート|デフォルトは3306です

※localhostで指定した場合、TCP/IPを使用した接続ではなくソケットファイルでの接続になり
ポート指定のオプションが無視されるため、基本的には`127.0.0.1`で接続をします。

## リモートサーバーに接続するための情報

項目|内容
---|---
SSHホスト|ssh接続する先(リモートサーバー)のホスト名を入力します
SSHユーザー|ssh接続する先のユーザー名を入力します
SSHパスワード|パスワードを設定している場合は入力します※
SSHポート|ポートの指定がある場合は入力します

※`~/.ssh`配下にある鍵は自動的にcheckされます。

# 切り分けて考える

DBクライアントが内部でどういった動きをしているのかが分かると
例えば接続がうまくいかない際に
「そもそもリモートサーバーへのssh接続はできているのか？」
など、問題を切り分けて対処することができます。

SSHホストとSSHパスワード
MySQLのホスト名のみを入力して接続を試みてみます。
(MySQLのユーザー名とパスワードは、あえて入力しません)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/7a5b4257-714a-94c1-83b3-697df46587cf.png)

この状態で接続をすると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/b4a518b3-34b3-173d-08dd-357f450de218.png)

このように、エラー文に『MySQLの応答』が表示されるため
**リモートサーバーへのssh接続には成功している**
と、判断することが出来ます。
リダイレクト　標準出力と標準エラー出力は別々のチャネル

![スクリーンショット (414).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614211/6b4cfdf5-dc99-2692-305f-1b5309e6b9d8.png)

cat > /etc/hosts 
hostsの中身を表示

cat > /etc/hosts > output.txt
hostsの中身を output.txtファイルを作成して内容を記述
cat output.txt で内容が一致することを確認する

cat  /hoge > output.txt 
output.txt にエラーメッセージを書き込む（/hogeというディレクトリはないから）

結果は

![スクリーンショット (415).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614211/7e954782-5a96-eead-a2f1-9659bc2a2941.png)

エラーメッセージがoutput.txtに書き込まれずに表示されてしまった。

これは　「標準出力」と「標準エラー出力」が異なるチャネルを有しているからです。

標準エラー出力のリダイレクトを行いたい場合は　2>　という記号を使う

![スクリーンショット (416).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614211/8e3baef7-1b14-05d8-dea0-b55e6b658b6d.png)

ls /hoge 2> output.txt
こちらでは特に表示は出ない。

cat output.txt
output.txtの中身にエラーメッセージがリダイレクトされていることが分かる
rails newしたときにインストールしている最新のRailsバージョンでアプリが作成されない場合の対処法

`rails new`を実行したときにインストールしているRailsの最新バージョンでアプリが作成されず、どハマりしたので投稿します。

## はじめに
バージョンを指定せずに`rails new`すると、インストールしているRailsの最新バージョンでアプリが作成されます。
が、私が遭遇したのは`rails new`すると最新版ではなく、古いバージョンでアプリが作成されるという現象でした。しかもそのバージョンは`gem list`コマンドでも表示されないバージョンでした。。

## 問題の原因
先に原因を書くと、環境変数の設定に問題がありました。

`/usr/local/bin`が`/Users/user_name/.rbenv/shims`より先に定義されており、`$PATH`は先に書いたほうが優先されるため、`/usr/local/bin/rails`が使われたことが原因でした。
つまり、rbenvで管理されているRailsのバージョンではなく、macにインストールされているRailsが参照されていました。

```
$ echo $PATH
/usr/local/bin:(中略)/Users/user_name/.rbenv/shims:/Users/user_name/.rbenv/bin:
(以下略)
```

## 問題発生から解決までの流れ
### 起きたこと
新規のアプリを作成しようとして`rails new`コマンドをバージョン指定無しで実行したところ、インストールしている最新バージョン(6.0.3)ではなく、古いバージョン（5.2.3）で作成されました。

```ruby:Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.3.7'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.3'
（以下略）
```

Railsのバージョンを確認したところ5.2.3になっていたのですが、`gem list`コマンドで確認したバージョンには5.2.3は含まれていませんでした。

```bash

$ rails -v
Rails 5.2.3
```

`which rails`でRailsの実行場所を確認すると、`/usr/local/bin/rails`になっていました。こうなっていた原因は上に書いたとおり、環境変数でrbenvのパスより先に`/usr/local/bin/rails`が定義されていたためです。

```bash
$ which rails
/usr/local/bin/rails
```

蓋を開けてみると単純な問題だったのですが、一度gemをすべてアンインストールしたりと無駄なこともしてしまったので、同じ問題で困った方の助けになれば幸いです。

## 他に原因として考えられること
`rails -v`で存在しないはずのRailsのバージョンが表示されるときは、railtiesも疑わしい場合があるようです。
[Railsのバージョンがなんかおかしい時はrailtiesをチェック - かなりすごいブログ](http://blog.supermomonga.com/articles/rails/rails-version-railties.html)
VRoidの服をVCIで着替える

#概要

VRoidの服をVCIで着替えてみました。
inバーチャルキャスト

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">見た目だけは、ぽい感じになった気がします。 <a href="https://t.co/WUqeYTXQs1">pic.twitter.com/WUqeYTXQs1</a></p>&mdash; 120 (@120byte) <a href="https://twitter.com/120byte/status/1266662236468084736?ref_src=twsrc%5Etfw">May 30, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#バージョン
Unity : 2019.3.0f6
UniVCI : 0.27
UniVRM : 0.55
バーチャルキャスト : 1.9.2d

#Unity完結式の手動作成手順

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286581/438a3126-4be1-2f90-8983-71697a20b60b.png)

##準備

VRM取り込み
VRMのオブジェクトにVCI Objectを追加
不要メッシュ等の削除or透過（ホントは全て削除したい）
主要ボーンをVCI Objectの直下へ引っ張り出す

●主要ボーンのオブジェクトへ以下を追加
・VCI Sub Item
・Rigidbody
・VCI Attachable
・Box Collider

##全部位設定

●VCI Sub Item
・GrabbableをOnに設定
・ScalableをOnに設定
・Group Idを1に設定
※VCI Sub Itemは手動だと強制個別なので要気合

●Rigidbody
・Use GravityをOffに設定
・Is KinematicをOnに設定

●VCI Attachable
・Sizeを1に設定
・Distanceを0.05に設定

●Box Collider
・Sizeを0.1に設定
・Is TriggerをOnに設定

##個別部位設定

各VCI AttachableのElementを対応する部位ごとに設定

●ChestのBox Colliderだけ
・Centerを0, 0.1, 0に設定
・Sizeを0.2に設定
※この部位の大きさの違いが目立つので、調整しやすいように大きくしておく

●HandのBox Colliderだけ
・Sizeを0に設定
※着た後に強制選択状態になってしまうので対策

##luaコード

VCI ObjectのScriptsに以下を設定

```lua
local Attached = false

function onUse(use)
    local owner = vci.studio.GetOwner()

    -- 体幹
    SetAtt(owner, "Hips", "J_Bip_C_Hips", Attached)
    SetAtt(owner, "Spine", "J_Bip_C_Spine", Attached)
    SetAtt(owner, "Chest", "J_Bip_C_Chest", Attached)

    -- 足
    SetAtt(owner, "LeftUpperLeg", "J_Bip_L_UpperLeg", Attached)
    SetAtt(owner, "RightUpperLeg", "J_Bip_R_UpperLeg", Attached)
    SetAtt(owner, "LeftLowerLeg", "J_Bip_L_LowerLeg", Attached)
    SetAtt(owner, "RightLowerLeg", "J_Bip_R_LowerLeg", Attached)
    SetAtt(owner, "LeftFoot", "J_Bip_L_Foot", Attached)
    SetAtt(owner, "RightFoot", "J_Bip_R_Foot", Attached)

    -- 腕
    SetAtt(owner, "LeftUpperArm", "J_Bip_L_UpperArm", Attached)
    SetAtt(owner, "RightUpperArm", "J_Bip_R_UpperArm", Attached)
    SetAtt(owner, "LeftLowerArm", "J_Bip_L_LowerArm", Attached)
    SetAtt(owner, "RightLowerArm", "J_Bip_R_LowerArm", Attached)
    SetAtt(owner, "LeftHand", "J_Bip_L_Hand", Attached)
    SetAtt(owner, "RightHand", "J_Bip_R_Hand", Attached)

    Attached = not Attached
end

function SetAtt(owner, boneName, itemName, attached)
    local bone = owner.GetBoneTransform(boneName)
    local item = vci.assets.GetSubItem(itemName)
    if bone ~= nil and item ~= nil then
        -- 位置と回転の合わせ
        item.SetPosition(bone.position)
        item.SetRotation(bone.rotation)

        -- 脱着
        if attached then
            item.DetachFromAvatar()
        else
            item.AttachToAvatar()
        end
    end
end
```

#備考

VCI Attachableを有効にするには通常のColliderが必須（更にGrabbableOnも必須）
AttachToAvatarする時の位置合わせは同期が必要かと思ったけど、特に何もしなくても良さそう
服のサイズを着るアバターでVRM化してから作業すればサイズは丁度
素体側ではみ出やすい部位は透過すると良いかも
今回のバージョンではGetAvatarsによるゲストのTransform取得が動かない？（ので他の人に着せられない）
変換ツール作成予定→できた（https://120byte.booth.pm/items/2115099）
スクリプトからPrefabの生成。


```C#
using UnityEngine;

// 事前準備
// Resourcesフォルダを作成
// Resources内にPrefabsフォルダを作成

public static class Prefabs
{
    public static void Create(string prefabName)
    {
        var obj = Find(prefabName);
        Object.Instantiate(obj);
    }

    public static GameObject Find(string prefabName)
    {
        return (GameObject)Resources.Load($"Prefabs/{prefabName}", typeof(GameObject));
    }
}
```
BigQueryのウェブUIで宛先テーブルが指定できないとき

# はじめに

BigQueryを仕事で最近いじっていまして、ちょっとハマったのでそれについてのTipsです。

# 前提

BigQuery上で実行したクエリは、宛先テーブルというものが指定でき、クエリの結果を指定したテーブルに保存することができます。

以下のような「クエリの設定」というところから指定が可能です。
<img width="575" alt="スクリーンショット 2020-05-30 22.19.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147934/1ecb31ad-9ed4-da2f-ff33-babcb6342c48.png">

# 問題

あるときBigQueryのウェブコンソールでクエリを実行していたのですが、以下のようにクエリの設定を表示しても宛先テーブルの項目がなくなってしまいました。

<img width="573" alt="スクリーンショット 2020-05-30 22.22.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147934/0e4fd0b9-e37d-73ad-0bab-8462db65c71d.png">

# 原因

https://cloud.google.com/bigquery/docs/scheduling-queries?hl=ja

こちらのドキュメントに書いてありました。

> DDL または DML クエリを使用している場合:

> Cloud Console で、[処理を行うロケーション] または [リージョン] を選択します。処理を行うロケーションは、宛先テーブルを作成する DDL または DML クエリに必要です。
>従来の BigQuery ウェブ UI では、[Destination table] を空白のままにします。

試しに使っていた変数宣言の時に使用する`declare`文などのDDL（データ定義言語）を使用していたことが原因でした。まだサポート外ということなのでしょうか。

DMLの解説はこちら
https://cloud.google.com/bigquery/docs/reference/standard-sql/data-manipulation-language?hl=ja
DDLの解説はこちら
https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language?hl=ja

# 結論

BigQueryのウェブUIでDDL（データ定義言語）やDML（データ操作言語）を使用すると、宛先テーブルが指定できなくなるので、テーブル指定が必要な場合は使用しないようにするしかなさそう

まだデータ分析周りは素人なので、誤りなどあれば指摘いただければ幸いです。最後までご覧いただきありがとうございました。
DockerでCakePHP4.0.8さわってみました。(apach)

#はじめに
##今回githubの方にまとめる形をとってみました！！
手順まとめてあるので以下見てください！:relaxed:
https://github.com/sachiko-kame/docker_cakePHP

ちなみにDockerコマンド打てるところからお願いします！
打てない場合『困ったときは以下も』の一番上のリンクから行う形になるかんじです！
apacheとかあまりないような気がして今回載せました。





一応:

CakePHP 4.0.8 Strawberry 
php7.4
mysql8
docker ver3
Apache/2.4.38 (Debian) ←指定したわけでなくコマンドで確認したもの($ apachectl -v)

#工夫したところ
ボリュームするとコピーファイル消えるので、コンテナ中で作成したものをコマンドで移動すると言う方法を取りました。
コマンドで移動出来なかったものは手作業で移動しています。
apacheのファイルのみ移動すれば問題ないと思ったのですが本来入るべき場所にとあるもの全部移動した感じです。

<img width="428" alt="image5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133940/522c6421-43e8-5f8a-6a56-b7941433edcd.png">



#困ったときは以下も
全部自分の記事です！:relaxed:

[Dockerの大まかなイメージから自分が作成したものをDockerhubにあげて、インストールして実行まで](https://qiita.com/sachiko-kame/items/35e0cf07d117c3b92613)

[[Docker][apache][CakePHP]The requested URL was not found on this server.](https://qiita.com/sachiko-kame/items/e50cc399069edd5701fa)

[CakePHPハマったの対策](https://qiita.com/sachiko-kame/items/9b27781cf13ad13ce9dc)

[とりあえずhtmlの表示をDocker使って行う[apacheバージョン]](https://qiita.com/sachiko-kame/items/b91e47f0ad90ddc32498)


#最後に
テーブルの自動作成なぜかできなかったのですが普通にできたのでもし自動挿入に困っているかたいたらぜひみてください！！
https://qiita.com/sachiko-kame/items/0a4f335ab9b3b87c479c
GoogleSpreadsheetで多言語対応の翻訳ツールを作ってみる

##翻訳ツールが必要だ…
最近仕事で海外のエンジニアとやり取りしてるんだけど、先人達が残していったエクセル資産を有効活用できないのがつらい。Google翻訳で都度翻訳すればいいんだけど毎回やってるとキリがない…
それならドキュメント見るよりソースコードから仕様を読み解くぜって話になるんだけど思わぬ齟齬が起きたりしてやっぱり不便、ということで簡単に翻訳できるツールを自作してみる。

##GASで作ってみる
いろいろ調べたがExcelからいきなり翻訳するのはちょっとハードルが高そう…一方でSpreadsheetを使えばGoogletrancelate関数が使えるのでかなりハードルが低そう。Google翻訳のエンジンも使えるし翻訳の品質も（とりあえずは）文句なし。。。
Excel->SSに乗せ換えるのはやや面倒だが、Gdriveに放り込んでSSで開けば勝手に変換してくれるし…都度翻訳する手間に比べれば何でもない！！！
というわけでGoogleAppsScriptで書いてみた。

```javascript
function SheetTrancelate() {
  var TargetID = 'xxxxx';                                             //翻訳するSSのIDを取得
  var sourceLng = 'ja';                                               //翻訳前の言語コード
  var TranceLng = 'en';                                               //翻訳後の言語コード
  
  var ssTargetSheet = SpreadsheetApp.openById(TargetID);              //翻訳するSSを取得
  var sheets = ssTargetSheet.getSheets();				              //シート取得

  for(var i = 0; i < sheets.length; i++){						       //全シート分ループする
    var srcSheetName =  sheets[i].getName();					       //シート名取得
    var copiedSheet =sheets[i].copyTo(ssTargetSheet);                  //シートをコピー（翻訳後のシート）
    copiedSheet.setName(srcSheetName + '_' + TranceLng);               //翻訳後のシート名を変更
    
    for(var row = 1; row <= copiedSheet.getLastRow(); row++) {
      for (var column = 1; column <= copiedSheet.getLastColumn(); column++) {  //すべてのセルに対して翻訳を行う
        var range = copiedSheet.getRange(row, column);                  //セルを取得
        var stCellValue = range.getValue();                             //セルの値を取得
        if (stCellValue != '' && isNaN(stCellValue)){                   //セルが空白の場合と、数値のみの場合は翻訳しない
            range.setValue(LanguageApp.translate(stCellValue, sourceLng,TranceLng)) //翻訳実行
        }
      }
    }
  }
}

```

##めちゃくちゃ簡単だ…
今回、GASを書いたのは初めてだったけどJavascriptの要領で書けたしSheetの操作自体もめちゃくちゃ簡単。困ったらググればサンプルコードがわんさかあるし…
ほかにもGdriveとかDocumentとか、いわゆるGsuiteのアプリはGASで一通り自動化できるっぽいのでまた何か思いついたら自動化したい。。
[備忘録] iterm2インストールと設定

## これはなに
一言でいえば、iterm2インストールとカスタマイズの備忘録です。

## インストール

```bash:bash
$ brew cask install iterm2
```

## カスタマイズ
### iTerm2設定いじり

##### 任意のデスクトップ上にフルスクリーンで表示できるように  
iTerm2 > Preferences > General > Window > Native full screen windowsのチェックを外す

##### 新しいウィンドウの設定をフルスクリーンにする  
iTerm2 > Preferences > Profiles > Window > Settings for New Windows > Style='FullScreen', Screen='Screen with Cursor', Space='All Spaces'

##### HotKeyを設定
iTerm2 > Preferences > Keys > HotKey > Show/hide iTerm2 with a system-wide hotkeyにチェック

### Rictyインストール

```bash:bash
$ brew tap homebrew/cask-fonts
$ brew cask install font-ricty-diminished

# フォントのキャッシュファイルを更新
$ fc-cache -vf
```
iTerm2のpreference→Profiles→Textを選択
FontからRictyに変更
fontsizeを18に変更

## 参考文献
[Mac を買ったら必ずやっておきたい初期設定](https://qiita.com/ucan-lab/items/c1a12c20c878d6fb1e21)
[iTerm2のおすすめ設定〜ターミナル作業を効率化する〜](https://qiita.com/ruwatana/items/8d9c174250061721ad11)
[iTerm2のフォントを見やすく変更してみた](https://qiita.com/yu_haruchan/items/bc2fc9c55238002b6d18)
【AzuerAD】条件付きアクセスで社給PC以外のPC利用者は、Office365利用時に多要素認証を要求する

条件付きアクセスで　社給PC以外のPC利用者は、
Office365利用時に多要素認証を要求するように設定してみました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/6aab3d28-efd2-520b-1f0e-3d2150be9316.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/4ca5467c-9f9e-1683-c119-56b000f0074d.png)

社内PCと社給PCはintuneに準拠させておきます
（※社内は準拠しなくても可としました）

まずどこからアクセスさせてもMFA(多要素認証）するよう設定し、
社内(社内のGIP）からのアクセスは除外
intuneに準拠（社給PC）からのアクセスは除外
で設定してみました。
出向先は顧客のPCを利用しているパターンを想定し、顧客のPCを自社のintuneには参加させらないので、MFA(多要素認証）で対処することで、2要素認証を実現させています。

#条件付きアクセスの設定
今回はテスト用のユーザーを設定致しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/9579e092-9dc4-558c-64b5-11e11069ff9c.png)

対象アプリはOffice365にしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/15587aa6-cadc-b95a-3fba-839b9787cbf9.png)

デバイスの対象は以下に設定しています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/58d2adff-07e8-4c44-82c1-8120ad046dc8.png)

場所は対象を[すべての場所]にしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/e929bfb5-f9d9-820e-d843-5d470b934159.png)

場所の対象外を[自社用］を設定しました。
※自社用はネームドローケーションの設定で自社のGIP（グローバルIP）に設定しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/3a36d15b-3e2d-9226-dbba-dcf77a275ce7.png)

クライアントアプリは以下に設定しています。
ブラウザでもデスクトップアプリでもアクセスできるようにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/ca657681-0e23-2a0b-8d56-bb204dbe8354.png)

デバイスの状態を[すべてのデバイスの状態]にしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/a78540bb-0dcc-ad2e-ebb8-91a6c18fdb34.png)

デバイスの状態の対象外は以下に設定しています。
社給PCはintuneに準拠させているので　MFAからは外しています。
理由としては
ユーザーIDとパスワードを知っている+intuneに準拠した端末を持っている事により、2要素が成立しているからです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/493ce120-250e-c046-75d3-75dfbd01cb62.png)

許可は多要素認証を要求するにしました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480057/9aff02d3-0e63-955a-bf44-8072dc92ccad.png)

これで設定は完了です。
テストする前に、一度以下コマンドで更新トークンを失効しておきます。
更新トークンの失効方法はpowershellでAzureADにログインした後、
以下コマンドを実行します。

Revoke-AzureADUserAllRefreshToken -ObjectId （ここにユーザーのオブジェクトIDを記載）


その後テストしてみたら、Intuneに準拠していない社外PCからは多要素認証するように要求がきました
（多要素認証は電話を利用するパターンと、MicrosoftAuthenticatorを使うパターンがあります。）
これで出向先からのアクセスでも2要素認証でアクセスすることができました。

少しでも誰かの参考になればと思います(^^♪

次回はこれをベースに制御を増やしてみようと思います。
以上です。
C++11 + cmake プロジェクトへ組み込みしやすい SSL(TLS) ライブラリのメモ

## 背景

* レイトレーシングや機械学習, 暗号資産 wallet や miner, RDP 的画面転送アプリなどで, C++11 アプリで通信で SSL(TLS)のサポートをしたい.
  * Windows(MSVC, MinGW), macOS, Linux, Android あたりクロスプラットホーム対応必須 
* Android, MinGW などで cross compile するので, ビルドフラグの影響があると思うので, cmake(や meson などのナウでヤングなビルドシステム)で SSL ライブラリも一括ビルドしたい.
  * prebuilt とか, third party ライブラリだけ別ビルドは link 時などで問題がおおい(OpenSSL みたいに基本 C API だと, link 時あんまり問題はないかもですが)
  * SSL ライブラリを git submodule で追加するのを想定

## 組み込みしやすい SSL ライブラリ

ここでいう組み込みは, C++ アプリに組み込みやすいであって, ラズパイなど組み込み機器(IoT)で動かすという意味ではありません.

https://en.wikipedia.org/wiki/Comparison_of_TLS_implementations

を参考にし, 組み込みしやすいライセンス(Apache, MIT, BSD...)であることも考慮し,いくらか調べると, 以下に落ち着きました.

* OpenSSL : 本家. 1.x は OpenSSL ライセンス(Apahe, BSD ライク?). 3.0 から Apache 2.0
  * https://www.openssl.org/
* botan : BSD ライセンス.
  * https://botan.randombit.net/
  * BSD ライセンス. あんまり情報はないが機能は結構あるし ARM, POWER など対応もしっかりしている印象
* picotls
  * minicrypto と組み合わせることで小さくてよい. 
  * BSD ライセンス
  * 今回のようにとりあえずアプリにぺろっと SSL/TLS 機能追加したいのであれば, minicrypto で提供されている暗号化アルゴリズムで十分そう

BoringSSL は, ビルドに nasm(Windows), go とか Perl(!) が必須なので選択肢には入りませんでした.

s2n は結局は OpenSSL(libcrypto)に依存していました.

## OpenSSL

C です. コード古臭いし... configure(!) しかない(3.0 も同等).

まあでも Bitcoin core や miner などでみんな使っているから, なんとなく安心感あります.

CMake 対応してくれている方がいます. ありがとうございます.

https://github.com/janbar/openssl-cmake

とりあえず Linux native で問題なくビルドできるの確認しました.

こちらの viaduck 版は, cmake 外部コマンド呼び出し(i.e. configure を呼ぶ)で OpenSSL をビルドする版なので注意です!

https://github.com/viaduck/openssl-cmake

prebuilt 版ご用意いただいているので, 対応するプラットフォームが限られるのであればこちらでもいいかもしれません


## Botan

C++11 で BSD license. ナウでヤングそうな感じがありますが, 情報ほとんどないですね...

https://github.com/randombit/botan

Makefile しかない. 一部 Boost(asio)利用です.

Makefile を参考に, CMakeLists を書けばいけそうな雰囲気あります.

## picotls

C 実装.

cmake あります.

ファイル群はそんなに多くないので, 自前 CMakeLists 書いてもいいかもです.

Windows は VS ビルドしかなったので, MinGW ビルドご用意しました
(たぶん実際に動くはず)

https://github.com/syoyo/picotls/tree/mingw-build

https://github.com/syoyo/picotls/blob/mingw-build/WindowsPort.md

## まとめ

一実装だけ利用だと, どこかでハマったときにデバッグが面倒そうなので, OpenSSL, Botan, picotls 全部対応しておいて, 切り替えしやすくしておくのがよさそうです!

## TODO

* [ ] s2n を試す. s2n コード自体は cmake 対応されているが, libcrypto は OpenSSL あたりから用意しないといけない.
dockerのMutagen-based caching導入におけるファイル権限が変わってしまう場合の対応

記事は移動しました。
https://lanlib.com/2021/04/04/docker%e3%81%aemutagen-based-caching%e5%b0%8e%e5%85%a5%e3%81%ab%e3%81%8a%e3%81%91%e3%82%8b%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e6%a8%a9%e9%99%90%e3%81%8c%e5%a4%89%e3%82%8f%e3%81%a3%e3%81%a6%e3%81%97/
Rubyを使用してのカレンダー作成

Ruby学習のアウトプットとして行おうとしましたが、
正直手も足も出なかったので回答例を見て、
読み解く作業をおこなうこととしました。

その記録です。
「プロを目指す人のためのRuby入門」で学習を進めていますが、
まだまだ落とし込みが足りないようです。。。

・回答例
https://qiita.com/sackey_24/items/8fc236bb054aff6b74c8

・参考サイト
https://www.javadrive.jp/ruby/date_class/index5.html

#コードごとで読み解き

回答見てもわかるところもあれば初見のところもあったので、
そちらを中心にまず調べて見ました。

どちらにしてもDateクラスを理解しないことには始まらなそうです。。。
###Dateクラス
・Timeクラスは組み込みライブラリーだが、Dateクラスは違うので、”require”で呼び込む。
・主要メソッドは、day・mouth・year・wday(それぞれ整数で取得。wdayも日曜日を０として整数で取得)
・オブジェクト作成後、フォーマットを使用し文字列に変換可能（strftimeメソッド）
→%a　曜日の省略形（sun,mon,thu等々）　%w 曜日を表す数字


Dateクラスがある程度理解できたので、回答コードの意味もわかってきました。

まずは変数を作り、

        head = Date.today.strftime("%B, %Y") #今日の月と西暦を取得→カレンダー上部に表示
        year = Date.today.year #今年の西暦
        mon = Date.today.mon   #今日の月



Dateクラスから今日の西暦と月を作成できたところで、
要件に書いてあるように今月1日と末日もDateクラスから作成。
        
        firstday_wday = Date.new(year,mon,1).wday
        lastday_date = Date.new(year,mon,-1).day
        week = %w(Su Mo Tu We Th Fr Sa)

ここの重要点としては、

**・インスタンスの引数として先ほどの変数を持ってくる。**
**・末日は”−１”と表記することで取得可能。**
**・%wは配列をつくる表記（＊フォーマット文字列とは別）**


次にここまでを実際に出力。

       puts head.center(20)
       puts week.join(" ")
       print "  " * firstday_wday

ここも同じく？になったところをまとめます。

**・centerメソッドは引数の数が文字数となりそれに沿って中央揃い**
**・join(" ")→引数のスペースはweek配列の曜日を感覚を開けて表示させるため**
**・printは改行せず表示するという特性を使いカレンダー1日までの空白を表示。**
**→スペースを曜日の数字分作る**


最後に日付を表記。
数字はくり返し処理をし、改行に関しては条件分岐で設定

       wday = firstday_wday
       (1..lastday_date).each do |date|    
        print date.to_s.rjust(2) + " " 

右詰で数字を並べる。（1..lastday_wdayで指定した範囲）  
そして最後にスタートした曜日（月曜日だったら１）から繰り返し処理ごとに１を足して行き７の倍数に差し掛かったら改行する。
 
       　wday = wday+1
        if wday%7==0                     
         　print "\n"
        end
       end


     if wday%7!=0
       print "\n"
     end

これで出来上がり。

```
      May 2020      
Su Mo Tu We Th Fr Sa
 　 　 　 　 　  1  2 
 3  4  5  6  7  8  9 
10 11 12 13 14 15 16 
17 18 19 20 21 22 23 
24 25 26 27 28 29 30 
31     
```

##振り返り

参考書に書いてある部分が大半だったがそれをいざ０から実装していくとなるとちんぷんかんぷになってしまった。。。

アウトプットすることでその部分や参考書では深く語られてない箇所（今回でいうとDateクラスの詳細）に触れることができたりを確認することができるのでどんどんつづけていければと思います。

また、本記事は自分なりに解釈した内容となるので、もし間違い等があれば、ご指摘頂ければ幸いです。。。

とりあえず配列の章読み返そう。。。
Git マージ済みのブランチを一括削除する

## 問題

Gitのブランチはリモートリポジトリでマージされても自動的に削除されないので自分で削除する必要があります。

## 環境

```shell-session
$ git --version
git version 2.26.2
```

## 予備知識

### マージ済みのブランチを表示

```shell-session
$ git branch --merged
```

#### 補足: マージしてないブランチを表示

```shell-session
$ git branch --no-merged
```

#### 補足: リモートリポジトリも含めてすべてのブランチの一覧を表示

```shell-session
$ git branch --all
$ git branch -a
```

### ブランチを削除する

```shell-session
$ git branch -d feature/issue-xxx
$ git branch -D feature/issue-xxx
```

`-d` オプションはマージされていないブランチは削除されません。
`-D` オプションはマージされていないブランチも強制的に削除します。

### リモートリポジトリで削除されているブランチを削除する

`git fetch` する際に `prune` オプションを付けると削除済みのブランチを削除してくれます。

```shell-session
$ git fetch --prune
$ git fetch -p
```

#### 補足: 常にpruneオプションを有効にする

```shell-session
$ git config --global fetch.prune true
```

## 本題

`git fetch --prune` でリモートリポジトリで削除済みのブランチを削除したあと `git branch --merged` で出てきたブランチを削除すれば良いわけです。

注意点としては、 `main` や `master` や `development` といった特定のブランチは削除対象外にしたいところです。
`git alias` を使っても大丈夫なのですが、 `.gitconfig` ファイルを管理するのが少し面倒だなと感じたのでシェルスクリプトを書きたいと思います。

`zsh` でも `bash` でも動作しますが、 `zsh` の例で進めます。

`~/.zshrc` に以下のコードを追加します。

```shell:~/.zshrc
PROTECT_BRANCHES='main|master|development'

git-delete-merged-branch() {
    git fetch --prune
    git branch --merged | egrep -v "\*|${PROTECT_BRANCHES}" | xargs git branch -d
}
```

保護したいブランチは `PROTECT_BRANCHES` の環境変数に `|` 区切りで追加してください。
シェルの設定ファイルを読み直します。

```shell-session
$ exec $SHELL -l
```

コマンドを実行します。(Gitが管理しているディレクトリ内で実行してください)

```shell-session
$ git-delete-merged-branch
```

![ScreenShot 2020-05-31 0.33.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/c8f12281-c6be-1683-8d9e-7bab20b7ad1a.png)

試しに実行するとこんな感じです。

### 補足: .gitconfig のエイリアスでやる場合

`~/.gitconfig` の alias 設定でやりたい場合は下記のようにします。

```
[alias]
	delete-merged-branch = !git branch --merged | egrep -v '\\*|main|master|development' | xargs git branch -d
```

```
$ git delete-merged-branch
```

## Git関連の記事まとめ

- [Git関連の記事一覧](https://qiita.com/search?q=user%3Aucan-lab+tag%3AGit&sort=created)
Ruby クラスとインスタンスの作成

# クラスの作成
オブジェクトはクラスから作成されます。
クラスからオブジェクトを作成することをインスタンス化といいます。

実際にクラスを作成していきます。
以下のように、class構文を使用します。

```sample.rb
class House
end
```

クラス名の先頭は大文字にする規則があります。
この記述で、最小限のHouseクラスを定義できました。

# インスタンス化
次は、作成したHouseクラスからインスタンス（オブジェクト）を作成していきます。
newメソッドを使用することで、インスタンス（オブジェクト）を作成できます。

```sample.rb
class House
end
House.new
```

クラスを呼び出すためには、クラス名を記述します。

```sample.rb
class House
end
House
```

## インスタンス（オブジェクト）のクラス
インスタンスのクラスがHouseクラスであることを確認してみます。

```sample.rb
class House
end

puts House.new.class
```

コンソール上で、sample.rbを実行し、以下のように出力されていれば正しくインスタンスが、Houseクラスから作成できています。

```console
House
```
Pimpleの仕組みメモ

## 概要
以下のDIコンテナを利用してみようと思いましたが、
仕組みが分からなかったので調べた際のメモとなります。
https://github.com/silexphp/Pimple

## 公式で紹介されていた使い方
```
use Pimple\Container;
$container = new Container();

$container['session_storage'] = function ($c) {
    return new SessionStorage('SESSION_ID');
};

$container['session'] = function ($c) {
    return new Session($c['session_storage']);
};

$session = $container['session'];
```

## 分かっていなかったこと
$cにPimple\Containerオブジェクトが設定される仕組み

## 実装を確認して見て分かったこと
Containerクラスが実装しているArrayAccessの
offsetGet($id)内で$thisが渡されていたためでした。
使い方を確認しただけでは分かりませんでしたが、実装を見て納得できました。

```
offsetGet($id)メソッドの該当箇所抜粋
if (isset($this->factories[$this->values[$id]])) { |
    return $this->values[$id]($this); < この箇所
}
```
【JavaScript】別ページからアンカーリンク移動時の、固定ヘッダー分ずれ解消

移動先ページのURLにハッシュが含まれていれば、ヘッダー分移動してあげるというシンプルな作りです。

ミソは`setTimeOut`で、これがないとうまくいきません。
`headerHeight`の値を取得する前に`window.scrollBy`が終わってしまうということでしょうか。

```javascript
document.addEventListener("DOMContentLoaded", () => {
  if (location.hash) {
    const headerHeight = document.getElementById("js-header").clientHeight;
    setTimeout(() => {
      window.scrollBy(0, - headerHeight);
    },100)
  }
})
```
有限要素法による二次元ポアソン方程式の解法(with 三角形二次要素)（その３）

いつになったらサンプルコードまでたどり着けるんだろうか...

# 境界の積分
ノイマン境界条件を処理するために境界でも積分しなければ足りません。

## 線分要素の局所座標系
![bitmap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296000/05f84af5-87e9-1796-d9cd-fd914616c679.png)

この前と同じように局所座標系に変換していきます。元の要素上の点$\mathbf{x} = (x,y)$と局所座標系における値$\zeta$には以下のような関係が成り立ちます。

```math
\mathbf{x} = \zeta (\mathbf{x_2} - \mathbf{x_1})
```
つまり、その点は線分の端から端までのうちどの辺りに存在するかを$[0,1]$で表したものとなります。

## 内挿関数
その局所座標系における内挿関数は以下のように表されます。

```math
\begin{align}
\psi_1 &= 2(x-\frac{1}{2})(x-1) = 2x^2-3x+1\\
\psi_2&=-4x(x-1) = -4x^2+4x\\
\psi_3 &= 2x(x-\frac{1}{2}) = 2x^2-x
\end{align}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296000/e656fbdc-741b-c706-67b6-246541bdb438.png)


## 積分

```math
\begin{align}
q_i^l \int_{\Gamma_{N_l}} \psi_i^l \psi_j^l \mathrm{d\Gamma}
&= q_i^l \int_0^1 
\begin{pmatrix}4 \zeta^{4} - 12 \zeta^{3} + 13 \zeta^{2} - 6 \zeta + 1 & - 8 \zeta^{4} + 20 \zeta^{3} - 16 \zeta^{2} + 4 \zeta & 4 \zeta^{4} - 8 \zeta^{3} + 5 \zeta^{2} - \zeta\\- 8 \zeta^{4} + 20 \zeta^{3} - 16 \zeta^{2} + 4 \zeta & 16 \zeta^{4} - 32 \zeta^{3} + 16 \zeta^{2} & - 8 \zeta^{4} + 12 \zeta^{3} - 4 \zeta^{2}\\4 \zeta^{4} - 8 \zeta^{3} + 5 \zeta^{2} - \zeta & - 8 \zeta^{4} + 12 \zeta^{3} - 4 \zeta^{2} & 4 \zeta^{4} - 4 \zeta^{3} + \zeta^{2}\end{pmatrix} \mathrm{d}\zeta\\
&=\begin{pmatrix}
q_1 & q_2 & q_3
\end{pmatrix}
\begin{pmatrix}\frac{2}{15} & \frac{1}{15} & - \frac{1}{30}\\\frac{1}{15} & \frac{8}{15} & \frac{1}{15}\\- \frac{1}{30} & \frac{1}{15} & \frac{2}{15}\end{pmatrix}
\\
i &= 1,2,3
\end{align}
```
以後、これを$\mathbf{q^l}$と置きます。
# 全体の行列作成

もう一度要素に分割した際に導出した方程式を見てみましょう。


```math
\begin{align}
\sum_{e=1} \left[
w_j^e u_i^e  K_{i,j}^e 
+w_j^e   {f_j^e}
\right] 
=
\sum_{l=1} w_j^e q_{j}^l\\
\end{align}
```
そして、方程式を立てる元となっている要素分割の際の図も見てみましょう。
![element.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296000/ad9d8e30-9389-ab62-4267-147549b28936.png)
節点に各要素内の番号と全体の番号が割り当てられていて、要素内の番号（図ではe=3の要素のみ表示）は要素内に1,2,...6といったように割り当てられています。全体の節点の番号は1...17まであります。また、境界要素については、$l=1,2,...5$まであり、各要素内では1,2,3と番号が割り当てられています(煩雑になるため図には書いていません)。これらの$e=1,2,...6$の６つの要素で計算される$\mathbf{K^e},\mathbf{f_e}$、$l=1,2,...5$の５つの境界要素で計算される$\mathbf{q_l}$をまとめて一つの大きな方程式を作りたいのです。つまり、

```math
\mathbf{w}^T\mathbf{K}\mathbf{u} = \mathbf{w}^T (-\mathbf{f} + \mathbf{q})
```
としたいのです。
この大きな行列を$\mathbf{K}$の作り方を説明します。
$e=3$のとき、$\mathbf{K_e}$の(1,1)要素であれば、要素内の節点番号1の節点は全体番号では7であるため、$\mathbf{K}$の(7,7)要素に$\mathbf{K_e}$の(1,1)要素を足します。$\mathbf{K_e}$の(1,2)要素であれば、要素内の節点番号1の節点は全体番号では7、要素内の節点番号2の節点は全体番号では8であるため、$\mathbf{K}$の(7,8)要素に$\mathbf{K_e}$の(1,2)要素を足します。
これを(1,1)要素から(6,6)要素まで繰り返し行い、更に、$e=1$から$e=6$でも同じことをすることで$\mathbf{K}$が完成します。
$\mathbf{f}$と$\mathbf{q}$に関しても同様に行います。

また、任意の$\mathbf{w}$に対して

```math
\mathbf{w}^T\mathbf{K}\mathbf{u} = \mathbf{w}^T (-\mathbf{f} + \mathbf{q})
```
が成り立つため

```math
\mathbf{K}\mathbf{u} =  -\mathbf{f} + \mathbf{q}
```
となり、この連立方程式を解くことで$\mathbf{u}$を求めることができます.

次回、プログラム書きます...
pythonかCかfortran03かRustで書こうかなと...
ようやくqiitaらしく...

# 参考文献
偏微分方程式の数値解法 / 神谷紀生, 北栄輔著　東京 : 共立出版, 1998.3　(三角形一次要素を使った解法がのっています)
Linuxコマンドを言語化

##はじめに

私のPCはMacです。OSはMacOSを使用しています。
ターミナルではLinuxOSと同様にLinuxコマンドが使えます。
シェルはzshでした。ターミナルで`echo $0`と入力すると、使っているシェルを見ることができます。bashを使っている物だと思っていたのですがzshでした。

bashとzshの違いは以下のリンクで調べ学びました。
- [bashとzshの違い](https://kanasys.com/tech/803)

Linuxコマンドを、今までなんとなく使っていたのですが、そもそもMacOS使ってるのにLinuxOSのもの使ってるってどうゆうこと？と調べていくうちに疑問に思ったので調べました。ターミナルでのコマンドはLinuxOSとほぼ共通しているらしいです。以下のリンクで疑問が結構解消できました。
- [Linuxとは](https://www.sejuku.net/blog/4948)
- [ターミナルの使い方](https://blog.codecamp.jp/terminal-how-to)

この記事では、アウトプットするためにLinuxコマンドを言語化しました。ほぼ自分の学習用です。
間違いがありましたら訂正していただけると幸いです。


##Linuxコマンドを言語化

・`tabキー`　
入力補完ができます。もう一回`tabキー`を押すと候補を表示してくれます。

・`control + r`　
前に使ったコマンドを検索。更に`control + r` で複数検索に引っかかている場合の２つ目を表示します。

・`control + c`
現在入力中のコマンドを安全に終了できます。


・`cd -`　
直前にいたディレクトリに移動します。

・`cd ..`
１つ上の階層のディレクトリに移動します。

・`cp -r` 
再帰的にデイレクトリをコピーします。再帰的とは、中にあるディレクトリやファイルまで見るということです。多分。
参考サイト: [再帰的とは?](http://blog.livedoor.jp/engineercollege/archives/46559976.html)

・`cp ファイル名　コピー先`
ファイルをコピーできます。

・`mv`
ディレクトリやファイルを移動できます。

・`mv ファイル名　変更後のファイル名`
現在いるディレクトリのファイル名を変更できます。


・`ls -R`
再帰的に今いるディレクトリの下の階層のディレクトリやファイルを表示します。
参考サイト: [再帰的とは?](http://blog.livedoor.jp/engineercollege/archives/46559976.html)

・`mkdir` 
ディレクトリを作成します。

・`touch`　
ファイルを作成します。
参考サイト: [新規ファイル作成](https://uxmilk.jp/8395)

・`rmdir` 
空のディレクトリを削除できます。
中身がある場合は`rm -r`で削除できます。

・`ls`
今いるディレクトリの直下にあるディレクトリやファイルを表示します。

・`mv` 
ディレクトリやファイルを移動します。

・`cat`　
指定したファイルの中身を表示できます。

・`less`
中身が長い時に使えるコマンドです。中身を表示してくれます。`control + f`1画面先に`control + b`1画面前に`g`画面の先頭`G`末尾に移動`q`lessの終了

・`history`
コマンドの履歴を見ることができます。`! + historyで表示された数字`でコマンドを呼び出して実行することができます。`!!`で直前のコマンドを実行することもできます。`!-2`だと２個前のコマンドを実行することができます。

・`!$`
直前に渡した引数(文字列）を呼び出すことができます。
前にlsコマンドを実行していたと仮定して`!l`を入力すると直前に使ったlsコマンドを実行できます。前にpwdコマンドを実行していたとしたら`!p`や`!pw`などで直前に使ったpwdコマンドを実行できます。
実行せずに直前に使ったコマンドを確認するには`!l`に続けて`:p`を入力します。そうすると直前に使ったlsコマンドを実行せずに表示してくれます。`!pw:p`だと直前に使ったpwdコマンドを実行せずに表示してくれます。
`!pw:p`の後に、`!!`を入力すると表示されていたpwdコマンドが実行されます。

##その他参考URL
- [Linuxコマンドリファレンス]
(http://www.redout.net/data/command.html)
- [command killとcontrol Lの違い]
(https://qiita.com/ToshioAkaneya/items/663a4f19cad1ffbffd79)
- [知識０から始めるvim講座](https://qiita.com/JpnLavender/items/fabcc79b4ab0d52e1f6d)


##最後に
この記事を読んでいただきありがとうございました。

Twitter: [@SHUN15949496](https://twitter.com/SHUN15949496)
Pythonエンジニアに向けての学習計画

現在の自分だと足りないものが、多すぎる。

Pythonエンジニアとして働く未来の自分とのギャップ埋めていくための作業の青写真を記す


【学習方針】

・基本的にスクラッチで開発することで技術的な部分の理解を深める

・ライブラリ、フレームワークの使い方は必須事項なので早めに学ぶ

・UdemyでPythonならではの専門的な分野を深める(スクレイピング、データ分析、機械学習など)

・書籍、Udemy、ハンズオンと学習のやり方を多彩にする

・人と出会う機会を大切にし作っていくことで、自分に足りないものを把握する

・最終的にチームで開発することを念頭に入れる

・5年後、10年後のどういった立ち位置で働いているかを意識する



【手法】

・アウトプットから入って、効率よく学習する

・サイクルをまわすことを優先し完成度は後から上げていく

・覚えるのでなく、理解し習得することを意識する

・Webアプリを作りフロントエンドの技術やDB周りの知識も最低限つける

・誰でも作れる簡易的なアプリケーションをまず作り、自分がつくりたいものを作るための基礎とする
Flutterで文字サイズを固定にしたい

# 状況
iOSでもAndroidでも、端末本体の設定で文字サイズを大きくしたり小さくしたりすることが出来ますが、端末の文字サイズ設定を変更していると、レイアウトが崩れてしまうことが多々あります。
本来文字サイズに合わせて表示させるべきなんですが、どうしてもレイアウト構成上難しい箇所があり、固定にしたい場所が生じてしまいました。
Androidで言う、文字サイズを`dp`指定しちゃうみたいなことが出来ないかなと思って調べた結果です。

# 環境など

|ツールなど|バージョンなど|
|:--|:--|
| MacBook Air Early2015|macOS Mojave 10.14.6|
|Android Studio |3.6.1|
|Java |1.8.0_131|
|Flutter|1.12.13+hotfix.9|
|Dart |2.7.2|
|Xcode |11.3.1|

# 解決策

`Text`ウィジェットのパラメータ`textScaleFactor`に`1.0`を渡せば固定されます。
このパラメータを指定していないときは、`MediaQuery.textScaleFactorOf`が使用されます。端末の文字サイズを変更しているとこの値が変わるんですね。よって端末の文字サイズ設定に応じてフォントサイズが変わっているわけです。
そこに`1.0`を渡してしまえば、フォントサイズが固定されることになります。

```dart
 Text(
    'なんらかのタイトル',
    style: TextStyle(fontSize: 14),
    textScaleFactor: 1.0,
),
```

[flutter_screenutil](https://pub.dev/packages/flutter_screenutil)というパッケージもあるようですが、上記の方法の方が簡単かと思います。


# 参考サイトなど

https://api.flutter.dev/flutter/widgets/MediaQueryData/textScaleFactor.html
jQuery~中級編(アコーディオン機能)~

# プログラミングの勉強日記
2020年5月30日　Progate Lv.76

##アコーディオン機能
　クリックすることで隠れている詳細を展開表示させる機能のこと。今回はFAQに実装して、質問をクリックするとその答えがスライド表示/非表示されるのを作る。

1.隠したい部分（答えの部分）をCSSで非表示にする
2.クリックする部分（質問部分）には同一のクラス名にする
3.それらのclickイベントを作る

```html
<div class="answer">...</div>
<div class="answer open">...</div> <!--openは答えを表示するときの目印-->
```

<img width="672" alt="jquery.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/3d18f93a-9965-133c-86d0-ecd5ff1f74f5.png">


#####hasClassメソッド
　引数に指定したクラスをオブジェクトを持っているか判定するときに使う。（持っていればtrueを、持っていなければfalseを返す）

```html
<div class="answer">...</div>
<div class="answer open">...</div> 
```
```js
$('.answer').hasClass('open'); //結果はfalse
$('.answer open').hasClass('open'); //結果はtrue
```

######ifの使用
　隠れた部分（答えの部分）の表示/非表示に使う。質問をクリックしたときに`$('answer')`がすでにopenクラスを持っているなら（＝すでに表示されている）、openクラスを外して答えを隠す。（openクラスがないときは逆のことをする）

```js
if($('answer').hasClass('open')){
  //openクラスを外す処理と答えを隠す処理
}else{
  //openクラスをつける処理と答えを表示する処理
}
```
　このif文がtrueのとき、答えの部分はslideUpメソッドで隠す。逆にif文がfalseのときはslideUpメソッドで表示する。（<font color=orange>アコーディオンのスライド操作</font>）
FlutterアプリでonResume的なタイミングの処理をする

# 状況
カレンダー式表示のアプリを作成しています。「今日」が分かりやすいように、その日付のセルだけ背景色を変えています。
しかし、特にiOSで問題になるのですが、アプリをホームボタンでバックグラウンドに移動していて、もう一度アプリを立ち上げたときに、そのタイミングで日付が変わっていても「今日のセル」が移動してくれません。
Androidでいう、"onResume"のタイミングで処理ができれば解決できると思い、調査しました。

# 環境など

|ツールなど|バージョンなど|
|:--|:--|
| MacBook Air Early2015|macOS Mojave 10.14.6|
|Android Studio |3.6.1|
|Java |1.8.0_131|
|Flutter|1.12.13+hotfix.9|
|Dart |2.7.2|
|Xcode |11.3.1|

# 解決策

`SystemChannels.lifecycle.setMessageHandler`を使います。
詳しくはこちら。
https://api.flutter.dev/flutter/services/BasicMessageChannel/setMessageHandler.html

`Widget`の`build`内でこの関数にハンドラーを登録しておくと、任意のライフサイクルのタイミングで処理をすることが出来るようになります。

```dart
/// カレンダーウィジェット
class CalendarWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final viewModel = Provider.of<MonthlyViewModel>(context, listen: false);
    SystemChannels.lifecycle.setMessageHandler((msg) {
      if (msg == 'AppLifecycleState.resumed') {
        print('Resumed!');
        viewModel.updateToday();
      }
      return null;
    });

    return Column(...);
  }
}
```

# 参考サイト


https://qiita.com/sakyoyuto/items/a7a8ecefea1cee5fbac6


https://stackoverflow.com/questions/49869873/flutter-update-widgets-on-resume
Ruby環境構築まとめ~mac版~

# はじめに
あたらしくmacを購入して、Rubyの環境を作り直す機会があったので備忘録としてまとめます。
#Homebrewをインストール
まず[homebrew](https://brew.sh/index_ja)をインストールします。（もうすでにインストール済みの人は大丈夫です)

```shell

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

このコマンドをターミナルで実行するとインストールが完了します。
#wgetのインストール
wgetをインストールします。

```shell

brew install wget
```

#Rubyのインストール
wgetのインストールが完了したら、Rubyのインストールに入っていきます。
手順としては
- homebrewでrbenvをインストール
- パスを通す
- rubyのインストール
と言った感じです。
では、rbenvをインストールしていきます。

```shell

brew install rbenv
brew install ruby-build
```
この二つのコマンドを実行してインストールします。
インストールが終わったら、パスを通していきます。

```shell

echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.zshrc
echo 'if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi' >> ~/.zshrc
source ~/.zshrc
```
これでrbenvのインストールとパスを通すことができました。
いよいよRubyをインストールしていきます。

```shell
rbenv install --list
rbenv install 2.6.6
rbenv rehash
rbenv global 2.6.6
```
1つ目のコマンドでダウンロードできるRubyのバージョン一覧を確認できます。
2つ目のコマンドでダウンロードするRubyのバージョンを指定します。(今回は2.6.6を選択しました)
3つ目のコマンドでrbenvの再読み込み、4つ目でdefaultで使うバージョンの指定をしています。

一通りの作業が終わったら、ターミナルで

```shell
ruby -v
```
をやって自分が先ほど指定したバージョンになっているか確認してみてください。
なっていなかったら、pathがうまく通ってない可能性があるので、zshrcを確認してみてください。
ESLint簡単導入 × VSCode

# node.js をインストールする

## NodeBrewをインストール

NodeBrew は Nodeのバージョンを管理するツール
似たものに nodenv というものもある

```bash:bash
brew install nodebrew
```

## Nodebrewのセットアップ

初めに打たなければいけない

```bash:bash
nodebrew setup
```

## 最新版のnode.jsをインストール

もちろんバージョンを指定してインストールしても良し
`nodebrew ls-remote` で提供されているバージョンを調べられる

```bash:bash
nodebrew install-binary latest
nodebrew ls # インストールしたnode.jsのバージョンを確認
```

## バージョンを指定して使用できるようにする

複数のバージョンを切り替えるときにも同じようにバージョンを指定する

```bash:bash
$ nodebrew use v12.4.0 # ls で確認したバージョンを指定
```

# パスを通す

```plaintext:.bash_profile
PATH=/usr/local/var/nodebrew/current/bin:$PATH
```

参考：[MacにNode.jsをインストール](https://qiita.com/kyosuke5_20/items/c5f68fc9d89b84c0df09)
参考：[【2018年版】macのhomebrewでnodebrew入れてからnode.jsを入れるまで](https://qiita.com/Alex_mht_code/items/422f5ce10d9c9d5729b7)

# ESLintをインストールする

## ざっくりコマンド

```bash
$ cd {プロジェクトルート} # プロジェクトルートに移動

# package.json作成していない場合
$ npm init # 対話式でpackage.json作成 (適当にエンターでOK)

$ npm install eslint --save-dev # eslintのインストール (開発環境にしか必要ないはずなので --save-dev を付与)

$ npm install -g eslint-cli # eslintをグローバルインストールしなくてもeslintコマンドがパス通るようになる

$ eslint --init # ESLintの初期化 (.eslintrcファイルの作成)
```

### `eslint --init` の対話内容

```bash
# コードスタイルも強制してもらおうかなと一番厳しめな一番下を選択
? How would you like to use ESLint? 
  To check syntax only 
  To check syntax and find problems 
❯ To check syntax, find problems, and enforce code style

# フロントのJSしか書かないつもりなので一番上を選択
? What type of modules does your project use? 
❯ JavaScript modules (import/export) 
  CommonJS (require/exports) 
  None of these

# フレームワークは使わないので一番下を選択
? Which framework does your project use? 
  React 
  Vue.js 
❯ None of these

# TypeScriptは使わないので N
? Does your project use TypeScript? (y/N) N

# フロントのJSしか書かないつもりなので Browser のみ選択
? Where does your code run? 
❯◉ Browser
 ◯ Node

# 設定ファイルを自分で書くのは大変なのでスタイルガイドを使用すべく一番上を選択
? How would you like to define a style for your project? 
❯ Use a popular style guide 
  Answer questions about your style 
  Inspect your JavaScript file(s) 

# よく分からないけれど Airbnb を選択
? Which style guide do you want to follow? 
❯ Airbnb: https://github.com/airbnb/javascript 
  Standard: https://github.com/standard/standard 
  Google: https://github.com/google/eslint-config-google 

# 設定ファイルといえばJSONのイメージなのでJSONを選択
? What format do you want your config file to be in? 
  JavaScript 
  YAML 
❯ JSON 

# どうやら Airbnb だとESLintのバージョンを下げなければいけないらしくて大人しく従う Y
? The style guide "airbnb" requires eslint@^5.16.0 || ^6.8.0. You are currently using eslint@7.1.0.
  Do you want to downgrade? (Y/n) Y

# 関連するパッケージをインストールしろと言われたので Y
eslint-config-airbnb-base@latest eslint@^5.16.0 || ^6.8.0 eslint-plugin-import@^2.20.1
? Would you like to install them now with npm? (Y/n) Y
```

参考：[ESLintと「eslint --init」による「.eslintrc.json」の生成](https://www.konosumi.net/entry/2019/09/01/165449)


# VSCodeの拡張機能をインストールする

- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) をインストールする
- Cmd + Shift + P > ESLint: enable ESLint を実行
- 自動的にJSファイルがチェックされるようになるはず・
はじめてのThree.js 8章 日記

[はじめてのthree.js](https://www.amazon.co.jp/dp/4873117704)

#新たに知った知識
- group化で２つ以上のオブジェクトを一括でコントロールできる(これが一番知りたかった)
- mergeするか否かでパフォーマンスが変わってくる
- json保存するときにlocalstrageAPを使って保存
- collada(.dae)はジオメトリもマテリアルも定義できる


#気づいたこと
- blender2.8の神アップデートによりデフォルトでthree.jsで表示できるエクスポート形式が搭載されたためaddonをわざわざ入れる必要がなくなった **現在githubではglTFをサポートしているためremoveされている模様。どうしても本(筆者は第２版)通りにやりたい場合はcommit戻るべし**　[参考](https://qiita.com/adrs2002/items/dc6416d6fd2389c75ab5)
![Screen Shot 2020-05-30 at 7.39.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181534/36fc18bc-d425-402b-f77c-aafecd2b980d.png)
- blender無料はやっぱりおかしい(褒め言葉)

#wow moment
- blenderからの読み込みが一番やりたかった事！神！！！
- ポイントクラウドかっこいい
![Screen Shot 2020-05-30 at 21.00.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181534/45914fbb-a384-a6b7-7df9-18f99040e683.png)


#まだ解決していない点
- 


[9章はこちら](https://qiita.com/asadsexyimp/items/7aa06396e1386d9d1f93)
Googleフォームのテキスト入力で、すでに登録済みの文字列に警告を出す

#背景と目的

- 大学で担当している授業で、Google アプリをあれこれ利用している。
- Googleフォームを使って、ハンドルネームを登録してもらうことにした。
- ハンドルネームの **重複を避けたい** 。
- Googleフォームの **回答の検証** 機能を利用して実現したい。

#もくろみ

- Googleフォームの送信時に発火するトリガーを仕掛け、すでに送信されたハンドルネームのリスト作って、これらに一致するハンドルネームの送信を拒否するようにする。
- **回答の検証**は決まった数種類しかなく、関数を書いてカスタムの検証を設定することはできない。
    - もっとも自由なのは正規表現。正規表現でなんとかするしかない。
- **正規表現**で既存のハンドルネームに**一致しない**ような回答の検証を設定できればいいはず。
- これを、Google Apps Script（GAS）で実装する。

#Googleフォームで使える正規表現

- いろいろ試行錯誤した結果、Googleフォームの回答の検証では、正規表現の**否定的先読み** `?!(foo|bar)` は使えないことがわかった。
- 代わりに、正規表現パターンに**一致しない**条件での検証が可能。

#GASの実装

- Googleフォームを編集して、右上の〔⁝〕からプルダウンメニューを引きだし、クリプトエディタを呼びだす。
- 以下のようにスクリプトを書いて保存する。

![スクリプトエディタを開く.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64391/de0da11c-ddee-2f2b-926d-7b7856740905.png)

```javascript:コード.gs
function setHandlenameValidation() {

  var thisForm = FormApp.getActiveForm();
    
  // 既存の回答を全部引っ張ってきて、ハンドルネームを取りだす。ハンドルネームは２番目のItemに格納されている。
  // エスケープした既存ハンドルネームのリスト escapedHandlenameList を作成
  var escapedHandlenameList = []
  var responseList = thisForm.getResponses();
  for ( var i = 0; i < responseList.length; i++ ){
    escapedHandlenameList.push( 
      responseList[i].getItemResponses()[1]
        .getResponse().replace(/[\\^$.*+?()[\]{}|\ ]/g, '\\$&')
    );
  }

  // 正規表現のパターン文字列 validationExpression を生成
  var validationExpression = escapedHandlenameList.map(element => `${element}`).join('|')
  validationExpression = "^(" + validationExpression + ")$";

  // TextValidation オブジェクト textValidation を作成
  // requireTextDoesNotMatchPattern() で、正規表現パターンに一致「しない」ことを検証の条件にできる。
  var textValidation = FormApp.createTextValidation()
    .setHelpText('すでに使われているハンドルネームです。')
    .requireTextDoesNotMatchPattern( validationExpression )
    .build();

  // textValidation を２番目の Item に登録
  var formItems = thisForm. getItems()[1]
    .asTextItem().setValidation( textValidation );
}
```

- メニューの **実行** → **関数を実行** から書いた関数を実行して、正しく動作することを確認する。
    - 正しく動作すると、フォームの該当するテキスト入力アイテムに回答の検証が生成される。すでに存在していた場合には、現在の状況に応じた内容に上書きされる。
![スクリーンショット 2020-05-31 12.05.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64391/330006e1-9dc6-4cb1-f131-c078088026e1.png)


#トリガーの設定

- メニューの **編集** → **現在のプロジェクトのトリガー** をクリック。
- **トリガーを追加**をクリック。
    - イベントのソースを選択：**フォームから**
    - イベントの種類を選択：**フォーム送信時**
![スクリーンショット 2020-05-31 11.30.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64391/6ea209c9-0aeb-b6ce-e240-947580db6c27.png)

# 動作状況の確認

- GASダッシュボード上のプロジェクト名からのプルダウンメニューで**実行数**をクリックすると、トリガーの実行状況を確認できる。実行に失敗した場合、ステータス欄に**失敗しました**と表示される。
    - ダッシュボード左側のナビゲータ内にある **実行数** からは、すべてのトリガーの実行状況がわかる。
![スクリーンショット 2020-05-31 11.38.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64391/c26a28eb-f8c9-5d62-f39c-8021edd17fe2.png)

#問題点

- 回答の検証の内容はフォームを**開く際に確定**する。そのため、ユーザーがwebブラウザでフォームを開いてから送信するまでの間に他のユーザーが送信したハンドルネームとの重複は検証できない。
- サーバ側では検証は行われないので、こうした状況が発生すると、重複するハンドルネームが登録されてしまう。
- GASでこれを回避するのはおそらく難しい。
    - 重複が発生した場合にハンドルネームの末尾に適当な文字列を付加するなどして重複を避け、GmailApp を使ってそのことをユーザーに知らせるくらいが限界か。
- 筆者のケースは、大学の授業で履修者はおよそ250人で、人数が増えることもなく、アクセス頻度や登録数もさほどではないので、重複に関してはマニュアル対応することにしている（発生頻度はとても低いと考えられるので）。
brew cask install でマイナポータル


# 免責

自分なりに動作確認をしましたが、この記事のやり方で問題が起きても一切責任を取りません。


# TL;DR

```
$ brew tap hiroga-cc/tap
$ brew install myna-portal-chrome
```


# 解説

特別定額給付金のオンライン申請をPCから行うべく、マイナポータルAPをインストールします。  
公式手順はこちら。
https://app.oss.myna.go.jp/Application/resources/dousakankyou/index.html

## Caskファイルの作成

今回はChrome対応版だけをインストールすることを目標に、Cask用の設定を書いていきます。

まず普通にダウンロードして、バージョンとハッシュ値を調べます。

```terminal
$ sha256sum MynaPortalAppSetup.dmg
1abcc1d25e8f1af03b30cdc44df43873ea30915a534049132ef0b58d5cb756e5  MynaPortalAppSetup.dmg
```

```/Applications/MynaPortalApp.app/Contents/info.plist

（省略）
	<key>CFBundleShortVersionString</key>
	<string>8.2.0</string>
```

調べた内容をCaskファイルに反映します。

```myna-portal-chrome.rb
cask 'myna-portal-chrome' do
  version '8.2.0'
  sha256 '1abcc1d25e8f1af03b30cdc44df43873ea30915a534049132ef0b58d5cb756e5'

  url "https://img.myna.go.jp/tools/mac/MynaPortalAppSetup.dmg"
  name 'マイナポータルAP'
  homepage 'https://app.oss.myna.go.jp/Application/resources/dousakankyou/index.html'

  pkg 'MynaPortalAppSetup.pkg'

  uninstall delete: [
                      '/Applications/MynaPortalApp.app',
                      '/Library/Google/Chrome/NativeMessagingHosts/jp.go.cao.mpa.json',
                    ]

  caveats <<~EOS
    Chromeで以下のURLにアクセスし、Chromeウェブストアから拡張機能をインストールしてください。
    https://chrome.google.com/webstore/detail/fjjibalalngebiaophebgkkohaaggphf
  EOS
end
```

リポジトリは [hiroga-cc/homebrew-tap](https://github.com/hiroga-cc/homebrew-tap/blob/master/Casks/myna-portal-chrome.rb) です。

## 動作確認

```terminal
$ brew tap hiroga-cc/tap

$ brew cask install --verbose myna-portal-chrome
# 省略
🍺  myna-portal-chrome was successfully installed!

# ブラウザ拡張をインストール後、以下のURLでの案内にしたがってブラウザからの起動を確認する。
# https://app.oss.myna.go.jp/Application/environmentCheck/initStatic

$ brew cask uninstall --verbose myna-portal-chrome
==> Uninstalling Cask myna-portal-chrome
==> Removing files:
/Applications/MynaPortalApp.app
/Library/Google/Chrome/NativeMessagingHosts/jp.go.cao.mpa.json
==> Purging files for version 8.2.0 of Cask myna-portal-chrome
```

動作確認できましたね！

# 余談

特別給付金の申請完了しました。
Django REST frameworkの基本

# はじめに

Django REST frameworkを使うと、簡単にAPIを作成することができます。
ここでは、Django REST frameworkについて、最低限知っておきたいことにしぼって解説します。


# `settings.py`への追記

`INSTALLED_APPS`に`rest_framework`を追記します。

```python:settings.py
INSTALLED_APPS = [
    'rest_framework', # 追加
]
```


# serializerの作成

次に、serializerを作成していきます。

```python:serializers.py
from rest_framework import serializers


class SampleSerializer(serializers.ModelSerializer):

    class Meta:
        model = 対象モデル
        fields = 含めるフィールド（全部の場合は'__all__'） # または、exclude = (除外したいフィールド)
```


# viewの作成

serializerを作成したら、`views.py`に追記します。

```python:views.py
from rest_framework import generics


class SampleListAPI(generics.ListAPIView):
    queryset = 対象モデル.objects.all()
    serializer_class = シリアライザー


class SampleDetailAPI(generics.ListAPIView):
    queryset = 対象モデル.objects.all()
    serializer_class = シリアライザー
```


# `urls.py`の設定

最後に、ルーティングの設定をして一通り完了です。

```python:urls.py
from django.urls import path

from . import views


urlpatterns = [
    path('api/sample/list', views.SampleListAPI.as_view(), name='api_sample_list'),
    path('api/sample/detail/<int:pk>/', views.SampleDetailAPI.as_view(), name='api_sample_detail'),
]
```


# まとめ

ここでは、Django REST frameworkを用いたAPI作成方法について解説しました。
Linuxで電源をつける度に時間が狂ってしまう問題の解決方法

# 環境

Arch Linuxで試しました。

# 実行したコマンド

これだけです。

```bash
$ sudo timedatectl set-ntp true
```

# まとめ

このコマンドの効果は基本的には永続しますが、何かの拍子に外れてしまいます（なぜ？）・・・。その時はもう一度このコマンドを実行します。
form_withで、フォームの大きさを変える







form_withとform_forどっちを使えばいいのか？
違いがわからずにいました。


登録フォームを作る際に、
railsチュートリアルや、スクールのカリキュラムでは,form_forを使っていましたが、[現場で使える Ruby on Rails 5速習実践ガイド](https://www.amazon.co.jp/%E7%8F%BE%E5%A0%B4%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B-Ruby-Rails-5%E9%80%9F%E7%BF%92%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-%E5%A4%A7%E5%A0%B4%E5%AF%A7%E5%AD%90/dp/4839962227)では、form_withが使われていました。

どうやら、トレンドはform_withみたいですね。
この記事が、まとまっていてわかりやすかった。
[【Rails】form_withの使い方を徹底解説！](https://pikawaka.com/rails/form_with)
**form_withの使い方については、本記事では割愛します。**

##フォームの初期値

実際にフォームを実装していると、初期設定のフォームは小さく感じる。
ユーザーの観点で考えると、かなり使いにくそう。

よく使うであろう、**form.text_field**と**form.text_area**の幅の初期値は以下の通り。

```ruby:form.text_field
#form.text_field
#幅30文字。初期値について、以下はわざと記載しているが本来記載されていない。
<%= form.text_field :name,  size: 30 %>
```

```ruby:form.text_area
#form.text_area
#初期値は40x20。初期値について、以下はわざと記載しているが本来記載されていない。
<%= form.text_area :description, , size: "40x20" %>
```
##フォームの大きさを変える

```ruby:フォームの幅を指定する

<%= form.text_field :name,  size: 40 %>

<%= form.text_area :description, size: "40x20" %>

```
**結論:**

sizeの値を変えるだけで、幅が広がります。
**form.text_field**と**form.text_area**の初期の幅が違うので、レイアウト的に合わせたいなら、
上記のように値を合わせれば、いいと思います。


##新規投稿画面

```ruby

     <%= form_with model: @question, local: true do |form| %>

        <div class="form-group">
          <%= form.label :name, 'Title', class: 'form-control' %>
          <%= form.text_field :name, placeholder: "what is about?", size: "50" %>
        </div>
        <div class="form-group">
          <%= form.label :description, 'Content', class: 'form-control' %>
          <%= form.text_area :description,  placeholder: "Please your comments in 500 words", size: "50x10"%>
        </div>
        <div class="form-group, text-white">
          <%= form.label :image %>
          <%= form.file_field :image %>
        </div>
        <%= form.submit 'Submit', class:'btn-block btn-success btn-lg' %>
        
     <% end %>
```

作成中の登録フォームです。
自分は**form.text_field**と**form.text_area**の幅は、50文字で合わせています。

余談ですが、**placeholder**を設定しておくと、ユーザーがフォームを記入する際の助けになって良さげそうです。

にしても全然関係ないですが、labelを使うと見た目が、ガツガツしてて疲れるので、pタグにしてしまおうか悩み中です。（実際にpタグに置き換えてもform_withは正常に動きました。）

それと、form_withを実装するのに、以下の記事が大変役立ちました。
[連日格闘したform_withとの戦いに決着をつけてきた](連日格闘したform_withとの戦いに決着をつけてきた)


それでは！
Expressを使ってみた ~ Expressに「ようこそ」と言われるまで ~

# そもそも Express とは
Node.jsのWebアプリケーションフレームワーク

# express-generator
アプリケーションジェネレータツール。これを使うと、アプリケーションの骨組みを素早く作成できる

## インストールしてみる
```vim
$ npm install -g express-generator
```

## 実際にアプリを作るためには
- まずはヘルプ機能を確認

```vim
$ express -h
```
- さっそくExpressアプリを作成
 - アプリ名：myapp
 - viewエンジン：pug

```vim
$ express --view=pug myapp
```

- 依存関係をインストール

```vim
$ cd myapp
$ npm install
```
- アプリの実行

```vim
$ DEBUG=myapp:* npm PORT=XXXX start
```

- ブラウザで http://localhost:XXXX/ をロードしてアプリにアクセス

...すると！
Expressがすでにいい感じの骨組みを作ってくれている！

<img width="259" alt="スクリーンショット 2020-05-30 19.57.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635139/3e7831e8-a978-276b-5845-befec508016c.png">

# 参考文献
Express
https://expressjs.com/en/starter/generator.html

###### 投稿の経緯
はじめまして。私は、独学でプログラムを勉強しており、
縁あって、Expressに遭遇したため、アウトプットの一環として残しました。
すごく便利そうだけれど、まだExpressの凄さをよく理解できてないので、
ドキュメントを読み込んで、Qiitaで共有したいです。
Scalaのコンパイルを import の簡略化をやめて高速化したメモ

Scalaのコンパイルが月毎に遅くなっていったため、調査した。


原因はSlickテーブルの自動生成コードであった。テーブルが増え、行数が増え、Classが増え(ry　となっているが、どうも6000行のファイルを、
`import ._`

のように一括でインポートしていたのが不味かったのが分かった。


改善

- 自動生成コードの中で、使用している必要なテーブルのみ抽出する。（使用されていない Class も大量に混ざっていたため）
  - ファイル行数が、6000行→1000行に。 class定義数も1/6くらいに。
- `import .{ *Table, *TableRow }` のようにちゃんと指定してimportする
- `build.sbt` に記述

コンパイル時間が、300秒越え→ 80秒になった。