OmniAICreator/Qiita-1.07M huggingface dataset:
Goでtar.gzを出力する

勉強用にtar.gzのサンプルを作りました。ソースコード自身をtar.gzに格納圧縮し、そのバイト列を標準出力に表示し、output.tar.gzに保存し、終了します。bytes.Buffer、gzip.Writer、tar.Writerは全てio.Writerインターフェースを実装しているので順番に噛み合わせてtar.gzされたバイト列を出力できます。

## ソース

```go:tar.gz.go
package main

import (
	"archive/tar"
	"bytes"
	"compress/gzip"
	"fmt"
	"io"
	"os"
)

func writefile(w *tar.Writer,name string){
	if file, err := os.Open(name) ; err == nil{
		fi, _:=file.Stat()
		hdr := new(tar.Header)
		hdr.Size=fi.Size()
		hdr.Name=fi.Name()
		w.WriteHeader(hdr)
		io.Copy(w, file)
		file.Close()
	}
}
func main() {
	var buf bytes.Buffer
	gz := gzip.NewWriter(&buf)
	tw := tar.NewWriter(gz)
	writefile(tw,"tar.gz.go")
	tw.Close()
	gz.Close()
	data:=buf.Bytes()
	fmt.Print(data)
	if file, err := os.Create("output.tar.gz") ; err == nil{
		file.Write(data)
		file.Close()
	}
}
```

### 補足
- １ファイルならtarする必要がないよね
    - そのとおりです。実際はwritefile()を複数呼んでファイルを追加します。
- 直接ファイルに書き込めばいいのでは？
    - 圧縮後の中身を見たかったので一度バイト列に出力しました。
docker-credential-ecr-login can only be used with Amazon Elastic Container Registry. のエラーを消す

# `docker-credential-ecr-login` とは？

`docker-credential-ecr-login` っていうのは、 **Amazon ECR**  （Amazon が提供している Dockerレジストリサービス）に、PCからアクセスする際に必要になるログイン作業を、自動化してくれるツールです。

`amazon-ecr-credential-helper` と同じものです。（多分）

