OmniAICreator/Qiita-1.07M huggingface dataset:
新入社員研修でモブプログラミングをやってみた！

今年度の新入社員研修の講師をお願いされたので、ノリでモブプログラミングでやります！と宣言し、やってみた！

# モブやったことなんて当然ない新入社員への説明資料

## プロジェクト演習で”モブ”やってみよう

### モブとは

* モブプログラミングのこと
* チーム全員が同時に、同じ場所で同じコンピュータを使って同じことをする。
* 全員で、１台のPCを使って、キーボードを入力する役（ドライバー）とそれ以外の人（ナビゲーター）がどういうコードを書くかを議論するスタイル。

つまり、“チーム”みんなで楽しく1つのものを作ろうということ

### ドライバーの仕事

* ナビゲーターに指示されたことを実装すること
* ナビゲーターが指示したことを理解すること
* 指示されたことがよくわからなかったら質問をすること
* 指示されたこととは違うアプローチのアイデアがある場合でも議論なしに実装してはいけません

### ナビゲーターの仕事

* 理解できるまで質問すること
* チームの理解度の水準を上げるために貢献すること
    * 実装するための意見を言うだけが貢献ではありません、なぜそういう実装をすべきなのかわからなければどんどん質問してください。
* 他のメンバーの意見も聞くこと、たくさんのアプローチがあることを理解しましょう

### メリット

* 今回の研修においてのメリット
    * 全体のレベルの底上げができる（はず）
        * チームみんなが同じレベルになることを目指す！
    * 進捗報告いらない
    * レビューいらない
        * なのできちんと理解してから進めよう！
    * 先輩がチームにいるときにどんどん質問しよう！

### デメリット

* 今回の研修においてのデメリット
    * たぶんなし
    * チームごとで進捗のばらつきが多少出るかも

### ルール

1チームは3人
＋先輩がランダムで自由に出入りします

ドライバーは15分で交代
PCでタイマーをセットしてから開始

作業開始前に前日のふりかえりと今日のやることを話し合おう
→研修中なのでふりかえりは他のチームにも交えて発表形式でやろう！
先輩は講師というよりみなさんより少しだけできるチームメンバーだと思いましょう。

# 実際にやってみた感想

まず前提として新入社員はたぶん全員文系出身の未経験者です。
なので、私はナビゲーターのフォローに努めました。理解度低いなという部分の説明を補足するのに必死でした。

んでやってみた感想ですが、、、

* 新入社員、先輩ともに満足度高め
    * 一人で悩んでいやるよりははかどるし（どうせ裏で共有するし、、）、先輩も例年なら一人ひとりレビューする必要があって、レビュー待ち行列ができていたのだけれどそれがなくなりました
* モブに積極的に参加しないやついたらしい
    * 説明に必死で気が付きませんでしたが、説明に必死になるよりも、メンバー全員から意見を絞り出させることに注力したほうが良かったかもしれません
* 上と絡めて、少し理解度高い人が終始負担が多いかも
    * うーん、これは仕方ないけど、先輩社員や理解度高い人ばかり意見を言っているのはモブっぽくない気が、、、
* ドライバーの入れ替えをうっかり忘れることが多かった
    * 疲れるのでどんどん変えるよう指示する必要があった
* 事前準備大事
    * Git：ドライバーのPCと他のPC間でのプログラムの共有でぐだぐだになってしまった
        * そもそも共有する必要はないのだけれどGitの勉強も兼ねてわざわざやっていた
    * 大画面モニター：チーム数分足りなくて小さめのモニターのチームにいたときはツライ

# 次があったらこうしたい

* 大画面モニターをチーム数分用意する**←必須**
* 研修担当ではない先輩社員たちに多少は関わってもらいたい
* 進捗気にしない
不定形なデータ構造を汎用的に扱うための方法

## はじめに
こんにちは。@harada_hiです。
今日はPLAID AdventCalendar 2019 16日目として最近社内で戦っていたデータ設計に関して書いています。

NoSQLが流行りデータ設計のあり方は広がりました。RDBが基本だった際は実際の業務Entityを正規化してテーブルを設計していたかと思います。しかし今はその業務Entityをそのままテーブル化することも可能です。またNoSQLだけでなくRDBにおいてもJSONを保持できるように進化し、1カラム1データが原則という世界からは変わっています。

これらはメリットに繋がっている部分もあれば、むしろやりにくくなった点もあると考えています。今回の話は、そうした一種のやりにくさを解消するための手段の紹介です。


## 課題: どんな形のデータが来るか分からない

プレイドではCX Platform [KARTE](https://karte.io/)を提供しています。このKARTEにはWEB上での行動情報がデータとして集まってきます。
この行動情報の詳細はJSONとなっており、各社各様の形式(スキーマ)で送られてきます。つまりタイトルにあるとおり不定形です。

これによって困るのは、この行動情報の詳細を使って後から集計をする場合です。
例えば購入という行動をブランド毎に集計したいとなった際に、
A社のスキーマ

```javascript:sample_a.js
{
   brand: "a"
}
```

B社のスキーマ

```javascript:sample_b.js
{ 
   item: {
      brand_label: ["b"]
   }
}
```

という形でkeyも異なれば、値の型も異なるということが考えられます。

もちろんA社、 B社をそれぞれ個別で集計処理を設ければ達成可能ですが、それは今後もスケールしていこうとするSaaSサービスとして明らかなアンチパターンです。


## 解決策: 集計軸をユーザーに決めてもらう

上の話は送られてくるデータのスキーマが合わせられれば、一番シンプルに解決できるものです。
しかし計測したい行動情報というのは各社各様であり、そこを揃え切ることは非常に難しいです。

では、どうやって集計を汎用化させていくか？
これは集計軸をユーザーに選んでもらうという手段で解消を図っています。

上のJSONのスキーマの例の場合、
以下のような構成のテーブルを作ってしま う形です。

| tenant_id | user_id | event | aggregate_schema | aggregate_value | raw_data |
| :--- | :--- | :--- | :--- | :--- | :--- |
| A | α | 購入 | brand | ["a"] | {brand: a} |
| B | β | 購入 | item.brand_label | ["b"] | {item: {brand_label: ["b"]}} |


集計に使うkeyとvalueを型の決まった世界に落とし込むことで、集計をシンプルかすることができます。
これを組み合わせることでスキーマの形が不定のデータが送られてきたとしても柔軟にデータの集計を行うことが可能になります。RDBでいうところの縦持ちテーブルの考え方です。


## 完璧な手段ではない

これでできます。という雰囲気で上では書いていますが、実際のところ集計軸をユーザーに決めてもらうことで集計幅を柔軟にする対応は極一部でのみしか対応できていません。

データを汎用的にうまく見せるということの取り組みが弱かったこともあり、
* 複数軸での集計の考慮
* ユーザーに設定してもらわなければいけないコスト
* パフォーマンス的な観点
などでまだまだ検討しなければいけない課題があります。特に最後のパフォーマンス部分に関しては悩みがつきません。

## おわりに
今回はスキーマのないデータに対してどう戦っているかという話でした。
なかなか正解のない戦いで、よく悩んでいたりします。

似たような悩みを持っている方がいれば是非お話しましょう！
unityのinput

#Input
入力を司るクラス。

Input.GetKey
キーを押している間trueを返す。

Input.GetKeyUp
キーを話した時にtrueを返す。

Input.GetKeyDown
キーを話した時にtrueを返す。

Input.AnyKey
なんでもいいのでキーが押されていたらtrueを返します。

Input.GetAxis
1つの軸に対して入力している間floatを返します。範囲は-1 ~ 1の間。

Input.GetButton
引数の入力に対応するボタンを押した時にtrueを返します。
Web版Twitterでリストが見れない問題


#概要
2019-12-12からいきなりWeb（Chrome）でTwitterのリストが使えなくなってました。
言うて2日くらいで直るだろうと思ってましたが、戻らず。使えず。

TweetDeck使えば見れたんですけど、ショートカットキーも使えるやつ減ってますし、妙にサイズ違うから見にくいし……。

どうしても諦められなかったのでちょっと色々試したら解決しました


#解決策

iOSのTwitter公式アプリから、**リストの名前を英語**にする。

これだけで良かったです。

lists/1
とか番号で指定したり非公開にしてみたりしましたが、英語にするだけで……。

Twitterくん日本人いじめるの辞めてくれ


#オマケ

リストのメンバー全員を取得
https://qiita.com/MATO/items/ff84ac64f44877924876

終わり
シェルスクリプトでディレクトリ名・ファイル名とファイル内に含まれる文字列を一括置換する方法

#はじめに
この記事は以下のことを実行するシェルスクリプトについて記載したものです
・ディレクトリ名やファイル名に含まれる特定の文字列を一括で置換する
・ファイル内の特定の文字列を一括で置換する

**環境**
mac OS 10.14.6

#シェルスクリプトの内容
```shell
#置換前と置換後の文字列を対話モードで受け付ける
echo "Input old text"
read oldText
echo "Input new text"
read newText


#フォルダ名、ファイル名を置換する
for i in $(seq $(find . -type d | wc -l))
do
    find . -maxdepth $i -name '*'$oldText'*' | \
    while read line
    do newline=$(echo $line | sed 's/'$oldText'/'$newText'/g')
        echo $newline
        mv "$line" $newline
    done
done

#ファイル内に含まれる文字列を置換する
find ./ -name '*.js' -exec sed -i '' 's/'$oldText'/'$newText'/g' {} \;
```

#参考にしたサイト
**再帰的にファイル名やディレクトリ名にある半角スペースをアンダースコア ( _ )で置き換えるスクリプト: Linux & Mac 対応**
https://www.nemotos.net/?p=1919
コマンドごとに丁寧な説明が書かれていたのでとても参考になりました。ありがとうございます。
Adaptive Codeまとめ：依存関係と階層化

#はじめに
私は普段C#を使ったUnity開発に取り組んでいます。これまではどちらかと言えば、「良いコードを書きたい」というより、「バグがなくてきちっと動けばそれで良い」という考えでコードを書いてきたように思います。ただ、エンジニアとしてはそれではやはり不十分でしょう。そこで、[『Adaptive Code ~ C#実践開発手法』](https://www.amazon.co.jp/Adaptive-Code-%E5%AE%9F%E8%B7%B5%E9%96%8B%E7%99%BA%E6%89%8B%E6%B3%95-%E7%AC%AC2%E7%89%88-%E3%83%9E%E3%82%A4%E3%82%AF%E3%83%AD%E3%82%BD%E3%83%95%E3%83%88%E9%96%A2%E9%80%A3%E6%9B%B8/dp/4822253546/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=adaptive+code&qid=1576395880&s=books&sr=1-1)を読んで勉強することにしました。
>「アダプティブ」とは、コードを大幅に変更することなく、新しい要求や予想外のシナリオに対処する適応力のことです。

ただ、本書は基本的に.NET Frameworkでの開発を前提として書かれていますし[^1]、文字数も多いので、自分にとって重要な箇所を抜き出してまとめながら学習を進めることは意味のあることだと思います。
今回のまとめは第3章の内容に当たります。
#本章の目的
- メソッドレベルからシステムレベルへの複雑な依存関係を管理する
- ~~依存関係がもっとも複雑な部分を特定し、ツールを使って複雑さを和らげる~~(.NET Frameworkのツールについての解説なのでここでは触れない)
- コードを小さく適応しやすい機能に分割することで、再利用を促進する
- 階層化パターンをそれらが最適な場所に適用する
- 依存関係を解決する方法を理解し、依存関係の問題をデバッグする
- 実装を単純なインターフェースで隠ぺいする

すべてのソフトウェアには依存関係がある。依存関係により、呼び出し元のコードは機能を抽象的に捉えるようになる。依存関係が何をするのか、それをどのように行うのかについては考えなくてもいいが、すべての依存関係が正しく管理されるようにしなければならない。依存関係の連鎖がうまく管理されなければ、必要のない依存関係が強引に作成され、コードが複雑なアセンブリ[^2]参照だらけになってしまう。
#依存関係
依存関係とは、2つのエンティティ間の関係であり、一方が存在しなければ、もう一方が何らかの機能を実行できない、あるいは存在し得ないことを意味する。
この定義をコードに当てはめると、多くの場合、エンティティはアセンブリである(クラス、メソッド、あるいはアセンブリの集まりの場合もある)。
　　　　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142900/a6d05718-6f00-64f4-7a65-8a16efb0e66b.png)
アセンブリAはアセンブリBを使用している。つまり、AはBに依存している。この時、AはBのクライアントであり、BはAのサービスである。Bが存在しなければ、Aは機能しない。
BがAに**依存していない**点は非常に重要。
コードがクライアントなのか、サービスなのかは、そのコードにどちらの視点からアプローチするのかによって決まる。つまりはどちらにもなり得る。
####有向グラフでの依存関係のモデル化
グラフとは、ノードとエッジの2つの要素からなる数学的構造のこと。エッジに向きがないものを無向グラフ、向きがあるものを有向グラフと呼ぶ。コードの依存関係は有向グラフで表現できる。
　　　　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142900/73056649-e16d-73e3-959e-7ea9404be872.png)
この構造は何種類かの粒度で適用することができる。
粒度の粗いノードごとに、より粒度の細かいノードの集まりが存在する。サブシステムの内部にはアセンブリがあり、アセンブリの内部にはクラスがあり、クラスの内部にはメソッドがある、といった感じ。このことから、１つのメソッドに対する依存関係がさらに依存関係を呼び、最終的にサブシステム全体が参照されるという構図が浮かび上がる。
扱っている依存関係がどのようなものであるかはわからない。わかっているのは、依存関係が存在することだけ。依存関係を管理するにあたって知っていなければならないのは2つのエンティティ間の2項関係、つまり「依存関係が存在するか、しないか」のみ。
以下のB→D→E→B→D→E→･･･のようなアセンブリ間の循環依存関係は禁止されており、いかなる場合も阻止される(Visual Studioで設定しようとするとエラーが出る)。
　　　　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142900/ef1aa2c4-336b-82d1-7bbd-7212e63ff0c5.png)
#依存関係の管理
Coming soon...

