OmniAICreator/Qiita-1.07M huggingface dataset:
【Vue.js】modelプロパティでコンポーネントを疎結合する

# はじめに
社内システムのフロントエンドにVue.jsを利用しています。
コンポーネント間でデータのやり取りをpropsやemitでやっていたのですが、
あまりにもそれらの量が多くなりコンポーネントどうしが密結合してしまいました。
状態はVuexで管理するとして、
「ダイアログの開閉動作もなんとか分離できないか？:disappointed_relieved:」
ということで、modelプロパティを利用して疎結合にしました。

# やること
modelプロパティを使う場合と使わない場合の、ダイアログの開閉動作の実装の違いを見て、
同プロパティが疎結合に寄与していることを確認します。
ダイアログは、VuetifyのVDialogを利用し独自に定義したコンポーネントを使うといった想定です。
※前提知識として、Vue.jsでは親の値を子が直接変更すると、動きはするものの怒られるということを知っておいてください。

# 環境
今回実行した環境は以下です。

- Vue.js 2.6.12
- Vuetify 2.4.3

# ソースコード
#### 1. modelプロパティを使わない場合
```vue:Parent.vue
<template>
  <div>
   <v-btn depressed @click="openDialog">
      Open
    </v-btn>
   <dialog :value="value" @close="close">
  </div>
</template>
<script lang="ts">
import Vue from 'vue';
import dialog from '@/dialog';
export default Vue.extend({
  name: "Parent",
  data: {
    value: false
  },
  methods: {
    openDialog() {
      this.value = true;
    },
    close() {
      this.value = false;
    }
  }
})
</script>
```
```vue:Dialog.vue
<template>
  <div>
    <v-dialog v-model="value">
      <v-card tile>
        hoge
      </v-card>
    </v-dialog>
  </div>
</template>

<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
  name: "Dialog",
  props: {
    value: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    close() {
      this.$emit("close", false);
    }
  }
})
</script>
```
#### 2. modelプロパティを使う場合
```vue:Parent.vue
<template>
  <div>
   <v-btn depressed @click="openDialog">
      Open
    </v-btn>
   <dialog v-model="value">
  </div>
</template>
<script lang="ts">
import Vue from 'vue';
import dialog from '@/dialog';
export default Vue.extend({
  name: "Parent",
  data() {
    value: false
  },
  methods: {
    openDialog() {
      this.value= true;
    }
  }
})
</script>
```
```vue:Dialog.vue
<template>
  <div>
    <v-dialog
      :value="value"
      @input="(val) => val || close()"
    >
      <v-card tile>
        hoge
      </v-card>
    </v-dialog>
  </div>
</template>

<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
  name: "Dialog",
  model: {
    prop: "value",
    event: "change-dialog"
  },
  props: {
    value: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    close() {
      this.$emit("change-dialog", false);
    }
  }
})
</script>
```
# 何が変わったか
#### 1. modelプロパティを使わない場合
##### やっていること
1. propsでvalue変数(ダイアログの開閉状態)を渡している
1. エラーを避けるため、ダイアログを閉じる処理はParent.vueが担っている

##### 良くない点 
1. 処理がParent.vueに依存する部分があるため、コンポーネントが密結合している
1. 閉じるためにモーダル部分をクリックすると、Dialog.vueがParent.vueのvalue変数を直接書き換えるためエラーとなってしまう
1. Dialogコンポーネントを使いまわそうとすると、そのたびに親にダイアログを閉じる処理を書かないといけない

#### 2. modelプロパティを使う場合
##### やっていること
1. v-modelを経由して、ダイアログの開閉状態をDialog.vueに渡している
1. v-modelで渡した状態をmodelプロパティ(とprops)で受け取っている
1. Dialog.vueの`@input`イベントでダイアログの開閉状態を監視している

##### 良い点
1. 処理がDialog.vueで完結しているため、1に比べてコンポーネントが疎結合になっている
1. モーダル部分をクリックして閉じたとしても、エラーとならない
1. 親コンポーネントが簡素になる

# 最後に
modelプロパティを使うことでコンポーネントを疎結合にすることが出来ました。
子コンポーネントにmodelプロパティとprops両方を書かないといけず、記述量が増えるのが難点ですが
疎結合になることで使いまわすことが容易になりました。
@PreparedForTestに入るクラス、お前やったんかい（PowerMockでwhenNewを伴う場合）

PowerMockでハマったので備忘。

クラス内処理で毎回インスタンスが生成されるようなクラスをテストしたい場合、生成されるインスタンス内の処理をモック化（つまり、テスト用に理想的なIN/OUTを設定）するには、PowerMockを用いる必要があります。

この際、ソースは下記のようになります
※下記の記事のソースにコメントを追記したものです

https://qiita.com/y-imai/items/0e002e16e38ba97e11f6#Mockito%E3%81%A8PowerMock%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%99%E3%82%8B

```Java:テスト対象クラス
public class ExampleService {
    public Integer count() {
        ExampleLogic logic = new ExampleLogic();
        //テストに当たって、countExamplesの処理はどうでもいいのでモック化したい
        return logic.countExamples();
    }
}
```

```Java:テストクラス/テストメソッド
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.powermock.api.mockito.PowerMockito.whenNew;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class) 
//hiroがハマったポイント、PreparedForTest
@PrepareForTest({ ExampleService.class }) 
public class ExampleServiceTest {

    ExampleService service = new ExampleService(); 

    @Test
    public void count() throws Exception {
        ExampleLogic logic = mock(ExampleLogic.class); 
        whenNew(ExampleLogic.class).withNoArguments().thenReturn(logic); 
        when(logic.countExamples()).thenReturn(0); 

        assertThat(service.count(), equalTo(0));
    }
}
```

hiroがハマったのはPreparedForTestの中身にどのクラスを書くか、でした。



```Java:正解
//テスト対象のクラスを書くのが正解
@PrepareForTest({ ExampleService.class }) 
```

```Java:不正解
//モック化されるクラスを書くと不正解
@PrepareForTest({ ExamleLogic.class }) 
```

不正解の方を書くと、うまくモック化されず実際の処理が行われてしまいます。

今後気を付けていきます！
ViewでJavascriptとCSSを読み込み方法を知ろう

|javascript_pack_tag|
|--|
Webpackerでビルドしたスクリプトを読み込むためにはjavascript_pack_tagを使う。

【例】 ERBファイルの中で

```js
<%= javascript_pack_tag 'application' %>
```
とすると、

```js
app/javascript/packs/application.js
```

が読み込まれる。

Rails 6 でのアセット管理
-

Asset Pipeline だ。これで JavaScript, CSS, Font など全てを一元管理してくれていた。
Rails 6 で作ったアプリでは JavaScript の管理 をするために Webpacker が搭載されている。
CSS や Font などは引き続き Asset Pipeline を使い続けるのが、Rails 6 の利用想定である。

|app/assets|開発中アプリに使用するアセットを保管|
|--|--|
|lib/assets|Railsの開発チームによって作成されたライブラリ用のアセットを保管|
|vendor/assets|サードパーティ製のアセットを保管|
あなたはapp/assetsを使って、Rails開発者さんはlib/assets、その他の人はvendor/assetsを使っていると考えておいてください。

アセットの読み込み
-
```rb:layout/application.html.erb
<%# CSS の読み込み。"application" は、エントリーポイントの名前 %>
<%= stylesheet_pack_tag 'application' %>

<%# JS の読み込み。"application" は、エントリーポイントの名前 %>
<%= javascript_pack_tag 'application' %>
```

マニフェストファイル
-
Railsでは、**Sprockets**というgemを用いると、ブラウザにアセット（CSS/JavaScript）をひとつにまとめて送れます。なぜひとつにまとめるかというと、1個ずつ２ファイルで送るのは非効率だから。「どのようにひとつにまとめるのか」のまとめ方について書かれているのが**マニフェストファイル**です。

【例】CSS用のマニフェストファイル

```rb:[場所]app/assets/stylesheets/application.css
/*
* This is a manifest file that'll automatically include all the stylesheets
 * available in this directory and any sub-directories. You're free to add
* application-wide styles to this file and they'll appear at the top of the
 * compiled file, but it's generally better to create a new file per style
* scope.
*= require_self
*= require_tree .
*/
```

*= require_self　と　*= require_tree .がSprockeに利用されます。

media:'all'
-

メディアタイプを使えるようにしています 

'data-turbolinks-track'オプション
-

Railsから同梱されるようになったturbolinks gemを使用している場合、'data-turbolinks-track'オプションが利用できます。これはアセットが更新されてページに読み込まれたかどうかをturbolinksがチェックします。

Turbolinksとは
-
画面遷移を高速化させるライブラリです。「rails new」した時点から、標準で組み込まれています。「asset pipeline」というフレームワークの一部です。Turbolinksはあるページから次のページへのアセット要素のURLを追跡し、変更された場合は自動的にフルリロードをします。**これがasset pipelineの働きです。**

|2通りハッシュの書き方|{media: =>  "all", "data-turbolinks-track" => true}|
|--|--|

>参考
>https://qiita.com/takuo_maeda/items/68b9d44344e6011f9045
numpy.histogramの使い方

NumpyのHistgramの使い方メモ