インストール方法等、詳細はこちらをご覧ください。
[amazon-ecr-credential-helperをWindowsにインストールする](https://qiita.com/segur/items/d2a9ae4215212af34f4d)



# プルしたら `docker-credential-ecr-login` でエラーが発生した

新しいPCに `docker-credential-ecr-login` をインストールして、 `docker pull node:12.3.1-alpine` を実行したところ、以下のエラーが発生しました。

```bash
$ docker pull node:12.3.1-alpine
ERRO[0000] Error parsing the serverURL                   
error="docker-credential-ecr-login can only be used with Amazon Elastic Container Registry." 
serverURL="https://index.docker.io/v1/"
```

> `docker-credential-ecr-login` 使って `https://index.docker.io/v1/` (Docker Hubのこと) にアクセスしようとしてますけど、 `docker-credential-ecr-login` はAmazon ECRでしか使えませんよ！

みたいな意味だと思います。



# `credsStore` じゃなくて `credHelpers` を使わなきゃダメらしい

こちらの記事に同じ症状のことが記載されてました。
[docker-credential-ecr-login can only be used with Amazon Elastic Container Registry](https://github.com/jenkins-x/jx/issues/4501)

どうやら、 `config.json` で `credsStore` を使うのはダメで、 `credHelpers` を使わなきゃいけないみたいです。



# `config.json` を修正した

`%USERPROFILE%\.docker\config.json` を確認したところ、以下のようになっていました。

```json
{
  // 省略
  "credsStore": "ecr-login",
  // 省略
}
```

この `credsStore` の行を削除して、以下のように書き換えます。

```json
{
  // 省略
  "credHelpers": {
    "{AWSアカウントID}.dkr.ecr.{リージョン名}.amazonaws.com": "ecr-login"
  },
  // 省略
}
```

例えば、

- `AWSアカウントID` が `00000000000000`
- `リージョン名` が `ap-northeast-1`

の場合、`00000000000000.dkr.ecr.ap-northeast-1.amazonaws.com` となります。

ちなみに、 `*` 等のワイルドカードは使えませんので、ご注意ください。
例えば、 `*.dkr.ecr.*.amazonaws.com` みたいなのはNGです。（私の環境で試したところ、ダメでした。）

これで再度、 `docker pull node:12.3.1-alpine` を実行したところ、無事にプルすることができました。

念のため、 ECRからもプルを試してみたところ、そちらも大丈夫でした。


# さいごに

以下のサイトを参考にさせていただきました。

- [docker-credential-ecr-login can only be used with Amazon Elastic Container Registry](https://github.com/jenkins-x/jx/issues/4501)
[iOS] 無音カメラ on Pythonista 

#無音カメラ作った

## Environment 
- iPhone 11 Pro
- iOS 13.1.3
- Pythonista 3.3

## 機能
- iPhone 11 Proのタピオカメラに対応した
- タップでピント調整できるようにした
- ピンチイン/アウトでズームできるようにした
- 横向きでとったらちゃんと回転するようにした
- 4Kでちょっと画質がいい
- 他のスクリプトから呼び出すことも考えた

## バグ・まだなこと
- 解像度がちょっとおかしい
- 連写したら落ちる
- フラッシュ
- iPad
- Objc_utilとiOSのカメラの仕組み
- ☠️🍝スパゲティコード🍝☠️
- 11 Pro以外で動くかはちょっとわかんない

## スクリーンショット
<img width="375" alt="175F8E9B-84AB-484D-81D5-0556FFABC724.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339688/9451472a-0701-07ea-6ac9-9f1520b21ecb.jpeg">

## ソースコード
こちらからどうぞ💁‍♂️
↓
[🐙Github🐙](https://github.com/nakano57/Pythonista_Silent_camera)

cloneしてフォルダ構造はなるべくそのままで使ってください

## 感想
iOSのアプリ開発って難しいデス

## 感謝
- [無音カメラ on Swift4](https://qiita.com/nasutaro211/items/9267ba651db90ecf977e)
- [[Swift] [iOS] ズーム、ピント調節可能な無音カメラのサンプル ](https://qiita.com/touyu/items/6fd26a35212e75f98c6b)

## 宣伝

[pythonで画像処理 〜黒板の写真を撮って文字以外を透過させた画像を作る〜](https://qiita.com/Iroha_168/items/19adfa99fc06acc24cb0)
自分用メモ linuxネットワーキングプログラミング

## 前書き
基本ネットや書籍から拾ってきた内容を雑にメモしているだけ
文面以上に内容をもっと深堀りたかったら、リンク貼るのでそこを見てください
ちなみに[ITインフラ技術の実験室](https://www.infra.jp)ってサイトが良すぎたので何かあったら基本的にそこに全部載ってる

## 用語
### ファイル
ファイルはインターフェイスです
ファイルインターフェイスが実装されたオブジェクトを操作すると、ローカルの補助記憶装置に対して読み書きできたり、通信相手と送受信できたりします。

* 補助記憶装置に対して読み書きするファイル[クラス|オブジェクト]は単純にファイルと呼ぶ
* プロセス間通信やtcp/udp等を利用する際に利用するファイル[クラス|オブジェクト]はソケットファイルと呼ぶ

### 記述子 (descriptor
識別子は識別する為のもの。
記述子は記述する為のもの。記述するためには識別したり、読み込んだりする必要もある。
なので、記述子は識別子よりも強力。
記述子は基本的に特定の関数やクラス等で引数として与え、その関数やクラスを利用して読み書きができるようになる。
Kernelレベルで実装されているらしい。

記述子には
* socket descriptor
* socket file descriptor
* file descriptor
* field descriptor 
等、その他沢山ある。 (発案の数だけある

参考資料:
https://unix.stackexchange.com/questions/233237/etymology-of-descriptor-in-file-descriptor/295746#295746
https://rust-jp.slack.com/archives/C8FLSR5F1/p1571635210176900

## Cでソケットを扱う際の各種関数等の仕様
この内容の軽いメモ
https://www.infra.jp/programming/network_programming_3.html#multiplexing

### accept
待機待ち行列があれば、そこから1つ取り出す。
なければ、ブロッキングする。

### select
引用: https://www.infra.jp/programming/network_programming_3.html#multiplexing
> select()はaccept()やrecv()同様、処理をブロックしますが、複数のディスクリプタを同時に見張ることができるため、クライアントからの新規接続や接続中クライアントからの受信など、記述子の変化があった場合にどのような変化かに関わらず処理を先に進められます。
また、各ディスクリプタに変化があるまでブロックするため、CPUパワーを無駄に消費することもありません。

### poll
selectより細かく指定できる

### EPOLL
数千コネクションでも耐えられる様にチューニングされている。
pollの上位互換だが、linux固有の実装らしい


## Cでネットワーキングプログラミングをする
...今時間が無いため後で書く
JavaScriptで録音サイトを作ってみたVer.2

Recorder.jsで録音サイトを作りました。
名前は「Recood」です。
![Screenshot from 2019-10-21 17-01-58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285513/39460cd8-3c17-b853-4c67-be644035d071.png)
基本的には、真ん中のマイクのボタンを押すと録音を開始することができると思います。
## 対応ブラウザ
Google Chrome(iOS、iPad OS版はわからないのでできればコメントでお願いします。)
URL https://anyfre.github.io/recood/
iMac 27inch (Late 2009) のSSD交換が思った以上に大変だった

# 目的

1年ほど前に、一度HDDを2.5inch SSDに交換したiMacですが、息子がプログラミング学習用に使うようになり、250MbyteのSSDでは手狭になってきたので、1TBのSSDに再交換しました。その際、思いのほかハマりました。前回交換した際は全く起こらなかったので、なぜ？と思うところも多々あるのですが、回避できたので忘れないうちにメモしておきます。

# はまった状況

いろいろなサイトで示されているように、iMac 27inch (Late 2009)は簡単にディスクを交換できます（もちろん自己責任で）。

- The Brave Penguin Lab.
    - [iMac(Late 2009)のハードディスクをSSDに交換しました](http://www.mobile4children.com/?p=657)
- YYCブログ
    - [iMac 2009 Late 分解 修理 ハードディスクをSSDに交換](http://www.yycrew.net/blog/?p=16578)

私自身、すでに1度交換済みなこともあり、この交換作業はサクサクと進みました。ちなみに、交換して新しくしたSSDはこれ。

![] (https://shop.westerndigital.com/content/dam/store/en-us/assets/products/internal-storage/wd-blue-3d-nand-sata-ssd/gallery/WD-Blue-SSD-3D-NAND-front.png.thumb.319.319.png)

そして、組み立てなおし、TimeMachine バックアップが入っている外付けHDDを接続して電源オーン。

![] (https://support.apple.com/library/content/dam/edam/applecare/images/en_US/osx/mac-prohibit-symbol-screen-icon.png)

あれ？ もしかして、外付けHDDを最初から接続しちゃダメだったのかな？　それならばと外して、もう一回電源オーン。

![] (https://support.apple.com/library/content/dam/edam/applecare/images/en_US/osx/mac-folder-questionmark-screen-icon.png)

は？　なんで？　もうここまで来ると焦る焦る。何が悪いのかさっぱりわからず、そこから何度も開いて接続確認を繰り返すも、表示される画面は一向に変わらず。もうほとんど諦めていました。

# 解決方法

結局何が悪かったのか正確なことは判っていないのですが、結果から類推するに、復元用のmacOSユーティリティがどこにもないと言いたかったような気がします。だったら意味の通じないアイコン出してる場合じゃなく、普通にそう書いてくれよと思うのですが、どこにもそんな気配さえ表示されません。

実際にどのように回避したかというと、

**取り出した以前まで使っていたSSD（HDD）を、USB HDDケース（あるいはHDDスタンド）等に挿してiMacにUSB接続し、iMac を command+R で起動する**

で問題なく先に進めることができました。これが正しい理由は良く判りませんが、それまで使用していたSSDには macOSユーティリティが入っているということなんでしょうか？　待っていれば無事に以下の画面になります（その前に言語選択画面があります）。

![] (https://support.apple.com/library/content/dam/edam/applecare/images/ja_JP/macos/highsierra/macos-high-sierra-recovery-mode-reinstall.jpg)

同じことではまっている方って、いるかな？　自分が将来同じことをしてハマりそうな気もします。
Django の ModelChoiceField で option タグに属性を追加したい

## 環境

django 2.2
python 3.6.8

## やりたい事

forms.Select の option タグに value 以外の属性も追加したい。

これを

```html
<select name="persons" required="" id="id_persons">
  <option value="" selected="">---------</option>
  <option value="1">山田 太郎</option>
  <option value="2">山田 花子</option>
</select>
```

↓みたいにしたい

```html
<select name="persons" required="" id="id_persons">
  <option value="" selected="">---------</option>
  <option value="1" age="10">山田 太郎</option>
  <option value="2" age="20">山田 花子</option>
</select>
```

## やってみた

modelsの定義はこんな感じ

```models.py
class Person(models.Model):
    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=20)
    age = models.IntegerField()

    def __str__(self):
        return f"{self.last_name} {self.first_name}" 
```

forms.Select を継承した SelectPersonWidget を作成

```custom_widget.py
class SelectPersonWidget(forms.Select):
```

\_\_init\_\_ で queryset を渡しておく

```custom_widget.py
class SelectPersonWidget(forms.Select):
    def __init__(self, attrs=None, choices=(), queryset=None):
        self.queryset = queryset
        super().__init__(attrs, choices)
```

create_option で queryset から必要な情報を取得して attrs に追加する

```custom_widget.py
class SelectPersonWidget(forms.Select):
    def __init__(self, queryset, attrs=None, choices=()):
        self.queryset = queryset
        super().__init__(attrs, choices)

    def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
        option = super().create_option(name, value, label, selected, index, subindex, attrs)
        if value:
            person = self.queryset.get(pk=value)
            option['attrs'].update({'age': person.age}) # ここで attrs に追加
        return option
```

作成した SelectPersonWidget を ModelChoiceField の widget に指定する

```forms.py
from django. import forms

from .models import Person
from .custom_widget import SelectPersonWidget


class SampleForm(forms.Form):
    all_person = Person.objects.all()
    
    persons = forms.ModelChoiceField(
        queryset=all_person,
        widget=SelectPersonWidget(queryset=all_person) # ここで指定する
    )
```

描画してみる。
option タグに age属性 が追加された

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259465/60487f9f-3e37-5003-0a5c-9a9d37713fbd.png)

他に方法があれば知りたい

### 参考

https://docs.djangoproject.com/ja/2.2/ref/forms/widgets/
MongoDB Atlas → AWSへのVPC Peering



# 概用
1. Atlas側のVPCからマイVPCにVPC Peeringのリクエスト
2. マイVPC側でAccept
3. マイVPC側のセキュリティグループにAtlasのVPCを追加

※基本的に[Atlasの公式ドキュメント](https://docs.atlas.mongodb.com/security-vpc-peering/)通りに作業します。

# 1. Atlas側のVPCからマイVPCにVPC Peeringをリクエスト

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96286/13d53d0e-3f0d-f077-6550-f0bda4dd10c8.png)

2020-05-12 追記: `Organization Owner` の権限が必要です。

# 2. マイVPC側でAccept

マネジメントコンソールからVPC Peeringのメニューを開き、VPC PeeringのリクエストをAcceptします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96286/9149a6b5-277a-df58-5743-92a5174f3fb8.png)


# 3. マイVPC側のセキュリティグループにAtlasのVPCを追加

ここがポイント。手動でRoute Tableの設定を修正してもいいですが、CFnで冪等に管理します。

スクリプト

```
#!/bin/sh -e

###
# VPC PeeringをAcceptした側のVPCに、VPC Peeringが存在する場合のみRouteを追加するスクリプト。
###

REQUESTER_VPC_ID=$1
REQUESTER_FRIENDLY_NAME=$2
DESCRIBE_VPC_PEER="aws ec2 describe-vpc-peering-connections --filters Name=status-code,Values=active Name=requester-vpc-info.vpc-id,Values=${REQUESTER_VPC_ID}"
echo ${DESCRIBE_VPC_PEER}

export VpcPeeringConnectionId=$(${DESCRIBE_VPC_PEER} \
    --query VpcPeeringConnections[0].VpcPeeringConnectionId \
    --output text)
export RequesterVpcCidr=$(${DESCRIBE_VPC_PEER} \
    --query VpcPeeringConnections[0].RequesterVpcInfo.CidrBlock \
    --output text)

if [ ${VpcPeeringConnectionId} != None ]; then
    aws ec2 modify-vpc-peering-connection-options \
        --vpc-peering-connection-id ${VpcPeeringConnectionId} \
        --accepter-peering-connection-options '{"AllowDnsResolutionFromRemoteVpc":true}' \
        --region ${AWS_DEFAULT_REGION}

    aws cloudformation deploy \
        --template-file cfn/vpc-peer-acceptor-config.yml \
        --stack-name vpc-peer-with-${REQUESTER_FRIENDLY_NAME} \
        --parameter-overrides \
            VpcPeeringConnectionId=${VpcPeeringConnectionId} \
            RequesterVpcCidr=${RequesterVpcCidr} \
        --tags date="$(date '+%Y%m%d%H%M%S')"
fi
```


CloudFormationテンプレート

```
AWSTemplateFormatVersion: '2010-09-09'
Description: VPC Peering Accepter Config

Parameters:
  VpcPeeringConnectionId:
    Type: String
  RequesterVpcCidr:
    Type: String

Resources:
  XXXRouteToVPCPeer:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: { "Fn::ImportValue": !Sub "XXXRouteTable-Id" }
      DestinationCidrBlock: !Ref  RequesterVpcCidr
      VpcPeeringConnectionId: !Ref VpcPeeringConnectionId
```


# 4. 疎通チェック

今回はAmazon Linuxにmongoコマンドをインストールします。

ダウンロードリンクはここから。
https://www.mongodb.com/download-center/enterprise?jmp=docs

```
# 絶対もっと効率いいやり方あります。
MONGO_SHELL=https://downloads.mongodb.org/linux/mongodb-shell-linux-x86_64-amazon-4.2.1.tgz
curl -O $MONGO_SHELL
tar -zxvf mongodb-shell-linux-x86_64-amazon-4.2.1.tgz
sudo cp mongodb-linux-x86_64-amazon-4.2.1/bin/mongo /usr/bin/mongo
```

```
# 接続確認
mongo "mongodb+srv://<your_mongodb_host>.mongodb.net/test" --username <username>
...
MongoDB Enterprise <your_mongodb_host>-0:PRIMARY> 
```
modelにカラムを追加したのにmigrationファイルに追加されない現象

# 事象
models.pyに定義したモデルにカラムを追加した後，makemigrationを実行するもカラムが追加されない

# 原因
追加したカラムの末尾にカンマが存在しており正しく認識されていなかった模様

```python:models.py
from django.db import models


class Category(models.Model):
    id = models.AutoField(primary_key=True)
    description = models.CharField(
        max_length=20
    )
    test_column1 = models.IntegerField()
    test_column2 = models.IntegerField(), # カンマがあるため反映されない

    class Meta:
        db_table = 'category'
```

`python manage.py makemigrations`を実行すると

```python:0001_initial.py
# Generated by Django 2.2.5 on 2019-10-21 07:51

from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Category',
            fields=[
                ('id', models.AutoField(primary_key=True, serialize=False)),
                ('description', models.CharField(max_length=20)),
                ('test_column1', models.IntegerField()),
            ],
            options={
                'db_table': 'category',
            },
        ),
    ]
```

たしかに`test_column2`が反映されていないことが分かる．
makemigrations, migrateともに実行してもエラーや警告が発生せず原因を特定するのに時間が掛かってしまった．
AWS EC2でhello world

AWSアカウントを作成してからEC2にApacheを入れてhello worldを表示するまでのメモ
使用OSはWindows
EC2インスタンスの作成方法とElasticIPの関連付けなどは省略

## キーペア作成
画面左の選択欄から キーペア ＞ キーペアの作成 を選択、適当なキーペア名を入力後作成ボタンをクリックし、「キーペア名.pem」をダウンロード
インスタンス一覧画面のキー名のところに作成したキーペアが登録されていることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384069/d299312b-b73d-1f5e-8868-971cf762ef26.png)

## TeraTermで接続
接続先のインスタンスのIPv4パブリックIPを入力してOKボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384069/9fba7392-9f5c-ff84-6637-1b7383fac6c4.png)
ユーザ名にec2-userを入力、先ほどダウンロードした認証キーを設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384069/6cbfaf7d-b2f6-2bdf-5c69-8f0ba6ed128d.png)
接続完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384069/713b9889-5c66-e8c3-f62c-c4e3895e9a14.png)

## Apacheをインストールして起動
```
// パッケージ更新
$ sudo yum update -y

// Apacheのインストール
$ sudo yum install -y httpd

// Apacheの起動
$ sudo service httpd start
```
```
// htmlファイル作成
$ sudo vim /var/www/html/index.html

$ cat /var/www/html/index.html
hello world!
```
## ブラウザから確認
その前にポートを開いておく
セキュリティグループ ＞ アクション ＞ インバウンドのルールの編集
タイプをHTTPにして追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384069/ac9796b9-3016-65f3-0ef0-617453f32c6a.png)

インスタンス ＞ パブリックDNS(IPv4)にあるアドレスにブラウザからアクセスすれば、hello worldが表示される
Kubernetesの脆弱性CVE-2019-11253についてわかっていることをまとめる

## TL;DR

- Kubernetesに脆弱性が見つかった([CVE-2019-11253](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11253))
- Severity7.5なので高め(昔からクラスター運用してる場合はなるはやで上げよう)
- Kubernetes API Server(kubectlがアクセスするエンドポイント)がPublic IPの場合は特に注意しよう

## 脆弱性の内容

特定の条件を満たすマニフェスト(YAML or JSON payload)を食わせるとKubernetesのマスターコンポーネントであるKubernetes API Serverが応答不能になる。

1.14.0以降のバージョンで新規に作られたクラスターの場合、デフォルトのRBACの設定が変更されており、認証済みユーザーのみがこの脆弱性を突くことが出来るようになっている。つまり、脆弱性の範囲が限定的になる(クラスターに対してYAMLを送るためにユーザー情報を持っているクライアントのみが実行可能なため)。

1.13以下のバージョンから運用しているクラスターの場合、匿名ユーザーでも脆弱性を突くことが出来る(ref. [再現コード](https://gist.github.com/superbrothers/a0575f286dd7fce1fd96acc0ea69868a))。

つまり、API Serverが誰でもアクセス可能なエンドポイントにあって、なおかつKubernetesのバージョンが**1.13以前から運用している場合、速やかなバージョンアップが必要。**

重要なのは1.13などから1.14に上げた場合でも、「RBACの設定は前方互換性のために変わらない」ということ。つまり、ただバージョンを1.14にあげるだけではだめで、脆弱性がパッチされたものに上げる必要がある。

## 各社パブリッククラウドの対応状況(2019年10月20日現在)

個人的に使っているものだけです。追加の情報があればコメントにどうぞ。

| サービス | 影響の有無 | 備考 |
|:------:|:------------:|:---:|
| GKE    | あり | [既にパッチが公開されている](https://cloud.google.com/kubernetes-engine/docs/security-bulletins#october_16_2019)ので、アップデートすればよい |
| EKS    | 不明 | まだ公式の声明が出ていない |
| AKS    | あるが低い | [Issue](https://github.com/Azure/AKS/issues/1262)参照。kubeletの起動オプションで匿名ユーザーを許可しない設定になっているようだ。パッチの有無については現時点では不明。 |
DebianでFlask環境（virtualenv, gunicorn, nginx, postgresql）を作る

## タイムゾーンの設定
```sh
$ timedatectl set-timezone Asia/Tokyo
$ timedatectl #内容の確認
```

## Flask、Nginxのインストール
```sh
$ apt-get install python3-pip python3-dev nginx
```

### virtualenvのインストールと設定

```sh
$ pip3 install virtualenv
$ mkdir /var/www-app/
$ cd /var/www-app/
$ virtualenv venv
$ source venv/bin/activate
$ cd venv
$ pip install gunicorn
$ pip install flask
```

### サーバーの起動
```sh
$ gunicorn --workers 2 --worker-class gevent app:app &
```

## PostgreSQLのインストール
```sh
$ apt-get install openssl libssl-dev libssl-doc
$ apt-get install postgresql postgresql-contrib
```

### DBとユーザーの作成
```sh
$ su postgres
$ psql
$ create database myapp_db;
$ create user myapp_db_user with encrypted password 'myapp_db_pass';
$ grant all privileges on database myapp_db to myapp_db_user;
```

# 参考
- タイムゾーン設定
https://www.server-world.info/query?os=Debian_9&p=timezone

- flaskのインストール
https://www.vultr.com/docs/how-to-setup-gunicorn-to-serve-python-web-applications

- postgresのインストール
https://www.vultr.com/docs/install-postgresql-on-ubuntu-14

- postgresのユーザー作成
https://medium.com/coding-blocks/creating-user-database-and-adding-access-on-postgresql-8bfcd2f4a91e
[Python/numpy] 隣接する要素との平均を計算する

# 本論

## 問題

numpy で隣の要素との平均を計算したいことがたまにあります. つまり, 長さ `n` の ndarray, 例えば

```python
x = np.arange(n)
```

が与えられたとき, 次の長さ `n-1` の ndarray が欲しいのです.

```python
ave = ndarray([
    (x[0]+x[1])/2.,
    (x[1]+x[2])/2.,
    ...,
    (x[n-2]+x[n-1])/2.,
])
```

## 解法

これは numpy 1.12 で導入された [numpy.roll](https://docs.scipy.org/doc/numpy/reference/generated/numpy.roll.html) 関数を使うのが最適解だと思います. 

```python
x1 = np.roll(x, -1)  # = np.ndarray([ x[1], x[2], ..., x[n-1], x[0] ])
ave = (x + x1)/2.    # これは長さ n の ndarray で最後の要素 (x[0]+x[n-1])/2. は要らない
ave = ave[:-1]       # これが欲しいもの
```

np.roll の第 2 引数の符号に注意してください.


# 参考文献

- [NumPy配列ndarrayをシフト（スクロール）させるnp.roll - note.nkmk.me](https://note.nkmk.me/python-numpy-roll/)
- [numpy.roll - NumPy Manual](https://docs.scipy.org/doc/numpy/reference/generated/numpy.roll.html)


# 追記

コメントで @shiracamus さんに

```python
ave = (x[1:]+x[:-1])/2.
```

で十分と指摘していただきました.
HTML CSS 【Font Awesome】を使ってみる

はじめは使い方が分からなくて苦労したのに一日経ってやってみたらあっさり出来たので、忘れない内にまとめます。
[参考サイト]https://webdesign-trends.net/entry/8351
Font AwesomeをHTMLとCSSで読み込む方法でやってみました。

---
####①＜head＞タグ内に入れる

```index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Font Awesomeを使ってみる</title>
    <link rel="stylesheet" href="css/styles.css">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
  </head>
</html>
```
＜link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css"＞を＜head＞内に入れる

####②使うアイコンを選ぶ
[アイコンを探す]https://fontawesome.com/icons?d=gallery
リンク先から使いたいアイコンを探す（当然英語で！）

[日本語で入力すると検索してくれるサイト]https://search-fa.com/

####③アイコンを表示させる
- 使いたいアイコンを選んだら＜i class=＞というのがあるのでクリックしてコピーして、HTML内で使うところにペースト

```index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Font Awesomeを使ってみる</title>
    <link rel="stylesheet" href="css/styles.css">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
  </head>

  <div class="icon-test">
    <i class="fab fa-facebook-square" style="color:#305097;"></i>
  </div>
</html>
```

- 次にCSSで疑似要素に下記のように追加

```styles.css
.fab fa-facebook-square::before {
	content:'\f082';
	font-family:'Font Awesome 5 Free';
	font-weight:900;
}
```
contentにアイコンのUnicode(ユニコード)をコピペ　頭に**￥(スラッシュ)**を忘れずに！

ブラウザ上では
<img width="19" alt="20191021_Qiita01.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509471/152fb20b-a401-951d-c7e1-faab158ce6c8.jpeg">
このように表示されました。
では色とサイズを変えてみましょう。

####④色を変える

```index.html
  <div class="icon-test">
    <i class="fab fa-facebook-square" style="color:#305097;></i>
  </div>
```
colorプロパティを指定することで色を変更できます。
<img width="19" alt="20191021_Qiita02.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509471/ae29418a-60d0-78ba-3853-c99af469ada4.jpeg">
色が変わりました。

####⑤サイズを変える
```index.html
  <div class="icon-test">
    <i class="fab fa-facebook-square fa-xs" style="color:#305097;"></i>
    <i class="fab fa-facebook-square fa-sm" style="color:#305097;"></i>
    <i class="fab fa-facebook-square fa-lg" style="color:#305097;"></i>
    <i class="fab fa-facebook-square fa-5x" style="color:#305097;"></i>
    <i class="fab fa-facebook-square fa-10x" style="color:#305097;"></i>
  </div>
```

class名にサイズを加えることで変更出来ます。
<img width="230" alt="20191021_Qiita03.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509471/04ff1bba-787d-ee30-cd42-5866f356b3b7.jpeg">
Python でデフォルトの引数値のある関数に型ヒントをつける


### ◯ 問題

関数にデフォルトの引数値をつけることができます。これにどうやれば型をつけられるのか分からずハマっていました。

```python
def combiner(*vals: bytes, maxlen: Optional[int] = None) -> List[bytes]:
    ...
```

* [4.7.1. デフォルトの引数値 - Python チュートリアル](https://docs.python.org/ja/3/tutorial/controlflow.html#default-argument-values)

### ◯ 対応

`Protocol` を継承させたクラスに `__call__` をつけます。

```python
from typing import Protocol

class Combiner(Protocol):
    def __call__(self, *vals: bytes, maxlen: Optional[int] = None) -> List[bytes]:
        ...
```

* [Callback protocols - Protocols and structural subtyping](https://mypy.readthedocs.io/en/latest/protocols.html#callback-protocols)
* [Proposal: Generalize `Callable` to be able to specify argument names and kinds #264](https://github.com/python/typing/issues/264)


<!--
全く関係ないですが、すこし読みました。

* [Type annotations for *args and **kwargs - Stackoverflow](https://stackoverflow.com/questions/37031928/type-annotations-for-args-and-kwargs)
 -->

### ◯ 補足

Protocol は、本来は静的にダックタイピングをしたいときに使うものです。

* [defined a protocol - PEP 544](https://www.python.org/dev/peps/pep-0544/#defining-a-protocol)
Aws cli ebcliでエラー、動かない時にはまずpipパッケージのバージョンを確認しよう

なんだかんだ１年以上運用したので
定期的にどんな作業が発生するかというのが溜まってきたのでまとめてみます。

環境周りのコマンドを実行する作業になるので
不安がある場合は仮想環境のコピーを作成するのをお勧めします。

私の個人的な経験ではほとんどが依存関係のバージョンが食い違っているというものが大半でしたので
バージョンアップのメンテナンス内容をメインに書きます。

これから導入を考えている方に
こんな作業が発生するんだとか
こんなスキルセットが必要になるんだとか
参考になれば嬉しいです。

※ここに書いてあることが全てではないのでその点はご注意を

# 定期的に必要となるお手入れ
コマンドラインツールもそれぞれバージョンアップをしてくれています。
ゆえに突然エラーが出てくるということもしばしば

そんな時はまずは現状確認しましょう。
※pipを使っていることが前提です

```piplisto.shell

$ pip list -o

```

続きましてpip自身のアップグレード

```upgrade.pip

$ pip install --upgrade pip

```

## awscliのアップグレード

```awscliupgrade.shell

$ pip install awscli --upgrade --user

```

参考URL
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/installing.html


## eb cliのアップグレード

```ebcliupgrade.shell

$ pip install awsebcli --upgrade --user

```

## botocoreのアップグレード

aws cliもアップグレードが同時に必要のような状態の場合

```piplist.shell

$ pip list -o
Package          Version   Latest     Type 

awscli           1.16.97   1.16.99    wheel
botocore         1.12.87   1.12.89    wheel

```

以下のコマンドでbotocoreとaws cliの両方がアップデートされた


```awscliup.shell


$ pip install awscli --upgrade --user


```


## その他pip管理のプラグインアップデート

pipでプラグインを個別にアップデートしないといけない場合もある。

```pipupdate.sh

$ sudo pip install プラグイン名 -U

#以下tabulateというpipパッケージをアップデートする場合
$ sudo pip install tabulate -U

```

# 再インストール
運用している中で何度かawscli,ebコマンド自体を再インストールしたら
治ったということがありましたのでそれも書いてみます。

## aws cliの再インストール
pythonモジュールのpipが入っていれば以下でアンインストールできます。

```uninstallaws.sh

$ pip uninstall awscli

```


## ebコマンドの再インストール

ebコマンドのアンインストール

```uninstallaws.sh

$ pip uninstall awscli

```

再度インストール


```installeb.sh

$ pip install awsebcli --upgrade --user

```

# エラーが表示されたら
## ebコマンドのデバッグ


```debug.sh

$ Eb deploy --debug

```

# pipパッケージのダウングレード

稀に以下のようなエラーが表示されることがあります。


```error.sh

ERROR: awscli 1.16.253 has requirement botocore==1.12.243, but you'll have botocore 1.12.253 which is incompatible.
ERROR: awscli 1.16.253 has requirement rsa<=3.5.0,>=3.1.2, but you'll have rsa 4.0 which is incompatible.

```

これはawscliが使っているパッケージのバージョンがあっていませんよ〜というもので
バージョンをあげる場合は前述のコマンドでいけますが
バージョンを下げろという場合もあります。
ダウングレードということになりますが
コマンド的にはバージョンを指定してインストールという形でダウングレードできます。


```downgrade.sh

$ pip install botocore==1.12.243

```

## パッケージのバージョンリストを確認

パッケージのバージョンって具体的にどんなものがあるかを確認したい時は以下のコマンドで表示されます。

```verification-version.sh

$ pip install パッケージ名==

#botocoreなら以下
$ pip install botocore==

```

[＞＞参考にさせていただきました](https://tzmi.hatenablog.com/entry/2020/01/13/232021#pip-install-version)

# linuxの時間がずれた時もエラーが出ます。

当方の環境としてCentOS７の仮想環境に置いている状態で
定期的にLinuxの時間がずれるという現象があり
ebコマンドが動かなくなる時があります。
私の環境では以下の方法で解決しています。
[＞＞CentOS7の時間がずれる](https://qiita.com/SwuBHj8aKGqBKHet/items/2f6a2003851420b460ba)

# 備考
pip listで表示されたパッケージを一括アップデートするコマンドはこちらです。
※ただし個人的経験ではaws-cli,eb-cli側で結構細かく指定があることが多いので結局個別にバージョン指定しながらやることが多くなるため一番最後に書いています。

```

$ pip list -o | tail -n +3 | awk '{ print $1 }' | xargs pip install -U

```

[＞＞参考にさせていただきました](https://qiita.com/kazushisan/items/183bdeaddf9629a2f21d)
配列をぶっこんだらそのままシートに挿入してくれる魔法のようなGAS関数

4年前にQiitaに投稿しようとして下書き保存になったままの記事を発見したので投下します。

# 背景
MySQLの結果(7万行くらい)をSpreadSheetに読み込んで解析しているんですが、結果をSpreadSheetに吐き出したかった。4年前のステータスなのでもしかしたら既に対応されているかも。

# 作用
配列の構造に沿ってセルに出力を行ってくれます。
作った当時は魔法のような関数でした。何かの足しになるかもしれないのでご自由にお使いください。

# 機能

```js
/*
配列をぶっこんだらそのままシートに挿入してくれる魔法のようなgas関数
@var  dataArray    Array   data you willing to import from.
@var  ss           Object  file you willing to import to.
*/

function bukkomiArrayMagic(ss, dataArray)
{
  //仕様上、一列ずつぶっこむしかないのが難点
  for (var i = 0;i < dataArray.length; i ++) {
    var loc = "A" + (i + 1) + ":" + getColAlp(dataArray[i].length) + (i + 1);
    ss.getRange(loc).setValues([dataArray[i]]);
  }
}

/*
列番号 -> Alphabet に変換してくれるエレガントなメソッド
*/
function getColAlp(num)
{
  var result;
  if (num <= 26) {
    result = c(num - 1);
  } else {
    var ten = c(parseInt(num / 26) - 1);
    var one = c((num % 26) - 1);
    result = ten + one;
  }
  return result;
}

function c(col)
{
  var alpha = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
  return alpha[col];
}

/*
testがないコードはレガシーなコードDA・KA・RA・NE☆
*/

function test_general(){
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheets()[0];
  var dataArray = [[0,1,2,4],[1,2,3],[2,3,4,4,6,7]];
  bukkomiArrayMagic(sheet, dataArray);
}
```
Gitの基本用語 + よくある事故

Gitに初めて触れる方や、事故ってあたふたする方に向けて書きます。
(自分の認識が間違ってないか整理する為にも)

- 自分なりの解釈でざっくりと書きます。
- しっかりと理解したい方や、より詳しく知りたい方には向かないかも知れません。
- Sourcetreeを使用する前提で解説していきます。
- 私も初心者につき、間違っている箇所があるかも知れません。


## 基本用語･操作

### リポジトリ
Gitで管理する対象になっているディレクトリのこと。
このディレクトリ下のファイルに変更があると、差分として表示される。  
以降でリモートとかローカルとか言っているのはそれぞれ`リモートリポジトリ`と`ローカルリポジトリ`のこと。


### クローン
全てはここから始まる。(多分)  
概ね、リモートリポジトリをローカルにコピーすること。
この操作でローカルにコピーしてきたものを`ローカルリポジトリ`と呼ぶ。  
ダウンロードだと思って良い(と思う)。

### ブランチ
枝。ゲームで言うストーリー分岐(?)みたいなもの。
ゲームと違うのはエンディングが大体ひとつしかない(全部最後はmasterにマージされる)事。
実装する機能毎や作業者ごと等、分ける際の考え方は色々ある。

よく使うブランチ名は以下みたいな感じ。

- master  
その名の通り。リリース用のものであることが多く、だいたいプロテクトが掛けられている。そのくらい大切なものなので、触ることがあれば細心の注意を払うこと。
- develop  
開発用のブランチ。  developから、各機能や作業事にブランチを切って作業し、終わったらdevelopへマージする。(という運用が多いと思う)

- feature/○○○○  
例えば`feature/add_input_view`
とか。featureというフォルダに、add_input_viewというブランチがあるイメージ。  
Sourcetreeでは実際にフォルダみたいに表示されるので、単純に見やすい。他にも`fix/○○○○`(修正)とかも使うかも。この辺はプロジェクトによって大きく変わる。

※詳しくは[[日本語訳]A successful Git branching model](https://qiita.com/homhom44/items/9f13c646fa2619ae63d0)とかを見て欲しい。

### チェックアウト
ブランチの切り替え。ソースツリーなら何も意識しなくてもやってる。

### コミット
ブランチに対して、変更を確定させること。
ゲームで言うセーブ。作業が一段落着いたら行う。
後で戻る事や、変更内容を確認するために
なるべく細かくコミットしておく方が(個人的には)好き。

### スタッシュ
変更したものを一時的に退避させて保管できる機能。
めちゃくちゃ使う。
コミットするほど作業してないけどブランチを切り替えたい時とかに。
`スタッシュに積む`とか言う。

### プッシュ
ローカルの状態をリモートへ反映すること。プルの逆。

### プル
リモートの状態をローカルへ反映すること。プッシュの逆。

### フェッチ
リモートの状態を確認すること。
フェッチを行うとプルする必要のあるリポジトリが分かるので、事故([こういうの](#リモートのコミットをプルせずにコミットしてしまった))を防ぐことが出来る。

### マージ
ブランチ同士を結合すること。そのまま。

### コンフリクト
マージされるふたつのブランチの差分がぶつかり合う事。
同じ箇所を複数のブランチで修正すると起こる。
このままではマージできないので、解決する必要がある。
解消方法は大きくわけて3通りある。
- 相手(マージする先)の変更を使う
- 自分の変更を使う
- 手動でいい感じに修正する

コンフリクトしないように、developを作業ブランチにこまめに取り込もう。

### リバート
特定のコミットの内容を打ち消す事。
正確には、特定のコミットの逆のコミットをすること。
ミスった時や、特定のコミットが不要になった時に使う。

### チェリーピック
特定のコミットを今いるブランチに取り込むこと。
時々つかう。

## よくある事故(経験したもの)
※他にいい方法があればお教えいただきたく存じます。
### コミットした内容を取り消したい
プッシュしていない場合
→めんどくさいのでローカルブランチを一度消して、
　もう一度リモートからチェックアウトする。

プッシュ済みの場合
→リバートする。

### リモートのコミットをプルせずにコミットしてしまった
これはめちゃくちゃやってしまってました。
こうならないように、まずはフェッチしてからコミットする癖をつけましょう。
もうやってしまった場合は↓の手順で解決してます。

![スクリーンショット 2019-10-21 19.45.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208118/a36476a0-0cde-907e-11a5-d8b854d8d046.png)
こんな表示になってると思うので、この状態でブランチを切る。(例えばHogeとか)
その後、ローカルブランチを削除してもう一度リモートからチェックアウトし、
hogeブランチのコミットをチェリーピックで取り込んで完了。

---
最後までご覧いただきありがとうございました！
Git触りたての方の参考になれば幸いです！

気になるところや間違っているところなどございましたら、お教えいただきたく存じます。
MacターミナルからAPKファイルをAndroidの実機端末にインストール

#前提条件
Android Studioが入っていること

#手順
- bash_profileにSDKのパスを通す
- インストールを行う。

##bash_profileにSDKのパスを通す
ターミナルを開き以下のコマンドを入力します。

```
vim ~/.bash_profile
```

先ほど確認したAndroid SDKのパスを記入します

```
export PATH=$PATH:/Users/ユーザ名/Library/Android/sdk/platform-tools
```
Android Studioを使用しているので同環境の方はSDKのパスのユーザ名のみの変更で問題ないかと思います。
※SDKのパスはAndroid Studioで「File」＞「Other Settings」＞「Default Project Structure…」ここに記載されています。
![alt](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F84307%2Fab51a002-5d94-99e9-0ab1-18660df9b86b.png?ixlib=rb-1.2.2&auto=compress%2Cformat&gif-q=60&s=804adf1dfa3417ae29386f9a478c112d)

#bash_profileを再度読み込む
方法は二つあります。
１．ターミナルを再起動

２．コマンドで改めて読み込む

```
source ~/.bash_profile
```
adbコマンドを利用することができます。

#インストール

```
adb install xxx.apk
```
xxx.apkはapkファイルまでのパスを入れてください。
Successが表示されたらインストール完了です。
Android Studioからrunするのとは違って自動ではアプリは開かれないです。

#補足
- adbとは『Android Debug Bridge』の略でAndroidのデバッグをサポートするツールです。 adbはAndroid SDKに含まれていますので、開発マシンにパスを通せば使えるようになります。
- androidとUSB接続時にデバックモードないと反映されません。
Vue router でのルーティングが NavigationDuplicated で動作しなときは

Vue/Javascript 入門１週間程度なのでよくわかっていないですが､以下のような書き方がサンプルコードとしてころがっています｡（コピペコーダー）

```vuejs
that.$router.replace("hoge");
```

それに無名関数を２つつけてください（何故直るかは知りません）
vue router の定義がこっそり変わったのかもしれません｡

```vuejs
that.$router.replace("hoge", () => {}, () => {});
```

１日ぐらいむだにしました
styled-componentsを使っているときのStoryBook v5.2対応

StoryBook v5.2 では、内部でTypeScriptが使われるようになり、型定義を同梱するようになりました。
しかし、内部でemotionを使っているため、その型定義が参照されてしまいます。何が問題なのかというとこの部分です。

https://github.com/emotion-js/emotion/blob/1bb3efe399ddf0f3332187f3c751fbba9326d02c/packages/core/types/index.d.ts#L82-L99

```emotion.d.ts
declare module 'react' {
  interface DOMAttributes<T> {
    css?: InterpolationWithTheme<any>
  }
}

declare global {
  namespace JSX {
    /**
     * Do we need to modify `LibraryManagedAttributes` too,
     * to make `className` props optional when `css` props is specified?
     */

    interface IntrinsicAttributes {
      css?: InterpolationWithTheme<any>
    }
  }
}
```

css propを拡張するので、styled-componentsなど他のCSSinJSをプロジェクトで使っている場合に型が競合します。

## emotionの型定義を無効化する

そこで`emotion`の型定義を無効化する必要が出てきます。
tsconfigのpathsを使って、参照を変えましょう。

tsconfig

```json

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@emotion/core": ["src/types/emotion.d.ts"]
    }
```

src/types/emotion.d.ts

```ts
declare module '@emotion/core';
```

以上です。これでemotionの型定義が無効化され、今まで通りプロジェクトにあるstyled-componentsなどのCSSinJSの型が適用されます。
User & IBM NEXT 2019@福岡

# NEXT 2019@福岡 ～ Jupyter notebook まで
**User & IBM NEXT2019@福岡** に行ってきました。最高に楽しかったです！
やはり、あの様な場に行くと、出会いあり、発見ありでテンションが上がります。
帰ってきた後の仕事に対するモチベーションも、非常に上がるので行って良かったです。

さて話を```IBMi```の話題に戻すと、会場でとある **イケメン** に、お会いすることが出来、その方から「``IBMi``で **jupyter notebook** 使えますよ。」と言われて「えぇーそうなんだ！」とビックリ。
本当に *yum* になってから、こっそり使える様になっている、パッケージが多いです。
(^-^) 早速入れてみました。
公式のBitbucketには記載がないので、[AIX 情報を参考](https://developer.ibm.com/tutorials/machine-learning-with-python-on-aix/) にしました。yum 楽勝です！

```sh
# 必要ライブラリ等のインストール（※デフォルトで既に入っているものもあり）
yum install gcc gcc-c++ gcc-gfortran xz python3 python3-devel libpng-devel libfreetype6 freetype-devel libzmq libzmq-devel liblapack3 libblas3
# Jupyterのインストール
pip3 install jupyter

# notebookの設定ファイル生成
jupyter notebook --generate-config

# notebook設定ファイルの変更
vim .jupyter/jupyter_notebook_config.py

## The IP address the notebook server will listen on.
#c.NotebookApp.ip = 'localhost'
c.NotebookApp.ip = 'xxx.xxx.xxx.xxx'

#c.NotebookApp.open_browser = True
c.NotebookApp.open_browser = False

#c.NotebookApp.port = 8888
c.NotebookApp.port = 8888

# パスワードを設定する場合
jupyter notebook password
Enter password:*****
Verify password:*****
# 以下に「.jupyter/jupyter_notebook_config.json」が作成される

# Jupyter notebookの実行
jupyter notebook
[I 15:34:37.114 NotebookApp] Serving notebooks from local directory:home/hoge
[I 15:34:37.114 NotebookApp] The Jupyter Notebook is running at:
[I 15:34:37.114 NotebookApp] http://xxx.xxx.xxx.xxx:8888/
[I 15:34:37.114 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).

```
---
実行結果
![2019-10-21_154242.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100029/53bea625-1582-3636-cbcb-b39f703fc968.png)
---
福岡の思い出
![IMG_20191016_103128.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100029/a689fd75-d9ca-dabd-1ee3-7db372df96a7.jpeg)
![IMG_20191016_123819.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100029/5c293a4a-d4a3-62a1-d963-c821e27aef3d.jpeg)
UILabelが省略されているか判定する

意外と見つからなくて困ったので、自分なりの実装方法を共有します。

## コード
```Swift
extension UILabel {
    
    var isOverflowing:Bool {
        return (realLineCount() > self.numberOfLines)
    }

    private func realLineCount()-> Int {
        guard let font = self.font else { return 0 }
        guard let text = self.text, text != "" else { return 0 }
        let sizeForWidthCheck = CGSize(width: Int.max, height: Int(ceil(font.pointSize)))

        let oneLineWidth = text.boundingRect(with: sizeForWidthCheck,
                                             options: .usesLineFragmentOrigin,
                                             attributes: [NSAttributedString.Key.font: font],
                                             context: nil).width
        let boundingWidth = text.boundingRect(with: self.bounds.size,
                                              options: .usesLineFragmentOrigin,
                                              attributes: [NSAttributedString.Key.font: font],
                                              context: nil).width
        return Int(ceil(oneLineWidth / boundingWidth))
    }
    
}
```
## 解説
UILabel.textは省略されている場合でも全文を返してくれるので、それを使用します。
`realLineCount`メソッドで、省略せずに全文を描画したときの行数を計算します。

```Swift
let oneLineWidth = text.boundingRect(with: sizeForWidthCheck,
                                             options: .usesLineFragmentOrigin,
                                             attributes: [NSAttributedString.Key.font: font],
                                             context: nil).width
```
boundingRectメソッドはStringを描画した場合のRectを返してくれます。
これを使って、１行で全部描画したときの横幅を計算します。[^1]

```Swift
return Int(ceil(oneLineWidth / boundingWidth))
```
それを`boundingWidth`(Labelに描画したときの横幅)で割って、行数を計算します。[^2]
小数点以下はいらないので、繰り上げます。


```Swift
var isOverflowing:Bool {
    return (realLineCount() > self.numberOfLines)
}
```
計算した行数を自身の行数(ここは実際に表示される行数)と比較し、
大きければ省略されているので`true`を返します。

純正で用意して欲しいな……  

ありがとうございました。
[^1]: widthが`Int.max`になっておりますが、<br />こんなに使うことないと思うので適宜小さめの値に変えたほうが良いかもしれません。
[^2]: 行数が増えると若干の誤差が出ると思います。(多分)
[Ruby] Hello world より前に出てくる「irb」の意味を知っているか！！

#はじめに
みなさん，Ruby入門書の初めの方に「Rubyを動かしてみよう」ってな感じで，[irb]とターミナルで記述することがあったかと思います．
そんな記憶はあるものの，ファイルから実行するそこまで，深く考える人はいないと思うので，ほんの少しだけ深掘りしてみよと思います．

##irb(Interactive Ruby)
ちなみにですが，略称は上の方になっています．
ここで，念の為英単語の意味を確認しておきましょう．

・interactive 対話方式

つまりは，，対話方式に実行するためのコマンドということになります．

####もう少し一般化した言葉で記述すると，**REPL**

##REPL(Read-eval-print loop) : 対話型評価環境
上にも書いてありますが，[irb]とはRubyにおける対話型評価環境ということです．


>入力・評価・出力のループのこと．主にインタプリタ言語において，ユーザーとインタプリタが対話的にコードを実行する．

[Wikipedia](https://ja.wikipedia.org/wiki/REPL)にはこのように書いてあります．

##まとめ
###**irb⊂REPL**

ということになります．

みなさんは"Hello world!"以外でどんな使い方をしているのでしょうか？
もし，テキスト出力以外で使っている人がいましたらコメント頂けると嬉しいです〜

では！
kaminariで複数のテンプレートを扱う

[READ ME](https://github.com/kaminari/kaminari#multiple-templates)の説明が少しわかりにくかったので補足。

```sh
% rails g kaminari:views default --views-prefix admin
```
で別のテンプレートを作った場合
`app/views/admin/kaminari/~`に作成されますが
ここで作った[テンプレートを呼び出したい](https://github.com/kaminari/kaminari#specifying-an-alternative-views-directory-default-is-kaminari)場合は

```slim:views/admin/hoge/index.html.slim
= paginate @users, views_prefix: :admin
```
とする。
Regex 正規表現についての学び （基本）

今回はRegex（正規表現）について学んだのでそれについて書いていきたいと思います。

##定義された文字
Regexにおいて定義された文字クラスがあります。これらは簡単で重要なので覚えてしまいましょう。


| 構文 | Matches |
|:--|:--|
| . | 任意の文字 (行末記号とマッチする場合もある) |
| \d | 数字: [0-9] |
| \D | 数字以外: [^0-9] |
| \s | 空白文字:[ \t\n\x0B\f\r] |
| \S | 非空白文字:[^\s] |
| \w | 単語構成文字:[a-zA-Z_0-9] |
| \W | 非単語文字:[^\w] |

##数量子、繰り返し
| 構文 | Matches |
|:--|:--|
| X? | X、1 または 0 回 |
| X* | X、0 回以上 |
| X+ | X、1 回以上 |
| X{n} | X、n 回 |
| X{n,} | X、n 回以上 |
| X{n,m} | X、n 回以上、m 回以下 |

##文字クラス
[]にある文字の中から一つを選ぶと言う意味。よく出てきます。

| 構文 | Matches |
|:--|:--|
| [abc] | a、b、または c (単純クラス) |
| [^abc] | a、b、c 以外の文字 (否定) |
| [a-zA-Z] | a 〜 z または A 〜 Z (範囲) |
| [a-d[m-p]] | a 〜 d、または m 〜 p:[a-dm-p] 結合 |
| [a-z&&[def]] | d、e、f 交差 |
| [a-z&&[^bc]] | b と c を除く a 〜 z:[ad-z] 減算 |
| [a-z&&[^m-p]] | m 〜 p を除く a 〜 z:[a-lq-z] 減算 |

##境界正規表現エンジン
^something$と言う形でよく使われます。

| 構文 | Matches |
|:--|:--|
| ^ | 行の先頭 |
| $ | 行の末尾 |
| \b | 単語境界 |
| \B | 非単語境界 |
| \A | 入力の先頭 |
| \G | 前回のマッチの末尾 |
| \Z | 最後の行末記号がある場合は、それを除く入力の末尾 |
| \z | 入力の末尾 |


これらが正規表現を学ぶ上で最低限知っておいた方が良いものをピックアップしたものです。
参考にさせていただいた記事にはさらに基本が詳しく書いてあるのでそれも見てみてください。

#参考記事

[正規表現の基本](https://qiita.com/sea_ship/items/7c8811b5cf37d700adc4)
JSON内の特定の値をマスクする

## 目的

APIリクエスト・レスポンスをログに吐きだす際など用のメモ書き

## 例

## javascript
```javascript
const MASK_KEYS = ['email', 'password']

const maskJson = obj =>
  MASK_KEYS.reduce(
    (memo, key) =>
      memo.replace(new RegExp(`"${key}":"[^,}]*"`), `"${key}":"XXXXXX"`),
    JSON.stringify(obj)
  )
```

### console
```javascript
maskJson({ email: 'sample@email.com', password: 'password' })
=> "{"email":"XXXXXX","password":"XXXXXX"}"
```

## ruby
```ruby
MASK_KEYS = %w[email password].freeze

def mask_json(hash)
  MASK_KEYS.inject(JSON.generate(hash)) { |memo, key| memo.gsub(/("#{key}":"[^,}]*")/, "\"#{key}\":\"XXXXXX\"") }
end
```

### console
```ruby
mask_json({ email: 'sample@email.com', password: 'password' })
=> "{\"email\":\"XXXXXX\",\"password\":\"XXXXXX\"}"
```
ExcelVBAで指定フォルダ内のbasファイルをインポートする

ExcelVBAでbasファイルをインポートする
===

## 前準備

VBA プロジェクト オブジェクト モデルへのアクセスを許可しておく。

## 実装

ThisWorkbookに下記の処理実装する。

```vb
Private Sub Workbook_Open()

    'ここで読み込みたいモジュールがあるフォルダを指定する
    importModules "\\xxxx" 
    importModules "\\yyyy" 

End Sub

'指定フォルダの*.basをインポートする
Private Sub importModules(ByVal dirName As String)

    Dim bas As String
    Dim cmp As Object

    bas = Dir(dirName)
    Do Until bas = "" 

        If bas Like "*.bas" Then

            For Each cmp In ThisWorkbook.VBProject.VBComponents
                If cmp.Name & ".bas" = bas Then
                    ThisWorkbook.VBProject.VBComponents.Remove cmp
                End If
            Next cmp

            ThisWorkbook.VBProject.VBComponents.Import dirName & bas
            bas = Dir

        End If

    Loop

End Sub
```
OutSystemsのCarousel Widgetの使い方

OutSystems UIに含まれるCarousel Widgetの使い方を確認してみます。
対象はTraditional Webです。
Reactive Web App用もあります(パラメータが違っていたり、イベントが追加されていたりします)。

# 環境
Personal Environment(Version 11.0.606.0)
Service Studio(Version 11.6.2)
OutSystemsUIWeb(Version 1.7.7)

# 利用方法

## Carousel Widgetの参照を追加する
Service StudioからManage Dependenciesダイアログを開き、ProducerとしてOutSystemsUIWeb、elementsとしてCarouselを選択してAPPLYボタンをクリック。
また、Carouselの表示位置を変更するServer Actionもあるので、後で動作確認するために追加しておきます。

![QCarousel1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/6d285204-52d2-cff3-1f39-4799ffc48cd7.png)

## Widgetを配置
Traditional WebモジュールにScreenを用意しておきます。
画面左側のToolbox上でCarouselで検索して、見つかったWidgetをScreen上にドラッグ＆ドロップして配置。

### 表示する画像が決まっている場合
Widget内のPlaceholder 「Items」に直接Image Widgetを配置していきます。
ここでは、InterfaceタブのImagesの下に画像をアップロードして使用。TypeはStaticに。

![QCarousel2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/6bb55231-63ae-c58a-2b20-f3e8d5db7be8.png)

### 表示する画像が動的に変わる場合
Widget内のPlaceholder 「Items」にList Recordsを配置し、画像を詰めたListをSource Record Listに渡します。

下の例は、Entityから取得した画像を含むレコードをList Recordsdを使って、画像とキャプション形式で表示しています。Line SeparatorはNoneにしておかないと、空のアイテムが表示されてしまうようなので注意。

![QCarousel3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/246ccd82-9ede-4738-8e95-0540dc0cadde.png)

## Widgetのプロパティを調整
下のスクリーンショットで説明します。
![QCarousel4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/070c6892-81be-d4b0-7c5f-7c20e19fcade.png)

- Navigation：①で示したアイテムを左右に移動させるボタンを表示するか
- Pagination：②で示した、指定のページヘジャンプするUIを表示するか
- ItemsDesktop|Tablet|Phone：端末の種類ごとに違うプロパティを指定するようです。1ページに表示するアイテム数。スクリーンショットはItemsDesktop=3の場合
- Margin：アイテム間の間隔の幅(ピクセル)

# AdvanceFormat
WidgetのAdvancedFormatプロパティにJSON形式の設定を渡すことで任意の設定項目が利用できます。

![QCarousel5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/fa5f2bb8-e86e-8971-9aa6-1a122b5f9a63.png)

上の例は、Carouselの方向を縦に変更したもの。
設定値は、AdvancedFormat: "{axis: 'vertical', autoHeight: false}"
autoHeightはfalseにしておかないと、Itemsを指定しても1アイテムしか表示されませんでした。

利用できる設定値は以下の、Widgetがラップしている元のJavaScriptライブラリのページを参照してください。
[tiny-slider](https://github.com/ganlanyuan/tiny-slider)

# Server Action
以下3種類のActionがあり、それぞれCarousel WidgetのIdを受け取ります。そのため、Carousel WidgetのNameを設定しておく必要があります。

- GoTo：レコードの位置を整数で指定。指定した位置へ移動する
- Next：次のレコードへ移動する
- Previous：前のレコードへ移動する

それぞれ、内部ではRunJavaScriptを読んでいるだけです。
そのため、Method=Ajax SubmitのButtonを配置し、上記Actionを呼ぶScreen Actionを作成するだけでOK。
macOS 10.15(Catalina)にアップデートしたらhttpd.confの設定が飛んだので復旧させたメモ

自身のMacBook ProのOSを10.14から10.15にアップデートしたらhttpd.confの設定が飛んでしまったので解決メモ。

正確には飛んでしまった、というよりもこれまで使っていたhttpd.confが「場所が変更された項目」に移動されてしまい、10.15に準拠したファイルが新たに作成されていました。

#「場所が変更された項目」とは
10.14から10.15へとアップデートが完了した際に、突如デスクトップに出現した「場所が変更された項目」へのエイリアス。大元は**_/ユーザ/共有/_**以下に作成されています。

そのフォルダに「場所が変更された項目とは?.lpdf」というファイルがあるので、その内容を抜粋。
（ん？.lpdfファイル？）



>前回のmacOSアップグレードまたはファイル移行中に、一部のファイルを新 しい場所に移動できませんでした。このフォルダには、移動できなかった ファイルが含まれています。

>**新しい場所に移動する必要があるファイル**
macOSのセキュリティ設定に適合しなくなった場所にあったファイルがありました。確認の ために、それらのファイルは“セキュリティ”フォルダに移動されました。
保持したいファイルは、アップグレードまたは移行の前の場所とは別の場所であれば、新しい 場所に移動できます。

>**構成ファイル**
これらの構成ファイルはご自身、別のユーザ、またはアプリケーションによって変更またはカ スタマイズされました。それらの変更は最近のmacOSアップグレードと互換性がありませ
ん。変更されたファイルは“構成”フォルダ内にあり、元の場所の名前が付いたサブフォルダで 整理されています。

>カスタム構成のいずれかを復元するには、macOSのアップグレード時に行われた構成変更と 比較して、可能であれば両者を統合してください。


ということです。httpd.confは「構成」フォルダ以下に置かれているので、構成ファイルの内容によれば、旧httpd.confと新httpd.confは互換性がないとのこと。マジですか。


#新しいhttpd.confを確認
とりあえず**_/etc/apache2/httpd.conf_**を開いて内容を確認。
一部これまでなかった記述があるものの、全体としては同じような内容。
一先ず旧httpd.confを参考に新しい方を更新。
自分のMacではPHPとPerlの設定がしてあったので、それを記載します。

```:PHP用の変更内容
186行目 #LoadModule php7_module libexec/apache2/libphp7.so　→コメントアウトはずす
458行目  #AddOutputFilter INCLUDES .shtmlから459行目 </IfModule>の間に
    AddType application/x-httpd-php	.php
    AddType application/x-httpd-php-source	.phps
の2行を追記
```
```:Perl用の変更内容
170行目 #LoadModule cgid_module libexec/apache2/mod_cgid.so
173行目 #LoadModule cgi_module libexec/apache2/mod_cgi.so
183行目 #LoadModule userdir_module libexec/apache2/mod_userdir.so
185行目 #LoadModule rewrite_module libexec/apache2/mod_rewrite.so
187行目 #LoadModule perl_module libexec/apache2/mod_perl.so
	→コメントアウトはずす
268行目 Options FollowSymLinks Multiviews	   →末尾にExecCGI追記
446行目 #AddHandler cgi-script .cgi	       →コメントアウト外して、末尾に.pl追加
```

```:必要があれば次の項目も変更
199行目 User _www       →設定したいユーザ名に
200行目 Group _www	  →設定したいユーザ名に
221行目 ServerAdmin you@example.com	→設定したいメールアドレスに
230行目 ServerName www.example.com:80	→設定したいURLに
```

変更が終わったら保存してapacheを再起動。
特に問題なく起動し、Webページも問題なく表示されました。



#まとめ
今回行った記述変更は旧OSと全く同じ。
ということは、移動された理由としては、新しいOSとの互換がないとのことだけど
自分で手を加えた内容がNG、ということではなさそう。
とはいえ、今回はローカル環境で気づいたけど、他の人も閲覧するサーバでアップデート後に
気づかないと各所問題が起きるので要注意。
正規表現にある「\x7f-\xff」の意味

「\x7f-\xff」を正規表現として、正しい書き方は[\x7f-\xff]である。
二つの部分を分けて、説明いたす。

**①「\x7f」と「\xff」**
全部ASCII（アスキー）文字コードを表している。
「\x7f」＝16進数の「0x7f」(10進数の127)
「\xff」＝16進数の「0xff」(10進数の255)

ASCIIコード表を参照すると、「\x7f」はDelete、
「\xff」画面に表示できないので、不明である

**②「-」**
ご存じだと思うが、
-前のやつから、-後ろのやつまでの範囲指定である。

**まとめると、[\x7f-\xff]はASCIIコード表の127位から255位までの符合を意味する。**

例：phpの関数名に関する制限の正規表現としては以下になる。
[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*（phpマニュアルによる）
this.$route.nameをStorybookで使えるようにする方法

## 背景
Nuxt.jsの`this.$route.name`を使ってページによって異なる処理を行うコンポーネントを作りました。

```vuejs
<template>
  <!-- 中略 -->
</template>

<script>
export default {
  name: 'Component',
  computed: {
    isHoge: function() {
      return this.$route.name === 'hoge'
    }
  }
}
</script>
```

```javascript
import { storiesOf } from '@storybook/vue'
import { action } from '@storybook/addon-actions'
import StoryRouter from 'storybook-vue-router'

import Component from './Component.vue'

storiesOf('Components', module)
  .add('Component', () => ({
    components: { Component },
    template: '<component />'
  }))
```

これをStorybookで表示＆動作確認したかったのですが、 

```
Cannot read property 'name' of undefined
```
となって表示できませんでした。
解決法を調べましたので備忘録として残します。

## 解決法

https://github.com/gvaldambrini/storybook-router を使うことにしました。
Nuxt.jsなので https://github.com/gvaldambrini/storybook-router/tree/master/packages/vue に倣いインストールします。

```bash
npm install --save-dev storybook-vue-router
```

```javascript
import { storiesOf } from '@storybook/vue'
import { action } from '@storybook/addon-actions'
import StoryRouter from 'storybook-vue-router'

import Component from './Component.vue'

storiesOf('Components', module)
  .addDecorator(StoryRouter({}, { initialEntry: { name: 'hoge' } })) //<--追記
  .add('Component', () => ({
    components: { Component },
    template: '<component />'
  }))
```

これで期待通り動きました。
Railsで論理削除（soft delete）を実装する（discard gem利用）

# 環境

- Rails 5.2.3
- Ruby 2.6.5
- [Discard](https://github.com/jhawthorn/discard) 1.1.0

# Gemの選択に要注意

- [`paranoia`](https://github.com/rubysherpas/paranoia)は、自らのREAMDEで「新規にプロジェクトに導入するのは非推奨」としている。
- 同READMEで推奨されている[`discard`](https://github.com/jhawthorn/discard)を使う。

#### 非推奨の背景
- ActiveRecordの`delete`や`destroy`をoverrideしているため、開発者が予期しない挙動をする。
- `dependent: :destroy`関連のレコードは削除（物理削除）される（※開発者が期待する動作ではない）。

上記に伴い、バグフィックスと、Railsの新しいバージョンへの対応は行うが、新しいfeatureは受け付けていない。

# Discardの導入

## Gemのインストール

```file:Gemfile
gem "discard"
```

```ruby
$ bundle install
```

## db migration

posts テーブルに適応する例。

```
$ rails generate migration add_discarded_at_to_posts discarded_at:datetime:index
```

以下のようなファイルが生成される。

```ruby
class AddDiscardedAtToPosts < ActiveRecord::Migration[5.2]
  def change
    add_column :posts, :discarded_at, :datetime
    add_index :posts, :discarded_at
  end
end
```

```
$ rails db:migrate
```

## モデルに定義追加

```ruby
class Post < ApplicationRecord
  include Discard::Model
end
```

# 使い方

## 削除

`destroy`の代わりに、`discard`を使う。

```ruby
@post.discard
```

## コマンド実行例

```ruby
# 削除
post.discard       # => true
# 確認
post.discarded?    # => true

# 強制削除。既に削除済の場合は、exceptionが発生する。
post.discard!      # => true
post.discard!      # Discard::RecordNotDiscarded: Failed to discard the record

# 削除したレコードを元に戻す
post.undiscard     # => true
post.undiscard!    # => Discard::RecordNotUndiscarded: Failed to undiscard the record
post.discarded_at  # => nil

# 削除した日時を確認
post.discarded_at  # => Mon, 21 Oct 2019 14:34:41 JST +09:00

# 削除されたレコード一覧
Post.discarded     # => [#<Post:0x00007fc04dbe3010 ...]
# 削除されていないレコード一覧
Post.kept          # => []
```

## default_scopeの導入について

デフォルトでは、`Post.all`は削除されたレコードも含めて返す。
この挙動を変えて削除されていないものだけ返すようにするには、`default_scope -> { kept }`を設定する。

```ruby
class Post < ApplicationRecord
  include Discard::Model
  default_scope -> { kept }
end

Post.all                       # 削除されていないレコードのみ
Post.with_discarded            # 全てのレコード
Post.with_discarded.discarded  # 削除されたレコードのみ
```