OmniAICreator/Qiita-1.07M huggingface dataset:
PostgreSQLでHerokuへプッシュがうまくいかないときに試したこと

以前の記事で、Herokuへのデプロイ時にPostgresql関連のエラーが出て苦戦したことがありました。

こちら↓
[Herokuデプロイ時のエラー記録](http://nojishio-notes.hatenablog.com/entry/2018/03/26/231821)

そのときはPostgresqlの代わりにmysqlで代用したことでheroku openさせることができました。


今回はHerokuでPostgresqlを使い、同じようなエラーは出たけど、それも解決できたので投稿します。  
既出ですが自分の備忘録も兼ねてめもめも。( 'u')φ....
<br>
  
  
**作業環境**  

* Rails　5.0.1
* Ruby　2.5.0
* mysql2　0.4.10　(ローカル環境)　　



# エラー内容:Gem::LoadError: Specified 'postgresql' for database adapter, but the gem is not loaded.
## (エラー発生までの経緯)Gemfileにpgを追加


まず、自分の作業経緯を振り返る。  

1：Gemfileにpgを追加


```r:Gemfile
gem 'pg', group: :production
```

`group: :production`で本番環境はPostgresqlを使うよう指定しています。

2： `bundle install`を実行

3：database.ymlに以下の記述を追加

```database.yml
production:
  <<: *default
  adapter: postgresql
  encoding: unicode
  pool: 5
```
※もともとのproduction:~の記述箇所を上の内容に書き換える
※ymlファイルでは改行場所やスペースなどでエラーが出ることがあるので、既存の記述と見比べるなどして特に気を付ける。

<br>
4：この状態でherokuにプッシュまで行う  
`git add .`  
`git commit -m "コメント"`  
`heroku create`(初回の場合のみ)  
`git push heroku master`  **ここでエラー発生！**

<br>
5 ：発生したpgエラー

```
remote:        Gem::LoadError: Specified 'postgresql' for database adapter, but the gem is not loaded. Add ｀gem 'pg'｀ to your Gemfile (and ensure its version is at the minimum required by ActiveRecord).
```

## 対処：pgのバージョンを0.19.0に指定

参考記事。バージョン指定がポイントでした。
<https://qiita.com/Hijiri-K/items/51d53c0512a2ef455da6>

Gemfileでpgの記述をバージョン指定して、以下のように書き換えました。

```r:Gemfile
gem 'pg', '~> 0.19.0', group: :production
```
これで`bundle install`

これで再度herokuにプッシュまで行う  
`git add .`  
`git commit -m "コメント"`    
`git push heroku master`  **うまくいきました！！**

<br>
これで
`heroku run rake db:migrate`実行  
`heroku open`でアプリを開く、で終了。

-----------------------------
ちなみに
`bundle install`したときの画面で

```
Fetching pg 0.19.0 (was 1.0.0)
Installing pg 0.19.0 (was 1.0.0) with native extensions
```


pgは、もともと1.0.0だったけど0.19.0にバージョン下げていたようですがうまくいきました。
バージョンの違いによるエラー？

# まとめ

**成功した手順**  

1. pgのバージョンを0.19.0指定で記述  
* database.yml書き換え  
* git addとcommit

でPostgresqlを使ってherokuにプッシュが成功。
<br>
ちなみに私はこのあとの`heroku run rake db:migrate`実行で[別のエラー](https://qiita.com/nojishio/items/0595695c8a8572165ccf)が出たので、
別記事に書いておきました。


Hatenaでもエラー備忘録書いてます。
<http://nojishio-notes.hatenablog.com/archive/category/%E3%82%A8%E3%83%A9%E3%83%BC%E5%82%99%E5%BF%98%E9%8C%B2>
Qiitaでも記事増やしていきたいです。
ここまで読んでくださり、ありがとうございました^^
CentOS 7.4でホームディレクトリに勝手にperl5というディレクトリが作られるのを防ぐ

# 現象

CentOS 7.4で、ホームディレクトリに`perl5`というディレクトリが作られる。消しても、再度ログインするか、シェルを立ち上げるとまた作られてしまう。

```shell-session
$ ls
perl5             # perl5というディレクトリがある
$ rm -rf perl5    # perl5を消す
$ ls              # 消えた状態
$ 
$ bash            # bashを起動
Attempting to create directory /home/username/perl5 # 勝手に作る
$ ls
perl5
```

# 原因

これは、`perl-homedir`パッケージがインストールされているから。

```shell-session
$ yum list installed |grep perl-homedir
perl-homedir.noarch                    1.008010-4.el7                  @base  
```

# 対応方法

## perl-homedirをアンインストール

perl-homedirが原因なので、それをアンインストールしてしまえば良い。

```shell-session
$ sudo yum remove perl-homedir
$ rm -rf perl5 
$ bash # シェルを立ち上げても作られない
$ 
```

## .perl-homedirに`PERL_HOMEDIR=0`を設定する

`$HOME/.perl-homedir`に、`PERL_HOMEDIR=0`と記述しておくと、`perl5`が作られなくなる。

```shell-session
$ echo PERL_HOMEDIR=0 > .perl-homedir    # $HOME/.perl-homedirを作成
$ cat .perl-homedir
PERL_HOMEDIR=0
$ rm -rf perl5
$ bash
$ ls    # perl5が作られていない
$
```

# まとめ

CentOS 7.4において、ホームディレクトリに`perl5`というディレクトリが作られるのは`perl-homedir`というパッケージが原因であり、それをアンインストールするか、ホームディレクトリに`.perl-homedir`を作り、`PERL_HOMEDIR=0`と書いておけば作られなくなる。

# 参考

* [[CentOS] attempting to create directory /root/perl5](https://lists.centos.org/pipermail/centos/2014-July/144666.html)
* [How to disable automatic PERL5LIB setting in CentOS7.4](https://stackoverflow.com/questions/47873097/how-to-disable-automatic-perl5lib-setting-in-centos7-4)
HTML＆CSS　重要知識まとめ

プログラミングの基礎であるhtmlとcssに関する知識まとめ

#htmlまとめ

　・DOCTYPE宣言
　まず文書型を宣言しなければいけない
html5を使用する場合、頭に
　<！DOCTYPE html>を付ける


　・headとbodyの違い
  <head>と<body>は大まかに言うと、｢閲覧者に見えない部分を書くスペース」と「閲覧者に見える部分を書くスペース」といった感じの違い

　◎head部分に書き込むべきタグ
①titleタグ
　ページのタイトルを書く部分。ここに書き込んだ内容がタブに表示される。

②linkタグ
　画像やファイルなど参照先のリンクやファイル名を書く。
　<link **rel**=リンク先のリソースとの関係　**href**=URL>
ちなみに、relの後にはstylesheetやcanonicalなどと書く。canonicalと書けば、複数の内容が重複するページが発生した時、検索エンジンからのページ評価が分散するのを防ぎます。SEO対策の観点からも重要です。

③metaタグ
　ページの内容や文字形式を規定
　<meta charset="utf-8>は書くクセつけておこう

　◎bodyタグに書き込むべきタグ
　
①見だし<h1>~<h6>
 数字が小さければ小さいほど重要度up
　<p>タグ
　段落を意味する。

②aタグ
　リンクの出発点と到達点を指定する
　例）<a href="メールアドレス>メール</a>

③div,spanタグ
　どちらのタグもページの区分けをしてくれるタグだが、両者には少し違いがある。具体的には「指定できる内容」にちがいがある。
･divタグは、幅と高さが指定できる
･spanタグは、色や大きさを指定できる
divで大枠を指定し、spanで小さな調整をするといったところだろうか

④inputタグ
　フォームを作る際必要不可欠なタグ。
例）
    ```<input type="password>
    <input type="submit>
   ```

　このタグを使えば、送信ボタンを作成したり、バリデーションを効かせたりできるなど何かと便利。

⑤selectタグ
　セレクトボックスを作成。選択肢にはoptionタグを用いる。nameもしっかり決めておこう。
例）

```html:qiita.rb
<select name="地名">
<option value="東京">東京</option>
<option value="大阪">大阪</option>
<option value="福岡">福岡</option>

```

#CSSまとめ

CSSは見た目がしょぼいHTMLに付け加えることで、ウェブページの見た目を良い感じにしてくれる。
CSSはHTMLに直接書くことができる

･borderタグ
　borderは文字周辺に下線や括弧を付ける時に用いる。
borderと書いただけでは文字を四角で囲むような格好になるため、下線の時はborder-bottomといったように、線を引く位置を指定する必要がある。
太さや色、線のタイプなども同時に記述しよう。
例）

```css:
 border:5px solid red;
```

･marginとpadding

混同しがちな2つのタグ。
marginは、borderの内側に余白を作る、paddingは外側に余白を作るイメージ。
dockerイメージのダウンロードが途中で停まってしまった時に再開させる

イメージが重い && 通信が遅い場合とかに、以下のような状態で止まってしまうことがある。

<img width="782" alt="スクリーンショット 2018-08-05 21.07.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/121811/0e5528bb-3484-629b-2aad-2f1664b9f5f2.png">

wifiを一旦切って、戻すと、
こんな感じでリトライし始める。

<img width="336" alt="スクリーンショット 2018-08-05 21.06.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/121811/67b88c05-6452-8a2f-437f-8619387acd93.png">

以上。
OpenWeatherMap APIを呼ぶPythonコードをclass化してunittestしてみる

# はじめに
PythonとUnittestの勉強中。
ためしに、Class作って、Unittestしてみた。
selfだらけで、自信ない。
どなたかコメントもらえるとうれしいです。

# コード
jsonのデータを取得する部分とそこから温度、湿度を取り出す部分とに分けてみた。
オブジェクトを生成して、違うタイミングでまたデータをとることも想定して、jsonデータの取得は`__init__`ではやらないことにした。なんとなく都市名で初期化してみた。

```python:openweather.py
import requests
import json

class OpenWeatherMap():
    """Get weather from OpenWeatherMap API                                           
    """

    def __init__(self,city):
        """Initialize city                                                           
        """
        self.city = city
        self.api_key = "xxx"
        self.api = "http://api.openweathermap.org/data/2.5/weather?units=metric&q={c\
ity}&APPID={key}"
        self.url = self.api.format(city = self.city, key = self.api_key)

    def get_json_weather(self):
        """Get json weather data                                                     
        """
        response = requests.get(self.url)
        data = response.json()
        # jsonText = json.dumps(data, indent=4)                                      
        # print(jsonText)                                                            
        return data

    def get_temp(self, data):
        """Get temperature data from json data                                       
        """
        temp = data['main']['temp']
        return temp

    def get_humi(self, data):
        """Get Humidity data from json data                                          
        """
        humi = data['main']['humidity']
        return humi


if __name__ == '__main__':
    owm_kobe = OpenWeatherMap("Kobe")
    json_weather = owm_kobe.get_json_weather()
    print(owm_kobe.get_temp(json_weather))
    print(owm_kobe.get_humi(json_weather))
```


# テスト
何をテストすべきか悩ましいけど、それっぽい温度になるかだけ見ることにした。APIでちゃんとアクセスできるかはまた別途テストすべきなんかもしれない。テストというよりもエラー処理すべきなのかもしれない。よくわからん。

```python:tests/test_openweather.py
import unittest
import openweather

class TestCalc(unittest.TestCase):
    def setUp(self):
        self.owm_kobe = openweather.OpenWeatherMap("Kobe")
        self.json_weather = self.owm_kobe.get_json_weather()

    def test_get_temp(self):
        temp = self.owm_kobe.get_temp(self.json_weather)
        print(temp)
        self.assertTrue(temp < +50)
        self.assertTrue(temp > -10)

    def test_get_humi(self):
        humi = self.owm_kobe.get_humi(self.json_weather)
        print(humi)
        self.assertTrue(humi < 100)
        self.assertTrue(humi > 0)

    def tearDown(self):
        del self.owm_kobe
```


# おわりに
そこそこ、それっぽいコードが動いてよかった。
ただ、よくわからないことが沢山。

エラー処理のこと、いまいちわかってない。
Pythonのスコープのこと、いまいちわかってない。
どこまでdelすべきかよくわかってない。
ちゃんと、本読んで勉強しよっかなぁ。
"Failed to resolve: com.android.support:appcompat-v7:28.+"って出たときの解決法

Android Studio 2.3.3で新しくプロジェクトを作るとこのエラーが出たので簡単な解決方法をメモしておきます。意味も分からず勝手に数字いじってたので使うときは自己責任で...(27にしてもエラー出たので26です）

##1.**build.gradle(Module:app)**を開く
    compileSdkVersion 26
    buildToolsVersion "26.0.1"
    targetSdkVersion 26
    compile 'com.android.support:appcompat-v7:26+'
上記のように書き換え
##2.画面の表示に従う
Javascriptの正規表現：入力フォームでよく使うやつ

最近よく見る正規表現。JavascriptでもPythonでも、スクレイピングやクローリングをする時に正規表現で指定して取っていく。

今回はJavascriptで簡単な正規表現を使ったので、まとめてみる。と言っても４つだけ。

#正規表現入門

そもそも正規表現は以下のように表す。

```javascript
var hoge = /"pattern"/;
```
スラッシュの中にパターンを書いてそれをtest,match,replaceなどをする。

##よく使うやつ
`^`: これは文頭ということ
`$`: 逆にこれは文末
`\`: 探したいやつの前に置く。下に例あり。
`\d`: 数字。まあ%dとかで使うのでなんとなくわかる。
`\w`: [a-zA-Z_0-9]
その他にも山ほどあるが、今回はこれで足りるので、これくらいに。
実際に使用してみる。
##郵便番号

```javascript
var postcode = /^\d{3}-\d{4}$/;
```
最初見たときはよくわからなかったのだが、正規表現を理解すればめちゃくちゃ簡単。
スラッシュの中に書くので//←これは必須
文頭からスタートにしたいので、`^`を入れる。
`\d{3}`で[0-9]の文字が３つということ。同様に\d{4}は数字４文字。
最後に`$`を付けておしまい。`-`は郵便番号なので付けておく。

##E-mail

```javascript
var email = /^\w+\@\w+\.\w+/;
```
@前までは任意の文字が入るので`\w+`と記入。`+`は前の文字の連続。今回は\wが何回でも入るということ。
それ以外はもう見ればわかるでしょう。

##URL

```javascript
var url = /^\https?:\/\//;
```
ちょいとややこしい。`\https?`で?は前の文字が0or1回出るという意味なので、http,httpsの場合二つが取得できるというわけだ。

\/\/←これはhttp://←このスラッシュを表すためである。スラッシュを連続で書いてしまうと、エスケープになってしまうので、意味が変わってくる。従って上のように書いている。


##電話番号

```javascript
var tel = /(\d+)-(\d+)-(\d+)/;
```
今までのやつが分かれば簡単である。

また新しい正規表現を使う時があったら、追記しようと思う。
最近はvalidationもemailやtelなど自分で書く必要がないので、全部自力でやろうとするとわからなくなる。
便利な世の中だ。
querySelectorAll でブラウジング中に不要な要素を気軽に消したりする

- Chrome とか適当に開発コンソールが開けるブラウザでコンソールを開く
- おもむろに以下のようなコードを実行すればいらない要素を消せる
  - セレクタや消す条件は適宜読み換える

```js
(() => {
    // リスト一覧の要素を querySelectorAll で取得
    const listItems = document.querySelectorAll('table.mTop5 > tbody > tr');

    listItems.forEach(listItem => {
        // 条件に一致する要素があれば削除する
        // 今回の例だと、特定の label 要素に任意の文字列が含まれていなければ削除
        const labelElem = listItem.querySelector('label[title="メモリ規格"]');
        if (! labelElem) { return; }

        const text = labelElem.innerHTML.trim();
        if (text.indexOf('DDR3') < 0) {
            listItem.parentNode.removeChild(listItem);
        }
    });
})();
```
ダークウェブ探査(onionサイトの収集)

#はじめに
前回の記事でonionサイトを公開しましたが、一般公開していないonionサイトに思ったより訪問者がございましたので、世の人はどのように探査してるか考えてみました。
ダークウェブ、onionサイト、TOR、shodanって何ぞ？という方はググってください。

#onionドメインの生成
onionサイトを探査する前に、onionドメインについて考えてみます。
onionドメインを作成したことがある人は知っていると思いますが、onionドメインは自分で好きに生成することはできません。
onionドメインを生成するアルゴリズムは以下のサイトがとても参考になりましたので、気になる人はお読みください。

[onionアドレスの生成](http://epcnt19.hatenablog.com/entry/2017/04/16/200745)

簡単に解説しますと、onionドメインは英数字16文字で構成され、「aからzまでの英字」と「2から7まで」の数字を含めることができます。
そうすると、onionドメインの個数が恐ろしい数になりました。

「aからzまでの英字」と「2から7まで」の数字　= 32文字
英数字 32文字 ^ 16個数　= 1.2089258e+24個(onionドメインの個数)

IPv4アドレスが約43億個(4300000000)というので、約280000000000000倍と数が圧倒的です。
(IPアドレスとドメインを比べるな！という意見は勿論ございますｗ)

# onionドメインのアクセス方法
TORを用いたアクセス方法は以下のサイトが役に立ちました。

[Torを使って個人情報をコントロールする方法](https://qiita.com/syui/items/ebd6734a8102c7906cc1)
[FreeBSD9.1にTorを入れる](http://shutingrz.hatenablog.com/entry/2013/11/07/220650)

CUIでアクセスしたいなら、TORをデフォルトで動かしていれば以下のコマンドで可能です。

``CUIでのコマンド
curl -sL -v --sockes5-hostname 127.0.0.1:9050 onionドメイン
``

残念ながら閉鎖されてますが、ダークウェブ上をshondanみたいに探査するサイトがありました。
恐ろしいほどの数をどうやって探査してたんでしょうか。わたし、気になります。

[Ichidan Is a Shodan-Like Search Engine for the Dark Web](https://www.bleepingcomputer.com/news/security/ichidan-is-a-shodan-like-search-engine-for-the-dark-web/)

#調査結果
一日10万onionサイトを調査しても、100年で探査できないほどの数があります。
ランダムで20万onionドメインにアクセスしましたが、なかなかヒットできませんので、未知のonionサイトを見つけるのは難しそうですね。
現在の全onionサイトの稼働状況を知ってみたいですが、企業さんはどうされてるんですかね。

[ダークウェブ上で個人情報を売買](https://www.fireeye.com/blog/jp-threat-research/2018/05/japan-pii-finding.html)というニュースがありますので、乱れ打ちでonionサイトを探しているわけではないと思います。
やはり、定石である「掲示板等からonionドメインを仕入れる」しかないんでしょうか。
効率的なダークウェブの情報収集をしたいものです。教えてエロい人。

#最後に
ビール飲んでみたい
【Ruby】オブジェクト指向

## オブジェクト指向とは
開発を効率よく進めるための重要な概念
=> 設計図を元に部品を作成し、その部品を使用して完成品を作ろう！！という考え方のこと

## 例：「車」の製作過程
- 設計図：車の設計図
- 部品：ハンドル、タイヤ、エンジン、ボディー
- 完成品：車

### 設計図なしに車を作る
- ものすごくめんどくさい
- カスタマイズしにくい
- 品質が悪い

### 設計図を元に車を作る
- 効率が良い（再利用性）
- カスタマイズしやすい（拡張性）
- 品質が担保できる（保守性）

### Rubyの世界だと、、、、、

- 設計図 => クラス
- 部品 => オブジェクト
- 完成品 => Webアプリケーション

実は文字列もクラスから生まれたオブジェクトの一つ。

```ruby
puts String.new("Hello World")
puts "Hello World"
```

### 設計図（クラス）なし車を生み出す場合

```ruby
car1_price = 1000000
car1_color = "red"
car1_speed = 120
car1_accel = "進む"
car1_brake = "止まる"


car2_price = 1000000
car2_color = "red"
car2_speed = 120
car2_accel = "進む"
car2_brake = "止まる"

car3_price = 1000000
car3_color = "red"
car3_speed = 120
car3_accel = "進む"
car3_brake = "止まる"
```

### 設計図をもとに車を生み出す場合

車の設計図を作る
- Carクラスの定義

クラス名の先頭は大文字

クラスの構成要素

1. インスタンス変数（クラスが持つ情報）
2. イニシャライザ（初期値を設定するもの）
3. メソッド（一連の処理の塊）

```ruby
class Car

  # 1. インスタンス変数
　　　　# attr_accessor はセッター、ゲッターを合わせた機能を持つ
  attr_accessor :price, :color, :speed

  # 2. イニシャライザ（初期値を設定するもの）
  # クラスがオブジェクト化されたときに自動で実行される
  def initialize(price, color, speed)
    self.price = price
    self.color = color
    self.speed = speed
  end

  # 3. メソッド（機能）
  def accel
    self.speed += 10
  end

  def brake
    self.speed -= 10
  end

end
```

### クラスをオブジェクト化するやり方
car1(オブジェクト名) = Car(クラス名).new(オブジェクトを生み出す)

```ruby
car1 = Car.new(3123424242, "Black", 200)
car2 = Car.new(2000000, "Red", 300)
car3 = Car.new(10000000, "Green", 100)
car4 = Car.new(3444887437, "Black", 200)
car5 = Car.new(474366437, "Black", 150)


puts car1.price
puts car1.accel
puts car2.accel
puts car3.accel
puts car4.accel
puts car5.accel


puts <<~TEXT

car1の値段を5割引します
#{car1.pricedown(5)}

TEXT

```



### フィールドにアクセスする

```ruby
puts <<~HEREDOC

  car1の値段：#{car1.price}
  car2の値段：#{car2.price}
  car3の値段：#{car3.price}
  car4の値段：#{car4.price}
  car5の値段：#{car5.price}

HEREDOC
```

### メソッドを呼び出す

```ruby
puts <<~HEREDOC

  car1のアクセルを踏む：スピードが#{car1.accel}km/hになった
  car2のアクセルを踏む：スピードが#{car2.accel}km/hになった
  car3のアクセルを踏む：スピードが#{car3.accel}km/hになった
  car4のアクセルを踏む：スピードが#{car4.accel}km/hになった
  car5のアクセルを踏む：スピードが#{car5.accel}km/hになった

HEREDOC
```
Angular6の環境をVisualStudio2017で構築する方法

#### VisualStudio2017にAngularのTemplateがあるが、Angular4用なのでAngular6の環境を構築する方法を忘備録としてまとめてみた。
1.VisualStudio2017で「ASP.NET Core Webアプリケーション」を選択
![ng6-1.png](https://qiita-image-store.s3.amazonaws.com/0/184967/f580aa98-c7b8-6df0-784c-5d917cc0b5b6.png)

2.APIを選択
![ng6-2.png](https://qiita-image-store.s3.amazonaws.com/0/184967/388cbfd5-b935-c9ed-19e5-108d45243657.png)

3.ソリューションを選択し、右クリックから「Open Command Line」→「Developer Command Prompt」を開く
![ng6-4.png](https://qiita-image-store.s3.amazonaws.com/0/184967/62254ce3-29c9-8eda-82a5-dc250c3baf84.png)
※「Open Command Line」が表示されない場合は、拡張機能と更新プログラムからインストールする。

4.コマンドプロンプトから「ng new プロジェクト名」を入力して実行
![ng6-5.png](https://qiita-image-store.s3.amazonaws.com/0/184967/fa4d3eca-63df-64bd-1224-f8450f344306.png)
※エラーが表示されて終了するが無視

5.「package.json」からパッケージの復元を実行

6.「startup.cs」を開き、Configureメソッドを以下のコードを追加

```c#:startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  if (env.IsDevelopment())
  {
    app.UseDeveloperExceptionPage();
  }

  app.UseMvc();
  
  //以下の2行を追加
  app.UseDefaultFiles();
  app.UseStaticFiles();
}
```

7.「angular.json」を開き「outputPath」の設定値を「wwwroot」に変更
![ng6-9.png](https://qiita-image-store.s3.amazonaws.com/0/184967/b4061100-7443-217f-2acc-8c84fb26614b.png)

8.プロジェクトの編集を開き「PropertyGroup」タグに以下のコードを追加

```xml
<TypeScriptCompilerBlocked>true</TypeScriptCompilerBlocked>
<PostBuildEvent>ng build --aot</PostBuildEvent>    
```

![ng6-10.png](https://qiita-image-store.s3.amazonaws.com/0/184967/14b2e8c2-5fcb-eca4-8ef6-631e14334721.png)

9.「Developer Command Prompt」を開き、「ng build」コマンドを実行

10.エラーがないことを確認しVisualStudio2017にてデバッグを実行
初期状態だと「localhost/api/values」が起動されるので、必要に応じて変更する(プロジェクトのプロパティ→デバッグ→ブラウザの起動の設定を変更)。
![ng6-13.png](https://qiita-image-store.s3.amazonaws.com/0/184967/5e65410c-9d97-8c04-1e7e-8d59baf52771.png)
FWのassetに関する概念

# Assetの理解　rails and laraavel for Docker

assetとは、webアプリの直截的に関係の無いレスポンス要素機構のことをさしており、Webフレームワークには、大抵asset概念で、これを管理する。なるほど！
と言うわけで２つのフレームワークにこのassetを使ってVue.jsを使えるようにしてみた。
前提として、dokcerで二つのフレームワークを使えるように環境構築をしてください。
何か間違っていたら、ご指摘お願いします！

## laravel編

Larval mixを使い、webpackを導入する
Laravel mixは、webpackのラッパーであり、バージョン管理、アセットビルド、コンパイルと言ったことが、コーディングで可能にる

npmとnode.jsの理解が必要

Npmはjsのパッケージ管理ツールである。
Node.jsは、jsをサーバーサイドで使おうとして使え雨量にしたもの

Laravel MixとSassをインストール

```
$ npm install laravel-mix cross-env node-sass --save-dev
```

ドキュメントルートの中にwbpack.mix.jsというものが出来ているから、そこに

```webpack.mix.js
mix.js('resources/js/app.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css');
```
を追記する

```
$ npm install 
```
をして、パッケージをインストールして、

```
$ npm run watch
```
でwebpackを起動する

## rails編

Gemfileに

```Gemfile
gem ‘webpacker’, GitHub: ‘rails/webpacker’
```

を追加する

Webpackerは、asset piplineとwebpackを使ったJSアプリケーションが競合しないようにするラッパー

```
$ bundle install
```
しておく。ここでsudoを使うと、後で、buildする時にpermission errorを起すので、注意。

```
$ bin/rake webpacker:install
```
これにより、使うファイルやコマンドがインストールされる。

```
$ rails webpacker:install:vue
```
Vue.jsのインストールをこれで行う
テストフレームpytestをインストール

# Pythonのテストをしたい
私の他のQiita記事を見ていただければわかりますが、私のPythonの知識は**砂粒程度**&「テストとはどういうことをするのか」や「テストフレームワークの違い」もまったくわかっていないため、とりあえずドキュメントがしっかりしていると言われるpytestをインストールすることに決めました。
([↑@haminiku様のQiitaより](https://qiita.com/haminiku/items/9f1b9a2fb773c732c494))

「テストして、中でどんな動き方しているかわかったほうがのちのちトラブルも少ないよね?」というただの思いつきです:bowtie:

# 開発環境
- cloud9
- Python2.7

# 早速`pip install pytest`!
![pytest1.png](https://qiita-image-store.s3.amazonaws.com/0/171266/18795023-72e8-72d7-c161-d64b5504588b.png)

しかし
![pytest2.png](https://qiita-image-store.s3.amazonaws.com/0/171266/3839609f-1dcb-51b0-5423-a1b6a90ba3d5.png)

> OSError: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/_pytest'

**東京特許許可局今日特許許可却下**、と:sob:

# Google検索開始
まず「OSError:～」をまるっとGoogle検索。首尾よく[pipインストールエラーについて](https://teratail.com/questions/10352) という質問を見つけました。
> 単にディレクトリを作る権限が無いというだけのようです。 pipのインストール時にsudoを付けて管理者権限で実行すればOKです。

「で、sudoはどこにつければよいのか:frowning:? (ああ、砂粒!)」 ということで「pip install pytest sudo 管理者権限」で再度Google検索。すると[コンソール端末でのpipやpythonコマンドのエラー](http://y-okamoto-psy1949.la.coocan.jp/Python/Install35win/) がヒット。

> pipコマンドは管理者権限で使用するのがよい。管理者権限で実行しなかった場合、インストールできないパッケージもある。Unbuntuの場合に管理者権限で実行するときは、先頭にsudoを付けてsudo pip ・・・とpipコマンドを呼び出せばよい。

あー:innocent: `$ sudo pip install pytest`ね。と早速打ち込む。
![sudo.png](https://qiita-image-store.s3.amazonaws.com/0/171266/2cefacda-1ef0-ce82-9346-2e01c54bc1bb.png)

できました:sparkles::sparkles::sparkles:
![sudo2.png](https://qiita-image-store.s3.amazonaws.com/0/171266/993e568c-5a8a-504d-45ee-020c39f010e4.png)
`Successfully installed pytest pluggy atomicwrites funcsigs py more-itertools six pathlib2 attrs scandir
Cleaning up...`
コマンドラインからUnityのビルドを行う（バージョン: 2017.3.1f1）

基本的には以下の記事を参照
https://qiita.com/sango/items/474efb4c016a136c84ce

ただし、バージョン: 2017.3.1f1では上記記事の方法をそのまま使うことはできない。以前のバージョンまでは、以下のコマンドでよかったが、

```
"C:\Program Files\Unity\Editor\Unity.exe" -batchmode -quit -logFile .\build.log -projectPath C:\project\myUnityProj -executeMethod BuildClass.Build
```

バージョン: 2017.3.1f1だと認証まで行う必要があるので、ユーザ名とパスワードを引数で渡してやる必要がある。

```
"C:\Program Files\Unity\Editor\Unity.exe" -batchmode -quit -logFile .\build.log -projectPath  C:\project\myUnityProj -executeMethod BuildClass.Build -username "example@example.com" -password "password"
```
BookmarkletでURLのプロトコルを切り替える

# 概要

httpなサイトだと以下のようにプロトコルが省略されていて、`https://`とキーボードを打たなけばプロトコルを切り替えることができません。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/184311/c3a5cce7-7991-c09f-efc6-541e0f5573f7.png)


Bookmarkletを作成し
閲覧しているページのhttp/httpsの切り替えをできるようにしました。

```
http://example.com/ ⇔　https://example.com/
```


※ 自動でhttpsにリダイレクトするページは、切り替えることができません。Qiitaもちゃんとリダイレクトしているのでhttpsのままになります。


# Bookmarklet


下記コードをBookmarkletに設定するとワンクリックで切り替えられます。

(名前は好きにつけてください。私は、`http↔https`と名前を付けています。)

```javascript:http↔https
javascript:(function(){var%20url%3Dlocation.href%3Bvar%20protocol%3Dlocation.protocol%3Bif(protocol%3D%3D%22https%3A%22)%7BopenUrl%3Durl.replace(%2Fhttps%2Fi%2C'http')%3B%7Delse%7BopenUrl%3Durl.replace(%2Fhttp%2Fi%2C%20'https')%3B%7Dwindow.location.href%3DopenUrl%3B})();
```


# コードの中身

やっていることは簡単で
プロトコルを判別してURLを書き換えしているだけです。

```javascript

var url=location.href; //URLを取得
var protocol=location.protocol; //プロトコルを取得

//プロトコルを判定する
if ( protocol == "https:" ) { 
  // httpsの場合はhttpに置換する
  openUrl=url.replace(/https/i , 'http');
} else { 
  // httpの場合はhttpsに置換する  
  openUrl=url.replace(/http/i , 'https');
} 

// ページ遷移する
window.location.href = openUrl;
```

### 活用方法

Google Chromeの常時SSL化でどんどんhttpなサイトは減ってきているので、
用途は限られて来ますが、、、

- http/https両対応しているサイトの動作確認
- 他所様のサイトがhttps対応されたか確認

などが楽になります。
高度な業務知識が求められる業務システム開発でのスクラム試行

# はじめに

現場での仕事にガムシャラに向き合ってきた20才台を卒業して、
エンジニアとしてアウトプットをして世に貢献していける30才台を目指す、
とあるSIerのSEによる備忘録の第一号記事です。

スクラムの知識を前提としますので、意味のわからない単語がたくさん出てくる方は
[アジャイルでやってみた。](https://www.amazon.co.jp/%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%81%A7%E3%82%84%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%80%82%E3%82%A6%E3%82%A9%E3%83%BC%E3%82%BF%E3%83%BC%E3%83%95%E3%82%A9%E3%83%BC%E3%83%AB%E3%81%97%E3%81%8B%E7%9F%A5%E3%82%89%E3%81%AA%E3%81%8B%E3%81%A3%E3%81%9F%E5%83%95%E3%82%89SIer%E3%81%AE%E3%82%B9%E3%82%AF%E3%83%A9%E3%83%A0%E6%97%A5%E8%A8%98-%E7%AB%B9%E6%9E%97%E5%B4%87/dp/4798047406)とか[カイゼン・ジャーニー](https://www.amazon.co.jp/%E3%82%AB%E3%82%A4%E3%82%BC%E3%83%B3%E3%83%BB%E3%82%B8%E3%83%A3%E3%83%BC%E3%83%8B%E3%83%BC-%E3%81%9F%E3%81%A3%E3%81%9F1%E4%BA%BA%E3%81%8B%E3%82%89%E3%81%AF%E3%81%98%E3%82%81%E3%81%A6%E3%80%81%E3%80%8C%E8%B6%8A%E5%A2%83%E3%80%8D%E3%81%99%E3%82%8B%E3%83%81%E3%83%BC%E3%83%A0%E3%82%92%E3%81%A4%E3%81%8F%E3%82%8B%E3%81%BE%E3%81%A7-%E5%B8%82%E8%B0%B7-%E8%81%A1%E5%95%93/dp/4798153346)あたりが読みやすかったです。

初版：2018/08/05
最終更新：2018/09/09

## 目次

- 登場人物や最初に安定した役割分担：本記事
- 初回リリースに向けた取組：[こちらの記事へ](https://qiita.com/takeout44/items/f8316d1ab73702291981)

## 登場人物

ユーザー企業

- プロジェクト責任者
- コア業務の計算ライブラリ開発者
- 一般ユーザ

ベンダー

- ITコンサルタント
- コア業務の知見者
- アジャイル開発経験のない本件業務システムの開発者

## 採用技術要素

対応ブラウザ

- Chrome
- 将来的にEdge移行要件有

フロントエンド

- AngularJS
- Wijmo

バックエンド

- C#
- ASP.NET WebAPI
- AutoMapper
- EntiryFramework(Code First)
- OracleDB

その他

- SignalR(WebSochet)

開発ツール

- Visual Studio
- Visual Studio Code
- Team Foundation Server
- NUnit
- Redmine
- Jenkins

# 最初に安定した役割分担

大コケしない程度の安定感を持ってスプリントを回せるようになった、
最初の役割分担をまず書いておきます。
一般的なウォーターフォールやスクラムのあるべきからはほど遠い上に、
まだまだ課題のある状態である点はご留意ください。

本件業務システムのシステム要件定義での業務知見の要求が高いため、
業務知見のある人間による「要件具体化」（要件定義、基本設計の大部分に相当）と、
「開発」（基本設計の一部、詳細設計、実装、クラス単体テスト、動作確認）と、
「テスト」（結合テスト、非機能要件テスト、総合テスト）との、
3つに役割を分離しています。

開発手法も分離した体制毎に異なり、
「要件具体化」は超簡易スクラム（ストーリーポイントは振らずバックログ運用のみ）、
「開発」はスクラム（ストーリーポイントとベロシティによる管理）、
「テスト」はウォーターフォール（WBSによる管理）、
というように三者三様です。
※要件具体化は事前見積が非常に難しくストーリーポイントが機能しなかったため中途半端

## プロダクトオーナー

ユーザー企業のプロジェクト責任者が担当。

- プロダクトバックログ（要件具体化/開発）の優先順位の決定
- プロダクトバックログ（要件具体化/開発）からスプリントバックログ（要件具体化/開発）の決定
- プロダクトバックログ（要件具体化/開発）の受入判定
- リリーススプリントの決定
- テスト計画の承認
- エンドユーザー向け本件業務システム利用方法の説明、横断的なニーズヒアリングの企画、実施

## スクラムマスター

ベンダー開発者のうちマネジメント適性の高いメンバーが担当。

- スプリントプランニング（開発）、デイリースクラム、スプリントレビュー（開発）、スプリントレトロスペクティブの司会進行
- バーンダウンチャート、カンバン、デイリースクラムでのコミュニケーションロスの検知、解消
- 技術的な課題解消の支援
- プロジェクト推進上の課題解消の支援
- 開発環境の維持メンテナンス

## スーパーサブ

ベンダーのITコンサルタントが担当。

- プロダクトバックログ（要件具体化/開発）の起票
- スプリントバックログ（要件具体化/開発）の優先順位案の作成
- プロダクトバックログに対する要件具体化/開発チーム、プロダクトオーナーとのコミュニケーションハブ
- プロダクトバックログ（開発）に対するストーリーポイント見積の司会進行
- プロジェクト推進上の課題解消の主体

## 要件具体化チーム

ベンダーのコア業務知見者が担当。

- スプリントバックログ（要件具体化）の消化
- エンドユーザーの一部との要件検討ミーティングの企画、実施
- ユーザー企業のコア業務の計算ライブラリ開発者と開発チームとのコミュニケーションハブ
- スプリントプランニング（要件具体化）、スプリントレビュー（要件具体化）の司会進行　※ベンダー

## 開発チーム

ベンダーの残りメンバーが担当。

- スプリントバックログ（開発）の消化
- プロダクトバックログ（開発）に対するストーリーポイント見積
- 技術的な課題解消の推進

## テストチーム

この時はまだ編成されておらず。
後にテストエンジニアが担当。

# 役割分担の変遷

ここからがやっと本題で、これを書かないと歪な役割分担の意図が見えないのですが、
第一号はここまでとします。（2018/08/05）

きっと続きます！

# 編集後記

こうしてアウトプットしようと書いていると、改善点や、人が変わるとこの体制ではうまくいかないよなという、
当たり前のことがよく実感できます。

週末開発のがっつりプログラミングの記事も書けるようにがんばろう！
one-linerでデータを集計した話

# 仕事でデータの集計をした時にワンライナーを書いたので、その覚書です。

## 注意：sedとawkを使っていないです。

　sedとかawkを使う前に、シェルの計算式を作れる文法を知ってそっちで集計をしましたので、レベルとしては下の下だと思います・・・
次回には、awkやsedの記事もやりたいと思います。
個人的に、凄くone-linerカッコよくて楽しいです。

## 本編
初めてデータ集計の作業をしたので、ログをデータから引っ張ってくるところからの思考も書いておきます。これを書く理由は、ログを集計するという問題を解決するにあたり、どうやって中身を調べてきたかまでを含めて、ワンライナーを応用することであると考えるからです。

### 思考の走りだし１
##### サーバーのログファイルから、お目当ての情報だけを抜き出して、ファイルに変換する。ログファイルには、ユーザーのデータや日付け、などの今回の調べたいもの以外の情報も持っているため、まず、必要な情報だけを引っ張り出す所から始めます。

```
cat *.log | cut -f タブ番号 > log.log
```

今回自分が担当した案件では、Apachのログファイルだったので、タブ区切り表記を利用してURL部分だけを抽出しています。
これにより、必要な情報であるダウンロードされた分だけ叩かれたURLを抜き出せます。

### 思考の走りだし2
ここで大事なのは、集計したいデータがどこに格納されているかを考えること事です。今回はとあるコンテンツのダウンロードされた回数を知りたかったので、何回そのコンテンツのダウンロードボタンのURLにリクエストが飛んだかを調べればよいと考え、そのコンテンツが叩かれたであろうURLだけをコンテンツ毎にファイルかしていく

```
grep log.log 調べたいURL > コンテンツ名.txt
```

これをコンテンンツ分やって、コンテンツ毎に切り分けられてそのコンテンツのURLだけになったテキストファイルができあがります。

### 思考の最後
後はコンテンンツ毎に別れたファイルをカウントしてあげれば完了ですが、1個ずつカウントしていくのは大変なので、シェルスクリプトで処置しました。

```log_analysis.sh
#!/bin/bash
  
  for path in `cat コンテンツ名.txt`;
  do
    echo $path `grep $path log.log  | wc -l`;
  done;
  
  for path in `cat コンテンツ名.txt`;
  do
    echo $path `grep $path log.log  | wc -l`;
  done;
 
  for path in ` cat コンテンツ名.txt`;
  do
    echo $path `grep $path log.log  | wc -l`;
  done;

  for path in `cat コンテンツ名.txt`;
  do
    echo $path `grep $path log.log  | wc -l`;
  done;
```
これを、

```
/bin/bash anarysis.sh
```
で実行してあげると、シェルスクリプトのfor文を使い、コンテンツのファイルを引数としてcatした状態で渡して、ログでgrep検索をかけた状態で、行数をwc　-lで集計させて、echoで標準出力させルことができます。

以上で、データ集計を行なえます。どこか間違っている所や、改善点などあれば、教えて下さい！
VisualStudioのビルドイベントで自動的にzipを作る

VisualStudioで開発をして、ClickOnceで配布しているプロジェクトがあるんですが、ClickOnceでは不具合が出た時に1つ前のバージョンの戻せるとはいえ、それでは足りない事もままあります。
GitHubでReleaseを切る時に毎回zipを貼り付けておけば、いざという時はそこから任意のバージョンを取得して使ってもらえるのですが、それが面倒くさい。

ということで、VisualStudioのビルドイベントを使ってビルド後に自動でReleaseフォルダをzipで固めてくれるようにしました。
参考にさせていただいたのは、こちらの2ページ。
http://kuttsun.blogspot.com/2017/11/visual-studio-zip.html
https://sakapon.wordpress.com/2015/10/14/dotnet-build-2/
1つ目は.pdbなど不要ファイルを削除している点、2つ目はzipファイル名にバージョン番号を含めている点がそれぞれイケてるので、そのハイブリッドを目指しました。

出来上がったPowerShellスクリプトはこんな感じ。

```powershell:CreateZipForAssembly.ps1
# source assembly file path
if (-not ($Args[0])) { return 100 }

Add-Type -AssemblyName System.IO.Compression.FileSystem

$outputPath = "C:\\OutputDir\\zip"

$assemblyName = [System.IO.Path]::GetFileNameWithoutExtension($Args[0])
$assembly = [System.Reflection.Assembly]::LoadFrom($Args[0])
$assemblyFileVersion = [System.Reflection.CustomAttributeExtensions]::GetCustomAttribute($assembly, [System.Reflection.AssemblyFileVersionAttribute])
if (-not ($assemblyFileVersion)) { return 200 }

$sourceDirPath = [System.IO.Path]::GetDirectoryName($Args[0])
$targetZipFileName = [string]::Format("{0}-{1}.zip", $assemblyName, $assemblyFileVersion.Version)
$targetZipFilePath = [System.IO.Path]::Combine($outputPath, $targetZipFileName)

Remove-Item -Recurse -path $sourceDirPath -include *.pdb
Remove-Item -Recurse -path $sourceDirPath -include *.xml
Remove-Item -Recurse -path $sourceDirPath -include *.config -Exclude NLog.config


[System.IO.File]::Delete($targetZipFilePath)
[System.IO.Compression.ZipFile]::CreateFromDirectory($sourceDirPath, $targetZipFilePath)
```

元記事ではビルドイベントで出力パスを指定していましたが、他の開発メンバーは違うパスを指定したいこともあろうかと思い、（リポジトリに含まれない）PowerShellスクリプト側で指定するようにしました。パス区切りは「\\」と2回打ってエスケープするの大事。
これを各プロジェクトフォルダの上、私の場合、C:\Users\(ユーザ名)\Sources\ReposにCreateZipForAssembly.ps1という名前で保存しました。他のリポジトリのディレクトリが並んでいるのと同階層です。
で、VisualStudioの各プロジェクトでProperty->ビルドイベントを開き、「ビルド後のイベントのコマンドライン」に下記のように書きます。

```
if $(ConfigurationName) == Release (
cd $(ProjectDir) 
powershell -ExecutionPolicy Unrestricted ..\..\CreateZipForAssembly.ps1 $(TargetPath)
)
```

cdで移動する$(ProjectDir)は、Hogeというプロジェクトの場合、Hoge\Hogeと潜った場所を指しているようなので、..\..\と2階層上がるとスクリプトに辿り着けるわけです。もちろん任意の場所に置いて絶対パスで指定しても良いでしょう。

基本的にはこれでReleaseビルドの度にoutputDirにzipが作られるはずです。ClickOnceの発行でも作成されるようです。私はClickOnce用ファイルを一旦ローカルに発行してから非IISなサーバーにアップロードしているので、それ用のパスの側にzipも書き出して、FTPでアップロードする時に見落とさないようにしてみました。

PowerShellはあまり馴染みがないのですが、エラーが起きた時にVisualStudioのエラー一覧には何も出てこないのでデバッグが大変でした。なにかやり方があるのかも知れません。
WordPressのプラグイン「All-in-One Event Calendar」で使用する地図をLeaflet (OpenStreetMap)に置き換える方法

All-in-One Event Calendar」で使用する地図をLeaflet(OpenStreetMap)に置き換えるスクリプトを作ってみました。

それでは、置き換え方法です。

まず、WordPressでスクリプトを追加するプラグイン"Insert Headers and Footers"をインストールして有効化してください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/191171/c8ca5942-7b63-37ba-3fdd-9f62ffa0f55d.png)

設定→Insert Headers and Footers を開きます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/191171/78af9e07-2095-0492-1d95-5f5370797754.png)

```HTML
<link rel='stylesheet' id='leaflet_stylesheet-css'  href='https://unpkg.com/leaflet@1.3.3/dist/leaflet.css' type='text/css' media='' />
<script async type='text/javascript' src='https://unpkg.com/leaflet@1.3.3/dist/leaflet.js'></script>
<style type="text/css">
.leaflet-zoom-box { z-index: 280; }
.leaflet-pane         { z-index: 240; }
.leaflet-overlay-pane { z-index: 240; }
.leaflet-shadow-pane  { z-index: 250; }
.leaflet-marker-pane  { z-index: 260; }
.leaflet-tooltip-pane   { z-index: 265; }
.leaflet-popup-pane   { z-index: 270; }
.leaflet-control { z-index: 280; }
.leaflet-top,
.leaflet-bottom { z-index: 299; }
.ai1ec-gmap-link { z-index: 299; }
</style>
<script type="text/javascript">
    var oc = document.getElementById("ai1ec-gmap-canvas");
    if (oc) {
        oc.style.visibility = "hidden";
    }
    window.addEventListener("load", function ()
    {
        setTimeout(function ()
        {
            var o = document.getElementById("ai1ec-gmap-address");
            if (o) {
                var oc = document.getElementById("ai1ec-gmap-canvas");
                if (oc) {
                    oc.innerHTML = "";
                    oc.style.visibility = "visible";
                }
                var
                    lat_lng = o.value.split(','),
                    lat = parseFloat(lat_lng[0]),
                    lng = parseFloat(lat_lng[1]),
                    map = L.map('ai1ec-gmap-canvas', {
                        scrollWheelZoom: false,
                        tap: false,
                        dragging: window.ontouchstart !== null
                    }).setView(
                        [lat, lng],
                        17
                    );
                L.tileLayer(
                    '//{s}.tile.osm.org/{z}/{x}/{y}.png', 
                    { attribution: 'Map data © <a href="https://osm.org/copyright">OpenStreetMap</a>' }
                ).addTo(map);
                L.marker(
                    [lat, lng]
                ).addTo(map);
            }
        }, 500);
    }, false);
</script>
```
https://gist.github.com/tablacus/f4aee1181d70301865aa64ee1278dd0e

上記コードを Scripts in Footer にコピペして Save を押せば完了です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/191171/7379974f-9e4a-06d0-5541-06d1239428d1.png)

Leaflet(OpenStreetMap)で表示するようになりました。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/191171/5dcdf99d-776d-f84b-6606-0af39bb33ce0.png)
【 AWS S3 static website hosting 】 静的ファイルをS3でホスティングする。（https対応）





<br/>
AWSでインスタンスを立てて運用していたのですが、

ランニングコストを下げるためにAWSのS3で静的サイトをホスティングしてみました。


# 手順

<br/>
1. S3バケットを作成し、index.html（表示させたいファイル）をアップロード
2. S3バケットのアクセス権限とプロパティエンドポイントの設定
3. Cloudfront distributionの設定。※ACM取得
4. Route53の設定




# S3バケットを作成し、表示させたいファイルをアップロード

<br/>

バケット作成においては、特に設定はありませんので、"バケットを作成"ボタンで作成します。
※ S3バケットの名前は、必ず公開したいドメイン名で設定してください。
  ex) https://issho.io => issho.io


単なる静的サイトであれば、html/css/Javascriptをアップして終了です。

僕の場合、create react appで作成したので、一度buildが必要でした。

なぜかディレクトリごとまとめてアップする場合、ドラッグ＆ドロップでしかUPできなかった謎が残る...。




# S3バケットのアクセス権限とプロパティエンドポイントの設定

<br/>
アクセス権限タブ ＞ バケットポリシー

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::[バケット名]/*"
        }
    ]
}
```

プロパティタブ ＞ Static website hosting

<img width="432" alt="メモ 2018-08-05 18-48-40.png" src="https://qiita-image-store.s3.amazonaws.com/0/244700/1b184ad9-4190-b25c-7cfa-ea3b5ed4d601.png">


インデックスドキュメントとエラードキュメントをそれぞれ指定する。


# Cloudfront distributionの設定 ※ACM取得

<br/>

Cloudfrontで証明書を使うために `us-east-1 (N. Virginia)` で、事前に証明書を発行する必要があります。
他のリージョンに既存である場合も、併用不可なので、新規作成をしてください。

Create Distribution > Web: Get Started

### - Origin Settings

Origin Domain Name > S3 Static website hostingのエンドポイント > Origin ID自動設定

Restrict Bucket Access > Yes

Origin Access Identity > Yes

Grant Read Permissions on Bucket > Yes, Update Bucket Policy

### - Default Cache Behavior Settings

Viewer Protocol Policy > Redirect HTTP to HTTPS

### - Distribution Settings

Alternate Domain Names (CNAMEs) > ドメイン名

SSL Certificate > Custom SSL Certificate (example.com): > 事前に作成した`us-east-1`のACM　

Default Root Object > S3のインデックスドキュメントの指定ファイル名（index.html）

Create Distribution で作成に入ります。

Statusが`Deployed`になったら完了です。　※１５分くらいかかりました。

# Route53の設定

<br/>
最後です。

Hosted zones > 対象のドメインを選択

Type > A - IPv4 address
Alias > Yes
Alias Target > 作成したCloudFront Distributionを選択

<br/>
#### DONEです、お疲れ様でした。
GCE(f1-micro)のdocker-composeでCannot allocate memory

# 背景
GCP(Google Cloud Platform)いいですよね！AWSより取っつきやすいので最近よく使っています。
その中にGCEというssh接続できるコンピューティングリソースあるんですが、無料枠のf1-microで
以下のGitHubの内容を`docker-compose up`したところ以下のエラーが出たのでシェアです！
https://github.com/koyo-miyamura/latestgram

ちなみにf1.microのスペックはこちら
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201242/d1996b66-2107-71ab-6832-7708121dd317.png)

### エラー内容

```bash

Installing ffi 1.9.25 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /usr/local/bundle/gems/ffi-1.9.25/ext/ffi_c
/usr/local/bin/ruby -r ./siteconf20180729-6-5nocr2.rb extconf.rb
Cannot allocate memory - /usr/local/bin/ruby -r ./siteconf20180729-6-5nocr2.rb
extconf.rb 2>&1

```

<details>
<summary>**エラーメッセージ全文（クリックで展開）**</summary>
<div>

```bash
Building web
Step 1/6 : FROM ruby:2.5.1
 ---> 1d8640b852eb
Step 2/6 : WORKDIR /app
 ---> Using cache
 ---> 2b92751173b0
Step 3/6 : ADD Gemfile /app/Gemfile
 ---> Using cache
 ---> 64d4e0189481
Step 4/6 : ADD Gemfile.lock /app/Gemfile.lock
 ---> Using cache
 ---> c0a4503d04ac
Step 5/6 : RUN bundle install
 ---> Running in 15c608884196
Fetching gem metadata from https://rubygems.org/..........
Using bundler 1.16.3
Fetching ffi 1.9.25
Installing ffi 1.9.25 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /usr/local/bundle/gems/ffi-1.9.25/ext/ffi_c
/usr/local/bin/ruby -r ./siteconf20180729-6-5nocr2.rb extconf.rb
Cannot allocate memory - /usr/local/bin/ruby -r ./siteconf20180729-6-5nocr2.rb
extconf.rb 2>&1

Gem files will remain installed in /usr/local/bundle/gems/ffi-1.9.25 for
inspection.
Results logged to
/usr/local/bundle/extensions/x86_64-linux/2.5.0/ffi-1.9.25/gem_make.out

An error occurred while installing ffi (1.9.25), and Bundler cannot continue.
Make sure that `gem install ffi -v '1.9.25' --source 'https://rubygems.org/'`
succeeds before bundling.

In Gemfile:
  rerun was resolved to 0.13.0, which depends on
    listen was resolved to 3.1.5, which depends on
      rb-inotify was resolved to 0.9.10, which depends on
        ffi
ERROR: Service 'web' failed to build: The command '/bin/sh -c bundle install' returned a non-zero code: 5
```

</div>
</details>

# 解決策
エラーメッセージよく見るとメモリが足りないと言われているので、(有料になっちゃいますが)`g1-small`にすれば動きました！

流石にメモリ600MBは限界ある場面も出てくるみたいですね><
WiFiBoy32 初めの第一歩

#WiFiBoy32とは

以下にページがあります。
http://wifiboy.org/
<img width="1184" alt="スクリーンショット 2018-08-05 21.14.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/121950/d73775e2-0cd6-7538-8075-72a065102c9a.png">

日本のフェイスブックページもありました。
https://www.facebook.com/wifiboyjapan/


#入手方法
私は、先日(8/4) Maker Faire Tokyo 2018で入手しました。
「Maker Faire TOkyo 2018 Special Edition」ということで（何がスペシャルなのかちょっと調べてもわかりませんでしたが）3,000円と安かったので購入しました。

内容は、以下の３つでした。
1. マニュアル
2. USBケーブル
3. 本体

![15334715158977.jpg](https://qiita-image-store.s3.amazonaws.com/0/121950/ff15c4f9-4216-d543-8323-2320b395add9.jpeg)

#準備
私は電源を投入したら即使えるものと思っていましたが、USBを接続して通電しても何もおきませんでした。この時２つのことに気づきました。
1. あ、これDeveloper Kitだ（確かに袋に書いてある）
2. バッテリーは付いてないな（つまり、常にＵＳＢ接続 or バッテリーを接続する必要あり。

ということで、簡単に使えるようになるまでをまとめました


##Arduino IDEインストール

この部分はQiitaや、色々な記事があるので、省略します。

##CP2102 USB-Serial ドライバのインストール
以下からダウンロードしてインストールします。
https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers

<img width="699" alt="スクリーンショット 2018-08-05 20.37.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/121950/d60edb71-2b41-60dc-f4a7-9e034081ec3a.png">


途中警告が出るので、許可してインストールします。
うっかり許可し損ねた私のような人は、以下を開いて許可しましょう。
「システム環境設定」→「セキュリティとプライバシー」→「：ダウンロードしたアプリケーションの実行許可」

<img width="670" alt="スクリーンショット 2018-08-05 20.34.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/121950/a96739ba-3ada-fd3b-4567-2026177a4df2.png">

ドライバのイスンストールがうまく行くと、MACの場合、デバイスファイルが確認できます。

```ruby:デバイス確認
$ ls -l /dev/tty.*
crw-rw-rw-  1 root  wheel   21,   0  8  5 21:05 /dev/tty.Bluetooth-Incoming-Port
crw-rw-rw-  1 root  wheel   21,   2  8  5 21:08 /dev/tty.SLAB_USBtoUART
```

##WiFiBoyライブラリインストール
これをインストールしないと、サンプルプログラムなどがコンパイル時にエラーを吐きます。

WiFiBoy32Lib.zip
http://wifiboy.org/files/wifiboy32lib.zip

メニューから、「スケッチ」→「ライブラリーをインクルード」→「.ZIP形式のライブラリをインストール」から、ダウンロードしたZIPを指定します。

<img width="622" alt="スクリーンショット 2018-08-05 20.08.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/121950/fe7bf30a-bed8-9309-cf0a-45b70e3c167b.png">

#ゲームのインストール

#ソフトのダウンロード
まずは、ゲームを以下からダウンロードしましょう。
http://wifiboy.org/tutorials.html

この記事ではとりあえず、一番先頭のテトリスをダウンロードします。
![tetris.jpg](https://qiita-image-store.s3.amazonaws.com/0/121950/31fd7a5d-b480-4cb3-b99a-7fa72228b2c7.jpeg)

http://wifiboy.org/files/wb32tetris.zip

ZIPなので、解凍して、Arduino IDEで開きます。

ボードの設定はよくわからないので、"ESP32 Dev Module"を選択して、シリアルポートだけ、"/dev/cu.SLAB_USBtoUART"に変更して、「マイコンボードに書き込む」ボタンで無事書き込めました。

<img width="895" alt="スクリーンショット 2018-08-05 21.29.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/121950/abdca9cb-9361-dbbe-8085-210fe0ce4336.png">

私の場合、いきなり始まりましたが、無事テトリスが起動してすでに、３，０００円分くらいの満足感はあったかなぁ。

![15334724169918.jpg](https://qiita-image-store.s3.amazonaws.com/0/121950/71d1fd1f-1ab5-583e-6f91-3f0a323c962e.jpeg)

#所感
ちらっとしかコードを見てないんだけど、
・wb32_setTextColor
・wb32_drawString
など、簡単な表示用のAPIが準備されていて、「ディスプレイや、ボタンを半田付けして、ライブラリ読み込んで…　etc」とするよりも、サンプルもあるし、ゲームを作る第一歩としては面白いかなと思いました。

現代は、市販のゲームと、自分で作れるものの差が大きすぎてあまり面白みがないかもしれないけど、こういう小さいもので、自分が作ったものがすぐに楽しめるのはいいんじゃないでしょうか。
IntelliJ IDEA で日本語Javadocを表示する設定

## IntelliJのJavadoc設定

IntelliJ機能に、Web上のJavadocを表示することができる機能が存在するので、それをOracleのWebページに設定するだけ。
場所はプロジェクトのモジュール設定内にあるSDKsの場所。

![2018-08-05 (6).png](https://qiita-image-store.s3.amazonaws.com/0/278549/e4f2cda8-ebc0-67a6-7713-07fb500cc12d.png)

各バージョンのJavadocのURL
https://docs.oracle.com/javase/jp/8/docs/api/
https://docs.oracle.com/javase/jp/11/docs/api/

ただ、IntelliJのデフォルト設定では、自動でJavadocの表示がされないので別途設定が必要

## 簡単にJavadocを表示する

### 1. マウスオーバーで自動表示

![2018-08-05 (3).png](https://qiita-image-store.s3.amazonaws.com/0/278549/e682797e-b374-8061-7d82-211e06a9e3b9.png)

![2018-08-05 (5).png](https://qiita-image-store.s3.amazonaws.com/0/278549/dda0e346-1a2f-4b88-6b2e-06d9d5f30be7.png)

### 2. オートコンプリートで表示

![2018-08-05 (4).png](https://qiita-image-store.s3.amazonaws.com/0/278549/5c90b12f-93cc-cb13-3339-9f450a092da7.png)

![2018-08-05 (7).png](https://qiita-image-store.s3.amazonaws.com/0/278549/47ce4f22-0ea8-e3c9-bf9f-2344109b66f7.png)

ただし、ドット等の入力の自動オートコンプリートではJavadocは表示されない。
*Ctrl(cmd)+スペース* でオートコンプリートを発動させたときのみ有効。

### 3. Javadocブラウザ起動のショートカット

![2018-08-05 (2).png](https://qiita-image-store.s3.amazonaws.com/0/278549/9771782b-a9e7-3c91-71be-7709688f8ec1.png)

ワンボタンで起動するように設定できる。
色々な言語でフィボナッチ数を求めるプログラム

# はじめに

「こう実装するともっときれいだよ！」
「こっちの方がいいんじゃない？」
等あれば、コメントお願い致します。

# フィボナッチ数とは

> n 番目のフィボナッチ数を Fn で表すと、Fn は再帰的に
F0 = 0,
F1 = 1,
Fn + 2 = Fn + Fn + 1 (n ≧ 0)
で定義される

[フィボナッチ数 - Wikipedia](https://ja.wikipedia.org/wiki/フィボナッチ数)

最初の2項(0,1)を除き、1つ前と2つ前の和となる

```
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...
```


# いろいろな言語で実装してみた

以下の言語で実装

* JavaScript
* Java
* Ruby
* Python
* Go
* Kotlin

## 気をつけたこと

* 普通に再帰するだけにしない(パフォーマンス的に)
    * メモ化等する
    * ひとまず`n = 50`までを求められるくらい
* なるべく短く記述する

## JavaScript

```javascript:fibonacci.js
// memoize
var fibs = {}

// fibonacci function
function fib(n) {
  if (n <= 1) return n
  if (fibs[n]) return fibs[n]
  return fibs[n] = fib(n-1) + fib(n-2)
}

for (let i = 0; i < 50; i++) {
  console.log(fib(i))
}
```

## Java

```java:Fibonacci.java
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

public class Fibonacci {

  // memoize
  private static Map<Integer, BigInteger> values = new HashMap<>();

  public static void main(String[] args) {
    for (int i = 0; i < 50; i++) {
      System.out.println(fibonacci(i));
    }
  }

  public static BigInteger fibonacci(Integer n) {
    if (values.containsKey(n)) return values.get(n);
    else if (n == 0) return BigInteger.ZERO;
    else if (n == 1) return BigInteger.ONE;
    else {
      BigInteger fib = fibonacci(n - 1).add(fibonacci(n - 2));
      values.put(n, fib);
      return fib;
    }
  }
}
```

## Ruby

メモ化を使ったパターン

```ruby:fibonacci.rb
@values = Hash.new

def fib(n)
  return @values[n] if @values[n]
  return n if n <= 1
  return @values[n] = fib(n - 1) + fib(n - 2)
end

50.times do |i|
  puts fib(i)
end
```

よりシンプルに書くパターン

```ruby:fibonacci.rb
a, b = 0, 1
50.times do
  puts a
  a, b = b, a + b
end
```

## Python

```python:fibonacci.py
# fibonacci function
def fib(n):
  a, b = 0, 1
  for _ in range(n):
    yield a
    a, b = b, a + b

# print
[ print(i) for i in fib(50) ]
```

## Go

割と[公式](https://golang.org)そのままになってしまった...

```go:fibonacci.go
package main

import (
	"fmt"
)

func main() {
	f := fib()
	for i := 0; i < 50; i++ {
		fmt.Println(f())
	}
}

// fibonacci func
func fib() func() int64 {
	var a, b int64 = 0, 1
	return func() int64 {
		a, b = b, a+b
		return a
	}
}
```

## Kotlin

```kotlin:fibonacci.kt
val fibs = mutableMapOf(0 to 0L, 1 to 1L)

fun main(args: Array<String>) {
  for (i in 0..50) {
    println(fib(i))
  }
}

// fibonacci function
fun fib(n: Int): Long? {
  return if (fibs.containsKey(n)) fibs[n]
        else {
          fibs.put(n, fib(n-1)!!+fib(n-2)!!)
          fibs[n]
        }
}
```

# まとめ

* 色々な言語で同じアルゴリズムを実装してみると、違いが分かって面白い
* 基本的なアルゴリズムでも、言語仕様の理解が深まるし勉強になる
* GoとかKotlin使いこなしたい
padasの基本的なtips

df_new=df_old['A']とすると、列名が消えるが、df_new=df_old[['A']]とすると残る。

dfで特定の条件を満たさない値をnaにしてしまう方法

```python
df_ret[~((df_ret < 0.3) & (df_ret > -0.3))]=np.nan
```
Swift制御構文まとめ

# 条件分岐
## if文
``` 書き方
if a > 0 {
    
} else if a > 10 {

} else {

}
```
* 条件に()をつける必要はない
* {}は省略不可
* 条件にbool型以外を入れることはできない

## switch文
```
let n = 4
switch n {
case 0: print("nはゼロでした")
case 1: print("1や")
case 3: break
default:
    print("あーーーー！！！！")
}

switch n {
case 4:
    print(4)
    fallthrough
case 5:
    print(5)
default:
    print(1)
}
```
* case毎にbreakを書く必要がない
    * breakを書かなくてもcase文が何か一致したらその時点で処理は終了
* case文が一致した後も処理を続けたい場合は「fallthrough」を使う
    * fallthroughを使うと次のcase文は条件が一致してなくても実行される。
        * 上の例だと4と5がprintされる
* caseのあとは必ず何か文を書かないといけない
    * 「case:」だとエラー, 「case: break」って書くことができる 

## 三項演算子
```
let i = 3
let s = i == 1 ? "1や" : "1やない"
print(s)
```
* 特に他の言語とかわらない雰囲気

# 繰り返し
## while文
``` 書き方
var i = 1 //変数定義

while i < 10 {
    print(i)
    i += 1
}

var j = 1

while j < 10 {
    if j % 3 == 0 {
        j += 1
        continue
    }
    print("\(j)は3の倍数ではない")
    j += 1
}

var k = 1

while k < 10 {
    if k % 3 == 0 {
        break
    }
    print("3の倍数がきたらwhile文が終わる")
    k += 1
}
```
* 条件に()をつける必要はない
* swift3で++, --は廃止されているので使えない
* ループから抜け出す時にbreak, 繰り返しの内容を1つ飛ばす時にcontinueは使える


## repeat-while文
```　書き方
var i = 4
repeat {
    print(i)
    i -= 1
} while i > 5
```
* while文と一緒
* 他の多くの言語でいうdo-while文と一緒

## for-in文
```
for i in 1 ..< 10 {
    print(i)
}

for i in 1 ... 10 {
    print(i)
}

for i in 1 ... 10 where i % 3 == 0 {
    print(i)
}

let fruits = ["banana", "peach", "apple"]
for s in fruits {
    print(s)
}
```
* for i = 1; i < 9; i++ みたいなfor文はswift3で消えた
* 「..<」と「　...」で範囲を表す
    * 1 ..< 10だと1以上10未満
    * 1 ... 10だと1以上10以下
* whereをつけることで条件をつけることができる
    * where i % 3 == 0で3で割った余りが0(つまり3の倍数)の時だけ実行する
* in の右側に配列を指定することができる
    * 配列を指定すると配列の中身を順番に取り出してくれる

## foreach
```
let me = ["name": "da-ike", "age": "27", "address": "Cebu"]
me.forEach { (key, value) in
    print("\(key)は\(value)です")
}

let fruits = ["banana", "peach", "apple"]
fruits.forEach { (value) in
    print("\(value)です")
}
```
* 特になし
【laravel5】Ruleクラスでuniqueを使う【バリデーション】

株のポートフォリオを管理できるwebアプリを自作していた時、バリデーションで詰まったので備忘録として記事に記します。

OS mac10.13 
PHP7.1.14 
laravel 5.6


# 目的
各銘柄（≒企業名）には、独自の「証券コード」があります。
IDのようなものだと考えていただいて結構です。
株のポートフォリオを組む時、この証券コードが重複したら変なのでそのチェックが目的です。
（銘柄名も重複したらおかしいので、これもチェック）

# 調べた結果・・・
`unique`というバリデーションルールがlaravelにありました。
基本的には、`unique:テーブル,カラム`というように第一引数にテーブル名・第二引数にカラム名を指定して、同一の値が無いかチェックします。
（そのカラムに同じ値があればNG,異なればOK）
ただ、これ通り使うと、Aさんが登録した銘柄をBさんが登録出来なくなってしまいます。

```php
//stock_codeは、証券コードの意
//stocksは、証券コードや銘柄名が登録されているテーブル
'stock_code' => 'unique:stocks,stock_code'
```

そのため、[ドキュメント](https://readouble.com/laravel/5.6/ja/validation.html#rule-unique)には「アカウントIDが１である場合にのみチェックする」という例も載せてくれています。
>
```php
'email' => Rule::unique('users')->where(function ($query) {
    return $query->where('account_id', 1);
})
```

私が詰まったのはここからで、「アカウントIDが１」ではなく現在のユーザーIDの指定方法でした。
色々と調べた結果、以下の解決方法を導きました。

# 解決方法
`stocks`テーブルには`user_id`カラムがセットされ、`users`テーブルとリレーションされています。
例↓

| id     |   user_id   |    stock_code    |
|:-------|------------:|:----------------:|
| 1      |           1 |            2162  |
| 2      |           2 |            9433  |
もう一度目的を書くと、`user_id`１の人が証券コード9433を入力出来るようにして且つ、2162を入力出来ないようにさせたいです。
なので、where句で以下のように書きます。

```php
'stock_code' => [
       Rule::unique('stocks')->where(function ($query) {
       return $query->where('user_id', $this->user()->id); }),
      ],
```
`user_id`と現在のユーザーのIDを照合しているという形になりますね！

これで目的が達成されました！！
新人エンジニアの時に知っておきたかったこと

## はじめに
振り返ってみると、新人エンジニアの時に知っておきたかったなぁと思うことが少なからずあります。

当時は自分で調べようにもどうやって調べたらいいのか分かりませんでした。
よく言われる言葉ですが、「何が分からないのか分からない」という状態です。
私自身、当時はやっていることの全体像が理解できず、
手探りな状態でエンジニアというキャリアを歩んできたような気がします。

あの頃、ある程度まとまったインプットを得たり、全体像を理解できていたら良かったなぁと感じています。
そんな私も新人エンジニアに関わる機会が増えてきました。
そこで、素晴らしいと言われるような経験をしてきたわけではありませんが、
誰かの役に立てないものかと思い、記事を連載することにしました。

### 対象者
新人エンジニアを対象としています。その中でも、特にWeb系のエンジニアの方々に向けて書いています。
理由としては、私自身がWeb系出身であり、私自身の体験を基にして記事を作成しているためです。
もちろん、対象者以外の方々においても役立つ内容があるかもしれません。
なお、本記事では「Web系の新人エンジニア」を「新人エンジニア」として記述します。

### 目標
新人エンジニアがそのキャリアをスタートする際のストレスを減らすこと、
あるいはその一助となることを目的とします。

### 方法
この目標を達成するため、実用的な方法や便利なツール、知っておきたいノウハウ等を一連の記事を通してご共有します。

### ポリシー
一連の記事は、すべて私自身の経験を基にして情報を取捨選択した上で作成しています。
そのため、すべての情報を網羅されているとは言えません。

また、世の中にはもっと質の高い情報を提供している記事があります。
本記事はあなたがエンジニアというキャリアを歩む上での足がかりにすぎません。
記事の内容に疑問を持ち、あなたがより質の高い情報に触れられるようになれば幸いです。
皆様のノウハウ等をコメント等にご投稿いただくことは大歓迎です。

## シリーズ一覧
* [新人エンジニアの時に知っておきたかったこと[Macキーボード設定編]](https://qiita.com/hirokisan/items/799091bb481637e3e302)
* [新人エンジニアの時に知っておきたかったこと[Macキーボードショートカット編]](https://qiita.com/hirokisan/items/9271c0757e9e86c56225)
* [新人エンジニアの時に知っておきたかったこと[情報管理編]](https://qiita.com/hirokisan/items/0ef42b3ba6d0d26670d7)
* [新人エンジニアの時に知っておきたかったこと[ツール編]](https://qiita.com/hirokisan/items/193a73363e3fa3879612)
* [新人エンジニアの時に知っておきたかったこと[sandbox環境編]](https://qiita.com/hirokisan/items/be61f55afc8312bd07f1)
* [新人エンジニアの時に知っておきたかったこと[Vim編]](https://qiita.com/hirokisan/items/0b433aa20ad2a6a8257b)
* [新人エンジニアの時に知っておきたかったこと[Zsh編]](https://qiita.com/hirokisan/items/4122079709626db0944d)
* [新人エンジニアの時に知っておきたかったこと[tmux編]](https://qiita.com/hirokisan/items/f18a360714bd8f630b25)
* [新人エンジニアの時に知っておきたかったこと[Git編]](https://qiita.com/hirokisan/items/d0bbc435040391a8c008)