OmniAICreator/Qiita-1.07M huggingface dataset:
raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{file_path} to define it" unless from_mod.const_defined?(const_name, false)

##errpr!

```
raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{file_path} to define it" unless from_mod.const_defined?(const_name, false)
```
##原因
controllerの名称間違いだった


```tests_controller.rb

TestController < ApplicationController
  def index
  end
end
```

##解決

名前を修正したら治った

```
TestController < ApplicationController
// ↓↓↓修正↓↓↓
TestsController < ApplicationController
```
railsでhas_manyなmodelを条件付きで取ってくるのをあらかじめ定義しておくと読みやすい


**近況**
転職してRailsマンに戻りました。(しばらくpythonおじさんだった)

## やりたいこと
has_manyしているテーブルをselectするとき、コントローラの中でfindとか書かずに予めmodelの中に定義しておきたい。
(見た目スッキリさせたいとか、変数当てる必要がないから定義済みにしといた方が安全とか色々理由はあると思う)

## どう書く？
lambdaを使うのが良いみたい。

```ruby:app/models/user.rb
class User < ApplicationRecord
    # Userに紐づく予定を記録したSchedulesテーブルがあり、そこから稼働日に該当する予定だけを抜き出したい
    has_many :work_day, lambda { where not_work_day: True }, class_name: Schedules.name
end
```

コントローラからはこんな感じで書く。

```ruby:app/controlers/user_controller.rb
def work_day
    @result = User.find(id).includes(:work_day)
end
```

参考: https://blog.falconsrv.net/articles/415
Python のグラフを GIF にしてみた

こういうGIFを作った話

![am_fm.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265627/6ff41558-d1bf-62e1-8258-145b3d7a0927.gif)


単純なグラフなどは matplotlib の機能でもできるが、上記の画像など複雑になるにつれ厳しくなってくる

