OmniAICreator/Qiita-1.07M huggingface dataset:
Apache Zookeeper のインストール

やってみたのでメモ

# 前提
CentOS7
Java インストール済み

# 手順
1. tar ファイルをダウンロードする

    ```sh
    # curl -LkvOf https://downloads.apache.org/zookeeper/zookeeper-3.6.0/apache-zookeeper-3.6.0-bin.tar.gz
    ```

2. tar ファイルを展開する

    ```sh
    # tar zxf apache-zookeeper-3.6.0-bin.tar.gz
    ```

3. `/opt`配下に配置する

    ```sh
    # mv apache-zookeeper-3.6.0-bin /opt/zookeeper
    ```

4. 実行用ユーザを作成する

    ```sh
    # useradd zookeeper
    ```

5. 必要に応じて`zoo.cfg`ファイルを作成して設定を変更する（IPアドレスなど）
6. 所有者を変更する

    ```sh
    # chown -R zookeeper:zookeeper /opt/zookeeper
    ```

6. サービスファイルを作成する

    ```sh
    # vi /etc/systemd/system/zookeeper.service
    ```
    
    ```
    [Unit]
    Description=Apache Zookeeper Service
    
    [Service]
    Type=forking
    User=zookeeper
    ExecStart=/opt/zookeeper/bin/zkServer.sh start
    ExecStop=/opt/zookeeper/bin/zkServer.sh stop
    
    [Install]
    WantedBy=multi-user.target
    ```

7. 再読み込みする

    ```sh
    # systemctl daemon-reload
    ```

8. 起動する

    ```sh
    # systemctl start zookeeper
    ```

# 参考
【ページ内リンク】markdownとQiitaの書き方の違い (アンカーリンク設定時の注意)

#　【ページ内リンク】markdownとQiitaの書き方の違い
ページ内リンクを設置するときに、ｍarkdown（.mdファイル）とQiitaで一部ルールに違いがある。
気になって検証した結果のメモ


##共通の型
`[アンカーテキスト](#リンク先の見出し)`
　　└大枠の型は外部へのテキストリンクの設置と同じ
　　└（ ）の中が「#」＋「見出しテキスト」になる（*外部リンクはURL）

⇛ リンク型はQiitaもmarkdownファイルもどちらも同じ


##Qiitaの書き方要点まとめ

- 「#」の数　⇒　１個
- 記号　⇒　削除
    - ハイフン　⇒　そのまま
    - アンダーバー　⇒　そのまま
- 半角スペース　⇒　「-」ハイフンに変換
- 全角スペース　⇒　削除
- 数字　⇒　そのまま
- 大文字アルファベット　⇒　小文字に変換
- 小文字アルファベット　⇒　そのまま

<br>
<details><summary>全角・半角文字別の詳細</summary><div>
- 半角記号　⇒　削除　（※「-」「_」は例外）
    - 半角アンダーバー　⇒　そのまま
    - 半角ハイフン　⇒　そのまま
- 全角記号　⇒　削除（※「ー」「＿」は例外）
    - 全角アンダーバー　⇒　そのまま
    - 全角ハイフン　⇒　そのまま
- 半角スペース　⇒　「-」に変換
- 全角スペース　⇒　削除
- 全角数字　⇒　そのまま
- 半角数字　⇒　そのまま
- 全角大文字アルファベット　⇒　小文字に変換
- 半角大文字アルファベット　⇒　小文字に変換
- 全角小文字アルファベット　⇒　そのまま
- 半角小文字アルファベット　⇒　そのまま

