OmniAICreator/Qiita-1.07M huggingface dataset:
【初期導入がおすすめ】Tailwind.macro + emotionでデザインシステムベースのCSS-in-JSをしよう

# はじめに

*Tailwind.macro* + *emotion*によって、**迅速かつ保守性の高いコードベース**が構築できます。

どうやって？

まずはライブラリの紹介をします。

# ライブラリの紹介

- [tailwind.macro](https://github.com/bradlc/tailwind.macro)

[TailwindCSS](https://tailwindcss.com/)を[babel-plugin-macros](https://github.com/kentcdodds/babel-plugin-macros)を通して、使えるようにしたものです。

（Tailwindについては公式が一番ですが、[日本語の素晴らしい記事](https://qiita.com/oedkty/items/68461080515ec1012980)もありますよ。⇒手前味噌）

（※ *babel-plugin-macros*は、コンパイル時のコード変換に関するBabel Pluginです。今度別記事にまとめてみようかと思っています ⇒ [まとめました](https://qiita.com/oedkty/items/65c2d29f9e34bed9ac17)）

<font color="red">**どうやら[twin.macro](https://github.com/ben-rogerson/twin.macro)というものが出ている模様で、きちんとメンテナンスされてそうなのはこちらになりそうです。時間を見つけて、更新しようと思います。**</font>

- [emotion](https://emotion.sh/docs/introduction)

CSS-in-JSのライブラリで、*styled-component*などに影響を受けています。

詳しくは、[こちらの記事](https://qiita.com/__sakito__/items/d240840eef7123f62acf)がおすすめです。

**これらを組み合わせると、**

```javascript
import styled from "@emotion/styled"
import tw from "tailwind.macro"

const Button = styled.button`
  ${tw`bg-blue-500 px-5`}
`
```

`tw`は*babel-plugin-macros*によってコンパイルされます。

ではインストールしていきましょう。

# 前提

*babel-plugin-macros*を利用する上で必要になります。

1. *babel-plugin-macro*のインストール

```bash
npm install --save-dev babel-plugin-macros
```

2. `.babelrc` の設定

```json
{
  "plugins": ["macros"]
}
```

これら導入についての詳細は、こちらにあります。

さらに、*GatsbyJS* や *Create React App* **を使っている場合は、必要ありません**。

# インストール

まず、NPMパッケージのインストールです。

```bash
npm install --save tailwindcss tailwind.macro@next @emotion/core @emotion/styled
```

※ 2020/02/15日時点で、最新の*TailwindCSS*と*tailwind.macro*を組み合わせるには、*tailwind.macro@***next**が必要です。

TailwindCSSを初期化します。

```bash
npx tailwindcss init
```

これで、`tailwindcss.config.js`というファイルがルートフォルダにできます。

あとは使うだけです！

※ このマクロだけだとTailwindCSSのcss resetなどのベーススタイルは効かないので、必要に応じて

```css
@tailwind base;
@tailwind components;
```

を作って、読み込んでおきましょう。

ちなみに`.container`クラスを使わないなら、`@tailwind components`も不要になります。

# 嬉しさ

これらのライブラリを**初期に導入しておくこと**の嬉しさは、

この２つの性質を**兼ね備えている**ことです。

- 素早さ

**導入・実装が恐ろしく速い**です。

初期開発では、スピードが命でしょうから、素早いに越したことはないです。

- 拡張性

1. *TailwindCSS* のデザインシステムは**拡張可能**で、

2. *emotion* は、コンポーネント内で**再利用しやすい最小単位として存在し続ける**ことができます。

これら２つはアジリティが求められる現代の開発に、最適であることは言うまでもないでしょう。

- **初期の開発は、早ければいいってものではない**

> 後のコストも含めた ROI まで考えて作る

そんな開発者としての「エチケット」を、強力にサポートしてくれるライブラリの紹介でした。
地獄のフォントHellveticaでコーディングしてみたら発狂した

# はじめに
Twitterを覗いているとこんな投稿を見つけました。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">“地獄”からやってきたフォント「Hellvetica」、その恐るべき破壊力（2019）<a href="https://t.co/3RBc2pOuzG">https://t.co/3RBc2pOuzG</a></p>&mdash; WIRED.jp (@wired_jp) <a href="https://twitter.com/wired_jp/status/1228506749168021505?ref_src=twsrc%5Etfw">February 15, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

Helveticaって良く見るフォントだし、何が地獄なんだろうと思いましたが、公式サイトを見ると確かに地獄のようなフォントが掲載されていました。

というか、よくよく見たらHelveticaじゃなくて、**Hell**vetica。
地獄か。

これでコーディングしたらさぞ地獄なんだろうなと思いながらも、ちょっとした好奇心で試すことにしました。

# 試した環境
- MacBook Air (13-inch, Early 2015) Mac OS Catalina
- Visual Studio Code バージョン 1.39.2

# Helveticaをインストールする
まずは地獄のフォントHellveticaをインストールします。
[Hellveticaの公式サイト](https://hellveticafont.com/)のDownloadを押すとttfファイルをダウンロードできます。
あとはダウンロードしたttfファイルをダブルクリックするだけです。

インストール時にフォントファイルに問題が見つかった可能性がありますという警告が出ましたが、無視してインストールして使えたので、インストールする人は無視しても大丈夫だと思います。

# Visual Studio Codeにフォントを適用する
これに関しては本記事から逸れますが、一応書いておきます。
`Cmd + ,`で設定を開き、fontと検索するとエディタのフォント設定が出てきますので、そこの一番先頭にhellveticaと追記すればOKです。

# 実際に発狂する
実際に簡単なコードをRubyとPythonで書いて発狂してみました。
発狂するポイントも載せておきます。

## Rubyの場合

![スクリーンショット 2020-02-15 13.35.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68663/b98e7efa-b20f-86a7-5000-34a521ac4a63.png)

- `class`がもはや`class`に見えない
- `end`の`n`と`d`の間の微妙なスペースがかなり気になる
- 7行目と8行目に関しては`5`の左側のスペースが大きめなのか、微妙にずれていて発狂しそう

## Pythonの場合

![スクリーンショット 2020-02-15 13.37.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68663/28a2d96f-03c9-1ab8-4de7-ee1755b64e45.png)

- `:`の幅が小さすぎるのか、3行目の`:`に関してはあるかないか注意深く見ないと分からない
- `return`が`ret`と`urn`で別のキーワードみたいに見える
- `urn`に関しては`r`と`n`の間のスペースが小さすぎて`um`と見えそう
- 4行目、8行目、9行目のインデントは同じ深さなのに違うように見える。インデント命のPythonでは本当に発狂しそう


# まとめ
今回は**Hellvetica**という地獄のフォントでコーディングしてみました。
業務では見やすいフォントでコーディングしましょう。
それではまた。
【Emacs】Elispパッケージマネージャ package.elの使い方まとめ 

# EmacsのElispパッケージ管理
EmacsはElispを使って機能を自由自在位に拡張できる．Emacs 24以降からは標準搭載されている[package.el](https://emacs-jp.github.io/packages/package-management/package-el)を使って，Elispを管理するようになっている．この記事ではpackage.elの使い方をまとめる．

# package.elの使い方
package.elを使ってElispをインストールするには，ELPA(Emacs Lisp Package Archive)というElisp専用のパッケージリポジトリを通してインストールを行う．利用できる代表的なリポジトリは以下の通り(package.elのWebサイト引用)．

## ELPA一覧

### [GNU ELPA](http://elpa.gnu.org/packages/)
公式のリポジトリ. デフォルトの設定では, このリポジトリしか利用することはできない. 登録に手間がかかるためか, 登録されているパッケージ数は少なめであるが, 他の リポジトリに比べると登録されているパッケージの信頼度は高い.

### [Marmalade](https://github.com/timvisher/marmalade)
非公式のリポジトリ. アカウントを作れば誰でもパッケージを登録することが可能. MELPAにも登録されているパッケージの場合, 安定版のパッケージを Marmaladeにアップロードすると いう使われ方が多い.

### [MELPA](https://melpa.org/#/)
非公式のリポジトリ. githubのリポジトリに pull requestを 送ることで, パッケージを登録することができる. リポジトリに変更がある度に更新されるので, 登録されて いるパッケージの最新版をインストールすることができる(stable版もインストールできるようにする流れが あるが 2013年 9月 24日時点で未実装).

### [MELPA-stable](https://stable.melpa.org/#/)
安定版 MELPA. 最新のリビジョンでなく, 最新のタグのバージョンが取得できる.

## ELPAの登録・追加
```init.el
(require 'package)

;; HTTP 系のリポジトリ
(add-to-list 'package-archives '("marmalade" . "http://marmalade-repo.org/packages/") t)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
(add-to-list 'package-archives '("melpa-stable" . "http://stable.melpa.org/packages/") t)

(package-initialize) ; インストール済みのElispを読み込む
```
package-initialize関数によって，インストールされたElispが読み込まれるようになる．

## パッケージ一覧の取得
`M-x list-packages`で登録したリポジトリのパッケージ一覧を取得できる．

<img width="867" alt="スクリーンショット 2020-02-15 13.21.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517036/07083624-731e-0c6c-830e-d68dc6a2be5c.png">

この画面ではpackage-menu-modeというメジャーモードになる．操作は以下の通り．

| キー     |     説明 |
|:-----------------|:-------------------|
| h | 操作ヘルプを表示 |
| p | 前の行へ |
| n | 次の行へ |
| ?, RET | パッケージの説明を取得 |
| i | インストール候補としてマーク |
| U | アップデート可能なパッケージを全てマーク |
| d | 削除候補としてマーク |
| DEL | 1行上のマークを外す |
| u | 現在行のマークを外す |
| x | マークしたパッケージをインストール / 削除
| r | パッケージ一覧をリフレッシュ |
| q | ウィンドウを閉じる |
| f | フィルターで絞り込む (g or q で解除) |

パッケージをインストールすると~/.emacs.d/elpa以下に保存され，自動でバイトコンパルされる．
インストールされたパッケージを利用するために，`M-x package-initialize`を実行する．

コマンドから直接インストールするには，`M-x package-install RET XXXX RET`を実行する．
Raspberry Piのオーバーレイファイルシステム(Read Only)

自分用メモ

[スタート]-[設定]-[Raspberry Piの設定]-[パフォーマンスタブ]に「Overlay File System」なるものがあるのでそこで設定できそう。（まだ試してはいない:sweat:→その後試してみたらオーバーレイできた！:grin:）

ちなみにこれはRaspberry Pi 4(4GB)バージョンで実行したもの。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390938/c9370bfd-0748-2cea-2c70-0cf5c3f874b7.png)
Backbone.js - コレクション

# 概要
Collectionで任意のリストを作り操作してみる

## ローカル環境準備
dockerでnginxを起動して環境を整える。

```bash:ターミナル
$ docker-compose build
$ docker-compose up -d
```
※ 学習ように作ったコードはgithubにアップしています
https://github.com/reflet/sample-backbone.js

## サンプルコード
Ajax通信などせず、任意にリストを生成して制御してみる。

```html:./src/html/collection2.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>Backbone.js学習 [Collection]</title>
</head>
<body>
    <h1>Collection</h1>
    <p>Collectionを使ってみる</p>

    <script src="https://cdn.jsdelivr.net/npm/underscore@1.9.1/underscore.min.js"></script>
    <script src="https://cdn.jsdelivr.net/gh/jquery/jquery@3.4.1/dist/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/backbone@1.4.0/backbone.min.js"></script>
    <script>
        // Model
        const Person = Backbone.Model.extend({
            defaults: {
                country: '日本',
                prefecture: '東京',
                name: '',
                age: null,
            }
        });

        // Collection
        const Users = Backbone.Collection.extend({model: Person});
        const users = new Users();
        users.add({name:'次郎', age:28});
        users.add({name:'花子', age:25, prefecture:'大阪'});
        users.add({name:'三郎', age:32});
        users.add({name:'田中', age:25, prefecture:'名古屋'});
        console.log('dump1', users.toJSON());

        // 名前だけ取得する
        console.log(users.pluck('name'));

        // 全件取得する
        users.each(function(user) {
            console.log(user.toJSON());
        });

        // 年齢が25歳のユーザーのみ取得する
        $.each(users.where({age:25}), function(e,user) {
            console.log(user.toJSON());
        });

        // 最後のデータ要素を削除する
        users.pop();
        console.log('dump2', users.toJSON());

        // 指定した要素を削除する
        users.remove(users.at(1)); // 2番目
        console.log('dump3', users.toJSON());

        //すべてのデータを削除する
        users.reset();
        console.log('dump4', users.toJSON());
    </script>
</body>
</html>
```

## 動作確認
正常に処理できているようです。
![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142279/e12aeca7-eeed-c852-9d6d-4ef05f0b9df4.png)

## まとめ
1つのデータは、Modelで取り扱い、データの集合としてCollectionがあるといった感じで
割とシンプルな構成でわかりやすいですね。

## 参考サイト
- [github - backbone.js](https://github.com/jashkenas/backbone/blob/master/backbone.js)
- [Backbone.jsの基本チュートリアル](https://www.sejuku.net/blog/106675)
- [Backbone.js入門 「Collection」](https://qiita.com/yuku_t/items/c19d2fff0dc23e4015ff)
かんたんなレスポンシブルテーブル

## col使ってますか

`<table>`タグの中にちゃんと`<col>`を入れていますか？
自分は`<col>`の存在を知るまで数年かかりました。
使ってみたら本当に便利だったのでまずは基本的な使い方から。

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="sphenisc" data-slug-hash="JjdGvgg" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="JjdGvgg">
  <span>See the Pen <a href="https://codepen.io/sphenisc/pen/JjdGvgg">
  JjdGvgg</a> by sphenisc (<a href="https://codepen.io/sphenisc">@sphenisc</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

本来CSSでthやtdの長さを指定していと中身のテキスト量に応じて自動でthやtdの横幅が変化するのですがcolにそれぞれ25% 25% 50%と指定しているためキレイに表示できています。
widthの数値を変更してもこの割合は維持されるので最近のレスポンシブ環境の適正が高そうです。

## 応用
<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="sphenisc" data-slug-hash="RwPrBWM" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="RwPrBWM">
  <span>See the Pen <a href="https://codepen.io/sphenisc/pen/RwPrBWM">
  RwPrBWM</a> by sphenisc (<a href="https://codepen.io/sphenisc">@sphenisc</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

## SP幅にすると変形するテーブル
<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="sphenisc" data-slug-hash="MWwKNEO" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="MWwKNEO">
  <span>See the Pen <a href="https://codepen.io/sphenisc/pen/MWwKNEO">
  MWwKNEO</a> by sphenisc (<a href="https://codepen.io/sphenisc">@sphenisc</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
このぐらいの文字数なら変形しないほうが見やすいですが文字数が増えると便利。かも
jupyter lab の extension を install するためには git が必要な場合あり

jupyter lab に関わる環境構築の Tips です。2020年2月のメモです。

#### 前提 
Windows10, anaconda (miniconda)

`python 3.7.6`
`jupyterlab 1.2.6`
`nodejs 13.8.0`

`conda install -c conda-forge jupyterlab`
`conda install -c conda-forge nodejs `
 
などで作った環境です。

#### インストールできない状態
インストラクション通りに node.js をインストールしても、extension のインストールに失敗します。エラーログに、こういう記載がありました。
 
``` jupyterlab-debug-xxxxxxxx.log
......
yarn install v1.15.2
[1/5] Validating package.json...
[2/5] Resolving packages...
error Couldn't find the binary git
......
```

明示されていない前提条件として、コマンドラインで git が使える必要がある場合があるようです。（そもそもなぜ git が入ってないのか、とは聞かないでください）
#### 対策
安直ですが、git も conda で入れてしまいます。

```
conda install git

jupyter labextension install @jupyter-widgets/jupyterlab-manager k3d
```
エラー無く機能拡張がインストールできるようになりました。
Backbone.js - コレクション (Ajax)

# 概要
Backbone.jsのコレクションでAjax通信してリストを動的に取得してみる。

## ローカル環境整備
dockerでnginxを起動して環境を整える。

```bash:ターミナル
$ docker-compose build
$ docker-compose up -d
```
※ 学習ように作ったコードはgithubにアップしています
https://github.com/reflet/sample-backbone.js

## Ajax通信の準備
Collectionで扱うデータをAjaxで非同期通信にて取得するため、jsonファイルを準備する。

```json:./src/html/api/users.json
[
  {"country": "日本", "prefecture": "東京都", "name": "太郎", "age": "30"},
  {"country": "日本", "prefecture": "大阪府", "name": "次郎", "age": "28"},
  {"country": "日本", "prefecture": "愛知県", "name": "花子", "age": "25"},
  {"country": "日本", "prefecture": "福岡県", "name": "三郎", "age": "15"},
  {"country": "日本", "prefecture": "東京都", "name": "四郎", "age": "25"}
]
```

## サンプルコード
Ajaxで動的にデータを取得するCollectionを作成してみました。
※ データの取得先： GET http://localhost:8080/api/users.json

```html:./src/html/collection1.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>Backbone.js学習 [Collection]</title>
</head>
<body>
    <h1>Collection</h1>
    <p>CollectionでAjax通信して動的にデータを取得する</p>

    <script src="https://cdn.jsdelivr.net/npm/underscore@1.9.1/underscore.min.js"></script>
    <script src="https://cdn.jsdelivr.net/gh/jquery/jquery@3.4.1/dist/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/backbone@1.4.0/backbone.min.js"></script>
    <script>
        // Model
        const Person = Backbone.Model.extend({
            defaults: {
                country: '日本',
                prefecture: '東京',
                name: '',
                age: null,
            }
        });

        // Collection
        const Users = Backbone.Collection.extend({
            model: Person,
            url: '/api/users.json',
            parse: function(response){
                console.log(response);
                return response;
            }
        });
        const users = new Users();
        users.fetch().done(function(users){
            $.each(users, function(index, user){
                console.log(index, user);
            });
        });
    </script>
</body>
</html>
```

## 動作確認
正常にデータが取得できたようです。
![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142279/abe1f4c8-8c97-2140-53a9-99ce104cb3d0.png)

## 参考サイト
- [github - backbone.js](https://github.com/jashkenas/backbone/blob/master/backbone.js)
- [Backbone.jsの基本チュートリアル](https://www.sejuku.net/blog/106675)
- [Backbone.js入門 「Collection」](https://qiita.com/yuku_t/items/c19d2fff0dc23e4015ff)
Vue-cli-uiを起動しようとして失敗する時

備忘録です。

```
$ cd yourproject
$ source ~/.bashrc
$ vue ui
🚀  Starting GUI...
🌠  Ready on http://localhost:8000
```

んで`http://localhost:8000`が真っ白だった時、ありませんか？
`Chrome`のデベロッパーツールを見ると、こんなエラーが出ている時

```
GET https://unpkg.com/vue-cli-locales@4.0.5/locales/jp.json 404
```

なんか`vue-cli-locales`に対応する日本語ファイルがない時があるみたいです。
※ネットにつながってない時にも、このエラーが出ることがあります。

##結論：対応してる日本語ファイルがあるバージョンを選ぶ。
`ja.json`がちゃんと入ってる`@vue/cli`のバージョンを選んだら良い。
https://unpkg.com/browse/vue-cli-locales@4.1.2/locales/

`@vue/cli`をアンインストールして、もっかい入れる。
また、ブラウザの言語設定を英語にしてしまえば、このエラーは出ないらしい。

##それでも起動に失敗する
何回も`@vue/cli`をインストールしたり、アンインストールしたりを
繰り返していると、vue-cli-uiが起動しなくなる場合があります。

Chromeのデベロッパーツールを見ると、こんなエラーが出ている時。

```
GraphQL error:Cannot read property 'homepage' of undefined
```
`GraphQL`？`homepage`？何これという時の解決法。

#結論：ホームディレクトリにある「.vue-cli-ui」を消す。

隠しフォルダごと消しても`db.json`だけ消しても良いと思います。
何回も`@vue/cli`を入れ直した場合にバグるらしいです。
隠しファイルが見えない人は、

```
$ defaults write com.apple.finder AppleShowAllFiles TRUE
$ killall Finder
```

以上です。

###参考にした記事
https://github.com/vuejs/vue-cli/issues/2914
https://github.com/vuejs/vue-cli/issues/4259
iOS開発メモ

# UICollectionView In UITableViewCell の高さ調整メモ

`collectionView.isScrollEnabled = false` にしておく。

```swift
    // viewDidLayoutSubviewsの初回判定用のフラグ
    var isFirstLayoutSubviews = true

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        guard isFirstLayoutSubviews else { return }
        // ここで調整
        collectionView.reloadData()
        tableView.reloadData()
        isFirstLayoutSubviews = false
    }

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        // TableViewCellの高さをCollectionViewのContentSizeの高さにする
        return collectionView.collectionViewLayout.collectionViewContentSize.height
    }
```
# UITextView in UITableViewCel の高さ変更メモ

```swift
class ViewController: UITextViewDelegate {
    
    var currentKeyboardHeight: CGFloat = 0

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        addObservers(showSelector: #selector(showKeyboard), hideSelector: #selector(hideKeyboard))
    }

    @objc func showKeyboard(_ notification: Notification) {
        currentKeyboardHeight = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height ?? 0
    }

    func textViewDidChange(_ textView: UITextView) {
        // TextViewの中身によってcellの高さを必要に応じて変えている
        let oldHeight = textView.bounds.height
        let newHeight = textView.sizeThatFits(CGSize(width: textView.bounds.width, height: CGFloat.greatestFiniteMagnitude)).height
        
        if oldHeight != newHeight {
            let cellRect = tableView.rectForRow(at: IndexPath(row: 4, section: 0))
            let memoTextViewTopLine: CGFloat = tableView.convert(cellRect, to: self.view).minY
            let newBottomLine = memoTextViewTopLine + newHeight
            let keyboardTopLine: CGFloat = view.bounds.height - currentKeyboardHeight
            
            if newBottomLine >= keyboardTopLine {
                // キーボードに隠れる高さになったらスクロールするようにして回避
                textView.isScrollEnabled = true
            } else if textView.isScrollEnabled {
                // テキストを削除して、隠れない高さになった直後は高さがずれるのでtableView.beginUpdates()とかしない
                textView.isScrollEnabled = false
            } else {
                // それ以外はスクロールを無効化してセルの高さを変更する
                textView.isScrollEnabled = false
                tableView.beginUpdates()
                tableView.endUpdates()
            }
        }
    }
    
    func textViewDidEndEditing(_ textView: UITextView) {
        tableView.contentOffset.y = 0
    }
}

```

編集時に初期値いれて、中身に応じて高さを合わせるときは、viewDidLoad()の中でこれでいけた。
tableView.performBatchUpdates(nil, completion: nil)を呼ぶと表示が崩れた。

```swift
if let memo = edit?.memo {
    memoTextView.text = memo
    memoTextView.layoutIfNeeded()
}
```
clangを使った変数定義の分類

```
$ clang --version
clang version 5.0.1-4 (tags/RELEASE_501/final)
```

clangでは、定義されている変数を以下のように分類できる。

|file  |function  | CODE  | Linkage  | isStaticLocal  |isFileVarDecl  | isLocalVarDecl |
|:----:|:--------:|:--:|:--:|:--:|:--:|:--:|
|header|none| int global_h = 0  | Linkage:6=clang::ExternalLinkage  | 0  | 1  | 0 |
|header|none| static int static_h = 0  | Linkage:1=clang::InternalLinkage  | 0  | 1  | 0 |
|header|none| thread_local int thread_h = 9  | Linkage:6=clang::ExternalLinkage  | 0  | 1  | 0 |
|source|none| extern int ext_global2  | Linkage:6=clang::ExternalLinkage  | 0  | 1  | 0 |
|source|none| struct _str st_global = {1, &global, global, 0}|Linkage:6=clang::ExternalLinkage|0|1|0|
|source|none| union _uni u_global ={0}  | Linkage:6=clang::ExternalLinkage  | 0  | 1  | 0 |
|source|none| static int static_module = 2  | Linkage:1=clang::InternalLinkage  | 0  | 1  | 0 |
|source|function| int (*func)() = local_func  | Linkage:0=clang::NoLinkage  | 0  | 0  | 1 |
|source|function| int local = TWO  | Linkage:0=clang::NoLinkage  | 0  | 0  | 1 |
|source|function| static int static_var = argc  | Linkage:0=clang::NoLinkage  | 1  | 0  | 1 |
環境変数でgitのプロキシ設定するなら Git Bashとコマンドプロンプトでやり方が違うよ

# 概要

「Windowsで、コマンドプロンプトとGit Bashを同時に使かもしれない人」かつ「環境変数でgitのプロキシ設定する人」という狭い範囲向けの話。

# 結論

環境変数でgitのプロキシ設定するなら、

- コマンドプロンプトは、setで環境変数の設定
- Git Bashは、exportで環境変数の設定

ということを思い出す・・・もしくは、

[一時的にproxyを有効_無効にしてgit cloneする方法 - Qiita][1]の

```
git clone <repository-url> -c http.proxy="http://<proxyserver>:<port>" -c https.proxy="https://<proxyserver>:<port>"
```

を使おう。

以下、詳細

# 詳細

コマンドプロンプト、Cmder、バッチファイルでは以下のようにしてました。

```
> set http_proxy=http://<proxyserver>:<port>
> set https_proxy=https://proxyserver>:<port>
> git clone <repository-url>
```

普段あまり使わないGit Bashを使ってみたら・・・

```bash
$ set http_proxy=http://<proxyserver>:<port>
$ set https_proxy=https://proxyserver>:<port>
$ git clone <repository-url>
Cloning into '<repository>'...
fatal: unable to access '<repository-url>': The requested URL returned error: 403
```

あら？cloneできない。

「[http経由の git コマンド(push,clone,fetch..)等がなんかうまく動かないときにデバッグする方法[2]」を試そう。

```bash
$ GIT_CURL_VERBOSE=1 git clone <repository-url> 
Cloning into '<repository>'...
* Couldn't find host <repository-host-server> in the _netrc file; using defaults
*   Trying <repository-host-server> ...
...略...
* Connected to <repository-host-server> (<ipaddress>) port 80 (#0)
> GET <repository-url>/info/refs?service=git-upload-pack HTTP/1.1
Host: <repository-host-server>
...略...
< HTTP/1.1 403 Forbidden
...略...
* Connection #0 to host <repository-host-server> left intact
fatal: unable to access '<repository-url>': The requested URL returned error: 403
```

`HTTP/1.1 403 Forbidden`が返ってきてる。

設定したはずの`<proxyserver>`が全く登場してない。

setが効いてない？

[Set an environment variable in git bash - Stack Overflow][4]

> You can combine the assignment with the export statement.
> `export HOME=c`

[Set an environment variable in git bash - Stack Overflow][3]

> (export if I am on Unix, or a simple set on Windows)


あ。Git「Bash」か。

あと、コマンドプロンプトは、`"http://<proxyserver>:<port>"`のようにダブルクオーテーションで囲むとエラーになるけど、

```
> set http_proxy="http://<proxyserver>:<port>"
> set https_proxy="https://proxyserver>:<port>"
> git clone <repository-url>
fatal: unable to access '<repository-url>': Unsupported proxy syntax in '<proxyserver>:<port>"'
```

Git Bashはエラーにならないよ。

```bash
$ export http_proxy="http://<proxyserver>:<port>"
$ export https_proxy="https://<proxyserver>:<port>"
$ git clone <repository-url>
Cloning into '<repository>'...
remote: Counting objects: 50, done.
remote: Compressing objects: 100% (45/45), done.
remote: Total 50 (delta 13), reused 0 (delta 0)
Unpacking objects: 100% (50/50), done.
```



[1]:https://qiita.com/ysm001/items/e1530d5449fb2c03ffb2
[2]:http://tanacasino.hatenablog.com/entry/2013/07/23/003000
[3]:https://stackoverflow.com/questions/19523903/how-to-temporarily-disable-git-http-proxy
[4]:https://stackoverflow.com/questions/34169721/set-an-environment-variable-in-git-bash
Backbone.js - モデル(Ajax)

# 概要
Backbone.jsのモデルを使ってみる

## ローカル環境整備
dockerでnginxを起動して環境を整える。

```bash:ターミナル
$ docker-compose build
$ docker-compose up -d
```
※ 学習ように作ったコードはgithubにアップしています
https://github.com/reflet/sample-backbone.js

## AJAX通信の準備
Modeで扱うデータをAjaxで非同期通信にて取得するため、jsonファイルを準備する。

```json:./src/html/api/user/1.json
{"country": "日本", "prefecture": "東京都", "name": "太郎", "age": "30"}
```


## サンプルコード
Ajaxで動的にデータを取得するModelを作成してみました。
※ データの取得先： `GET http://localhost:8080/api/user/1.json` 

```html:./src/html/model1.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>Backbone.js学習 [Model]</title>
</head>
<body>
    <h1>Model</h1>
    <p>ModelでAjax通信して動的にデータを取得する</p>
    <script src="https://cdn.jsdelivr.net/npm/underscore@1.9.1/underscore.min.js"></script>
    <script src="https://cdn.jsdelivr.net/gh/jquery/jquery@3.4.1/dist/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/backbone@1.4.0/backbone.min.js"></script>
    <script>
        const Person = Backbone.Model.extend({
            urlRoot: '/api/user',
            url: function () {
                var url = Backbone.Model.prototype.url.apply(this);
                return (this.isNew()) ? url : url + '.json';
            },
            parse: function (response) {
                response.datetime = new Date(response.datetime);
                return response;
            }
        });

        var user = new Person({id: 1});
        console.log(user.url()); // /api/user/1.json

        // Ajax通信でデータを取得する
        // ※ GET /api/user/1.json
        user.fetch()
            .done(function(user){
                console.log(user);
            });

        // Ajax通信でデータを取得する ← GETパラメータを追加してみる
        // ※ GET /api/user/1.json?limit=5&offset=0
        user.fetch({data:{limit: 5, offset: 0}})
            .done(function(user){
                console.log(user);
            });
    </script>
</body>
</html>
```

## 動作確認
正常にデータが取得できたようです。
![asmple.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142279/8e13eea0-d3b8-7dc1-e5f1-c57424a24510.png)

## まとめ
Ajax通信する際、IDを自動でURLに追加してくれるのはいい。
しかし、`.json`という拡張子をリクエストするURLに追加したくて調べるたがなかなか見つからず...

そのため、backbone.jsのurlのプログラムを参照して上書きする形で書いてみる。

## 参考サイト
- [github - backbone.js](https://github.com/jashkenas/backbone/blob/master/backbone.js)
- [Backbone.jsの基本チュートリアル](https://www.sejuku.net/blog/106675)
- [Backbone.js入門 「Model」](https://qiita.com/yuku_t/items/5acef8dd49f67fd7813c)
- [Backbone.jsのModel.fetch で RESTful API から情報取得](https://qiita.com/ledsun/items/d1146682e409c0687a1a)
DELPHIのプロジェクトでライブラリにパスを通す方法

久しぶりにdelphiを使ったら、外部のライブラリをプロジェクトに追加する方法が分からなかったのでメモ

[プロジェクト]→[オプション]
下記のフォームの
[ビルド]→[Delphiコンパイラ]→[検索パス]

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/b5d04442-da83-4a86-81ee-0d2b831d6a9a.png)
追加したい構成を選んで追加したいライブラリのフォルダを指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/65278672-c581-7beb-358b-e618841da304.png)
学習メモ / 2進数の補数

2進数の補数とは？補数を使って何が出来るかをまとめます。

###何が出来る？
「補数」を使えば、2進数でマイナスを表現出来る。例えば、２進数同士の引き算の計算をするときに使える。

###補数とは
>Wikipedia
ある基数法において、ある自然数aに足した時、桁が１つ上がる数のうち最も小さい数

####例えば、10進数で考えてみる
ある数に何を足したら10になるか考える。
例えば、４の補数は6（4に6を足すと10になるので）。

次に補数を使って引き算をしてみる。
引き算をするには、「補数を足し、上位の１桁を無視」することで計算できる。

例：
7−4

① 4の補数は6

② 7に補数を足す
= 7+6
= 13

③ 10の位を無視する
= 3

###２進数でやってみる
流れは一緒なので、2進数で引き算をしてみる。
やり方は、同じく「補数を足し、上位の１桁を無視」。

例：
1111 - 1101 (10進数では15 - 13)

① まず、1101の補数を求める。
1101の補数 = 0011

2進数の補数の求め方：
ビットを反転させて1を足す。

1101 
↓   反転
0010
↓　1を足す
0011

なので、1101の補数は0011

補数であるか確認してみる。
1101 + 0011 = 10000 (桁が1つ上がったので補数)

② 補数を足し 
1111 + 0011 = 10010

③ 上位の１桁を無視
0010

結果:0010(10進数で2)
gulpでscssファイルをcssにコンパイルしてもcssの更新日が変わらない問題

コンパイルしたcssをsftp使ってサーバー上にあげたいなと思いやってみたらものすごく苦戦してしまってその時のことをまとめます。

#問題点
なぜかscssをgulpでcssにコンパイルしても更新日が変わらずwatch出来ず苦戦してました。
きっと内容が更新されてるだけで保存されてないんでしょうね。しみじみ

##やったこと
とりあえずファイルが更新されれば一件落着なので下記のプラグインを入れるだけでした。

```
yarn
yarn global add through2

npm
npm install -g gthrough2
```
```
const gulp = require('gulp');
const sass = require('gulp-sass');
const through2 = require('through2');

gulp.task('scss', function () {
  return gulp.src(['scss/*.scss'])
    .pipe(plumber())
    .pipe(sass({ outputStyle: 'expanded' }))
    .on('error', sass.logError)
　　　// 更新日を書き換える
    .pipe(through2.obj((chunk, enc, callback) => {
      const date = new Date();
      chunk.stat.atime = date;
      chunk.stat.mtime = date;
      callback(null, chunk);
    }))
    .pipe(gulp.dest('css/'));
});
```
これで無事cssファイルが更新されwatchが出来てサーバーに上げることが出来ました。
VuetifyとNetlify Formsを使ったときに躓いたところ


Nuxt, Vuetifyで簡単なページを作り、Netlifyでページを公開しようとした際に、躓いたときのメモです。  

問合せフォームをつけていたので、Netlify Formsを使いました。  

> Code an HTML form into any page on your site, add a `netlify` attribute or `data-netlify="true"` to the `<form>` tag

Netlifyでフォームを使うには、`form`タグに`netlify`属性をつけ、`<form netlify>`とするだけです。  

ただ、Vuetifyでは、単に`<v-form netlify>`としてもうまく動作しませんでした。  


> Netlify automatically adds a hidden field to your published form called `form-name` with a value to match the `name` attribute of the form when you submit an HTML form

Netlifyは、自動的に`name="form-name"`を持ったテキストフィールドをつけているようです。  

そこで、以下のようにフォームを書きました。


```vuejs:contact.vue
<template>
  <v-container tag="section">
    <v-row>
      <v-col
        v-text="title.toUpperCase()"
        cols="12"
        tag="h1"
      />
    </v-row>
    <v-form method="post" netlify>
      <v-text-field
        v-show="false"
        v-model="title"
        name="form-name"
      />
      <v-row>
        <v-col cols="12">
          <v-text-field
            v-model="name"
            label="name"
            name="name"
            autofocus
          />
        </v-col>
      </v-row>
      <v-row>
        <v-col cols="12">
          <v-text-field
            v-model="email"
            label="E-mail"
            name="email"
          />
        </v-col>
      </v-row>
      <v-row>
        <v-col cols="12">
          <v-textarea
            v-model="message"
            label="message"
            name="message"
          />
        </v-col>
      </v-row>
      <v-row>
        <v-col>
          <v-btn
            :disabled="isEmpty"
            type="submit"
          >
            submit
          </v-btn>
        </v-col>
      </v-row>
    </v-form>
  </v-container>
</template>

<script>
export default {
  data () {
    return {
      title: 'contact',
      name: '',
      email: '',
      message: '' 
    }
  },
  computed: {
    isEmpty () {
      if (
        this.name !== '' &&
        this.email !== '' &&
        this.message !=='' 
      ) {
        return false
      }
      return true
    }
  }
}
</script>
```



↓ フォームの見た目
![contact.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230954/f03bcc49-fcd1-9c27-4ec9-c12271a03b2d.jpeg)


このように、

```vuejs
<v-form method="post" netlify>
  <v-text-field
    v-show="false"
    v-model="title"
    name="form-name"
  />
```
`v-form`に`netlify`属性をつけて、  
`v-show="false" v-model="title"`をつけた`v-text-field`を`v-form`下に置くと、正常に動作します。


## 参考

- [netlify docs (Forms setup)](https://docs.netlify.com/forms/setup)
backbone.js - 環境準備

# 概要
普段は、vue.jsなどを使っていますが、backbone.jsを使うことがあったので、学習してみる。

## ローカル環境整備
dockerでnginxを起動して環境を整える。

```bash:ターミナル
$ docker-compose build
$ docker-compose up -d
```
※ 学習ように作ったコードはgithubにアップしています
https://github.com/reflet/sample-backbone.js

## サンプルコード
とりあえず、必要なjsを読み込んで、動かしてみました。

```html:./src/html/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>Backbone.js学習</title>
</head>
<body>
    <h1>TOP Page</h1>
    <p>ひとまず動く環境を整えてみる。</p>
    <script src="https://cdn.jsdelivr.net/npm/underscore@1.9.1/underscore.min.js"></script>
    <script src="https://cdn.jsdelivr.net/gh/jquery/jquery@3.4.1/dist/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/backbone@1.4.0/backbone.min.js"></script>
    <script>
        const Person = Backbone.Model.extend({
            defaults: {
                country: '日本',
                prefecture: '東京',
            },
            hello: function() {
                console.log('こんにちは、' + this.get('name') + 'さん');
            }
        });
        const user = new Person({name: '太郎', age: 30});

        // データ確認
        console.log(user.toJSON()); // {country: "日本", prefecture: "東京", name: "太郎", age: 30}

        // 名前を取得する
        console.log(user.get('name'));

        // 独自定義した関数を実行してみる
        user.hello();
    </script>
</body>
</html>
```

## 動作確認
正常に処理され、コンソールに結果が表示されたようです。
![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142279/1bf3b62d-1805-62bc-6ae7-0fa932b22195.png)

## まとめ
`underscore.min.js`, `jquery.min.js`, `backbone.min.js` を読み込めば使える点は、vue.jsと同じでお手軽で導入コストは低そうですね。

## 参考サイト
- [github - backbone.js](https://github.com/jashkenas/backbone/blob/master/backbone.js)
- [基本チュートリアル](https://www.sejuku.net/blog/106675">Backbone.js)
- [試して学ぶ Backbone.js入門](https://appkitbox.com/testkit/knowledge/javascript/20130315-45)
Ruby　コーティング規約について　コレクション編　2

# はじめに
[コレクション編 1 はこちらをクリック願います。]
(https://qiita.com/raigakun/items/68f96b3704cb9ad6398b)
[命名規則編 2 はこちらをクリック願います。]
(https://qiita.com/raigakun/items/9db169935baa654af90d)
[レイアウト編 3 はこちらをクリック願います。過去記事リンクあり。](https://qiita.com/raigakun/items/7416db5b4d70ea93046e)
[構文編 2 はこちらをクリック願います。過去記事リンクあり。](https://qiita.com/raigakun/items/80ba30671d7b2b18c44e)
Rubyの基礎を学習中の方に向けて記載致します。
私自身これからチーム開発を行う上で大事にしたい。知っておきたいことをOutputします。


##① ハッシュ記法とロケット記法を同じハッシュリテラル内で混在させてはいけない。 

※　シンボルでないキーがある場合は、ロケット記法を使う。

```qiita.rb
# 悪い例
{ a: 1, 'b' => 2 }

# 良い例
{ :a => 1, 'b' => 2 }
```

##② ハッシュのキーがシンボルの時は、ハッシュリテラル記法を用いる。

```qiita.rb
# 悪い例
hash = { :one => 1, :two => 2, :three => 3 }

# 良い例
hash = { one: 1, two: 2, three: 3 }
```

#さいごに
毎日更新します。
皆様の復習等にご活用頂けますと幸いです。
EntityManagerを使った汎用的なSELECT文

## IN句を作りまくる

```EntityManagerを用いたselect.java
package sql;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

public class Sql {
	
	private EntityManager em;

	public <T> T select(Class<? extends Object> clazz, Map<String, List<Object>> conditions) {
		
		String tableName = camelToSnake(clazz.getSimpleName());
		String select = "SELECT entity FROM " + tableName + " entity ";
		
		String state = select + conditions.entrySet().stream()
				.map(Entry::getKey)
				.map(column -> "WHERE " + camelToSnake(column) + " IN :" + column)
				.collect(Collectors.joining(" "));
		
		TypedQuery query = em.createNativeQuery(state, clazz);
		conditions.entrySet().forEach(map -> query.setParameter(map.getKey(), map.getValue()));
		return query.getResultList;
	}
	
	public String camelToSnake(final String camel) {
		final StringBuilder sb = new StringBuilder(camel.length() + camel.length());
		for (int i = 0; i < camel.length(); i++) {
			final char c = camel.charAt(i);
			if (Character.isUpperCase(c)) {
				sb.append(sb.length() != 0 ? '_' : "").append(Character.toLowerCase(c));
			} else {
				sb.append(Character.toLowerCase(c));
			}
		}
		return sb.toString();
	}
}
```

"userName", List("A子", "B太郎")
といったMapを入れて、user_nameというカラムにIN句でリストをバインドするようにしています

NOT INを使いたい場合は、NOT IN用の引数を増やす必要があったり、完全にどんな状況でも使えるわけではありませんが
IN句である以上=よりは便利ですし、IN句も複数指定できるため
かなり汎用的といえるのではないでしょうか
instance_evalについて

# instance_evalの役割・特徴
- instance_evalにブロックを渡すor文字列を引数で渡して、特異クラスを定義
- ローカル変数は引き継ぐ
- 文字列を渡した場合は特異クラスにネスト

```ruby
class C
  CONST = "CONST in C"
end
hoge = "hoge"
CONST = "CONST in main"

c1 = C.new
c1.instance_eval(<<-EOS)
  CONST = "CONST in singleton_c1"
  p hoge
  p Module.nesting
  p CONST
EOS

c2 = C.new
c2.instance_eval do
  CONST = "CONST in singleton_c2"
  p hoge
  p Module.nesting
  p CONST
end
```

## 文字列実行結果
ネストが特異クラスになるのでCONSTは特異クラスで初めて定義される


```
"hoge"
[#<Class:#<C:0x000000000500fb18>>]
"CONST in singleton_c1"
```

## ブロック実行結果
ネストが特異クラスの外になるのでCONSTは外側のものを上書きすることになる

```
rex.rb:17: warning: already initialized constant CONST
rex.rb:5: warning: previous definition of CONST was here
"hoge"
[]
"CONST in singleton_c2"
```
EntityManagerを使った汎用的なDELETE INSERT UPSERT

##TRUNCATE

ロールバックしないので怖いですが、レコード数が多い場合は
テーブルを消してから作り直すことでレコードを全行削除する
TRUNCATEの方が、DELETEよりも高性能ですね

```truncate.java
	@Transactional
	public void truncate(Class<? extends Object> entityClass) {
		em.createNativeQuery("TRUNCATE TABLE " + camelToSnake(entityClass.getSimpleName())).executeUpdate();
	}
```

camelToSnakeは前回に引き続き。
キャメルケースをスネークケースにするもので、その辺にライブラリ転がってると思うので内容は割愛します

##DELETE

```delete.java
	@Transactional
	public void truncate(Class<? extends Object> entityClass) {
		em.createNativeQuery("DELETE FROM " + camelToSnake(entityClass.getSimpleName())).executeUpdate();
	}
```

まぁDELETEも同じですね

##INSERT

```insert.java
	@Transactional
	public void insert(List<Object> entity) {
		entity.forEach(em::persist);
	}
```

一行ずつ、永続化コンテキストの管理下に置くpersistメソッドを施してあげる、そんだけですねぇ

##UPSERT

```upsert.java
	@Transactional
	public void insert(List<Object> entity) {
		entity.forEach(em::merge);
	}
```

mergeを使うと、差分のみupdateしてくれます
EntityManagerまじでえらい


テーブル操作をする時、マルチスレッドでなくてもトランザクションの管理をしっかりしておくべきですね
積もり積もったAMIをまとめて消す

## はじめに

日々バックアップを取得するのは大切ですが
数年分くらいが積もり積もってチリツモで多少なりコストにもなっていたので
大掃除に取り組みました。

## やったこと

### EBSスナップショット削除の設定

AMIはEC2インスタンスの設定とEBSボリュームのスナップショットから成り立っており
単にAMIの登録を解除しても、スナップショットは削除されずに残り続けます。

紐付いたスナップショットを確認して逐一削除するのも大変なので
AMIの登録解除をトリガーにスナップショットが削除されるように設定します。
下記の記事を参考に設定しました。
[AMI登録解除時、スナップショットを自動で削除するように設定してみました！](https://coatiblog.sios.jp/ami%E7%99%BB%E9%8C%B2%E8%A7%A3%E9%99%A4%E6%99%82%E3%80%81%E3%82%B9%E3%83%8A%E3%83%83%E3%83%97%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%E3%82%92%E8%87%AA%E5%8B%95%E3%81%A7%E5%89%8A%E9%99%A4%E3%81%99/)

- CloudTrailで証跡を残している前提
- Cloudwatch EventsでAMIの登録解除を検知
- 連動して発火するLambdaがスナップショットを削除

### CLIでAMIの登録を解除

スナップショットを気にする必要がなくなったので、心置きなく登録を解除します。
CLIを使って、条件に合致するAMIの登録を解除します。

```bash:実行コマンド
aws ec2 describe-images --filters Name=owner-id,Values=【アカウントID】 --query 'Images[?contains(Name, `【検索文字列】`)]' | jq '.[].ImageId' | xargs -I {} aws ec2 deregister-image --image-id {}
```

【アカウントID】: 自身のAWSアカウントID
【検索文字列】: AMINameの検索用の任意の文字列
（jqなしでできれば嬉しい…。）

## むすび

秘伝のタレ的なスクリプトで定期取得されていたのが原因なので
世代管理もできるようイマドキな感じに置き換えていきたいとおもっています。
PMPを取得したのでいろいろとまとめてみる

## この記事について
結構頑張ってPMPを取得した(2020/02/08)。
忘れないうちに勉強した事や試験を受けて感じたことをまとめておく。

ちなみに試験結果は以下。
<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268929/01ab24e4-2e31-0c43-8fa7-d8130911ba14.png" width="60%"></div>

Initiating（プロジェクトの立ち上げ）のみ、`Needs Improvement`
それ以外は合格ライン以上。
後述する分かり辛い日本語のせいだと思っている。

## こんな人向け
* これからPMPを取得しようと勉強している人
* PMP試験の受験直前の人

## これで勉強しました
以下の2つを主に使用し、どうしても分からないところはPMBOK 6版（日本語）を参照した。

#### (書籍) [PMP試験合格虎の巻 第6版対応](https://www.amazon.co.jp/PMP%E8%A9%A6%E9%A8%93%E5%90%88%E6%A0%BC%E8%99%8E%E3%81%AE%E5%B7%BB-%E7%AC%AC6%E7%89%88%E5%AF%BE%E5%BF%9C-%E5%90%89%E6%B2%A2-%E6%AD%A3%E6%96%87/dp/4865751211)

通称、赤本。
教科書として試験直前まで活用出来た。後々の教科書としても活用出来るのでおススメの一冊。

一方で、知識エリア毎に章立てられている為勉強には良いが、知識エリア間の繋がりや時系列的な流れがイメージしにくい。
正直この本だけではPMP合格は**難しい**。(個人の感想です)

#### (e-learning)[【アジャイル実践ガイド対応】PMP（R）試験対策テスト](https://www.bizlearn.jp/bizlearn-pm/608)

合格に向けてこれは<font color="red">**必須**</font>だと感じた。
金額は少し高めだが、十分に価値がある。

書籍では理解できなかった知識エリア間の繋がりや時系列的な流れがイメージしやすい構成になっている。
演習問題も約1300問と豊富で、問題を繰り返し解くだけでもかなり理解が深まる。

ただ、これをやり込みすぎると試験で思わぬ弊害が出るので、試験に向けては注意が必要。
理由は後述する。

## 試験までにやった事
試験を受けるまでにどんな流れで勉強したかを書く。
PMP試験申し込みまでのプロセスが面倒で、試験を受けるまでのハードルが実は結構高い。が、これは気が向いたらまとめる。

1. 赤本を読み込んで、何となく知識エリア毎のプロセスを理解する
2. 赤本に載っている模擬問題200問を解いてみる
3. 間違った問題を赤本を見ながら復習  
----この辺で、プロセス間の繋がりや時系列的な流れが理解し辛いことに気づく----
4. 迷ったあげくにe-learningに申し込む（2019/12末）
5. e-learningの練習問題(1000問)を全問解く。不明点は赤本やインターネットで調べながら適宜知識は補完する
6. e-learningの模擬試験(100問)を6回解く  
⇒何度やっても75%前後でなかなか点数が上がらない（試験まであと10日。**かなり焦る…**）
7. e-learningの練習問題を参考に時系列的な流れと、各プロセスのinput/outputをまとめてみた  
↓↓こんな感じ。手書きで雑な感じでまとめたが、<font color="red">**これが一番効果があった。**</font>
<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268929/16e61ef4-8bf6-6c8c-08b5-c559b32d10b2.jpg" width="50%"></div>
8. e-learningの模擬試験(100問)を3回解く  
⇒ 85%～90%くらいとれるようになる（試験3日前くらい。これでダメなら仕方ないと腹を括る）

### まとめ
* **時系列的な流れと各プロセスのinput/outputの理解は必須**。これを理解することが点数に一番直結する。

## 試験はこんな感じ
### 試験の概要
* 試験開始前に簡単なチュートリアル（GUIの使い方等）がある（5分程度で試験時間の4時間とは別枠）
* 4時間で200問。見直しまで含めると時間が足りなかった

### 所感
#### 1. 日本語訳が理解しづらい
英文を見た方が理解出来る場合もある。私自身は30問くらい英文を読んだ
`Quality Control`が、品質のコントロールではなく、品質管理と訳されていたりする。

#### 2. ケーススタディの問題が中心
次のアクションとして何をするか。を問う問題が中心。どの文書を更新する？、次に実行するフェーズは？等

#### 3. 計算問題は簡単
EVM（アーンド・バリュー・マネジメント）の問題が3問くらい出た。これは**点取り問題**
SPIが0.8、CPIが1.1だけどこれはどんな状態?とか、PV,AC,EVが提示されていてSVやCVを計算させる。程度

#### 4. e-learningをやり込みすぎると戸惑う
e-learningの模擬テストは文章が分かりやすいので、この問題に慣れているとすごく戸惑う。
解決策は分からないが、心構えをしておくとだいぶ違うと思われる。

以下の様な違いがあると感じた。

|種別|問題文の傾向例|
| --- | --- |
|e-learningの模擬テスト|あなたは今○○フェーズを実行中です。<br>□□が発生しました。<br>どの文書を参照/更新するべきですか？|
|PMP試験|~~あなたは今○○フェーズを実行中です。~~**←これがない!<br>**□□が発生しました。<br>どの文書を参照/更新するべきですか？|
これの違いがあるので日本語が分かりづらいと感じているような気がする。

## ざっくり解いて、後で見直す
試験を受けて感じた、個人的なおススメの解き方。
以下の順で解くと良いと思う。

1. 分からない問題、問題文が理解できないは考え込みすぎずに見直しフラグを立ててバンバン先に進む
⇒PMP試験の**独特な日本語に慣れてくる**　<font color="red">**これ重要！**</font>
　目標は 2.5h くらいでざっと解いて、1.5h くらいかけてじっくり見直す

2. 見直しフラグが立っている問題をじっくり見直す
⇒PMPの日本語に慣れた後に見直すと「これを聞いているのか！」が分かる。30問中15問くらいは回答を変更した…。
　私は見直し開始時点で1時間くらいしか残っておらず、30問くらいしか見直し出来なかった…。(60問くらい見直しフラグが立っていた)

## 最後に
最後まで読んで頂いてありがとうございました。
PMP取得に向けて勉強されている方向けに、勉強の仕方や試験を受ける為の心構え等参考になれば思って書きました。
不明点等あればお気軽にご連絡ください！
Let'sEncryptの証明書を更新したのにブラウザから脆弱だと怒られたが、nginxの設定が悪かった話

#証明書の警告
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46533/d47e008d-baa7-0c73-29e6-3fedbb775c5f.png)

Let's Encryptの証明書のキーサイズかと思い、2048→4096へ変更したが、効果なし

#原因
nginxのconfig「ssl_protocols」が「TLSv1」となっていたため。

##変更前
```nginx
       server {
         listen 443 ssl;
         server_name yourserverdomain;
         ssl_certificate chain.pem;
         ssl_certificate_key key.pem;
         ssl_session_timeout 5m;
         ssl_protocols TLSv1; ssl_ciphers
         ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
         ssl_prefer_server_ciphers on;

       }
```

#対策
nginxのconfig「ssl_protocols」を「TLSv1.2」へ変更する。

##変更後
```nginx
       server {
         listen 443 ssl;
         server_name yourserverdomain;
         ssl_certificate chain.pem;
         ssl_certificate_key key.pem;
         ssl_session_timeout 5m;
         ssl_protocols TLSv1.2; ssl_ciphers
         ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
         ssl_prefer_server_ciphers on;

       }
```
##適用後の証明書の状態
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46533/077592c1-263c-ec50-1515-b7693a91c303.png)
Visual Studio Codeのショートカットが便利だと思った話

みなさん開発する際テキストエディタは何を使用されていますか？
僕はVisual Studio Codeを使用してRailsの勉強をしています。

railsを勉強するにあたって初心者あるあるだと思ってるんですが、（僕だけかな。。。？）
rails new でアプリケーションの雛形作って
controller作って、model作ってview作って編集して。。。

開発を進めて行くとファイル数が多くなっていき、
修正したいファイルを探すのに時間を使っちゃうことが多々ありました。
例)index.html.erbを修正したい！
　　えーと確かappフォルダのえーとviewフォルダのホゲホゲフォルダのなかで。。。。あれ今どこみてるんだ。。。？などなど

疲れているとよく指定のファイルを探す時間が多くなってしまってどうにかならないかなーって思ってました。

#考えたこと
rails newで作成したら機械的に決まったフォルダを作成しており
基本的に触るのってviewファイルとcontrollerファイルとmodelファイルなんですよね。
そしてrailsアプリケーションって
veiwだったら
```
app/views/hogehoge/fugafuga.html.erb
```

modelだったら
```
app/models/hogehoge/fugafuga.rb
```
controllerだったら
```
app/controllers/hogehoge/fugafuga_controller.rb
```
とだいたい置き場所って決まっているのでターミナルから起動できれば便利だなーって考えました。

# 実はターミナルから開ける
MACだと下記コマンドを打てば、Visual Studio Code上の一部画面にターミナルを開くことができました。
```
Cntrol + Shift + `
```

でターミナル上で
```
code フォルダ名/ファイル名
```
※[codeに関しては別途インストールが必要](https://qiita.com/1natsu172/items/b951aa33451dad36bd7c)

と入力すれば任意のファイルを開くことができます。

これに気付いた時本当にテンション上がりました。
タイピングする際のホームポジションを崩しませんからね。

またtabでの入力補完を使用すればタイピングミスが少なく爆速でファイル作成＆修正ができちゃいます。

他にも便利なショートカットがたくさんありますので、余裕がある時にでも一つづつ覚えていこうと思っております。


#参考情報
[コマンドラインからVS Codeでファイルやフォルダを開く](https://qiita.com/1natsu172/items/b951aa33451dad36bd7c)
[Visual Studio Code キーボード ショートカット](https://qiita.com/oruponu/items/ae9c720d4522c1606daf)
Application Load Balancerで付与されるHTTPヘッダ


###概要
AWSのApplication Load Balancer(ALB)を使ってWeb-App-DBの３層構成を組むことが一般的に多いと思われるが、ALBではHTTPリクエストに対してHTTPヘッダを付与することがある。非ALB構成とALB構成で付与されるHTTPリクエストヘッダの差異をネットワークキャプチャで調査してみる。

##ネットワークキャプチャコマンド
```ruby
###tcpdumpをWebサーバで発行
tcpdump -i eth0 -n -tttt port <port番号> -w /tmp/web.pcap
```

##前提構成

```ruby:①前段ALB_HTTPS構成
#HTTPリクエストの流れ(APP,DB層は検証の目的に外れるので省略。
Clinet  ===> ALB(443) ===> NGINX@WebServer(80)
```
<img width="551" alt="Screen Shot 2020-02-15 at 11.51.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245585/3bb54821-87db-6ed2-ba7b-acaf4724f142.png">

```ruby:②前段ALB_HTTP構成
#HTTPリクエストの流れ(APP,DB層は検証の目的に外れるので省略。
Clinet  ===> ALB(80) ===> NGINX@WebServer(80)
```
<img width="454" alt="Screen Shot 2020-02-15 at 11.47.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245585/7b4ada8e-9943-0b9c-cb68-ed8dd75dc72c.png">


```ruby:③Webサーバ直HTTP構成
#HTTPリクエストの流れ(APP,DB層は検証の目的に外れるので省略。
Clinet  ===> NGINX@WebServer(80)
```
<img width="464" alt="Screen Shot 2020-02-15 at 11.56.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245585/63c64a15-261e-77e9-6ae3-fe3325e69f41.png">

###検証結果

- 結果的に、ALBを経由した場合だと以下の4つのHTTPヘッダが追加付与されていることが分かる。

<strong>`X-Forwarded-For`

ロードバランサなどの機器を経由してWebサーバに接続するクライアントの送信元IPアドレスを特定する際のデファクトスタンダード。クライアントの送信元IPアドレスの特定は、ロードバランサなどでクライアントの送信元IPアドレスが変換された場合でも、HTTPヘッダに元のクライアントIPアドレスの情報を付加することで実現。Webサーバ側でクライアントのIPアドレスを特定するために前段のLBで付与する必要がある。

例えば以下のような構成だと、Webサーバで受け取るHTTPリクエストヘッダは<strong>X-Forwarded-For: Clinet</strong>となる。

```ruby:
Clinet  ===> ALB(443) ===> WebServer
```

上記であればSimpleだが多段プロキシ構成だと話が複雑になる。
例えば以下のような構成だと、Webサーバで受け取るHTTPリクエストヘッダは<strong>X-Forwarded-For: Clinet ALB Proxy1</strong>となる。Webサーバにリクエストを転送する主体はそれまでのアクセス元のIP(自らを含まない)をWebサーバに転送する時点でX-Forwarded-Forに付与する仕組み。

```ruby:
Clinet  ===> ALB(443) ===> Proxy1 ===> Proxy2 ===> WebServer
```

この状態から、ClientのIPアドレスをフィルタする方法は各Webサーバの設定による。

<strong>`X-Forwarded-Proto`

プロキシまたはロードバランサーへ接続するのに使っていたクライアントのプロトコル (HTTP または HTTPS) を特定する。

<strong>`X-Forwarded-Port`

プロキシまたはロードバランサーへ接続するのに使っていたクライアントからの宛先ポートを特定する。

<strong>`X-Forwarded-Amzn-Trace-Id`

クライアントからのターゲットまたは他のサービスへの HTTP リクエストを追跡するための一意な識別子。ALBが、クライアントからのリクエストを受信すると、ターゲットにリクエストを送信する前に、[X-Amzn-Trace-Id] ヘッダーを追加、または更新する。Webサーバのアクセスログに記録することでALB側のアクセスログと比較してリクエストを特定可能

###参考URL
- https://www.infraexpert.com/study/loadbalancer11.html
- https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Forwarded-Proto
- https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Forwarded-Host
- https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-request-tracing.html
Google Glass Enterprise Edition 2を弄った感想

![IMG20200214180145.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142638/d1782937-567b-279f-b675-68ff24d83996.jpeg)

#感想

けっこう画面小さい。リアル視界がメインで通知程度…というコンセプトなのだろうから、…仕様です。

しかし最初に生まれたのが2013年であることを考えると、ARグラスとか意識してない設計なのでは…と思ったりもしつつ、ほぼ同形で2を出したのだから、コンセプトを貫いただけ…とも（信者なら）捉えられる。

HoloLens等の大きさを考えると、両取りが無理なのはわかるのですが、もうちょっと大きくても…（中略）
（※SmartとARの違いを理解した上でSF脳で話しています）

一方で、私はアンチDisplay & Keyboardなので、カメラで見たものを処理して、音声で伝えてくれるサービスの方に期待しています。期待していますというか、買ったからには何か作ります。

大きさとしては日常でかけていても問題ないですが、カメラを常に人様に向けることになるので、そちらの方が気になるかもしれません。完全監視社会アイテムの一つです。

あとメガネ民はコンタクトしないとよく見えない。
黒縁の方かって度付きレンズ入れたい気持ちでいっぱいです。（チタンにはレンズはまらなそう）
裸眼の人はチタンの方が軽くてよさそう。

日本に届けてくださった友人に感謝。


#使い方等
(Macです)

WiFiを接続するために、My Glass SiteたるものでWiFiのQRを生成し、Glassで読むのが正攻法らしいのですが、
http://glass.google.com/myglass
なぜかうまく行かなかった(Invalidが出た)ので、Vysorで繋いでやってしまいました。

公式もMirroringはVisorでやっては、と言っているのでもう繋いでしまいましょう。
https://support.google.com/glass-enterprise/customer/answer/9220200?hl=en&ref_topic=9235678
入ってない方は↓

```
% brew cask install vysor     
```

USBをつなぐだけで宜しくやってくれます。

アプリが何も入っていないので、まずはサンプル動かすところからかなと。
https://github.com/googlesamples/glass-enterprise-samples

```
% git clone https://github.com/googlesamples/glass-enterprise-samples.git
```

Android Studioでビルドしてください。

```
% brew cask install android-studio
```

使いながら記事updateしていきます。
Swiftのオプショナル型・型キャストなど短縮された記号について(1)

Swiftのオプショナル型は簡潔に書きやすいが、短縮された記号は慣れるまで理解しにくいと感じた。そのため、Swiftの記法についてまとめようと思う！
今回は、?・!あたりがややこしく感じたのでその辺をまとめることにする。as?・as!は(2)でまとめる。

# オプショナルとは？
そもそもオプショナルとは？  オプショナルとは変数の中にnilの代入を許可している型である。Swiftでは変数の中身がnilであることを基本的に許可していないが、 `Optional<String>` のような型にすることでnilが代入できるようになる。
## なぜオプショナルを使うのか？
なぜオプショナル型を使う必要があるかと言うと、使い手(クライアント)が変数を呼び出した際にnilであることに気づかずに操作しようとすると`nullpointerexception`と言うエラーになり落ちるためである。

# オプショナルの扱い方
## ?
swiftのOptinal型は先ほども触れたが、`Optional<String>`のような型になっている。それを省略形で書いたのが、`?`である。

```
// swiftはnilを許さないのでこの場合はエラーになる
    var middleName: String
// この場合は初期化されているので大丈夫
    var middleName: String = "middle"
// 下記の意味は同じくオプショナル型になる
    var middleName: Optional<String>
    var middleName: String?
```

また、`?`にはオプショナルの他にもう一つの概念があり、それが三項演算子である。三項演算子はif文を省略した形式である。下の例はオプショナルと三項演算子の`?`が合わさって判定されているパターンだ。

```
// 下記の例だとisHumanがtrueなら人間、falseならその他が表示される
    var isHuman: Bool = true
    print(isHuman ? "人間": "その他")

// 三項演算子とオプショナルの?の合わせ技
    var monthlyIncomeA: Int? = 200000
    print(monthlyIncome ?? "あなたはニートです。") //200000
    var monthlyIncomeB: Int? = 200000
    print(monthlyIncomeB ?? "あなたはニートです。") //あなたはニートです。

```

## !
### unwrap
オプショナル型は呼び出す時にはそのまま使うことができないので、利用するために`unwrap`する必要がある。unwrapは`Optional<String> → String`のようなイメージ。  
普通にunwrapして使うには下記の2通りがある。

```
let middleName: String? = nil

// unwrap1
// middleNameがnilじゃないかをifで判定し、値がある場合のみprintする
if middleName != nil {
    print(middleName)
}

// unwrap2 (Optional Binding)
// middleNameの値をvalue詰め、値がある場合のみ{}にvalueを渡してprintする
if let value = middleName {
    print(value)
}
```

### 暗黙的unwrap
Optionalは毎回unwrapしなければならないため、コーディングが長くなってしまうと言うデメリットがある。そのため、暗黙的unwrapを使えば一度値がセットされたら、以降nilになることはないと言う前提でunwrapしなくてよくなる。  
暗黙的unwrapした後にnilが入ってしまうとアプリがクラッシュするので使うときは要注意！

```
// 宣言時に!をつけると以降unwrapをしなくてよくなる。
var income: Int!
income = 2500000
print(income) //2500000 !をつけずにprintすることができる 

// 暗黙的unwrapした値にnilが入ると。。
income = nil
print(income) //　クラッシュするので要注意！！
```

# まとめ
今回はオプショナルの省略記号についてまとめてみた。オプショナルやunwrapの概念について理解する時に参考にしてもらえればと。型キャストや引数の省略などの書き方もswiftは独特な印象だったので、(2)以降でその辺りも触れていきたいと思う！