なのでライブラリを探した結果 [animatplot](https://animatplot.readthedocs.io/en/stable/) がよさそうだったのでこれを使う。
簡単なグラフに関しては[公式のチュートリアル](https://animatplot.readthedocs.io/en/stable/tutorial/getting_started.html)が用意されている。

今回のような複数のグラフを使うコードは以下の通り。

```py
import numpy as np
import matplotlib.pyplot as plt
import animatplot as amp
from pylab import rcParams
rcParams['figure.figsize'] = 16, 8
%matplotlib ipympl # lab
%matplotlib qt

fs = 40000.0
fc = 40.0
fm = 4.0

fig, (ax1, ax2, ax3, ax4) = plt.subplots(4, 1)

for ax in [ax1, ax2, ax3, ax4]:
    ax.axis('off')

time = np.arange(fs) / fs
ts = np.linspace(0, 1, 100)
Xs, Ts = np.meshgrid(time, ts)

Y_modulator = np.sin(2.0 * np.pi * fm * (Ts + Xs))
Y_carrier = np.sin(2.0 * np.pi * fc * (Ts + Xs))
Y_am = np.sin(2. * np.pi * fc * (Ts + Xs)) * (1 + 0.9 * np.cos(2.0 * np.pi * fm * (Ts + Xs)))
Y_fm = np.sin(2. * np.pi * (fc * (Ts + Xs) + Y_modulator))
    
B_modulator = amp.blocks.Line(Xs, Y_modulator, ax=ax1)
B_carrier = amp.blocks.Line(Xs, Y_carrier, ax=ax2)
B_am = amp.blocks.Line(Xs, Y_am, ax=ax3)
B_fm = amp.blocks.Line(Xs, Y_fm, ax=ax4)

anim = amp.Animation([B_modulator, B_carrier, B_am, B_fm])
anim.save_gif("am_fm")
```

基本的には `matplotlib` の使い方と同じで、アニメーションを行う軸を `ax` で指定する。
最後に `amp.Animation` で複数のブロックを指定する。

アニメーションを付けるとわかりやすいので、今後も活用していきたい。
jQueryに頼らない！ DOM操作を伴うブックマークレットの作り方

# 概要
- jQuery使わないよ
- 基本的なDOM情報の取得・操作はJavaScriptの`querySelector` `querySelectorAll`を使うよ
- ネイティブのメソッド（querySelectorなど）を別の変数に入れて使おうとしたら怒られたよ
- querySelectorで取得できるNodeListは配列ではないので、配列のメソッドで処理する時は配列化しておくと便利だよ

# ブックマークレットとは
1. ブックマークに追加
2. 適当な名前をつけ、URLとして「`javascript:`」から始まるコードを保存。
3. 任意のページで実行する（そのブックマークをクリックする）と、そのスクリプトが実行できる。

# ES2015
自分が使えればいいので、ブラウザ対応は考えなくて良い。
思う存分最新のJS文法で書きましょう。

即時実行関数（一番外側のfunction）の内側に処理を書いていきます。

```js
(function() {
  "use strict";
  r();
  // 実行本体
  function r() {
    // ここに色々書いていく
  }
})();

```

# 取得→配列化
配列のメソッドを使って抽出・操作したいので、任意のDOMを取得したら即配列化します。
`domArr`は配列なので、`.map()` や `.filter()`、`.reduce()` など自由に使えます。 
※callメソッドを使えばNodeListのまま関数適用は可能ですが、繰り返しメソッドを適用する場合には面倒です。

```js
// 取得
const $dom = document.querySelectorAll('.className');

// 配列化
const domArr = [].slice.call($dom);

// スプレッド演算子を使っても良い
const domArr = [...$dom];
```

# 抽出
クラスで大まかに絞った後、「要素内のタイトルが「にゃーん」の要素だけに絞りたい」なんていうことをしないといけなかったりします。
配列のfilter、findメソッドの出番です。メソッド内で、任意の要素を取得し、そのtextContentを文字列比較して true を返すようにすれば抽出できます。
そもそも要素自体が取得できないケースもあるため、その場合はfalseを返すようにします。

## filter
複数の要素を抽出する場合に使います。

```js
const $target = domArr.filter(el => {
  const $title = el.querySelector('.title');
  if(!$title) { // そもそも要素が取得できないケースもあるので falseを返すようにする
    return false;
  }
  return $title.textContent === 'にゃーん';
});

// $targetは配列なので、抽出した1つの要素を操作する場合は $target[0] でアクセスする 
```

## find
最初に見つかった1つの要素のみで良い場合は、filterよりもfindの方が向いています。
挙動・返り値が変わるだけで、条件の書き方はfilterと同じです。
つまりリファクタリングしやすい、ということ。

```js
const $target = domArr.find(el => {
  const $title = el.querySelector('.title');
  if(!$title) { // そもそも要素が取得できないケースもあるので falseを返すようにする
    return false;
  }
  return $title.textContent === 'にゃーん';
});

// $targetはDOM要素
```


# 合計する
今回はターゲットとなるカラムのアイテム1つ1つに含まれるポイント数を合計したかったので、
さくっとポイントの文字列を抽出して合計します。

```js
// ポイントが含まれている要素を抽出
const $pointDom = $target.querySelectorAll('.point');

// 配列化
const pointDomArr = [...$pointDom];

// ポイント文字列を数値に変換しつつ抽出 → さらにundefinedなど、合計すると NaN になる要素を除外
// [1, 3, 5...] のような配列が生成される
const pointArr = pointDomArr.map(v => v.textContent * 1).filter(v => v);

// 合計
const points = pointArr.reduce((a, b) => a + b, 0);
```

# セミコロンを忘れないこと
minifyして１行にするため、各処理の最後にセミコロンがないと意味が変わってエラーが生じてしまいます。省略しないこと。

# minify
素晴らしいWebサービスが存在するので使わせていただきましょう。
エディタ上で出来るけど？ という方はそれで構いません。
下記のサービスの場合、ブックマークレット化に必要な「javascript:」も補ってくれます。

- [ブックマークレット作成](https://crocro.com/tools/item/gen_bookmarklet.html)

# 備考
怒られました。

```js

// TypeError: Illegal invocation
const qAll = document.querySelectorAll;

// これならOK
const qAll = function(selector){
  return document.querySelectorAll(selector);
};
```

# 作ったもの
今回はAsanaの「DONE」とタイトルの付いたリストのポイント（スクリーンショット「2」の部分）を合計するためのブックマークレットを作りました。
日頃のタスクをちょっと便利にするブクマ、気軽に作っていきましょう〜。

- [asana-count](https://github.com/yama-t/code/tree/master/bookmarklet/asana-count)

![スクリーンショット 2019-06-07 午後3.19.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46299/ea4e4d1b-a8da-d38b-1f30-453899e5543d.png)
SalesforceからCloud Natural Language APIにアクセス

SalesforceからGCPのサービスにアクセスします。
メールの本文を解析したかったので[Cloud Natural Language API](https://cloud.google.com/natural-language/?hl=ja)をAPEXから利用する場合の設定です。

## GCP側の設定
### プロジェクトの作成
プロジェクトを作ります。
[この辺](https://cloud.google.com/resource-manager/docs/creating-managing-projects?hl=ja&visit_id=636954821776357371-3997656483&rd=1#identifying_projects)を参照に。
お支払い情報が必要になると思いますが、素直に入れるしかないです。
### APIキーの作成
Cloud Natural Language APIはOAuthなどの認証情報が必要なくAPIキーさえ指定してやれば利用できます。
APIキーはプロジェクトの「APIとサービス」にある「認証情報」から遷移した画面で作れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356061/dd09a298-3905-cf80-6556-8a71cc283aba.png)
***APIキー***を選択して必要な項目を入力しますとキーを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356061/cd2ee7a6-3769-62be-66eb-91e399789736.png)

## salesforce側の設定
### 指定ログイン
エンドポイントは必要になるので指定ログインを作成します。
ハードコートすれば必要ないですが、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356061/5c53446f-a56a-cd23-0e81-fdd581bce9c3.png)
表示ラベルと名前は好きなものを。
URLは利用したいAPIのエンドポイントを。
- エンティティ分析：https://language.googleapis.com/v1/documents:analyzeEntities
- 感情分析：https://language.googleapis.com/v1/documents:analyzeSentiment
- 構文解析：https://language.googleapis.com/v1/documents:analyzeSyntax
- 構文感情分析：https://language.googleapis.com/v1/documents:analyzeEntitySentiment
- コンテンツ分類：https://language.googleapis.com/v1/documents:classifyText
各々どんな解析が行われるのかは[この辺](https://cloud.google.com/natural-language/docs/how-to?hl=ja)読んでください。
ID種別は匿名でいいです。APIキーがあれば認証は必要ないので認証なしで問題ないはずです。

## APEX
詳しい説明は省きます。
コールアウトでNatural Language APIにアクセスさせています。
req.setEndpointで「指定ログイン」を指定したうえでパラメータ（kye）に"APIキー"を渡しています。
後はヘッダーを設定したりPOSTで送るのでBodyとしてJSONを組み立てています。

```
public without sharing class MailBodyParse {
    @AuraEnabled
    public static String parse( String body ) {

        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:GoogleML?key=[ここは作ったAPIキーを指定するんです]');
        req.setMethod('POST');
        req.setHeader('Content-Type','application/json; charset=UTF-8 ');
        //JSON作るよん
        JSONGenerator gen = JSON.createGenerator(false);
        gen.writeStartObject();
        gen.writeStringField('encodingType', 'UTF8');
        gen.writeFieldName('document');
        gen.writeStartObject();
        gen.writeStringField('type', 'PLAIN_TEXT' );
        gen.writeStringField('content', body );
        gen.writeEndObject();
        gen.writeEndObject();
        //bodyを設定だよ
        req.setBody(gen.getAsString());
        Http http = new Http();
        HTTPResponse res = http.send(req);
        return res.getBody();
    }
}
```

実行すればJSONがレスポンスとして返ってきます。

## 終わりに
エンティティ解析しか使ってませんがなかなかにいい結果が返ってきました。
ちなみに月で5,000回までは無料で使えますが調子に乗って使うと課金が始まるです。
bitnamiでRedmineのローカル環境を作成する

## Redmineとは
Redmineはプロジェクト管理ができるオープンソースソフトウェアです。やるべき作業を記録・管理したり社内で情報共有ができます。例えば、チームでシステム開発を進める場合に誰がいつまでに何をやるのか、現在どのくらい進んでいるのかをRedmineに記録することで進捗状況を明らかにし計画通りに進むよう支援します。


![issue-list.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61070/97e8fa5f-e012-3c58-b88a-8ecfe0f9a918.png)
![gantt-detail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61070/27fae5ba-e051-97ce-1ea0-2aba9878c579.png)

## 機能
やるべき作業を管理する「チケット」という機能が一番よく使われています。チケットはガントチャートやカレンダー、ロードマップなどで表示ができます。他にも共同でメモを作成できる「Wiki」、SubversionやGitなどと連携できる「リポジトリ」、メンバーへのお知らせを掲載する「ニュース」などの機能があります。

## Redmineを使うべき理由
Redmineには今までの作業がよりスムーズになるメリットがたくさんあります。Webアプリケーションなので複数人が同時にアクセスでき、本社と支社が離れた場所にあっても一緒に作業を進めていくことができます。

## 利用シーン
システム開発をしていく上でのバグ管理、仕事の計画と進捗の管理、顧客からの問い合わせにどぼように回答したのか記録するなど様々な用途があります。

## bitnamiとは
bitnamiは、いろいろなWebアプリケーションをオールインワンパッケージで提供しているサービスです。

## redmineのローカルへのインストール方法
こちらからインストールしました。
https://bitnami.com/stack/redmine/installer



<img width="851" alt="スクリーンショット 2019-06-07 14.57.46.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61070/fea48b64-09e6-622e-99ec-815717584183.jpeg">
インストールしたら起動します。


<img width="514" alt="スクリーンショット 2019-06-07 14.58.29.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61070/93f61a6d-4f46-0898-cdef-495b74476bf2.jpeg">
Startを押してStatusが緑になるのを待ちます。
<img width="514" alt="スクリーンショット 2019-06-07 14.58.36.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61070/307cda4c-28bd-92a2-9b1e-9c52d6b38a83.jpeg">
Statusが緑になったらServicesの画面でStart Allを押して全て起動します。

<img width="1002" alt="スクリーンショット 2019-06-07 15.02.13.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61070/d2230f25-3a0b-5cde-70b1-744e0081e3b4.jpeg">
GeneralのIP Address（この場合はhttp://192.168.64.2/）
にアクセスするとRedmineの画面があらわれます。
右下にはManageのボタンがあることがわかります。

<img width="1004" alt="スクリーンショット 2019-06-07 15.04.49.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61070/b5ec2669-34e4-2117-9c7d-21c41fe18ab2.jpeg">
Manageのボタンを押して
http://192.168.64.2/bitnami/index.html
の画面に飛ぶとユーザーの情報が記載されているのでそれでログインするとRedmineのいろいろな機能を試すことができます。
Goのスコープに苦しんだ事例集

コンパイル通るけどtestで死ぬ事例、個人的No.1のスコープ関連についてまとめ。

## 事例その１ メソッド完結

メソッド内でスコープ切れちゃうので、メソッド内でnewしてもダメだぜの例。
"スコープが切れる"という表現でいいのだろうか。。。

```
type hogehoge map[string]string

func (h hogehoge) Seter(p string) {
	h["key"] = p
}
func (h *hogehoge) NewSeter(p string) {
	h = &hogehoge{"p": p}
}

func main() {
	f := hogehoge{}
	f.Seter("ddd")
	fmt.Println(f) // <- map[key:ddd]

	f.NewSeter("sss")
	fmt.Println(f) // <- map[key:ddd]
}
```
https://play.golang.org/p/mCEUyNGLgsy

そもそも、[こういうこと](https://play.golang.org/p/kourvtWmd3P)がやりたかったのでコード間違ってたんですけどね。

## 事例その２ ループ内部完結

`=`と`:=`を間違える、よくやるやつ。

```
dev := "hoge"

for _, v := range []string{"a", "b"} {
	dev := v
	fmt.Println(dev) // <- "a","b"
}
fmt.Println(dev) // <- "hoge"
```
https://play.golang.org/p/ilj019ANt_f
React hooksのuseReducerをuseStateから作る

## はじめに

[前の記事](https://qiita.com/daishi/items/53e7cfeffbb37600a953)で、 useReducer から useState を作ってみましが、逆はできるのだろうかと挑戦してみました。

## useReducerを作る

結果的には次のようになりました。

```javascript
import { useCallback, useMemo, useState } from "react";

export const useReducer = (reducer, initialArg, init) => {
  const [state, setState] = useState(
    init ? () => init(initialArg) : initialArg
  );
  const dispatch = useCallback(
    action => {
      setState(prev => reducer(prev, action));
    },
    [reducer]
  );
  return useMemo(() => [state, dispatch], [state, dispatch]);
};
```

[lazy initialization](https://reactjs.org/docs/hooks-reference.html#lazy-initialization)のあたりが期待通りに実装できているか、確信はありません。useStateの方のシグネチャがシンプルなので、何か違いがあるような気もするのですが。

## おわりに

useReducerからuseStateを作って、そのuseStateからまたuseReducerを作って、が永遠にできますね。何か見落としがあったらすみません。
DBの共通SQL

複数テーブルの件数を一緒に出力する
--

```
select 'Table501',count(*) from Table501 union
select 'Table502',count(*) from Table502 union
select 'Table512',count(*) from Table512 union
select 'Table522',count(*) from Table522 union
select 'Table530',count(*) from Table530;
```

Cross join(交差結合:全部の組み合わせが返ってきます)※直積※
--
```
-- 新規カレンダ追加
-- workcalテーブルに日付と稼働日フラグを入れてから実行
INSERT INTO t_workcal 
SELECT
  b.BushoCd
  , a.CalDt
  , a.WorkFlg
  , '0' WorkDtSq
  , "admin"
  , CURRENT_DATE + 0
  , CURRENT_TIME + 0
  , "admin"
  , CURRENT_DATE + 0
  , CURRENT_TIME + 0 
FROM
  workcal a 
  CROSS JOIN busho b 
WHERE
  a.CalDt >= '20220401' 
ORDER BY
  b.BushoCd
  , a.CalDt
```
https://www.dbonline.jp/sqlite/join/index3.html

leftjoin：左表の件数を基準にして、減らない方法
--
```
SELECT
 DATE_FORMAT(a.CalDt, '%Y/%m/%d') CalDt
  , dayname(DATE_FORMAT(a.CalDt, '%Y/%m/%d')) dayname
  , WEEK(DATE_FORMAT(a.CalDt, '%Y/%m/%d'),3) WEEK
  , b.ShainNo
FROM
  t_workcal a 
  LEFT JOIN t_sagyoushashift b 
    ON a.BushoCd = b.BushoCd 
    AND a.CalDt = b.CalDt 
	and b.ShainNo='test'
WHERE 
a.BushoCd = '11'
and left(a.CalDt,6) = '202209'
```
条件はWhereに置かないで、「ON」のところに置くと、件数が減らない。
https://blog.csdn.net/qq_34224565/article/details/125760805
当where 条件在外，会先聚合后过滤，所以结果会变少
[Kaggle]Santander Customer Transaction Prediction（その３）

#Santander Customer Transaction Prediction に挑戦してみた。（その３）
この記事は「Santander Customer Transaction Prediction に挑戦してみた。（その２）」の続きです。

- [[Santander Customer Transaction Prediction に挑戦してみた。（その１）](https://qiita.com/pappapa/items/aaddde9c731a154c512b)
- [[Santander Customer Transaction Prediction に挑戦してみた。（その２）](https://qiita.com/pappapa/items/df42b7af5e4779745354)

##（８）コールバック
###コールバックを組み込む
今回使用したコールバックは「ReduceLROnPlateau」で、訓練中に学習率を調整してくれる魔法のようなものです。
使い方はとても簡単で、下記のリストを作成してからモデルに入れるだけです。（8-2）
**コールバックは検証データを監視するため、モデルには"validation_data = (x_val, y_val)"を入れる**

```python:8-1
callbacks_list = [keras.callbacks.ReduceLROnPlateau(
                                        monitor = "val_loss", #損失値を監視
                                        factor = 0.1, #コールバックが起動したら、学習率に0.1をかける(位を一つ下げる)
                                        patience = 5, #検証データでの"val_loss"が５エポック改善されなければ起動
                            )]
```

###コールバックを組み込んだモデル
一般的なモデルに、１行加えるだけで魔法が使えます。Kerasに感謝

```python:8-2
now_list = high_feature_list + medium_feature_list
print(len(now_list))

x_train_in_model = x_train_ss[:, now_list]#モデルに入れる訓練データ
y_train_in_model = y_train_ss[:, now_list]#モデルに入れるテストデータ

percent_train = 80#訓練データに使う割合（残りは検証データ）[%]
train_num = round(200000*(percent_train/100))#訓練データに使うデータ数（残りは検証データ）

par_train = x_train_in_model[:train_num, :]
par_targets = train_targets[:train_num]
val_train = x_train_in_model[train_num:, :]
val_targets = train_targets[train_num:]

b_size = 1024
epoch = 12


model = Sequential()
model.add(Dense(64, input_shape = (len(now_list), ), activation = "relu"))
model.add(Dense(32, activation = "relu"))
model.add(Dropout(0.5))
model.add(Dense(32, activation = "relu"))
model.add(Dropout(0.5))
model.add(Dense(1, activation = "sigmoid"))

model.compile(optimizer = optimizers.Adam(), loss = "binary_crossentropy", metrics = ["acc"])

history = model.fit(par_train, par_targets, 
                    epochs = epoch, 
                    batch_size = b_size, 
                    callbacks = callbacks_list, #このように記載するだけで、コールバックを組み込める
                    validation_data = (val_train, val_targets))#コールバック使用時、ここは必須
```
![スクリーンショット 2019-06-07 午後14.46.13 午後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427946/41290f54-d7ac-8fa8-79b7-63d54432d84e.png)

##(9)提出
###提出用データを作成
提出データは０〜１の確率で提出するそうです。０と１の値に直して提出しないように注意してください。
（インデックスをつけていいかなどがわかりにくく、いつも１回は弾かれます・・・）

```python:9-1
ans = model.predict(y_train_in_model)
#ans = np.round(ans).astype(int)とすると０・１になる
ans = ans.flatten()
ans = ans.tolist()

print(len(ans))

data = {"target": ans}
ans_df = pd.DataFrame(data)
ans_df.index = test["ID_code"]
ans_df.to_csv("sub_1_Santander_Customer_Transaction_Prediction.csv")
```

###結果
提出期限が過ぎているからか、順位は確認できませんでした・・・
（左）Private Score　　（右）Public Score
![スクリーンショット 2019-06-07 午後14.51.46 午後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427946/7c827ed6-66da-d35e-2b55-ca060123e834.png)
ES2019 の flatMap は何に使うのか

[Meguro.es # 21 @ ビザスク](https://meguroes.connpass.com/event/125499/) で紹介されていた ES2019 の `flatMap` の具体的な用途がパっと思いつかず、少し調べたり聞いたりしてみました。

ちなみに `flatMap` は IE や Edge 以外のブラウザではすでに使えますが、まだ Stage3 のプロポーザルです。（2019/06/07現在）
[Array.prototype.flatMap & Array.prototype.flat (公式ドキュメント)](https://tc39.es/proposal-flatMap/)
![スクリーンショット 2019-06-07 14.31.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114828/d2784266-46c7-4a1d-5c9c-12bb0856098e.png)


[flat & flatMap array methods - Can I use](https://caniuse.com/#search=flatmap)
[![スクリーンショット 2019-06-07 14.26.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114828/60e6eb0a-884c-6cbb-8a0d-3bf6acf5c486.png)](https://caniuse.com/#feat=array-flat)

# flatMap とは
`Array.prototype.map` と `Array.prototype.flat` の合わせ技。

```js
[1, 2, 3].flatMap(x => [x, x, x]); // [1, 1, 1, 2, 2, 2, 3, 3, 3]
// 以下でも同じ結果になる --> [1, 2, 3].map(x => [x, x, x]).flat();
```

# どんなときに使うのか考えてみた
`flatMap` を使えば、ある Array の各値をチョキチョキして新しい Array をたくさん作り、できた Array たちを１つの Flat な Array にできる。

例えば、売れ筋商品の購入者一覧を取り出すとか。

```js
const targetUsers = popularItems.flatMap(item => item.buyers);
// 実際に使うときは User ID などの Array に変換してから重複するユーザーを削除したりが必要かも
```

例えば、その購入者のウィッシュリストにある商品一覧を取り出すとか。

```js
const wishListItems = targetUsers.flatMap(user => user.wishLists.flatMap(list => list.items));
// 実際に使うときは(ry
```

# まとめ
結構いろんな場面で活躍しそう。
意識して使うというよりは `map(func).flat()` みたいなコードを見つけたら `flatMap` にリファクタリングして効率良く処理してもらおう！みたいな感じでしょうか。

他にもこんな使い方できそう（した）とかがあればコメントをもらえると嬉しいです。
ESLint プラグインのテンプレートを作った

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Why reinvent the wheel?<br><br>With GitHub repository templates you can easily reuse code across all your projects.<a href="https://t.co/4aDIcTkaJl">https://t.co/4aDIcTkaJl</a> <a href="https://t.co/yjKN9sprTT">pic.twitter.com/yjKN9sprTT</a></p>&mdash; GitHub (@github) <a href="https://twitter.com/github/status/1136671651540738048?ref_src=twsrc%5Etfw">June 6, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

GitHub がリポジトリ テンプレートの機能をリリースしたそうなので、ESLint プラグインのテンプレートを作ってみました。

> https://github.com/mysticatea/template-eslint-plugin

[Use this template](https://github.com/mysticatea/template-eslint-plugin/generate) ボタンを押下すると新しいリポジトリを作る画面になるので、いつも通りにリポジトリを作るとテンプレートのファイル群がコミットされたリポジトリが作成されます。

ファイル群がそのままコピーされるだけなので、`package.json` のパッケージ名やリポジトリへのパスなんかは手動で書き換える必要があります。この辺はこれから機能拡充されていくのでしょう。

----

このテンプレートの内容を少しだけ解説します。

## ファイル構造

名前 | 解説
:----|:----
`docs/rules/` | ドキュメント置き場
`lib/rules/` | ルール定義ファイル置き場
`scripts/` | 開発補助スクリプト置き場
`tests/lib/rules/` | テストファイル置き場
`.eslintignore`, `.eslintrc.js` | ESLint の設定ファイル
`.gitignore`, `.gitattributes` | git の設定ファイル
`.npmrc` | npm の設定ファイル
`.nycrc` | カバレッジ測定の設定ファイル
`.travis.yml` | CI の設定ファイル
`LICENSE` | MIT の条文が書いてある。名前を追加してください。
`README.md` | りーどみー。お好みで更新してください。
`package.json` | パッケージ情報。パッケージ名その他を更新してください。

## 依存パッケージ・サービス

以下を使うようになっています (ESLint 本体と同じ)。お好みで変更してください。

- **テスト**: [mocha] と [nyc]
- **CI**: [Travis CI]
- **ESLint の設定**: [eslint-config-eslint] と [eslint-plugin-eslint-plugin]

## 開発補助ツール

- `npm test` ... 各ルールをテストし、カバレッジを測定します。カバレッジは `coverage/lcov-report/index.html` に吐かれます。
- `npm run add-rule ルール名` ... ルールの定義ファイル・テストファイル・ドキュメント ファイルを作成します。
- `npm run update` ... ルール定義ファイルに基づいて、`lib/configs/recommended.json`, `lib/index.js`, `README.md` のルールテーブル等を更新します。

[mocha]: https://www.npmjs.com/package/mocha
[nyc]: https://www.npmjs.com/package/nyc
[eslint-config-eslint]: https://www.npmjs.com/package/eslint-config-eslint
[eslint-plugin-eslint-plugin]: https://www.npmjs.com/package/eslint-plugin-eslint-plugin
[Travis CI]: https://travis-ci.com/
VSCode の Remote Development の設定

# Remote Development

VSCode の拡張機能でssh接続したマシンのファイルをローカルマシンのVSCodeで編集するためのもの.

# 設定

以下の手順で行う.

1. 拡張機能のRemote Developmentをインストール
2. ~/.ssh/configの設定(しなくても接続はできます)
3. 接続

## 1. 拡張機能のRemote Developmentをインストール

VSCodeで拡張機能"Remote Development"を検索し、インストール.
Remote Developmentをインストールすると,必要な拡張機能諸々インストールされる.

![remote_development_install.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294169/bbbc4e2f-f56c-bcfb-7b81-f17c1630b132.png)


## 2. ~/.ssh/configの設定

`~/.ssh/config`を設定しておけはVSCodeからssh接続先のマシンにすばやくアクセスするすることができます.
この設定を行わなくてもRemote Developmentを使うことはできます.

`~/.ssh/config`の設定に関しては[ここ](https://qiita.com/0084ken/items/2e4e9ae44ec5e01328f1)を参考にしました.
最低限これだけ書いておけはOKです.

```
Host remote               # ホスト名
    HostName 192.168.1.10 # ssh接続するホストのipアドレス
    User yourname         # ログインユーザ名
```

## 3. 接続

#### `~/.ssh/config`を設定した場合

![connect.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294169/897c7148-f00b-f88a-a7db-ebcd9ba40c92.png)


画像の1をクリックすると, 画像の2に先程`~/.ssh/config`で設定したホスト名が現れます. 画像の3をクリックすると新しいウィンドウで接続先を開きます.

![open_folder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294169/e94357a8-8b74-23d5-1e7d-88306f4d584d.png)

"Open Folder"で作業したいフォルダを開けば接続先のファイルをローカルかのように作業することができます.


#### `~/.ssh/config`を設定しなかった場合

1. コマンドパレットを開く
2. "Remote-ssh: Connect to Host"を実行
3. `user@hostname`で接続




# 参考

- [設定爆速】VS CodeのRemote Developmentを使ってSSH接続したEC2上のファイルを編集する](https://dev.classmethod.jp/etc/vs-code-remote-development-ec2/)

- [Remote Development using SSH](https://code.visualstudio.com/docs/remote/ssh)
AngularでGitHub Pagesを作るときの素材のパスについて

#GitHub Pagesにデプロイしたときの素材のパスの書き方

GitHubPagesで自分のポートフォリオを公開しようと思ったときにハマったので備忘録として残しておきます。

#ファイル構成
```
src
│  index.html
│  karma.conf.js
│  main.ts
│  polyfills.ts
│  styles.css
├─app
│  │  app-routing.module.ts
│  │  app.component.css
│  │  app.component.html
│  │  app.component.spec.ts
│  │  app.component.ts
│  │  app.module.ts
│  ├─component1
│  ├─component2
│  │      component2.component.css
│  │      component2.component.html  <-ここで画像を使う
│  │      component2.component.spec.ts
│  │      component2.component.ts
│  ├─component3
│  └─component4
├─assets
│      .gitkeep
│      code-tags.svg
│      headerimages.png
│      image.png <-この画像を使う
```


ローカルで作っているときに動いていた画像のパスの書き方

```component2.component.html
<img mat-card-image src="../../assets/image.png">
```

この状態でpushして見ると画像ソースが見つからず404になりました。
ので、このように変更。

```component2.component.html
<img mat-card-image src="assets/image.png">
```

これで無事表示されました。


普段, フロント側なんてほとんどいじらないから基礎的なことも割とあやふやですぐつまづきます。
[mac]ターミナル+bashでgit操作してるなら脳死でこれやっとけ

#注意
これやったのmac使い始めて1ヶ月目くらいなので正直あんまり覚えてない
ミスってるとこあったらコメントで指摘もらえるとありがたい

#この記事でできること
所要時間 5〜15分
・ターミナルの$前(プロンプト)にカレントディレクトリが表示される
・プロンプトに時間が表示される
・プロンプトにブランチ名が表示される
・プロンプトに色がつく

プロンプトのデフォは↓

```bash:terminal
shinozakirinka-no-MacBook-Air:lisbeth shinozakirika　＄
```
ダセェ

僕のプロ子↓
![ScreenShot 21.png](https://qiita-image-store.s3.amazonaws.com/0/158085/87f16a09-30d5-ee0a-feb8-0a1d63f664d5.png)
可愛い

構成 : `現在時刻(hh:mm:ss) カレントディレクトリ 果実　( gitのbranch名 ) $`
色も付いてて無駄な情報がない！

#カレントディレクトリを出力する
まずはカレントディレクトリのみを表示するように変更

viコマンドで.bashrcを編集

```bash:terminal
$ vi ~/.bashrc
```

```text:.bashrc
export PS1='\W $'      # 追記
```

`PS1`というのがプロンプトの内容みたいな感じ、`\W`がカレントディレクトリを表す変数
sourceコマンドを流すと、設定反映

```text:terminal
source ~/.bashrc
```

これでプロンプトにカレントディレクトリが表示されたはず

#タイムスタンプを出力する


```text:terminal
$ vi ~/.bashrc
```

```text:.bashrc
export PS1='\W $'       # これを

export PS1='\t \W $'  　# こう
```

`\t`というのが時間（２４時間形式）を表す変数
またsourceで設定反映

```text:terminal
source ~/.bashrc
```

タイムスタンプが表示されたはず

#現在のブランチ名を表示する
結論から書くと

```text:.bashrc
source ~/project/git/contrib/completion/git-completion.bash
source ~/project/git/contrib/completion/git-prompt.sh

GIT_PS1_SHOWDIRTYSTATE=true
GIT_PS1_SHOWUNTRACKEDFILES=true
GIT_PS1_SHOWSTASHSTATE=true

export PS1='\t \W$(__git_ps1) $ '
```
とするとブランチ名が表示される

>source ~/project/git/contrib/completion/git-completion.bash
source ~/project/git/contrib/completion/git-prompt.sh

この2つはブランチ名表示するのに必要なやつ
（理解はしてないけど、とりあえず理解する必要もない）
brewでgitをインストールしたならここにあるはず

```text:.bashrc
$ ls /usr/local/etc/bash_completion.d/
```
↑流して出ない人は↓から落として来て、そのpathを書けばいい
https://github.com/git/git/tree/master/contrib/completion

>GIT_PS1_SHOWDIRTYSTATE=true
GIT_PS1_SHOWUNTRACKEDFILES=true
GIT_PS1_SHOWSTASHSTATE=true

ブランチ名の右側にステータスが表示される
変更されたファイルがあれば `*`
addされたファイルあれば `+`
追加されたファイルがあれば `%`
stashがあれば `$`

便利


#[おまけ1]色を付ける

いい感じになったけど色つけると可愛くなる

```text:.bashrc
export PS1='\[\033[33m\]\t \[\033[36m\]\W\[\033[35m\]$(__git_ps1)\[\033[00m\] \$ '
```

本題とずれるので自分好みにしたい人は↓記事みてみるといい
https://qiita.com/fernet/items/4dcb6f82520d87227121

#[おまけ2]点滅する果実を表示する

僕は最終的に↓使ってる

```text:.bashrc
export PS1='\[\033[33m\]\t \[\033[36m\]\W\[\033[5;31m\] \[\033[00m\]\[\033[35m\]$(__git_ps1)\[\033[00m\] \$ '
```

#おわり
これでgit branchとかgit status打つ機会は圧倒的に減ったと思う
ブラウザのfaviconキャッシュを消す

## faviconが消えない。

Webアプリを作ってて仕上げにアイコン画像を設定するも、ブラウザの方はたとえばVue.jsで作ったシステムだといつまでたっても緑のVアイコンが変わらないなんてことがよく起きますよね。（特に開発環境localhost:xxxxとか）

![これですw](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51116/bbfce136-bd19-bda2-e583-f1be80f39553.png)

ブラウザのタブ部分とかに表示されてるfaviconは、強制リロードしてもキャッシュを削除してリロードしてもなかなか反映されないです。

そんな時、私はブラウザのfaviconキャッシュを消すようにしてます。

パスの備忘録も兼ねて...

## Chrome

- よくわからないがjournalも削除してる。

```
rm -f ~/Library/Application\ Support/Google/Chrome/Default/Favicons
rm -f ~/Library/Application\ Support/Google/Chrome/Default/Favicons-journal
```

## Safari

- ディレクトリごと削除。

```
rm -rf ~/Library/Safari/Favicon\ Cache
```

## Firefox 

- プロファイルが個別なのがいやらしい、とにかく全部消す。

```
rm -f ~/Library/Application\ Support/Firefox/Profiles/*.default*/favicons.sqlite
```

----

あ、Macしかわかりません。
【Vue.js - 1】基礎知識

## 1. 公式サイト

Vue.js日本公式サイト
https://jp.vuejs.org/

## 2. リソースサイト

リソース
https://github.com/vuejs/awesome-vue
https://curated.vuejs.org/

UIコンポーネント集
Element
https://element.eleme.io/#/en-US
OnsenUI
https://onsen.io/

## 3. Vue.jsのインストール

CDNを読み込む

```html:html
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
```

lodash.min.js（ユーティリティ用ライブラリ）

```html:html
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.5/lodash.min.js"></script>
```
axios.min.js（HTTP 通信用ライブラリ）

```html:html
<script src="https://cdn.jsdelivr.net/npm/axios@0.17.1/dist/axios.min.js"></script>
```

## 4. Vue.jsの基本機能

Vueインスタンスを作成
（変数名は、慣例的にappやvm(viewmodelの略)が使われる）

```js:javascript
var app = new Vue({
  el: '#app'
})
```

テキストのバインディング {{}}

```html:html
<p>{{ message }}</p>
```

```js:javascript
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  }
})
```

オプションに定義したデータはコンソールからアクセスできる

```js:javascript
console.log(app.message)
```

繰り返し v-for

```html:html
<ol>
  <li v-for="item in list">{{ item }}</li>
</ol>
```

```js:javascript
var app = new Vue({
  el: '#app',
  data: {
    list: ['りんご', 'ばなな', 'いちご']
  }
})
```

イベント v-on:click

```html:html
<button v-on:click="handleClick">Click</button>
```

```js:javascript
var app = new Vue({
  el: '#app',
  methods: {
    handleClick: function (event) {
      alert(event.target)  [object HTMLButtonElement]
    }
  }
})
```

フォームの入力と同期 v-model

```html:html
<input v-model="message">
<p>{{ message }}</p>
```

```js:javascript
var app = new Vue({
  el: '#app',
  data: {
    message: '初期メッセージ'
  }
})
```

number修飾子を付与→入力値を数値として受け取る

```html:html
<input v-model.number="message">
```

条件分岐 v-if

```html:html
<button v-on:click="show=!show">切り替え</button>
<p v-if="show">Hello Vue.js!</p>
```

```js:javascript
var app = new Vue({
  el: '#app',
  data: {
    show: true
  }
})
```

トランジション＆アニメーション trantisionタグ

```html:html
<button v-on:click="show=!show">切り替え</button>
<transition>
<p v-if="show">Hello Vue.js!</p>
</transition>
```

```js:javascript
var app = new Vue({
  el: '#app',
  data: {
    show: true
  }
})
 .v-enter-active, .v-leave-active {
   transition: opacity 1s;
 }
 /* opacity:0から1へのフェードイン＆フェードアウト */
 .v-enter, .v-leave-to {
   opacity: 0;
 }
```


オプションの構成

```js:javascript
var app = new Vue ( {
  //mountする要素
  el: '#app',
  //アプリケーションで使用するデータ
  data: {
    message: 'Vue.js';
  },
  //算出プロパティ（関数によって算出されたデータ）
  computed: {
    computedMessage: function(){
      return this.message + '!'
    }
  },
  //ライフサイクルフック
  created: function(){
    ///処理
  },
  //アプリケーションで使用するメソッド
  methods: {
    myMethod: function() {
      //処理
    }
  }
});
```

ライフサイクルフック

| Left align | Left align | 
|:-----------------|:------------------|
| beforeCreate | インスタンスが作成され、リアクティブの初期化がされる前 |
| created |  |
| beforeMount | インスタントがマウントされる前 | 
| mounted |  データが変更され、DOMに適用される前 | 
| updated |  | 
| beforeDestroy |  Vueインスタンスが破棄される前 | 
| destroyed |  任意の子孫コンポーネントからエラーが捕捉された時 | 
| errorCaptured | その後 |
Excelを閉じるとき「図が大きすぎます。入りきらない部分は切り捨てられます」と出る場合の対処

2019年6月現在、VBAからクリップボードに大きなデータをコピーした状態で、Excelを保存せずに終了しようとすると、「図が大きすぎます。入りきらない部分は切り捨てられます。」というメッセージが出ることがあります。発生を確認した環境はWindows 10/Excel 2016です。
<img width="249" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135911/84a2a53d-c8f4-dcf3-9d39-36fe1a741a21.png">
このメッセージ、図がひとつもなくても出るので、バグといってよさそうです。放置しても、とくに何も起こらないようなので、実害はありません。でも、何度も表示される場合もあって面倒だし、切り捨て御免とは穏やかでない。

現在、2つの対処方法が提案されています。

- [オプションを変更](https://rakugakiman.com/archives/3484)：ファイル→オプション→詳細設定→「切り取り、コピー、貼り付け」グループの、「挿入したオブジェクトをセルと共に切り取り、コピー、並べ替えを行う」オプションのチェックを外す。
- [クリップボードを消す](https://qiita.com/histak/items/1c3920e8dd64760094f4)：VBAでクリップボードを消すコードを追加する

オプションを変更する方法は、自分の環境では有効ですが、他の人に使ってもらう場合は難しいです。また、[副作用](
https://qiita.com/tshiono9/items/3137c46c26230e97d9b7
)もあります。クリップボードを消す方法は、WindowsのAPIを操作する必要があるのでやや高度です。

そこでもうひとつ、クリップボードに大きいもんがあったらあかんゆうんやったらなんでもええから小さいもんいれといたらええやん、というチープな回避策を考えてみました。

```vb:sample.bas
somethingBig.copy(target)	'クリップボードに大きなオブジェクトを格納する処理
Range("A1").copy			        'ActiveSheetのA1セルをクリップボードにコピー（バグ回避）
```

`Range("A1")`はActiveWorksheetのA1セルです。`[A1]`と書いてもいいです。もちろんA1でなくてもどこのセルでもOKです。

なお、値だけをコピーする場合など、そもそもクリップボードを使わなくていい書き方が可能であればそのほうが速いので、それにこしたことはないです。
Laravel Envoy でデプロイ対象サーバを指定してデプロイする

Envoy はとてもシンプルなデプロイツールでLaravel の Blade を使ったことがあれば直感的に記述できます。

https://laravel.com/docs/envoy

ただ、複数のサーバを対象とする場合、基本的には記述されたすべてのServerがデプロイ対象となり、対象を選択するようなオプションが標準では準備されていません。
（`@task` のオプションである `on` を利用すればタスク毎に対象サーバを絞ることができますが、実行時に対象サーバの選択はできない。）

そこで試行錯誤して複数環境にリリースできるようにしてみました。

``` Envoy.blade.php
@servers(['production' => 'example.com', 'staging' => 'staging.example.com'])

@story('deploy')
    git
    composer
    migration
    cache
    autoload
@endstory

@setup
    $docRoot = '/var/www/html';

    if (empty($server)) {
        $server = 'production';
    }
@endsetup

@task('git', ['on' =>  $server])
    cd {{ $docRoot }}
    git pull origin master
@endtask

@task('composer', ['on' =>  $server])
    cd {{ $docRoot }}
    composer install --no-interaction --no-dev
@endtask

@task('migration', ['on' =>  $server, 'confirm' => true])
    cd {{ $docRoot }}
    php artisan migrate
@endtask

@task('cache', ['on' =>  $server])
    cd {{ $docRoot }}
    php artisan cache:clear
@endtask

@task('autoload', ['on' =>  $server])
    cd {{ $docRoot }}
    composer dump-autoload
@endtask

@finished
    @slack('webhook-url', '#example', $server . 'にデプロイしました')
@endfinished
```

## 実行方法

```
# production
$ envoy run deploy

# staging
$ envoy run deploy --server=staging
```

production は、serverを指定してもOK

## 解説

実行対象を分けるだけであれば、実はそれほど難しくありません。
`@story` を分けて

```
@story('production', ['on' => 'production'])
    ...
@endstory

@story('staging', ['on' => 'staging'])
    ...
@endstory
```

のように記述すればできます。

ただ、この方法ではSlack通知のメッセージを出し分けることができませんでした。
理由は以下の制約があるからです。

- `@setup` 内じゃないと変数代入できない。
- `@finished` 内じゃないと `@slack` が使えない。

ということでコマンドのオプション変数で対応しました。
（まさか `on` に変数を直接書けるとは思わなかった）

`--server` オプションを必ず指定するのであれば、各 `@task` の `on` を削除して以下の記述でもいけます。

```
@story('deploy', ['on' => $server])
    ...
@endstory
```

この場合 `--server` が未指定の場合に `@setup` で補完する処理を記述しても、すでに `on` の記載されている `@story` が呼ばれているためなのか効果がありませんでした。

## まとめ

これで、1ファイルでデプロイ先のサーバを切り替えることができそうです。
もし、もっとスマートなやり方を知っている方は教えてください！
Slackワークスペース統合時に気を付けなければいけないこと

先日ワークスペースの統合を行った際にいろいろとハマったので備忘録として書いています。

統合の手順は以下のステップで行います。
1. インポートしたいワークスペースのコピーをエクスポートする
2. エクスポートファイルをアップロードする
3. インポートするメンバーを選択する
4. インポートするチャンネルを選択する
5. サマリーを確認してインポートを実行する

それでは各ステップで注意しなければならないTipsを紹介していきます。

## インポートしたいワークスペースのコピーをエクスポートする        
- スタンダードプランの場合、エクスポートできるのはパブリックチャンネルのみとなり、ファイルもリンクは含まれますが、ファイル自体は含まれません。
-  プライベートチャンネルやダイレクトメッセージ、グループ DM からコンテンツをエクスポートする際には、ワークスペースのオーナーは Slack に連絡し、エクスポートを申請する必要があります。
- 参考ですが4年間運用したワークスペースの全ログをエクスポートするのにかかった時間は10分程度で、zipのファイルサイズは約180MBでした。（環境や、エクスポートする内容によって差がありますことをご了承ください）

## エクスポートファイルをアップロードする
- インポートするファイルが2GB以下のサイズであればローカルからのアップロードも可能ですが、セキュアなオンラインストレージサービス (Google ドライブや Dropbox、Box など) からの直接アップロードリンクを指定したほうがアップロード時間も短く（5分程度）、安定していました。

## インポートするメンバーを選択する
- ユーザーを統合する場合はユーザーの種別に注意してください。ワークスペースAからワークスペースBにインポートを行う場合、AでシングルチャンネルゲストのユーザーをBでは通常メンバーのユーザーに統合しようとするとインポート時にエラーが発生します。
 - インポートする際にユーザーの種別や権限は表示されないので事前に確認もしくは元のワークスペースの情報と突き合わせながら慎重に実施することをお勧めします。
- 特定のユーザーのインポートをスキップすると、そのユーザーの DM は Slack に追加されなくなります。ユーザーのメッセージをインポートするオプションを選択した場合に追加されるのはパブリックチャンネルのメッセージのみです。

## インポートするチャンネルを選択する
- 「チャンネルを既存の Slack チャンネルに統合する
」を指定しない場合、名前が同じチャンネルには「general2」のように連番が振られます。

## サマリーを確認してインポートを実行する
- 実行中にエラーが発生した場合、ログなどは出力されないため調査はサポートに連絡するほかありません。※リアルタイムチャットでのサポートは英語のみの対応
- 「インポートを元に戻す」ボタンをクリックすると、インポートがロールバックされます。インポートしたチャンネルとメッセージが Slack ワークスペース から削除されますが、***メンバーは削除されません。***
- 「チャンネルを既存の Slack チャンネルに統合する」を選択していて統合先のチャンネルに一件もメッセージ投稿がなかった場合はロールバックするとチャンネルそのものが消えてしまいます。
- ロールバックを実行しても新たにつくられた「general2」のような連番が振られたチャンネルは削除されません。
- 参考までにインポート完了までは約9時間ほどかかりました。

## まとめ
基本的にSlackには検証環境などの概念がなく、ぶっつけ本番で統合を実施するのはきつかったです。サポートに聞かないと公開されていない暗黙の仕様などもあり不安な方もいらっしゃると思い情報をシェアしました。
これから統合を行おうと思っている方の助けになれば幸いです。 

## 参考
https://get.slack.help/hc/ja/articles/217872578-%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%81%8B%E3%82%89%E5%88%A5%E3%81%AE%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%81%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88%E3%81%99%E3%82%8B
EC2へ自動テスト、デプロイをCircleCIで実現する(Django)

# はじめに
AWSのEC2インスタンスにSSH接続→`git pull`して手動でデプロイしていたのですが、CircleCIを使用して自動デプロイする手順をまとめました。

# 実現したいこと
GitHubにmasterブランチをpushした際に、CircleCIを動かしてDjangoのUnittestを実施。
テストにパスした際は、そのままEC2インスタンスにSSH接続して`git pull`して最新のコードを反映させる。
なお、Djangoのアプリはdocker上で動かしています(`docker-compose up -d`)。
下記リンクがdockerの環境構成です。
[Django+Nginx+MySQLの開発環境をDockerで構築する](https://qiita.com/kenkono/items/6221ad12670d1ae8b1dd)

# EC2インスタンス
事前に`git` `docker` `docker-compose`をインストールしておきます。
さらに、後述しますCircleCI用の公開鍵も記述します。
手順は下記にまとめました。
[EC2インスタンスにgit,docker,docker-composeを導入、公開鍵の登録(CircleCI用)](https://qiita.com/kenkono/items/2a614cdaafdf956a8572)

# CircleCI
対象のGitHubリポジトリをCircleCIに登録しておきます。
以下を実行します。
1. 秘密鍵の登録
2. EC2インスタンスのホスト名、ドメイン名の登録
参照記事：[Circle CIでwebサイトを自動デプロイ](https://esnetk6.com/2018/04/circle-ci-deployment/)

### 秘密鍵の登録
CircleCIに使用できる鍵認証は形式が決まっていますので、それに従い作成します。
フォルダを作成し、そこに作成します。
参照：[Adding an SSH Key to CircleCI](https://circleci.com/docs/2.0/add-ssh-key/)

```
# 鍵の作成
$ mkdir ssh
$ ssh-keygen -m pem
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/kenkono/.ssh/id_rsa): ssh
```

CircleCIのコンソール画面で作成した秘密鍵を登録します。
Hostnameには任意の文字を記入します。
![Screen Shot 2019-06-07 at 11.37.05 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291139/ad36d09e-10cb-f2ac-c638-4809d8f893a9.png)

### EC2インスタンスのホスト名、ドメイン名の登録

環境変数として登録します。
EC2の場合、`ec2-user@ドメイン名`かと思いますので、以下登録します。
HOST_NAME = ドメイン名
USER_NAME = ec2-user
![Screen Shot 2019-06-07 at 11.40.15 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291139/1c913bf5-2f13-bdec-58e8-6779036ffa33.png)

# CircleCIの実行コード
`.circleci/config.yml`に記載したコードが、対象のGitHubレポジトリにpushされた際に実行されます。
以下記述内容です。
docker-composeを実行したいので、CircleCIでは仮想マシンである`circleci/classic:edge`を指定します。

```config.yml
# circleCIのバージョン指定
version: 2
jobs:
  build:
    machine:
      image: circleci/classic:edge
    steps:
# Djangoのテストを実行
      - checkout
      - run:
          name: docker-compose up
          command: docker-compose up -d
      - run:
          name: sleep for launch db to migrate at Django
          command: sleep 10
      - run:
          name: migrate
          command: docker-compose run python ./manage.py migrate
      - run:
          name: test
          command: docker-compose run python ./manage.py test
      - run:
          name: docker-compose down
          command: docker-compose down
# EC2にSSH接続し、デプロイを実行
  deploy:
    machine:
      image: circleci/classic:edge
    steps:
      - checkout
      # CircleCIに登録した秘密鍵を呼び出す。
      - add_ssh_keys:
      - run: ssh ${USER_NAME}@${HOST_NAME} 'cd todoList && git pull && docker-compose run python ./manage.py migrate'

# テストが成功した場合のみ、deployを実行するようにします。
workflows:
  version: 2
  build_and_deploy:
    jobs:
      - build
      - deploy:
          requires:
            - build
          # masterブランチがpushされた場合のみdeployするようにする。
          filters:
            branches:
              only: master
```

# 実行
`git push`で一連の記述が動作します。

# 参照元
[docker-composeでRailsを開発しCircleCI 2.0でテストしてHerokuにdeployする](https://qiita.com/Kesin11/items/47079bc7f659e71b694c)
[BQ] Bigqueryメモ

# 自分用bigqueryメモ
小ネタから備忘録まで

## ウィンドウ関数はWINDOWを使って定義しよう
以下のようなウィンドウ関数を使った処理を考える．

```sql
SELECT
  AVG(expr) OVER (PARTITION BY hoge) AS avg_expr,
  COUNT(expr) OVER (PARTITION BY hoge) AS cnt_expr,
  SUM(expr) OVER (PARTITION BY fuga) AS sum_expr
FROM
  tablename
```

同じサブクエリー内ではウィンドウ関数を別で定義できる．
こうすると一括で処理を書き換えられる．

```sql
SELECT
  AVG(expr) OVER (hoge_window) AS avg_expr,
  COUNT(expr) OVER (hoge_window) AS cnt_expr,
  SUM(expr) OVER (fuga_window) AS sum_expr
FROM
  tablename
WINDOW
  hoge_window AS (PARTITION BY hoge),
  fuga_window AS (PARTITION BY fuga)
```

## パーセンタイル
$y$%誤差で$x$パーセンタイルを取る．
このとき，
$a = \frac{x}{y} + 1,\ b=\frac{100}{y} + 1$
が自然数であれば以下のやり方で指定できる．

```sql
SELECT
  APPROX_QUANTILES(expr, b)[SAFE_ORDINAL(a)] AS y_percentile
FROM
  tablename
```

厳密解を得たい時？は以下のようにする．（上に比べて遅いし冗長）

```sql
WITH
  middle AS (
    SELECT
      PERCENTILE_CONT(expr, y/100) OVER () AS y_percentile
    FROM
      tablename
  )
SELECT
  ANY_VALUE(y_percentile) AS y_percentile
FROM
  middle
```
React hooksのuseStateをuseReducerから作る

## はじめに

[React hooksのドキュメント](https://reactjs.org/docs/hooks-reference.html)では、 useState は basic hooks として、 useReducer は additional hooks として分類されています。ところが、実際の実装としては useReducer が基本実装で useState がラッパー実装となっているようで、プルリクなどでは useReducer のみが修正されていることがあるようでした。

## useStateのラッパーを書いてみる

Reactのソースコードを読んだわけではありませんが、useStateをuseReducerのラッパーとして書いてみたらどうなるか試してみます。

```javascript
import { useReducer } from "react";

const isFunction = f => typeof f === "function";

const reducer = (state, action) =>
  isFunction(action) ? action(state) : action;

export const useState = initialState => {
  const args = isFunction(initialState)
    ? [undefined, initialState]
    : [initialState];
  return useReducer(reducer, ...args);
};
```

思ったより、簡単にできました。

## おわりに

繰り返しになりますが、Reactの実装を再現したものではありません。あくまで勉強用です。本物実装はさらにエラー処理や開発時チェックなどが追加されているかもしれません。
今週の学習記録 : 知識0からポートフォリオ作成を目指して 6月第一週

#これまで
全くのプログラミング無経験で職業訓練校に入校。授業の進行スピードの遅さに不安を覚え、独学開始。
訓練校ではJavaを扱っていたが、自分の興味からひとまずJavascript、HTML/CSSを学ぶことに決める。
周囲には経験者や同分野を学んでいる人がいないため、かなり独学の「独」の側面が強い学習生活になっています

#今週取り組んだもの・所感

##Progate　

###・javascriptコース　Ⅲ～Ⅶ（復習含む）

「メソッド」「オブジェクト」「関数」等の概念が、分かっているつもりで進んでもいつの間にか頭の中でグシャッとこんがらがってしまう事が多々あり、何度も引き返して見直しました。
こんな時に質問できる人がいたらいいだろうな...と、過去に存在したらしいProgateプレミアムプラン（質問し放題らしかった）に思いを馳せました。
まだ完全に定着しているとは思えないので、来週は何か簡単なものを作りつつスライドを見返したいと思います。


###・HTML/CSSコース　初級～上級編（復習含む）

「float:left」したdivが改行されない現象と2時間ほど格闘したのが良くも（？？）悪くも一番の思い出です。
結果、幅の指定がされておらず表示するスペースの無いことが原因だったようです。

ひとつひとつ、想像していたよりもはるかに大変な作業だな、と思う一方、一通りルールを覚え慣れればある程度感覚的に出来そうな予感もしているので、とにかく数をこなすのが大事そうだ、という印象を受けました（浅見すみません）。


##書籍　

###・HTML&CSSとWebデザインが 1冊できちんと身につく本（途中まで）

ProgateのHTML/CSSコースに一先ずの終わりが見えたため、実践的にポートフォリオを作ることを目的としたこちらの書籍を購入し進めることにしました。
類似書籍はたくさんあったのですが、とにかく語り口とレイアウトが読みやすかったのが決め手でこちらを選択することに。
ホームページというものの成り立ちからひとつひとつ解説があり、Progateで学んだ内容と合わせてより理解が進みました。
続きを読むのも楽しみです。
やはり様々な角度から知識を得るのは重要だな、と実感したので書籍に関しては今後もどんどん活用していきたいです。


##・js-primer
無料でいいの！？！？！って感じでjavascriptの知識がたくさん得られました。
受験勉強などの時もそうでしたが、何言ってるのか分からないものでも一通り読んでおくと後々急に理解できたりするのでとりあえず読むことにしています。現段階では理解できない分野も多数ありました。
諸般の事情で現在お金が全くがないので本当に助かりました（浅薄


##訓練校の授業・その他

今週はネットワーク技術に関しての授業でした。
基本情報処理技術者試験の出題範囲となっている分野がメインなので、試験対策の意味合いが強そうです。
来週に単位認定試験があるようなので、復習に時間を割いています。

転職サイトに未経験でもok研修します系のWEbデザイナー求人があるけど、どの程度信用したら良いものか、考えあぐねています


##反省・来週の展望

同じところで何度も詰まったときに、投げ出し気味になって他のことに手を出してしまう（javascript→HTMLなど）のはやめるべき、と己に戒めます。
理解が悪くなかなか進みが遅いですが、初めてだしこんなもんだろ、というある種の恥知らずさをもってポジティブに焦らず取り組んでいきたいと思います。

今のところ、書き方やルールを学ぶのみで具体的に何か動かすことができていないので、来週は簡単なものでもjavascriptを使ったゲームかホームページか何か、作りながら復習していく所存です。

もし読んで下さっている方がいらっしゃいましたら、御清読ありがとうございました。
アドバイス等いただけたら誠に幸甚に存じます。
乱文失礼いたしました。
iOS/Android設定画面の各アプリの画面から独自の設定やライセンス表示をするには？

iOS/Android において、変更頻度の低いアプリの設定や、直接ユーザーには関係のないライセンス表示のような画面は、アプリの中から遷移させる必要性は薄いですし、その遷移のためのボタンの領域を確保するのはもったいないですよね。

ということで、各OSの設定画面にあるアプリ情報の画面でそれを行う方法をまとめます。

## iOS

iOS では Settings.bundle を用いることで iOS設定画面の各アプリの画面でそのアプリの設定項目を表示することができます。

**Appleサポート** アプリの場合
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16508/1394fb9d-e254-c5f7-29ad-860ad2e93744.png">

### アプリの設定

アプリの設定項目を Settings.bundle として定義しておくだけです。ここで設定された項目はアプリからは [UserDefaults](https://developer.apple.com/documentation/foundation/userdefaults) により取得できるようになります。詳細は公式ドキュメントを読みましょう！

[Preferences and Settings Programming Guide / Implementing an iOS Settings Bundle](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/UserDefaults/Preferences/Preferences.html)

### ライセンス表示

[LicensePlist](https://github.com/mono0926/LicensePlist) を使いましょう！
CocoaPods や Carthage でインストールしたライブラリからライセンス一覧を生成して Settings.bundle への組み込みまで自動でやってくれます。

## Android

Android N 以降限定ですが、マニフェストファイル中の Activity の Intent Filter に [ACTION_APPLICATION_PREFERENCES](https://developer.android.com/reference/android/content/Intent#ACTION_APPLICATION_PREFERENCES) を追加することで、Android 設定画面のアプリ情報画面にその Activity への導線が表示されるようになります。

```xml:AndroidManifest.xml
<activity android:name=".SettingActivity">
    <intent-filter>
        <action android:name="android.intent.action.APPLICATION_PREFERENCES" />
    </intent-filter>
</activity>
```

Android P の場合
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16508/3aa42c58-2e4c-b0ec-90f1-005d66d82f36.png">

Android N,O の場合
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16508/407d5579-bf83-7dac-4229-6b0df0a2fa31.png">


### アプリの設定

Android Jetpack の Preference 機能を使うことで、XML でアプリの設定項目を定義するだけで設定画面を構築することができます。ここで設定された項目はアプリからは [SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences) により取得できるようになります。詳細は公式ドキュメントを読みましょう！

[Android Developers / Android Jetpack / 設定](https://developer.android.com/guide/topics/ui/settings.html)

### ライセンス表示

[com.google.gms:oss-licenses](https://developers.google.com/android/guides/opensource) を使いましょう！これによりアプリが依存しているライブラリのライセンス情報を取得し、それを `OssLicensesMenuActivity` で表示することができます。

上記の Preference 機能では設定項目からインテントを投げる[アクション](https://developer.android.com/guide/topics/ui/settings/customize-your-settings#actions)も定義できるので、そこから `OssLicensesMenuActivity` を開くと良さそうです。
UbuntuでiCloudカレンダーを使う

macの便利な点にiCloudカレンダーアプリ、iCloudリマインダーアプリなどの存在が挙げられます。windowsやUbuntuからもウェブ上(icloud.com)で一応アクセスできるのですが、ネイティブアプリと比べるとやや使いづらさがあります。

と思っていたのですが、iCloudカレンダをUbuntuのネイティブアプリで使う方法を見つけました。以下の英語サイトが参考になります。
[iCloudカレンダーをGNU/Linuxで使う](https://ar.al/2018/08/05/using-icloud-calendars-on-gnu-linux/)
SeleniumのChromeDriverでGoogle Chrome以外のブラウザを動かす

#はじめに
ブラウザ自動テストのデファクトスタンダードである`Selenium`
その`ChromeDriver`を使って`Google Chrome`以外のブラウザを操作することができるのか？
という遊び。

動かせた時の感動は省略

#やったこと
##Chrome.exe
ここから取得：https://download-chromium.appspot.com/
そして適当なパスに配置する
※後述するが、取り直すことになった…

##NuGet
`Selenium`系のモジュール参照
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432322/5da66990-fc98-038c-7b97-78bc6cd9b4d7.png)
##ソース
```csharp
var options = new ChromeOptions
{
    // 結局、いつもと違うのはここだけ！
    BinaryLocation = @"C:\Win_x64_638880_chrome-win\chrome-win\chrome.exe"
};

// ヘッドレスでもできたよ！
options.AddArgument("--headless");

using (var driver = new ChromeDriver(options))
{
    var wait = new WebDriverWait(driver, new TimeSpan(0, 0, 5));
    driver.Navigate().GoToUrl("https://www.google.com");
    driver.FindElementByName("q").SendKeys("Chromium");
    driver.FindElementByName("q").Submit();

    wait.Until(ExpectedConditions.TitleIs("Chromium - Google 検索"));
    ((ITakesScreenshot)driver).GetScreenshot().SaveAsFile($"{DateTime.Now.ToString("yyyyMMddHHmmss")}.png");
}
```

##はまったこと
`Chrome`のバージョンと`ChromeDriver`のバージョンがずれているとエラーになるので注意
こちらを参照ください：[Chromiumの特定バージョンをダウンロードする](https://qiita.com/cognitom/items/cf00c3c79fa80ac12a4a)

エラーはこんな感じ
>ChromiumDriverSample.ChromiumChromeDriverTest.Sample が例外をスローしました: OpenQA.Selenium.ElementNotInteractableException: element not interactable  (Session info: chrome=75.0.3770.0)  (Driver info: chromedriver=74.0.3729.6 (255758eccf3d244491b8a1317aa76e1ce10d57e9-refs/branch-heads/3729@{#29}),platform=Windows NT 10.0.17763 x86_64)

#おわりに
次は`Chromium`ベースの`Microsoft Edge`を動かせるかどうかやってみたい。
※`BinaryLocation`変えて起動してみるとこんな感じ。できそうな雰囲気はあった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432322/bb8d58c9-60a1-7066-de2b-64f44d094d5e.png)

※現時点で、[ChromeDriverの最新バージョン](http://chromedriver.chromium.org/downloads)が75だったので検証保留
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432322/87113efb-1a85-d867-d807-1e447220ceec.png)

あとは、[CefSharp](https://bitbucket.org/chromiumembedded/cef/src/master/)で自作したブラウザとか動かしてみたい気持ちがある。
React hooksとuse-immerを使いながらTypescriptでreduxっぽいことをする

use-immer
https://github.com/immerjs/use-immer

テストrepo
https://github.com/github0013/react-hooks-immer-redux-typescript
`yarn && yarn develop`で動きます

1. reducerを作る   
[リンク1][1]
1. use-immerの`useImmerReducer`を使ってstateとdispatchを作る    
[リンク2][2]
1. contextを使って、stateとdispatchを保持する   
[リンク3][3]    
https://reactjs.org/docs/context.html     
1. useContextを使って<Context.Provider>を参照する     
[リンク4][4]     
https://reactjs.org/docs/hooks-reference.html#usecontext


[1]: https://github.com/github0013/react-hooks-immer-redux-typescript/blob/74b9f37e5569d9b4ab95749370137fe6bde162e6/src/components/Loading/reducer.ts
[2]: https://github.com/github0013/react-hooks-immer-redux-typescript/blob/74b9f37e5569d9b4ab95749370137fe6bde162e6/src/components/index.tsx#L11
[3]: https://github.com/github0013/react-hooks-immer-redux-typescript/blob/74b9f37e5569d9b4ab95749370137fe6bde162e6/src/components/Loading/context.ts
[4]: https://github.com/github0013/react-hooks-immer-redux-typescript/blob/74b9f37e5569d9b4ab95749370137fe6bde162e6/src/components/Home/index.tsx#L10


# 問題

通常`reducer`内では`state`を`immutable`にする為に、

```ts
  switch (action.type) {
    case "some_action_name":
      return [...state, abc: new_value]
```
などとする必要がある。結構面倒

# useImmerReducerだと...

これをuse-immerの`useImmerReducer`を使う事で

```ts

  switch (action.type) {
    case "some_action_name":
      // 直接stateをいじれる上に、returnする必要すら無い
      state.abc = new_value
```

として、処理が簡単にかける。