# 任意のbinを指定

bins引数で任意のbinを指定することができる.

bins引数で与える数値はbinのエッジを表している。bins=[0,1,2,3]の例では、

- 0以上1未満 [0,1)
- 1以上2未満 [1,2)
- 2以上3未満 [2,3)

の3のつのbinが用意される。

下記の例では[0,1)に1つ, [1,2)に2つ, [2,3)に1つ入る.

```python
>>> np.histogram([0,1,1,2],bins=[0,1,2,3])
(array([1, 2, 1]), array([0, 1, 2, 3]))
```

binsの範囲外の値はカウントされない.

```python
>>> np.histogram([0,1,1,2,4],bins=[0,1,2,3])
(array([1, 2, 1]), array([0, 1, 2, 3]))
```

binの範囲外に落ちた値もカウントするなら、下記のようにする

```python
>>> np.histogram([-1,0,1,1,2,4],bins=[-sys.float_info.max,0,1,2,3,sys.float_info.max])
(array([1, 1, 2, 1, 1]), array([-1.79769313e+308,  0.0,  1.0,
        2.0,  3.0,  1.79769313e+308]))
```

binは単調増加であれば、等間隔である必要もない。
Javascript あれこれ

# Background
- 久しぶりにJavascriptの知識の整理を実施することになった
- 良くわかりにくくなる事項について、自分の理解の整理のために本記事を投稿する


# 1. 関数の記法

## 1-1. 通常版
- 通常版では`function`キーワードに関数名を続けて記載する

（定義）

```javascript
// 関数名: sayHello
// 引数: name
function sayHello(name) {
  return `${name}さん、こんにちは！`; //処理
}
```

（実行方法）

```javascript
console.log(sayHello('Taro'));
```


## 1-2. 無名関数
- 無名関数では関数定義を変数の値として代入して定義する
- 関数定義は呼び出し側の前に行う必要がある（いわゆる巻き上げが発生しない）
- 実行する場合は関数を代入した変数に引数をぶち込む
- 関数リテラルとも呼ばれる（リテラルとはソースコードに直接ベタ書きした文字や数字のこと）

（定義）

```javascript
// 関数を代入する変数名: myfunc
// 引数: name
const myfunc = function (name) {
  return `${name}さん、こんにちは！`; //処理
}
```


（実行方法）

```javascript
console.log(myfunc('Taro'));
```

## 1-3. アロー関数
- `function`キーワードの代わりに「=>」（矢）を使って無名関数を記述する
- アロー関数では、thisはアロー関数が宣言された場所によって決定される
- つまり定義したコンテキストでthisが固定される
- これによってvar self = this; を書かなくてよくなったりする

（定義）

```javascript
// 関数を代入する変数名: myfunc
// 引数: name
// 平たく書くと、
// 無名関数: function(引数,...){...関数の本体...}
// アロー関数: (引数,...)=>{...関数の本体...}
const myfunc = (name) => {
  return `${name}さん、こんにちは！`; //処理
}

// 関数処理が１文の場合`{}`を省略できる
const myfunc = (name) => `${name}さん、こんにちは！`;

// 引数が１つの場合、引数の`()`も省略できる
const myfunc = name => `${name}さん、こんにちは！`

// 引数が無い場合は`()`だけを記載する
const myfunc = () => "こんにちは！"
```

（実行方法）

```javascript
console.log(myfunc('Taro'));
```