#階層化
Coming soon...
[^1]: 監訳者の方は、本書の読者対象は、初学者からベテランまでのC#開発者すべてだと断言している。また、サンプルコードはC#でも、他のプログラミング言語(特に型付けされた言語)で開発しているチームにとっても大切なエッセンスを学べるとも。
[^2]: ここでのアセンブリとは、クラスやインターフェイスの集合のこと。正しく構造化されたアセンブリには、1つの機能グループにのみ関連するクラスとインターフェイスだけが含まれている。例を上げれば、Views、Controllers、ViewModelsなど。
Javascriptで動的に関数を呼び出す

# やりたいこと

探せばいくらでも出てきそうな、変数などを利用して動的に関数を呼び出す方法です。

# ソース
```js
let funcName = 'hogehoge'
let arg = 'fugafuga'

Function("return this")()[funcName](arg);

function hogehoge(arg) {
    console.log(arg);
}
```
## 解説
関数の実体である`function`オブジェクトは、スコープの一番外側であるグローバルオブジェクトのメンバとして登録されます。
従って、グローバルオブジェクトを取得してそいつにブラケット記法でアクセスすれば、動的に関数を呼び出すことができます。

# 参考にしたサイト
[globalオブジェクトを取得する \- Qiita](https://qiita.com/Hiraku/items/d249a2f2f13532748324)
[👻globalThis👻と🌏global🌏と🌝this🌝 \- Qiita](https://qiita.com/uhyo/items/f3b6feef9444e86bef94)
ActiveStorageで恒久的なURLを取得する

この記事は[Fusic その2 Advent Calendar](https://qiita.com/advent-calendar/2019/fusic-2)16日目の記事です。 

## 経緯

弊社内にはTamelというQiitaに似た社内情報共有ツールがあります。
Railsのバージョンが古くなってもいたので、刷新プロジェクトを走らせているのですが、
特に苦労したのはファイルアップロード機能をPaperclipからActiveStorageに移行する作業でした。

## ActiveStorageを使って困ったこと

いろんな記事を参照しながら、ActiveStorageを使うと`url_for`メソッドでは、ワンタイムURLしか発行できないようです。
Tamelでは記事をMarkdownで書くため、ファイルのURLが記事のレコードに登録されます。
ワンタイムURLがレコードに登録されても、期限が切れたら画像が表示されないという問題がありました。

## 気づいたこと

ファイルを参照するだけの口をつくるだけでいいかー、とコントローラーを作り、pathが正しく登録されているか確認するために、以下のコマンドを叩いてみると、こんな記述が。

```
bundle exec rake routes
                   rails_service_blob GET    /rails/active_storage/blobs/:signed_id/*filename(.:format)                               active_storage/blobs#show
            rails_blob_representation GET    /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
                   rails_disk_service GET    /rails/active_storage/disk/:encoded_key/*filename(.:format)                              active_storage/disk#show
            update_rails_disk_service PUT    /rails/active_storage/disk/:encoded_token(.:format)                                      active_storage/disk#update
                 rails_direct_uploads POST   /rails/active_storage/direct_uploads(.:format)                                           active_storage/direct_uploads#create
```

むむ、rails_blob_representationってなんだ？
と思って調べてみると、どうやら恒久的なURLを発行してくれるもののようでした。

## 対応方法

↓のように`rails_representation_url`というものを読んで上げれば良さそう。

```
class Medium < ApplicationRecord
  has_one_attached :file

  def url
    helpers = Rails.application.routes.url_helpers
    helpers.rails_representation_url(file.variant({}), only_path: true)
  end
end
```

こうすると、

```
Medium.first.url
```

みたいな形で恒久的なURLが取れます。

## どう動いているのか

[中身](https://github.com/rails/rails/blob/317760c5ad405795a0c019ec7dba801d5b6b5d77/activestorage/app/controllers/active_storage/representations_controller.rb)を読んでみると、このURLにアクセスすると、どうやら、ワンタイムURLへリダイレクトしてくれるようです。

まだ、深いところまでは追えていないのですが、また、何か分かったらこの記事に追記したいと思います。

## まとめ

自分で実装する前に気づいてよかった。
TeraTerm使いの私がPoderosaを使ってみた話

##Poderosaいいじゃん
普段、私はLinuxサーバなどにSSHをたたくときはTeraTermを使っています。
ある日、とあるSNSで「Poderosaいいよ～」と言っていた方がいたので、とりあえず使ってみたんです...

「えっちょっとこれいいじゃない」

それがきっかけで、Poderosaにドはまりしてしまいました...。

##Poderosaのここがいい
- タブで分割できる

何画面も同時に開かなくていいんです！
Chromeのタブみたいに1画面で複数のセッションを開くことができます。
画面分割もできます。

- 鍵を覚えておいてくれる

TeraTermは接続先のホスト名(IP)をヒストリとして記憶しておいてくれますが、
Poderosaではアカウント，秘密鍵のパスも覚えておいてくれます。(TeraTermでマクロ作ればいいじゃん)

- Amazon EC2と連携できる
AWSのアクセスキーIDとシークレットキーを入れておくと、接続先ホストにリストしてくれます

- 「スターウォーズオープニングエフェクト」機能がある
設定しておくと、tail -fとかしたときに スターウォーズのオープニングの「てーてーててててーてー」の画面みたいにログを流してくれます。
デスクに和み要素をもたらします。

##さいごに
TeraTerm使いのみなさんは、一度でいいのでPoderosaつかってみてください！

###ダウンロード先
Poderosa 5 https://ja.poderosa-terminal.com/ (継続利用はライセンス購入必要)
Poderosa 4 http://poderosa.sourceforge.net/index-ja.html
CI/CDは誰のものか

>この記事は[CI/CD Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ci-cd)の16日目の記事です。

こんにちは、16日目のアドベントカレンダーを担当させて頂きます。

# はじめに
早速ですが、CI/CDと聞いて皆さんが最初に思い浮かべることは何でしょうか？
おそらく自動テストの実装やデプロイの自動化など、自動化技術のことを思い浮かべる方が多いのではないでしょうか。
弊社でもこのような自動化には取り組んでおり、Bitbucket PipelinesやJenkins等を利用したりしていますが、タイトルの通りこれから書くのはCI/CDの技術的側面についてではありません。
技術的な内容については他のアドベントカレンダーの記事に期待してます。皆さん、応援してます！
なお、この投稿は個人の意見にもとづくものであり、所属する組織を代表するものではありません。
異論などもあるかと思いますが、こんな考え方もあるんだなくらいで参考にして頂ければと思います。

# CI/CDとは
おそらくこの記事をご覧の方はCI/CD = Continuous Integration／Continuous DeliveryあるいはContinuous deployment(日本語では継続的インテグレーション／継続的デリバリーあるいは継続的デプロイ)という言葉の略だということはすでにご存知ではないでしょうか。
この言葉に向きあってみると、本質的には技術的な何かを指すのではなく、**習慣**のことを指すのだということに気づいてきます。
実際に[Wikipedia](https://ja.wikipedia.org/wiki/%E7%B6%99%E7%B6%9A%E7%9A%84%E3%82%A4%E3%83%B3%E3%83%86%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3)にも以下のように記載されています。
>継続的インテグレーション、CI（英: continuous integration）とは、主にプログラマーのアプリケーション作成時の品質改善や納期の短縮のための習慣のことである。

常に一定以上の品質のテストができるようにする(もしくは繰り返す、継続する)ことで変更しやすくする、
一定のデプロイ手順を定義し繰り返す、継続することでリリースに対する心理的負担を軽減する、
その習慣そのものがCI/CDであり、習慣を継続しやすくするための手法として注目されているのが自動テストやデプロイ自動化のような技術なのだと思います。

# 自動化がないときテスト/デプロイは誰がするのか
少し話が横にそれますが、ある程度プロジェクトやプロダクトが大きくなると、おそらく技術要素によって役割分担されたチームが出来上がることが多いと思います。
弊社も漏れなくそんな感じです。全員がフルスタックにはなれません。
フロントエンド開発をする役割・バックエンド開発をする役割・インフラ構築をする役割などになると思いますが、
すべての役割で共通して発生する業務がテストとデプロイ(リリース)です。
もちろんテストエンジニアのようなその部分に特化した役割があることもあると思いますが、その手前で多かれ少なかれ何かしらの確認はすると思います。
つまり、テスト/デプロイは中身は違っても全員がする作業なのです。

# CI/CDは誰のものか
ここでタイトルに戻ります。
皆さんの開発現場では、自動化職人が生まれてしまっていませんか？
特定の技術領域の人に自動化の実装・保守が偏ってしまっていることはありませんか？
前述の通り、テスト/デプロイは全員に必要な作業です。
自分が作った成果物がどのような(どのように)テストを経ているのか知らない、どのような手順を踏んでビルドされデプロイされているのか知らない、ということはありませんか？
そんなときにチームが使っている自動化環境が壊れてしまったらどうしますか？
そのようなことを考えると、人任せにしていていい気がしなくなってきませんか？
CI/CDという習慣は、誰か特定の役割の人たちのものではなく全員のものではないでしょうか。
全員がオーナーシップを持って育てていくものだと思います。

# 最後に
CI/CDは習慣であり、みんなのものです。
だからといって自動化難しそうだなと敬遠している人は大勢いると思います。
でも、取り組み始めると面白いですし、最初から壮大なことをする必要はありません。
できることから一緒に楽しんで取り組んでみんなで育てましょう。
4GPiで使うGPIOピンを変更する

4GPiで使用するGPIOピンは[公式ドキュメント](https://github.com/mechatrax/4gpi/wiki/%E3%83%8F%E3%83%BC%E3%83%89%E3%82%A6%E3%82%A7%E3%82%A2)にあるとおり、それぞれ2つのピンから選択できる
初期状態では

| 記号 | 名称 | GPIO | Default |
|:----:|:----:|:----:|:----:|
| JP2 | 着信通知 | 16 or 18 | 16 |
| JP3 | 電源制御 | 17 or 12 | 17 |
| JP4 | リセット | 22 or 13 | 22 |
| JP5 | 電源状態 | 27 or  6 | 27 |

こうなっている

# 変更方法
まずはジャンパの接続を変更する
例) JP2: 16 → 18
:black_circle::black_circle::white_circle:　:arrow_right:　:white_circle::black_circle::black_circle:

次に4GPiが読み込むファイルを編集する
パッケージをインストールしていれば
`/etc/default/4gpi`
というファイルがあるはず
このファイルの

```text
RI_PIN=16
POWER_PIN=17
STATUS_PIN=22
RESET_PIN=27
```

この部分を編集する
このファイルの詳細は[4gpi-utils](https://github.com/mechatrax/4gpi-utils/)に書いてある
WebpackのIE対応でつまずいたこと

# はじめに

今回は私が体験したwebpackのハマった点を紹介していきます。

# PromiseとIE11
jsで非同期処理を実装する際、axiosを利用するシーンは多いのでないでしょうか。
ただそのままこのaxiosIE11で使用することはできません。
IE11以下では、非同期処理を可能にする[Promiseにサポートしていないため。](https://caniuse.com/#search=promise)
(IEは見事に真っ赤ですねw）


# 本題
とある日私は、既存プロジェクトに追加の実装を担当することに
そのプロジェクトでは既にwebpackの設定がされており、私は実際のjsにだけ意識をして開発を進めていました。
そして無事リリース。（この時はスマホサイトのみ実装）

数週間後、新規機能をPCにも実装が決まり、スマホで実装したソースを流用して開発することに。
ですが開発の途中、IE11でテストをしているとエラーが発生。
調査していると疑問が、「既存の機能では、どう対処しているのだろう」と。
ソースを見てみても特段変わった記述は見つかりませんでした。

# ソース比較
下記は実際のソースから一部抜粋したものになります。
パッと見大まかな処理は変わりません。
ですがパターンBではIE11でエラーが起きてしまいました。

## パターンA(既存コード)
IE11: ○

``` app.js
let Vue = require('vue');
let axios = require('axios');

new Vue({
    data: {},
    methods: {
        getData: function() {
            return axios({
                method: 'post',
                url: '/XXX/',
                data: params,
            });
        }
    }
});
```

## パターンB(新規コード)
IE11: ×

``` template.vue
<template>...</template>

<script>
import axios from 'axios';

export default {
    data: function() {
        ...
    },
    methods: {
        getData: function() {
            return axios({
                method: 'post',
                url: '/XXX/',
                data: params,
            });
        }
    }
}
</script>
```

```app.js
import Vue from 'vue';
import App from './App.vue';

new Vue({
    ...
});
```

# なぜ
webpackの設定とjsの記述に問題がありそうだと推測。

既存コードはrequire構文でaxiosを読み込んでいる。
require構文はwebpackが直接コンパイルできるので、依存関係はwebpack側でシンプルに解決できていました。

一方新規のコードはimport構文を使用しており、webpackでコンパイルする前にbabelがトランスコンパイルが行われていました。
またwebpackの設定を見てみると、babelが.jsにのみ適応されていました。
新規コードでは.vueファイル側でaxiosを読み込んでおり、上手く依存関係を解決出来なくなっていました。

```webpack.config.js
...
{
    test: /\.js$/,
    exclude: /node_modules/,
    use: {
        loader: 'babel-loader',
        options: {
            'presets': ['@babel/preset-env']
        }
    }
},
...
```



# 解決策
nodeモジュールの`es6-promise`を読み込み、Promiseのトランスコンパイルさせることで取り急ぎは解決。

``` template.vue
<script>
import axios from 'axios';
require('es6-promise').polyfill();

...
</script>
```
※とりあえず解決したが、今度はwebpackの設定から根本解決できるようにしていきたいです。

# 最後に
今回の件が無かったらwebpackに対する理解を深める機会が無かったかもしれない。
そう言う意味ではIEに感謝(?)
【ruby】簡単ッ! do~endブロックって？

rubyを扱っていると、当たり前のように`do ~ end`の記述を書きますが、実際にはどんな感じで実行されているのか、サラッと書きます。
厳密な話は置いておきましょうよ😚
ノリで理解してくれればok!

## block/procを理解する
[Ruby block/proc/lambdaの使いどころ](https://qiita.com/kidach1/items/15cfee9ec66804c3afd2)
こちらの記事が凄いわかりやすいので、細かいことは読んでほしいのですが、
簡単な理解を箇条書きします。

- blockは処理の集合
- blockは単体で存在しない、引数になる
- blockはメソッドの最後の引数になる(do~endは2つない)
- `&block`は`block`を`proc`に変換してる
- procはblockをオブジェクトにしたもの

細けえことはコード見ればええねん🖐

### blockの実行方法

ここで注意してほしいのは、
実行しているのは`just_do_your_block!`メソッドで、その引数に`block`を渡しているだけです!
つまり`return`されるのは`just_do_your_block!`の最後の値であって、
今回はたまたま`block.call`の返却値がそのまま出力されているだけです🤽‍♂️

```class_for_test.rb
# クラス定義
class ClassForTest
  def just_do_your_block!(&block)
    block.call
    # instance_eval(&block) # でもok
    # yield # でもok
  end
end

# 実行部分
ClassForTest.new.just_do_your_block! do
  'Hello ruby!'
end
# => "Hello ruby!" 
```

### ブロック変数と一緒に実行する

blockが最後の引数になってるということがわかりやすいですね。

```class_for_test.rb
class ClassForTest
  def just_do_your_block!(e, &block)
    block.call(e)
    # instance_exec(e, &block) # でもok
    # yield(e) # でもok
  end
end

ClassForTest.new.just_do_your_block!('block_params') do |e|
  puts "Hello ruby! with #{e}"
end
# => "Hello ruby! with block_params" 
```

## mapを実装してみる
実際のコードはもっと複雑そうだし、C言語はよくわかりません🙄
単純に出力結果を`add`しているだけですね

```array_for_test.rb
# クラス定義
class ArrayForMap
  def initialize(array)
    @array = array
  end

  def map(&block)
    new_array = []
    @array.each do |e|
      new_array << block.call(e)
    end
    new_array
  end
end

# 実行部分
array = ArrayForMap.new([1,2,3])
array.map do |e|
  e + 1
end
# => [2, 3, 4] 
```

## 所感
`block/proc`という概念は、ちゃんと考えると理解できますが、無意識でも使えるのが`ruby`の凄いところなのかもなあ、と思いました。  
てか、他の言語にも`block/proc`ってあるのだろうか🌝🌚
僕のarcpy(Python)

自分用のまとめ
随時更新
**自分がわかればいいからところどころ用語が間違ってるかも**

！見方

```python
#コマンド
    #引数のオプションの説明
```

###モジュール読み込み

```python

import arcpy
```

##操作

####読み込み

```python
#シェープファイルのプロパティの読み込み
arcpy.Describe() #返り値はdescribeオブジェクト
```

####クラス・テーブルの構造的な操作
```python
#フィールドの追加
arcpy.AddField_management()
    #第一引数：フィールドを追加するテーブル(シェープファイルとか）
    #第二引数：追加するフィールドの名前
    #第三引数：追加するフィールドのデータ型
```

####クラスの作成
```python
#shapeファイル等のコピー
arcpy.Copy_management()
    #コピーされるファイル
    #コピー先のパス

#フィーチャークラスの作成
arcpy.management.CreateFeatureclass()
    #第一引数：アウトプットパス
    #第二引数：アウトプットクラス名
    #geometrytype=タイプ
    #spatial_reference=使用する空間オブジェクト

```

####書き込み等

```python


#フィールド演算
arcpy.CalculateField()
    #第一引数：計算を行うテーブル
    #第二引数：計算を行うフィールド
    #第三引数：演算式

#テーブルのポイントデータからフィーチャークラスを作成する
arcpy.management.XYTableToPoin()
    #第一引数：読み込むテーブル
    #第二引数：作成先のパス
    #第三引数：X
    #第三引数：y

#クラスにフィールドを追加
arcpy.AddField_management()
    #第一引数：追加先のクラス
    #第二引数：フィールド名
    #第三引数：追加するフィールドの型
    #field_length = フィールドの幅
    #field_alias = エイリアス

#フィールドを日付フィールドに変換

arcpy.ConvertTimeField_management()
    #第一引数：対象クラス
    #第二引数：対象フィールド
    #input_time_format= 日付のフォーマット。少し間違えると、読み込みミスる。
    #output_time_field= 出力先のフィールド。新しく作ってもいい。


#pointデータをlineデータに加工
arcpy.PointsToLine_management()
    #第一引数：入力クラス
    #第二引数：出力クラス
    #linefield= 線としてつなげるフィールド
    #sortfield= ソートするフィールド

#フィールド演算
arcpy.AddField_management()
    #第一引数：演算を行うファイル
    #第二引数：演算を行うフィールド
    #第三引数：SQLでの演算式

#ジオメトリ属性の追加
arcpy.AddFeometryAttributes()
    #第一引数：属性を追加するフィーチャークラス
    #第二引数：属性もしくは形状のプロパティ
    Length_Unit = #長さの単位


```

- リンク
 - [ジオメトリ属性の追加](https://pro.arcgis.com/ja/pro-app/tool-reference/data-management/add-geometry-attributes.htm)
【Angular】複数アプリケーションの共存

#はじめに
本記事ではAngularで大規模プロジェクトを行う場合の複数アプリケーションやライブラリを一つの`angular.json`で共存させる方法について書きます。

#複数のアプリケーションにするシチュエーション
複数のアプリケーションに分けるもっとも多いシチュエーションはユーザーによって画面が全く異なる場合だと思います。
例えばECサイトなどの場合など、管理サイドのサイトとユーザーサイドのサイトが存在する場合に、ユーザーサイドは管理サイドのサイトを一切閲覧することが出来ません。
こう言った場合に一つのアプリケーションで作ると、不要な画面の分までファイルサイズが増大します。ビルド時間も無駄に長くなります。
また管理サイドのjavascriptのソースがユーザーサイドに閲覧されるのはセキュリティ的にもよろしくありません。
アプリケーションを分けることにより、このような問題は発生しなくなります。

# 作成方法
##プロジェクト作成
複数アプリケーション共存時の場合、`angular cli`が生成するファイルのフォルダ構成が異なります。
srcフォルダ配下ではなくprojectフォルダ配下に、アプリケーションを追加していくようになります。
そのため、`ng new`する場合に最初からあるsrcフォルダ配下のappアプリケーションは邪魔になります。
アプリケーションが作成されないように`--createApplication=flase`にして`ng new`します。

```
ng new --createApplication=false
```
プロジェクト作成直後
![b171973c57b7ab8901b79a9d81a6b868.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252031/7cee02f4-71f8-af24-f5a0-2d0ba3c15d46.png)

##アプリケーション作成
アプリケーションを追加していきます。コンポーネントのprefixはデフォルトではappになってしまいますが、アプリごとに異なる方が良いと思います。`--prefix`で指定します

```
ng generate application main --prefix=main
ng generate application admin --prefix=admin
```

アプリケーション作成直後
![f3940635cd908ec14c80a8be0c58bd3e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252031/215ce3b4-b5d6-d856-37cb-beb960f59221.png)
追加したアプリケーションが、projectフォルダ配下に並ぶようになります。
##起動
`--project`で起動するアプリを選択して起動します。同時に起動出来るようにportは分けています。

```
ng serve --project main --port 4200
ng serve --project admin --port 4300
```

`http://localhost:4200/` でmainアプリ
`http://localhost:4300/` でadminアプリの開発が行えるようになります。

##共通assets
画像などで共通の部品がある場合は多いと思います。一つのフォルダで管理したいものです。
どちらのアプリケーションからも見ることが出来るassetsフォルダを作成し、`angular.json`に設定を追加します。

assetsフォルダ作成
![4563bfdbf04877b42bcfad3515820369.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252031/607b7c8b-17bd-516d-b0a5-78a3c8ae234e.png)

angular.json内(各アプリケーションのビルド設定)

```
                        "assets": [
                            "projects/main/src/assets",
                            "projects/main/src/favicon.ico",
                            "projects/assets",
+                            {
+                                "glob": "**/*",
+                                "input": "./assets/",
+                                "output": "./assets"
+                            }
                        ],
```
##ライブラリ追加
アプリケーションの数が増えてきた場合に、共通のコンポーネント、サービスなどをライブラリ化させるとのも良いと思います。

```
ng generate library common --prefix=common
```

##ライブラリのビルド
```
ng build --project common
```

ビルドされたライブラリをアプリケーションが参照するようになります。

全部やったあと
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252031/1ea02c4c-d2ca-ee0c-df16-e493b47f041b.png)

#最後に
angularは色々親切だなと思います。
構成で悩む時間が減り、スタートアップがしやすい。
連番のダミー画像を取得する

連番の画像が必要になったので
Placehold.jp をcurlで叩いて取得します

```
http://placehold.jp/{文字サイズ}/{背景色}/{文字色}/{幅}x{高さ}.png
```

-o でファイル名も指定して 0〜40の連番ファイルを作ります。

```bash
curl -o '#1.png' 'https://placehold.jp/100/35947b/ffffff/400x400.png?text=[0-40]'
```
基本情報9週目(12/16週)

# 目標と結果
### 目標
- 参考書をみる。
- 基礎理論とアルゴリズムの勉強を続ける。
    - 時間管理、工数管理も忘れずに。
- [基本情報技術者試験ドットコム](https://www.fe-siken.com/)を使う。
    - (午後問題もカバーされてる)
- 独習ゼミの解説動画を観てみる。
- 午後で通用する様に内容を理解する。
- 独習ゼミのアセスメントを受ける。
- 12月の計画を水曜日までに立てる。

### 結果
- アセスメントを受けた。
    - テクノロジとマネジメントどちらも、よく読めばできる問題と意味のわからない問題がある。
        - 複雑でさらに計算問題が含まれている問題。

# 振り返り
### Keep
- 道場は継続。

### Problem
- プログラミングとアルゴリズム。
- 計算問題が苦手。
    - 稼働率。

### Try
- 何に集中するのか決める。
    - ソフトウェア開発(言語)以外は一通りできるようにする。
僕のstr(Pytnon)

自分用のまとめ
随時更新
**自分がわかればいいからところどころ用語が間違ってるかも**

！見方

```python
#コマンド
    #引数のオプションの説明
```


###モジュール読み込み

無し

##頻出操作

```python
#全て大文字に変換
str.upper()

#埋め込み表示
line = "{0}さんの身長は{1}cmです。{0}さんの体重は{2}kgです。".format("山田", 190, 105.3)
#山田さんの身長は190cmです。山田さんの体重は105.3kgです。
#{インデックス番号:書式指定}

```
CircleCIで使用するDockerのイメージを完全に固定する

先日あるAndroidアプリのCI環境が突然動かなくなりました。

原因は `circleci/android:api-28-node` の nodejsのバージョンがv12に上がっていたことのようでした。

「CI環境のイメージを勝手に変えてくれちゃって困ったもんだなぁ」とか思っていました。
しかし[ドキュメント](https://circleci.com/docs/ja/2.0/configuration-reference/#docker--machine--macosexecutor)を漁ってみると、以下のようにハッシュ値を指定して完全に同じイメージを毎回使用できるようにすることができることがわかりました。

```
docker:
  - image: redis@sha256:54057dd7e125ca41afe526a877e8bd35ec2cdd33b9217e022ed37bdcf7d09673
```

それまでは以下のように指定しており、これで完全に同じイメージが毎回使えるのだと誤解していました。

```
docker:
  - image: circleci/android:api-28-node
```

サンキューCircleCI.
僕のConfigParser(Python)

自分用のまとめ
随時更新
**自分がわかればいいからところどころ用語が間違ってるかも**

！見方

```python
#コマンド
    #引数のオプションの説明
```

###ConfigParserっていつ使うの？
設定ファイル（iniファイル）を扱うとき


###モジュール読み込み

```python
import ConfigParser #Python2
import configparser #Python2
```

##頻出操作

こんなiniファイルがあったとする

```
[I]
name = taro
age = 40
```


```python
#iniファイルの読み取り
ini = Configparser.SafeConfigParser()
ini.read()
    #引数に読み取るiniファイルのパス

#要素の取得(taroの取得を例に）
#パターン1
name = ini.get['I']['name']
#パターン2
name = ini.get('I','name')

```
WordpressのAccess-Control-Allow-Originヘッダ追加


Wordpress（ver 5.3.1）サイトのRSSフィードをAjaxで取得しようとしたときに
CORSでブロックされてしまった時の話。



#ChromeのDeveloper Tool Consoleのエラー
※URLはサンプル例

```
Access to XMLHttpRequest at 'https://mydomain.com/?feed=rss2&_=xxxxxxxxxx' 
from origin 'https://test.mydomain.com' has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
```

#対策

Wordpressのテーマのfunctions.phpに以下のコードを追加した。

```php:functions.php
/**
 * CORS対策
 * Access-Control-Allow-Originヘッダの追加
 */

add_action('send_headers', 'cors_http_header');
function cors_http_header(){
    header("Access-Control-Allow-Origin: https://test.mydomain.com");
}
```
#Stripe のクレジットカードで、顧客からの不正利用申請・不審請求のテストをするためのカード番号四種類

# 番号

特定の番号を使うとシュミレートできるみたいだ。

https://stripe.com/docs/testing

![image](https://user-images.githubusercontent.com/13635059/70855500-09f14a00-1f0f-11ea-8c0c-7bbd7f6b70f2.png)

定期支払いでテストを行った

# 顧客からの「カード不正使用」の不審請求

支払いは成功するが、対応必須扱いになるようだ

>4000000000000259 | With default account settings, charge succeeds, only to be disputed as fraudulent. This type of dispute is protected if 3D Secure was run.


>支払いに関し不審請求が申請された理由:
>カード保有者はこの請求を認めておらず、カードの不正使用であると主張しています。
>2019年12月24日の午前8:59までに顧客のカード発行会社に反証資料を提出してください
>この支払いはブロックされるべきものですか？
>ブロックしきい値を調整してください。


![image](https://user-images.githubusercontent.com/13635059/70855498-01990f00-1f0f-11ea-97db-8aece839d033.png)

# 顧客から「商品が届かない」という理由で不審請求されるもの


>4000000000002685
>With default account settings, charge succeeds, only to be disputed as product not received. This type of dispute is not protected if 3D Secure was run.

![image](https://user-images.githubusercontent.com/13635059/70855728-f5af4c00-1f12-11ea-90be-c267f60116bb.png)

# 不正請求の照会を受けるもの 

>4000000000001976 | With default account settings, charge succeeds, only to be disputed as an inquiry.


>不審請求の照会を受けた支払い
>カード保有者はこの請求を認めておらず、カードの不正使用であると主張しています。
もっと知りたい
>現時点では、ご利用の銀行口座から引き落としは行われていません。ただし、カード保有者に代金を返金するかどうかを判断するうえで必要であるとして、カード保有者のクレジットカード会社がさらに情報を提供するよう要求しています。
>2019年12月24日の午前8:59までに顧客のカード発行会社に反証資料を提出してください


![image](https://user-images.githubusercontent.com/13635059/70855777-d369fe00-1f13-11ea-9ebe-b278a300d972.png)

# 早期警告を受けけるもの

>4000000000005423 
>With default account settings, charge succeeds, only to receive an early fraud warning.
![image](https://user-images.githubusercontent.com/13635059/70855740-27c0ae00-1f13-11ea-81d9-3e9d0dc45d3a.png)



# リスクスコア

支払いをブロックするために、閾値を設定できるらしい


![image](https://user-images.githubusercontent.com/13635059/70855524-7ec48400-1f0f-11ea-893b-0825b363db57.png)


# 顧客理由でカードが使えない場合をテストするには？

それはそれで他の番号あるみたいだ。
最初、こちらを探していたのだが、別の場所にたどり着いてしまっていたみたいだ。

https://stripe.com/docs/testing#cards-responses

![image](https://user-images.githubusercontent.com/13635059/70855831-baae1800-1f14-11ea-9909-5f4f04737e58.png)


# Original by Github issue

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








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Site24x7のAzure監視を試してみた

こんにちは。@Miu24x7です。

みなさんはAzure使ってますか？AWSやGCPと合わせて利用している方も多いと思います。
今回はSite24x7の機能の1つ、Azure監視を行って、そのメリットを見ていきたいと思います。

#Site24x7とは
Site24x7はWebサイト、サーバー、AWSなどのクラウド等を監視できるオールインワン型クラウド製品です。
ブランド評価機能では、Webページのマルウェアやフィッシング詐欺の脅威があるかどうかを判定することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/aa4e7828-a716-948e-7995-cb1119e8108e.png)

#設定方法
###Azure Active Directory(Azure AD)でのアプリの登録
・Azureアカウントにログイン
・Azure ADにアクセスし、[アプリの登録]→[新規登録]の順にクリック
・登録するアプリケーションの名前（とくに指定なし）を入力し[登録]をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/5b55664f-c715-a161-09c7-4ab7506f7873.png)
・発行されたアプリケーションIDとテナントIDを保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/d02a5370-22b0-76ce-bb09-4e318fe1b592.png)

###シークレットキーの取得
・該当アプリページ内で[証明書とシークレット]→[新しいクライアント シークレット]の順にクリックし、シークレットキーを保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/df249140-c4ea-a993-0bb5-9506020d7575.png)

###アプリへのロールの割り当て
・[サブスクリプション]→[アクセス制御（IAM）]→[追加]の順にクリック
・共同作成者を選択後、先ほど作成した"アプリ"を選択し[保存]をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/8f1687db-c35a-993a-349e-97351c1a092c.png)

###Site24x7コンソールでAzureアカウントをディスカバリー
・[Azure]→[Azure監視の追加]にアクセス
・[カスタムアプリで認証する]を選択後、保存した各情報を入力し[リソースのディスカバリーを進める]をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/249f1021-4584-5ba3-61bd-3dbc752e1fa8.png)

・各項目を入力（赤は必須項目）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/cf5a41fd-4cf5-a340-c82c-23e0b579fad0.png)



#連携結果
自動的にAzureに登録されているリソースがSite24x7に反映されました。
Microsoft APIから各監視データを持ってきています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/b1da5590-4681-c50b-dda9-eab3d235c5f1.png)

**・仮想マシン監視画面**
下記の他にCPU使用率などを表示しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/c0f9a008-842e-c9c2-2ed6-7a5607013bfc.png)


基本的にSite24x7の機能としてあるAWSやGCPの監視と差はないように感じますが、単一コンソール上で「一元管理/一元監視」できるのが良いですね。


#最後に
今回はSite24x7でAzureサービスを監視できるようにしました。
複数のクラウドサービスを利用している人は、すぐに各サービス監視データにアクセスできるため使い勝手〇です！

Site24x7では無料期間を設けていますので、ご興味があれば是非！
https://www.site24x7.com/signup.html
僕のsys(Python)

自分用のまとめ
随時更新
**自分がわかればいいからところどころ用語が間違ってるかも**

！見方

```python
#コマンド
    #引数のオプションの説明
```

###モジュール読み込み

```python

import sys
```

##操作
```python
#プログラム終了
sys.exit()

#自作のモジュール等のインストール元パスの設定
sys.path.append()

#コマンドラインの引数をリストで取得
[引数] = sys.argv
```
.gitignore_global を活用してメモやスクリプトを整理しよう

.gitignore_global を活用してメモやスクリプトを整理しよう

[Git Advent Calendar 2019](https://qiita.com/advent-calendar/2019/git) の 16 日目の記事でございます

## メモ、あるよね
プロジェクトに関するメモとかさ、開発環境立ち上げるコマンドのメモとかさ、デプロイ方法のメモとかさ、動作確認のやり方のメモとかさ、特定の内容を確認する SQL のクエリメモとかさ、とにかくなんかあるでしょ？

ない？  
ない人はいーや、はいメリークリスマースおつかれさまでしたー

メモある人さ、どこにメモしてる？

色々工夫はあると思うんだけど、今日は一風変わった方法を紹介するよ

## メモ、散らかるよね
チームを移動したり複数プロダクトを保守したりすると、当たり前だけどプロダクトごとに違う内容をメモしないといけないよね

`~/Documents/memo`とかに置いといた巨大な`メモ.txt`から今欲しい内容だけ目で探して、例えば長いコマンドなんかを手でぺ〜っと選択・コピーしてターミナルに戻って貼り付け、なんてやってない？

それさ、めんどくさくない？

## メモ、プロダクトごとに整理したいよね
自分の`.gitignore_global`に例えば`my-memo/`なんて書いておけば、clone してきたプロジェクトの`my-memo/`の下に何をどう置いたって他の人には影響しない

```
$ cat ~/.gitignore_global
my-memo/
```

```
$ echo 'bla bla bla...' > my-memo/initialize.txt

$ git status -sb
## No commits yet on master
```

プロジェクトによって異なるメモは、そもそもプロジェクトとセットにしておけば良いじゃん？

## メモ、中身がコマンドなら実行したいよね
じゃあ`my-commands/`なんてのを無視指定しておいて、その下にどかどか`.sh`でも`.py`でも入れれば良いよ

```
$ cat ~/.gitignore_global
my-memo/
my-commands/
```

```
$ cat my-commands/boot.sh
docker-compose -f docker/docker-compose.yml up -d db
./gradlew clean bootRun

$ cat my-commands/allocate.sh
curl -X POST localhost:8000/foo/v1/options/new

$ cat my-commands/change.sh
curl -X PUT localhost:8000/foo/v1/options/change/$1 -d "changeTo=option-b" -d "reason=more-performance" -d "date=`date "+%Y%m%d"`"
```

```
$ sh my-commands/boot.sh

$ sh my-commands/allocate.sh
35

$ sh my-commands/change.sh 35
option ( id = 35 ) was changed.
```

なが〜い`メモ.txt`から持ってきて書き換えたりするより使いやすいね

## メモ、無くさないようにね
git 管理されてないので、また clone すれば良いや〜って感覚で消しちゃわない様に気をつけてね

こんなやり方もあるよ、整えると便利だよ、ってことで紹介でした
SaaSやクラウドストレージ前提のデータ保存計画（案）

# SaaSやクラウドストレージの利用は当たり前

　ビジネスだけでなく、プライベートにおいても、SaaSやクラウドストレージをつかってデータを作ったり、保存したりするのは多くなってきた。
SaaSにおいても、GoogleDriveやDropBox、OneDriveにデータを保存する機能がほとんど付いている（付けるのが仕様上当たり前かも）。

　そうなると、ローカルPC、USBのハードディスク、NASとかで保存していた時代とは違う、クラウド上のデータもどう管理していくかを考えないといけない。

# データの形式：できるだけテキスト形式、汎用的なフォーマットで

　データそのものについては、できるだけテキストベース、かつ、汎用的なフォーマットのものでバックアップを取れるようにすべきであると思う。
　SaaSについてはExportでCSV、XML、JSONなどデータをテキストベースで書き出せるものがある。
　Office365のように、ExcelやWordなど特定のアプリに依存したファイルもあるが、やむを得ない場合はのけて、できるだけテキストベースでの保存がよいと思う。

　理由は、データのサイズが小さいこと。壊れにくいこと。
　また、CSVやJSONであれば、自分で加工して、別のSaaSへの転送もできる。

　
# 各ストレージの役割を明確に設計する

　今は、フリーでつかえるものから、比較的低額でつかえるストレージがたくさんあり、会社にしろ個人にしろ色々な場所にデータを点在させている人も少なくないのではと思う。

　作業上急いで、手軽なところにおいたりすることはある。
　けれど、できれば本体となるデータストレージは一つにするか、もしくは、ストレージを何らかのツールやサービスで統合しているなら、その統合したものをメインにつかって管理するべきだと思う。

　つまり、データの配置計画をたてて、ここにメインは保存するというポリシーを作っておく。
　そうしないと、データの検索もさることながら、バックアップとかデータ移行をするときに手間取ってしまう。
 
 会社でよく使う方のドライブをメインする。特に、SaaSを提供しているクラウドストレージをメインにするのがいいのだろうと思う。
Office365+OneDrive、GSuiteとか。
　dropBoxとかSaaSを持ち合わせないものは、共有やサブとして使うのがいいのかもしれない。

# ローカルストレージの扱い

　これまでは外付けのHDDやNASがデータのバックアップ先であった。
　けれど、SaaSやクラウドストレージがでてくると、少し役割が変わる。

　割り切って、ローカルストレージを放棄するのも一つの選択だと思う。SaaSやクラウドストレージを信じて、いつでもネットが繋がるのでローカルストレージは基本いらないとする。
　
　一方、やはり大手SaaSやクラウドストレージですら大障害がおきないとはいいきれない。

　それに備えて、ローカルストレージとバックアップをとるというのもありだと思う。
　Office365だとOneDriveがストレージとなるが、これをローカルのドライブと同期ができる。SharePointはOneDriveと同期すれば、自然とローカルのドライブと同期ができる。

　また、GoogleDriveもローカルとの同期ツールがある。DropBoxはいうに及ばない。

　このようにクラウドストレージの大半は、ローカルドライブとの同期ツールを提供しているので、外付けドライブなどとクラウドストレージを同期すれば、万が一のネットワーク障害、サービス障害への対応もできる。

　ローカルストレージについては、ただバックアップするだけでなく、暗号化やロックをしておくことも必要であると思う。


# ほんの少し考えるだけで、バックアップはすっきりする

　いろんな会社の手伝いをしたり、自分も含めて、データのバックアップについては結構、時間をさかずいきあたりばったりになっているところもある。
　でも、すこし落ち着いて考えると、それほど難しいことはなく、何をつかうのか、そして、そこにどんなデータを置くのかを整理すると意外とすっきりとデータは管理していける。

　個人はともかく、企業では、「データ保存設計」というのをしておくべきだろうと思う。ナレッジ共有としては当たり前だけど。
MySQL5.7以下の外部キー制約がない物理削除と論理削除のテーブルを安易に人的削除してはいけない理由


この記事は[Hameeアドベントカレンダー2019](https://qiita.com/advent-calendar/2019/hamee) 16日目の記事です。

物理削除と論理削除についての説明に関しては別で詳しい記事を書いてくれている人がいるのでそちらを見てください。

今回の扱うテーブルは例としてあげているだけなのでテーブル自体の設計に対してのツッコミは無しでお願いします。

実際に試した環境　mysql 5.6.22 innodb

# 今回取り扱う論理削除と物理削除のテーブル例
本テーブルと技術本テーブルがあり
本テーブルは物理削除
技術本テーブルは論理削除だったとする

先に技術本テーブルが存在し論理削で運用されており、他の種類の本などのテーブルを作成するために、全ての本に共通する項目を持つ本テーブルを新しく作成。論理削除する理由が特になかったため物理削除のテーブルとした。

book テーブル

|id |title |
|---|---|---|
|1  |PHPの本  |
|2  |Rubyの本  |
|3  |Pythonの本 | 
|4  |Goの本|


technical_book テーブル

|id |book_id|del_flg  |
|---|---|---|
|1  |1|0|
|2  |2|0|
|3  |3|0|
|4  |4|0|



# GOの本を削除した場合

1 Goの本情報を物理削除
2 太郎が投稿した記事の削除フラグをTRUEに変更する必要がある。

book テーブル

|id |title | 
|---|---|---|
|1  |PHPの本  |
|2  |Rubyの本|
|3  |Pythonの本|


technical_book テーブル

|id |book_id |del_flg  |
|---|---|---|
|1  |1|0|
|2  |2|0|
|3  |3|0|
|4  |4|1|

これが正しい状態だったとします。


# bookテーブルが削除されない期間が生まれてしまった時に、id=3のPythonの本を消した場合

book テーブル

|id |title | 
|---|---|---|
|1  |PHPの本  |
|2  |Rubyの本|
|3  |Pythonの本|
|4  |Goの本|


technical_book テーブル

|id |book_id |del_flg  |
|---|---|---|
|1  |1|0|
|2  |2|0|
|3  |3|0|
|4  |4|1|

本当であれば、bookテーブルのid = 4のGoの本のレコードは物理削除しなければいけない

bookテーブルに登録できる上限が決まっていて上限に行ってしまった時に、どのようにbookテーブルのレコードを削除するのが正しいでしょうか？

1番最初に思いつく方法としては、technical_bookとbookをJoinして削除フラグが立っている物にひもづくbookテーブルのレコードを削除すれば良さそう

```sql:delete.sql
DELETE `book` 
FROM 
  `book` 
  INNER JOIN `technical_book` ON `technical_book`.`book_id` = `book`.`id` 
WHERE 
  `technical_book`.`del_flg` = 1;
```
book テーブル

|id |title | 
|---|---|---|
|1  |PHPの本  |
|2  |Rubyの本|
|3  |Pythonの本|

technical_book テーブル

|id |book_id |del_flg  |
|---|---|---|
|1  |1|0|
|2  |2|0|
|3  |3|0|
|4  |4|1|


しかしこの方法で消していくの方法ではMySQLのバージョンがMySQL 5.7以前の場合、まずいパターンが存在する

この状態でserver restartすると自動採番が再計算されてしまう。
auto_incrementの値は再計算されて4になる。

この状態で新しいJava本とPerlの本ができてPerlの本を削除した場合
bookテーブル

|id |title | 
|---|---|---|
|1  |PHPの本  |
|2  |Rubyの本|
|3  |Pythonの本|
|4  |Javaの本|
|5  |Perlの本|


technical_book テーブル

|id |book_id |del_flg  |
|---|---|---|
|1  |1|0   |
|2  |2|0  |
|3  |3|0  |
|4  |4|1  |
|5  |4|0  |
|6  |5|1  |

上記のSQLを実行してした場合、現在生存しているJavaの本も消えてしまう。

bookテーブル

|id |title | 
|---|---|---|
|1  |PHPの本  |
|2  |Rubyの本|
|3  |Pythonの本|


technical_book テーブル

|id |book_id |del_flg  |
|---|---|---|
|1  |1|0   |
|2  |2|0  |
|3  |3|0  |
|4  |4|1  |
|5  |4|0  |
|6  |5|1  |

つまり以下のSQLを実行して対応するレコードが存在する場合は、上記のSQLでの削除すると消えてはいけないレコードが消えてしまうことになる。

```sql:delete.sql
SELECT 
  id 
FROM 
  `technical_book` 
GROUP BY 
  `book_id` 
HAVING 
  COUNT(`book_id`) > 1 
  AND MAX(`del_flg`) != MIN(`del_flg`);
```

# 何が問題だったのか

このテーブルで問題だったのは既存のテーブルが論理削除で運用されているのに新しいテーブルを物理削除で作成してしまったことが原因だと考える。

# 参考リンク
[MySQL 5.7以前のAUTO_INCREMENTはサーバ再起動すると値が変わるがMySQL 8.0では変わらなくなった
](https://qiita.com/matyahiko2831/items/afd0e460085e99cc5466)
僕のDjangoアプリ立ち上げ




自分用のメモ
随時更新

**自分がわかればいいからところどころ用語が間違ってるかも**

##djangoのアプリを作成～テンプレートの読み込み

- 条件
 - getとpostはビュークラスで管理
 - URLは各アプリで管理
 


####1.ANACONDAのトップ画面のEnvironmentsタブのCREATEをクリック
<img width="253" alt="スクリーンショット (11).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549748/38874832-bdc2-334f-5a6b-a307223ac1be.png">



####2.仮想環境の詳細を選択
<img width="315" alt="スクリーンショット (10).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549748/39ff5976-477e-5744-a76b-63a2d58f4dc0.png">



####3.ターミナルから仮想環境にDjangoをインストール
ターミナルで`pip install django`
<img width="240" alt="スクリーンショット (12).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549748/ceebec14-1e1c-ad63-380c-a1ebb4912779.png">


####4.プロジェクトを作成する。
ターミナルでcdをプロジェクトを作成したいディレクトリに移動して`django-admin startproject 任意のプロジェクト名`



####5.アプリケーションを追加
ターミナルで`python manage.py startapp  任意のアプリ名`
<img width="298" alt="スクリーンショット (14).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549748/a7f76c47-7295-8a1f-eb63-72785adc50ef.png">


####6.アプリケーションを開く
<img width="248" alt="スクリーンショット (15).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549748/66c29929-b767-0a51-bce7-75af3bec586a.png">


####7.URLの処理をアプリ内に移す
プロジェクトのurls.py

```python
from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('sns/',include('sns.urls')),
]
```

アプリのurls.py

```python
from django.urls import path
from . import views
from .views import SnsView

urlpatterns = [
    path('',SnsView.as_view(),name='index'),
]


```

####8.URLの処理をアプリ内に移す
アプリをsettings.pyに追加
プロジェクトフォルダ\プロジェクト名\settings.py

```python
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'sns_app' #アプリを追加
]
```

####9.templatesフォルダの作成とhtmlの作成
`アプリ\templates\アプリ名`
にテンプレートを作成


####10.viewクラスの作成

```python
from django.shortcuts import render
from django.http import HttpResponse
from django.views.generic import TemplateView


class SnsView(TemplateView):
    def get(self,request):
        self.params={}
        return render(request,'sns/index.html',self.params)
```
flutter doctorでのエラー突破方法　191216


##目標
flutter導入後に
flutter doctorで出てくるエラーを対処する
※flutter doctorとはflutterでを使う上の開発環境が不足箇所がないぁ診断してくれう便利な機能です。

##結論
Androids Studioをダウンロード
Androids Studioのプラグインでflutterをダウンロードする
android　licenses statusの設定をする

Xcodeをダウンロード・アップデート
cocoapodsの導入


##詳細
```flutter:ターミナル
flutter doctor
[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from:
      https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK
      components.
      (or visit https://flutter.dev/setup/#android-setup for detailed
      instructions).
      If the Android SDK has been installed to a custom location, set
      ANDROID_HOME to that location.
      You may also want to add it to your PATH environment variable.

[!] Xcode - develop for iOS and macOS (Xcode 10.3)
    ✗ CocoaPods not installed.
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin
        code that responds to your plugin usage on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To install:
        sudo gem install cocoapods

[!] Android Studio (version 3.5)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.



[!] Connected device
    ! No devices available


```
##解決方法

###Android Studio

####ダウンロード
https://developer.android.com/studio/index.html

####flutterのプラグインを入れる
(1)Android Studioを開く
(2)ヘッダー部分の『Android Studio』をクリック
(3)preferenceをクリック
(4)Pluginsをクリック
(5)検索画面でflutterを検索、ダウンロード


####android　licenses statusの設定
```ターミナル
flutter doctor  --android-licenses
```
で全部の質問をyで回答する


###xcode
自分の場合、すでにダウンロードされていたのでアップデートのみ行った。
23Gの空き容量（20Gでは容量不足と注意された)がないとアップデートが開始されない。

####cocoapodsの導入
→iOSのライブラリを管理してくれるソフトらしい

```ターミナル
brew update
brew install cocoapods
pod setup
```
→home brewがない人はダウンロードしてください
SequelProの代替を淡々と探す

MacのMySQLクライアントと言えば、SequelPro。SequelProがあるから、WindowsではなくMacがいいとも言えるし、SequelProがあるからPostgresではなくMySQLが良いとも言える。

以下、SequelProがいいところ。

- SSL Tunnelができる
- クエリ結果をエクセルにコピペできる
- sqlのコード補完が賢い
- 複数のWhere文くらいまでは、コードを書かなくてもGUIのみで可能
- TEXTフィールドみたいな長いフィールドは一覧では読み込まないという設定が可能
- BLOBに入った画像やPDFがプレビューできる
- インポート、エクスポートが楽

めちゃくちゃ便利なので、エクセルの代わりに、MySQLデータベースを使ってるくらい。ちょっとしたテーブルデータはsqlダンプファイルでやり取りする。下手にCSVにして前ゼロが消える恐ろしさもない。

ただしそれもSequelProがあってのこと。WindowsやLinuxの人は苦労をしている。そしてまだ決め手はないので、この記事を淡々と更新していく。

### Adminier（今の普段使い、ただしおすすめしない）

AdminerはphpmyadminのようなブラウザベースでのDBのインターフェース。実は私はこれを使ってる。ブラウザなので、ローカルのMySQLに接続するにもWebサーバを建てなくちゃいけない。ApacheやNginxがなくても、PHP単体でもWebサーバにはなり得るので、スタンドアドン版あるけど、実体はWebサーバーがたってる。

SequelProみたいには、SSHトンネルができないので、ローカルサーバにSSHポートフォワードをした上で、リモートのDBに繋いでいる。SSHポートフォワードしなくちゃいけない時点で、初心者には難しい。さらにSSHポートフォワードは当然切れるので、autosshというツールで「一度キレても再接続」するようにしている。このあたりも他人におすすめするのには複雑すぎる。

phpmyadminとできることはほぼ一緒だが、Adminierは後発でphp一枚で完結しているので、インストールがめちゃくちゃ楽。

### MySQL WorkBench 

公式のMySQLクライアント。Javaでできてるので、UIがOSの標準提供とはちょっと違う。文字が滲む。（過剰なアンチエイリアスなのかな）。レスポンスもいまいち。そしてすぐに落ちる。コンテンツを開くまでの階層が深い。と、公式な割には使いづらい場面が多い。公式がいまいちだからこそ、SequelProのようなものが登場しているとも言える。

ただし、SSHトンネルもできるので、機能としてはSequelProと同等（というかそれ以上の機能）。だから「我慢して使う」というのも一つだが、こういうUIを我慢できちゃう人は他人にもダメなUIを強いるスタンスになっちゃいそうで教育上良くない。

### chrome myadmin

Chromeアプリなので、インストール不要。
SSHトンネルで接続もできる。
（なぜか）私の環境では接続できるサーバーの数に上限ができてしまった。
エクスポート／インポート機能がない。リモートサーバーからサクッと現在のマスタをローカルマシンに持ってくるなんてことができないのが辛い。
エクセルに対するコピペができない。

### DBeaver（たぶんこれが一番）

Java製。ちょっと動作はもっさり。MySQL Workbenchほどではない。何よりも「文字がにじまない」という時点で、Java製アプリにしてはUIがしっかりしている。

機能としてはMySQL Workbenchなみに充実。SSHトンネルもできるし、データのインポート、エクスポ―トにも対応。
選択結果をコピーしてエクセルにも貼り付けれる。
SQLのコードアシストもある。
おそらくこれが一番。

Java製なので、イマドキのJava環境を入れるのがコツがいる。（JREが単体で配布されてないことや、OpenJDKを入れましょうとか、イマドキならchocoでインストールするのが楽だけど、choco自体のインストールも準備が必要だとか）。

他にも、Google BigQuery にも接続できたりといろいろ便利そう。

### Access リンクテーブル

SequelProの代替ソリューションとして一番近いのが、Accessのリンクテーブル。ただしデータベースやテーブル単位でリンク設定をいちいちしなくちゃいけない。さらにODBCドライバがイマドキはめちゃくちゃインストールが面倒。32bitと64bitをちゃんと使い分けなくちゃいけない。他人におすすめできるレベルではない。ボツ。

### HeidiSQL 

UIとしては、一通りカバーされている。ただしSQLのコード補完はない。SSHトンネルもない。手元のMySQLにつなぐだけの用途。

文字が滲む。どうも標準のUIツールキットを使ってなさそう。文字が滲んでいると、目がすごく疲れる。レンダリングという観点では、Electron製の方が良さそう。

### Sqlectron

Eelectron製で文字のレンダリングは見やすい。
SQLのコード補完はあるが、テーブル名とカラム名を全てサジェストするだけで、どのテーブルのカラム名かはわからない。（ピリオドでフィールド名一覧を出して欲しいところ）
テーブルのエクスポート機能はない。
GUI上で、並び替え、where検索はできない。（全てSQLを書く必要がある）
機能としてはchrome myadminと同等なので、chrome myadmin で十分。

### ElectroCRUD

Electron製のDBクライアント。MySQL以外もいけるみたい。
インストールしたけど、必ずデータベースを指定しないとサーバーにさえ繋いでくれない。rootでDBまたがって操作したい時（ローカルのMySQLはそういう使い方してる）には使えない。

### DbVisualizer

試してない。

### Navicat

有料？試してない。
AIカメラ M5StickV 向けアプリ Brownie

# はじめに
M5Stack社のAIカメラ M5StickV 向けアプリ [Brownie](https://github.com/ksasao/brownie/blob/master/README.ja.md) についての情報をまとめます。このページは不定期に更新されます。

現在、下記の3種類がありますが、区別したい時を除き、まとめて Brownie と呼んでいます。

- Brownie
    - 物体検出アルゴリズム Tiny YOLO v2 を利用して顔認識と各種物体認識(20種類)を行います。大きなボタンを押すとその物体の名前を読み上げます。
    -  [Brownie](https://github.com/ksasao/brownie/blob/master/README.ja.md) に説明とアプリがあります。
- Brownie 1000
    - 物体識別アルゴリズム MobileNet v1 を利用して1000種類の物体を見分けます。 大きなボタンを押すとその物体の名前を読み上げまず。
    - [ここ以下のファイルをmicroSDカードにコピーしてM5StickVに入れて実行してください](https://github.com/ksasao/brownie/tree/master/src/brownie_1000)
- Brownie Learn
    - 転移学習という手法を利用して、認識したい物体を自分で追加することができるアプリです。学習処理も M5StickV 本体内で行っています。QRコードを利用して簡単に学習しなおすことができます。
    - [ここ以下のファイルをmicroSDカードにコピーしてM5StickVに入れて実行してください](https://github.com/ksasao/brownie/tree/master/src/brownie_learn)。現在ファームウェアとして [v0.5.0](http://dl.sipeed.com/MAIX/MaixPy/release/master/maixpy_v0.5.0_0_gae433e8/maixpy_v0.5.0_0_gae433e8_m5stickv.bin) が必要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43450/15a45a46-96b4-9a5d-9613-63e4b85b1113.png)

また、Brownie Learn 向けに外部のアプリと連携するためのツール Brownie Monitor を用意しています。物体認識をすると、QRコードに書かれた文字列に紐づけられた物体の名前がシリアルポート経由で送られてきます。その文字列をトリガーにしてアプリケーションを起動することができます。Windows デスクトップアプリと Node.js (Mac, Linux, Windowsなどで動きます)があります。

- Windowsバイナリ
    - [Maker Faire Taipei 2019 Kit](https://github.com/ksasao/brownie/releases/tag/v2.0) に含まれています

- Node.js
    - [Brownie Monitor for Node.js](https://github.com/ksasao/brownie/tree/master/tool/BrownieMonitor/BrownieMonitorNodeJs) (GitHub) 

# 関連ドキュメント
- [M5StickVではじめる軽量モデルの実世界への応用 #TFUG](https://www.slideshare.net/ksasao/20190928-m5stickv-tfug) (SlideShare)
- [3000円の液晶付きAIカメラでオフライン転移学習する #M5StickV](https://qiita.com/ksasao/items/6d6bcac4c5e92fa692a2)
 (Qiita)
- [Brownie - Automate Your Home with AI](https://www.hackster.io/ksasao/brownie-automate-your-home-with-ai-886e5c) (Hackster)
GraphQLの便利なツール

GraphQLのAPIを簡単に実行するためのツールがオープンソースで開発されています。こういったツールを使うことで、自分が作ったGraphQL APIを簡単に実行し、挙動の確認を行うことができます。有名なツールとして、GraphiQLとGraphQL Playgroundがあります。

## GraphiQL
https://github.com/graphql/graphiql
GraphiQLは、Facebookが開発したブラウザ上で利用できる統合開発環境です。シンタックスハイライト、入力補完、構文エラー検知などの機能が搭載されています。[RESTの課題とGraphQL 〜GraphQLを簡単に使ってみる〜](https://qiita.com/NagaokaKenichi/items/a4991eee26e2f988c6ec)でも紹介しましたが、SWAPIのような公開APIには、GraphiQLがホスティングされていることもあります。
https://graphql.org/swapi-graphql
作ったGraphQL APIを公開する場合は、上記のようにGraphiQLのインターフェースを提供することで、利用者に簡単に試してもらうことが可能になります。

また、ホスティングしなくても、スタンドアロンでGraphQL APIを試すことも可能で以下からダウンロードできます。
https://electronjs.org/apps/graphiql

UIは以下の通りシンプルです。
※SWAPIのGraphiQLを利用します（https://graphql.org/swapi-graphql）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23101/566185c1-fb62-ef6c-6f9c-25036acbffd3.png)

試しに、以下のクエリを発行してみます。クエリを入力し再生ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23101/02952768-90ac-867e-68c8-18f1da69c559.png)
右ペインがレスポンスです。簡単に試すことが可能です。また、クエリドキュメントも右上のDocsから確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23101/732abb1c-5d59-6c8f-cbb4-9647b71894c7.png)


## GraphQL Playground
https://github.com/prisma-labs/graphql-playground
Prismaチームによって開発されたツールです。GraphiQL同様、ブラウザ上、スタンドアロン両方で使うことができます。スタンドアロン版は以下からダウンロードできます。
https://electronjs.org/apps/graphql-playground

GraphiQL同様、UIは以下の通りシンプルです。公開されているSnowtooth APIで試してみます（http://snowtooth.moonhighway.com/）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23101/182201fd-ffcd-39ca-773b-5e58ad7f8503.png)

GraphiQLとの違いは以下があります。

* HTTPヘッダーを自由に書き換えられる
* タブ機能で複数のクエリを1ウィンドウで試せる
* curlコマンドでも投げれるように、curl copy機能がある
* エディターの外観やフォントの設定が可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23101/592c096c-f9c7-3106-db35-3fbd10125d53.png)

ちなみに、curl copyは以下のようにコピーされました。

```
curl 'http://snowtooth.moonhighway.com/' -H 'Accept-Encoding: gzip, deflate, br' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Connection: keep-alive' -H 'DNT: 1' -H 'Origin: http://snowtooth.moonhighway.com' --data-binary '{"query":"# Write your query or mutation here\nquery {\n  allLifts {\n    name\n    status\n  }\n}"}' --compressed
```

以上です。

## 参考
* [初めてのGraphQL ―Webサービスを作って学ぶ新世代API](https://www.oreilly.co.jp/books/9784873118932/)