OmniAICreator/Qiita-1.07M huggingface dataset:
slackbot + GASで401エラーが返ってきたときに確認すること3つ

GASを公開/デプロイするときの設定でミスってる可能性が大です
以下確認すること3つ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430849/4da10ee5-755b-a66b-2745-aacfe6506ddd.png)

### 1. Project version は `New` にした?

New にないと変更が反映されないです

**2020.06.03追記**
Newにする理由は、[この記事](https://qiita.com/t-morik/items/a6c73e5aff17a52cc104)の@iamaimiさんのコメントにありました

> これはアプリケーションをバージョン管理しているためです。
> 保存してすぐに実行しているアプリケーションのコードが書き換わってしまうと、動作検証ができないですよね。
> 「New」にすることで、現在のコードを新しいバージョンとして登録します。
> バグがでた場合には、再び「1」や「2」に戻せば、元通りです。

> また、ここでNewを選択せずに、ファイルメニューから新しい版を生成して、その版で公開することもできます。

### 2. Execute the app as.. は `Me (...@gmail.com) `にした?

権限の関係で、「Me」にしないとエラーになります

### 3. Who has access to the app は `Anyone, even anonymous` にした?

`Anyone`と`Anyone, even anonymous`の2つがあるので注意です
`Anyone`だと動きません
コーディングテスト受けたくない

# コーディングテスト受けたくない
コーディングテスト受けるので、メモしておく。
メモしていくので更新します。
テキトーなので勘弁してください

2019/12/15
取り敢えず、普段使っているpythonでやります。
競プロだったら、C++に移行した方がいい？

2019/12/16
AtCoderの過去問を解きたい
取り敢えず、githubのリポジトリ作った。
[βshortのリポジトリ](https://github.com/betashort/AtCoder_Repository)


## 競プロ関係？
[paiza](https://paiza.jp/challenges/info)
[AOJ](http://judge.u-aizu.ac.jp/onlinejudge/)
AtCoder

## 問題
1. [AtCoder Beginners Selection](https://atcoder.jp/contests/abs)
2. [AtCoderの問題](https://kenkoooo.com/atcoder/#/table/)
3. 

## 参考&リンク
1. [AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～](https://qiita.com/drken/items/fd4e5e3630d0f5859067)
2. [Pythonで使う競技プログラミング用チートシート](https://qiita.com/_-_-_-_-_/items/34f933adc7be875e61d0)
3. https://1kohei1.com/leetcode/
4. https://www.madopro.net/entry/2016/09/05/135126
5. https://www.freecodecamp.org/news/coding-interviews-for-dummies-5e048933b82b/
6. https://qiita.com/yohachi/items/e4bef4035da135a4808d
7. https://app.codility.com/programmers/lessons/1-iterations/
8. [AtCoder に登録したら解くべき精選過去問 10 問を別解で解いてみた](https://qiita.com/259_Momone/items/991d31ccc1f830a1d578)



# Pythonのメモ
文法的なこと、numpy関係のメモです。
## 入力関係
参考:https://qiita.com/fmhr/items/77fc453e2fb1bc02e392
### 複数の数値を指定の変数に
```python
a, b, c, d = map(int, input().split())
```
### 複数の数値をリストに
```python
#入力 1 3 4 5
a = [int(i) for i in input().split()] 
#a=[1 3 4 5]
```
### 複数の文字列をリストに
```python
a = [i for i in input().split()] 
```

## 出力関係

### ゼロ埋め出力
複数の場合インデックスで指定
2桁の10進の場合

```python
#{インデックス番号:書式指定}.format()
print("{0:02d}".format(1))
#01
```

### 改行なし

```python
print("文字など", end='')
```

### 小数点
```python
#切り上げ
math.ceil()
#切り捨て
math.floor()
#四捨五入
round()
```
### n進数
2進数:bin()
8進数:oct()
16進数 : hex()

## 一致
全一致 'abc' == 'abcd' はFalse
否定は !=

部分一致　'abc' in 'abcd' はTrue
否定は、not in

## 文字列
### 文字列sに'a'が何個あるか
```python
s.count('a')
```
```python
s.replace("置換前", "置換後")
```
### 指定したインデックスの文字を置換(代入)したい
```python
#文字列=>list
s = list("文字列")
s[2] = "式"
s = "".join(s) 
```
## list
https://docs.python.org/ja/3/tutorial/datastructures.html
各要素の個数（要素ごとの出現回数）をカウントするには、count()メソッドを使う。

```python
a.append("格納したい値")
a.remove("削除したい値")
a.pop()
```

リスト内包表記

```python
[i for i in range(10)]
```

```python
#昇順
a.sort()
#降順
a.sort(reverse=True)
```

```python
sum(a)
```

mapは、pandasでいうapply関数

```python
map(func, list)
```

## set
```python
a.add()
a.delete()
```
## dict

## numpy

```python
np.zeros('shape')
np.ones('shape')
np.full('shape', 'value')
```

### 条件を満たす配列の要素数

```python
np.count_nonzero(a < 4)
```

### 配列の最大値のインデックス
```python
#https://qiita.com/shippokun/items/01c85e36b8de7afd01a6

maxValue = np.max(a)
maxIndex = []
for i in range(len(a)):
    if maxVaule == a[i]:
        maxIndex.append(i)
print(maxIndex)    # [1, 4]
``` 

### numpy配列の各要素に対しての条件分岐
```python
np.where(条件, True, False))
```
データモデリング基本

#データモデリング概要
RDBを利用してデータを管理する時や、アプリケーションとRDBを連動させるときに、適当なデータ設計をしてしまうと、データ管理が煩雑になったり、アプリ側の機能拡張が困難になる可能性があります。

そこで、データモデリングという手法を行うことで上記の問題を解決することができます。データモデリングの手法にはたくさんの種類があり、データモデルに合わせたデータモデリングの手法を使うことが多いです。
>データモデルは、おおまかに「階層型」「ネットワーク型」「リレーショナル（関係）」に分けられます。

今回は、RDBを利用したデータ管理を行うので、リレーショナルデータモデルに合ったデータモデリングの手法を使います。

#データモデリング実践
それでは、データモデリングをしていきます。
今回はSQLというRDBMSを操作する言語を使いますので、その知識がある前提で始めます。

今回は例として、ある社内プロジェクトをデータベースで管理するとします。

###１. エンティティを定める。
エンティティとは、データベースを使って管理したい対象のことを指します。

社内プロジェクトをデータベースで管理したい時、どんなもの対象として管理したいでしょうか。
この場合、
**「プロジェクト」
「プロジェクトの名前」
「プロジェクトの進行状況」
「プロジェクトの概要」
「担当社員」
「担当社員の名前」
「担当社員の年齢」
「担当社員の性別」
「担当社員の電話番号」
「担当社員の部署名」**
などが管理したい対象となります。

ここで、これらの対象全てをエンティティに含めても良いのでしょうか。

先ほどは説明しませんでしたが、詳しくいうと、エンティティとは**独立した一つの意味の対象物**を指し示します。
そのため、別のエンティティに付属する**情報**はエンティティではありません。
ここで情報という言葉が重要です。
「プロジェクト」や「担当社員」は情報ではなく対象物です。
「名前」「性別」などが情報となります。

そのため、ここで独立した付属しないもの、つまりエンティティは、
**「プロジェクト」
「担当社員」**
となります。


###２. エンティティ同士の関係を考える。
エンティティが決まったら、エンティティ同士の関係（リレーションシップ）を考えます。

今回はエンティティが2つなので、簡単に決まります。
**担当社員はプロジェクトを担当する。
プロジェクトには担当社員がつく。**
などの関係性があります。

これだけではとどまらず、さらに厳密に分析していきます。

####カーディナリティ（多重度）
データの種類がどのくらいあるのか測る記号を「カーディナリティ」と言います。
>「カーディナリティ」とは、「１対１」「１対多」「多対多」など、リレーションの詳細を表現する記号のことです。「0以上」や「0または1」といったことも表現することができます。
引用：[５分で理解できるER図の書き方５ステップ](https://it-koala.com/entity-relationship-diagram-1897)

例えば、今回のプロジェクトでは、

1つのプロジェクトに1人の担当社員がつく、
**プロジェクト1　対　1担当社員**

多数のプロジェクトに1人の担当社員がつく、
**プロジェクト多　対　1担当社員**

多数のプロジェクトに多数の社員がつく、
**プロジェクト多　対　多担当社員**

1つのプロジェクトに多数の社員がつく、
**プロジェクト1　対　多担当社員**

のどれか、考える必要があります。

今回は**プロジェクト1　対　多担当社員**とします。

####従属性の確認
エンティティ同士で、一方が存在していないと、もう一方も存在できないかどうかの依存関係を確認することを「従属性の確認」と言います。

例えば、今回のプロジェクトでは、

**プロジェクトは担当社員がいないと存在できない。**

**担当社員はプロジェクトがないと存在できない。**

などと考えて、どっちのエンティティが依存しているのかを考えます。

**依存されているエンティティを「独立エンティティ（親エンティティ）」**
**依存しているエンティティを「従属エンティティ（子エンティティ）」**
と呼ぶこともあります。

また、依存関係にないエンティティ同士もあることがあるので、必ずしもエンティティの従属性があるとは限りません。

今回は依存関係がないものとして扱います。

###３. アトリビュート（属性）を考える。
最後に各エンティティに含まれる属性を考えます。

先ほど、エンティティを考える時に
**「プロジェクトの名前」
「プロジェクトの進行状況」
「プロジェクトの概要」
「担当社員の名前」
「担当社員の年齢」
「担当社員の性別」
「担当社員の電話番号」
「担当社員の部署名」**
が候補にあげられました。

しかし、これらの情報は別のエンティティに付属するのでエンティティではないと言いました。

これらの情報は属性として扱うことになります。

###４. ER図にまとめる。
それでは、最後にこれまでのデータモデリングを元にER図を書いていきます。
ER図とは、データベースのエンティティ（Entity）とエンティティ同士の関連（Relationship）を図に表したものです。

![スクリーンショット 2019-12-12 2.23.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374924/2a6aeacb-eb0e-44f8-276d-ff99bff60dd9.png)


正確な詳細などは省きましたが、このような感じになりました。
ちなみにプロジェクトエンティティに属する社員IDの(FK)は、外部キー（Foregin Key）を意味します。
外部キーはSQLでデータベースを操作する際、テーブル間を結合するために設定する列（カラム）のことです。

今回は基本なのでER図に書きませんでしたが、**SQLでテーブル（エンティティのこと）を扱う際には主キー（Primary Key）を設定する**必要があり、主キーをER図に書いたりします。


以上でデータモデリングの基本を終わりにします。
次は、このデータモデリングを元にSQL操作について書いていきます。
VagrantとVirtualBoxについて

VagrantとVirtualBoxを使う機会があったので、調べたことのメモを残します。

## VirtualBoxとは
仮想化ソフトの一つです。ハードウェア(CPUやメモリ、ストレージ)を論理的に分割し、別のOSを動かすことができます。コンピュータの中に別のコンピュータを作り動かすイメージで、例えば、OSがWindowsのパソコンを仮想化ソフトを使うことで、OSXを動かしたりできる。

### ホストOS型の仮想化
VirtualBoxはホストOS型仮想化ソフトの種類の一つ。自分が使っているコンピュータのOSをホストOSといい、仮想化ソフトをインストールすることで、ホストOS上で別のOS(ゲストOS)を動作させる仮想技術。ホストOS＋ゲストOSも動かすためハードウェアのリソース消費が大きい。

![ホストOS型.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308896/755a5aab-bf12-258e-b4a2-38f5d4f430ce.png)


### ハイパーバイザ型の仮想化
直接インストールした仮想化ソフトウェア上で、仮想マシンを動作させるものなので、ホストOS型と違い、ホストOSやゲストOSの概念がありません。そのためリソースの消費量が軽くなるのが特徴です。

![ハイパーバイザ型.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308896/b32cad4e-b3a8-b0ff-f659-c4ef3920324d.png)

## Vagrantとは
VirtualBoxやVMwareを使用した仮想環境の構築や共有を簡単にできるようにしてくれるツールです。Vagrantfileという仮想化環境の構成情報を記したファイルを元に構築する。ファイルとして保管できるのでチーム内で環境の共有ができ、コマンドで破棄＆再構築も簡単にできる。
PDFの英語論文をコピペして翻訳するときに改行を簡単に取り除く方法

# はじめに
pdfで配布されている英語論文をGoogle翻訳にかけるときに、コピペすると行末の改行が混ざってしまい、翻訳ミスが発生します。
この問題を簡単に解決する方法を見つけたので紹介します．
**[追記](#追記)：2020/5現在、DeepLを使った場合でも同様の処理が可能です。翻訳精度も高く、画面遷移がないため便利です。**

<img width="329" alt="スクリーンショット 2019-12-12 1.47.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133979/b90eb8aa-3742-f07f-e521-ff9a38492430.png">
<img width="949" alt="スクリーンショット 2019-12-12 1.58.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133979/9e253b51-ea1e-117e-4a89-47e1c3ad36a5.png">




# 事前準備
- Chromeをpdfビューワーとして利用します
- [Google翻訳のChrome拡張](https://chrome.google.com/webstore/detail/google-translate/aapbdbdomjkkjkaonfhkkikfgjllcleb?hl=ja)をインストールしてください。

# 方法
**範囲選択を行った後、右クリックでGoogle翻訳を呼び出す**
<img width="325" alt="スクリーンショット 2019-12-12 2.18.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133979/8d985460-9e26-2505-8605-a8d3bb004408.png">

<img width="906" alt="スクリーンショット 2019-12-12 2.17.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133979/3bad9a4d-b397-7c57-67af-e093adca1d2b.png">

## 追記
### DeepLを使った翻訳
2020/5現在、[DeepLのChrome拡張](https://chrome.google.com/webstore/detail/deepl-translator/fjokdddhdjnpombkijbljbeemdmajgfj)でも同様の処理が可能です。
手順としては、
1. 翻訳範囲選択
2. DeepLのアイコンをクリック
で使用可能です。(右クリックメニューからのDeepLの拡張機能の呼び出しは、当方の環境では機能しなかったです。)

DeepLを使用すると、新しいタブに遷移せずに使用できるためGoogle翻訳よりも便利かもしれません。
チーム開発日誌１-20191212-

プログラミングの勉強をはじめて９ヶ月目に入るのだけど
幸運なことにシステム開発の案件をいただくことができた（本当奇跡

チームでおこなうので記録に残していこうと思う
思いつくままツラツラと書いているので話が飛ぶこともある（許して

## 開発環境どうする？
JavaScriptでいける内容だからFirebase使ってつくろうか
と最初サクッと決めて進めていっていた
Vue.jsが良さそうだねーと

Firebaseでデータベース設計、バックアップ、セキュリティ、機能追加と考えたところ
これでいいのかなぁ...となって相談

うまく言葉にはできなかったのだけど
何を選ぶにしてもデータベース設計はよく考えなければなのは置いといて
１からつくるときにFirebaseをデータベースに使うのに何か抵抗がでた
（語彙力。。。）

チーム開発する＆いずれ誰かが保守する＋諸々考慮で
ある程度書き方にもルールがあって保守＆機能追加しやすいものがよくないか
とも思って、LaravelでVue.jsを用いてMySQL使おうとなった

ただ、、開発コストと時間が不安点。。

つづく
iOSアプリの多言語対応

# 多言語対応
iOSにて多言語する際の方法とメリット・デメリット使い分けなどをまとめた。

# swiftでの実現方法3パターンとメリット・デメリット
| |メリット|デメリット|
|:-------------------|:--------------------|:-----------------------|
|Localizable.strings 利用|- NSLocalizedStringで自動で端末ごとの設定を呼び出せる。<br> - NSLocalizedStringをoverrideすれば、再起動しないでも言語変更可能|- 端末の言語設定を読み込むが故に動作が完全にos設定依存する。（言語設定をdefaultのまま変更していないユーザも一部海外だと多い）|
|storyboard(Storyboard自体切り出し)|- 言語ごとにレイアウト自体も設定出来る|- レイアウトに関してはダブルメンテナンス必要<br> - cacheしている言語設定を利用するため、再起動しないと言語切替が出来ない|
|storyboard(言語のみ切り出し）|- storyboardは共通で言語のみ設定出来る|- ObjectId.text = `文言`形式で指定するが、レイアウトと文言の紐付けが分かりづらい。|

# 個人的使い分け案
| |再起動なしで言語切替<br> `必須` |再起動なしで言語切替<BR> `不要`|
|:-------------------|:--------------------|:-----------------------|
|言語ごとのUI設定<BR> `必須`| 標準ですべてやるのは出来ないので独自実装するしかなさそう。| storyboardを言語ごとに切り出して対応 |
|言語ごとのUI設定<BR> `不要`|localizable.stringsのみ利用 + NSLocalizedStringをovverideする|以下のいずれでも対応可能だが、storyboardの言語切り出しにあまりメリットがなさそうなので、localizable.stringsのみで良さそう。<br> - localizable.strings <br> - storyboardの言語切り出し|

# Localizable.stringsを使った多言語対応
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237101/3a819307-ee3c-3edc-71f8-07bd66f3b5eb.png)
※ファイル名は、これじゃないと動作しない。

 ファイルの中身
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237101/d0116f7f-ec85-ece8-a5e8-edb54d555fdc.png)

呼び出し方
```
NSLocalizedString("LocalizationStringKey", comment: "")
        print(NSLocalizedString("test", comment: ""))
```

# アイコン・画像の出し分け
画像を両方用意した上で、NSLocalizedStringで出し分ける
```img.image = UIImage(named: NSLocalizedString("img", comment: ""))```

# storyboardを使った多言語対応
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237101/19a22fb4-9ad3-31a9-2fbe-9b2e125e4434.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237101/fe93b075-91ae-25ed-0af9-6350c2621af3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237101/08eba197-0580-202d-ce60-b3018c902157.png)
- 言語ごとにレイアウトも含めて設定することが出来る。

# Tips
## 端末の言語設定
`UserDefaults`の`Key:AppleLanguages`に格納されている。
上記を上書きすることでアプリで利用する言語の上書きが可能。
正しい、上書きした際にはアプリの再起動が必要。

## 言語設定を変更後のアプリの再起動
アプリの再起動を行う処理を記載することは出来ない。

参考
http://quesera2.hatenablog.jp/entry/2013/11/11/013341

## 再起動させたくない場合
参考： アプリの言語設定を、アプリ内から操作したい
https://techlife.cookpad.com/entry/internationalization-and-localization-of-ios-apps

## 端末の設定が対応していない言語の場合のデフォルト言語
日本語と英語しか対応していない場合に、端末の設定が中国語しかなかった場合にアプリの言語がどうなるのか。
めちゃくちゃ調べたけど、結局設定ありました。
`Localization native development region`を変更すると対応してない言語の時のデフォルトになります。
<img width="1015" alt="defaultLanguage.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237101/676eddb8-5d11-0be0-9b46-1c9dcdeaf86f.png">
FedoraにDiscordを入れる

### 2023年4月追記
文面の体裁を整えるため更新。新しい情報は何も入っていません。

## 前置き

日本語情報がないので書きました。
後で詳しく書きますが、現状は**正しくインストールできていない**状態です
実施の際は自己責任でお願いいたします。

## 環境

Fedora 31

## やったこと

### 公式サイトから``tar.gz``パッケージをダウンロード 
[Discord公式サイト](https://discordapp.com/download)から落としてきてください。
``.deb``と``.tar.gz``の2種類がありますが、``.deb``パッケージはDebian系(Ubuntuなど)でしか取り扱えないため、後者を選択してください。

### 適当な場所に解凍する

好きな場所に解凍してください。

```bash
tar -C {インストール先ディレクトリ} -zxvf {落としてきたパッケージ}
```

### Discordを起動する

解凍したディレクトリ内の``Discord``内に移動

```bash
cd {解凍先ディレクトリ}/Discord
```

#### 実行権限をつける

実行ファイルは``{解凍ディレクトリ}/Discord/Discord``だが、デフォルトの状態だと実行できないので、権限を付ける

```bash
chmod +x Discord
```

#### 実行

```bash
Discord

Discord 0.0.9
Fontconfig warning: "/usr/share/fontconfig/conf.avail/05-reset-dirs-sample.conf", line 6: unknown element "reset-dirs"
Starting app.
Another instance exists. Quitting.
```

fontconfigでwarningは出ていますが、
特に何もなければGUIが立ち上がります。

### 解凍したディレクトリにPATHを通す

ここまでのやり方では、解凍先ディレクトリに移動しないと``Discord``コマンドでDiscordを起動できませんでした。  
``~/.bashrc``の末尾に下記を追記し、PATHを通すことで、 
カレントディレクトリに拘わらず``Discord``コマンドを打つことでDiscordを起動させることができます

#### Pathの登録

```bash:.bashrc
# Discord
export PATH=$PATH:{解凍先ディレクトリ}/Discord
```

#### .bashrcの更新

```bash
source ~/.bashrc
```

## 正常にインストールできない、とは？

ログインするまでは特に問題なく動作しましたが、ログイン後、上部に下記のような表示が出ます。

> おや、Discordのインストールに失敗しているようです。この問題を修復しましょう…一緒に。

![oops.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261258/75b1fabe-9363-5af4-0e7b-9293617ada97.png)

今のところ、下記のことは行い、動作に問題は出ていないのですが。  

* テキストチャットの送受信
* ボイスチャットの送受信

現状何が失敗しているのかもよくわからないので、情報をお持ちの方、コメントいただければと思います。

## 参考ページ

https://unix.stackexchange.com/questions/538922/how-can-i-install-discord-in-ubuntu-18-04-3-lts-using-tar
初学者が初学者なりにメゾットについて考えた

全体、プロパティについてすごく調べた。

プロパティは

```
import UIKit

//↓playgroundの最初の表記
var str = "Hello, playground"

//class、UISliderの変数sliderインスタンスを作成して
var slider = UISlider()

//インスタンスsliderのvalueプロパティの値は1.0だよ
slider.value = 0.5
```

という事。

言葉で説明するなら

UI部品のテンプレートであるclassから、インスタンス（改造したクラスの実態のUI）の、細かな設定をプロパティを言う！！

という感じであろう。

テンプレ、カスタマイズ、詳細設定。だな。

##じゃあメゾットは？

メゾットはアニメーションUI部品などに「動き」をつける時につけるものである。

音楽のボリュームとかって、触ると動くでしょ。

それがメゾット。

メゾットの実行方法はこちら

> <変数名>.<メゾット名>（）

インスタンスの作成に似ているね。

眠いのでまた追加します。
Next.js + Firebaseでの開発でハマったところ

Next.js + Firebaseで開発する際にハマった箇所や注意点などを共有したいと思います。

目次:
[本番環境とローカル環境でConfigを切り替えた場合の動作](#本番環境とローカル環境でConfigを切り替えた場合の動作) 
[getInitialProps内でのStorageの画像を参照する場合の動作](#getInitialProps内でのStorageの画像を参照する場合の動作) 
[Next.jsをHostingとCloudfunctionでデプロイし、別のプロジェクトをCloudfunctionにデプロイした場合
](#Next.jsをHostingとCloudfunctionでデプロイし、別のプロジェクトをCloudfunctionにデプロイした場合)  

## 本番環境とローカル環境でConfigを切り替えた場合の動作

```js

if(process.env.NODE_ENV === "production") {
  firebase.initializeApp(/** 本番用の設定 */);
} else {
  firebase.initializeApp(/** ローカル用の設定 */);
}
```

この場合の注意点はローカルで実行するコマンドによっては本番用の設定で動いてしまう点です。
しかも`NODE_ENV=development firebase serve`みたいにNODE_ENVを設定しても"production"で動きます。

```
$ npm run serve // NODE_ENVは"production"
$ npm run dev // NODE_ENVは"development"
```

## getInitialProps内でのStorageの画像を参照する場合の動作
結論から言いますと以下のようなエラーが出て動きません。

```
ReferenceError: XMLHttpRequest is not defined
```

Storageの画像を参照する場合の内部に使われているXMLHttpRequestがサーバー側(Node)には存在しないためです。
client側でStorageの画像を参照するようにするのが無難？？？

## CIでNext.jsと他のプロジェクトなどをCloudfunctionsにデプロイする場合
手動で`firebase deploy`を使用してデプロイした場合は、既存のfunctionを上書きするか上書きせずにデプロイするかを選べます。

CIで`firebase deploy`で自動デプロイしようとすると上記の選択肢が出るためCIが終わりません。
ちゃんとfunction名を指定することで選択肢が出ず無事デプロイできました。

```
firebase deploy --only functions:<function名>
```

## 最後に
Nextでハマった際は日本語の情報がないため苦労しました。
誰かの助けになれば幸いです。
【SQL Server】2番目に大きい/小さい値を取得する

#2番目に大きい値を取得したい
意外とめんどくさいので簡単にまとめてみました。
適当に作った一時データの２番目に大きい値を取得します。
サンプルコードはそのまま実行できるようにしてあるので、試してみてください

##値のみを取得したい場合

```sql:main.sql
DROP TABLE IF EXISTS #tes

SELECT 1 AS id, 11 AS num, 'Adam'    AS cust_name INTO #tes UNION ALL
SELECT 3 AS id, 12 AS num, 'Bob'     AS cust_name           UNION ALL
SELECT 5 AS id, 13 AS num, 'Charlie' AS cust_name           UNION ALL
SELECT 7 AS id, 14 AS num, 'Dom'     AS cust_name           UNION ALL
SELECT 8 AS id, 15 AS num, 'Eva'     AS cust_name           UNION ALL
SELECT 9 AS id, 16 AS num, 'Flynn'   AS cust_name 


--プランA その値だけ持ってくる
SELECT MAX(id) AS 二番目
FROM #tes AS MAIN
CROSS JOIN (SELECT MAX(id) AS 最大 from #tes) AS F
WHERE id <> 最大

SELECT MAX(id) AS 二番目
FROM #tes
WHERE id < (SELECT MAX(id) FROM #tes)

```
このままDECLAREで定義した変数などに入れることができます。
CROSS JOINするのでデータ量が多くなるほど遅くなります。
WHEREのほうに入れるのが一番使い勝手がいいかもしれません。

##レコードを取得したい場合

```sql:main.sql
DROP TABLE IF EXISTS #tes

SELECT 1 AS id, 11 AS num, 'Adam'    AS cust_name INTO #tes UNION ALL
SELECT 3 AS id, 12 AS num, 'Bob'     AS cust_name           UNION ALL
SELECT 5 AS id, 13 AS num, 'Charlie' AS cust_name           UNION ALL
SELECT 7 AS id, 14 AS num, 'Dom'     AS cust_name           UNION ALL
SELECT 8 AS id, 15 AS num, 'Eva'     AS cust_name           UNION ALL
SELECT 9 AS id, 16 AS num, 'Flynn'   AS cust_name 


--プランB そのレコードを取得する①
SELECT * 
FROM (SELECT ROW_NUMBER() OVER(ORDER BY id DESC) AS RNUM
           , *
	  FROM #tes
	 ) AS A
WHERE RNUM = 2
```

ROW_NUMBERは直接WHEREで指定できないので入れ子にして対応します。
見た目が少し回りくどい気がするのと、ROW_NUMBERを付与するのに意外と時間がかかるので、大量のデータだとやはり遅いです。
モノづくりとラーメンとエンジニア

## この記事について

実際のところQiitaに書いてふさわしい内容かどうかはやや疑問が残るが、それでもエンジニアとして、物を作るものとして、どうしても心に留めておきたいと思った経験を、形にしておきたいと思ったのでここにも投稿した。
本当に何も関係ないところから始まるのは許してほしい。でも大事なことだとも思っているのは保証する。

あと、エンジニアという職種柄、少しでも共感してもらえたらこんなに嬉しいことはない。いいねしてくれた人のところページにはちょっとお邪魔しに行きますね。

## ラーメンは美味い。

私はたぶん、世の中の成人男性の中でも食事には割と気を使わない方の部類であり、

故に、夜にラーメンを結構な頻度で食べる（故に？）。

幸にして、先日の健康診断はオール１（問題なし）で、これも健康な人体に育てていただいた両親への感謝を禁じ得ない。

そして私は今日もラーメンを食らうのである。

[（よく行くラーメン屋。味八。後輩や部下はよくここに付き合わされる）](https://tabelog.com/tokyo/A1304/A130401/13149493/)



ある日のこと。ふと思ってしまった。


## 「全くの無から、この今のラーメンの形状に至るまでに、一体どれほどの人間が研鑽を重ねたのか」

と。

ラーメンはもちろん、小麦粉による麺と、煮込まれたスープのコラボにより生まれる料理である。

しかし原始の人類が、その辺に生えている麦を目にしたとき「お、ラーメンにしよう」などと思うはずもない。何しろ麦を初めて目にした人類からすれば、それは「その辺に生えている草」でしかなかったはずだ。

## 気狂い1人

まず「その辺に生えている草」を食べようと思った人物が、長い人類の歴史上確実に1人存在する。

とんでもない気狂いである。
腹が減って食うに止まれずの行動とはいえ、「その辺の草」を口に入れるなどは正気の沙汰ではない。


## 気狂い2人

しかし、あくまでも「その辺の草」である麦は、おいしくない。
そこで、外側の殻を外して中の胚乳だけ食べようと思った人物も、やはり人類の歴史上1人存在する。


気狂いその２である。
普通の人間は、ボソボソで食べられないなら、食べない。わざわざ食べられるように工夫なんぞしない。


## 数々の気狂い

さらに、胚乳だけにしてそれをすりつぶして粉にしようとした人間

水と卵と混ぜてこねた人間

スープにひたして食べた方がうまいと思った人間

骨だけスープで煮込めば旨味が出ると気づいた人間


どれ一つ抜けたとしても、現代のラーメンは完成しないけれど、どれ一つとして自分が再現できる気がしない。


## ここで大きく出る

詰まるところ、その辺にある一杯のラーメンは、長い長い人類の歴史の中でたくさんの人間たちが積み上げてきた研鑚の結晶だった。


我々が、1時間の労働により手に入れることができる1000円という対価によって、人類の文化の結晶に最もたやすくありつける。

こんなに素晴らしい世界があるだろうか。信じがたい。


## エンジニアとして

ひょっとして、自分が今やっている仕事も、「これや！」とか「もう少し」とかで生み出した新しい価値は、あとの人に繋がっていくのかもしれない。

ちょっとしたアルゴリズムだったり、なんてことないメソッドかもしれない。

名前は残らないかもしないし、ましてやありがたがってももらえもしないだろう。

それでも、将来誰かが気づかないところで喜んでくれるかもしれない。

こんなに嬉しいことがあるだろうか。明日も頑張って、いい仕事できるように頑張ろう。


気づいてしまって、そう思ってしまった。そしてまたラーメンを食らうのである。


終わり。
【golang】Goでbit全探索をしよう 

# 概要

先日、Goの勉強も兼ねて久しぶりにAtCoderの [ABC147](https://atcoder.jp/contests/abc147) に参加しました。

その際のC問題が **bit全探索** を使用する問題だったのですが

- **実装をパッと思いつかない**
- **Goの文法知らない**

で自分の貧弱さが浮き彫りとなってしまったので戒め(復習)のためbit全探索のGoでの実装をまとめます。


# Goのbit演算

Goのbit演算は以下のような感じです: 
参照: [Goプログラミング言語仕様](http://golang.jp/go_spec#Arithmetic_operators)

```go
const(
  A uint = 10   // 1010
  B uint = 12   // 1100
)

func main() {
  var bits uint
  
  // AND演算
  bits = A & B   // 1001
  // OR演算
  bits = A | B   // 1110
  // XOR演算
  bits = A ^ B   // 0110
  // AND NOT演算
  bits = A &^ B  // 0010
  // 左シフト演算
  bits = 1 << uint64(3) // 1000 : 2の3乗かかる
  // 右シフト演算
  bits = 8 >> uint64(3) // 0001 : 2の(-3)乗かかる
}
```

# bit全探索とは

bit全探索については、ネットの海を探せばいくらでも出てくるので詳細は割愛します。

中学・高校数学で以下のようなことを習った記憶があるかと思います:
> 並べられた$n$個の要素がそれぞれ2つの状態を持つ場合、全パターン数は $2^{n}$ 通りある。

設問に出てくる一見複雑なシチュエーションを上記の考え方に当てはめることで
網羅的に全パターンを探索しようと試みるのが**bit全探索**のアルゴリズムの主旨です。

## 例
3種類のOS Linux, MacOS, Windows のうち好きなOSを選んでください。ただし、複数選択可能です。

上記の回答の全パターンを数えるときに、各OSに関して 好き/嫌い の２パターンが独立して存在するので $2^3 = 8$ 通りとなります。

## 実装パターン
bit全探索をプログラムで実装する場合は、基本的に以下のパターンになると思います。

```go
var n int  // 独立な要素数

// bitsがn個の要素の各パターンを表す
for bits:=0;bits<(1<<uint64(n));bits++ {
  // bitsの各要素についてのループ
  for i:=0;i<n;i++ {
    // bitsのi個目の要素の状態がonかどうかチェック
    if (bits>>uint64(i))&1 == 1 {
      // 何かしらの処理
    }
  }
}
```

問題によってここから変形していくと思いますが
実装力をつけるためには型に慣れるというのは結構大事な気がします。

# 実装例

実際のコンテストで出題された問題に対して、bit全探索を利用した回答例を以下に示します。
(Goをビギナーのためクソコードな部分はぜひ指摘ください！)

## 問題
[ABC128 C - Switches](https://atcoder.jp/contests/abc128/tasks/abc128_c)

## 回答

onとoffの2つの状態を持つ $N$ 個スイッチということで、全パターン数は $2^N$ 通りです。

$2^n$ 通り各パターンに対して、

1. 電球に繋がる各スイッチのビットの0/1をチェック(ビット演算を活用)
2. 点灯しない電球がある時点で`break`して次のループへ
3. 全電球が点灯する場合、`count++`

を行う実装となっています。

```go
package main

import "fmt"

// Solve the problem of ABC128 C
func main() {
	var n, m int
	fmt.Scan(&n, &m)
	slist := make([][]int, m)
	for i := 0; i < m; i++ {
		k := 0
		fmt.Scan(&k)
		slist[i] = make([]int, k)
		for j := 0; j < len(slist[i]); j++ {
			fmt.Scan(&slist[i][j])
		}
	}
	plist := make([]int, m)
	for l := 0; l < m; l++ {
		fmt.Scan(&plist[l])
	}

	count := 0
	for bits := 0; bits < (1 << uint64(n)); bits++ {
		ok := true
		for j := 0; j < m; j++ {
			sum := 0
			for _, sNo := range slist[j] {
				sum += bits >> uint64(sNo-1) & 1
			}
			if sum%2 != plist[j] {
				ok = false
				break
			}
		}
		if ok {
			count++
		}
	}
	fmt.Println(count)
}

```

各電球主体に考えだすとパターンが複雑で混乱しますが、
スイッチの状態主体に考えると網羅的に探索できると思います。

ここら辺の発想は、bit全探索が使える問題をいくつか解くと勝手に身に付きます。
自分の場合、AtCoderの問題をユーザーの投票でカテゴリ分けする

[AtCoder Tags - bit全探索](https://atcoder-tags.herokuapp.com/tags/Searching/Bit-Brute-Force)

というサービスで似たような問題をまとめて解きました。便利！


# まとめ

- Goでbit全探索を実装できるようになった
- bit演算の感覚をつかもう
- bit全探索を使えるシチュエーションに慣れよう
【Discord】配信開始をCouchBotで通知する【Bot】

#DiscordにBotで配信開始を通知する
**目的**：DiscordのBotであるCouchBotをサーバに招待し、テキストチャンネルにYoutube liveの開始を通知する。
CouchBotの招待から、配信開始を通知させる設定までを説明する。

**前提**：Discordのサーバの**管理人**である。
なぜならば、管理人でない場合はサーバーへのBotを招待する権限がないためである。


##CouchBotの招待
[CouchBot](https://top.gg/bot/308371905667137536)からinviteをクリックしBotを招待する。
Discordのログイン画面に遷移するので、項目を埋めてログインする。
Botを追加するサーバーを選択し、許可する権限を確認して認証をクリックする。
ロボットではないことを確認すると、選択したサーバーにBotが追加される。

Discordのサーバーのメンバー一覧に、CouchBotが参加していたら成功である。


##通知用テキストチャンネルの作成
配信開始の通知先にするためのテキストチャンネルを設置する。
ここからはDiscordのアプリケーションから設定を行う。

###テキストチャンネルを作成
カテゴリー名の右にある＋をクリックすると、チャンネル作成画面が開く。
チャンネルの種類は、テキストチャンネルを選択し、適当なチャンネル名をつけて、チャンネル作成をクリックする。
チャンネルの一覧に、作成したチャンネルが追加されていることを確認する。

###権限の設定
作成したチャンネルの名前の右側にある歯車マーク⚙をクリックし、編集画面を開く。
権限タブを開き、ロール/メンバーの右側にある直和記号⊕をクリックし、ロールのCouchBotを追加する。
ここまでで、およそ半分ほどである。あなたはよくやっている。頑張れ。

##CouchBotの設定
ここからはCouchBot自体の設定をする。
以下に出てくるコマンドは、すべてテキストチャンネルに打ち込むことでBotの設定を行う。

###Admin権限を付与する
Admin権限を自分に付与する。自分のDiscordのユーザー名を`UserName`の部分に入力する。

`!cb admin add @UserName`

なんでAdminの設定するかは聞くな。

###通知したいYoutubeチャンネルを登録する（通知元）
通知したいYoutubeチャンネルのチャンネルIDを、`YouTubeChannelID`の部分に入力する。

`!cb youtube add YouTubeChannelID`

チャンネルIDはYoutubeチャンネルのトップページのURLが`https://www.youtube.com/channel/hogehoge`だとすると、`hogehoge`がチャンネルIDである。
実際は、半角大小英字で構成された24文字の文字列である。

複数のチャンネルを登録したい場合は、上記のコマンドを各々のチャンネルIDに変えて繰り返し実行する。

###通知を送るテキストチャンネルを登録する（通知先）
通知を送る先のテキストチャンネルをCouchBotに登録する。
`DiscordChannelName`の部分に通知用テキストチャンネルの名前を入力する。

`!cb channel live #DiscordChannelName`

###通知を許可する
CouchBotの通知を有効にする。

`!cb allow live true`

以上で設定は完了である。お疲れ様。

#余談
この記事ではYoutube liveの通知だけを取り扱っているが、新しい動画の公開の通知も行うことができる。
また、Youtubeだけではなく、その他多くの動画配信サイトに対応している。
それらの設定方法は[こちら](https://couchbot.readthedocs.io/en/latest/index.html)(英語のサイト)を参照していただきたい。

>参考ページ一覧
[DiscordにTwitchの配信を通知する「Couch Bot」の導入と設定](http://tenmihi.hateblo.jp/entry/2017/09/03/190006)
[CouchBot’s documentation](https://couchbot.readthedocs.io/en/latest/index.html#)
[CouchBot](https://top.gg/bot/308371905667137536)
K3s on ConoHa

# はじめに

この記事は[ConoHa Advent Calendar 2019](https://qiita.com/advent-calendar/2019/conoha)の12日目の記事です。
ConoHaで安価にKubernetesを始めようという内容です。

# きっかけ

普段は[OpenShift](https://www.redhat.com/ja/technologies/cloud-computing/openshift)をオンプレで運用しています。OpenShiftは[Kubernetes](https://kubernetes.io)をベースにしていますが、いろいろお膳立てしてくれるためコンテナ基盤としては比較的とっつき易いです。しかし、OpenShiftには独自の作法があるので、たまに素のKubernetesを試したくなる時があります。そんなとき、マネージドなKubernetesではなく、あえてConoHaを選ぶ人も多いと思います。（このはちゃんかわいいという理由で。）

ConoHa VPSの最安プランはメモリが512MBと控えめで、Kubernetesを動かすには不足です。しかし安さにはかえられません。そこでおすすめしたいのが、軽量Kubernetesである[K3s](https://k3s.io)です。先月[v1.0.0](https://github.com/rancher/k3s/releases/tag/v1.0.0)がリリースされたばかりなので、是非この機会にKubernetesデビューしてみましょう。

# 環境

Ubuntu 18.04の512MBプランで動作確認していますが、他の環境でも大丈夫だと思います。

# インストール

K3sのインストールは非常に簡単で、シングルノード構成であればスタートアップスクリプトだけで完結します。以下の内容をコピペしてください。

```sh
#!/bin/sh
curl -sL http://get.k3s.io | sh -
```

あとはsshかコンソールでログインして、

```
# kubectl get node
NAME             STATUS   ROLES    AGE   VERSION
hostname     Ready    master  1m   v1.16.3-k3s.2
```

などとすれば良いです。

以上で終わりなのですが、これだけというのもつまらないので証明書の取得を行います。

# DNS認証の自動化

Kubernetesではリバースプロキシを使って複数のWebサービスを公開することが多いです。そこで便利なのが[Let's Encrypt](https://letsencrypt.org)のワイルドカード証明書で、その取得には[DNS認証](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge)が必須です。

最近はドメインの取得からDNSの設定までConoHaだけで済むようになっているので、これを利用するのがベストです。K3sではデフォルトのリバースプロキシとして[Traefik](https://traefik.io)を採用していますが、実は[ConoHa APIと連携したLet's EncryptのDNS認証](https://docs.traefik.io/https/acme/#providers)が可能です。（この辺りの話は@sekaiさんの[去年の記事](https://narusejun.com/archives/25/)が詳しいです。というかこの方のおかげ。）

これを利用すれば、スタートアップスクリプトで証明書の取得まで済ませることができます。以下が設定例です。メールアドレスやドメイン名、APIの認証情報は適宜変更してください。（事前にConoHaコントロールパネルでドメインを取得して、DNSにドメインを追加しておく必要があります。仮想マシンの作成後、AレコードにIPアドレスを追加するのを忘れないでください。）

```yaml
#cloud-config
write_files:
- path: /var/lib/rancher/k3s/server/manifests/traefik.yaml
  content: |
    apiVersion: helm.cattle.io/v1
    kind: HelmChart
    metadata:
      name: traefik
      namespace: kube-system
    spec:
      chart: stable/traefik
      valuesContent: |
        rbac:
          enabled: true
        ssl:
          enabled: true
        acme:
          enabled: true
          email: "root@example.com"
          staging: false
          domains:
            enabled: true
            domainsList:
            - main: "*.example.com"
            - sans:
              - "example.com"
          challengeType: dns-01
          dnsProvider:
            name: conoha
            conoha:
              CONOHA_API_USERNAME: ""
              CONOHA_API_PASSWORD: ""
              CONOHA_TENANT_ID: ""
              CONOHA_REGION: ""
runcmd:
- curl -sL http://get.k3s.io | INSTALL_K3S_EXEC="--no-deploy=traefik" sh -
```

TraefikのHelm Chartの詳細な設定は[ここ](https://github.com/helm/charts/tree/master/stable/traefik)を参照してください。

# まとめ

K3sクラスタを一発で作成するコマンドラインツールを作るつもりだったのが、スタートアップスクリプトで充分じゃないかと思い直し、今回の内容になりました。コントロールパネルを使った方がこのはちゃんかわいいというメリットもあります。

K3sはMicroK8sと異なり、マルチノード構成での本番運用も見据えたディストリビューションです。試して終わりにせず、今後の運用についても報告していきたいと考えています。

なお、本記事のスクリプトではセキュリティは考慮していないので、必要に応じて設定するようにしてください。
カンファレンススタッフのススメ！

[PHPカンファレンス2019](https://phpcon.php.gr.jp/2019/)の当日スタッフをやってみました！
カンファレンスに参加したことはありますが、スタッフ側は初めてでした。やってみて、良かったことを残しておきます。
みんなで、スタッフやろうぜ！

# なぜやろうと思ったのか
* やったことないし、やってみるかというノリ
* 後輩が去年やっていた（楽しそう）
* 社外の人と交流したい

まぁ、なんとなくですね。勢いとノリが大事！

# 何をしたか
## 事前スタッフミーティング
当日の2週間くらい前に事前MTGがありました。
場所は六本木のDMMオフィス。責任者の紹介、各人の役割の説明、同じ班？の人との打ち合わせがありました。
自分は、会場係だったので、あまり打ち合わせることもなく。
その後、スタッフ懇親会がありました。

## 当日
前日準備もありましたが、自分は仕事で行けず。
当日、朝早くから会場に集合しました。
会場係だったので、椅子並べたり諸々の準備をし、カンファレンススタート。
会場では、来場者の誘導や、質問者にマイク渡したりとか、してました。

## 懇親会
カンファレンス終了後、チケットを買った来場者とスタッフとで懇親会がありました。
これがかなり面白かった。みんな酔っ払って、テンション高い中でのLTは面白かった。
あとは、スタッフ同士普段の仕事の話をしたり。勉強になりました。
その後は、スタッフ打ち上げへ。ここも勉強になりました。


# 良かったこと
## 普段会わない人と交流できる
**WEBの中の人がいました。**
雲の上のような話が聞けて、面白かったです。

**PHPカンファレンスのスタッフなのに、みんなPHP書いてない。**
コアスタッフの人の方が書いてなかった。

**色んな人いる。**
エンジニア、デザイナ、ディレクター、大学生、女性、男性、女装、などなど。エンジニアばかりだと思っていたのに意外でした。
優秀な大学生がいたり、WEBで活躍している人がいたり、他社の実情聞いたり、とても勉強になりました。

## 意外とふつうに発表聞ける
会場係なので、その会場の話は聞けますし、休憩時間に見たいもの回ったり。
オープニングと最後のLTもやることなかったので、聞けました。
やっぱり、刺激多くて楽しいですね。

## グッズいっぱいもらえた
例年はTシャツだけみたいですが、今年はパーカーとelePHPantがもらえました。
お弁当も出ました。

## 楽しい
- 楽しいよ！

# 良くなかったこと
- 朝が早い

# こうすると良いよ
- 誰かと一緒に参加するとやりやすいよ。
    - 後輩がたまたま参加していたので、あまり心細くなかった。笑
- 懇親会は名刺があると良いよ。
    - なんやかんや名刺交換する。
- Twitterはあると良いよ。
    - みんなTwitterやってる。つながりやすい。
    - FBでもつながった。
- 積極的に話しかけたら良いよ。
    - 自分が心細いのと同じで相手も心細いよ。

# まとめ
一日フルで動いて、すごい疲れたけど、とても楽しかったし、良い経験になりました。
来年もやってみたい、コアスタッフもやってみたい、LTとかもやってみたい、なんならいつか弊社スポンサーとしても出したいと思いました。


みんなで、スタッフやろうぜ！
Update, FixedUpdate, AddForce, Input などについて

# ネタ元
https://qiita.com/yuji_yasuhara/items/6f50ecdd5d59e83aac99

# tl; dr

## 以下は Update でも使える(いつ使っても、その1度きりの呼び出しで(どのような時間の流れ方倍率でも)同じ効果が得られる)
- AddForce (ForceMode.Impulse) // 質量の影響を受ける(重ければ変化しづらい)力を加える
- AddForce (ForceMode.VelocityChange) // 質量を無視して速度を加える

##  FixedUpdate のみで使う((連続したFixedUpdateで)何度か連続して使い続けられることを想定している。)
- AddForce (ForceMode.Force) // 質量の影響を受ける力を加える
- AddForce (ForceMode.Acceleration) // 質量を無視して加速度を加える

## 以下は Update のみで使える
- Input.GetKeyDown // キーが押下されたUpdateのその1フレーム内で有効(FixedUpdateのフレームではない)
- Input.GetKeyUp // キーが押下されたUpdateのその1フレーム内で有効(FixedUpdateのフレームではない)

## 以下は FixedUpdate でも使える
- Input.GetKey // キーが今押されているかどうかの判断なのでフレーム関係ない

## つまり

ボタンが押された瞬間に力を加える(ジャンプめいた処理) → Update で Input.GetKeyDown を見て AddForce (ForceMode.Impulse)

ボタンを押している間は力を加える(移動めいた処理) → FixedUpdate で Input.GetKey を見て AddForce (ForceMode.Force) 

# おまけ
https://docs.unity3d.com/ja/current/Manual/ExecutionOrder.html
Railsしか知らないけれどあるアプリケーションを作る時、DBが必要ないことに気づいた。

#経緯
あるアプリケーションを作ろうとした時に、あれ、これRailsじゃない方がいいんじゃ、、と思ったが、私、Railsぐらいしかまともに触ったことがないため、そのままRailsで開発することを決意。

さて、DBは必要ないため`rails g model`をする必要もないためそのまま`rails s`したらエラー。。


#処置
予想はしていたが、やはりダメらしいので、DBなしでRails newする方法をググると、、

```ruby:ターミナル
$ rails new アプリ名　-O
```
でdb無し仕様railsアプリ完成！！


#まとめ
DB指定したり、DBのバージョンを変えたりしましたが、今回はDBをそもそも作らないことにしました。
作っても別に影響はないのだろうけれど。

とりあえずRubyonRailsで一つのアプリケーションを完成させるところまで備忘録を続けてみる。
Winhttp Proxy設定したら環境が逝きそうになった話

# 要約

わい「Winhttp Proxy設定しよ」
Windows Update「わしじゃよ！」

# はじめに

やらかした話が盛り上がる年末ときいて、ひと月ふた月ほど前にやらかした話を供養したいと思います。
なお、皆さん大好きな本番環境でのやらかしですが、残念ながらダメージはかすり傷程度でした。
~~もうほとぼりも冷めてると思うし~~
凡ミスのたぐいなのでどうか皆様もお気をつけください。

# 何が起こったのか

要約で書いてあるとおりなのですが、

1. Winhttp Proxyを設定したら(開けたら)
2. Windows Update サービスがアップデートを~~勝手に~~始め
3. 環境が逝きそうになりました。

## 環境

Windows クライアントはProxyを通らないと外部インターネットには接続できず、
直接GWに行っても基本的にはブロックされる一般的な環境
くだんのWindows Update自体もProxyを通らないとアップデート ファイルをダウンロードできない

## Windows クライアント

Winhttp Proxy：未設定
Windows Update サービス：生きてる
WSUS：なし
Windows Updateの実行：君のような勘のいいガキは嫌いだよ

このような状況をろくに確認せずWinhttpを設定したら、Windows Update サービスは生きており、
WSUSもないのでグローバルのアップデート ファイルのダウンロードを始め、
気づいた頃にはダウンロードとインストールが終わっていました。

# 不幸中の幸い

もともと、WinhttpはADからGPOで設定を配布しようとしていました。
しかし、GPOの追加にはいろいろ処理だったりなんだりが必要とのことだったので、
念の為とWindows クライアント1台にのみ実施した作業でした。
そのため、影響はこのクライアント1台のみにとどまりました。

# Q & A

Q. Windows Updateのなにがだめなの？
A. 色々理由があってこの環境ではクライアントの状態が同一でなければなりませんでした。
　 Windowsのバージョンも同一の必要があるため、1台だけアップデートされると困るのでした。

Q. Windows Updateの設計どうなってるの？
A. 別チームの担当なので詳しくはわからないです。
　 あともう関わりたくない・・・

Q. そもそも気づけなかったの？
A. いや、まともな環境ならWSUSでWindows Updateくらいしてるだろうし
　 仮にWindows Update実行しないならサービスのスタートアップ無効化してるじゃないですか！
　 まさかWindows UpdateをWinhttp閉じてるだけで無効化に近いことやってるとは思わないじゃないですか！
GitHub Actions でキャッシュされない罠

GitHub Actions の「beta」が取れ、キャッシュもできるようになったので、色々遊んでいます。
キャッシュの中で思わぬ罠に囚われてしまっていたので、共有しておきます。

# 結論

**key** が同じだと、**キャッシュ対象のファイルに変更があったとしても**、キャッシュが上書きされないという点です。
つまり、一度正常で無い状態で保存されると、それ以降は更新(保存)されません。 [^1]

当たり前といえば当たり前ですが、[公式にある examples](https://github.com/actions/cache/blob/master/examples.md) 通りに使用すると、この問題に気づかずに引っかかってしまうような気がします。

[actions/cache](https://github.com/actions/cache) を使用すると、job の最後に保存処理が行われますが、そのログを見ると下記のように書いてあります。

```sh
# 通常の保存処理
Post job cleanup.
/usr/bin/tar -cz -f <キャッシュ保存パス> -C <キャッシュ対象パス> .
Cache saved successfully

# 既に同一キーのキャッシュが存在する場合
Post job cleanup.
Cache hit occurred on the primary key <KEY>, not saving cache.
```


# 具体例

## 前提

iOS で carthage を使用していたとします。
GitHub Actions で下記のような step を実行するとします。
キャッシュに関しては、[公式に書いてある example](iOS で carthage を使用していたとします。) 通りに記述しています。

```yml
- uses: actions/cache@v1
  with:
    path: Carthage
    key: ${{ runner.os }}-carthage-${{ hashFiles('**/Cartfile.resolved') }}
    restore-keys: ${{ runner.os }}-carthage-

- run: carthage bootstrap --platform iOS --cache-builds
  env:
    GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

## 実行の流れ

### 1度目 の実行
- 最初はキャッシュがないのでリストアされない
- `$ carthage bootstrap` が **途中でなんらかのエラー** [^2] → `Carthage/` フォルダ内は不完全<br>
※ exit status は 0 とする
- 不完全な `Carthage/` ディレクトリを保存

### 2度目 の実行
- キャッシュをリストア
- `$ carthage bootstrap` は有効なキャッシュがあれば使用する [^3] が、今回は無いので、ゼロからすべてインストール。<br>
つまり `Carthage/` ディレクトリ内は完全な状態。
- 同一のキーで既にキャッシュ済みなので **保存は行わない** → `Carthage/` フォルダ内は不完全なまま！

### 3度目 以降

「2度目の実行」と全く同じ処理になる。
つまり、キャッシュを使用して `$ carthage bootstrap` の処理を早めたいのに、毎回ゼロから実行しているのと同じことになる。キャッシュ機能を利用していないのと同じことになる。

## 解決策

ようはキーが毎回変わればいいわけです。
自分は下記のように `-${{ github.sha }}` を付け足しました。

注意すべきは、`key` は毎回変わるので正しくリストアされるように `restore-keys` を指定することです。
また、キャッシュが毎回上書きされるということは、正常な状態のキャッシュを不正常なファイルで上書きしてしまう可能性があるということも念頭に置くべきです。

```yml
- uses: actions/cache@v1
  with:
    path: Carthage
    key: ${{ runner.os }}-carthage-${{ hashFiles('**/Cartfile.resolved') }}-${{ github.sha }}
    restore-keys: ${{ runner.os }}-carthage-
```



[^1]: [7日以上キャッシュにアクセスしない](https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy)など、削除された場合はこの限りではありません。
[^2]: 本文中には記述してありますが、環境変数 `GITHUB_ACCESS_TOKEN` を記載しないと GitHub の API 利用制限に引っかかる可能性が高いです。この場合 exit status は 0 となります。<br>参照: http://yudoufu.hatenablog.jp/entry/2016/06/09/011754
[^3]: `--cache-builds` を指定しているので。
Fortranよどこへ行く？

# 概要
ポエムです．

# 第5回並列Fortranシンポジウム
今年8月2日に，[第5回並列Fortranシンポジウム](http://site.hpfpc.org/home/events/parallel_fortran_sympo5)が開催されました。これは，Fortran規格について議論するISO/IEC Fortran Committee WG5国際会議が東京で開催される事を受けての開催であり，WG5の前議長John Reid氏と現議長Steve Lionel氏の両名を招いて，Fortranの将来についての講演と，フリーディスカッションが行われました．

当日のプログラムは，以下のようになっています．

- 日本における Fortran 規格化の歴史
- Coarrays in Fortran 2008 and Fortran 2018
- Fortran Today and Fortran Tomorrow
- フリーディスカッション

シンポジウム開催にあたり，事前に質問の受付がありました．それらの質問に対してフリーディスカッションで議論したと聞いています．
残念ながら我々は参加できなかったのですが，モダンFortran勉強会としていくつか意見や質問を送りました．

# 質問に対する回答
本日，第5回並列Fortranシンポジウムで出た意見や質問，事前に受け付けていた質問に対する[回答](http://site.hpfpc.org/home/events/parallel_fortran_sympo5/qa)が公開されました．

モダンFortran勉強会として送った意見・質問については，実のところ締切を大幅に過ぎており，主催者の方からその旨と質問に対するコメントは頂いていたのですが，どうやら両方にも繋いで頂けたようです．この場を借りて，ご対応にお礼申し上げます．

回答からは，Fortranという言語として，下記2点を維持し続けようとしている姿が見えてきます．

- 効率的な実行
- 古いプログラムとの互換性の担保

また，最も印象的だったのは，Q25（数値計算用の言語としてすら不親切で不十分）に対する回答です．

> この要望には，共感する部分もありますが，Fortranの強みは，特にスーパーコンピューター上での高性能にあります。MATLABと競争しようとするのは，間違っているでしょう。（主催者訳）
> While we are sympathetic to this wish, Fortran’s strength lies in high performance, especially on super-computers. It would be a mistake to try to compete with MATLAB.（原文）

# 回答に対して思うこと

Fortranの強みは何か，何を目指しているかが非常に明快な回答だと感じました．

Fortran 2003で導入されたオブジェクト指向プログラミングの評判（使い勝手ではなく，機能があること自体）が悪いと聞いており，非常に不思議だったのですが，確かにこの方向を目指すのであれば，オブジェクト指向プログラミングは鈍重だし，使う人は多くないでしょう．

回答を眺めると，規格策定の場において以下の様な共通認識がある印象を受けました．

- Fortranで重要なのは，実行効率と後方互換である
- 規格でサポートしない範囲は，ライブラリがサポートすればよい
- 各ベンダの実装の負担になるような大きな機能は避けたい

WGとしては保守的なのでしょうが，必須と思われる機能（変数のバイト数を指定する定数等）の導入が遅かったり，それより前にやることあるんじゃない？と思われる機能が導入されたりと，委員の趣向が色濃く反映されているのかな？とも思います．また，物理定数を規格で用意して欲しいとの要望がこれまで無かった，というのも意外でした．

さて，最も印象的だった回答に対して，「なるほど，Fortranのターゲットは非常に明快だ」と思う一方で，「スーパーコンピュータで性能を出すことを目的としてFortranに乗り換える人は，どれくらいいるのだろう？」という疑問も湧いてきます．

現代では様々な言語が存在し，それぞれが使い勝手を改良しています．Matlab，C/C++言語，Python，Juliaなど，Fortranの代替となりうる言語は多く存在します．ここでいうFortranの代替とは，数値計算を行うためのプログラミング環境だけでなく，大学で取り扱われる，プログラミング学習用の言語という意味もあります．

プログラミングの講義でPythonを習い，実験でMatlabを使っていた学生が，スーパーコンピュータで数値計算をやりたいからFortranを使い出す，という状況がどれくらいあるでしょうか？その学生に，C++ではなくFortranを選ばせるような魅力は何でしょうか？乗り換えた後に（満足はしなくても）使い続けるだけの使い勝手を備えているでしょうか？

我々は，完璧ではないにしても，使い続けるだけの魅力がFortranにはあると思っています．しかし，奇しくも昨年度のAdvent Calendarの[記事の最後](https://qiita.com/implicit_none/items/8229d1931cd236d62ca9#%E7%B5%82%E3%82%8F%E3%82%8A%E3%81%AB)で述べたように，高い性能を得るにはFortranでなくてもよいという状況になっており，過去の資産とコンパイラ最適化でパワープレイをしていたFortranという恐竜が，柔軟性のなさから環境変化に対応できず，頭数を減らしたような印象も持っています．

Fortran規格が使い勝手を重要視しないのであれば，コミュニティあるいは個人がその役割を担うしかありません．今後，Fortran規格が改定されていくとして，やらなければいけないのは

- Fortran自体の使い勝手を改善する機能の提供
- 数値計算等のライブラリの充実（インタフェースの改良も含む）
- 情報発信

の3点でしょうか．

回答の中には「その機能はすでに提供している」旨の回答がいくつも見受けられます．これは明らかに情報発信不足に起因するので，まずはよい情報も悪い情報も積極的に公開することから始めなければならないでしょう．

# Fotranよ，どこへ行く？
Fortranの行き先は極めて明確でした．しかし，そこに向かうユーザの姿は，明確ではありません．
終わったら「できた！」ってコマンド叩いて気持ちよく言いたい。あのビストロの時のように

# はじめに

この記事は、[Hamee Advent Calendar 2019](https://qiita.com/advent-calendar/2019/hamee) の12日目のエントリです！
担当しますのはHamee株式会社、新卒3年目インハウスデザイナーの[ブライアン](https://twitter.com/skinnybrian_tw)です！！
今回もよろしくおねがいします( ´ ▽ ` )ﾉ

# こんな経験ありませんか
僕はよく、もくもく作業を1人でやったり、はたまた友人や先輩たちとやったりすることが多いです。

そんなあるとき。そう。これが言いたい時は必ずやってきます。

### 僕「できた！！！！」

### そして周囲の人達「おお〜〜〜👏👏👏👏」

そう。
完成した時。とてもキリがいい時。自分にLGTMを贈りたい時・・・・・。
その時僕の心は幸福に満ち溢れています。

この幸せを追い求めるからこそ、私達ものづくりする人間は日々成長していくのだと思うのです。

# この幸せを、最高潮にできるたった1つの方法

数年前に僕の実家で、母親が月曜夜10時からとあるバラエティ番組をよく見ていたやつがあったのですが。
その番組は、どうやら2人チーム対抗で料理バトルをするコーナーがあり、
料理が完成したら「できた！！」って２人でせーのっ！で声を合わせて言う定番シーンがありました。

その時をふと思い出したんです。
この「できた！」の後、なんかこう・・・心がとてもウキウキする効果音というか、BGM的なのが流れてて、
あっ・・・・これだ・・・・・「できた！」って思ったときにいつでも鳴らせる環境があれば、できた後の幸せを最高潮にできるぞ・・・！！！



# というわけで
その環境を作っていきましょう。

## 用意するもの
- Mac
    - お近くのAppleストアで購入可能です。
- ターミナル
    - iTermでもターミナル.appでも。お好きなものをどうぞ。
- 音声ファイル
    - 「できた！」の後に流したいBGMや効果音を用意します。

## この環境を実現するコマンド
`afplay` というコマンドを使います。Macにしかないようです。
このコマンドを使えば以下のように、引数でmp3等の音声ファイルを与えるとターミナル上で再生することができます。

```shell
$ afplay hoge.mp3
```

はい、基本これだけ。

# エイリアスをつくって・・・

お好きなコマンド名をエイリアスで指定してあげます

```shell:.zshrc
alias dekita="afplay ~/path/to/file/dekita.mp3"
```

# ソース読み込ませて・・・

```shell
$ source ~/.zshrc
```

# 「できた！！！！」

```shell
$ dekita
```

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">で、出来た！！！<a href="https://twitter.com/skinnybrian_tw?ref_src=twsrc%5Etfw">@skinnybrian_tw</a> <a href="https://t.co/LlBoj39GHP">pic.twitter.com/LlBoj39GHP</a></p>&mdash; HIROKI (@littlejazzbass) <a href="https://twitter.com/littlejazzbass/status/1094258282309382144?ref_src=twsrc%5Etfw">February 9, 2019</a></blockquote>

*あ〜〜気持ちいい〜〜・・・・。これだよ・・・俺の求めていた幸せ・・・。*

これでいつでも、「できた」時の感情を最高潮にさせることができるようになりました。
※僕のお友達がデモ撮影してくれました。

# 応用編
↑の仕込みが事前に必要ですが、あなたの手元にあるシェルスクリプトの最終行などに追記しておけば、
処理が終わった後に幸せを最高潮にできます。
もう、あなたの好きなところに仕込んでください。

```shell:sample.sh
#!/bin/sh

ln -sf ~/dotfiles/.vimrc ~/.vimrc
ln -sf ~/dotfiles/.zshrc ~/.zshrc
.
.
.
.
.
.
dekita
```

# おわりに

素敵なものづくりライフをお送りください( ´ ▽ ` )ﾉ
.bat バッチファイルで sudo もどき

# これは何

Windows のバッチファイルで、 sudo っぽいことをする方法を紹介します。

- できること
    - 管理者権限で実行
    - 実行コマンドの終了コード(`%errorlevel%`)の取得
- できないこと
    - 現在のコマンドプロンプトで実行。必ず新しいウィンドウが開きます

# 想定読者

pip や choco コマンドを実行する時、管理者権限つきターミナルを起動し忘れる人

# 結論

```bat:sudo.bat
@echo off
setlocal
if ""=="%~1" exit /b 1
set "cmd=%~1"
if ""=="%~2" goto :parse_end
set "args="
shift
:parse
if not "%~1"=="" (
  set args=%args%,\"%~1\"
  shift
  goto :parse
)
set args=-ArgumentList %args:~1%
:parse_end
powershell -command "exit (start \"%cmd%\" -Wait -PassThru -Verb runas %args%).ExitCode"
exit /b %errorlevel%
```

# 使用例

```
sudo.bat py -m pip install tensorflow
```

管理者権限のウィンドウが新たに開き、そこで pip が走ります。

# 感想

実行直後にウィンドウが閉じてしまうため、エラー修了したときの原因を追うのが困難。
pip とか　choco とかでしくじったときに確認したいとき使い勝手が悪すぎるぅぅ。
終了コードが取れるだけましだけど、 `if errorlevel 1 pause` とかでウィンドウを閉じるのを止めたいところと思って、 pause を仕込んでみたけれど start-process が完了したときにウィンドウが閉じてしまっているので意味なかった。
エラーでたら、管理者権限付与した cmd から実行し直すってことで。

# 参考リンク

[Windowsでsudoしたい](https://qiita.com/AinoMegumi/items/fd56711fe1fd2a0e1bbf#_reference-ed09ab347e1935f20565)
[How to make SHIFT work with %* in batch files](https://stackoverflow.com/questions/9363080/how-to-make-shift-work-with-in-batch-files)
[【Start-Process】PowerShellでプロセスをバックグラウンド起動する方法](https://cheshire-wara.com/powershell/ps-cmdlets/system-service/start-process-window/)
[Obtaining ExitCode using Start-Process and WaitForExit instead of -Wait](https://stackoverflow.com/questions/10262231/obtaining-exitcode-using-start-process-and-waitforexit-instead-of-wait)
[呼び出し元のバッチに戻り値を返す方法](https://bayashita.com/p/entry/show/132)
機械学習系の論文を読むときの6つのポイント


# はじめに

最近までというか、ついさっきまで我流で機械学習系の学術論文を読んできたのですが、どうも効率が悪いなーと感じていました。かつマレーシアにそんなことを教えてくれるような人も居ないので、有名なStanfordの講義「CS230」も観て得た「機械学習系の論文を読む際に抑えるポイント」を紹介します。（というか、この記事のコンセプトはもはや自分のためのメモみたいなカンジです）

# 読む論文をリスト化する

まず、自分が読みたい論文を5つリスト化します。

例えばこんな感じ。
![Slide1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549641/f47d2605-e40f-23c3-7767-ec91ca48ace9.jpeg)

横軸は達成率になっていて、100%は「読み終わった、理解した」。0%は「まだ読んでいない。手をつけていない」を表します。
そして100%に到達した論文は新しい論文に更新していくという流れです。（常に論文が5つある状態をキープする）

なぜこのようなことをするかというと、論文によっては最初読み始めた時に、「いや、今の自分のレベルと照らし合わせると少し難しいなー」ということがあると思います。そのような論文は一旦キープしておいて、自分のレベルにあった論文を読むところからスタートして、そのレベルに達したらキープしておいた論文を読むというフローを作る為です。（人間なんで、読む前からこれムズそうとか判断するの難しいですし...しかも英語やし...）

# 読み方

- **読む流れ**

1. Title、Abstract、Figures (図)　を抑える
2. Introduction、Conclusion、Figureを抑えて、そのあと軽く全体をザッと流し読みする。
3. 全体を読む。(ただし式などの数学の部分は飛ばすor軽く読むでOK)
4. 全体を読む（ただし、なんかはっきりとわからないところは飛ばしてOK）

なぜ全体を読む前にIntroductionとConclusionを抑えるかというと、著者はその論文のポイントのまとめをその2つに書いている場合が多いからです。

- **著者が何を成し遂げたのか、トライしたのかを理解する**
- **その研究のアプローチのキー要素を理解する**
- **その研究内容、結果を自分は何に使えるかを考える**
- **その為どんな参考文献を追いたいかを考える**

# 数学部分

ここは結構レベル高いが、新しいアプローチだったりアルゴリズムを作るヒントになることが多い。
例えば、Batch Normalizationの論文を読んで、スクラッチから実装する。

# コード

- 研究で使われたオープンソースのコードを実行してみる
- スクラッチから自分で実装してみる

# 読むペース

短期集中ではなくて、長期的な期間安定的に読む。オススメのペースは1週間に2、3論文。

# さいごに

以上、いかがだったでしょうか？
僕はこの読み方を今から実践して、また結果を記事にしようかなと思っています。

# 参考文献

[Stanford CS230: Deep Learning | Autumn 2018 | Lecture 8 - Career Advice / Reading Research Papers]https://youtu.be/733m6qBH-jI
WIndows キーの無いキーボードで Windows キーを使う

ヤフオクで間違えて [Win] キーの無い Realforce 106 (LA0100) を落札してしまったのでどうしようか悩み検索してみると、[Caps Lock] を [Win] キーに割り当てることができるらしい。

やってみたので手順メモ。
※注：入力を間違えると入力できないキーが出てくる可能性がありますので注意。パスワードとか打てなくなるかもしれません。また、開くところや追加するところを間違えるとどんな不具合が起きるか想像できませんので間違えないように注意。

イ、 管理者権限でレジストリエディタ (regedit) を管理者として起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306041/7c9dc636-47ca-609c-b58a-9968c351972d.png)

ロ、 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout を開いて左ペインの空いている部分で右クリックして「バイナリ値」を追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306041/d7b01338-148c-1714-552c-d864b54a83a4.png)
⇓ このように追加されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306041/37d7f5de-1fa3-66c3-3bba-d11ddac9f0c0.png)

ハ、 名前を「Scancode Map」へ変更する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306041/4d126b08-f4a8-cc90-f263-d9524158de2c.png)

ニ、 「Scancode Map」をダブルクリックして開いたウィンドウに以下の値を入力する
値の意味については末尾のリンクを参照

```reg:キーの値
0000 0000 0000 0000
0200 0000 5ce0 3a00
0000
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306041/70769da6-3e48-cdd0-dd4b-27fb26b4291a.png)

ホ、 OK を押して値が反映されたことを確認
データ欄に値が入っていることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306041/5d9635af-632b-6a3e-52bd-267d63a84aa9.png)

ヘ、 再起動
再起動しないと反映されないので Windows の再起動。
起動後にログインし、設定が反映されたことを確認。

参照 [レジストリを修正してCAPSLOCKの割り当て変更](http://yanor.net/wiki/?Windows%2FTIPS%2F%E3%83%AC%E3%82%B8%E3%82%B9%E3%83%88%E3%83%AA%E3%82%92%E4%BF%AE%E6%AD%A3%E3%81%97%E3%81%A6CAPSLOCK%E3%81%AE%E5%89%B2%E3%82%8A%E5%BD%93%E3%81%A6%E5%A4%89%E6%9B%B4)
Terraform AWS Providerにドキュメント修正でContributeしました

# はじめに
7月頃にたまたまTerraformのAWS Providerのドキュメントに一部誤りを見つけ、
勇気を出して初めてのPull Requestを作った & めでたくマージしてもらいました。
→ [Update rds_global_cluster.html.markdown #9187
](https://github.com/terraform-providers/terraform-provider-aws/pull/9187)

AWS Providorのリソース: rds_grobal_clusterに関して、
ドキュメントの "Argument Reference" 入力必須である引数 "global_cluster_identifier" が書かれていないことに気づき修正したものです。

非常に小さいPRですが、OSS活動初心者目線での知見の共有が
今後Terraformをより良くしていく人を増やすためのきっかけになれば幸いです。

# 想定読者
- Terraformコミュニティへの貢献に挑戦してみたいと思っている人
- Terraformのドキュメントに誤りを発見したけれどもどこから報告したらいいかわからない人

# ドキュメントコントリビュートの流れ
## 修正箇所を特定する

[Terraform公式のCommunityページ](https://www.terraform.io/community.html)を参照すると、
Hashicorp社の持つ各種Providorのissueなどは
https://github.com/terraform-providers
で管理されていることがわかりました。

今回は後者のオーガニゼーションから[対象リポジトリ](https://github.com/terraform-providers/terraform-provider-aws)にたどり着きました。

更に、AWS Providorの場合、ドキュメント類は[こちらのディレクトリ](https://github.com/terraform-providers/terraform-provider-aws/tree/master/website/docs)に集約してあるようでした。
(※ `d/` ディレクトリはdatasource, `r/`はresource, `guide/` はprovidor自身のガイド)


## コントリビューションガイドラインを探す
プロバイダのREADME.mdから飛べる[ガイドライン](https://github.com/terraform-providers/terraform-provider-aws/blob/master/.github/CONTRIBUTING.md)を一読しておきます。
ドキュメント更新も含め、コントリビューション時に気をつけるべき心得が書いてあります！

## 修正
プルリク一覧を検索し、既に同様のプルリクが出ていないかを確認したら
修正に取り掛かります。

GitHubにおけるOSS修正の一連の流れはこちらがとても勉強になります！
 →[GitHubでフォークしてプルリクしてOSSにコントリビューションする](https://qiita.com/sotoiwa/items/327f4f4e5cdb0e2bd2f9)

また今回参加してるterraform Advent Calendar 2019 7日目の yutachaos さんの素敵な記事も
是非に是非にご参照ください！
→ [Terraform Registryに初めてcontributeしたときの話](https://qiita.com/yutachaos/items/6732895b89832324b29d)

## Pull Request
修正したらいよいよPullRequestを出します。
本文は[あらかじめ用意されたテンプレート](https://github.com/terraform-providers/terraform-provider-aws/blob/master/.github/PULL_REQUEST_TEMPLATE.md)に沿いつつ、直近他の方が出されてMarge済みのドキュメント修正のPRを参考に書いたところ、無事1日以内にマージいただくことができました。


# 反省点
Pull requestに対して感謝のコメントを頂いたものの（とてもありがたく嬉しいものですね）、
以下のご指摘をいただきました。

> Relating to the inclusion of forces new resource for arguments, please note that we do not typically intend to include this information with every resource documentation page as the Terraform plan output will show which can update in place as necessary and the documentation can easily become out of sync with the resource logic.

(筆者拙訳: "forces new resource"に関する記述はなくても`terraform plan` 時に気づけるし、今後実際のロジックとの同期が大変になる可能性があるため、すべてのリソースのページに含めるつもりはないので注意してください)

ということで、今後はこの点に関する修正は控えるようにしたいと思います。
ここに関してのみ更にPRを出すのは却ってレビュアーの方の手間を増やすのではないかと踏みとどまりましたが、そのあたりの温度感(直すべき or このままでよい)おわかりの方がいらしたら教えていただきたいです…。

# まとめ

反省は残りつつ、ドキュメント更新を通してTerraformへ貢献することができました。
改めてこの記事が今後Terraformをより良くしていく人を増やすためのきっかけになれば幸いです。
[Ruby on Rails5 アプリケーション プログラミング]学習ログ#1[2019/12/11]

**前回 ->**
**次回 -> [[Ruby on Rails5 アプリケーション プログラミング]学習ログ#2[2019/12/12]](https://qiita.com/CAD-guest01/items/0d8a89a724c588f8ec3f)**

---
#目的
### Progateで学んだことをローカル環境で手を動かして復習することで、基礎を固める

#使用する教材
###山田祥寛(2017). RubyonRails5 アプリケーションプログラミング　株式会社技術評論社

#Q.「RubyonRails5 アプリケーションプログラミング」とは？
#A.ProgateのRoRコースを終えた後にするRoRの勉強としておすすめされている本

出典
(Samurai Blog / Ruby on Rails学習本おすすめ6選【入門者〜上級者までレベル別に解説】)[https://www.sejuku.net/blog/110292]

---
#今日したこと
## 環境設定(p19~p20)
### CentOS7 / Ruby 2.6.5 / Rails 5.0.7.2

### 新規アプリ（アプリ名:railbook）の作成(p22~p24)
```:端末
rails new railbook
```
### アプリを起動してみる(p25~p26)
```:端末
rails s
```
ブラウザ(Mozilla Firefox)を使って**http://localhost:3000にアクセスしてみる**
->エラー吐いた
![An-error-message-rails-s.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547164/ec6c12b1-b207-811e-0c10-71e6044f15d1.png)

エラーコードコピペしてググったらすぐに解決法が出た。

```:端末
vi Gemfile
---------------------------------
[Gemfile]
'sqlite3'
を
'sqlite3', '~> 1.3', ' < 1.4.0'
に変更
---------------------------------
bundle up sqlite3
rails s
```
![An-success-picture-YouareonRails.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547164/863a7cb2-9f65-6348-1810-031d06c8b334.png)

>出典
[真夜中エンジニアリング / Rails 5.x: Specified 'sqlite3' for database adapter, but the gem is not loaded. Add `gem 'sqlite3'` to your Gemfile ](http://midnight-engineering.hatenadiary.jp/entry/2019/02/17/222012)

## コントローラーの基本(p27~p33)
### helloというコントローラを作る

```:端末
rails g controller hello
```
### hello_controller.rbに文字を出力するアクションメソッドを追記
### routes.rbにhelloコントローラのindexアクションを呼び出させるようなルーティングを行う

## ビューの基本(p34~p43)
### ERBとは？ -> HTMLにRubyを埋め込む(embedded)仕組みのこと
### テンプレート変数の設定
### テンプレートファイルの作成

## モデルの基本(p44~p62)
### O/Rマッパーとは？ -> オブジェクトモデル（アプリ側）とリレーショナルモデル（データベース側）間のギャップを解消するもの
### YAMLとは？ -> データの構造を**`インデント`**や記号で表現するファイル形式
### モデルクラスの作成
```:端末
rails g model book isbn:string ・・・
```
###マイグレーション（テーブルレイアウトを作成、変更する仕組み）ファイルを実行してテーブルを作成
```:端末
rails db:migrate
```
###rails dbconsoleでデータベースの内容を確認
```:端末
rails dbconsole
# テーブルの一覧を表示
sqlite> .tables
# booksテーブルの構造を確認
sqlite> .schema books
# booksテーブルの内容を確認
sqlite> select * from books;
```
###データ取得
#### 1. hello_controller.rbにlistアクションを追加
#### 2. app/views/helloにテンプレートファイル（list.html.erb）を作成
#### 3. routes.rbにhelloコントローラのlistアクションを呼び出させるようなルーティングを行う
###つまづいた（軽微）ところ
- アプリ固有の設定を定義するために、my_config.ymlを/configフォルダ配下に作成
- 初期化ファイルで明示的に読み込むために、my_config.rbを/config/initializersのフォルダ配下に作成
- hello_controller.erbにグローバル変数を使ったアクションメソッドを定義
- rails sで実行

->エラー吐いた

```:エラーの内容
(<unknown>): found character that cannot start any token while scanning for the next token at line 2 column 1 (psych::syntaxerror)
```
コピペしてググると解決法が出た

- ymlファイルはタブの使用が認められていないらしいので
my_config.ymlのタブを消してスペースに置き換えた

>出典
[teratail / ［Rails］［SyntaxError］$ rails db:create が出来ません。](https://teratail.com/questions/157758)

#コマンドまとめ
```:console
#アプリの作成
rails new appName [option]
#サーバの起動
rails s(erver) [option]
#コントローラクラスの作成(ビューの自動生成)
rails g(enerate) controller name [option]
#まとめて削除
rails destroy controller name [option]
#モデルの作成
rails g(enerate) model name field:type [option]
#マイグレーションファイルの実行
rails db:migrate
#sqliteクライアントを起動
rails dbconsole
```
---