## Reference
- [JavaScriptの無名関数について現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/35133)
- [async/await 入門（JavaScript）] (https://qiita.com/soarflat/items/1a9613e023200bbebcb3)
- [export defaultってなんだろう] (https://qiita.com/rena_m/items/b9e79dc88e5c5bc5b245)
- [イマドキのJavaScriptの書き方2018](https://qiita.com/shibukawa/items/19ab5c381bbb2e09d0d9)
- [【JavaScript入門】誰でも分かるPromiseの使い方とサンプル例まとめ！](https://www.sejuku.net/blog/52314)



# 2. デフォルト引数
- 関数のデフォルト引数 は、関数に値が渡されない場合や undefined が渡される場合に、デフォルト値を指定できる

(Before) 従来こうしていたものが

```javascript
function multiply(a, b) {
  b = (typeof b !== 'undefined') ?  b : 1 //bがundefinedだったら初期値として1を設定
  return a * b
}
```

(After) こう定義できる

```javascript
function multiply(a, b = 1) {
  return a * b
}
```








## Reference
- [デフォルト引数](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Default_parameters)
アセットパイプラインの仕組み（概要）


アセットパイプライ（以下の仕組み）
-

|開発（時）|Ruby on Railsのアプリケーション内で使用したいJavaScriptやCSS、画像ファイルを「開発作業がしやすいようにファイルを分割してコーディング|
|--|--|
|WEB表示（時）|最終的にWEBページ表示の際にCSS,JavaScript,Imageファイルなどを「連結・圧縮する」仕組みです。

 

・WebブラウザがWebページを表示するために必要なHTMLファイルの元ファイル（.erb）をapp/viewsディレクトリ内に配置します。

・一方、そのHTMLを装飾するためのCSSファイルや画像ファイル、JavaScriptファイルは、app/assetsディレクトリ内に配置します。

・stylesheetsディレクトリ内には、CSSファイル。imagesディレクトリには、Imageファイル。javascriptsディレクトリには、JavaScriptファイルを配置します。

記載する内容の種類ごとにディレクリやファイルを分けています。
**それは、「開発者にとって、何がどこに記載されているかをわかりやすく認識させるため」です。**

Webブラウザには、ひとつのWebページを表示するために複数のファイルを結合する機能は備わっていません。そのため、開発者が作業をしやすいようにファイルをたくさんのディレクトリに分けてしまうと、それらのディレクトリをそのままひとつのWebページとして扱うことができなくなってしまいます。

そこで、このアセットパイプラインの仕組みが考え出されました。

###アセットパイプラインは、複数のディレクトリやファイルに分かれたassetsディレクトリ内のファイルをひとつに連結・圧縮する機能です。

> Ruby開発・事例サイト
提供：Ruby開発に強いトランスネット
>https://www.transnet.ne.jp/2016/02/28/rails%E5%88%9D%E5%AD%A6%E8%80%85%E3%81%8C%E3%81%A4%E3%81%BE%E3%81%9A%E3%81%8Dcolnr%E3%80%8C%E3%82%A2%E3%82%BB%E3%83%83%E3%83%88%E3%83%91%E3%82%A4%E3%83%97%E3%83%A9%E3%82%A4%E3%83%B3/
Ubuntu20.04でChromeから音が出なくなった際の対策



# 環境
OS：Ubuntu 20.04

# 事の発端
ある日Chromeでアマプラミュージックを聞こうとしたら音が出ない
Chromeのアップデートなどブラウザ起因で考えられることを試すが直らず
しかし「設定」 > 「サウンド」の警告音はちゃんと鳴るという状況

もしやワイヤレスヘッドセット導入時に設定をいじくり回したことが影響している？

# PulseAudioの設定ファイルを削除
PulseAudioについては下記の参考資料へ
自分でいじったのに全く把握していないPulseAudioの設定ファイルを消し飛ばして解決を図る

pulseaudioサーバを停止

```
pulseaudio --kill
```
ホームディレクトリ配下の謎設定ファイルを消去
※ 色々設定している場合は，バックアップ取るなりちゃんとこの辺を見る
システム全体の設定ファイルは `/etc/pulse` に存在

```
rm -rf ~/.config/pulse
```

pulseaudioサーバを再開

```
pulseaudio --start
```

無事に音が出るようになった

# おわりに
よくわかっていない状態でコマンドを叩いて変な設定をしてはいけない
それを中途半端に残しておくのもダメ
後では絶対にやらないので，やるなら最後までやり切ること


# 参考資料

https://wiki.archlinux.jp/index.php/PulseAudio

https://endy-tech.hatenablog.jp/entry/linux_sound_troubleshooting

https://qiita.com/propella/items/4699eda71cd742cba8d3

https://askubuntu.com/questions/943509/sound-card-gone-from-pactl
Herokuへのデプロイ方法

Herokuへのデプロイ方法を備忘録も兼ねて記述します。
なおこれはRails 6.0.0で作成したアプリをHeroku-18デプロイする方法になります。

まず Heroku CLIをインストール

```:ターミナル
% brew tap heroku/brew && brew install heroku
```
次に下記のコマンドを入力
バージョンが出れば成功

```:ターミナル
% heroku --version

heroku/7.40.0 darwin-x64 node-v12.16.2
```
Herokuにログイン

```:ターミナル
# Herokuへログインするためのコマンド
% heroku login --interactive
  => Enter your Heroku credentials.
# メールアドレスを入力し、エンターキーを押す
  => Email:
# パスワードを入力して、エンターキーを押す
  => Password:
```
緑色でメールアドレスが表示されれば成功です。

Heroku上にアプリケーションを作成

```:ターミナル
% cd ~/アプリのあるディレクトリ
% pwd
#カレントディレクトリを確認
% heroku create アプリケーション名
```
下記のコマンドを入力し設定が正しくできたか確認

```:ターミナル
% git config --list | grep heroku
```

ClearDBアドオンを追加
ClearDBアドオンとは、MySQLを使うためのツールでHerokuでMySQLを使用できるようになります

```:ターミナル
% heroku addons:add cleardb
```
データベースの変更をする
Ruby on Railsを使う場合は、MySQLに対応するGemについて考慮する必要があり、そちらの設定を変更する必要があるとのことです


```:ターミナル
% heroku_cleardb=`heroku config:get CLEARDB_DATABASE_URL`
```
```:ターミナル
% heroku config:set DATABASE_URL=mysql2${heroku_cleardb:5}
# 以下、コマンドの実行結果
Setting DATABASE_URL and restarting ⬢ ○○○○○... done, v◯◯
DATABASE_URL: mysql2://000000000000:0aa0000@us-cdbr-east-02.cleardb.com/heroku_aaa00000000?reconnect=true
```
次にHeroku上で非公開の値(サーバーのアクセスキーやAPIキーなど)を管理するために暗号化をする必要があります。
credentials.yml.encファイルという外部に漏らしたくない情報を扱う際に用いるファイルがあり、master.keyファイルでその暗号文を復元します。

まずcredentials.yml.encの中身を確認

```:ターミナル
% EDITOR="vi" bin/rails credentials:edit
```
確認後は、「escキー」→「:」→「q」と入力し、「enterキー」を押して閉じる
Heroku上にmaster.keyを設置する
Heroku上で環境変数を設定

```:ターミナル
% heroku config:set RAILS_MASTER_KEY=`cat config/master.key`
```
環境変数を確認
RAILS_MASTER_KEYという変数名で値が設定されていれば成功

```:ターミナル
% heroku config
```
Herokuで利用するStackを指定
Stackとは、Herokuにおけるアプリケーションの動作環境のことでStackはデプロイされたアプリケーションを読み取り正常に稼働させるために用意されています。
下記のコマンドを実行。

```:ターミナル
% heroku stack:set heroku-18 -a アプリケーション名
```

git push heroku masterを実行

```:ターミナル
% git push heroku master
```
Heroku上でマイグレーションを実行

```:ターミナル
% heroku run rails db:migrate
```
heroku apps:infoで公開を確認

```:ターミナル
% heroku apps:info

===○○○○○○
Addons:         cleardb:ignite
Auto Cert Mgmt: false
Dynos:          web: 1
Git URL:        https://git.heroku.com/○○○○○○.git
Owner:          sample@sample.com
Region:         us
Repo Size:      ○○○ KB
Slug Size:      ○○○ MB
Stack:          heroku-18
Web URL:        https:/○○○○○○.herokuapp.com/
```

あとはURLヘアクスして表示されれば成功
複数のセレクトボックスをJavaScriptで連動させる方法

まずは以下画像の赤枠部分を見ていただきたいのですが、２つのセレクトボックスを連動させて、左のセレクトボックス（画像では「食材群」）で値を選ぶと、右のセレクトボックス（同「食材」）の選択肢が動的に変更されるような方法を調べました。
![画像1 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569762/3a4bf730-9d69-614f-5672-fec8d72318bb.png)
<br>

例えば、食材群で「野菜類」を選ぶと、食材の選択肢には野菜の仲間が表示されます。
![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569762/3860d1e8-4511-fc7f-3c4b-0aef1ab61253.png)
<br>

また、食材群で「魚介類」を選ぶと、食材の選択肢には魚介の仲間が表示されます。
![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569762/3bc24aa6-4e14-c473-6e9d-2d4de3d62126.png)
<br>

この機能は以下のコードで実現できます。

```JavaScript:select_change.js
// 食材群選択
$(function(){
    var $children_default = $('.children');
    var original = $children_default.html();

    $('.parent').change(function() {
        var $children = $("#children");
        var val1 = $(this).val();
        $children.html(original).find('option').each(function() {
            var val2 = $(this).data('val');
            if (val1 != val2) {
                $(this).remove();
            }
        });
        if ($(this).val() === '') {
            $children.attr('disabled', 'disabled');
        } else {
            $children.removeAttr('disabled');
        }
    });
});
```

```HTML:food_register.html
<form method="post">
    食材群：
    <select class="parent" id="parent" name="parent" required>
        <option value="" selected="selected" disabled>
            食材群を選択して下さい
        <option value="vegetables">野菜</option>
        <option value="seafood">魚介類</option>
    </select>
        食材：
    <select class="children" id="children" name="children" disabled>
        <option value="0" selected="selected" disabled>
            食材群を選択して下さい
        </option>
        <option value="1" data-val="vegetables">キャベツ</option>
        <option value="2" data-val="vegetables">白菜</option>
        <option value="3" data-val="vegetables">レタス</option>
        <option value="4" data-val="seafood">アジ</option>
        <option value="5" data-val="seafood">タイ</option>
        <option value="6" data-val="seafood">マグロ</option>
    </select>
</form>
```
<br>

ちなみに、画像は食品ごとの食材(栄養価)を登録するアプリケーションの一部で、カレーライスの1人分の食材は以下のような分量となります。
![画像5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569762/2231deca-63c2-ce3a-9e65-604972238cda.png)
Gmail APIでメールを検索する

# 目的
PostmanからGmail APIをつかってメールを検索し、特定のメールの詳細を表示したい

# さてやるか、その前に
PostmanでGmail APIどうやって使うの、はこちらの記事を参照されたし：[PostmanでGmailを取得する](https://qiita.com/hideshis/items/700b62328bcf14cc15fd)

# さてやるか
## 今回使うGoogle API
今回使うのは、以下のメソッド：

* [users.messages.list](https://developers.google.com/gmail/api/reference/rest/v1/users.messages/list)
* [users.messages.get](https://developers.google.com/gmail/api/reference/rest/v1/users.messages/get)

手順としては、users.messages.listで検索し、ヒットしたメールのIDを使ってusers.messages.getで詳細を表示する感じ。

## 検索ってどうするの
users.messages.listには`q`というパラメータが定義されていて、ここに検索条件をぶっこみます。
説明文コピペしとくか

```text:document.txt
Only return messages matching the specified query. 
Supports the same query format as the Gmail search box. 
For example, "from:someuser@example.com rfc822msgid:<somemsgid@example.com> is:unread". 
Parameter cannot be used when accessing the api using the gmail.metadata scope.
```

例えば、Findyから送信されたメッセージの一覧を取得したいときには
`from:support@findy-code.io `
とパラメータを設定する。
また、そのなかから企業が自分に興味を持っているメールだけを取得したいときには
`from:support@findy-code.io subject:さんに興味を持っています【Findy】`
とパラメータを設定する。

![mail_search1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77762/e565b981-d629-234d-0ab1-3deba6551a0b.jpeg)

## オマケ：取得したメール一覧のそれぞれに対して、メール詳細を取得する
前回同様、リポジトリにcollectionファイルを配置した（[リポジトリ](https://github.com/hideshis/gmail_api_sample)）。
![mail_search2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77762/90252291-f28c-2bce-2792-2d89084eb957.jpeg)
[MySQL]カラムのデータ型を変更

データ型を変更する方法をよく忘れてしまうので、メモとして残します。

**テストテーブル**

```
mysql> DESC employee;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| code  | varchar(45) | NO   | UNI | NULL    |                |
| name  | varchar(45) | YES  |     | NULL    |                |
| age   | int(11)     | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
```

**codeカラムのデータ型をintに変更**

```
mysql> ALTER TABLE employee MODIFY code int NOT NULL;

mysql> ALTER TABLE employee MODIFY code int; ## NOT NULL制約を外したりすることも可能
```
初心者のためのRuby on Rails環境構築


# Ruby on Rails 環境構築


### この記事の対象者
- ローカル環境でRailsで環境構築を初めてする人
- mac 使っている人
- Railsチュートリアルや入門レベルで環境構築したことがある人


### 環境
- mac Big Sur Version 11.3
- Ruby 2.5.1
- Rails 5.2.5
- ターミナル bash
* zshになっている場合は(%で始まる)ターミナル設定からbash($で始まる)に切り替えてください
* ここからターミナルで行う作業は最初のほうはホームディレクトリで進めてください。

https://qiita.com/___xxx_/items/c9a30e78196998f4160c


### 参考書籍
- 現場で使える Ruby on Rails5 速習実践ガイド(5.2対応)

## Command Line Tools for Xcodeをインストール
```$ xcode-select --install```
- これはHomebrewを使うためにインストールします。かなり重たいのでストレージを気にしてください。

https://aadojo.alterbooth.com/entry/2020/12/17/114107

インストールできたら

```$ xcodebuild -version```

で確認。
ここで僕はエラーが起きたのですが
どうやらXcodeのインストールが必要だったみたいなのでお忘れなく。

## Homebrewのインストール
### Homebrewとは
https://qiita.com/omega999/items/6f65217b81ad3fffe7e6

ではHomebrewをインストールしていきます

https://brew.sh/index_ja のページに行って/bin/bash....という文字が並んでいるところがあるのでこれをコピペしてターミナルで実行してください。

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

インストールできたら

```$ brew doctor```

でインストールが正常にできているか確認。

Your system is ready to brew.みたいなことがレスポンスとして返ってきたら問題なしです。


## rbenvをインストール
```$ brew install rbenv```

## rbenvコマンドを利用できるようにする

- パス設定と初期化処理を.bash_profileに追加。
```$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"'>> ~/.bash_profile```
```$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile```

- これをやる理由
https://qiita.com/1000ch/items/a61e65fe82d8bdea840e

## Rubyのインストール
```$ rbenv install 2.5.1```

- インストールが終わったら、システム全体で使用するRubyのバージョンをrbenvに変更する。

```$ rbenv global 2.5.1```

- 最後に正しくrbenvでインストールしたバージョンのRubyが利用できるか確認する。

```$ ruby -v ```
```$ which ruby```

ここでうまく行かなかったので、以下の記事を参考にしたら解決できました！

https://qiita.com/opiyo_taku/items/3312a75d5916f6cd32b1

## Rubyのパッケージ管理ツール「RubyGems」をアップデート
- Ruby本体だけでも動作するが、公開されているライブラリを使うことでより、生産的にプログラムを書いていくことができる。
最新版のシステムにアップデートしておきます

```$ gem update --system``` 


## Bundlerのインストール
- Bundlerとはgem（ライブラリ）を束ねてどのgemのどのバージョンが必要なのか明示してくれる仕組み。

```$ gem install bundler```

## Railsのインストール
```$ gem install rails -v 5.2.5```

## Node.jsのインストール
- WebアプリケーションのフロントエンドにJavaScriptを使う場合、効率よく配信するためにJavaScriptを圧縮するのが一般的。
Railsにもその機能は備わっているが、JavaScriptランタイムが必要なのでNode.jsをインストールする。

```$ brew install node```

## データベースのインストールとセットアップ
- postgresqlのインストール

```$ brew install postgresql```

- 正しくインストールされているか確認

```$ postgres -V```(Vは大文字なので注意！)

- PostgreSQLを起動する

```$ brew services start postgresql```

- PostgreSQLサーバを立ち上げたらコンソールに入って動作確認

```$ psql postgres```

control + Dで脱出できます

- PostgreSQLを停止する

```$ brew services stop postgresql```


## Gemfile編集
https://bamboo-note.tokyo/Ruby/rails-new-error-messages/
この記事をみてGemfileを編集してください

## アプリケーションを新規作成

- rails newでアプリの雛形を作成。データベースをpostgresqlに指定

```$ rails new アプリ名 -d postgresql```

これでアプリフォルダが自動生成されるので、アプリフォルダに移動

```$ cd アプリ名```

## データベース作成

- PostgreSQLを起動した状態でデータベース作成コマンドを実行

```$ bin/rails db:create```

railsコマンドではなく、bin/railsにしている理由は、アプリのルートディレクトリ直下のbinディレクトリにある
railsというスクリプトを呼び出している。このスクリプトを使うと「bundle exec rails」として実行した時と同様に
Gemfile通りのgemを使える環境上でコマンドを実行できるようになります。

## サーバ立ち上げ

```$ bin/rails s```


ここからアプリの開発を進めてください！
おつかれさまでした！
Windowsショートカット「Alt+Space」でできること

Y子です。
今日は、Windowsのショートカットのうち、「Alt+Space」の便利さを、皆さんと共有しておきたいと思います。
_【[確認環境：Windows 10 Home (Bld. 19042.928)](https://qiita.com/koiwaiwaiko/items/ef2d457ae1e1a7c8b698 "Windows10のバージョンを確認・表記する")】_

# 概要
何かウィンドウを選択した状態で、`Alt`キーを押しながら`Space`キーを押すと、ウィンドウの左上に次のようなメニューが表示されます。
このメニューの意味と使い方について、考えます。
![Alt+Space.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1265690/12f1108e-2597-2001-5d9d-221de2966dac.png)

## (1) 移動（Alt+Space → M）
`Alt + Space`を押してメニューを表示させた後、`m`キーを押すと、マウスカーソルがウィンドウ上部のタイトルバー中心に移動します。
この状態で、（マウスではなく）キーボードの矢印キー（↑↓←→）を操作すると、矢印の方向にウィンドウを動かすことができます。
任意の場所で`Enter`を押すと位置決定、または`Esc`を押すと移動前の場所に戻ります。

つまり、__キーボードを使ってウィンドウを動かす__ことができる、ということです。

以下のような場合に、この「移動」メニューは重宝します。

* マウスが壊れて使えない
* 何かの拍子にウィンドウ全体が画面外に出てしまい、マウスでドラッグできないため、なんとかして画面内に移動させたい
* 使い慣れないPC・使い慣れないポインティングデバイスで、キーボードの方が操作しやすい
* ウィンドウを細かく移動させる必要があり、マウスでは細かい操作が難しい

時には、マウスでのウィンドウ移動ができない設定になっているソフトウェアでも、この技でウィンドウ移動できることもあり、裏技や保守用として使えたりもします。

## (2) サイズ変更（Alt+Space → S）
`Alt + Space`を押してメニューを表示させた後、`s`キーを押すと、マウスカーソルがウィンドウの中心に移動します。
この状態で、（マウスではなく）キーボードの矢印キー（↑↓←→）を操作すると、矢印の方向のウィンドウ枠を選択した状態になるので、さらに矢印キーでサイズを変更します。
任意の場所で`Enter`を押すとサイズ決定、または`Esc`を押すと変更前のサイズに戻ります。

つまり、__キーボードを使ってウィンドウサイズを変える__ことができる、ということです。

このメニューが活躍するのは、「(1) 移動」と同じような場合です。
トラックボールしかないキーボードは、使い慣れないと「ウィンドウの右端をつまんでリサイズ」のような繊細な操作が難しいものですが、そういう時にこの技を知っていると便利です。

## (3) 最小化（Alt+Space → N）
`Alt + Space`を押してメニューを表示させた後、`n`キーを押すと、ウィンドウが最小化します。
最近のOSでは、`Win + ↓`でも同じことができるので、どちらかを知っていればよいでしょう。

## (4) 最大化（Alt+Space → X）
`Alt + Space`を押してメニューを表示させた後、`x`キーを押すと、ウィンドウが最大化します。
最近のOSでは、`Win + ↑`でも同じことができるので、どちらかを知っていればよいでしょう。

## (5) 元のサイズに戻す（Alt+Space → R）
(4)で最大化したウィンドウを、元のサイズに戻します。
`Alt + Space`を押してメニューを表示させた後、`r`キーを押すか、そのまま`Exter`を押すと、元のウィンドウサイズに戻ります。
最近のOSでは、`Win + ↓`でも同じことができるので、どちらかを知っていればよいでしょう。

# おわりに
ショートカットは、「マウス操作でも可能な操作が、ショートカットを知っていると大幅に時短できる」というものが多そうですが、この「Alt+Space」は「マウスが使えないときに何とかする」ような場合に重宝します。
使い慣れてくると、マウスに手を伸ばさずにちょっと楽する、のような用途にも便利です。

Windowsを使う限り、地味だが知っていて損はないショートカットの筆頭とすら思います。
特に「移動」と「画面サイズ変更」は、ぜひご活用ください。


ではー。
Kicadでシンボルの参照エラーを起こした

<h2>Macのインストールの際に失敗した</h2>
MacでKicadをインストールしようとした際にApplicationsには正常に
コピーできたのだがApplication Supportには正常にコピーできなかった。
![スクリーンショット 2021-05-01 23.13.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/e1f25925-f73e-7519-65d9-6ee436e9ad0f.png)

まあいいやと思ってそのままKicadを起動したらシンボルが正常に読み込まれていない。。。

色々調べてみるときちんとApplication SupportをコピーしてからKicadを
起動しないとシンボルの参照エラーが起きるようだ。

なぜだか以下の画面ではコピーできなかったのでFinderを使用し
KicadのライブラリーをApplication Supportに手動コピー
その後隠しフォルダになっている（これを探すのに時間かかった・・・）
Users＞＊＊＊＞Library＞Preferences＞Kicad＞sym-lib-tableを
手動で削除してKicadを再起動。

シンボル管理のフォームを開くと参照先を聞かれるので
既存を選択。
これで正常にシンボルが参照されるようになった。
sshリモートログイン時にエラー"WARNING: UNPROTECTED PRIVATE KEY FILE!"

sshリモートログイン時にエラー`WARNING: UNPROTECTED PRIVATE KEY FILE!"`

```
$ ssh -i ~/.ssh/privatekey seigot@xxx.xxx.xxx.xxx
The authenticity of host 'xxx.xxx.xxx.xxx' can't be established.
ECDSA key fingerprint is SHA256:O5Sf+YaiANOeAAkpABSNJj8r5Fk1vN4je3q2dLYJuVI.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'xxx.xxx.xxx.xxx' (ECDSA) to the list of known hosts.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/Users/user/.ssh/privatekey' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/Users/user/.ssh/privatekey": bad permissions
```

permissionを更新して解決

```
chmod 600 ~/.ssh/privatekey
```
Vue.js3とMaterializeでモダンな掲示板を作った話

# 作ったやつ
https://modern-board-vm.web.app

VM＝VueMaterialize

# はじめに
<!-- 発端や概要を記載 -->
かっちょいいデザインのウェブサイトを作りたかった

仕事で使っているのは、みんな大好きBootStrap
でもやっぱり、ダサいなと（カスタムする力がないからかもしれないけど）

手軽にかっちょいいデザインに出来ないかなと思って調べてみた
すると、マテリアルデザインというものを発見。
Googleが提唱した！Googleが提唱した！って色んな所に書いてあるので調べてみてください

それで、Vueで出来ないかなと思って調べてみました

# Vue3でマテリアルデザイン
Vue.jsで一番人気のマテリアルデザインフレームワークはVuetifyらしい
ただ、これがVue3に対応しておらず（2021/3Qに対応予定）
フレームワークに密結合してしまっているのも使いたくないなと思いました

そこで、マテリアルデザイン単体のフレームワークを調べてみました

###[google material design](https://material.io/design)
Googleが提唱しているって言うんで、さぞかし使いやすいんだろうなと思って
サンプルコードを覗いてみましたが、ボタンを作るだけで6行くらい書かないと実装できず、これはないなと思いました

###[Materialize](https://materializecss.com/)
これが使いやすそうだった、なんか有名らしいし
class名でコンポーネントを紐付けるというのもBootStrapみたいで良いなと思ったのでこれに決定


# 実装
1.Materializeをインストール

```terminal
npm install materialize-css@next
```


2.main.ts(js)でCSSをImport

```typescript.main.ts
import 'materialize-css/dist/css/materialize.min.css'
```

これで、基本的なCSSは有効になります

ただ、マテリアルデザインのボタンをタップしたときの波紋やら、ハンバーガーメニューを開いたりとか(javascriptを使う)動的な動作が有効になっていない状態です

3.javascrip有効化
公式にInitializeする必要があると書いてあるので、します
共通コンポーネントのApp.Vueでやります

```vue.App.vue
import M from "materialize-css";
export default defineComponent({
  name: "App",
  mounted() {
    M.AutoInit();//MaterializeのInitialize
  }
});
```
ここまで来ると、Materializeの機能が全部使えるようになっています

4.内部実装
HostingはFirebaseDBはRealTimeDatabseを使いました


# 完成！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/911989/966d2b83-ef2a-80e2-cc55-845a9dfcdad7.png)
さすがマテリアルデザイン。
フォームをクリックしたとき、ボタンを押したとき、エフェクトが気持ちいい！



# 参考文献
- [Proper MaterializeCSS initialization in VueJS Project](https://stackoverflow.com/questions/51106757/proper-materializecss-initialization-in-vuejs-project)
- [Materialize](https://materializecss.com/)
GASの権限エラー（UrlFetchApp.fetch など）

GASの開発の中で引っかかってしまった、権限系のエラーのについてまとめました。
基本的にはappscript.jsonに決められた文字列を追加するだけです。

# appscript.jsonの表示

まずは非表示になっているappscript.jsonを表示させます。
スクリプトエディタの設定にてチェックを入れます。
![script.google.com_home_projects_1GrBZtq5-qsA56ytK8mU1CdhQ1Iiw8HTQlv5tSHrV0AXHnzAUAzi_yfbT_executions (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1115033/95c30da7-fef1-abeb-8960-c58c7428c935.png)


# UrlFetchApp.fetch
SlackのAPIなどを使用する際に、UrlFetchApp.fetchを使うと下記のようなエラーが発生します。
![script.google.com_home_projects_1GrBZtq5-qsA56ytK8mU1CdhQ1Iiw8HTQlv5tSHrV0AXHnzAUAzi_yfbT_executions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1115033/53de3eb5-b73a-4fc2-d9b6-7b6a3854d186.png)

先ほどのjsonに以下を追記します。

```
"oauthScopes" : [https://www.googleapis.com/auth/script.external_request]
```

![script.google.com_home_projects_1GrBZtq5-qsA56ytK8mU1CdhQ1Iiw8HTQlv5tSHrV0AXHnzAUAzi_yfbT_executions (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1115033/d4ea4da1-2006-b017-257b-c890778ff7f8.png)

# SpreadsheetApp.openById
IDを使用してスプレッドシートを取得しようとした際に出たエラーです。
![script.google.com_home_projects_1GrBZtq5-qsA56ytK8mU1CdhQ1Iiw8HTQlv5tSHrV0AXHnzAUAzi_yfbT_executions (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1115033/d8b7fb47-3abc-3d01-0ef6-6f7a2c570e10.png)


同じように下記を追加します。

```
"oauthScopes" : [https://www.googleapis.com/auth/script.external_request]
```
![script.google.com_home_projects_1GrBZtq5-qsA56ytK8mU1CdhQ1Iiw8HTQlv5tSHrV0AXHnzAUAzi_yfbT_edit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1115033/43d99fba-18f1-1ef0-b3fd-8d529dd1e215.png)
HTTPステータスコード　代表的なエラーコード（メモ）

##400番台はクライアント側のエラー
- 400（Bad Request）: urlに間違いがある場合に返される。
- 401（Unauthorized）: パスワードなどに誤りがあり、認証に失敗したときなどに返される。
- 403（Forbidden）: アクセスの権限を認可してないときに返される。
- 404（Not Found）: アクセスしたページが存在しないときに返される。

##500番台はサーバー側のエラー
- 500（Internal Server Error）: サーバーに何らかの問題が発生した場合に返される。
- 503（Service Unavailable）: 過負荷やメンテナンスなど、何らかの理由で一時的にアクセスできない場合になどに返される。
Fortranのallocatableがわかりにくいと言われたので対応してみました。

## 学生さんに、「FortranのAllocatableってよくわからない」と言われた

ので、Allocatableを書かずに行列計算できるようにしてみました。
また始めたばかりですのでおいおい追記します。

ソースコードは
https://github.com/kazulagi/plantFEM.git

ここの、```src/ArrayClass/ArrayClass.f90```　にあります。

## 例

```Fortran
program main
    use ArrayClass
    implicit none

    type(Array_) :: A, B, C, I

    print *, " "

    ! create new matrices
    call A%random(3,3) ! random matrix
    call B%zeros(3,3)  ! zero matrix
    call I%unit(3,3)   ! unit matrix

    C = A * B ! A_ij B_jk

    C = A + B ! A_ij + B_ij

    call A%print()
    call B%print()
    call C%print()
    call I%print()

    print *, dot(C, C)

end program

```
簡単な行列を作り、行列積、行列和を計算します。
手抜き実装なのですべてreal(real64)型です。

結果はこちらです。

```shell
  
  0.10888631199620769       0.37555478464439451       0.29852568070134511     
  0.47234444240835993       0.90576310861565290       0.37337424467292313     
  0.37658869302848197       0.43165157640659590       0.99078645087898243     
  
 size :: 3 x 3
  
   0.0000000000000000        0.0000000000000000        0.0000000000000000     
   0.0000000000000000        0.0000000000000000        0.0000000000000000     
   0.0000000000000000        0.0000000000000000        0.0000000000000000     
  
 size :: 3 x 3
  
  0.10888631199620769       0.37555478464439451       0.29852568070134511     
  0.47234444240835993       0.90576310861565290       0.37337424467292313     
  0.37658869302848197       0.43165157640659590       0.99078645087898243     
  
 size :: 3 x 3
  
   1.0000000000000000        0.0000000000000000        0.0000000000000000     
   0.0000000000000000        1.0000000000000000        0.0000000000000000     
   0.0000000000000000        0.0000000000000000        1.0000000000000000     
  
   2.7347395334124354     
```

暇なときに拡充していきます。
自動車の故障診断に関連するプログラマーになりたての方が参照するとよさそうな情報

自動車の故障診断に関連するプログラマーになりたての方が参照するとよさそうな情報をまとめておく。
無料で参照できる日本語の情報のみを記載する。
随時追加予定。

# はじめての診断
Vectorのサイト

https://www.vector.com/jp/ja/know-how/beginners/beginners-diag-jp/

#Ｊ―ＯＢＤ２（自動車の排ガスの故障診断装置）を活用した点検整備情報の取扱指針を策定し、排ガス機能の故障に対処する点検整備情報等の提供が始まります。
国土交通省のサイト

https://www.mlit.go.jp/report/press/jidosha09_hh_000041.html

# 車載式故障診断装置を活用した自動車検査手法のあり方検討会
国土交通省のサイト

https://www.mlit.go.jp/jidosha/OBD_Inspection_System.html

# 自動車整備技術の高度化検討会
国土交通省のサイト

https://www.mlit.go.jp/jidosha/jidosha_tk9_000023.html

# 自動車の標準化2020
公益社団法人自動車技術会で作成された資料

https://www.jsae.or.jp/08std/docu/tc22_2020_JP.pdf

# 技術解説ー排出ガス低減技術の車上診断（OBD）
公益財団法人日本自動車輸送技術協会（JATA）のサイト

http://www.ataj.or.jp/technology/obd_regulation.html

# 2011 年度自動車の情報セキュリティ動向に関する調査 付録編
独立行政法人情報処理推進機構（IPA）で作成された資料

https://www.ipa.go.jp/files/000014165.pdf

# クルマの自己診断機能「OBD2」の用途は“診断”だけじゃない
MONOistの記事。カーライフプロデューサー　テルさんが執筆。

https://monoist.atmarkit.co.jp/mn/articles/1511/11/news004.html

#AUTOSARを使いこなす
MONOistの「AUTOSARを使いこなす」の連載記事一覧。櫻井剛さんが執筆。

https://monoist.atmarkit.co.jp/mn/series/9343/

# 車両診断通信【バックナンバー】
KEIさんのサイト。

https://www.simulationroom999.com/blog/diagnostic-communication-backnumber/

# 自動車修理事例

https://syuuri2012.web.fc2.com/


# Qiita（タグ"OBD2"）
QiitaのOBD2に関する投稿

https://qiita.com/tags/obd2

# iOBD2
スマホアプリのiOBD2。
デモモードがあるため、診断ツールの操作感や表示イメージを知ることができる。

https://apps.apple.com/jp/app/iobd2/id528881858

# 書籍「自動車工学」
無料ではないが、以下の書籍も参考になる。

* 自動車工学　8月号臨時増刊 (知らなければ損をするOBDⅡの全て　オンボード・ダイアグノーシス, Vol.58 No.10)
* 自動車工学増刊 「OBD2」の全て PART2 実践編 2012年 01月号 [雑誌]
* 自動車工学増刊　知って得するスキャンツールの活用法　２０１４年　０１月号

#参考記事
https://qiita.com/kaizen_nagoya/items/0c6b8373f93ce52def33
強化学習で上昇気流を捉える２

# 背景
[前回](https://qiita.com/goichiya/items/f00141fe8a2e2aff71bc)の続き。今回の結果に納得が行かない、、と一見思ったものの、データを個別に見て表現方法の検討が必要と思った、、
# 前提
[前回の設定](https://qiita.com/goichiya/items/f00141fe8a2e2aff71bc#%E5%89%8D%E6%8F%90)にちょっと条件を追加
6. ~~最善のポリシーを決める際に、進行方向を勘案せずに集計~~
(進行方向を勘案して表現しないと解釈しずらかった）

# ポリシー反復法？
動的計画法で各セルの状態価値関数が求めた（つもり）
各セルで次の行動を決めるときに、どの方向が一番勝ちが高くなるか？を求めるのがポリシー反復法という理解で良い、、のか？
今の設定だと以下のような感じで環境を表現している

```
((x, y, 進行方向), 次のアクション)
```

進行方向を勘案してベストの次のアクションを求めるのが良いとは思うものの、表現が難しそうなのと、とりあえず結果を見てみたいので進行方向を考えずにベストの次のアクションを求めるようにした

```python:policy_update
def policy_update(air_space,gamma=0.99):
    update=False
    for s in air_space.states:
        q_max = -10**10
        a_best = None
        for a in air_space.actions:
            # いったん進行方向は考えずに処理を進める
            results = air_space.move(s,a)
            # print(results)
            q = 0

            # 確率により次の状態が変化することはないのでp=1で計算
            r=results[0]
            s_new=results[1]
            p=1
            q += p * (r + gamma * air_space.value[s_new])
            if q > q_max:
                q_max = q
                a_best = a
        if air_space.policy[(s,a_best)]!=1:
                update=True
        for a in air_space.actions:
            air_space.policy[(s,a)] = 0
        air_space.policy[(s,a_best)] = 1
    print('a_best : ',a_best)
    return update
```
表現のためにｘ，ｙ単位でベストの次のアクションを求める(もっと要領の良い方法があるはず,,)

```python:集計
pre_result = np.zeros([air_space.size,air_space.size,6])
result=np.zeros([air_space.size,air_space.size])
for  state_policy in air_space.policy:
    pre_result[state_policy[0][0]][state_policy[0][1]][state_policy[1]]+=air_space.policy[(state_policy[0],state_policy[1])]
for x in range(9):
    for y in range(9):
        result[x][y] = max(pre_result[x][y])-1
```
# 結果
でた！が、直感と全く一致しない、、ほぼ全てのセルで南東に進むのがベストのアクションになっている、、なぜだ、、
![202105013352580904.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328600/01307858-45da-e1d0-5bc8-8c016e48cb6d.png)

個別のデータを見てみる

一番左下のセルで進行方向が北東のとき、ベストなアクションは北東

```
status: (-4,-4,0)
action:value
(0 : 1), 1 : 0, 2 : 0, 3 : 0, 4 : 0, 5 : 0
```
一番右上のセルで進行方向が南東のとき、ベストのアクションは南西

```
status: (4,4,2)
0 : 0, 1 : 0, 2 : 0, (3 : 1), 4 : 0, 5 : 0
```
個別に見ると直感と一致する。
進行方向ごとにベストのアクションを表示してみると概ね直観にあっている
![tile.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328600/c6e4dc4c-c643-e75c-48be-5060b4d16c1c.jpeg)



# このあと
[前回](https://qiita.com/goichiya/items/f00141fe8a2e2aff71bc#%E3%81%93%E3%81%AE%E3%81%82%E3%81%A8)の物に足したり引いたり
- ~~なぜこうなったのかもう少し考える、、(新)~~
- ~~進行方向を考慮した表現もなんとかしたい(新)~~
- ~~できればベストの方向を表示させたい~~
- もっと強化学習っぽいアルゴリズムを試してみる(新規)
- サーマルエリアに4回以上滞空出来たらゴールとしたい（サーマルエリアを突っ切って出てしまわないように
- いつの日か実際の距離感に合わせてみたい
- そしてさらにいつの日か携帯デバイスとして飛びながらベストな方向を教えてくれるようにしたい


# 参考
引き続き同じ書籍をもとに色々試行錯誤
[ITエンジニアのための強化学習理論入門](https://amzn.to/3fXoAAh)
理論もコードも丁寧に解説されていて素敵
Dockerコンテナ間でssh接続をする

# Dockerコンテナ間でssh接続をする
ssh学習用に、ssh接続できるようなコンテナ2つを立てた。
その備忘録。

※ほぼほぼこちらを参考にさせていただいた。
https://qiita.com/3104k/items/16102a64fb1bae6665af

## コンテナ2つを起動

- Dockerfile。

```
FROM centos:7

# yum update
RUN yum -y update && yum clean all

# ssh install
RUN yum install -y openssh-server openssh-clients

CMD ["/usr/sbin/init"]

RUN mkdir  ~/.ssh && \
    touch  ~/.ssh/authorized_keys && \
    chmod 600  ~/.ssh/authorized_keys
```

- Dockerイメージ生成

```
$ docker build -t fukafukafukka/centos_for_ssh_lesson .
```

- Dockerコンテナ起動


```
$ docker run --privileged -d -v `pwd`:`pwd` -it --rm --name master -p 8080:80 -p 2222:22 fukafukafukka/centos_for_ssh_lesson

$ docker run --privileged -d -v `pwd`:`pwd` -it --rm --name slave -p 8090:80 -p 2233:22 --link master:mas fukafukafukka/centos_for_ssh_lesson
```

## slaveコンテナ内でssh-keyを生成

```
$ docker exec -it slave bash

# cd ~/.ssh

# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
// 省略
```

## slaveコンテナ内で~/.ssh/configの設定

masterコンテナのIPをチェック。

```
# ping master
PING mas (172.17.0.2) 56(84) bytes of data.
64 bytes from mas (172.17.0.2): icmp_seq=1 ttl=64 time=1.53 ms
64 bytes from mas (172.17.0.2): icmp_seq=2 ttl=64 time=0.184 ms
^C
--- mas ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.184/0.858/1.532/0.674 ms
```

~/.ssh/configファイルを設定する。

```
# vi ~/.ssh/config

Host master
HostName 172.17.0.2
User root
Port 2222
IdentityFile ~/.ssh/id_rsa
```

## slaveコンテナ内の公開鍵をコピー
masterコンテナ配置用のslaveコンテナ内の公開鍵をコピーしておく。

```
# vi id_rsa.pub

// 中身をctl + c でコピー。
```

## masterコンテナ内へ公開鍵を配置

```
$ docker exec -it master bash

# cd ~/.ssh

# vi authorized_keys
// slaveコンテナ内でコピーした公開鍵をペーストする
```

## masterコンテナ内でsshポートをデフォルトから2222へ修正する

```
// コピーしてバックアップしておく。
# cp /etc/ssh/sshd_config /etc/ssh/sshd_config.org
```


```
# vi /etc/ssh/sshd_config

// 以下のようにデフォルトではなっているので、Portを2222にしてコメントアウトを外す。
# If you want to change the port on a SELinux system, you have to tell
# SELinux about this change.
# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
#
#Port 22 ← Port 2222に変更する。
```

上記の通り修正したら、sshdを再起動する。

```
# sshd -t

# systemctl restart sshd.service
```

slaveコンテナよりmasterコンテナへssh接続する

```
# ssh master
Last login: Sat May  1 02:49:38 2021 from 172.17.0.3
```
webサービスを個人で開発・運営するときに知ってほしい6つのこと【個人開発】

#初めに
自分が今まで個人開発をしてきて学んだこと、考えたことをまとめます。

#筆者について
webアプリを作るのが好きでここ一年間、公開したものだけで15個はあります


###最近作ったもの（宣伝も兼ねて）
![スクリーンショット 2021-04-30 133001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480294/e114a4b8-5868-a99a-4155-df2eebaab8ad.png)

https://ammot.net/

AmmotというSNSで、コンセプトは「制限の少ない自由な投稿を」です。
「ツイッターは文字数制限がきつい、ただfacebookは実名制だしデザインがごちゃごちゃでいや」
という声を聴いたので作ってみました。

文字数制限が6000字まで、画像・動画・音声は同時に10個まで投稿可能です。
詳しくはこちらも見てください

https://qiita.com/UTOG/items/d5e6194aaa31b54e97c9

#1.アイデアを出す方法
一番いいのは自分が困った経験を思い出すことです。
「○○あったらいいのになぁ」「○○がなくなればいいのになぁ」など

特に「このサービス使いにくいなぁ」とか結構いいかもしれません。
そのサービスを使ってる人はある程度自分が作ったサービスに興味を持つだろうし、使う人（ペルソナ）が絞られているので。

ただし急にそんなことを思い出そうとしてもなかなか出ないので、日ごろからメモをしたり
付箋に適当なことを書きまくってそれをグループ分けして要らないものをそぎ落とし、残ったものを順序よく並べて整理するという方法もあります。（KJ法と言われています。）

↓自分の日ごろのメモ
![スクリーンショット 2021-04-30 134209.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480294/d0c65fc3-be85-1953-a3b3-0731fea4cf4a.png)

まともなアイディアがありませんね。はい

##アイディア出しの注意
めちゃ個人的意見ですが
基本的には悩みを解決するタイプ以外のwebアプリは使われにくいです。
理由は二つ。

#####1.検索されないから。
「なんかおもろいwebサービスないかなぁ」で検索されることはほぼないです。
ユーザーがwebサービスを探す理由は基本的に困ったことがあるからです。

#####2.実際に使ってくれる人が少ない
緊急でもないので
「面白そうだな」とは思ってもそこから実際に使ってくれる人は非常に少ないと思います。

そう考えるとBoketeってすごい


#2.開発する前のアイディアの確認
開発する前に確認するべきことは大体こんな感じ

- 自分はそのサービスを使うか。
- なぜそのサービスを作りたいのか。
- 悩みをどうやって解決することができるサービスでしょうか。
- 最初は日本語だけで運営可能か
- 個人で管理できるか
- ほぼコンテンツがいらない or 自分で初期コンテンツが作れる
- 1～2年は運用できそうか
- 差別化はできそうか
- ユーザーにどんな体験を与えるか

一番重要なのは「自分はそのサービスを使うか」です。
自分が使うサービスは成功しやすいです。
開発してる時もユーザーの気持ちなどをいちいち考えず「自分がどうしたら使いやすいか」という主観的な目線で作れるからです。

ただ注意してほしいのは「これは自分も使う！」と思って開発したが結局自分は使わなかったというパターンです。
これを防ぐのは結構難しいですが、いったん休憩をしてみて落ち着いた状態でもう一回そのアイディアを見つめなおすと良いかもしれません。

#3.開発中
意識してるのは2つ
###デザインを重視する
これは結構意見が分かれがちですが僕はデザインはかなり重要だと思ってます。
最初はデザインなんて適当でいいやと思っていましたが
トップページのデザインは、ユーザーがどのくらい登録してくれるかに大きく左右します。

###動作速度を見る
railsは素の状態で使うと結構遅いので工夫が必要です。
僕がやってるは

- countメソッドを使わない
- キャッシュを使う
- scriptにはasync属性を付ける
- turbolinksは絶対に外さない
- render collectionを使う

くらいですかね。
それでもAmmotはそこそこ遅いので困ってます。

#4.リリースしたら
qiita
[service-safari](https://www.service-safari.com/)
[zenn](https://zenn.dev/)
[note](https://note.com/)
[つくログ](https://creators.eightbit.jp/)
[twitter](https://twitter.com/)

最低でもこのくらいは宣伝したほうがいいです。
無料で宣伝できるところがあったらなんでもやるくらいの心がけで挑みましょう。

名言：
宣伝はやりすぎるくらいがちょうどいい

#5.少し過疎ってきたら...

- 内容を変えて再度、qiitaやnoteに宣伝してみる。
- ログインをしないとコンテンツが見えないようにする
- 投稿時刻などを見せない

など
ツイッターやQiitaではスパム報告をされない程度に全力でやりましょう。
過疎ったということは一度は人を寄せ付けたということですから。

#6.諦めるタイミング
何度も宣伝したが無理...
完璧に過疎った...PV数0

某掲示板製作者のひ○ゆきという方が言っていました
「口コミで広がらないサービスは伸びない」

宣伝をしたら最低でも100人くらいの人が作ったwebアプリを見てくれると思います。それを何度かやって無理なら、あきらめましょう。

期間でいえば大体1月くらい公開・宣伝して全く無反応だったらやめましょう。
愛着があるサービス程、閉鎖は悲しいと思いますがあなたの中でその失敗の原因を探して今後に生かせば失敗しても「作ってよかった」といえる日がくるはずです。

#まとめ
一番重要なのは
**自分が使うサービスを作ろう**

ただそれでも失敗することはあるので

- webアプリを当てるのは結構難しいのでへこまず前へ進もう。
- 数を作ろう(そのためにスピードを上げよう)

最後に僕の作った[Ammot](https://ammot.net)もぜひ使ってみてください！

AmmotのURL
https://ammot.net/

僕のAmmotのアカウント
https://ammot.net/user/yamada(%E9%96%8B%E7%99%BA%E8%80%85)

僕のツイッターアカウント
https://twitter.com/yamada1531
CodeceptJSでブラウザの言語を取得して処理を分岐させる

Vue / BuefyのDatepickerコンポーネントはブラウザの言語によって月の名称が自動で変わる。
github actionsのCI用環境だと英語になっちゃうので月の指定を「5月」日本語で書いてると通らない。
なので、テストシナリオの中で直接ブラウザの言語を取得して分岐させたらうまくいった、というメモ。


- ローカルPC環境のブラウザだと日本語
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158169/b8ac0490-3325-c85b-be5d-6e34655a5c3f.png)

- CI環境(github actions)だと英語になっちゃう！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158169/64c4bf8d-436c-e44d-73ca-f9cbaeaffa00.png)

(参考)<a href="https://buefy.org/documentation/datepicker/#inline">Datepicker | Buefy</a>


## 対策1(失敗)
ログイン処理の中で言語指定のリクエストヘッダを送り込んでもうまく行かなかった。
`I.haveRequestHeaders({ 'accept-language': 'ja,en-US;q=0.9,en;q=0.8' })`

## 対策2(いまいち)
仕方ないので `navigator.language`を取得する。
ていうか、`I.executeScript`コマンド使えば何でもできるな。すごい便利。

```
const { format } = require(('date-fns'))

Feature('カレンダーテスト')

Scenario('日付セット', async ({ I }) => {

    //ブラウザの言語を取得する
    let lang = await I.executeScript(function () {
        return navigator.language.slice(0, 2)
    })
    //言語によって処理分岐
    if (lang === 'ja') {
        currentMonth = format(new Date(), 'M')//date-fnsでフォーマット
        I.click(`${currentMonth}月`)
    } else {
        currentMonth = format(new Date(), 'MMMM')//date-fnsでフォーマット
        I.click(`${currentMonth}`)
    }
})
```

## 対策3(成功)…10ヶ月後の追記
ヘルプをよーく読んだら、PlayWrightでlocale設定できた。
これで解決。時間返せ
```
  helpers: {
    Playwright: {
      locale: "ja-JP",
```
タグとプロパティの色々

## HTML、CSSの知識

さらに得た知識です。
HTMLとCSSを同時で学んでいるので
行ったり来たりしています。


# 1.divタグ(html)
* ディビジョンのことで領域（エリア）を示すためのタグ
* タグ自身には意味がない
* class属性（組：グループ分け）をつけることが多い
* class属性はグローバル属性

# 2.marginプロパティ(css)
* margin 上　右　下　左　で指定する
* margin 10 auto;　で要素を中央に配置することができる
* 左右をautoにすると中央に寄るのはCSSの仕様
* paddingは内側の余白を指定できる

# 3.font-sizeプロパティ(css)
* em→倍率を表す　ex)1.2em→元の大きさから1.2倍

# 4.labelタグ(html)
```html
<div class="control">
  <label for="mymail">メールアドレス</label>
  <input id ="mymail" type="email" name="mymail">
</div>
```
* for属性でinputタグと紐づける

# 5.spanタグ(html)
* divと同じように意味はない
* 改行したくない、1つの要素の中に納めたいときはspan
* 逆に改行して使いたいときはdiv


---

htmlとCSSが繋がって色々できるの面白いな。
指定した通りに見た目が変わっていくと嬉しい。

以上
【初心者向け】Windows10でUSBメモリを暗号化する【テレワーク】

初心者向けテレワーク豆知識第２弾です。
[第１弾はこちら](https://qiita.com/ronkabu/items/038d2b92abffb0ad9d24)

なるべく専門用語は使わないように避けている（つもり）です。

# なくすとやばいUSBメモリ
今まで一体何人がUSBメモリをなくして処分されてきたでしょうか。
実際に処分されないまでも、ヒヤリハットも含めるとかなりの方の寿命を縮めてきたことでしょう。

これらのために予めUSBメモリを暗号しておいて、なくした場合も含めて自分以外の他人が内容を見ることができないようにすることがWindowsの標準機能でできます。

そもそも無くさないようにすることが一番ですが、テレワークなどでどうしてもメディアを持ち出さなければいけないときに万が一に備える意味で紹介します。

# BitLocker
BitLockerはWindowsのドライブ暗号化機能です。
Bitlockerで暗号化されたドライブは、復号する鍵をなくした場合基本的に誰にもどうにもなりません。

※注意①：BitLockerを使った暗号化はWindows Pro以上の機能です。家庭用のHome Editionでは暗号化することはできません。（復号化はできます。）そのため、会社のProで暗号化して、自宅のHomeで閲覧・編集することはできます。
※注意②：Windows限定の機能です。暗号化したUSBメモリはMac、Linux、Android等では読み込みできなくなります。

また、暗号化することで読み込み・書き込みの性能が数％低下します。体感ではわかりづらいですが、気になる方は注意してください。

# BitLocker To Go
BitLockerをUSBメモリに適用する機能です。
暗号化されたUSBメモリは↓のようになり、アクセスするときにパスワードの入力を求められます。一度入力すると、取り外すかPCをシャットダウンするまでは暗号化されていないように扱うことができます。
![スクリーンショット 2021-05-01 214156.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207100/c3b594fc-6c40-98d0-94a6-91bc6ec66c48.png)

## 適用の仕方
これは簡単で、エクスプローラ（↑のような画面）を開き、USBメモリ（上の画像では「USBドライブ(D:)」）を右クリックします。
すると、ポップアップしたメニューの中に［BitLockerを有効にする］があると思うのでこれを選択します。この後、以下のような選択を求められるので、それぞれ選択していきます。

###「パスワード」か「スマートカード」のどちらでロックするか
ここでは「パスワード」を選択します。

### 回復キーのバックアップ方法
自分で生成したパスワードとは別に、ランダムに生成される回復鍵を保存する方法を聞かれます。
ファイルで出力したり、マイクロソフトアカウントと紐づけたり、印刷！することもできます。
ここで注意してほしいことは、

* 回復鍵
* この回復鍵がこのドライブの復号鍵であるという情報

のセットが漏れると、もちろんですが復号化できてしまいます。
つまり、「印刷してUSBメモリに書いておく」などはNGなので注意してください。
逆に、回復鍵だけ漏れてもどのドライブの復号鍵かがわからなければ危険性はありますが、致命傷にはならないことがあります。（家の鍵を拾ってもどこの家かわからなければ侵入されないのと同じ）

### 暗号化するディスク領域
これは既にUSBメモリにあるファイルを暗号化するかどうかで選んでください。

### 暗号化アルゴリズム
暗号化する方法を2通りから選びます。
新しい方法は新しいWindows10（Ver. 1511以上）でしか復号化できないので注意してください。（よくわからなければ従来の古い方法を。安全性には違いがありません）

## 暗号化実行
これらを選択し終わると暗号化が始まります。
暗号化が完了後、一度USBメモリを取り外し、PCを再起動してUSBメモリを挿入した後、設定したパスワードで中身が閲覧できて読み書きができることを確認してください。
お疲れ様でした。
GitlabのSSHの設定をしてみた

#はじめに
Gitlabのアカウントを初めて登録して、SSH認証の設定をした流れを記述します。
すでにGithubのSSHも持った状態です。なので今回は複数のSSHを管理する方法を学びます。

Githubでキーを使用しているにも関わらず新たSSHキーを生成、上書きしてしまい二度手間になりました。
もう一度作り直さないと行けなくなるので注意が必要です。

**ディレクトリ構成は下記**

```
$ cd ~/.ssh 
```

```
.ssh
  .config
    .githubフォルダ
　    |_id_rsa
　    |_id_rsa.pub
    ・gitlabフォルダ
    　|_id_rsa
    　|_id_rsa.pub
    known_hosts 
```

同じキーを色々なアプリで使い回せないので上記の様にアプリごとにキーの管理します。

***
####ちなみにSSHとは

**SSH(Secure Shell)とは通信規格の一種です。**
他にはHTTP,HTTPSなどがありますがこれらよりもSSHはセキュリティがしっかりしています。

ローカルリポジトリの情報をリモートリポジトリに送るときは、認証を行い他人からのアクセスをができない様に制限します。
***


##keyの生成
Gitlabに登録しているメールアドレスを入力してください

```
$ ssh-keygen -t rsa -C "xxxxxxxx@example.com"

# keysの保存先聞かれる
Enter file in which to save the key (/Users/name/.ssh/id_rsa): ディレクトリ位置のパスを指定

# 例 指定した位置に生成される。　特に指定がない場合はEnter。
Enter file in which to save the key (/Users/name/.ssh/id_rsa): /Users/name/.ssh/gitlub/id_rsa 
```

yを入力、再びEnter。

```
The key's randomart image is:
```
の下にkeyが表示されればOK
lsコマンドでフォルダの中身を確認

```
$ ls ~/.ssh/gitlab
id_rsa		id_rsa.pub	
```

id_rsa.pubとid_rsaの2つの鍵(公開鍵と秘密鍵)が書かれたファイルが生成されているはず。

##Gitlabへkeyの設定
catコマンドでファイルの中身を表示
ssh-rsa から メールアドレスの末尾まで をすべてコピー

```
$ cat ~/.ssh/gitlab/id_rsa.pub
```

もしくはコピペコマンドで

```
$ pbcopy < ~/.ssh/gitlab/id_rsa.pub
```

コピーできたら Gitlabのユーザー設定 > SSH鍵
キーのフォーム内に貼り付け追加する

##~/.ssh/configの設定

ファイル作成

```
$ touch ~/.ssh/config
```

権限を変更

```
$ chmod 700 ~/.ssh/config
```

権限が変更されたか確認する。下記の様になればOK

```
$ ls -la ~/.ssh 
-rwx------   1 username  staff     0  4 27 18:45 config
```

ファイルに設定を書く

```
vim ~/.ssh/config
```
"i"(insert)で入力

```
Host gitlab.com
    HostName gitlab.com
    User name
    #ディレクトリで分けている
    IdentityFile ~/.ssh/gitlab/id_rsa
    TCPKeepAlive yes
    IdentitiesOnly yes

Host github.com
    HostName github.com
    User name
    IdentityFile ~/.ssh/github/id_rsa
    TCPKeepAlive yes
    IdentitiesOnly yes

```

esc #インサート終了
:wq　#保存して閉じる


[known_hostsから特定のsshを削除する](https://qiita.com/grgrjnjn/items/8ca33b64ea0406e12938)
[ssh/config記事参照](https://qiita.com/passol78/items/2ad123e39efeb1a5286b)

##SSH接続確認

```
$ ssh -T git@gitlab.com
Welcome to GitLab, @name!
```

Welcomeが表示されれば成功！

###以上
ActionController::RoutingError - uninitialized constant GraphiQL::Rails::EditorsController エラーの解決方法

## 困ったこと

Rails 6 環境でGraphQLを実装するため[こちらのサイト](https://zenn.dev/slowhand/articles/4fe99377185100)を参考に各種セットアップをしていたところでした。

`rails generate graphql:install` コマンドを実行後、 `http://localhost:3000/graphiql` を開いたところ、以下エラーが発生した... :sob:

```ruby
ActionController::RoutingError at /
uninitialized constant GraphiQL::Rails::EditorsController
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29755/88558e31-8257-07de-cf63-6ae209088ebc.png)


## 前提

- 以下の Gem を利用している環境とする
    - `rails (6.1.3.1)`
    - `graphql (1.12.8)`
    - `graphiql-rails (1.7.0)`

## 解決方法

答えは Gem 本家のIssueに投稿されていた[コメント](https://github.com/rmosolgo/graphiql-rails/issues/43#issuecomment-614997706)でした。以下を追記後、Railsサーバーを再起動したら GraphiQLの画面が表示できました :tada: 

```diff:config/initializers/zeitwerk.rb
Rails.autoloaders.each do |autoloader|
  autoloader.inflector = Zeitwerk::Inflector.new
+  autoloader.inflector.inflect(
+    'graphiql' => 'GraphiQL'
+  )
end
```

## 関連
- [uninitialized constant GraphiQL::Rails::EditorsController · Issue \#43 · rmosolgo/graphiql\-rails](https://github.com/rmosolgo/graphiql-rails/issues/43)
- [Rails \+ GraphQLでAPI作成](https://zenn.dev/slowhand/articles/4fe99377185100)
- [fxn/zeitwerk: Efficient and thread\-safe code loader for Ruby](https://github.com/fxn/zeitwerk)
セッションベースの権限セットとセキュリティ ⇒ コードを作成せずにセッションベースの権限セットを有効化

１．セッションベースの権限セットを有効化するには、どのメカニズムを使用すればよいですか?
２．次の文が正しいか、誤りかを選択してください: コーディング方法を知らなくても、フローを使用してセッションベースの権限セットを有効化できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/a0432ce1-6d16-413b-ca70-6cc0b33c360b.png)