<br>
詳細は[こちら](hhttps://qiita.com/yuta-38/items/a65f1e2b6a3c3a4a28e1)にまとめてあります。
</div></details>

# Markdownファイルの書き方要点（Qiitaとの違い）

- 記号はあってもなくてもいい（Qiitaは基本省略）
- 全角スペースはそのまま（Qittaは省略）
- アルファベットの大文字も使える（Qiitaはすべて小文字になおす）
    - ※ただし、小文字と大文字の区別はされない
- 「<>」も使える（Qiitaでは使えない）
    - ※ないものとして扱われる
    - ※記号のみは使えない（Qiitaも同じ）
- 全角記号は文字列として使える（Qiitaは省略）
    - 「＜＞」などが使える


##markdownファイルの注意点
###同じリンク先を参照するパターンが発生する

####大文字と小文字の区別がない
例えば、「###AAA」という見出しに対して①～④がすべて同じリンク先になる

①[AAA](#AAA)
②[aaa](#aaa)
③[AAA@](#AAA@)
④[aaa@!+-#$%&<>](#aaa@!+-#$%&<>)

※マークダウンファイルの話なので、ここでは飛ばない

```
[AAA](#AAA)
[aaa](#aaa)
[AAA@](#AAA@)
[aaa@!+-#$%&<>](#aaa@!+-#$%&<>)
```

- 大文字と小文字の区別がない（A=a)
- 記号は省略される
- リンク先の見出しは上にあるものが優先される

> 「###AAA」、「###aaa」、「###AAA@」が順に設置してある場合に、すべて「###AAA」に飛ぶ


<br><br>
##補足(その他のmarkdownファイル(以下md)とQiitaの書き方違い)

- 見出しの「#」のあとに半角スペースが必要（QiitaはなくてもOK）
    - 「#AAA」→　md：NG、Qiita：OK
    - 「# AAA」→　md：OK、Qiita：OK
- 引用の「>」は各行に必要（Qiitaは空白行がなければ一塊として認識）


##まとめ##
Qiitaはミスが発生しにくい＋使いやすいようにカスタマイズされている。
markdown形式で他のツールやファイルに記述するときは注意が必要かも。
【FuelPHP】SSLリバースプロキシ下での設定。

※この記事は、下記の経緯の中で作成しました。
docker-composeでNginx+php環境を構築。(そのときの記事は[こちら](https://qiita.com/uecoeco/items/d4a9ff7705c2a278a10b))
HostOSのNginxでHTTPS->HTTPのリバースプロキシを行い、DockerのNginxではHTTPでうける。PHP環境にFuelphpをインストールし、早速welcomeページをブラウザ表示したところ・・・
コンソールに下記が表示。

```
Mixed Content: The page at 'https://xxxx.jp/' was loaded over HTTPS, but requested an insecure stylesheet 'http://xxxx.jp/assets/css/bootstrap.css?1561651380'. This request has been blocked; the content must be served over HTTPS.
```

HTTPSサイトなのに、HTTPでCSSををリクエストするのは（混在）NG、というわけ。
こちらの解決策について。

#HostOSのNginx（リバースプロキシ）の設定
こんな感じ。

```/etc/nginx/conf.d/xxx.jp.conf
server {
    listen 80;
    server_name xxxx.jp;
    location / {
        rewrite ^(.*)$ https://$host$1 permanent;
    }
}
server {
    listen 443 ssl;
    server_name xxxx.jp;

    access_log   /var/log/nginx/xxxx.jp/access.log  main;
    error_log    /var/log/nginx/xxxx.jp/error.log warn;

    ssl_certificate ssl/xxxx.jp.crt;
    ssl_certificate_key ssl/xxxx.jp.key;

    location / {
        # docker's port
        proxy_pass http://localhost:8082;
        # https -> http
        proxy_redirect http:// https://;
        # inherit remote info
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
```
※Dockerのnginxは8082ポート(HTTP)で受けている。
※proxy_redirect のところでHTTPにプロキシ。
※X-Forwarded-Protoで、クライアントのプロトコル（HTTPS）をx-headerを使って転送先に伝えている。

#原因
welcomeページのCSSの読み込みは・・・

```fuel\app\views\welcome\index.php-L6
<?php echo Asset::css('bootstrap.css'); ?>
```

fuelphpの中でプロトコルを判定している箇所は・・・・？

```fuel\core\classes\input.php
	/**
	 * Return's the protocol that the request was made with
	 *
	 * @return  string
	 */
	public static function protocol()
	{
		if (static::server('HTTPS') == 'on' or
			static::server('HTTPS') == 1 or
			static::server('SERVER_PORT') == 443 or
			(\Config::get('security.allow_x_headers', false) and static::server('HTTP_X_FORWARDED_PROTO') == 'https') or
			(\Config::get('security.allow_x_headers', false) and static::server('HTTP_X_FORWARDED_PORT') == 443))
		{
			return 'https';
		}

		return 'http';
	}
```

static::server('HTTP_X_FORWARDED_PROTO')は先述のHostOSの設定でtrueできている。
問題は、\Config::get('security.allow_x_headers', false)がfalseになっていること。
→
・x-headerが許可されていない。
・configで設定できるっぽい

#解決策

下記のように直す。

```fuel\app\config\config.php-L245
// 'allow_x_headers' => false,
```

```fuel\app\config\config.php
'allow_x_headers' => true,
```
【CMS】ローカル環境でJS CMSをお試しする

最近WordPress、いやだなあ～なんて思ってます。
更新通知メール多いのもなんですけど。
ブロック配置のところが分かりにくいのでメリットがまるで生かせてません。
WIXとかJIMDOとかだと重い上に細かいCSSカスタマイズが出来ないのでもだもだします。

正直、静的サイトドーン！　でもいいなあと思って、
改めてCMSツールを調べたところ「JS CMS」なるものを発見。

・DBレス
・リアルタイムレイアウト
・完全無料
という謳い文句に惹かれていざいざお試ししてみます！
……ローカル環境で。

[JS CMS公式サイト](https://www.js-cms.jp/index.html)
（公式にもローカル環境の手引きがあるんですけど、それとは違う方法です）


#本体とテンプレートをDL
JS CMSは本体とテンプレートをセットでダウンロードします。
敢えて嫌な感じに言うと、一度落としたらテンプレートは変更できません。
とは言え痒い所はHTMLとかCSSいじったりすればいいだけなのでモーマンタイ。

[ダウンロードページ](https://www.js-cms.jp/html/download.html)

そんなこんなで適当なところに解凍。
index.htmlがあるので、実はこれだけでもデモサイトが見れます。
全然実はじゃないけど。
でもブラウザで弄りたいので、それは後回し。


#環境をささっと整える
参考：[PHPのダウンロードとインストール - Windows環境](https://webkaru.net/php/windows-php-instal/)

JS CMSはPHPだけで動いてるので、PHPだけ入れれば自前の環境でも動かせます。
静的ジェネレーターじゃないので、あくまでちょっと動作確認したいって時だけのほうがいいと思います。
……静的ファイルは生み出す点では否定は出来ませんが。

[公式サイト](https://www.js-cms.jp/html/intro_05.html)によると「PHP4.3以上」が条件のようです。（2020/03/16現在）
なので、ver4.3以上のPHPを入れます。
    　 
    
①[配布ページ](https://www.php.net/downloads)から適当なWindows向けPHPをDL（今回は7.3.15）
②Cドライブ直下にzipを解凍し、フォルダ名を「PHP」に変更
③PHPフォルダにある「php.ini-production」ファイルをコピーし、「php.ini」というファイル名で上書き保存
④エクスプローラーのPCを右クリック→プロパティ→システムの詳細設定→環境変数に移動
⑤Path→新規をクリックしてから、```C:\PHP```と入力してOK
⑥コマンドプロンプトを起動し、「php -v」と入力して、以下のような画面が出たらOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412138/824c12cf-74a2-8633-efd2-8c87323bea0e.png)


これでPHPが入りました。
文字だけの説明になってしまったので、画像で詳しく見たい方は上記の参考サイトまで。
CMSって（多分）複雑だと思うので、PHP一本で動かせるのってレアな気がします。
他のCMSになるとDB入れたりNode入れたりしそうなので、今回のは今更ながらアプリ依存な手法かと。

まずローカルで試すなって話ですかね！！！


#localhostを設置
参考：[指定フォルダを簡単に localhost でアクセスできるようにする](http://var.blog.jp/archives/79635343.html)

さあ本題。
PHPを入れても、そのままじゃPHPファイルはブラウザでは見れません。
結論から言うと「http://」から始まらないとダメっぽいです。
なので力業……でもないですが、ローカルサーバを起動してなんとかします。  
     
  
①参考サイトに載っているソースをコピー
②JS CMSのフォルダ内に```_local.txt```というファイルを作成し、コピーしたソースをペースト
③```_local.txt```を閉じてから、```_local.txt```を```_local.bat```という名前にリネーム

これで準備は完了です。
このバッチファイルを叩けば、現在地のフォルダがローカルサーバとして立ち上がる？　ようなかんじ。
コマンド叩くよりバッチのほうがいいなあって思ったのでこんなかんじです。

ちなみにでもないですが、バッチ叩くとポート番号入力画面が出ますけども、
入力せずにエンター押せばデフォルトで設定したポート番号（何もしていなければ8000）が設定されます。
ので、どのポート番号が良いのやらってなっている人はエンターだけ押せばいいと思います。
自分だ！


#いざいざ！
バッチを叩いてから```http://localhost:8000/_cms/```にアクセスしてみます。
こんなかんじの画面が出たら成功！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412138/6f16ec02-daaa-769c-757f-b9a091397794.png)


ちなみにログインIDとパスワードはデフォルトで「guest」になっています。
変更したいときは```/_cms/setting/setting.php```の該当欄をいじれば良いです。

あとは存分にローカルで弄り倒して下さい。
WordPressより楽しいですよ！（当社比）
IT業界の歩き方

IT業界の歩き方なんて、Qiitaのユーザー層には必要ないかなと思っていたのですが、[これからエンジニアを目指す人に見て欲しいです。](https://qiita.com/hukusuke1007/items/1f3843a9f044a8affeee)や[プログラミング初心者のために簡単用語説明](https://qiita.com/dd0125/items/be98a6ccab5e357d806d)を見るに、そうでもないのかと思ったので、非IT業界の方向けに作ったYoutube動画の内容を記事化しました。

初心者エンジニアの方が勉強するのにQiitaを活用するのは良いことですね。

↓動画はこちら
[![IT業界の歩き方 エンジニア編【業界研究】](http://img.youtube.com/vi/PEekLmBkRpQ/0.jpg)](http://www.youtube.com/watch?v=PEekLmBkRpQ)

# IT業界見取り図

一口にIT業界と言っても多岐にわたるので、どんな分野があるのか一枚絵でまとめてみました。

<img width="2560" alt="スクリーンショット 2020-03-16 10.37.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26825/38e78396-ed57-3a07-0514-d375f3e2df04.png">
※「うちの業界載ってません」などありましたらごめんなさい。

# システム開発のプロセス

エンジニアをやっているとシステム開発というと「要件定義からリリースまで」ですが、その上に企画や要求定義があります。
日本では要求定義は蔑ろにされていますが、プロジェクトの成否を決める大きな要因の一つはこの要求定義だと個人的には思います。

<img width="2560" alt="スクリーンショット 2020-03-16 10.33.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26825/a9e3825e-58d6-2f14-cae6-7c14e2181dbf.png">

# 業種と守備範囲

システム開発のプロセスにおいて、各業種がどう関わっているかを一枚絵にしています。UXの重要度が上がり、最近ではコンサル、広告代理店（マーケター）、UXデザイナーの仕事がダダ被りになっていますね。

<img width="2560" alt="スクリーンショット 2020-03-16 10.33.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26825/adbdd2c9-8d8e-11bd-b0db-4046d2b7cd8e.png">

# 業種と技術要素

今度は業種毎にシステム開発のプロセスのどのフェーズに携わるのかを、最近（あるいは昔から今でも）幅を利かせている技術要素とともにまとめました。

<img width="2560" alt="スクリーンショット 2020-03-16 10.33.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26825/6232ebb5-1c7b-b77f-f2dc-99543346c50a.png">


# 最後に

無理やり一枚絵にまとめているので詳細は他に譲りますが、非ITの方、これからエンジニアとしてやっていきたいという方への概要説明などに使ってもらえれば幸いです。

あと業界中の人的なここはこうでしょ的なツッコミも頂ければ幸いです。
変数の名前を付けるときに、絶対パスを格納していることを明記したい場合はabs_がよさげ

# はじめに
相対パスではなく、絶対パスを変数に格納してほしい場合がしばしば生じます。
その際今まで私は、

```
$setting_json_full_path
``` 
とかの名前を利用していました

# abs
```
$abs_setting_json_path
```
とか、

```
$abs_ubuntu_iso
```
とかの方が文字数も少なく、見た目もスッキリする上、意味もしっかり伝わるのでよいなと思った次第です。特に出典はありません。

`abs`は`absolute path`、絶対パスの略称です。

突き詰めると好みの問題になりそうですが、`abs`を使っていこうと思った次第でした。[^1]
[^1]: 一番ベストなのは、参加したプロジェクトに合わせて使い分けることですね
input type="number"で表示される矢印を消したいhttps://qiita.com/stock


<input type="number">


##google chrome 
input[type="number"]::-webkit-outer-spin-button, 
input[type="number"]::-webkit-inner-spin-button { 
  -webkit-appearance: none; 
  margin: 0; 
} 


## IE , firefox
input[type="number"] { 
  -moz-appearance:textfield; 
} 

##ついでに右寄せ

input[type="number"]{
	text-align:right;
}
Gerritの構築方法と使い方

# Gerritとは

Gerritとは無料のブラウザベースで使えるコードレビューツールです。主にソフトウェアのアジャイル開発を行う目的で利用されます。チームでソフトウェア開発を進める際に、ソースコードの変更をお互いにレビューし合い、レビューを通過したものだけを開発中のコードにマージすることができます。Gitを使って、開発しているソースコードのクローンや変更の提出などを行います。また、Jenkinsと連携させることで提出したコードの自動検証も可能です。Gerritの構築方法と簡単な使い方を紹介します。

# Gerritの構築
Gerritはサーバー上で構築し、ブラウザからアクセスして使用します。構築の方法は[公式ページ](https://gerrit.googlesource.com/gerrit/)にもいくつか書いてあります。その中でもDockerを使った構築方法が最も簡単でした。

```
sudo docker run -d -p 8080:8080 -p 29418:29418 gerritforge/gerrit-ubuntu15.04
sudo docker ps
CONTAINER ID        IMAGE                            COMMAND                  CREATED             STATUS              PORTS                                              NAMES
bdaf2ac5560f        gerritforge/gerrit-ubuntu15.04   "/bin/sh -c '/var/ge…"   5 minutes ago       Up 5 minutes        0.0.0.0:8080->8080/tcp, 0.0.0.0:29418->29418/tcp   pedantic_ardinghelli
```

ブラウザで0.0.0.0:8080を開けるようになります。

<img width="1032" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602996/f71dd395-52a2-4ae7-bb33-8f1895fab9a9.png">

次に、sshでGerritに接続できるようにします。

```
ssh-keygen -t rsa
cat ~/.ssh/id_rsa.pub
```
catで出力された公開鍵をGerritのブラウザから登録します。
`Account`>`Settings`>`SSH Public Keys`の場所から登録します。
その後以下のコマンドで、ssh接続ができることを確認します。

```
ssh admin@localhost -p 29418
  ****    Welcome to Gerrit Code Review    ****

  Hi Administrator, you have successfully connected over SSH.

  Unfortunately, interactive shells are disabled.
  To clone a hosted Git repository, use:

  git clone ssh://admin@25680d00e8b3:29418/REPOSITORY_NAME.git

Connection to localhost closed.
```

次に、練習として、testプロジェクトを作成して修正をコミットする手順を示します。

```
ssh -p 29418 admin@localhost gerrit create-project --empty-commit test
```
`test`というプロジェクトが作成されました。

<img width="1027" alt="キャプチャ1.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602996/21f56017-1752-a6df-dd3d-514aba4bf8a9.png">

`test`というプロジェクトに変更点を提出していきます。

```
git clone ssh://admin@localhost:29418/test
cd test

scp -p -P 29418 admin@localhost:hooks/commit-msg .git/hooks/

echo 'test' > test.txt
git add test.txt
git commit -m "test commit"
git push ssh://admin@localhost:29418/test  HEAD:refs/for/master
```
3行目の`scp ・・・`というコマンドは、コミットに自動でIDを付与するために必要です。IDが付与されていないと変更点の提出ができないことがあります。
下の画像の通り、変更点が提出されました。

<img width="1038" alt="キャプチャ2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602996/8cb7fc0b-29b3-4e15-fa74-64b964ea7a81.png">

# Gerritで変更点の提出までの流れ

現在開発中のリポジトリのクローンと、Gerritへの変更点の提出までの手順を書きます。

```
git clone ssh://admin@localhost:29418/test
cd test
git checkout -b myBranch
```
ソースコードに変更を加えます。JIRAとGerritの連携機能を使っているのであればJIRAの課題管理IDをコミットメッセージに記載します。

```
git add .
git commit -m "[JIRA issue ID] commit message"
```

最後に、Gerrit上のリモートリポジトリと同期し、[git review](https://pypi.org/project/git-review/)によりソースコードの修正を提出します。

```
git checkout master
git pull --ff-only origin master
git checkout myBranch
git rebase -i master
git review
```

# 提出内容の修正方法

提出した変更内容を修正したい場合の手順を示します。

```
git review -d [変更番号]
git checkout review/[提出者名]/[ブランチ名]
```
ソースコードを修正します。

```
git add .
git commit --amend
git review
```
google_image_downloadが使えなかったときの対処記録

##この記事の内容
- google_image_downloadが動かなかったので、自分で対処した方法のメモ
    - [この記事](https://qiita.com/rkura/items/453a2e90c1d2364dbf7b)を参考にして、教師データの画像をDLしようとしたが、 google_image_downloadが動かなかった。
    - 結局Githubに[修正版](https://github.com/arthursdays/GoogleImagesDownloader/blob/master/download_with_selenium.py)あったので、それをDLしたら動いたよって話。
- 上記の修正版がおいてあるページに書いてあることを、ほぼ和訳しただけ。

##環境
- Python3.7
- Win10 64bit
- Firefox ver72.0.2
- 他に何書いたらいいかわからん

##対処方法
1. Firefoxとgeckodriverを持ってない人は、インストール
    - geckodriverは[ここ](https://github.com/mozilla/geckodriver/releases)から配布ページに飛べる。
    - geckodriverはユーザ変数のパスを通しておく。
        - わからなければ、[ここらへん](https://www.atmarkit.co.jp/ait/articles/1805/11/news035.html)を参考に。
            - （参考までに）自分はシステム環境変数に、解凍後にFirefoxのインストールフォルダ内に移動させたgeckodriverフォルダーまでのパスを記述。
2. GoogleImagesDownloaderをDLし、解凍
    - [ここ](https://github.com/arthursdays/GoogleImagesDownloader)からDLできる。
2. 解凍フォルダ内から使いたいプログラムを利用。
    - 自分は download_with_selenium.py を実行
        - プログラム190行あたりのキーワードを書き換えれば、好きな単語で画像収集できる。
    - user_agentのエラーが出た人は、pipでモジュールをインストールすれば動くようになると思われ。
     - [この](https://pypi.org/project/user_agent/)モジュール。
     - 自分は以下コードでモジュールをインストールした。
            - ``` pip install user_agent ```
            

4. 上手く行けば、プログラム実行と同時にFirefoxが立ち上がり、カレントディレクリに検索ワードの名を冠したフォルダが作成され、ダウンロードされていく。
    - 最初にURLをまとめて取得して、その後に実際に画像をDLするようだ。
    - なので、フォルダをじっと見てても最初のうちは全然画像が入らなくて不安になっる。
    - 待ってれば、画像がDLされると思われる。
Slack App Directoryにアプリを公開した際の所感をまとめてみた。

# SlackアプリをApp Directoryに公開した

エンジニアの皆さんが普段使っているツール(多分、、)Slack内にアプリを公開したので、
その際の所感をまとめたいと思います。

Slackアプリの開発方法などは、qiitaにも多く乗っていますが、App Directoryへの公開手順などはあまり乗っていないのでいい機会だと思い投稿します。
また、開発や申請部分で個人的に詰まった部分も載せます。

# 個人的に詰まった部分(困った点)

## まず、日本語の公式ドキュメントがそこまで多くない。(あるある)

まぁ、日本語のドキュメントが完璧にあってもねぇ、、
(英語のドキュメントの方で再確認するから問題ではないか)
でも、Slack developer向けのSlackコミュニティがあるので英語未対応の方もご安心を
(リンク忘れちゃった😩)

## App Directoryへの申請時には英語が必要になる。

基本的に、App Directoryに申請する際は、SlackのUSの方と会話する必要があります。😭
なので、基本英語での対応が必要です!

## リクエスト署名の確認

アプリ側のエンドポイントでこのリクエストが本当にSlackから来たのかを確認する必要があります。
簡単に説明すると、timestampとリクエストのpayloadをHMACSHA256でいい感じにしてそれを
header内の```X-Slack-Signature```に格納されている情報と比較して検証します。
詳しくはこちら,[公式ドキュンメント](https://api.slack.com/authentication/verifying-requests-from-slack)
この検証に、リクエストの生のpayloadを使用するのですが、ここで引っ掛かりました。。
自身が使っているフレームワークでは、直接生のpayloadを取得することが出来ず、フレームワークが使いやすく整形してくれたpayloadを元のpayloadに戻すという作業が必要でした。😢

## Slackアプリのoauth scopeが変わる。

アプリを公開する際に、アプリが使用許可をユーザーに得る権限が必要です。
その際に、scopeを設定します。これが、途中で変わりました。
認証が細かく管理されることは望ましいですが、アプリ公開後に変わってくれよ〜😵という気分でした。
変更点をまとめている記事は以下です。
https://medium.com/slack-developer-blog/how-to-upgrade-your-slack-oauth-scopes-96f1eb6e5bc8

# Slackのチャンネル、ユーザー、ファイル、アプリなどのIDが11文字へ

アンドキュメントな情報ではありますが、上記のIDは、基本的にPrefix1文字を含む9桁でした。
が、今後は11桁に変更になるようです。
自身は9桁ありきで作成していなかったですが、9桁ありきで開発してしまっていた人は注意です。
*11桁ありきで開発する意図ではないです。
https://twitter.com/SlackAPI/status/1238519158012182528

## アプリの公開には、アプリインストール用のランディングページが必要になる。

これが一番盲点でした。
App Directory以外にSlackアプリの説明ページが必要となります。💪🏻
自社のHPや製品ページにWebページを作成する必要があります。

# App Directoryへ公開する際に行うこと。

## アプリが使用する権限を設定&説明する。

アプリが使用する権限を設定します。
それに加えて何故このアプリがこの権限を必要とするかを説明する必要があります。😇

## Slackの人がサービスを検証できるよう情報を提供する。

ユーザー情報などが必要な場合には、検証用のユーザー情報を提供する必要があります。
また、どの操作を行うとどういうことができると言った情報も。

## 申請が弾かれたら修正する。

初めての申請で一回で通ることの方が少ないと思います。👍
アプリの説明が少ない、必要な情報が足りてない、動かないなど様々だとは思いますが修正して再度申請をあげましょう。

## 出来る限りアプリ名は英語へ(神経質な人は)

App Direcotry上のURLが以下のように多分ふられます。
https:/slack.com/apps/hogehoge-{アプリ名}
ですが、日本語はアプリ名で弾かれます。
例えば、アプリ名がキータ for Slackだと以下です.
https:/slack.com/apps/hogehoge--for-slack
↑-が連続であるのが個人的には気になります。。
なので、出来るだけアプリ名は英語にした方が個人的には良いかと思います。

# 最後に

App Directoryへ申請を行いましたが、他のアプリへの申請に比べるとそこまで大変なものではないと思います。
申請だけで3~4ヶ月かかるようなものもありますが、Slackは頑張れば1~2週間程度で申請を行えると思います。
なので、皆さんも自身が作成したものをApp Direcotryへ公開してより便利にSlackを利用できるようにしていきましょう。
Cloud9にYarnをインストールする

# はじめに

Cloud9で使用しているデフォルトのOSであるAmazon LinuxにはYarnをインストールする。

# Yarnとは

JavaScriptのライブラリを管理するツール。

# 前提条件

* AWSにサインアップしていること
* Cloud9のプロジェクトを作成していること
    * 本手順ではAmazon Linuxを使用している

```bash
cat /etc/system-release
Amazon Linux AMI release 2018.03
```

# 手順

以下のコマンドを実行する。

```bash
npm install -g yarn
```
Cloud9のNode.jsのバージョンを上げる

# はじめに

Cloud9で使用しているデフォルトのOSであるAmazon Linuxでは、Node.jsのバージョンがv10.19.0のため、2020/03/16時点で最新のv12.16.1にバージョンアップする。

# 前提条件

* AWSにサインアップしていること
* Cloud9のプロジェクトを作成していること
    * 本手順ではAmazon Linuxを使用している

```bash
cat /etc/system-release
Amazon Linux AMI release 2018.03
```

# 手順

以下のコマンドを実行します。

```bash
nvm install v12.16.1
nvm alias default v12.16.1
npm update -g npm
npm i -g npm
```
テーブルのカラムに変更を加えたいです 【 rails 】

##マイグレーションファイルとは

マイグレーションファイルとは、テーブルのカラムを追加したり消したり型を変更したりする役割があるファイル

また、何か、カラムに変更を加える場合、必ずマイグレーションファイルを記述する必要がある

##初めに

あーーnameカラム邪魔だなーと、　おもたら削除しましょう😩


#テーブルのカラム削除方法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538355/3547fcba-983b-c282-1915-9df139ec73c3.png)


①ターミナルに下記のコマンドを記述して実行する

rails generate migration　テーブル名 カラム名:データ型


```
helloland@hellolandnoAir freemarket_sample_65a % rails generate migration users name                                    
```


②マイグレーション ファイルが作られるのでそれに変更の内容を記述して

今回は削除したいので、remove_colum です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538355/3b46efc3-032b-5212-c6ad-8e3fd2a3bf29.png)



③ターミナルでrails db:migrate を実行する

```
rails db:migraet
```

④カラムが完全に消滅しました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538355/95276f61-f1b2-6e22-6f89-961851662b96.png)


#追記

もしエラーが出た場合、あせらずに　エラー文を翻訳して解くいていきましょう

また、エラー内容は一行にまとめられているので、そこだけを見ることをお勧めします


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538355/52f9b993-5cf6-13ad-8afc-238e757a7e52.png)


大体マイグレーションファイルの記述ミスの場合が大半の為、エラー内容にしたがって作成したマイグレーション ファイルを修正することをお勧めします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538355/f78dd42e-9eea-a7a3-bd8c-7239d29ca683.png)
Go 言語で "declared but not used" のエラーを無効にするには 未使用変数をアンダースコアだけにすれば良いじゃない ( #go lang ignore ))

```go
package main

import (
	"fmt"
)

func main() {
	cards := []string{"A", "K", "Q", "J"}

	for _, card := range cards {
		fmt.Println(card)
	}

	// i declared but not used
	// for i, card := range cards {
	// 	fmt.Println(card)
	// }

}

```

`_i` とかじゃなくアンダースコアだけ `_` にすると良さげ

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/3029








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Go 言語で無限ループしながら コンソールのユーザー入力を待ち受ける ( #Go wait user input in console with infinite loop )

```go

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	for {
		fmt.Println("Enter some words!")
		input := bufio.NewScanner(os.Stdin)
		input.Scan()
		fmt.Println("input is " + input.Text())
	}
}

// Enter some words!
// A
// input is A
// Enter some words!
// B
// input is B
// Enter some words!
// C
// input is C
// Enter some words!

```

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/3028








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
突然CORSで怒られたときの対処法(.NET Core)

いつも通り、APIを作り、Chromeからリクエストしたところ、今まで普通にリクエストができていたのに、突然CORSで怒られるようになったので、調べてみた。

# 発生事象
ChromeではCORS、Edgeでは404が返ってきた。

Chrome

```
Access to XMLHttpRequest at 'https://localhost:44342/api/{長いため以下略}' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
```

Edge
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256853/cfeba369-cd62-f5dd-0a21-5cc7c1f1befa.png)

その他の検索メソッドなどは普通に動いている&クエリを減らせばリクエストが通るため、クエリに何らかの問題があるのではないかとにらんだ。

# 原因
結論から言いますと、Getのクエリ文字列が長すぎる場合に、.NETでは404.15というものを返しているということが分かった。

404の先入観から、これは想定外だった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256853/2a282f32-86aa-6c47-b0a4-2ddb5e95cdf5.png)

[公式ドキュメント](https://support.microsoft.com/ja-jp/help/943891/the-http-status-code-in-iis-7-0-iis-7-5-and-iis-8-0)にもそう記載があった。
> 404.15 - クエリ文字列が長すぎます。

どうやらクエリは2048バイトまでらしい。
https://docs.microsoft.com/en-us/aspnet/whitepapers/aspnet4/overview#0.2__Toc253429244
https://docs.microsoft.com/ja-jp/dotnet/api/system.web.configuration.httpruntimesection.maxquerystringlength?view=netframework-4.8

# 対処法
ググってみると、web.configに設定を記載すればよいとのこと。
> [IIS7以降でURLクエリ文字列が長いと404エラー - ゆれくるコール開発日誌](http://rcsc.hatenablog.com/entry/2015/01/14/123801)

しかし、.NET Coreの場合はweb.configがないのですが、作ってあげれば読み込んでくれるようです。

> [ASP.NET Core アプリケーションでも web.config をカスタマイズしたい - しばやん雑記](https://blog.shibayan.jp/entry/20190604/1559616472)

プロジェクト直下にweb.configファイルを作成し、以下の設定をします。

`maxQueryString`パラメータを増やしてあげればOKです。

```
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <security>
        <requestFiltering>
          <requestLimits maxQueryString="10000" />
        </requestFiltering>
      </security>
    </system.webServer>
  </location>
</configuration>
<!--ProjectGuid: {略}-->
```

これで再実行すると、長いクエリ文字列でも受け付けてくれ、ChromeでCORSが出なくなりました。
go.modってどこにおくのがいいのだろう

#go.modってどこにおくのがいいのか

 先日一からgoでサービスを作っていたのですが、go.modの置き場で迷ってしまい少し時間を無駄遣いした時に、意外と日本語の情報がなかったので残そうと思います。

#結論：ルートディレクトリに置く

　結論からいうと、プロジェクトのルートディレクトリにおくのが正解でした。
go modはもともと業務でも使っていたのである程度知識はあると思っていたのですが、いざ自分で初めから作るとなるとどこで `go mod init` するんだ？ってなってしまいました。勉強不足です。色々とググってみたのですが、あまりgo.modをおく場所に関する情報はなくて、自分で色々いじってみてなんとか解決しました。
　解決した後に１次ソースには当たっていなかったので（まず当たれという話ですが、、）１次ソースをみてみるとそう行った記述がありました。

```
A module is a collection of Go packages stored in a file tree with a go.mod file at its root.
```

ざっくり訳すと

```
モジュールとは、ルートディレクトリにgo.modがあるファイルツリーに保存されたGoのパッケージのコレクションである
```

という感じでしょうか。つまり、ルートディレクトリにgo.modを置くのが正解。ということでした。

#自分でいじってみて、もうちょっと突っ込んでみる

初め、自分は１次ソースに当たらずに自分で調べたりいじったりしたので、自分なりの理解も得られました。
###そもそも、 `go.mod` がルートディレクトリにないとどうなるのか
例えば、こんな構成のコードがあったとします。

```
Service
|
ー　handler
ー　model
ー　dao
```
こういう構成であれば、handlerからdaoをimportする時、こう書きたいですよね

```
import "Service/dao"
```
ですが、例えば、go.modをhandler,model,daoの各ディレクトリ内に置いてしまうと、コンパイルした時にhandler,model,daoが別の外部パッケージとして見なされてしまい、「gorootかgopath内にそんなパッケージないよ」といった旨のエラーが吐かれます。
（私はこれが、gorootやgopahtにないというエラー内容から、go.modの配置の問題であることに気づくのが遅れました。）
また、エディタ上でもgo.modを参照して依存を解決している場合、赤くなると思います。
これを、Service配下にgo.modを一つ置くようにすることでhandler,model,daoが同一パッケージないのものとみなされ、上のimport文で解決できるようになります。
　反対に、自分で作ったパッケージをサブパッケージみたいに外部パッケージとして読み込みたい場合は、上の例であれば、handler,models,dao内にgo.modをおいて、giuhubとかに上げて、

```
import "github.com/user_name/repository_name/..."
```
と書いてあげれば、良さそうなこともわかりました。

#最後に
go.modは自分が同一パッケージとして見なしたいもののルートディレクトリに置く、というのが正解でした。
それと、go.modの配置が悪くて依存が解決できない場合、コンパイルエラーのメッセージが

```
"package_name" is not in GOROOT
```
みたいに出ます。（goのバージョンで文言が変わる）なので、このエラーメッセージの時は、go.mod周りを疑うといいのかなと思いました。

何かを調べるときは、英語嫌がらずにまず１次ソースに当たるのがやはりいいですね、、

#参考文献
https://blog.golang.org/using-go-modules
Railsのtravel_toについてまとめた

## はじめに
日付関係のテストをしていたときに、`travel_to`を使うといいと教えてもらいました。
今回は、`travel_to`メソッドについてまとめていきます。

## travel_toとは
`ActiveSupport :: Testing :: TimeHelpers`のメソッドの一つです。

変更したい日時を渡すと、`Time.now`、`Date.today`、`DateTime.now`で返される日時を変更することができます。

## コード例

`travel_to do`と`end`で囲まれた部分の中だけ、時間が変更されています。</br>
コメント文のとおりに出力されました。

```rb
it 'puts date and time' do
  travel_to Time.zone.local(2020, 03, 16) do
    pp Date.today   # -> Mon, 16 Mar 2020
    pp Time.now     # -> 2020-03-15 15:00:00 +0000
    pp DateTime.now # -> Mon, 16 Mar 2020 00:00:00 +0900
  end
end
```

## SyntaxError
`Time.zone.local`に`08`または`09`を渡すと、`Invalid octal digit`でエラーとなります。</br>
そういうときは、下の例のように`0`をつけずに渡してあげればOKです。

```rb
travel_to Time.zone.local(2020, 8, 16) do

end
```

## 参考

[ActiveSupport::Testing::TimeHelpers](https://api.rubyonrails.org/v5.1.7/classes/ActiveSupport/Testing/TimeHelpers.html)

`ActiveSupport :: Testing :: TimeHelpers`には他にもメソッドがあるので参考にしてみてください！
Go 言語でスライスの要素をすべて展開して、インデックスの順序と値を出力する例 ( #go foreach slice all elements )

```golang
// https://golang.org/pkg/math/rand/

package main

import (
	"fmt"
)

func main() {

	cards := []string{"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}
	for i, card := range cards {
		fmt.Println(i, card)
	}

}

// e.g
//
// 0 2
// 1 3
// 2 4
// 3 5
// 4 6
// 5 7
// 6 8
// 7 9
// 8 10
// 9 J
// 10 Q
// 11 K
// 12 A

```

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/3027








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
WordPressに新着情報を表示するショートコード

# やりたいこと
- WordPressの新着情報リストを表示させたい
- グーテンベルグの機能では日付と記事タイトルしか表示できないので、カテゴリも含めたリストにしたい

##表示イメージ
<img width="707" alt="スクリーンショット 2020-03-15 1.18.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592738/419fa495-bbb8-9e96-163d-143bcfb829ed.png">


#出来上がったコード

```functions.php
function newsFunc() {
	global $wpdb;
	global $post;
	$news_links = '<ul class="news_links">';
	$news_post = get_posts(array('posts_per_page' => 5,'post_type' => 'post'));
	if($news_post){
		foreach($news_post as $post) : setup_postdata( $post );
		$cat_now = get_the_terms($post->ID, 'category');
		$cat_now = $cat_now[0];
		$now_id = $cat_now->slug;
		$now_name = $cat_now->name;
		$news_links .= '<li><span class="date">'.get_the_time('Y年m月d日').'</span>';
		if($cat_now){
			$news_links .= '<span class="cat '.$now_id.'">'.$now_name.'</span>';
		}
		$news_links .= '<a href="'.get_permalink().'">'.get_the_title().'</a></li>';
		endforeach;
	}
	$news_links .= '</ul>';
	wp_reset_postdata();
	return $news_links;
}
add_shortcode('newsLink', 'newsFunc');
```
```style.css
ul.news_links{
	list-style: none;
}
ul.news_links li{
	display: flex;
	padding: .5em 1em;
	border-bottom: #e4e4e4 1px solid;
	align-items: baseline;
}
ul.news_links li .date{
	width: 7rem;
	font-size: .8em;
	color: #555;
}
ul.news_links li .cat{
	width: 6rem;
	margin-right: 1rem;
	font-size: .7em;
	background-color: #666;
	color: #fff;
	text-align: center;
	padding: 2px 5px;
}
ul.news_links li a{
	width: calc(100% - 14rem);
}
@media screen and (max-width: 599px){
	ul.news_links li{
		flex-wrap: wrap;
	}
	ul.news_links li a{
		width: 100%;
		margin-top: 5px;
	}
}
```

#使い方
表示させたい箇所で`[newsLink]`というショートコードを追加します。

##カスタム投稿で使う場合
functions.phpの`'post_type' => 'post'`のpostを使用したいカスタム投稿名に変更してください。
表示するカテゴリーをカスタムタクソノミーにする場合は、`get_the_terms($post->ID, 'category')`のcategoryをカスタムタクソノミー名に変更してください。
Go 言語でスライス/配列をランダムな順番でシャッフルっする ( #go shuffle array / slice / cards example ) 

```golang
// https://golang.org/pkg/math/rand/

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	cards := []string{"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}
	cards4 := []string{}

	for i := 0; i < 4; i++ {
		cards4 = append(cards4, cards...)
	}

	rand.Seed(time.Now().UnixNano())
	rand.Shuffle(len(cards4), func(i, j int) { cards4[i], cards4[j] = cards4[j], cards4[i] })

	fmt.Println(cards4)
	// [7 3 10 7 10 9 A 8 K 9 J 10 10 A K Q K 5 K Q 6 J 3 8 2 6 2 7 Q J 8 3 J 6 2 8 4 9 A 9 2 4 4 3 5 A 4 6 5 Q 7 5]
	// [5 2 K K K 10 4 J 9 8 A 3 3 5 4 Q 9 3 4 J 7 6 5 Q 10 J A A 2 7 9 6 7 8 8 7 9 K Q 2 J 5 10 2 4 Q 8 A 6 6 10 3]
}

```

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/3026








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
[Rust] とりあえずHello World!してみた

会社の人が学ぶ価値がすごいと言っていたので、
とりあえず Hello World! してみました。

## インストール

```shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

こんなのが表示される。

```shell
Welcome to Rust!

This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.

...

Current installation options:


   default host triple: x86_64-apple-darwin
     default toolchain: stable
               profile: default
  modify PATH variable: yes

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation

```

デフォルトの1を選択する。


```shell
Rust is installed now. Great!

To get started you need Cargo's bin directory ($HOME/.cargo/bin) in your PATH
environment variable. Next time you log in this will be done
automatically.

To configure your current shell run source $HOME/.cargo/env
```
完了！

## 動作確認

```shell
source $HOME/.cargo/env
rustc --version
```
```shell
rustc 1.42.0 (b8cedc004 2020-03-09)
```
OK！

## Hello World!してみる

ファイルを用意して`rustc`コマンドでコンパイルする。

```rust:hello.rs
fn main() {
    println!("Hello World!");
}
```

```shell
rustc hello.rs
```

出力されたバイナリファイルを実行する。

```shell
./hello
```

すると、、、

```
Hello World!
```

簡単！！！


## まとめ
実行環境の構築はびっくりするほど簡単でした。
学習コストは高いがそれに見合うものがある
とのことなので挑戦してみようかと思います。

## 参考
https://www.rust-lang.org/ja/learn/get-started
【Docker】データボリュームをバックアップ→リストア

データが入ったDBがあると仮定して話を進めます。

##ボリュームと紐づいているコンテナの名前を確認
```terminal
$ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
7b6a79314721        sample-app_web       "/bin/sh -c 'rm -f t…"   5 minutes ago       Up 5 minutes        0.0.0.0:3000->3000/tcp   sample-app_web_1
2ed21c2aac12        postgres            "docker-entrypoint.s…"   5 minutes ago       Up 5 minutes        0.0.0.0:5434->5432/tcp   sample-app_db_1
```
`NAMES`を参照。今回の場合は`sample-app_db_1`

##コンテナをストップ
```terminal
$ docker-compose stop
```

##バックアップ
```terminal
docker run --rm --volumes-from sample-app_db_1 -v `pwd`:/backup busybox tar cvf /backup/backup.tar /var/lib/postgresql/data
```
Postgresqlの場合の例です。
`sample-app_db_1`の部分に、先ほどのステップで確認したコンテナ名を設定
mysplの場合`/var/lib/postgresql/data`の部分を`/var/lib/mysql`に変更

<details><summary> (mysqlの場合)</summary><div>

 ```terminal
$ docker run --rm --volumes-from sample-app_db_1 -v `pwd`:/backup busybox tar cvf /backup/backup.tar /var/lib/mysql
```
</div></details>

##コンテナとボリュームを削除→コンテナを再作成
```terminal
$ docker-compose down --volumes
$ docker-compose up -d
```

##コンテナをストップ
```terminal
$ docker-compose stop
```

##リストア
```terminal
$ docker run --rm --volumes-from sample-app_db_1 -v `pwd`:/backup busybox tar xvf /backup/backup.tar
```
<details><summary>(mysqlの場合)</summary><div>
同じ

```terminal
$ docker run --rm --volumes-from sample-app_db_1 -v `pwd`:/backup busybox tar xvf /backup/backup.tar
```
</div></details>

##最後に
本当はこの方法より、[SQLによるダンプ](https://www.postgresql.jp/document/9.6/html/backup-dump.html)でバックアップを取るほうが望ましいらしいです。

まだ検証できていないので、興味がある方はご自身で調べてみてください。

##参考
- [【Docker】具体例で理解するデータボリュームのバックアップ・リストア方法](https://nishinatoshiharu.com/docker-volume-backup/)
- [Dockerのデータボリュームのリストアがうまくいかない](https://teratail.com/questions/246606)
Go 言語で配列(Slice)からランダムに文字列を選ぶ ( #go random select string in slice )

```golang
// https://golang.org/pkg/math/rand/

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	cards := []string{"A", "B", "C"}

	rand.Seed(time.Now().UnixNano())

	for i := 0; i < 10; i++ {
		num := rand.Intn(len(cards))
		fmt.Println(cards[num])
	}
}

// result

// e.g

// C
// C
// C
// C
// C
// B
// B
// C
// B
// C

```

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/3024








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Go 言語で スライスを合体させてトランプの組み合わせを作る ( #go join multiple string slice n times )

```go
// https://golang.org/pkg/math/rand/

package main

import (
	"fmt"
)

func main() {
	cards := []string{"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}
	cards4 := []string{}

	for i := 0; i < 4; i++ {
		cards4 = append(cards4, cards...)
	}

	fmt.Println(len(cards4)) // 52
	fmt.Println(cards4)      // [2 3 4 5 6 7 8 9 10 J Q K A 2 3 4 5 6 7 8 9 10 J Q K A 2 3 4 5 6 7 8 9 10 J Q K A 2 3 4 5 6 7 8 9 10 J Q K A]
}

```

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/3025








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
【ふくだ学習録】アプリ制作part14【41日目】

# ふくだ学習録とは？
ふくだが学習したことの備忘録。
目に見える形で残すことによってやる気を出す個人的な作戦です。
他人に見せるように書いているわけではないので、すごく読みにくいです。

### 読了した本
[データベースエンジニア養成読本 [DBを自由自在に活用するための知識とノウハウ満載!]](https://www.amazon.co.jp/dp/4774158062/ref=cm_sw_r_tw_dp_U_x_FPphEbQFPPQRM )
[ゼロから作るDeepLearning](https://www.amazon.co.jp/dp/4873117585/ref=cm_sw_r_tw_dp_U_x_y3UiEbF3P6EG7)
[PHPフレームワーク CakePHP 3入門](https://www.amazon.co.jp/dp/4798048577/ref=cm_sw_r_tw_dp_U_x_.YIjEbS1K4JY2)
[SQLアンチパターン](https://www.amazon.co.jp/dp/4873115892/ref=cm_sw_r_tw_dp_U_x_XlokEbJQK2N7P )
[Docker入門](https://www.amazon.co.jp/dp/480071091X/ref=cm_sw_r_tw_dp_U_x_xVlmEbN8ZTHZK)
[PHPフレームワーク Laravel入門](https://www.amazon.co.jp/dp/4798052582/ref=cm_sw_r_tw_dp_U_x_zzeyEbJBSQ5Y0 )


### 今読んでいる本


# アプリ制作

### 定期ジョブの作成
対象サイトに対して、定期的にスクレイピングを実行したかったので実装していく。
今回の環境（pythonでscrapy）で実装するとすると、下記の２パターンでできそうだった。

**①scheduleライブラリをimportし、pyrhonプログラムとして、定期的にジョブを実行する。**
**②cronに定期ジョブとして登録しておいて、、pythonコマンドをLinux側から呼び出す。**

今回は②を採用して実装することにする。理由としては下記の2つ。

**・cronに登録する方法であれば、言語や環境が変わっても使用できるので、汎用性が高そう。（Linuxベースなら基本OKの認識）**
**プロセスを常に起動しておく（pythonを常に実行させておく）のはメモリ的によくない（はず）。**
**・scrapyに用意されている「scrapy crawl 〇〇」というコマンドで、スクレイピング実行したかったから。（というかソースコード読み解いてパッチ当てるのがめんどくさかった）**

まぁcronいじれるようになったほうが良さそうなので、とりあえずは②で進めていく。

参考にするのは下記記事
[Pythonでプロセスを監視して終了したらgmailを使ってメール送信する(Python3版)](https://sekailab.com/wp/2018/02/03/watch-process-to-send-gmail-with-python3/)

### 現在のcronの確認

まずは、今のcron設定の確認をする。
alpineLinuxではcron(crontab)はデフォルトで下記の設定が書いてあった。

```text:/etc/crontabs/root
# do daily/weekly/monthly maintenance
# min   hour    day     month   weekday command
*/15    *       *       *       *       run-parts /etc/periodic/15min
0       *       *       *       *       run-parts /etc/periodic/hourly
0       2       *       *       *       run-parts /etc/periodic/daily
0       3       *       *       6       run-parts /etc/periodic/weekly
0       5       1       *       *       run-parts /etc/periodic/monthly
```

### cron設定の変更

下記の記事を参考に設定していく。

[docker alpineでcronスクリプトを実行する](https://akamist.com/blog/archives/3565)
[Docker + Cron環境を実現する３つの方法](https://qiita.com/YuukiMiyoshi/items/bb7f14436d60d4bd8a8b)
[Supervisorで簡単にデーモン化](https://qiita.com/yushin/items/15f4f90c5663710dbd56)

# 今日の一言
Linuxの機能とか設定するのまぁまぁ時間取られるけど、めちゃめちゃおもろい。
楽しみながらペース上げてこ。池田エライザと柔道したい！
【Vue.js】ファイル名に連番を付けていく方法

vue-awesome-swiperを使うときにファイル名をバラバラにせず、連番にすればスッキリできるのではと思いそのやり方をまとめてみました。

開発環境はNuxt.js + Vuetifyにvue-awesome-swiperを使った状態です。

[Nuxt.jsにvue-awesome-swiperを導入し、カルーセルを表示させてみる](https://qiita.com/hiroyukiwk/items/4ead9e150579363d50bb)
[【Nuxt.js】imgファイルの指定方法について](https://qiita.com/hiroyukiwk/items/a26e767d193ef8d9155b)
[【Nuxt.js】Universalモードで「window is not defined」エラーが出たときの対処法](https://qiita.com/hiroyukiwk/items/a3ea08bc50e15384f9bb)


# 変数を宣言する

```javascript
const items = []
```

# ループを作る
```javascript
for (let i=1; i<=5; i++) {
//ここに処理を入力する
}
```
# ループ内の処理を記入する
itemsに数字を足していく処理が必要なのでpushを使用します。

```javascript
items.push({
  no: i,
  title: 'title' + i,
  slideimage: `/images/home/slide${i}.jpg`
})
```
※１.画像ファイルの部分ですがシングルクォートで囲っているのではなくバッククォートで囲っている点注意。
※2.スライドショー等で見せたいような画像はコンパイルの時間も減るでstaticに格納するほうがおすすめです。

ただしこのままだとファイル名に変数iによる連番を付加することができますが、ファイル名の連番部分の前の0を付けた"slide01.jpg"のようなフォーマットだと、変数のiが一桁のときに前0を付加する処理が必要になります。

# 数値のゼロを埋め、桁を揃える
zeroPadding方を応用します。

```javascript
zeroPadding(index, size) {
  let tmp = index + ''
  while (tmp.length < size) tmp = '0' + tmp
  return tmp
}
```
# まとめる
上記をまとめたコードになります。

```index.vue
<template lang="pug">
	section.py-12
		v-layout(column align-center justify-center)
			v-flex(xs12 sm4 class="my-4")
        swiper(:options="swiperOption")
          swiper-slide(v-for="(item, index) in items" :key="index")
            img(:src="item.slideimage" :alt="item.title" :id="item.no")
</template>

<script>
export default {	
	data () {
		const items = []	
		for (let i=1; i<=5; i++) {
      items.push({
        no: i,
				title: 'title' + i,
        slideimage: `/images/home/slide${this.zeroPadding(i, 2)}.jpg`
			})
		}
		return {
			items,
		}
	},
	methods: {
    zeroPadding(index, size) {
      let tmp = index + ''
      while (tmp.length < size) tmp = '0' + tmp
      return tmp
    }
  }
}
</script>
```

これでファイルの連番については実装できました。
このやり方だと連番はできたのですが個別ごとのテキスト名とかの設定でできないので
複数の項目があるときはjsonで読み込んでv-forで回したほうがいいかもしれませんね。

参考：
[数値のゼロ埋め（桁を揃える）](http://shanabrian.com/web/javascript/zero-padding.php)
[第一回 Vue.jsでWebアプリをつくろう！](https://www.monster-dive.com/blog/web_creative/20180608_001789.php)

##### 追記

`String.prototype.padStart()`をつかったほうがいいという意見をいただいたので使った方法で書き換えてみました。

```javascript

<script>
export default {	
	data () {
		const items = []	
		for (let i=1; i<=5; i++) {
      items.push({
        no: i,
				title: 'title' + i,
        slideimage: `/images/home/slide${this.setDigits(i, 2)}.jpg`
			})
		}
	},
	methods: {
		setDigits(number, digits) {
			const number_string = String(number).padStart(digits, '0');
    return number_string;
		}
	}
}
</script>
```
Laravel+SendGrid WebAPIでメール送信

#1.はじめに
LaravelでSendGrid Web APIを使ってメール送信する方法を記載していきます!
メール本文はbladeで書いて、様々なメールのテンプレートを利用できるようにします。


#2.環境

- Laravel Framework 6.0.4
- "sendgrid/sendgrid": "^7.4"

#3.SendGridのコンソールで、API Keyを発行

SendGridにログイン（アカウントがない場合は作成）し、
[https://app.sendgrid.com/settings/api_keys](https://app.sendgrid.com/settings/api_keys)にアクセスします。

[Create API Key]をクリックし、APIキーを作成しましょう。

※APIキーは一度しか表示されないので注意!

#4.パッケージのインストール

laravel側で、SendGridのパッケージをインストールしましょう。

```bash:terminal
composer require sendgrid/sendgrid
```

#5.envファイルにAPIキーとかを追記

APIキーや送信元アドレスなどを記載しておきます。

```env:.env
#sendgrid 
SENDGRID_API_KEY="ここにAPIキーを記載する"
FROM_EMAIL="ここに送信元アドレス"
FROM_NAME="ここに送信元の名前"
```
#6.処理を書く

controllerやmodelなどにメール送信のコードを書きます。
今回はシンプルにRequestのデータからユーザのデータを取得してメール送信する例です。

※下記ではメール送信に失敗した際の処理をLogとして残していますが、要らない場合は削除してください。

```php

use Exception;
use Log;

~

public function sendMail(Request $request)
    { 
        $data = $request->all();

        $email = new \SendGrid\Mail\Mail();
        $email->setFrom(getenv('FROM_EMAIL'), getenv('FROM_NAME'));
        $email->setSubject("○○○○○○○○○○○○通知");
        $email->addTo('送信先アドレス');

        $sendGrid = new \SendGrid(getenv('SENDGRID_API_KEY'));
        $email->addContent(
            "text/plain",
            strval(
                view(
                    'emails/templates/notificationMail',
                    compact('data')
                )
            )
        );
        $email->addContent(
            "text/html",
            strval(
                view(
                    'emails/templates/notificationMail',
                    compact('data')
                )
            )
        );
        try {
            $sendGrid->send($email);
            return true;
        } catch (Exception $e) {
            Log::debug($e->getMessage());
            return false;
        }
    }

```

#7.メール本文をbladeで書く
6.のコードだと、「emails/templates/notificationMail.blade.php」をテンプレートとして指定しています。

viewをメールの体裁ごとに作成しておけば、便利だと思います。

通常のreturn viewと同様にcompactで渡したデータを好き放題表示しましょう！

```php:notificationMail.blade.php

<div>
    <p>
        〇〇〇通知です<br>
        以下詳細をご確認ください。
    </p>
    
    <div>
        <p>-------------------------------------------------------</p>
        <div>お名前：{{ $data->name }}</div>
        <div>メッセージ：{{ $data->message }}</div>
　　　　 <p>-------------------------------------------------------</p>
    </div>
  
</div>

```

#8.宛先を複数人にしたいとき

宛先が複数人の場合は、「$email->addTo('送信先アドレス');」をforeach等で追加分実行すればできます。

同じアドレスが複数あるとBad Requestになってしまいメールが送れないので、配列にして重複を除いてから送信するとよいと思います！

```php:example

$emails = array('test1@example.com', 'test2@example.com','test3@example.com');

$uniqueEmails = array_unique($emails);
$alignedUniqueEmails = array_values($uniqueEmails);

```

#9.まとめ

あとは、メールを送信したいタイミングで関数を実行するだけです。
関数はどこかに汎用的に使えるようにしておくといいですね！

SendGrid社に感謝です。
アリガトウゴザイマス！
Go lang / rand.Seed(time.Now().UnixNano()) used as value / #go

```go
// https://golang.org/pkg/math/rand/

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	// NG
	seed_result := rand.Seed(time.Now().UnixNano())

	// OK
	// Seed does not need return value
	// rand.Seed(time.Now().UnixNano())

	fmt.Println(rand.Int())
}
```

Seed生成した値を使い回すのではなく、一回だけ設定すれば良いみたいだ。なので帰り値は要らない。

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/3022








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Go lang で1桁のランダムな数値を生成する / rand.Intn(9) / #go

```golang
// https://golang.org/pkg/math/rand/

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	rand.Seed(time.Now().UnixNano())

	for i := 0; i < 100; i++ {
		fmt.Println(rand.Intn(9))
                // e.g exclude zero
                // fmt.Println(1 + rand.Intn(9-1))
	}

}

// Result example
//
// 2
// 7
// 1
// 0
// 2
// 8
// 3
// 1
// 2
// 4
// 3
// 3
// 3
// 4
// 4
// 7
// 3
// 2
// 6
// 7
// 2
// 4
// 1
// 4
// 4
// 2
// 1
// 2
// 1
// 7
// 1
// 0
// 8
// 1
// 4
// 3
// 5
// 7
// 0
// 7
// 6
// 3
// 8
// 4
// 8
// 4
// 1
// 8
// 2
// 0
// 2
// 4
// 1
// 6
// 7
// 7
// 1
// 1
// 2
// 3
// 5
// 5
// 6
// 5
// 2
// 4
// 5
// 6
// 2
// 4
// 6
// 8
// 2
// 7
// 1
// 3
// 8
// 8
// 6
// 3
// 8
// 0
// 0
// 3
// 1
// 8
// 6
// 1
// 5
// 5
// 1
// 5
// 5
// 1
// 5
// 5
// 2
// 1
// 3
// 7

```

`rand.Intn()` に上限の値を与えれば良いみたいだ。



# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/3023








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Mac ネイティブのGitからHomebrewでインストールしたGitに切り替えた話

# 目的

- Git本体のバージョン管理をHomebrewで行いたくていろいろやった話をまとめる
- 書いている内容は単純にHomebrewでGitをインストールして使用するものと変わらない

# 実施環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.3) |
| ハードウェア | MacBook Pro (16-inch ,2019) |
| プロセッサ | 2.6 GHz 6コアIntel Core i7 |
| メモリ | 16 GB 2667 MHz DDR4 |
| グラフィックス | AMD Radeon Pro 5300M 4 GB Intel UHD Graphics 630 1536 MB |

# 実施方法概要

1. HomebrewでGitのインストール
1. パスを通し
1. バージョン確認 

# 実施方法詳細

1. HomebrewでGitのインストール
    1. 下記コマンドを実行してHomebrewをインストールする(すでに実施済みの場合は飛ばす。)

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

    1. 下記コマンドを実行してHomebrewでGitをインストールする。

        ```terminal
        $ brew install git
        ```

1. パス通し
    1. 下記コマンドを実行してHomebrewにてインストールしたGitのバージョンを確認する。

        ```terminal
        $ brew info git | grep stable
        ``` 
    1. 下記コマンドを実行してHomebrewのgitのパスを通す。(X.XX.XはみなさんのHomebrewでインストールしたgitのバージョン)

        ```terminal
        $ echo "export PATH=/usr/local/Cellar/git/X.XX.X/bin:$PATH" >> ~/.bash_profile
        ```

    1. 下記コマンドを実行して.bash_profileを再読み込みする。

        ```terminal
        $ source ~/.bash_profile
        ```

1. バージョン確認
    1. 下記コマンドを実行してGitのバージョンがHomebrewでインストールされたものになっているのか確認する。

        ```terminal
        $ git --version
        >git version X.XX.X
        ```
ファイル一覧生成マクロ

Option Explicit

Sub ファイル一覧生成()

    '参考サイト：http://blog.jmiri.net/?p=1763

    Call setFileList(ThisWorkbook.Path)
    

End Sub

Sub setFileList(searchPath)

    Dim startCell As Range
    Dim maxRow As Long
    Dim maxCol As Long

    'データ設定開始位置
    Set startCell = Cells(2, 1)
    startCell.Select
    
    'データ設定範囲の初期化
    maxRow = startCell.SpecialCells(xlLastCell).Row
    maxCol = startCell.SpecialCells(xlLastCell).Column
    Range(startCell, Cells(maxRow, maxCol)).ClearContents
    
    'カレントフォルダ配下のファイル一覧取得
    Call getFileList(searchPath)
    
    startCell.Select
    
End Sub

Sub getFileList(searchPath)

    Dim FSO As New FileSystemObject
    Dim objFiles As File
    Dim objFolders As Folder
    Dim separateNum As Long
    
    Dim cur_BookName, fpath, fname

    '現在のブック名を取得
    cur_BookName = ActiveWorkbook.Name

    'サブフォルダ取得
    For Each objFolders In FSO.GetFolder(searchPath).SubFolders
        Call getFileList(objFolders.Path)
    Next
    
    'ファイル名の取得
    For Each objFiles In FSO.GetFolder(searchPath).Files
    
        separateNum = InStrRev(objFiles.Path, "\")
        
        'パスとファイル名を取得
        fpath = Left(objFiles.Path, separateNum - 1)
        fname = Right(objFiles.Path, Len(objFiles.Path) - separateNum)
        
        '現在のブックを除く
        If cur_BookName <> fname And "~$" & cur_BookName <> fname Then
        
            'パス
            ActiveCell.Value = fpath
            'パスにリンクを挿入
            ActiveSheet.Hyperlinks.Add Anchor:=Selection, Address:=fpath, TextToDisplay:=fpath
            
            'ファイル名
            ActiveCell.Offset(0, 1).Value = objFiles.Name
            
            '種類
            ActiveCell.Offset(0, 2).Value = objFiles.Type
            '生成日時
            ActiveCell.Offset(0, 3).Value = objFiles.DateCreated
            '更新日時
            ActiveCell.Offset(0, 4).Value = objFiles.DateLastModified
            'サイズ（KB)
            ActiveCell.Offset(0, 5).Value = Format((FileLen(objFiles) / 1024), "#.0")

            'ファイル名にリンクを挿入
            ActiveCell.Offset(0, 1).Select
            ActiveSheet.Hyperlinks.Add Anchor:=Selection, Address:=fpath & "\" & fname, TextToDisplay:=fname

            ActiveCell.Offset(1, -1).Select
        
        End If
        
    Next
    
End Sub