OmniAICreator/Qiita-1.07M huggingface dataset:
sizeForItemAt indexPathでサイズをセットしているのにUICollectionViewCellのサイズが変わってしまう

## 問題

久しぶりにiOSアプリを修正していて、CollectionViewで横スクロールさせていたら、スクロール開始時にセルのサイズが変わってしまう問題が起きた。
`sizeForItemAt indexPath`では固定のサイズをちゃんとセットしているのにも関わらず、debug view hierarchyでチェックしても確かにセルのサイズが変わってしまっている。。

## 解決方法

久しぶりの開発で、CollectionViewの`Estimate size`というプロパティにデフォルトで`Automatic`がセットされていることを知らなかったのですが、これを`None`にすることで解決しました。
Estimate sizeはセルのサイズを概算してくれるようですが、Noneにしておくのが無難かもしれないですね。

![stackoverflow](https://i.stack.imgur.com/7uuKv.png)

## 参照

https://stackoverflow.com/questions/56840665/why-on-xcode-11-uicollectionviewcell-changes-size-as-soon-as-you-scroll-i-alre
Vue.js 算出プロパティとメソッドの違い

## はじめに
[Vue.js テンプレート制御ディレクティブ まとめ](https://qiita.com/yukiji/items/a77dd6d8dd0f194770c3)の続きです。

今回は算出プロパティとメソッドの違いを学習していきます。

## 算出プロパティcomputed

算出プロパティ`computed`は、関数によって算出したデータを返す事ができるプロパティ。

例えば、以下のようにマスタッシュ構文内に複雑なロジックを書くと可読性が悪くなる。

```html
<!-- 文字列を反転する式 -->
{{ message.split('').reverse().join('') }}
```
こういった複雑なロジックを実行する時に、算出プロパティを利用することが推奨される。

また、ロジックの再利用性を高めたい時などにも利用できる。

`computed`を利用してコードを書いてみる。

```html
<div id="app">
  <p>
    {{ reverseMessage }} <!-- !sj.euV olleH -->
  </p>
</div>

<script>
  var app = new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue.js',
    },
    // 算出プロパティの定義
    computed: {
      // メソッドの定義
      reverseMessage() {
        return this.message.split('').reverse().join('')
      }
    }
  })
</script>
```

**あれ？これ`methods`と何が違うの・・・**

`computed`と`methods`それぞれの違いを深掘りする。


## 算出プロパティとメソッドの3つの違い

**①プロパティとメソッド**

`computed`はプロパティなので`()`が不要。

`methods`はメソッドなので`()`が必要。

```html
<!-- computed -->
{{ reverseMessage }}
<!-- methods -->
{{ reverseMessage() }}
```


**②getterとsetter**

`computed`は`getter`と`setter`を定義する事ができる。

`methods`は`getter`しか定義できない。

**③キャッシュ**

`computed`はキャッシュされる。

`methods`はキャッシュされない。

`methods`は呼び出されるたびに関数の処理を行う

## まとめ

実行したい処理の内容によって`computed`か`methods`か使い分けるのが良さそう。

しかし、現状どういったケースで使い分けるかイメージが沸かない。

この辺りは、実際にアプリケーションを開発しながら身に付けるしかなさそう。

知見が深まり次第、追記していきます:writing_hand:

## 更新履歴

:zap:[Vue.jsの基本的な使い方まとめ](https://qiita.com/yukiji/items/862b8dd91dc410259fb4)
:zap:[Vue.jsでTO DOアプリを作る](https://qiita.com/yukiji/items/dc45f45f7f3f0e53f626)
:zap:[Vue.js テンプレート制御ディレクティブ まとめ](https://qiita.com/yukiji/items/a77dd6d8dd0f194770c3)
:zap:[Vue.js 算出プロパティとメソッドの違い](https://qiita.com/yukiji/items/525469503cdba334658e) :point_left:今ココ
npm-run-allでnpm scriptsを整理してみた

Angularのマルチプロジェクトを構築していると、スクリプトがカオスになってきます。
npm-run-allを使って整理したときのナレッジを書き溜めておこうと思います。

# 修正前

プロジェクトが増えるたびに開発ビルド／本番ビルド／ウォッチのスクリプト追加、一括ビルド（開発用／本番用）スクリプトの修正が必要になってしまい、メンテナンスがかなりめんどくさいです。

```package.json
"scripts": {
  "build:dev": "npm run build-app:app1 && npm run build-app:app2 && npm run build-app:app3",
  "build:prod": "npm run build:prod:app1 && npm run build:prod:app2 && npm run build:prod:app3",
  "build-app:app1": "ng build app1",
  "build-app:app2": "ng build app2",
  "build-app:app3": "ng build app3",
  "watch:app1": "ng build app1 --watch",
  "watch:app2": "ng build app2 --watch",
  "watch:app3": "ng build app3 --watch",
  "build:prod:app1": "ng build app1 --prod",
  "build:prod:app2": "ng build app2 --prod",
  "build:prod:app3": "ng build app3 --prod",
  ・・・
}
```

# npm-run-allを使う

[npm-run-all](https://github.com/mysticatea/npm-run-all/blob/HEAD/docs/run-s.md)を使うことで、かなりシンプルに出来ます。

npm-run-allはワイルドカードを使って一括でスクリプトを実行したり、`-p`オプションでスクリプトを並列実行することができます。

早速、上記のpackage.jsonをnpm-run-allを使って改修していきます


# 引数でまとめる

```
"scripts": {
  "build:dev": "run-s build-app:*",
  "build:prod": "run-s \"build-app:* -- --prod\"",
  "build-app:app1": "ng build app1",
  "build-app:app2": "ng build app2",
  "build-app:app3": "ng build app3",
  "watch": "run-s \"build-app:{1} --watch\" --",
  ・・・
}
```

こうなりました。
プロジェクトが増えても`build-app:XXX`を追加するだけで、良くなります。

## 解説

基本的には[公式リファレンス](https://github.com/mysticatea/npm-run-all/blob/HEAD/docs/run-s.md)に従って、シンプルに使ってます。

ちなみに、今回は直列実行するので`npm-run-all -s`の短縮形である`run-s`で実行します。
（並列実行したい場合は`npm-run-all -p`もしくは`run-p`を使用してください。）


### ワイルドカード

シンプルなワイルドカードです。
`build-app:*`とすることで`build-app:`がつくスクリプトがすべて実行されます。

```
  "build:dev": "run-s build-app:*",
```

ダブルコーテーションで囲うことでオプションを指定することもできます。
`build-app:*`で実行される各スクリプトに対して`--prod`オプションを指定します。

```
  "build:prod": "run-s \"build-app:* -- --prod\"",
```

### 引数

引数を使って動的に実行スクリプトを切り替えます。
{1}、{2}、・・・で引数を扱うことができます。
末尾に`--`を置くのがポイントですね。

```
"watch": "run-s \"build-app:{1} --watch\" --",
```

`npm run watch app1`を実行することで、`run-s \"build-app:{1} --watch\" -- app1`が実行され、最終的に`build-app:app1`スクリプトが実行されます。
TeXiFy IDEA + macで日本語LaTeX環境を作る際のトラブルシューティング

# 環境
* macOS Catalina 10.15.2	
 
# 基本
基本的には[このページ](https://scrapbox.io/satakebox/LaTeX_on_IntelliJ)にしたがって導入すればよいです。

# 問題
しかしこのまま`\documentclass{jsarticle}`としてコンパイルを試みたところ、

```
"! LaTeX Error: This file needs format `pLaTeX2e' but this is `LaTeX2e'."
``` 

が出てハマりました。

Windows OSの場合[この記事](https://qiita.com/minkmaguro/items/4d830ba5f6af2c58537e)に対処策が載っています。ここではOS関係なしにできる（はずの）簡単な解決策を述べます。

# 対処
結論は簡単で、コンパイラを[LuaLaTeX](https://texwiki.texjp.org/?LaTeX%E5%85%A5%E9%96%80%2F%E7%99%BA%E5%B1%95%E7%B7%A8#mb665da8)にすることで解決されました。[このページ](https://github.com/Hannah-Sten/TeXiFy-IDEA/wiki/Compilers)に従ってコンパイラを変え、texファイル内では`\documentclass{ltjsarticle}`とすれば勝利です。
子要素にcheckboxを持つ要素に実装したjQueryのclickイベントが2回発生する

以下のようなcheckboxとそれに紐付くlabelを子要素としてもつ要素にjQueryでclickイベントを実装すると
label上をクリックした際にイベントが2回重複して発生します。

```html:html
<div id="box">
  <input type="checkbox" id="chekbox">
  <label for="checkbox">checkbox</label>
</div>
```

```js:js
let count = 1;
$("#box").on("click", function(){
  console.log(count+ " clicked");
  count ++;
});
```

```:console（クリック後）
> 1 clicked
> 2 clicked
```

これはそもそもlabelがクリックされた時にlabelに紐付くinputもクリックされたとみなされるために起こるそうなので、
クリック対象をinputに向けることで解決する。

```js:js
$("#box input").on("click", function(){
   // クリック後にしたい処理
});
```

![animal_chara_computer_penguin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315096/b6828466-5732-b85e-9855-d9797209f42c.png)
【Rails】一対一対多のアソシエーション

結局は基本的なことなのですが、少し変わると途端にハマってしまう。
アソシエーションがうまくいかずに時間を溶かしてしまったので、そんな過去の自分といるかもしれない未来の誰かのために書き残しておきます。

## テーブル構造

UserモデルとTagモデルの中間テーブルから派生させたTagSettingモデルを作りました。
![erd.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322882/7b3143f5-88ac-0e8a-c4af-117301deef78.jpeg)
ただ、今回の話にはUserモデルはあまり関係ありません。
また、この後「tag_usersとtag_settingsを別々にしなくていいんじゃないか？」という指摘を受けてテーブル構造を変えました。なので、例としては少々不適切かもしれませんがご容赦を。

## モデルのアソシエーション

```user.rb
class User < ApplicationRecord
  has_many :tag_users
  has_many :tags, through: :tag_users
  has_many :tag_settings
end
```

```tag_user.rb
class TagUser < ApplicationRecord
  belongs_to :user
  belongs_to :tag
  belongs_to :tag_setting
end
```

```tag_setting.rb
class TagSetting < ApplicationRecord
  has_one :tag_user
  has_one :tag, through: :tag_user
  belongs_to :user
end
```


```tag.rb
class Tag < ApplicationRecord
  has_many :tag_users
  has_many :tag_settings, through: :tag_users
end
```


## 注意点

### 中間テーブルへのアソシエーションを追加する

`has_many :tag_users`なしで`has_many :tag_settings, through: :tag_users`を定義することはできない。
また、中間テーブルへのアソシエーションの方を上に記述する必要がある。

### 単数形・複数形に注意する

`has_many :tag_settings, through: :tag_users`
`has_many`のときは`:through`も複数形

`has_one :tag, through: :tag_user`
`has_one`のときは`:through`も単数形

## リンク

- [Active Record の関連付け - Railsガイド](https://railsguides.jp/association_basics.html)
AWSとFilezillaをつなぐ

AWSのEC2インスタンスにファイルをアップしたい。ローカルからFilezilla経由をするには。

Filezillaで行うこと。
①新しいサイトを作成（名前はなんでもOK）

②プロトコル　は　SSH File Transfer Protocol を選択

③ホスト　に EC2のIPアドレスを入れる。これはAWSのインスタンスページにある、「パブリックIP」をコピペ(123.456.789みたいな数字のやつです）

④ログオンタイプ　鍵ファイル　を選択（AWSのEC2への接続時に、秘密鍵をつくってると思いますが、あれを使うということです）

⑤ユーザー　
EC2インスタンスに接続してるときの、ターミナル（Macだと）に書いてあります。$の左側。
例えばインスタンスのOSにubuntuを選んでると、デフォルトではubuntuになってます。
`ubuntu@ip-123.456.789: $` 部分の、`@`の前がユーザー名です。

⑥鍵ファイル　参照　のところで、鍵ファイルを選択。　~~.pemというファイルです。

⑦接続を押して完了！

参考：
https://agohack.com/cyberduck-ec2/
https://support.amimoto-ami.com/en/articles/934126-filezilla-%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F-sftp-%E6%8E%A5%E7%B6%9A
【Java】Optional覚書

# レガシーコードとは縁のないOptional
最近初めて業務で使ってうれしくなっちゃったので、次からも使えるように使用例のメモです。

2019年の完全新規案件でJava1.6を強制されることのある現場に在籍しています。
この期に及んでJava8に触れる機会があまりありません。
そんな中で「Java8からはnullチェックが簡単に書けるらしい」というJava8登場時に聞いた情報で書きました。
一応複数のサイトを確認して書いていますが、マサカリとか改善方法とかがありましたら、ぜひコメントをお願い致します。
(私のコードレビューが可能なレビュアーが案件に不在のため)(他のメンバーのレビューは私がしています)

## `get`について
使いどころがわからなかったので、使っていません。
いくつかサイトを見ると「`get`使うな論」を見かけたので、逆に正解だったのでは？感ある。

# 注意
「Optionalは単純に従来のnullチェックを置換できる」は正しい認識ではありませんでした。
「Optionalを使うとnullチェック忘れの可能性撲滅のためにnullチェックを強制できる」が正しいですね…
なのでサンプルコードは動きますが、Optionalの使い方としては正しい認識のもと書かれたコードではありません。
忘れないためにこの記事は削除せずに残しますが、「Optional初めて～！」な私みたいな方は引っかからないようにお気を付けください。
@sikani さん、ありがとうございました！やっぱり有識者にレビューしてもらわないとダメだ…
Optionalで書くことを他人のレビュー指摘で挙げてなかったのが不幸中の幸い。(Java8っぽいコードを強制されない案件なので)

# サンプルコード
Java1.6はわざとアレな書き方をしています。Java8はすっきり書けますね:relaxed:
Java8の方は**[ちょっと使い方間違ってるけど。](#注意)**
~~Java1.6でも三項演算子でワンライナーで書けますけどもね…retは無駄なだけだしアーリーリターンすらもせずにif～else使うしprivateメソッドも切らないで毎回if文書いてるタイプの現場でまじイケてないレガシーコードが大半なので、リファクタリングでいつも心が死ぬ。更に言うとJava8使ってもJava1.6の書き方そのままのメンバー多すぎて最早笑う。自分を意識高い系と誤解しそうになるので困る…最近賑わってた格上格下論争を思い出します。~~愚痴ですまない。

```java:Java1.6
public String toStringIfNotNull(final Object obj) {
	String ret;
	if (obj == null) {
		ret = null;
	} else {
		ret = obj.toString();
	}
	return ret;
}
```
```java:Java8
public String toStringIfNotNull(final Object obj) {
	return Optional.ofNullable(obj).map(Object::toString).orElse(null);
}
```

nullチェックの代わりにOptionalを使うなら、`of`よりも`ofNullable`と`orElse`の組み合わせが最適解なのではないかな！？という印象。
nullじゃなければ元の値をそのまま返すのであれば、`map`とか中間処理？が不要になるだけですし。

`map`の他には、`filter`と`flatMap`があります。
`filter`はnullとfilter結果がfalseの場合に`orElse`の引数が返ります。
`flatMap`はnullの場合は`orElse`の引数が返りますが、flatMap処理の結果がnullの場合、NullPointerExceptionがスローされます。(`map`の場合は処理結果がnullでも`orElse`の引数が返る)

nullかどうかで値を返すのではなく処理を分岐する場合は、`if (Optional.ofNullable(obj).isPresent())`って書けば大丈夫らしいぞ！
また、`isPresent`は真偽値が返るだけですが、`ifPresent`にして引数でラムダ式を渡せば、null以外の時のみ引数のラムダ式を実行、という風に書けるそうな。
まあでもJava7以降であれば、isPresentより`if (Objects.isNull(obj))`(nonNull)で分岐したほうがすっきり書ける気はするけど。

ここまで書いて気付いたけど、サンプルコードの処理内容なら、`Objects.toString(obj, null)`(StringUtils.defaultStringみたいなやつ)でよかったね…確認不足でした。
plunkerでvega

#概要

plunkerでvegaやってみた。
数式をグラフにしてみた。

#写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/015d4d91-0b3d-2d94-2988-0e3d99ecb20e.png)

#サンプルコード


```

function run() {
  var src = document.getElementById('src').value;
  var values = [];
  for(var x = -1; x < 1; x += 0.1)
  {
    eval(src);
    values.push({
      x: x, 
      y: y
    });
  }
  const spec = {
    '$schema': 'https://vega.github.io/schema/vega-lite/v2.json',
    'width': 300,
    'height': 300,
    'data': {
      'values': values
    },
    'mark': 'point',
    'encoding': {
      'x': {
        'field': 'x', 
        'type': 'quantitative'
      },
      'y': {
        'field': 'y', 
        'type': 'quantitative'
      }
    }
  };
  vegaEmbed('#vis', spec);
}





```

#成果物

https://embed.plnkr.co/plunk/hmO2QWGQQJ0Njtl1

以上。
【GCP】リポジトリを作成した

topgateのサイトに習ってやって行ったりシてましたが、
インスタンスでアプリを動かすには、リポジトリを作成したほうがいいみたい。
この辺の概念知らないの恥ずかしいし、もっと勉強しないと。

なので、
PJ作成⇛リポジトリ作成の流れになる感じ。

【参考サイト】
https://blog.apar.jp/web/7494/
https://cloud.google.com/source-repositories/docs/quickstart?hl=ja

【注意】
https://www.topgate.co.jp/gcp02-getting-started-guide
topgateのページ見てて、ここにはdeveropmentがあると書いてあるけど、多分2020/4現在はなくなっている。
なので、
Source Repositoriesから操作する。
仕様が変わるから、try&errorでいろいろ触ったほうが早そう。

↓
元々は以下の目的を達成したかった。
【目的サイト】
https://www.topgate.co.jp/gcp04-google-compute-engine-run-application

操作を進めると以下の選択肢が出る。
　　新しいリポジトリを作成：空のリポジトリを作成するには、このオプションを選択します。
　　外部リポジトリの接続：GitHub や Bitbucket などのホスト型サービスからリポジトリをミラーリングするには、このオプションを選択します。

目的サイトを実現するには、「新しいリポジトリを作成」っぽい。

新しいリポジトリを作成　＞　リポジトリ名を適当に　＞　作成したPJを選択（ここはプルダウンが表示される）
指定したPJにリポジトリができるイメージ
ここまでやればリポジトリはできていそう。

＝＝＝＝
で、作成すると「リポジトリにコードを追加」ページに遷移し、以下を選択。
	ローカル Git リポジトリからコードを push
	ローカル Git リポジトリへのリポジトリのクローンを作成する

ここで2つ選択できるが、その下に記載されるコマンドが変わる。
SSH認証タブ、GCSタブ、手動で作成した認証があり、
目的サイト的には、「ローカル Git リポジトリからコードを push」な気がする。
使用するコマンドとかみながら選ぶ。

これでできたので、目的サイトの内容を進めていこうと思います。

【今後読んでおいたほうが良さそうなサイト】
https://qiita.com/macotok/items/264c3cfc82381517681d
https://qiita.com/rubytomato@github/items/72983ec37d7539253f38
「brew --prefix」とは何か？

`mysql2`のインストール中にエラーが起きた際の対処法で見かける`openssl`のインストール先を指定する以下の方法

```
brew --prefix openssl
```
`brew --prefix`とは何ぞや？と思ったので調べてみました。ターミナルで。

# そもそも「--prefix」とは？
言わずとしれたインストール先の指定方法

```
--prefix='インストール先のアドレス'
ex.
--prefix=/usr/local
```
# brew --prefix
じゃあ「brew --prefix」は何だと思って試しにターミナルさんに聞いてみた。

```
% brew --prefix
/usr/local
```
`brew`のインストール先のアドレスだった。単純な話だった。
PHP if, isset, emptyの真偽の判定について if()

条件分岐の基本的なところでつまづいたので、if,isset,emptyの挙動について簡単にまとめてみます。


######配列$arrayをif, isset, empty それぞれで出力してみました。

```php
$array = [0, '0', 10, false, true, null, '', [] ];


foreach($array as $val){
  if($val){echo "truthy";}
  if(!$val){echo "falsy";}
  echo "\n";
}

foreach($array as $val){
  if(isset($val)){echo "truthy";}
  if(!isset($val)){echo "falsy";}
  echo "\n";
}

foreach($array as $val){
  if(empty($val)){echo "truthy";}
  if(!empty($val)){echo "falsy";}
  echo "\n";
} 

```

######結果

```php
$array = [
  0,            //[if]→falsy      [isset]→truthy      [empty]→truthy
  '0',          //[if]→falsy      [isset]→truthy      [empty]→truthy
  10,           //[if]→truthy     [isset]→truthy      [empty]→falsy
  false,        //[if]→falsy      [isset]→truthy      [empty]→truthy
  true,         //[if]→truthy     [isset]→truthy      [empty]→falsy
  null,         //[if]→falsy      [isset]→falsy       [empty]→truthy
  '' ,          //[if]→falsy      [isset]→truthy      [empty]→truthy
  []            //[if]→falsy      [isset]→truthy      [empty]→truthy
];

```
######まとめ

この結果から、例えばif文で「何かしらの数値(0や'0'を含む)が入った状態を"真"としたい場合」などのときは、(==, !=, ===, !==)を使って比較してあげる必要がある、といったところが注意点でしょうか。

基礎的な部分ですが見落としがちで、気が付きにくいエラーの原因にもなりそうなので、簡単にまとめてみました。

他にも注意点や内容のご指摘あればご教授していただけると喜びます。
以上です。
【find】こんなコマンドあったら嬉しいと思っていたら見つけた

#はじめに
ターミナルから、自分が探したいソースを探せたらいいのになと思ってた時に
見つけたコマンド。

##コマンド
```bash
#検索したいディレクトリの、検索したい拡張子かつ、そのファイル内の'ほげ'が何行目に書かれているか探す。
find ファイルパス -name "*.php" | xargs grep 'ほげ' -ns
```
ファイルパス
検索したいディレクトリを指定。

-name 
拡張子がｐｈｐのものに絞る。

パイプ（|）
コマンドとコマンドを繋ぐもの

xargs
パイプで繋いだ前のコマンド(コマンド1)で取得した値を利用してxargsで指定した別のコマンド(コマンド2)に引数として渡して実行させる事ができるコマンド。

grep
ファイルの中の文字列を検索

-n
行番号を表示

-s
ファイルがない時、エラーを表示させないようにする。
マンガを1話だけ完成させてみた

漫画を1話だけ完成させてみました。ページ数的には、1話くらいの分量ですね。物語的にも一区切り付きました。絵を書くのって大変で、セリフとか背景とか時間がかかります。週間連載の漫画家は、バケモンじゃないかと思いました。

![](https://syui.cf/manga/0.png)

https://syui.cf/manga

漫画のページはvue.jsで構築しています。次のページボタンと画像URLのリンクを生成。

### ここから技術的な話

昔は、gitbookを使ってみたことがあったのですが、シンプルじゃないと思ったので、vueで作りました。

vue 2.x + webpack 4.x 系でenvを使うのにハマったのでメモ。

結論としてdotenv-webpackを使えばいけました。

```sh
$ echo "page=4" >> .env
$ yarn add dotenv-webpack
```

```js:webpack.config.js
const Dotenv = require('dotenv-webpack');

module.exports = {
  plugins: [
    new Dotenv('./.env')
	]
}
```

```js:src/main.js
var app = new Vue({
  data: {
    products: [...Array(Number(process.env.page)).keys()]
  }
})
```

```json:package.json
"scripts": {
  "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
}
```

以上、漫画の宣伝をqiitaでもやってみたという話でした。
tsconfig.json の compilerOptions の順序を整理する基準

TypeScriptで欠かせないのが `tsconfig.json` のチューニングです.
基本的にはオプションを有効/無効にするだけなんですが、 `compilerOptions` を雑多に書いていくと、目Grepが辛くなってきます.

そこで `tsc --init` すると自動で生成される `tsconfig.json` に `/* Basic Options* /` とかでブロックを分けて各種オプションが書かれてるのを見て明確な分類ができるっぽいと気がついた.

ドキュメントを見る限りは近いものはあるけども、欲しいものと違うので直接 TypeScript のリポジトリを確認したところ見つけました.

- [/src/compiler/commandLineParser.ts]( https://github.com/microsoft/TypeScript/blob/5596ed80d7fe72914262b77510aea65d8223c75a/src/compiler/commandLineParser.ts)

内部的には `category` として分けているようです.
あとは自動生成された `tsconfig.json` の様に書いていけば、ある程度はブロック分けされた書き方ができます.

```js:tsconfig.json
{
  "compilerOptions": {
    /* Basic Options */
    "target": "es2017",
    "module": "commonjs",
    "lib": ["es6", "dom", "esnext"],
    "outDir": "../../dist/functions",
    "sourceMap": true,
    "isolatedModules": true,

    /* Module Resolution Options */
    "baseUrl": ".",

    /* Advanced Options */
    "resolveJsonModule": true
  },
  "compileOnSave": true,
  "exclude": ["node_modules", "**/*.test.ts", "**/*.test.tsx"],
  "extends": "../../tsconfig.base.json",
  "include": ["**/*.ts", "**/*.tsx"]
}
```
画像データ　型変換 【Python】

# 概要

Pythonにて画像データを扱うとき、「numpy（opencv）」「pillow」「byte」にて扱うことがある。それぞれの型変換させるための備忘録。

# numpy -> bytes
```python
_, num_bytes = cv2.imencode('.jpeg', num_numpy)
num_bytes = num_bytes.tobytes()
```

# numpy -> pil
```python
num_pil = Image.fromarray(num_numpy)
```

# pil -> bytes

```python
num_byteio = io.BytesIO()
num_byteio.save(num_pil, format='png')# 仮にpngにしている
num_bytes = num_byteio.getvalue()
```

# pil -> numpy
```python
num_numpy = np.asarray(num_pil)
```

# bytes -> numpy

```python
num_byteio = io.BytesIO(num_bytes)
with Image.open(num_byteio) as img:
  num_numpy = np.asarray(img)
```

# bytes -> pil

```python
num_byteio = io.BytesIO(num_bytes)
num_pil = Image.open(num_byteio)
```
virtualenvでpipdeptreeを使う

virtualenv上にpipdeptreeを入れて以下のコマンド。

```bash
python -m pipdeptree
```

# 環境

```
$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.4
BuildVersion:   19E266
```

- Python: `3.6.1`
- pip: `9.0.1`
- pipdeptree: `0.13.2`
WSL2を操作しようとすると「カーネル コンポーネントの更新が必要です」と表示される

# tl;dr
2020/3/13以降、wsl2の実行には、アップデートファイルのダウンロード＆インストールが必要になりました。

# 対応

`wsl`コマンドや`LxRunOffline`コマンドを実行すると、「WSL 2 を実行するには、カーネル コンポーネントの更新が必要です」と警告されます。

```
PS > wsl --set-version Ubuntu-18.04 2
変換中です。この処理には数分かかることがあります...
WSL 2 を実行するには、カーネル コンポーネントの更新が必要です。詳細については https://aka.ms/wsl2kernel を参照してください
```

ここで、警告文の通り、[https://aka.ms/wsl2kernel](https://aka.ms/wsl2kernel)にアクセスし、`wsl_update_x64.msi`をダウンロードします。
ダウンロードしたmsiファイルをインストール後、再度wslのバージョンアップコマンドを実行しました。

```
PS > wsl --set-version Ubuntu-18.04 2
変換中です。この処理には数分かかることがあります...
WSL 2 との主な違いについては、https://aka.ms/wsl2 を参照してください
変換が完了しました。
```

以上。
SSHの鍵追加時、特定のコマンドだけ実行できるようにする

# はじめに
自動デプロイが好きです！
いろんな案件で自動デプロイやCDの導入をオススメしています。

自動デプロイを行なうためにはデプロイ出来る権限を渡す必要があります。
例えばCircleCIにAWSのシークレットIDとキーを環境変数で渡したり、秘密鍵を使ったりなどです。

SSHと秘密鍵でやり取りする方法は最も基本的で汎用性が高いのですが、その反面チームでの鍵の管理に困ります。
すでに特定のサーバにアクセス件を持っているのか、なければ鍵をDMなどでやりとりするのか、その鍵から他のプロジェクトへのアクセス件が漏れないか…。
また案件、メンバーごとの個別に鍵を発行していると鍵の紛失、共有のためのコミュニケーションコストがかかります。

こういったセキュリティリスク軽減策と利便性はトレードオフの関係にあります。そのトレードオフの落としどろころとして良い方法を取るようにしています。

1. 鍵はリポジトリで共有
2. 鍵を元にデプロイできるようにする
3. その鍵でできることを制限する
4. （必要に応じて）鍵ごとにIPアドレス制限を行なう

# 鍵の共有
デプロイに必要な鍵をGitリポジトリで共有します。
こうすることでDMなどでやりとりしたり、紛失するリスクが無くなります。
ただそうするとリポジトリのアクセス制御＝鍵のアクセス制御となるため、想定以上のアクセス権が出てしまうことがあります。

# 鍵のコマンド制限

SSHの鍵には実行できるコマンドに制限をかけることができます。
下記のように`~/.ssh/authorized_keys`の鍵の行に`command`を設定します。

```conf:~/.ssh/authorize_keys
command="ls /path/to/deploy/" ssh-rsa AAiajfpisodaijfpoisadjspodisfjpasodifjaspodifjsapoijfspsadfijfpoaisjdfpoiasjofpoasijdfpoaisjfpoasijsdfpoasijsddYEaqL75Tf6BRYZuhaJMBAVDSn4grC7ypsjjdVLQDhmW40LEl4aLkbmFyI6lrzhoz1Y9j yousan@example.com
```

このコマンドは実行されるコマンドとしてキッチリ揃える必要があります。rsyncの場合、`-vv` オプションでどういったコマンドが送られるのか確認するとよいです。


```bash
$ rsync -vv -vlogDtpr -e "ssh -v -i ../etc/id_rsa"  . host.example.com:/path/to/deploy

opening connection using ssh -v -i ../etc/id_rsa host.example.com rsync --server -vvvlogDtpr . /path/to/deploy
```

上記の場合、`rsync --server -vvvlogDtpr . /path/to/deploy` がコマンドになります。
なのでauthorized_keysはこういった形で書くとよいです。

```conf:~/.ssh/authorize_keys
command="rsync --server -vvvlogDtpr . /path/to/deploy" ssh-rsa AAiajfpisodaijfpoisadjspodisfjpasodifjaspodifjsapoijfspsadfijfpoaisjdfpoiasjofpoasijdfpoaisjfpoasijsdfpoasijsddYEaqL75Tf6BRYZuhaJMBAVDSn4grC7ypsjjdVLQDhmW40LEl4aLkbmFyI6lrzhoz1Y9j yousan@example.com
```

# デプロイスクリプト

SSHの起動時にフィンガープリントの確認を求められることがあるため、オフにしておくと自動化は捗ります。[^1]

```bash
$ ssh -o 'StrictHostKeyChecking no'
```

特にCDで回す場合にはFingerprintの登録を行なうか、ここでオフにしておくと良いです。

[^1]: Man-in-the-Middle Attackのリスクは十分にご理解を。https://www.gremwell.com/ssh-mitm-public-key-authentication

```bash
#!/usr/bin/env bash
set -xe
cd -- "$(dirname "$BASH_SOURCE")" # ディレクトリをファイルがおいてある場所に移動する
cd ../dist # デプロイしたいディレクトリに移動する

chmod 0600 ../etc/id_rsa # Gitで共有されるファイルのパーミッションでは出すぎている可能性があるため、ここでパーミッションをへらす

rsync -vlogDtpr -e "ssh -o 'StrictHostKeyChecking no' -i ../etc/id_rsa" . yousan@example.com:/path/to/deploy

echo 'Successfully deplyed! Enjoy your coding.'

echo 'http://example.com'
```


# その他
鍵のコマンド制限をやっている事例って殆ど見かけないけど、実際のところはどうなんだろう…。
実はセキュリティ上問題がありますとか、知られていないだけとか、ご意見お待ちしています！
FuelPhpとUnity間でWWWFormの値を取得

## Unity側

```
WWWForm form = new WWWForm();
if (userID != "")
{
    form.AddField("userID", userID);
}
if (token != "")
{
    form.AddField("token", token);
}
if (stageId != "")
{
    form.AddField("stageId", stageId);
}

※何かしら処理（ヘッダー追加したり色々）

yield return www.SendWebRequest();
```

↓↓↓↓↓↓↓

## FuelPhp側

```
$stageId = Input::post('stageId');

// ログ出力
Log::info('Application started (with $stageId = '.$stageId.')', 'action_index()');

```

Input::Postで取得、キーを指定して受け取る

参考URL
http://fuelphp.jp/docs/1.7/classes/input.html

###キーを指定しない場合は連想配列で取得できる
(試してないがWWWFormのDictionaryを全部取得できると思われる)
※エラーになったので後で考える

```
$post = \Input::post();

$stageId = $post['stageId'];
```
MacBookProのSSDを引越したらbootcampが起動できなくてハマった

MacBook Pro (Retina, 13-inch, Mid 2014) の512GBのSSDを2TBに交換して、データ移行したら、bootcampの起動ができなくてハマったというお話
成功例だけを記す。

## 環境
MacBook Pro (Retina, 13-inch, Mid 2014) 
 - OS 10.15.3
 - Windows 10 with bootcamp

## やったこと

0. 各種バックアップ
1. xubuntuをusbでboot
2. ddコピーで 512 GB SSD --> 2TB 外付けHDD
3. MacBookProの底面を外して、SSD交換
4. xubuntuをusbでboot
5. 2TB 外付けHDD --> 2TB SSD
6. bootcampのMBRの修復

## 買ったもの
samsung 970 evo plus 2TB
M.2 -> 12+16 pin 変換アダプタ

## 作業

### xubuntuインストール

ddコピーを自分のディスクに対して行うのはちょっと気持ちが悪いので、
いつもlinuxを作ってそこからコマンドを出している。

普段はubuntuだったけど、気分を変えたいので、xubuntuを使ってみた。
xubuntuのisoイメージをDLして、usbにddコピーしただけ。

### 512 GB SSD --> 2TB 外付けHDD

xubuntuをusb bootして、端末を表示。

```
sudo fdisk -l
```

MacOS、BootCampが入っているドライブ名(/dev/sda)を確認。
移動先(/dev/sdcなど）が外付けHDDか確認。
この時、外付けHDDのパーティション方式はMBRにしていた。
(これも効くのか？）

そして、

```
sudo dd if=/dev/sda of=/dev/sdc bs=4096 status=progress
```

として、HDDに吸い出す。(~1h)

`bs=4096`はブロックサイズで、HDDへのバッファサイズと理解したら良い。
大きい値だと一度に書き込めるので、高速になる。4096 byteで十分だった。

`status=progress`は、`dd`の途中経過を標準出力に書き出すという指定。


### SSD交換

購入したものがぴったりハマってご満悦。
（IT用語のハマるでポジティブの使い方もあるんですね）

### 2TB 外付けHDD --> 2TB SSD

続いて、再度xubuntuを起動し、

```
sudo fdisk -l
```

で、出力元、出力先のドライブ名を確認したのち、

```
sudo dd if=/dev/sda of=/dev/nvme01p bs=4096 status=progress
```

として、書き込み。
データの入っている512 GiBを超えてしばらくしたら、ctrl + cで止めた。
（乱暴・・・）

### MBR修復


OSXは無事に起動。
bootcampは何度か再起動を繰り返し、リカバリーモードへ。

ここから悩んだのだが、bootcampはmbrを偽装しているらしく(hybrid gptという？)、
windowsからmbrを修復すれば良さそうという結論に至り、挑戦。

`システム回復オプション`から`コマンドプロンプト` を選んで、

```
bootrec /fixmbr
bootrec /rebuildbcd
```

として、MBRを修復する。
再起動して、無事にbootcampが起動。

めでたし
登录相关的日志查看

登录相关的日志涉及到系统的安全，所以是系统管理中非常重要的一部分内容。本文试图对登录相关的日志做一个整理。

## /var/log/auth.log
这是一个文本文件，记录了所有和用户认证相关的日志。无论是我们通过 ssh 登录，还是通过 sudo 执行命令都会在 auth.log 中产生记录。

执行
`$ ssh nick@myserver`

再执行下面的命令试试：
`$ sudo vim /var/log/auth.log`

日志同样会详细的记录本次 sudo 操作的过程。从中我们可以看到是哪个用户通过 sudo 执行了什么命令！

## /var/run/utmp
这是一个二进制文件，所以不能直接通过文本编辑器查看其内容。
它记录当前登录的每个用户的信息。因此这个文件会随着用户登录和注销系统而不断变化，它只保留当时联机的用户记录，不会为用户保留永久的记录。系统中需要查询当前用户状态的程序，如 who、w、users 等就需要访问这个文件。

## /var/log/wtmp

这是一个二进制文件，所以不能直接通过文本编辑器查看其内容。
该日志文件永久记录每个用户登录、注销及系统的启动、停机的事件。因此随着系统正常运行时间的增加，该文件的大小也会越来越大，增加的速度取决于系统用户登录的次数。该日志文件可以用来查看用户的登录记录，last 命令就通过访问这个文件获得这些信息。

## /var/log/btmp
这是一个二进制文件，所以不能直接通过文本编辑器查看其内容。
这个文件记录的是所有失败的登录尝试，使用 last 命令及其 -f 选项可以查看这个文件的内容：

`$ sudo last -f /var/log/btmp`

## /var/log/lastlog
这是一个二进制文件，所以不能直接通过文本编辑器查看其内容。
它会记录系统中所有用户最近一次登陆的信息。比如我们通过 ssh 登录时提示的此用户最后一次的登录时间，就是从这个文件中取出的：

其实这个文件的主要使用者是 lastlog 命令。

特别是 /var/run/utmp、/var/log/wtmp 和 /var/log/lastlog 这三个文件，它们都是日志系统中的关键文件，并且具有如下的逻辑联系：
当一个用户登录系统时，login 程序在 lastlog 文件中查看用户的 UID。如果该用户存在，就把该用户上次登录、注销的时间以及从哪个主机登录的信息写到标准输出中。然后 login 程序在 lastlog 中记录新的登录时间，并打开 utmp 文件添加用户本次的登录记录。接下来，login 程序打开 wtmp 文件并添加用户在 utmp 文件中的记录。当用户退出时会把更新的 utmp 文件中的记录添加到 wtmp 文件中，并从 utmp 文件中删除用户的记录。

我们可以看到除了 auth.log 文件，其它几个文件都是二进制文件，因而不能使用 less 之类的命令直接查看。下面我们来介绍和登录相关的一些命令，其实它们几乎都是通过查询这些日志文件来提供信息的。

lastlog 命令
lastlog 命令用来显示系统中所有用户最近一次登陆的信息：


图中显示的只是完整列表的一部分，**Never logged in** 表示该用户从来没有登陆过。如果要查看某个用户的最后登陆信息，可使用 -u 选项：



其实 lastlog 命令就是从 /var/log/lastlog 文件中取出的内容。

last 命令
last 命令用来显示用户最近登录的信息。执行 last 命令，它会读取 /var/log/wtmp 文件的内容。并把该文件记录的用户登录历史全部显示出来：

`$ last`


信息记录了谁在什么时间从哪里登录了服务器，登录了多长时间。需要注意的是系统中的 wtmp 日志文件经常会被轮转，所以有时你需要显式的指定 last 命令从哪个文件中读取信息：

`$ last -f /var/log/wtmp.1`


如果我们想快速知道系统最后一次的重启时间，可以使用下面的命令：

`$ last reboot`

who 命令
who 命令通过查询 /var/run/utmp 文件来显式系统中当前登录的每个用户。默认的输出包括用户名、终端类型、登录日期及远程主机：

w 命令
如果能够查询到当前登录系统的用户都在干什么是不是一件令人很兴奋的事情呢！使用 w 命令就可以做到：

`$ w`

我们可以看到用户 nick 同时登录了两个终端，在其中一个终端中执行了 w 命令，而在另一个终端中正通过 vim 编辑  /etc/passwd 文件！
其实 w 命令是先通过查询 utmp 文件获得当前登录的用户，然后显示每个用户和它所运行的进程信息。

users 命令
users 命令用单独的一行打印出当前登录的用户，每个显示的用户名对应一个登录会话。如果一个用户有不止一个登录会话，那他的用户名将显示多次：

因为 nick 通过三个终端登录了主机，所以在同一行中名字出现了三次。

总结
本文整理了 Ubuntu 系统中常见的一些与登录相关的文件和命令。通过它们可以快速的查看当前用户的登录情况和所有用户登录登出的历史记录，并且可以查询到用户使用 root 权限执行的操作。这对我们维护系统的安全和用户的管理都非常有帮助。
【GCP】DNSを設定してみた

GCPにてDNSの設定をしてみました。

設定は問題ないと思いますが、自分で払いだしたドメイン名でないと効果のほどがわからないので、
今度そのへんの設定をしてみたいと思います。

以前にお名前.comで0円のドメインを払いだしたからそれを使おうかな。

【参考サイト】
http://yebisupress.dac.co.jp/2018/08/23/publish_website_with_google-cloud-platform/

【作業】
以下の作業をGCPにて実施していきます。
	DNSゾーンの作成
	Aレコードの追加
	レジストラへの登録

DNS関係は前のPJで少し勉強していましたが、
レジストラについて、理解が及んでいなかったので、以下のサイトを参照。

https://www.onamae.com/clever/about/regist.html?&banner_id=1075_kwt_domain_dsa_a&utm_source=google&utm_medium=paidsearch&utm_content=dsa&waad=AZSRqhEU&flow=normal&argument=29kVaVam&dmai=a5c6568ac40122&gclid=EAIaIQobChMI67mv3NLI6AIVDa6WCh3irwLzEAAYASAAEgKhjPD_BwE

レジストリ、レジストラ、代理店併せて理解しておくことが大事。

お名前.comとかがレジストラにあたり、公認レジストラが国内に19社しかない。

GCPでドメインを作成したら公認レジストラに登録する作業が必要。

今回、参照サイトに合わせてmy.zone.jpというのを登録して、
問題はなかったけど、ちゃんと取得したDNSじゃないと実際に使うことができないと思う。

実際にmy.zone.jpをdigると他のIPがでてくる。

【NextAction】
・実際に取得したドメインで設定してみたい。
初投稿

## 自己紹介
初めまして！社会人２年目、漸く業界に慣れてきた者です。
私は文系出身のため、理系出身の方の考え方に合わせられるよう考え方も学びつつ日々業務を学んでいます。

##Qiitaと自分
就職活動中、様々なIT企業で勉強するうえでお勧めされたサイトの一つがQiitaでした。
調べたところとても個性豊かで面白いサイトだと分かり、それ以降プログラミングの書き方の勉強と理系の価値観の習得を目指すために色んな記事を読んでます。
今回投稿するに至ったのは、たまたまお見かけしたとある記事に触発され、社会人２年目になったこともあり自分用のメモを兼ねてアウトプットしたいと思ったからです。

## これから
今まで学んできたことや初心者として経験した時の体験談などのアウトプットやこの先行うことの自分用のメモとして記事を投稿していきます。
よろしくお願いいたします！
typescript + jest

## singletonクラスのmock化

テスト対象が依存しているsingletonクラスの雛形

```typescript:singleton.ts
export class singleton {
    private static instance_:instance_
    public static instance():singleton {
        if (!this.instance_) {
          this.instance_ = new singleton()
        }
        return this.instance_
    }

    private constructor(){}

    public func1() {}
    public func2() {}
}
```

テストターゲットクラス

```typescript:hoge.ts

import {singleton} from "./singleton"
export class hoge {
    public hoge() {
        singleton.instance().func1()
    }
    public piyo() {
        singleton.instance().func2()
    }
}
```

hoge.tsのテストコード

```typescript:hoge.test.ts
import {singleton} from "./singleton"
const mock_instance = jest.fn()
const mock_func1 = jest.fn()
const mock_func2 = jest.fn()
jest.mock("./singleton")
mock_instance.mockImplementation(()=>{
    return {
        func1: mock_func1 ,
        func2: mock_func1 
    }
})
singleton.Instance = mock_instance
```

自動生成されたモックをベースに手動でモックを作っています。
これでhoge.tsが参照するsingletonクラスはモック化されているので、
テストを行うことができます。  

注意点は以下です

* mock_instance変数名はmockから始める必要があります。  
* singletonクラスのinstance関数にget修飾子を使用することはできません。
Jamstack　Docker + Nuxt + Contentful + Vuetify + Netfliyでポートフォリオ作成②

前回の続きです。
https://qiita.com/knitbow/items/89478226da7bd365b9cd

# やりたいこと
- Nuxtでフロントを作成
- Dockerで環境構築
- Contentfulでポートフォリオ情報の取得
- Vuetifyで見た目整形
- Netfliyで公開


## NuxtとContentfulの連携部分
- Contentfulにて、SpaceIDとトークンの確認
Setting - API kyes
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166346/96d0bd35-c5c0-5036-813f-152c48822c89.png)
Add API Keyをクリック

Space IDとContent Delivery API - access tokenを確認


## .envの作成
```
.env

CTF_SPACE_ID=ContentfulのspaceID
CTF_CDA_ACCESS_TOKEN=Contentfulのaccess token

```
環境ファイルはgit保存しないように、ignore設定


## lib/config.js
```
require('dotenv').config()

function getValidConfig(configEnv, keys) {
  let { config, missingKeys } = keys.reduce(
    (acc, key) => {
      if (!configEnv[key]) {
        acc.missingKeys.push(key)
      } else {
        acc.config[key] = configEnv[key]
      }
      return acc
    },
    { config: {}, missingKeys: [] }
  )

  if (missingKeys.length) {
    throw new Error(`Contentful key is missing : ${missingKeys.join(', ')}`)
  }
  return config
}

module.exports = {
  getConfigForKeys(keys) {
    const configEnv = {
      CTF_SPACE_ID: process.env.CTF_SPACE_ID,
      CTF_CDA_ACCESS_TOKEN: process.env.CTF_CDA_ACCESS_TOKEN
    }
    return getValidConfig(configEnv, keys)
  }
}

```
キー管理のConfigを用意

## plugins/contentful.js
```
const contentful = require('contentful')
const defaultConfig = {
  CTF_SPACE_ID: process.env.CTF_SPACE_ID,
  CTF_CDA_ACCESS_TOKEN: process.env.CTF_CDA_ACCESS_TOKEN
}

module.exports = {
  createClient(config = defaultConfig) {
    return contentful.createClient({
      space: config.CTF_SPACE_ID,
      accessToken: config.CTF_CDA_ACCESS_TOKEN
    })
  }
}

```
Contentfulを利用するためのjsを用意


## nuxt.config.js
```
import colors from 'vuetify/es5/util/colors'
import {createClient} from './plugins/contentful.js'

const pkg = require('./package')
const {getConfigForKeys} = require('./lib/config.js')
const ctfConfig = getConfigForKeys([
  'CTF_SPACE_ID',
  'CTF_CDA_ACCESS_TOKEN'
])

const {createClient} = require('./plugins/contentful')
const cdaClient = createClient(ctfConfig)

export default {
  mode: 'universal',

略・・・
}
```
nuxt.config.jsを設定

## 参考にしたサイト
- https://qiita.com/isihigameKoudai/items/3e45ade7c438176a4cc9
AnsibleでwindowsのRDP複数セッションを有効化する

## モチベーション :innocent:

Windows の踏み台サーバとかで、複数セッション張りたいシチュエーションがありました。
ユーザー作成とかの流れで実行するといいかと。

## 環境 :computer: 

- local
  - macOS 10.15.3
  - ansible 2.9.6 (Python 3.7.5)
- remote
  - GCE instance
  - Windows Server 2016 Datacenter

## やり方 :muscle: 

レジストリを編集します。

```yaml:multi-rdp-sessions/tasks/main.yml
- name: "Allow Multiple RDP Sessions"
  win_regedit:
    path: HKLM:\System\CurrentControlSet\Control\Terminal Server
    name: fSingleSessionPerUser
    data: 0
    type: dword
    state: present
```

## 参考

- マニュアルで実施するばあい
  - [HOW TO ALLOW MULTIPLE RDP SESSIONS FOR THE SINGLE USER IN WINDOWS?](https://manage.accuwebhosting.com/knowledgebase/2617/How-to-allow-multiple-RDP-sessions-for-the-single-user-in-Windows.html)
- 元々この方法ができないか検討していたんですが、今のところローカルグループポリシーを編集する ansible module はなさげ :thinking:
  - [リモートデスクトップで2セッション有効にする方法 – Windows Server 2012 R2](https://mseeeen.msen.jp/enable-multiple-session-in-windows-server-2012-r2/)
- Remote Desktop Gateway server が設定されている場合はこれかな？
  - [win_rds_settings – Manage main settings of a Remote Desktop Gateway server](https://docs.ansible.com/ansible/latest/modules/win_rds_settings_module.html)
開発用のテキストエディタを導入する


開発用のテキストエディタは好みのものを選べばいいのですが、情報量が多いものを選ぶほうが無難です。
2020年4月現在、Microsoft社の[Visual Studio Code](https://azure.microsoft.com/ja-jp/products/visual-studio-code/) (vscode)がよく利用されているので、ここでもvscodeを利用してます。


## インストール

いくつかの方法でインストール可能ですが、brew でインストールしてみます。

>普通にインストーラーも利用できます。

```bash
brew cask install visual-studio-code
```

>すでにvscodeがインストールされている場合、エラーとなる場合があります（追加インストールの必要はありません）。

## Launchpadから起動

インストールが完了したらLaunchpadもしくはApplicationから起動できます。

![スクリーンショット 2020-04-02 10.31.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/28ebd9db-88a9-bdcb-23db-b5ef0f0161b5.png "スクリーンショット 2020-04-02 10.31.37.png")

## コマンドラインから起動

コマンドラインからcodeと打つことでも起動できます。

>この方法は実際の開発ではよく使います。

作業フォルダにて下記のよう入力します。 

```bash
code .
```

Visual Studio Codeが起動すると下記のような状態です。

![スクリーンショット 2020-04-02 10.45.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/ed83d551-87c1-e840-993b-c724e2ea0d4d.png "スクリーンショット 2020-04-02 10.45.28.png")



## 考えよう

* 他にどのようなエディタの選択肢がありますか？
* 普通のテキストエディタと開発用のテキストエディタは何がちがいますか？
* Visual StudioとVisual Studio Codeの差はなんですか？
* IDEとはなんですか？
psycopg2 インストールエラー

```terminal
$ pip install psycopg2
```

でエラー。

エラー内容（抜粋）：

```terminal

 Error: pg_config executable not found.

pg_config is required to build psycopg2 from source.  Please add the directory
    containing pg_config to the $PATH or specify the full executable path with the
    option:
    
        python setup.py build_ext --pg-config /path/to/pg_config build ...
    
    or with the pg_config option in 'setup.cfg'.
    
    If you prefer to avoid building psycopg2 from source, please install the PyPI
    'psycopg2-binary' package instead.
    
    For further information please check the 'doc/src/install.rst' file (also at
    <http://initd.org/psycopg/docs/install.html>).
```

背景：
Ubuntu 18.04.4
AWS EC2インスタンス
Django実装のため、仮想環境にpsycopg2インストールしようとしていた。

やったこと。

①以下をインストール

```terminal
$ pip install psycopg2-binary
```

→解決せず。

②pg_config　がインストールに必要と書いてあるため、あるか確認

```terminal

pg_config --version

```

→出力結果。

```terminal
Command 'pg_config' not found, but can be installed with:

sudo apt install libpq-dev        
sudo apt install postgresql-common
```

`pg-config` が見つからないが、以下のコマンドでインストールできるとあったので、

③pg_config をインストール。

```terminal
$ sudo apt install libpq-dev   
```

④再度トライしたらインストールできた。

```terminal
$  pip install psycopg2
```

参考： https://www.psycopg.org/docs/install.html

エラーメッセージをよく読み→公式ドキュメントを読むのが結局早かった。
SpringMVC 多重From、サーバー側に処理を呼び出す方法の一つをメモ

`````xxx.jsp
xxxxx
 <a href='javascript:downloadAAA("${xxxId}");'>
 <a href='javascript:downloadBBB("${xxxId}");'>
xxxxx
<form:form
	action='<%=ActionUtils.getActionPath(request, AAAController.class, "AAAControllerMethod")%>'
	modelAttribute="AAAForm" id="xxxDownloadFormA"
	method="get">
</form:form>
xxxxx
<form:form
	action='<%=ActionUtils.getActionPath(request, BBBController.class, "BBBControllerMethod")%>'
	modelAttribute="BBBForm" id="xxxDownloadFormB"
	method="get">
</form:form>
xxxxx
```

`````xxx.js
//AAA
function downloadAAA(xxxId) {
	var form = $('#xxxDownloadFormA');
	location.href = form.attr('action') + "/" + xxxId;
}
//BBB
function downloadBBB(xxxId) {
	var form = $('#xxxDownloadFormB');
	location.href = form.attr('action') + "/" + xxxId;
}
```

`````xxxController.java
@RequestMapping(method = RequestMethod.GET, value = "downloadAAA/{xxxId}/{yyy}")
public ModelAndView AAAControllerMethod(@ModelAttribute XXXDownloadForm xxxDownloadForm,
		BindingResult bindingResult) throws Exception {
xxx
}

@RequestMapping(method = RequestMethod.GET, value = "downloadBBB/{xxxId}/{yyy}")
public ModelAndView BBBControllerMethod(@ModelAttribute XXXDownloadForm xxxDownloadForm,
		BindingResult bindingResult) throws Exception {
xxx
}
AWSの費用をslackに通知する

# クラウドの費用は定期的に確認
日々開発を行なっているとCost Explorerを段々と見なくなり、後になって多額の請求が来て死ぬってことありますとねw
ってことでLambdaで定期的にslackに通知して確認できる様にしました

# 構成
![CostxLambda.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/c1fae5e7-d171-e338-36ab-3b2d80d0859d.jpeg)

# Lambdaのソースや詳しい設定方法
https://dev.classmethod.jp/cloud/aws/notify-slack-aws-billing/
classmethodさんよく活用させてもらっています、ありがとうございます！！
BizRobo!basicでライセンスを更新する際にハマった話

知っている人は問題無いのでしょうが、個人的にハマったのでメモとして残しておきます。  

BizRobo!basicでライセンスを更新する際は、ManagementConsoleの「管理」タブから「ライセンス」タブを選択することになっています。  
しかし、自分の環境で確認したところ「ライセンス」タブがどこにも無い！
![clip_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375744/914b3947-5409-a7a7-f4e3-0d23a7c93077.png)


<br/>実は、デスクトップが小さかった（普段会社で使用しているPCはSXGA＝1280×1024）だけで、縮小表示したらちゃんとライセンスタブがありました。
![clip_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375744/26bf4c18-7b3c-44a1-a8ef-928cba4f6f4c.png)


<br/>それにしても、もっとこう、何とかする方法は無かったんですかね。
最新版では直っているんでしょうか（確認したバージョンは10.4.0.1）。
バックグラウンド音源をミュート

効果音を再生する時に裏で音楽再生アプリ等で再生していると音が重なって聞き取れない！
という時にバックグラウンドの音を一時的にミュートする方法

バックグラウンド音源をミュート

```java:
AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
	AudioFocusRequest focusRequest =
		new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK)
			.setAudioAttributes(new AudioAttributes.Builder()
			.setUsage(AudioAttributes.USAGE_MEDIA)
			.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
			.build())
		.setAcceptsDelayedFocusGain(true)
		.setOnAudioFocusChangeListener(audio_focus_listener)
		.build();
	audioManager.requestAudioFocus(focusRequest);
} else {
	audioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
}
```

バックグラウンド音源のミュートを解除

```java:
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
	AudioFocusRequest focusRequest =
		new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK)
			.setAudioAttributes(new AudioAttributes.Builder()
			.setUsage(AudioAttributes.USAGE_MEDIA)
			.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
			.build())
		.setAcceptsDelayedFocusGain(true)
		.setOnAudioFocusChangeListener(audio_focus_listener)
		.build();
	audioManager.abandonAudioFocusRequest(focusRequest);
} else{
	audioManager.abandonAudioFocus(null);
}
```
git cloneで「fatal: Unable to find remote helper for 'https'」 が出たときの対処方法

## はじめに

ググるとlibcurl-develをリンクしろというのが多くひっかかりますが、libcurl-develをリンクしていてもエラーが出るケースがあります。

例えば、最小のgit環境を作ろうと、以下のようにした場合、

```Dockerfile:Dockerfile
FROM centos:7 AS src
RUN yum install -y  git
FROM centos:7
COPY --from=src /usr/bin/git /usr/bin/git
ENTRYPOINT ["/bin/sh"]
```

centos7のgitはhttpsにも対応しているのですが、できあがったコンテナではhttpsが利用できません。

```console
# git clone https://github.com/qualitiaco/action-lambda-build-pack-sample.git
Cloning into 'action-lambda-build-pack-sample'...
warning: templates not found /usr/share/git-core/templates
fatal: Unable to find remote helper for 'https'
```

## 原因

文字通り「remote helper for 'https'」というのがないのが原因です。

これは、git-remote-httpsという名前で、/usr/libexec/git-coreの下にあります。

```console
# ls -l /usr/libexec/git-core/git-remote-https
-rwxr-xr-x    4 root     root       1495272 Dec 10 21:39 /usr/libexec/git-core/git-remote-https
```

## 解決方法

/usr/libexec/git-core/git-remote-httpsをコピーします。

OSによってはgit-remote-httpへのsymlinkになっている場合もあるので、その場合、git-remote-httpもコピーします。

## 確認

```Dockerfile:Dockerfile
FROM centos:7 AS src
RUN yum install -y  git
FROM centos:7
COPY --from=src /usr/bin/git /usr/bin/git
COPY --from=src /usr/libexec/git-core/git-remote-https /usr/libexec/git-core/
ENTRYPOINT ["/bin/sh"]
```

```console
# git clone https://github.com/qualitiaco/action-lambda-build-pack-sample.git
Cloning into 'action-lambda-build-pack-sample'...
warning: templates not found /usr/share/git-core/templates
remote: Enumerating objects: 103, done.
remote: Counting objects: 100% (103/103), done.
remote: Compressing objects: 100% (49/49), done.
remote: Total 103 (delta 30), reused 89 (delta 21), pack-reused 0
Receiving objects: 100% (103/103), 11.33 KiB | 0 bytes/s, done.
Resolving deltas: 100% (30/30), done.
```

動きました。

## alpineでもっと小さく

alpineだと、もっと小さくなりますが、追加でいくつかファイルが必要になります。

```Dockerfile:Dockerfile
FROM alpine AS src
RUN apk add git
FROM alpine
COPY --from=src /usr/bin/git /usr/bin/git
COPY --from=src /usr/lib/libpcre2-8.so.0 \
                /usr/lib/libcurl.so.4 \
                /usr/lib/libnghttp2.so.14 \
                /usr/lib/
COPY --from=src /usr/libexec/git-core/git-remote-https /usr/libexec/git-core/
COPY --from=src /etc/ssl/certs/ /etc/ssl/certs/
ENTRYPOINT ["/bin/sh"]
```

これで動きます。

## おわりに

git cloneで「fatal: Unable to find remote helper for 'https'」のエラーが出る場合についての、libcurl-develを入れて再コンパイルしましょう、では解決いない場合の解決方法について説明しました。

*本記事は @qualitia_cdevの中の一人、@hirachanさんに作成していただきました。
Ajax通信でActionController::InvalidAuthenticityTokenしたときの対応

# 原因とか理由とかすっ飛ばして結論

送信するdataに`authenticity_token: $('meta[name="csrf-token"]').attr('content')}`を追加。

```js
    let ajax = function (method, data) {
      data = $.extend(data, {authenticity_token: $('meta[name="csrf-token"]').attr('content')});
      $.ajax({
        type: method,
        url: "hope/the/colona/is/orver",
        timeout: 3000,
        data: data,
        dataType: 'json'
      }).done(function (response, textStatus, jqXHR) {
        console.log(response);
      }).fail(function (jqXHR, textStatus, errorThrown) {
        console.log(response);
      });
    };
```
Pythonで制御可能な直流電源の調査

電子回路の実験で使う機器がPythonで制御できると、様々な実験やテストが自動化できて便利である。ということで、Pythonで制御可能な直流電源を探してみました。

まとめ
- VISA/SCPIプロトコルサポートの製品であれば、Pythonで制御可能
- 安価なところだと Rigol、Siglent の製品が良さげ


# 参照

## Standards

- GPIB (IEEE-488.2)
    - 昔の標準、ケーブルが驚きの太さ
- RS232
    - 昔の標準、USB変換できるが手間
- LAN
    - 大量に制御とか、距離があるときは便利
- USB
    - お手軽
    - Using Linux to Control USB Instruments
        - http://literature.cdn.keysight.com/litweb/pdf/5989-6718EN.pdf
    - USB計測器制御チュートリアル
        - http://www.ni.com/tutorial/4478/ja/
- SCPI 
    - OSS
        - https://github.com/j123b567/scpi-parser
        - https://github.com/MightyPork/scpi_parser
    - Guide
        - https://en.wikipedia.org/wiki/Standard_Commands_for_Programmable_Instruments
        - https://manual.kikusui.co.jp/P/PLZ4W/i_f_manual/japanese/PLZ_COM_LIST.pdf
        - https://www.keysight.com/main/editorial.jspx%3Fcc%3DJP%26lc%3Djpn%26ckey%3D2304680%26id%3D...Part0?&cc=JP&lc=jpn
- VISA 計測制御用バスを用いた通信に使用される高レベルAPI
    - OSS
        - PyVISA https://github.com/pyvisa/pyvisa
        - GPIB-pyvisa https://github.com/MarkDing/GPIB-pyvisa
        - DCPS https://github.com/sgoadhouse/dcps
    - Guide
        - Linux + Python で VISA/SCPI を使った機器制御
            - https://heptech.wpblog.jp/2019/12/05/contol_devices_via_visa-scpi_with_python_on_linux/


## プログラマブル DC電源 製品

- Siglent Technologies
    - https://siglent.jp/sl/about-siglent-2/
    - SPD1000X,(SPD1168X, SPD1305X)
        - https://siglent.jp/sl/spd1000x/
        - I/F: USB,LAN
        - Protocol: SCPI
    - SPD3303X-E 
        - https://siglent.jp/sl/spd3303x-spd3303x-e/
        - I/F: USB,LAN
        - Protocol: SCPI
        - OSS
            - https://github.com/Kurokesu/siglent_psu_api
- Rigol
    - https://www.rigolna.com/
    - DP700
        - I/F:RS232
    - DP800, DP832A DC Power Supply 
        - I/F:RS232, USB, LAN
        - Protocol: SCPI
        - OSS
            - https://github.com/sgoadhouse/dcps
            - https://github.com/kearneylackas/DP832-Python
            - https://www.eevblog.com/forum/testgear/controlling-rigol-dp832a-psu-with-python/
- Keysight(Agilent)
    - E3631A  3 重出力 DC 電源装置 (販売終了)
        - http://literature.cdn.keysight.com/litweb/pdf/E3631-90413.pdf
        - I/F:RS232, GPIB
        - Protocol: SCPI
- OWON
    - 1CH Liner DC Power Supply (P4305,P4603)
        - http://www.owon.com.hk/products_owon_1ch_liner_dc_power_supply
        - I/F: RS232
        - Protocol: SCPI
- 菊水 Kikusui
- 松定
    - P4K-80
        - I/F: USB,LAN,RS232,RS485,GPIB
        - Protocol: ？
- KORAD
    - KA3005P
        - I/F:USB
        - Protocol: ?
        - OSS
            - https://github.com/starforgelabs/py-korad-serial
            - https://github.com/vb0/korad

その他、おすすめの製品やコード(OSS)があればご伝授ください。
PostgreSQLを利用すると、rails db:createでエラーが発生するトラブルシューティング

# 環境
Vagrant + Ubuntu 16.04.5 LTS
Rails 5.2.4.2
PostgreSQL9.5.19

# はじめに
データベースにPostgreSQLを指定して、データベースを作成しようとすると、PostgreSQLに、vagrantというロールがありませんというエラーが表示されて、Railsからデータベースが作成できません。

```cmd
$rails new test_migrate -d postgresql
$cd test_migrate
$rails db:create

FATAL:  role "vagrant" does not exist
Couldn't create 'test_migrate_test' database. Please check your configuration.
rails aborted!
ActiveRecord::NoDatabaseError: FATAL:  role "vagrant" does not exist
bin/rails:4:in `<main>'

Caused by:
PG::ConnectionBad: FATAL:  role "vagrant" does not exist
bin/rails:4:in `<main>'
Tasks: TOP => db:create
(See full trace by running task with --trace)
```

# 解決方法
PostgreSQLをインストールした時に、postgresというユーザーが作成されているため、postgresユーザーでログインする。

```cmd
$sudo su - postgres
```
createuserコマンドは、PostgreSQLのロール（ユーザーという言い方をしてもいいかも知れない）を作成するコマンドです。普段、Ubuntuにログインしているユーザー名のロールを作成します。自分はVagrantを使っているため、vagrantユーザーでログインしているため、vagrant名のロールを作成することになります。また、予め、パスワードを設定しておかないと、pgAdminから接続ができない事るので注意。オプションの**-s**は、スーパーユーザーの事。

[createuserのコマンド解説] (https://www.postgresql.jp/document/9.0/html/app-createuser.html)

```cmd
~$createuser vagrant -s
```
**\du**で、ロールの一覧を表示して、**vagrant**が追加されている事を確認する。既に存在している**postgres**は、デフォルトで用意されているものです。

```cmd
~$psql
postgres=#\du
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/926d6640-592e-3833-83fb-f241e783cd83.png)

PostgreSQLからログアウトします。その後、exitをして、postgreユーザーからもログアウトします。

```cmd
postgres=#\q
~$exit
```
その後、rails db:createをすれば、問題は解決！
【Day42】積み上げ日記

##予定
■しまぶーのIT大学＃３　＃４
■ドットインストール
−クリックイベント
−アロー関数
−getzelementById
−CSSクラス操作
−定数

##完了
■しまぶーのIT大学＃３　＃４
■ドットインストール
−クリックイベント
−アロー関数
−getzelementById
−CSSクラス操作
−定数

##学習時間
４h

##学習ポイント
■一度JSで変化させたものを、元の状態にする。
add → toggle　に変える！

■学習は立体的に理解するため、紙でまとめました。

#疑問点
・コンソールが結果何のためにあるのか

##計画通り進んだか？
進んだ。JSを完璧に覚えようとしすぎているので、インプット２割、アウトプット８割の配分でスケジューリングする。明日はおみくじアプリを作るまで寝ない！
Introducing 1.1.1.1 for Families - 翻訳

2020/4/1 22:00に投稿されたCloudflare社の[ブログ記事](https://blog.cloudflare.com/introducing-1-1-1-1-for-families/)の翻訳記事です。

---

2年前の今日、私たちは1.1.1.1を発表しました。
1.1.1.1は安全で高速、プライバシーに配慮したDNSリゾルバで、誰でも無料で使用することができます。
この2年間で、1.1.1.1は私たちの想像を超えた成長を遂げました。
今日では、1日あたり2,000億以上のDNSリクエストを処理し、Googleに次ぐ世界第2位のパブリックDNSリゾルバとなりました。


昨日、1.1.1.1のプライバシー審査結果を発表しました。
Cloudflareのビジネスは、ユーザーデータの販売やターゲット広告に関わらないため、1.1.1.1の強力なプライバシー保護にコミットすることは簡単なことでした。
また、`DNS over TLS`や`DNS over HTTPS`などの暗号化されたDNS技術のサポートにも率先して取り組んできました。
DNSを平文で送信するのをやめるのはもうとっくに過去のことであり、暗号化されたDNSトラフィックが日々増えているのを目の当たりにして興奮しています。

## 1.1.1.1 for Families

1.1.1.1.1を発売して以来、私たちが受けたリクエストの中で一番多かったのは、悪質サイトを自動的にフィルタリングしてほしいというものでした。
1.1.1.1.1はユーザーのプライバシーを保護し、効率を最適化することができますが、これはもともと高速なDNS解決のために設計されており、コンテンツをブロックしたり、フィルタリングしたりするためのものではありません。
私たちが受け取ったリクエストの多くは、セキュリティ上の脅威からの保護手段を確保し、子供がアダルトコンテンツにアクセスしないようにしたいというホームユーザーからのものでした。
本日は、そのようなご要望にお応えします。


**1.1.1.1.1 for Familiesのご紹介**
ホームネットワークに保護層を追加し、マルウェアやアダルトコンテンツから保護する最も簡単な方法です。
1.1.1.1.1 for Familiesは、Cloudflareのグローバルネットワークを活用し、世界中で高速かつ安全にご利用いただけます。
また、2年前に1.1.1.1.1をリリースしたときに約束したものと同じ強力なプライバシー保証が含まれています。
また、1.1.1.1.1と同様に、世界中のどの家庭にも無料で提供しています。

## Two Flavors: 1.1.1.2 (No Malware) & 1.1.1.3 (No Malware or Adult Content)

1.1.1.1.1 for Familiesはセットアップとインストールが簡単で、ご家庭の機器やネットワークルーターの設定でプライマリDNSとセカンダリDNSの2つの数字を変更するだけで完了します。
1.1.1.1.1 for Familiesの設定は通常1分もかからず、一般的なデバイスやルーターについてはインストールガイドで説明しています。

1.1.1.1.1 for Familiesには、マルウェアをブロックするオプションと、マルウェアやアダルトコンテンツをブロックするオプションの2つのデフォルトオプションがあります。
どのIPアドレスを設定するかを選択します。

```
Malware Blocking Only
Primary DNS: 1.1.1.2
Secondary DNS: 1.0.0.2

Malware and Adult Content
Primary DNS: 1.1.1.3
Secondary DNS: 1.0.0.3
```

## Additional Configuration

今後数ヶ月の間に、1.1.1.1.1 for Familiesの追加設定を定義する機能を提供する予定です。
これには、特定のサイトのホワイトリストやブラックリストを作成するオプションが含まれます。
ソーシャルメディアなどのカテゴリがブロックされる時間帯を設定したり、ご家庭のインターネット利用状況のレポートを取得したりすることができます。

1.1.1.1.1 for Familiesは、CloudflareのGateway製品と同じサイトカテゴリ化およびフィルタリング技術の上に構築されています。
Gatewayの成功を受けて、私たちは、どのようなホームネットワークでも、高速で信頼性が高く、安全で、潜在的に有害なコンテンツから保護されるような、使いやすいサービスを提供したいと考えました。

## Not a Joke

Cloudflareの事業のほとんどは、企業向けサービスの販売です。
しかし、毎年4月1日には、当社のネットワークを活用した新しいコンシューマ製品を発売し、すべてのインターネット・ユーザーにさらなるスピード、信頼性、セキュリティを提供するのが恒例となっています。
企業向けに販売することで収益を上げていますが、この時期に発売する製品は、すべてのインターネットユーザーに幅広い影響を与えるため、私たちの心に深く刻まれています。

今年は、私たちの多くが自宅に閉じこもり、COVID-19から地域社会を守り、ホームネットワークに依存している中で、1.1.1.1.1 for Familiesを立ち上げることが特に重要であると考えました。
私たちは、この困難な時期に、1.1.1.1 for Familiesがあらゆる家庭に少しでも安心感を与える一助となることを願っています。