OmniAICreator/Qiita-1.07M huggingface dataset:
nuxtのサブディレクトリをHerokuにデプロイする方法

nuxtのアプリケーションをデプロイしたい場合、Herokuを使って簡単に立ち上げることができます。

例えば以下のようなnuxtのディレクトリ構造がある場合(docker使ってるならimageデプロイしたほうがいいのはおいておいて)

```
├── docker/nuxt.js
│   ├── assets
│   ├── components
│   ├── pages
│   ├── ....
│   ├── nuxt.config.js
│   ├── package.json
│   ├── Procfile <- Heroku で必要となる、アプリケーションの起動に関するファイル
│   ├── yarn.lock
│   ├── README.md
├── package.json
├── docker-compose.yml
```

# サブディレクトリに移動してherokuアプリをつくる
```
cd docker/nuxt.js && heroku create sample-nuxt-app
```

# heroku-buildpack-monorepoを追加
```
heroku buildpacks:add -a sample-nuxt-app https://github.com/lstoll/heroku-buildpack-monorepo
```

# サブディレクトリのパスをconfigに追加
```
heroku config:add APP_BASE=docker/nuxt.js -a sample-nuxt-app
```

# nodeのbuildpacksを追加
```
heroku buildpacks:add heroku/nodejs
```

# remote repository を登録
```
heroku git:remote -a sample-nuxt-app
```

# envを登録
```
heroku config:set NPM_CONFIG_PRODUCTION=false
heroku config:set HOST=0.0.0.0
heroku config:set NODE_ENV=production
heroku config:set API_HOST={任意のドメインなど}
```

# Procfileを作成
```:docker/nuxt.js/Procfile
web: npm start
```

# deployを実行
```
git push heroku master
```

※ gitの `master` ブランチじゃなく `develop` ブランチをデプロイしたい場合

```
git push heroku develop:master --force
```

# 起動確認
```
open https://sample-nuxt-app.herokuapp.com/
```

-------------

# 補足

configを削除

```
heroku config:unset {削除したいenv名} -a sample-nuxt-app
heroku config:unset buildpacks -a sample-nuxt-app
```

buildpacksを削除

```
heroku buildpacks:clear -a sample-nuxt-app
```


# 参考資料
- [Nuxt.jsをHerokuへデプロイする手順
](https://qiita.com/00092/items/4f7e5d08c897e113e50c)
- [monorepo構成のGitrepositoryのsubdirectoryをherokuにデプロイする](https://ohbarye.hatenablog.jp/entry/2018/07/08/160003)
- [Herokuアプリケーションのビルドパックについて
](http://info-i.net/heroku-buildpacks)
3Dプリンタ初心者が3時間程度でリモコンケースを作って3Dプリントした話

# 経緯
エアコンのリモコンの位置が毎回同じでないと気になるので、専用のリモコンケースを作成しました。

CADについて何も知らない状態からでも、３時間程度でリモコンケースが作れちゃいました。案外、簡単に作れたのでここで共有させていただきます。

# 道具
- iPad Pro(Airでもいいかも)
- Shaper3Dというアプリ
- Apple Pencil
- 定規

# 作るもの
エアコンのリモコンケースを作ります。
![20190901_143047.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250965/2a4b049d-5acb-0736-bd77-6ee55b15f0c1.jpeg)

リモコンケースは、こちらのハンガーレールに接合できるように作成します。
![20190901_143350.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250965/9efa929d-be5d-633a-8828-9e1c86536408.jpeg)

以下の写真は、ハンガーレールに付属していたフックです。
ハンガーレールに、リモコンケースを接合するためには、写真の赤枠部のような細工が必要です。
![20190901_143841.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250965/86cec6dc-12b0-c4f3-f874-229d9e61dc24.jpeg)

# 制作過程
Apple Pencilでゴニョゴニョするだけで、立体物を描画することができます。Shaper3Dはかなり直感的なUIで、使いやすかったです。

### 面の横と縦の長さ微調節
<img width="1024" alt="IMG_0004.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250965/76da38da-b19d-2ef5-3bbd-630096b0c3e4.jpeg">

### 面の選択
<img width="1024" alt="IMG_0005.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250965/7a2ac757-57fc-3fd4-8a5f-cee17ef83737.jpeg">

### 面を凹ませる
<img width="1024" alt="IMG_0006.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250965/04d6f997-eccf-dcee-53c0-a8e7d47d59b0.jpeg">

### 凹ませ具合の微調整
<img width="1024" alt="IMG_0007.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250965/e1d0f81f-f76d-819f-c322-fa5e3c658fc8.jpeg">

### 3Dプリント
完成した3Dモデルは[こちら](https://make.dmm.com/item/1092868/)になります。
3DプリントはDMM.makeに発注しました。DMM.makeでは3Dプリントに使用する素材を選ぶことができるみたいですが、私はナイロン素材を選択しました。

#### DMM.makeで選べる素材(2019/09/01の時点)
- ナイロン
- Agilusゴム
- アルミ
- ステンレス
- 石膏
- ゴールド
- etc...

素材は全部で28種類の中から選べるみたいです。

### 完成品
完成品です。触り心地がザラザラしています。
![20190901_140713.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250965/f92c825a-1176-4df0-e76b-ff2276c7c0fd.jpeg)

カーテンレールとの接合箇所です。接合箇所の数ミリ程度の隙間が正確にプリントされていることが確認できます。
![20190901_140718.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250965/07bedfed-b03e-1036-6fd4-be6b54d86e9b.jpeg)

# 設置
綺麗にスッポリはまりました。
![20190901_153345.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250965/427455d7-3ab0-19fd-f41f-35d449b9160a.jpeg)

リモコンを入れたときの写真です。
![20190901_153338.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250965/27511aac-7e87-5b9e-af90-0c036a72c9c3.jpeg)


# おわりに

* 3Dモデルが意外と作成できた
* Shaper3DのUIが直感的
* 印刷費用が2210円と割高
* Raspberry PIと3Dプリンタを組み合わせると何か面白いものが作れそう
データ指向設計（Data Oriented Design）でのゲーム開発について

## 詳細
ゲーム開発を行う上での考え方に**データ指向設計 (Data Oriented Design)**というものがあります。

この数十年でCPUの性能が１万倍以上になっているのに対して、メモリの性能は10倍未満しか達していません。更に今後もCPUとメモリとの差はだんだん増えていくと思われます。
そのため、ゲーム開発でのボトルネックがメモリ帯域となることが多くなりました。![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229633/aafa4d9b-5724-357c-acc3-848ea58adb53.png)
**参考：**INTRODUCTION TO DATA ORIENTED DESIGN
https://www.ea.com/frostbite/news/introduction-to-data-oriented-design

ゲームの処理やパフォーマンスに一番影響されるのはメモリの読み取りスピードです。現在、CPUのほとんどの時間がメモリからのデータの転送待ちになっています。CPUの性能を引き出すためには、メモリ帯域をいかに効率よく使うかが重要になっています。

今後のゲーム開発では、メモリのデータを読み取るプロセスをできるだけ少なくすることに着目した設計が求められます。**データ指向設計 (Data Oriented Design)**ではこの様な考え方のもと、効率の良いメモリレイアウトを考えて設計します。
### データ指向設計とは
プログラムでは、データを入力として受け取り、データに何らかの加工を行い、結果のデータを出力しています。 何をするにもデータが絡みます。そのため、データのメモリレイアウトや、データがどう読まれて書き出されるのかに着目した設計がデータ指向設計です。

## Unityでのデータ指向設計について
Unityの場合はEntity Component System（略称:ECS）というソフトウェアアーキテクチャパターンがあります。

サンプルコード：EntityComponentSystemSamples
https://github.com/Unity-Technologies/EntityComponentSystemSamples
![02.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229633/d958dffb-211d-2be9-6eca-ba7075af74bb.gif)

## 参考
* **Data-Oriented Design (Or Why You Might Be Shooting Yourself in The Foot With OOP)**
http://gamesfromwithin.com/data-oriented-design

* **INTRODUCTION TO DATA ORIENTED DESIGN**
https://www.ea.com/frostbite/news/introduction-to-data-oriented-design
GitHub Actionsを使ってAWS Lambdaへ自動デプロイ

# 前置き
ソースコードの管理をGitHubで行なっているのでCI/CDもGitHubに統一できたら楽だな〜と思って、GitHub Actionsを色々検証したり、実際にステージング・本番環境へデプロイするのに使ったりしています。
そこで今回はAWS Lambdaへの自動デプロイ方法を説明したいと思います。

# 概要
CDはタイトル通りGitHub Actionsを使い、デプロイには[Serverless Framework](https://serverless.com/)を使います。ただデプロイするのは簡単なので、GitHubのSecretsからLambdaの環境変数に値をセットするのをやります。
デモ用のアプリは[こちら](https://github.com/homoluctus/demo_auto_deploy_lambda)に置いてあるのでforkしてGitHubのSecretsにAWSの認証データとSlackのIncoming Webhooks URLをセットして、何かしら編集してcommit/pushすれば自動デプロイを体験できるようにしてあります。デプロイに成功すればLambdaが実行されてLambdaからSlackへ通知がいくようになっています。

# 自動デプロイ方法
## Serverless Framework
SlackのIncoming WebhookのURLはホストの環境変数から取得します。

```serverless.yml
service: auto-deploy-lambda

provider:
  name: aws
  region: ap-northeast-1
  timeout: 120

  environment:
    SLACK_WEBHOOK: ${env:SLACK_WEBHOOK}

package:
  exclude:
    - Dockerfile
    - docker-compose.yml

functions:
  slack:
    handler: src/index.post
    description: "Post message to Slack"
    timeout: 60
```

## GitHub Actions
リポジトリにある定義ファイル`.github/workflows/deploy.yml`は全てコメントアウトしてあるので、デモをする際はアンコメントしてから実施してください。
やるべき事として、GitHubのSecretsに3つのパラメーターの設定があります。`AWS_ACCESS_KEY_ID`、`AWS_SECRET_ACCESS_KEY`、`SLACK_WEBHOOK`です。これらが設定されていないと失敗するので注意が必要です。わざと失敗させてみるのもいいですが...

```..github/workflows/deploy.yml
on:
  push:
    branches:
      - master

name: Auto Deploy to AWS Lambda

jobs:
  deploy:
    name: Auto Deploy
    runs-on: ubuntu-18.04
    steps:
      - uses: actions/checkout@master

      - name: Setup Node.js
        uses: actions/setup-node@v1
        with:
          node-version: '10.x'

      - name: Install Dependencies
        run: |
          npm install serverless -g
          npm install

      - name: Deploy to Lambda
        run: sls deploy
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

      - name: Execute Lambda
        run: sls invoke -f slack
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

      - name: Notify result to slack
        uses: homoluctus/slatify@master
        if: always()
        with:
          type: ${{ job.status }}
          job_name: '*Deploy Lambda*'
        env:
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
```

内容としては、Serverless Frameworkを使ってLambdaへデプロイした後にその関数を実行するようになっています。正常に実行されれば以下のような通知がLambdaからSlackへ飛んできます。

<img width="405" alt="スクリーンショット 2019-09-01 14.34.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173064/9407743e-9a53-4193-a134-c7aa5f9fdc19.png">


### Job結果
色々ごにょごにょしたい方のためにGitHub Actions自体のJob結果を通知するjobを最後に加えています。`name: Notify result to slack`から下の箇所ですね。
Jobが成功すると↓の感じの通知がSlackへきます。

<img width="654" alt="スクリーンショット 2019-09-01 14.37.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173064/4f4a84f7-c6bd-c169-a2ec-3ca089fb8abb.png">

何らかのjobが失敗した時にはサイドバーの色が緑色から赤色に変わります。リンクからGitHub Actionsの実行結果画面にとべるようになっているのですぐに原因を調べることができます。
【Azure】QnA MakerでFAQチャットボットを作る

QnA Makerとは、AzureのCognitive Serviceを使い、FAQ用の質問＋回答のナレッジベースを作成できるもの。

QnA Maker 全般にわたって解説した記事
[QnA Maker Deep Dive (といいつつ実際は公式ドキュメントのサマリ) - Qiita](https://qiita.com/kenakamu/items/6fa208fa384196009d94)

# 初期構築時の注意
利用者のログを残したければ、App Insightsを有効にして作成する。
FAQチャットボットを運用する場合、ログが無いと何も改善できないので、有効にするのが良いと思われる。

# ナレッジベース初回登録時の注意
ナレッジベースに初めて登録する質問＋回答で、Search Serviceの言語が決まる。後からの変更はできないので、QnA Makerを作り直さなければいけない。

参考：下記記事のQ1
[QnA Maker API V4 (一般公開版) のよくあるご質問 – Japan Cognitive Services Support Blog](　https://blogs.msdn.microsoft.com/jpcognitiveblog/2018/06/05/qna-maker-api-v4-ga-faq/)
  
質問と全く同じ文を入力しても答えが返ってこない場合、この状態に陥っている可能性がある。

# QnA Maker構築時に作られるApp Serviceについて
QnA Makerを作成して出来るApp Serviceは、ナレッジベースのメンテ等APIの提供に使われているっぽいので、いじってしまうとAPIが動作しなくなったりしてしまう。

# Q&Aのログを参照する
QnA Maker作成時にApp Insightsを有効にしていれば、App Insightsにログがたまる。
https://docs.microsoft.com/ja-jp/azure/cognitive-services/qnamaker/how-to/get-analytics-knowledge-base

# 同義語を登録する
「パソコン」であれば、「PC」や「コンピュータ」など、同義語を登録してQ&Aのヒット率を向上させることができる。同義語についてはAPIしか用意されていないため、PowerShellなどを使って登録＆更新する必要がある。

[Alterations (Azure Cognitive Services) | Microsoft Docs](https://docs.microsoft.com/ja-jp/rest/api/cognitiveservices/qnamaker/alterations)

APIの実行に必要な Endpoint と Key は、Azureポータルの Cognitive Service のページから取得できる。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/c1e61cf6-f468-ac01-ee79-a1d9a8d52b0e.png)

同義語の登録は置換式なので、一度登録済みの内容を取得してから同義語を追加し、登録するのが良い。

以下、同義語の取得＆登録ができるPowerShellのサンプル。

```powershell
Param($func)

$endpoint = "https://westus.api.cognitive.microsoft.com/qnamaker/v4.0"
$key = "Azureポータルで取得したキー"

$headers = @{"Ocp-Apim-Subscription-Key" = $key}

$filename = "alterations.json"

<#
    同義語を取得する
#>
function GetAlterations() {
    $url = "${endpoint}/alterations"

    $rc = Invoke-WebRequest -Uri $url -Headers $headers -OutFile $filename -PassThru
}

<#
    同義語を登録する
#>
function PutAlterations() {
    $url = "${endpoint}/alterations"

    $rc = Invoke-WebRequest -Uri $url -Headers $headers -Method Put -InFile $filename
}

if ($func -eq "get") {
    GetAlterations
} elseif ($func -eq "put") {
    PutAlterations
}
```

コンソールから`.\alterations.ps1 "get"`と実行すると登録済みの同義語の取得、`.\alterations.ps1 "put"`と実行すると同義語の登録ができる。同義語のファイルは、スクリプトと同じフォルダに`alterations.json`というファイル名で保存される。

# 次のステップ

[Bot Serviceを作る (ナレッジ←→UIの中間部分)](https://qiita.com/vicugna-pacos/items/adeab5caf0c438c46041)
DBLink越しのクエリがOracle11gから12cに変更した時に性能が劣化した件について

# サーバ構成とアプリの仕様から問題発生まで
まずはサーバ構成とアプリの仕様から問題発生までを下の図で示す。
![アートボード .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136860/8ec952ac-179e-1d55-9c25-70c9b73984b7.png)
# 原因調査
まずは原因調査のため発行されたSQLの実行計画について11gと12cでそれぞれ取得した

 - 11gの実行計画    
 テーブルBで論理削除コード='1'を絞り、テーブルAにテーブルBの絞り込んだ結果でアクセスしている
 - 12cの実行計画    
 テーブルAからキーAを全件取得し、取得した分、テーブルBにアクセスしている

次にテーブルA、Bの情報を収集し、以下の点が判明した

 - テーブルA,Bともにデータ件数は500万件
 - テーブルBで論理削除レコード='1'は2000件程度

# 原因の特定
SQLの構造と実行計画から、11gから12cに変更したことでDBLink越しの通信が増えたからではないかと推測した。
つまり、11gの時は「テーブルBで論理削除レコード='1'」の件数分、すなわち2000回リモートアクセスが発生していたが、12cに変更した後はテーブルAの件数分、すなわち500万回リモートアクセスが発生していると

試しに、カーソルの宣言で記載しているSQLをテーブルBの取得を先に評価するように直してみた

``` 
Selet * from テーブルB main where Exists(
    select 1 from テーブルA@DB_A sub where main.キーA = sub.キーB 
) where main.論理削除コード ='1'
```

修正後のSQLをOracle12cの環境で実行してみたところ、実行計画も実行時間も11gと同様のものになった

# 終わりに
DBLINK越しのSQLを作るときは、当たり前だがリモートアクセスをなるべく発生させないようクエリを組もう。
Oracleのオプティマイザに頼るとひょんなことから非効率なアクセスパスになってしまうことがあるのだから。
PWA化したサイトにOneSignalを設定するための注意点

## 初めに
PWA?OneSignal?と思われる方もいらっしゃるでしょうが、それらはググって頂ければ詳細はたくさんあるとおもうので割愛して、今回は、仲間内でのみ使う、Webスクレイピングした情報を見やすくまとめたサイトをPWA化してプッシュ通知を対応させようとして嵌まった話を。

## 普通のサイトと異なる点
OneSignalの設定をしたら、OneSignalSDKUpdaterWorker.jsとOneSignalSDKWorker.jsをダウンロードして、それをサーバーにアップロードしなければなりません。まず、この2つのファイルをこう設定します。

```
importScripts('serviceworker.js');
importScripts('https://cdn.onesignal.com/sdks/OneSignalSDKWorker.js');
```
一番上の行にserverworksまでのパスを貼付けます。そして、HTMLのserverworksの記述をしていたところを例えばこういう風に書き換えます。

```
<script src="https://cdn.onesignal.com/sdks/OneSignalSDK.js" async=""></script>
<script>
    var OneSignal = window.OneSignal || [];
    OneSignal.push(function() {
        OneSignal.init({
        appId: "あなたのID",
        });
    });
    if('serviceWorker' in navigator) {
    navigator.serviceWorker
            .register('OneSignalSDKWorker.js')
            .then(function() { console.log("Service Worker Registered"); })
            .catch(function() { console.log("Service Worker Not Registered"); });
    }
```
以前はmanifest.jsonも書き換える必要があったようですが、現在はその必要がありません。

## 嵌まったところ

　ここからが本題なのですが、「どうせ仲間内だし」と独自ドメインも取らずに、VPSのサーバー内でmydnsのドメインで運用していましたが、他にもWebアプリやページがあったので、https;//hogehoge.mydns.jp/example/というドメインで運用したのですが、どうしてももプッシュ通知が出ずに詰まりました。あれこれ試行錯誤するうちに気がついたのはOneSignalとPWA関係のは必ず **ルートディレクトリに置かないとならない**　ということです。

　今回の場合CentOSにApacheをインストールしていたので、*/var/www/html/example/*ではなく、*/var/www/html/*です。例えば独自ドメインをとって、/var/www/html/example/をルートディレクトリとして指定したら、/var/www/html/example/で問題ない（それは別件で確認済み）のですが、**1つのドメインにおけるOneSignalは1つ**と言うことなのでしょう。

あと、間抜けな話として、それに気がついてHTMLを変えてる最中で、間違った設定を読み込んだら以後エラーが出たことがありました。設定は必ず統一する必要があることは言うまでもありません。

## 最後に
以前はメールでページ更新を知らせていたのですが、プッシュ通知にすることで他のメールと埋もれることもなくモダンさも増してました。OneSignalのサイトは英語しかありませんが、日本語の解説も充実しているので機会があればお試し下さい。
ES モジュールローダーを使ってみた

元ネタは「[現代の JavaScript チュートリアル](https://ja.javascript.info/modules-intro)」。

```.js
// say_hi.mjs
export function sayHi(user) { console.log(`Hello, ${user}`); }
```

```.js
// main.mjs
import { sayHi } from './say_hi.mjs';

console.log(sayHi);
sayHi('John');
```

# 実行結果

![screenshot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28376/7b98f3f0-6c34-2366-8bcc-152ea151f0fb.jpeg)


# 参考にしたページ
- [【Node.js入門】初心者でも分かるimport / exportでモジュールを使う方法まとめ！](https://www.sejuku.net/blog/86754)
- [Node.js の開発版で ES モジュールローダーを試す - Qiita](https://qiita.com/masakielastic/items/8dd290780d2667c9e78a)
- [ES2015のモジュール管理](https://thinkit.co.jp/article/10644)
MySQL でダミーデータをたくさんつくる

とりあえず、SQL 描きたいとき。とりあえず、レコードがたくさんあるテーブルを欲しくなります。そんなときに SQL だけでサクッと環境をつくりたくなります。

そんな記事です。

# テーブルを作る。

```sql:create_users_table.sql
create table users (
  id int not null auto_increment,
  name varchar(255),
  primary key (id)
);
```

# レコードを while で insert する

```sql:insert_users.sql
delimiter //
create procedure insert_users()
begin
  declare i int default 0;
  while i < 10 do
    insert into users (name) values (concat('name', i));
    set i = i + 1;
  end while;
end
//
delimiter ;

call insert_users;
```

procedure については [この記事(ストアドプロシージャの基本的ななにか)](https://qiita.com/setsuna82001/items/e742338eb93e3a48ba46) が、とてもわかりやすいです！

while 構文はこちらの [ドキュメント(13.6.5.8 WHILE 構文)](https://dev.mysql.com/doc/refman/5.6/ja/while.html) を見れば一発でわかります。



# 入ったデータを見てみる

```
mysql> select * from users;
+----+-------+
| id | name  |
+----+-------+
|  1 | name0 |
|  2 | name1 |
|  3 | name2 |
|  4 | name3 |
|  5 | name4 |
|  6 | name5 |
|  7 | name6 |
|  8 | name7 |
|  9 | name8 |
| 10 | name9 |
+----+-------+
```

以上です。簡単でした。

# おまけ ~ procedure の引数でレコード数を渡せるようにする ~

```sql:insert_users_v2.sql
delimiter //
create procedure insert_users(in x int) -- 引数
begin
  declare i int default 0;
  while i < x do -- 引数使う
    insert into users (name) values (concat('name', i));
    set i = i + 1;
  end while;
end
//
delimiter ;

call insert_users(100); -- ここでレコード件数を指定
```

では、これらを使って docker 環境でいろいろ SQL 叩いて行きたいとおもいます。 :lemon:
【UiPath】Excelがインストール済みなのにExcelアプリケーションスコープが使えない場合の対策

# 現象
Excelをインストールしてあるはずなのに、下記エラーが出てExcelアプリケーションスコープが使用できない。

```:エラー詳細
ソース: Excel アプリケーションスコープ

メッセージ: ワークブックを開くときにエラーが発生しました。Excel がインストールされていることを確認してください。

例外の種類: System.Exception

RemoteException wrapping System.Exception: ワークブックを開くときにエラーが発生しました。Excel がインストールされていることを確認してください。  ---> RemoteException wrapping System.Runtime.InteropServices.COMException: CLSID {00024500-0000-0000-C000-000000000046} を含むコンポーネントの COM クラス ファクトリを取得中に、次のエラーが発生しました: 80040154 クラスが登録されていません (HRESULT からの例外:0x80040154 (REGDB_E_CLASSNOTREG))。 
```

# 原因と解決策
複数バージョンのExcelをインストールし、先にインストールした方をアンインストールした場合に起こる。
Excelをインストールしなおすと解消する。

## 詳しい原因
UiPathのExcelアプリケーションスコープは、COMコンポーネントの呼び出しで実装しているようだが、
そのCLSIDの登録されている場所が、複数バージョンのExcelをインストール＆アンインストールするとずれてしまう。
CLSIDはレジストリエディタで参照できる。

↓UiPathがExcelを起動できないときのレジストリ
![01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/87e535e4-79a7-ecf3-721a-294be7e79478.png)

↓Excelをインストールしなおした後のレジストリ
![02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/f8c300cf-60be-86c8-98e0-8caaaded21dc.png)
プログラミング学習（五日目）ProgateでRuby On Rails レッスン4

<h1>今日学んだこと</h1>

##投稿の編集
`a = Post.find_by(id:2)`  データベースから編集したい投稿の取得
`a.content = "Hello World"`  編集したいカラムの値の上書き
`a.save`  データベースに保存

今までやったこととほぼ一緒なのであまり難しくはない

##投稿の削除
`a = Post.find_by(id:6)`  データベースから削除したい投稿の取得
`a.destroy` destroyメソッドでデータベースから削除

##編集時のポイント
html.erbファイルにて
`<textarea>こんにちは</textarea>`
とすると、入力フォームに「こんにちは」が元から入っている状態になる

##ルーティングでの「get」と「post」
`get "URL"`は、
データベースを変更しないアクションへ移動

`post "URL"`は、
データベースを変更するアクションへ移動

「link_to」メソッドは、ルーティングで`get"URL"`を探してしまうので
「destroy」メソッドを使うときに、「link_to」メソッドの第三引数に{method:"post"}を入れるとpostで定義されたルーティングを探してくれる。




危うく三日坊主になるところだった...
マークダウン必要なとこだけ

###マークダウン記法
githubやqiitaの記事を書くときなどに使用するやつ。
必要なとこだけ

####■「\」を頭につけてマークダウン無効化
####■「\*\*」で文字を囲めば太字
####■「\~\~」で文字を囲めば取り消し線
####■文頭に「>」で引用、上下には空行要、ネスト可
####■文頭に「#」で見出し、「#」文字大　→　「#####」文字小
####■文頭に「- 」でリスト、上下には空行要

- 単方向リスト
- 双方向リスト
- 環状リスト

####■コードブロック(C言語) 「\`\`\`c:ファイル名」ここに処理をかく「\`\`\`」

```c:main.c
#include <stdio.h>
int main(void){
  printf("おはよう");
  return 0;
}
```

####■コードブロック(言語指定なし)「\`\`\`」ここに処理をかく「\`\`\`」
```
print('おやすみ)
```

####■「-」、「*」、「_」などを3つ以上連続して記述することで水平線
---

####■リンク  　\[タイトル](URL)
[知らないと色まずIT知識](https://qiita.com/Banayad/items/b66effc86c3099adbbc6 "タイトル")

####■画像　　\!\[タイトル](URL)
![女神](https://img21.shop-pro.jp/PA01327/490/product/143042638.jpg?cmsp_timestamp=20190523181031)


####■その他　
大概はここを見れば分かるはず、本記事でも参考にさせて頂きましたm(_ _)m
[マークダウン記法](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)
IEのJavascriptで次の日リリースのものが動かなくて。。2019夏

jQueryがないよって言われる

```
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
```

for of構文が使えない

```
for ofから、for inに書き換えた。
```

ajaxの書き方が違う
だめな方

```
            $.ajax({
                url:'/api/xxx/',
                type:'GET',
                data: {
                    area: $('#area').val()
                },
                dataType: "json",
            })
            .done( (data) => {
              …
                }
            })

```


書き直したやつ

```
            $.ajax({
                url:'/api/xxx/',
                type:'GET',
                data: {
                    area: $('#area').val()
                },
                dataType: "json",
            })
            .done( function(data) {
              …
                }
            })

```

for文でグーグルマップのマーカーを、作成しイベントリスナを付けていたが、最後のマーカーにしかイベントが紐付かなかった。
現在、１つずつ生成し、イベントリスナを紐付けている。
ダサすぎる。。。
cliで環境構築したリポジトリをgit cloneしてローカル上で再現する。

vue-cliでの成果物を参考したいと思い、
git cloneでエディタにと入れnpm run serveでローカルで再現したがエラーが起きた。
解決方法は今思えば超簡単だったので、備忘録として残しておく。


``` bash
 git clone URL
```
でまずはコピー、ここまでは変わらない。

そのあとに、READMEのproject setupに書かれている

```
npm install 
```
を入力、ここでnode_modulesが作成される。やっとローカルに再現できる。

```
npm run serve 
```
立ち上がりました。

要するに、git cloneしてREADMEのproject setupを参考にすればOK
Excel/VBA関連の参考URL


個人用のメモです。
僕が初学者なので、初学者の人が読んでわかるリンクを載せています。
日々更新します。
世の中に発信してくれている人達のおかげで僕もコツコツ作品作れます。
ありがとうございます。

【前提】
OS : windows10 Pro 64bit
Office : 2016

- *セル内の該当の文字列の個数を数える*

[https://www.forguncy.com/blog/20180730_counttext](https://www.forguncy.com/blog/20180730_counttext)


- *TEXT関数で特定の数値を、書式指定して文字列化する*

[https://excel-ubara.com/excel1/EXCEL573.html](https://excel-ubara.com/excel1/EXCEL573.html)

- *タスクスケジューラでVBAを起動したい*

[https://qiita.com/miyamiya/items/c02e4aa5be35248099ce#2-%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%B9%E3%82%B1%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%A9%E3%83%BC%E3%81%B8%E3%81%AE%E8%A8%AD%E5%AE%9A](https://qiita.com/miyamiya/items/c02e4aa5be35248099ce#2-%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%B9%E3%82%B1%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%A9%E3%83%BC%E3%81%B8%E3%81%AE%E8%A8%AD%E5%AE%9A)

[http://www.siminpc-kitakyushu.com/index.php?QBlog-20141029-1](http://www.siminpc-kitakyushu.com/index.php?QBlog-20141029-1)
ESXi6.7にUbuntu18.0.4をインストール

#環境
- ハイパーバイザー　：　ESXi6.7U2
- 導入OS　：　Ubuntu18.0.4
    - 導入イメージ：ubuntu-18.04.3-live-server-amd64.iso


#手順
##ESXiで仮想マシン作成手順
1. vSphereWebClientからESXiにログインする
2. ナビゲータ画面のホストタブを開き、上段の「仮想マシンの作成/登録」をクリック
3. 「新規仮想マシン」ダイアログが表示されるので、以下選択を行っていく
    1. 作成タイプの選択 : 新規仮想マシンの作成 を選択
    2. 名前とゲストOSの選択
        3. 名前：　任意の仮想マシンを入力  (例　UbuntuVM）
        4. ゲストOSファミリ：Linux
        5. ゲストOSのバージョン：UbuntuOS（64ビット)
    6. ストレージの選択　：　仮想マシンのファイルを保存したいデータストアを選択（例　本手順ではdatastore1というデータストアを選択）
    7. 設定のカスタマイズ：CPU/メモリなどお好みで設定を変更可（本手順では変えない）。
    8. CD/DVDドライブ１をホストデバイス　から　データストアISOファイルに変更し、ダウンロードしてきたUbuntuのISOファイルを選択する[datastore1] isoimage/ubuntu-18.04.3-live-server-amd64.iso
    9. 設定の確認で内容を確認して完了
10. ナビゲータ画面に戻り、仮想マシンタブを開きます。
11. 先程作成した仮想マシン名（例　UbuntuVM）をクリックします。
12. ▶パワーオンボタンをクリックします。
13. 画面コンソールをクリックします。

##Ubuntuインストール手順
1. Welcome画面　：　English
2. KeyboardConfiguration　
    3. Layout：　Japanese
    4. Variant：　Japanese
5. NetworkConnections
    6. ここでは設定しないのでそのまま進む
7. Configure Proxy
    8. ここでは設定しない
9. Configure Ubuntu archive mirror
    10. ここもデフォルトのまま進む
11. FileSystem setup
    12. Use An Entire Diskを選択（LVMはここでは設定しない）
    13. 仮想マシン作成時に指定した容量のディスクが表示されるため、選択された状態でEnter
    14. サマリー画面が表示されるので、Doneをクリックし、確認画面でContinueを選択
15. ProfileSetup
    16. Your name : 名前を入力（※ユーザー名ではない）
    17. Your server's name : ホスト名を入力
    18. Pick a User Name : ユーザー名を入力
    19. Choose a Password : パスワードを入力
    20. Confirm your Password : 上記で入力したパスワードを再入力
21. SSH setup
    22. Install OpenSSH serverにチェックを入れ（スペースキー）、Doneを選択  **これでインストールが開始されます。**
23. インストールが完了したら、View Full Logの下にReboot Nowが表示されるので選択し、再起動させます
24. 途中、Enterキーを求められるのでEnterキーを押下
Pythonでアルゴリズム（マージソート）

#マージソート
##コード
###関数の定義
```merge_sort.py
def merge(A,left,mid,right):
    n1 = mid - left + 1
    n2 = right - mid
    L=[]
    R=[]
    for i in range(n1):
        L.append(A[left + i])
    for j in range(n2):
        R.append(A[mid + 1 + j])
    L.append(float('inf'))
    R.append(float('inf'))
    i = 0
    j = 0
    for k in range(left,right + 1):
        if L[i] <= R[j]:
            A[k] = L[i]
            i += 1
        else:
            A[k] = R[j]
            j += 1
    return A

def merge_sort(A,left,right):
    if left < right:
        mid = (left + right)//2
        merge_sort(A,left,mid)
        merge_sort(A,mid + 1,right)
        merge(A,left,mid,right)
    return A
```

###使い方
```merge_sort_use.py
A=[2,6,3,8,5]
print(marge_sort(A,0,4))
```
##説明
###関数mergeについて
　
・役割は、配列中のある部分に注目し、その部分を2つに分けた時、それぞれがソート済みだった場合に2つの配列を合わせて1つのソートされた配列を作る。

・ソートしたい部分の左端のインデックスをleft、右端をrightとし、2つに分ける際の境目をmidとする。
　
・前半のleft~midまでをサイズn1の新しい配列Lとし、後半のmid+1~rightまでを新しい配列Rとする。

・LとRの末尾に番兵として∞なる値を置いておく。

・LとRの先頭から順々に大きさを比較していき、小さいほうを配列Aのソートしたかった部分の先頭から代入していく。

###関数merge_sortについて

・役割は、mergeを再帰的に用いてある配列のソートしたい部分をソートする。（左端をleft、右端をrightとする。）

・再帰的にmergeを用いる際、停止するのは配列の大きさが1まで分割されたとき、すなわちleft>=rightとなるとき。（個人的にはright-left>=1の間は実行するとかの方が分かりやすかったです。）

・まず、ある配列を2つに分けるため、真ん中のインデックスmidを求める。

・その前半と後半それぞれでまたmerge_sortを用いる。




###参考文献

この記事は以下の情報を参考にして執筆しました。

-[アルゴリズムイントロダクション](https://www.amazon.co.jp/%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%82%A4%E3%83%B3%E3%83%88%E3%83%AD%E3%83%80%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3-%E7%AC%AC3%E7%89%88-%E7%B7%8F%E5%90%88%E7%89%88-%E4%B8%96%E7%95%8C%E6%A8%99%E6%BA%96MIT%E6%95%99%E7%A7%91%E6%9B%B8-%E3%82%B3%E3%83%AB%E3%83%A1%E3%83%B3/dp/476490408X/ref=pd_sbs_14_7?_encoding=UTF8&pd_rd_i=476490408X&pd_rd_r=aa75a9b3-c6d0-41a9-bdad-73d5a4d6c3f0&pd_rd_w=adVKT&pd_rd_wg=mw2lf&pf_rd_p=ad2ea29d-ea11-483c-9db2-6b5875bb9b73&pf_rd_r=0KCRMBPM51ZSJBSDD8KA&psc=1&refRID=0KCRMBPM51ZSJBSDD8KA)
[Rails] devise_token_auth 導入エラー対処

# 環境

* Rails 5.2.3
* Ruby 2.6.3
* devise_token_auth 1.1.1

# 概要

* 公式のgemからインストール。
* `gem 'devise_token_auth'`→`bundle install`にて。
* 別途deviseは入れていない。

最新の(書いている時点で)gemをデフォルトの状態で動かすため、下記、公式説明の通りに、コンティグレーションを実行した。

https://devise-token-auth.gitbook.io/devise-token-auth/

その際に、なぜかエラーがでてしまった部分の解決を記載する。

# User modelの修正

下記エラーが出る。

*NoMethodError: undefined method `devise' for User*

下記のように、`extend Devise::Models`を追加する。

参考) https://github.com/lynndylanhurley/devise_token_auth/issues/1276#issuecomment-478866479

```Ruby:app/models/user.rb
class User < ActiveRecord::Base
  extend Devise::Models
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  include DeviseTokenAuth::Concerns::User
end
```

# migrationファイルの修正

下記エラーが出る。

*NoMethodError (undefined method `current_sign_in_at'*

migrationファイルのUserに、下記のように、`trackable`の追加の必要がある。

※または、上記User modelの`:trackable`削除。

```ruby:2019mmddhhmmss_devise_token_auth_create_users.rb
  ## Tokens
  t.text :tokens

  ## Trackable
  t.integer  :sign_in_count, default: 0, null: false
  t.datetime :current_sign_in_at
  t.datetime :last_sign_in_at
  t.string  :current_sign_in_ip
  t.string  :last_sign_in_ip

  t.timestamps
end
```
WinActorでフォルダにまとめたWordファイルを一括で文字列置換する

#はじめに
前回に引き続き初心者向けの記事を書いていきます。

今回は簡単に**フォルダ内のWordファイルに含まれた特定の文字列を一括で置換する**シナリオです。

そろそろ消費税増税の頃ですし、社内でも一括で変更出来るようにしてほしい、という依頼があったため作成しました。

#要件
- 消費税額が8％と記載されているWordファイルを10％に一括で書き換えたい

- 置換前のファイルも残しておきたいため、変更前フォルダと変更後フォルダを用意し、変更したファイルは上書き保存せずに変更後フォルダに保存をする

- 半角全角が混じっている可能性があるので、どちらで入力されていても置換させる

- 動作出来る数に上限をつけ、ファイル数が既定の数を超えたらアラートを表示する

#内容
![コメント 2019-09-03 113437.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375914/fdeb8c66-5f1e-71bb-1e8e-94aede4222b8.png)

![Inkedコメント 2019-09-01 120830_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375914/1ed37377-186d-fd97-970d-a339b25fbe7f.jpeg)


上のフローチャートを流れをざっと説明すると、

1. 「変更前」フォルダ内のファイル数を取得し（ファイル数が101以上であればメッセージを表示して停止）
2. 「変更前」フォルダ内のファイル名を上から順番に読み取って
3. Word内の文字列を「8％」→「10％」に置換する
4. 名前を付けて保存（保存先は「変更後」フォルダになっている）
5. 上記を2.から、1.で取得したファイル数回だけ繰り返す

という機能です。

- ファイルの保存先変更は変数「fname」から変数「Change」に一度値を渡して、「Change」内のファイルパスの「変更前」部分を「変更後」に置換して行っています（変数「fname」を残しておく理由は元ファイルのファイルパスを名前をつけて保存の工程でWinActor側に要求されてるため）。

- Word内の文字列置換（画像の「検索した文字列を置換……」の部分）はライブラリが用意されていなかったのでユーザーフォーラムに投稿されていたスクリプト探究者様の**[【ユーザーライブラリ】Word文字列一括置換方法](https://winactor.com/questions/question/【ユーザーライブラリ】word文字列一括置換方法/)**をお借りしました。
**全角と半角の区別**をFalseにして区別させずにすべて置換出来るようにして使っています。

- ファイル＜101とありますが、101は上限のファイル数です。この数は各々PCのスペックに合わせて上限を変更してください（前に別なシナリオ作成した時にデータ数が多すぎて途中から処理が追い付かなくて失敗した事があったので、少なめで設定して始めています）。

#まとめ
かなり簡易的な作りなのであんまり書くことないですが、こんな感じで100件5分47秒程度で置換完了します。
導入したてで難しい事は出来ないけどなにか役に立った成果を残しておきたい！そんな時にいかがでしょうか？（愚）

最初は配列を使って一気にファイル名を取得してから文字列置換をしていこうと思っていたのですがうまくいかなかったのでWinActor配列マスターの人は教えてほしいです……:pray::sob::pray:
【Rails】初心者の為の部分テンプレートの使い方

#部分テンプレートとは
部分テンプレートはenderメソッドを使うことで指定でき、重複するHTMLの記述部分を文字通りテンプレ化する事で、共通化して綺麗にまとめる事が出来ます。

部分テンプレートを上手く使えば、コードを綺麗にまとめる事が出来るのは勿論のこと、修正するときも楽になりますし、コードを描くにあたって必須になってきますので、今のうちに基礎を抑えておきましょう。


##部分テンプレート内で変数を使う
まず、partialで部分テンプレートのファイルを指定します。この時ディレクトリの位置と、ファイル名に注意してください(※部分テンプレートのファイル名は_から始めます）。
例えば、tweets/index.html.haml内で、shared/_item.html.hamlを指定したいときは、このように書きます。

```index.html.haml
= render partial: 'shared/item', locals: {items:@items, word: 'レディース' }
```
大抵の場合controllerで指定したインスタンス変数を部分テンプレート先で使用したい事が多いです。
この時、localsを使用します。

```index.html.haml
= render partial: 'item', locals: { '指定先で使いたい変数名':'持っていく変数名' }
```
partialは省略することも可能ですが、上記のように変数を指定するときは省略は出来ません。

##部分テンプレート内でeach処理をする
each文で、＠itemsを一つずつ取り出したいとき、部分テンプレート先でeach文を使うことももちろん出来ますが、collectionオプションを使って複数形の変数を渡すと、部分テンプレート先でeach文を使用せずに繰り返し処理をしてくれるので便利です。
更に、＠itemsを、_item.html.haml内で、itemとして繰り返し処理したい時にpartialもcollectioinも省略して、render ＠itemsだけにする事ができます。

つまり、

```index.html.haml
- @items.each do |item|
  = render partial: 'item', locals: { item: item }
```
⬆️これを

```index.html.haml
= render partial: 'item', collection: @items
```
⬆︎こうして

```index.html.haml
= render @items
```

こうできます！

だいぶスッキリしましたね〜！
algolia 更新が反映されなかった

##ハマったところ
クライアント側でalgoliaデータを更新したときに、検索をし直しても、
algolia側ではデータが更新されてるにも関わらず、検索結果が更新前のデータのものであり、
毎回リロードをしないと更新後のデータが表示されなかった。

##ダメだった例
```javascript
const algoliasearch = require('algoliasearch')
const REACT_APP_ALGOLIA_ID = "YOUR_REACT_APP_ALGOLIA_ID"
const REACT_APP_ADMIN_API_KEY = "YOUR_REACT_APP_ADMIN_API_KEY"
const client = algoliasearch(REACT_APP_ALGOLIA_ID, REACT_APP_ADMIN_API_KEY)
const index = client.initIndex('body_search')

class Search extends Component {

    constructor(props) {
      super(props);
      this.onSearch = this.onSearch.bind(this)
    }

  async onSearch() {
    let search_results
    await index
      .search({
        query: '',
      })
      .then(function (responses) {
        search_results = responses.hits
      })
      .catch(function (error) {
        console.log(error)
      }) 

      // グローバルstateのstate.search_resultsにセットするreduxのaction
      this.props.searchFinish(search_results)
  }

  render() {
    return (
      <div>
        <button onClick={this.onSearch}>検索する</button>
        {this.props.search_results.map(search_result => {
            return (
              <Result result={result} />
            )
        })}
      </div>
    )
  }
}



```

##うまくいった例
```javascript
const algoliasearch = require('algoliasearch')
const REACT_APP_ALGOLIA_ID = "YOUR_REACT_APP_ALGOLIA_ID"
const REACT_APP_ADMIN_API_KEY = "YOUR_REACT_APP_ADMIN_API_KEY"
const client = algoliasearch(REACT_APP_ALGOLIA_ID, REACT_APP_ADMIN_API_KEY)

class Search extends Component {

    constructor(props) {
      super(props);
      this.onSearch = this.onSearch.bind(this)
    }

  async onSearch() {
    const index = client.initIndex('body_search')
    let search_results
    await index
      .search({
        query: '',
      })
      .then(function (responses) {
        search_results = responses.hits
      })
      .catch(function (error) {
        console.log(error)
      }) 

      // グローバルstateのstate.search_resultsにセットするreduxのaction
      this.props.searchFinish(search_results)
  }

  render() {
    return (
      <div>
        <button onClick={this.onSearch}>検索する</button>
        {this.props.search_results.map(search_result => {
            return (
              <Result result={result} />
            )
        })}
      </div>
    )
  }
}

```

言われてみればあたり前のことでしたが、毎回indexを初期化してから検索をしないと、algolia側で見たときにデータが変わっていても、検索結果は更新前のデータが出てきます＞＜
どなたかの参考になれば幸いです。
【Docker】Dockerメモ

Dockerについて自分用のメモ
## Dockerとは

**Docker**は、**コンテナ**と呼ばれる隔離された環境でアプリケーションを実行するためのプラットフォーム。

Dockerを使用することでアプリケーションを**コンテナ化**して実行したり、**コンテナ化**したアプリケーションを開発者間で共有できたりする。

初期のDockerはコンテナを実行するための「※ランタイム」としての機能が中心だったが、現在ではコンテナを使ったアプリケーションの開発から実行までをサポートするさまざまな機能を持つプラットフォームとなっている。

※ ランタイム：プログラムを動かすときに必要な部品



## コンテナとは

**コンテナ**とは、システムから隔離された環境で起動される一連のプロセスの呼称である。隔離された環境の中に起動されるプロセスは、その環境の外にあるシステムには基本的に、アクセスできない。

隔離された環境の中でプロセスを実行するのに必要となるCPUやメモリ、ネットワークインターフェースなどは、そのプロセス専用のリソースとして割り当てられる。

**Docker**が**コンテナ**として実行するアプリケーションは「**コンテナイメージ**」で管理される。これはある時点のファイルシステムの状態を保存したスナップショットのようなものである。

**コンテナイメージ**にはアプリケーション本体のファイルと、アプリケーションの実行に必要なライブラリなどの依存ファイルのすべてが保存されており、これをひとつの単位としてコピーや実行ができる。

**Dockerがコンテナを実行するまでの流れ**

1. DockerはOSの機能を利用してアプリケーションを実行するための隔離された環境を作り出す。
2. コンテナイメージからアプリケーションの実行に必要なバイナリやライブラリなどのファイルを取り出し、隔離された環境にそれらを展開する。
3. 展開したファイルを使用して隔離された環境の中でアプリケーションのプロセスを起動する。



## Dockerの構成

**Docker**は以下のようなクライアント／サーバの構成になっている。

CLIはDocker Daemonに命令を送信し、Docker Daemonは送られてきた命令に従ってコンテナの実行などを管理する。Docker Daemonはコンテナを起動するために必要なコンテナイメージも管理する。

コンテナの起動に必要なコンテナイメージがローカルに存在しない場合は、Docker Daemonは外部のDocker Registryからコンテナイメージを取得する。
![Docker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481315/99211025-786d-6d6b-fbac-6d150d576577.png)

## Dockerとコンテナのメリット

Dockerを利用することで、アプリケーションとその実行に必要なライブラリなどの依存ファイルを1つの標準化されたユニットであるコンテナイメージとして管理できる。コンテナイメージからコンテナを起動すれば、DockerがサポートするLinuxやWindowsなどの環境に加え、AWSをはじめとする主要なクラウドプロパイダでもアプリケーションが実行できる。

つまり、開発環境で動作したアプリケーションがテスト環境や本番環境でも同じ方法で実行できることを意味する。これによりアプリケーションのテストやデバックが容易になるだけでなく、素早いデプロイやロールバックも可能になる。
宗教論争との付き合い方

世の中には終わらない論争がある。それらは「宗教論争」と比喩される。プログラマに馴染深いのは[エディタ戦争](https://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF%E6%88%A6%E4%BA%89)だろう。

>エディタ戦争（Editor War）とは、プログラミングを行う人々（特にハッカー文化に属する人々）の間で続いている、どのテキストエディタが一番よいかというテーマの論争を指す。その中でも二大陣営といえるのは、vi愛好派とEmacs愛好派である。

この記事では、実は日常で散見される宗教論争への付き合い方を考察する。忘れないでいただきたいのは、この記事も宗教論争となりえることである。

# この記事で一番言いたいこと
- 宗教論争の仕組みを理解し、すばやく認識し、極力避ける（終わらせる）ことで時間を節約しよう
 
# 宗教論争は何故起きるのか

論争はステークホルダの`正解`に齟齬がある場合に、それを統一するためのプロセスである。

`正解`を統一する（認識を合わせる）ことは非常に重要なプロセスなので論争自体は大切なプロセスである。しかし、一部の宗教論争と呼ばれる終わらない論争に関しては、付き合い方を考えた方が良い。

なかなか終わらない理由は

```
各自の正解（条件・要件・制約）をなかなか曲げられない
```

からだと思う。

例えばグループでレストランに行った時に、

- たばこを絶対吸いたいから喫煙席にしたい人
- たばこの煙を絶対吸いたくないから禁煙席にしたい人

がいたら、席は決まらないだろう。宗教論争の本質的な原因は上記のようなそれぞれの`正解`（条件・要件・制約）が曲げられないことに由来するのではないだろうか。

# 宗教論争かを見極める

宗教論争かを見極めるためには、上記の構造になっていないかを検討してみれば良い。食い違っている`正解`は何かを明確にして、その`正解`をそれぞれが曲げられない感じだったら、それは宗教論争だ。

しかし、実践は難しい。例えば先ほどの席を決める例で言えば、禁煙・喫煙の論点に着目して宗教論争かどうかを見極められるが、実際には下記のように論争は始まる。

- 席Aは日当たりもいいし、ドリンクバーも近いし、喫煙できるし、トイレも近い
- 席Bは個室だし、禁煙だし、景色がいい

多くの論点の中で、各自が曲げられない`正解`が異なっている論点を見極めることが求められる。これができず、宗教論争と気づかずに議論を続けることがよくある。

# 宗教論争は避ける（終わらせる）
それぞれの答えを持つことは悪いことではないし、当たり前のことだ。その上で認識を統一しようとしているのだから宗教論争は必ず発生する。発生した際には、宗教論争であることを認識し、いつもの論争とは異なるアプローチで付き合うことが必要だと思う。このアプローチには例えば以下のようなものがあげられるだろう。

## 受け入れる

- 相手の`正解`を無理やり自分の`正解`にする
- 受け入れること・論争を続けることによるメリデリの整理は必要
    - 場合によるが、私の経験上では受け入れて終わりにした方が時間を節約し、有効活用できたことが多い

## 受け入れてもらう
- ステークホルダ全員に宗教論争であることを認識をさせ、`正解`を統一するためのルールを決める
- ルールは色々で、多数決でも、偉い人の`正解`で統一でもいい


# まとめ
- 世の中には終わらない論争（宗教論争と比喩される）がある
- 宗教論争の構造を理解する
- 論争が宗教論争かを見極める
- 宗教論争は避けて（終わらせて）、時間を節約しよう
openssl pkeyutlでメッセージダイジェストからの電子署名

OpenSSLは便利ですが
どうも使い方が分かりにくいと思うことがあります。

# 前提

とりあえずこんな感じで秘密鍵と公開鍵を作ったとしましょう。
> openssl genrsa 2048 > private.pem
> openssl rsa -pubout < private.pem > public.pem

# たぶん普通のやり方（でもちょっと変？）

sample.txtを署名して検証するならこんな感じでしょう。
> openssl dgst -sha256 -sign private.pem sample.txt > sample.sig
> openssl dgst -sha256 -verify public.pem -signature sample.sig sample.txt 

でもdgstで署名までするの？！という気もします。

# ダイジェストを作ってからpkeyutlで署名

ダイジェストを作るだけならこんな感じで
> openssl dgst -sha256 -binary sample.txt > sample.dgst

それを使って署名するならこうです。

> openssl pkeyutl -sign -inkey private.pem -pkeyopt digest:sha256 < sample.dgst > sample.sig

# 余談（rsautlで署名）

rsautlにも-signがありますがハッシュアルゴリズムを渡す方法が見つかりません。
オブジェクト指向について初心者が説明します

#オブジェクト指向がわからん

初心者はオブジェクト指向を理解する必要がある！
とか言われて色々調べたけど…

「モノとして考えるんだよ」とか

「現実世界と同じように考えるんだよ」とか

「愛とか国家と同じ"概念"の話なんだよ」とか・・・

**んー、わかるようで全くわからん！！**


ってことで、初心者からの視点でわかりやすく解説してみようと思います。

#オブジェクト指向の目的

概念をいくら説明されてもいまいちイメージが掴めないので、
そもそも**オブジェクト指向って何のためにあるの**ってことが大事だと思いました。

それはズバリ<font color="Red">**「開発を効率化すること」**</font>です。

かつては、開発する際に

- バグが多数発生
- どこに何が書いてあるかわからない
- 仕様変更に大きな時間がかかる

などなど。。技術者の能力では解決できない事態となっていたそうです。
そこで、先人は「もう、仕組みで解決するしかない」と考え、

- 構造化プログラミング
- モジュラプログラミング

などの様々な試行錯誤を繰り返し、その中で生まれたのが**「オブジェクト指向」**です。
これによって大規模開発も効率的に進めることができるようになったんですね。

#オブジェクト指向の３原則

「開発を効率化するためにオブジェクト指向が必要」ということがわかりました。
じゃあ具体的に何するのか？？ということですが、まずは**３原則**が大事だと言われています。

①カプセル化:プログラムごとの独立性を高める
②継承 :再利用性を高める
③ポリモーフィズム :コードの拡張性を高める

巷でよく言われる、

**オブジェクト指向とはプログラムを手順ではなくて、『モノの作成と操作として見る考え方』だ。**

とは、つまりこれら３原則を備え持ったプログラムの捉え方ということですね。
これらを実際にプログラムに反映させるために「クラス」や「インスタンス」「メソッド」が出てくる訳ですが、これは別で整理したいと思います。


#この記事を読んだ方へ
本記事は、プログラミング初心者がインプットも兼ねてまとめたのです。もし間違い等がございましたらご指摘いただけると幸いです。
Twitterの自作サイトへの埋め込み方について

自作サイトにTwitterを組み込んでみました。
TwitterAPIを用いなくても、自身のアカウントを表示させられます。


# HTML
[こちらのサイト](https://publish.twitter.com/#)にて、アカウント名を打ち込みます。
次に表示させたい形式を選択すると、コードが表示されるので、コピーします。
TwitterAPIだと、英語で取得したい理由などを書かないといけないので少し面倒ですが、こちらではアカウント名を打ち込むだけなので簡単です。



```sns.html
<h2 id="sns">SNS</h2>
<a class="twitter-timeline" href="https://twitter.com/"アカウント名"ref_src=twsrc%5Etfw"
data-tweet-limit="2"data-height="400" data-width="280">Tweets by アカウント名</a>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

```
HTMLの埋め込みたい場所にコードを貼りつけます。(href以降がコピー)
あとはdata-tweet-limit（何個のツイートを表示するか）やdate-height（高さ）、data-width（幅）といった細かな部分を調節していけば完成です。


# CSS
```sns.css
.twitter-timeline {
    height: 200px;
    width: 100px;
}
```
サイトに合うようにCSSでサイズ調整をしています。

# まとめ
基本コピペで済むので非常に簡単でした。
次はTwitter以外のSNSの埋め込み方も調べてみたいと思います。
Hyper+bobthefish (powerline) でフォントがズレた時のメモ＜Ubuntu 18.04＞

# powerlineが使いたかった

[![Image from Gyazo](https://i.gyazo.com/56ce1e700819c85525277c8d6a2c4b51.png)](https://gyazo.com/56ce1e700819c85525277c8d6a2c4b51)

## Hyper+Ubuntuの固有問題

みなさんも毎週末には環境構築を楽しんでいることでしょう。私も、今週はUbuntu 18.04なんてモダンなデスクトップ環境を構築し、「新しいターミナルやシェルを試してみよう」と思い立ったのです。

そんな私に訪れた不幸が冒頭の画像。流行りのElectron製ターミナル[Hyper](https://github.com/zeit/hyper.git)（ver 3.0.2）を入れ、シェルを[fish](https://fishshell.com/)にして、勢いにまかせて[oh-my-fish/theme-bobthefish](https://github.com/oh-my-fish/theme-bobthefish.git)を入れたところ、謎の隙間が現れました。

■塗りつぶしテキストに▶を重ねて表示しているだけなんですよね、Powerline。だから環境によってはずれちゃう。

「よーし、おじさんbug fixしちゃうぞー」

などとテンションを上げて挑もうとしたところ、開発機の**macOSでは隙間が現れない**。英語で検索しても情報が出てこない。半分あきらめていましたが、なぜか解決しました。メモがわりに残しておきます。

### 環境

OS: Ubuntu 18.04.3 LTS
Hyper: 3.0.2
fish : 3.0.2
fisher : 3.2.9

## 解決

変更したのはhyperの設定ファイル（$HOME/.hyper.js）の１行だけ

これを

```:.hyper.js
    backgroundColor: '#000',
```

こうする

```:.hyper.js
    backgroundColor: 'rgba(0,0,0,0.99)',
```

するとこうなる

[![Image from Gyazo](https://i.gyazo.com/bba54bdadb3511cc2d25144845cc8f7e.png)](https://gyazo.com/bba54bdadb3511cc2d25144845cc8f7e)


### 予想

rgba(0,0,0,1)にしたら隙間でてきちゃった。
プロンプトの表示位置の指定に、透明度を使って計算する処理があるのではないかと思います。透明度を少数型にしておかないと、どこかで1px計算がずれるのだと思う。ubutu（あるいはgnome系linux）の固有問題っぽい。

### おまけ

画像の設定値など

```sh:config.fish
# fishのキーバインドをvi風に
fish_vi_key_bindings
# プロンプトにviのモードを表記
set -g theme_display_vi yes

# 日付を表示
set -g theme_display_date yes
set -g theme_date_format "+%F %H:%M"

# 実は使っているフォントはpowerlineではなくnerd
set -g theme_powerline_fonts no
set -g theme_nerd_fonts yes

# masterでもブランチ名を表示
set -g theme_display_git_master_branch yes

# コマンドの実行時間を表示
set -g theme_display_cmd_duration yes

# shellのタイトルバー表示をカスタマイズ
set -g theme_title_display_user no
set -g theme_title_display_process yes
set -g theme_title_display_path no

# exitステータスを表示
set -g theme_show_exit_status yes

# ■▶の色テーマを設定
set -g theme_color_scheme dracula

# カーソルは■▶の次の行。プロンプトの頭は$。ディレクトリ名は省略表示しない（0）
set -g theme_newline_cursor yes
set -g theme_newline_prompt '$ '
set -g fish_prompt_pwd_dir_length 0
```

.hyper.jsはフォントとbackgroundColor以外は初期値

```:.hyper.js
    fontFamily: '"mononoki Nerd Font Mono", Menlo, "DejaVu Sans Mono", Consolas, "Lucida Console", monospace',
```
" ディレクトリ名 C:\Users\$(user名)COMPLUS_Version=\ が無効です"

#環境
Windows10,VisualStudio2017,ASP.NET Core
#追記
###2019/09/01
IISで実行しようとすると起きるので、私のIISの設定ミスとかが原因と思われます。
さきほどIISではなくプロジェクトのプロセスでアプリケーションをホストさせたところ、
エラーメッセージも出ず、通常通り動作しました。
(下の画像でいうと、「IIS Express」となっているところをプロジェクト名(今回の場合は「Trial_DependencyInjection」)を選択して実行すると動作しました。)
![c.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246006/776e7a10-0af1-ffee-4f61-0ef99b3b10f2.jpeg)


#問題

![a.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246006/fa96ad5f-a2af-507b-e059-255f89d6fba3.jpeg)

ASP.Netの新規プロジェクトでタイトル通りのエラーが発生し、
Webアプリケーションが動作せず、立ち上がったブラウザには以下のようなメッセージが表示されるだけです。

![b.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246006/712fee7f-56e7-c627-294a-0d9d1e5582f5.jpeg)

#対症療法
一応、現時点で対症療法のようなものとしてうまくいったものがあります。
1.プロジェクトのプロパティを開く。
2.「アプリケーション」から「ターゲットフレームワーク」の、「.NET Core2.2」となっているところをどれでもいいので(たとえば「.NET Core2.1」に)変更し保存する。
3.リビルドする。
4.ビルドエラーが出る。
5.「ターゲットフレームワーク」を「.NET Core2.2」に戻す。
6.リビルドする。
エラーは相変わらず出るものの、それを「続行」やら「終了」を押して無視しても、
Webアプリケーションは動作するようになります。

#今後
根本的な問題が解決されていなければこの先原因不明のエラーに悩まされかねません。
今後、少しずつ調べていきます。それについては投稿するかわかりません。
【okadash】Electronで Mac / Win 向けの爆捗りダッシュボードツールを作った話（跡地）


## 機能追加に伴い、構成の整理のために記事を新規作成しました。
### 最新の記事は以下になります。

- [【okadash】Electron で Mac / Win 向けの爆捗りダッシュボードツールを作り、アップデートした話 | Qiita](https://qiita.com/okadato623/items/cf78f7d738004519c800)
グレー画像のヒストグラムを取得

# 概要
グレースケール画像のヒストグラムを取得する方法を書きます。

### numpyの関数histogramを使う方法
画像の読み込みにはopenCVを使ってます。
グレースケールで読み込むので、cv2.imreadの第二引数に"0"を書きます。

np.histogram(配列, bins)で、binごとの要素数とbin(階級)の境界の値を配列で返します。
以下のコードでは、それらをそれぞれimg_hist, img_binsに格納しています。

np.histogramに与える配列は、今回はグレースケール画像（2次元）なので、flatten()で1次元配列に変換しています。

最後に、matplotlibでヒストグラムの描画をしています。


```python:
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 画像の読み込み
img = cv2.imread("Lena.jpg", 0)

# ヒストグラムの取得
img_hist, img_bins = np.histogram(np.array(img).flatten(), bins=np.arange(256+1))

# ヒストグラムの表示
plt.plot(img_hist)
plt.show()
```



### OpenCVのcalcHistを使う方法

ヒストグラム取得の部分のみが上のnumpyの例と異なります。
cv2.calcHist(image, channel, mask, histsize, range)

channelはヒストグラムを計算する画像のチャンネル
　　：グレースケールであれば[0]
　　：カラー画像であればB, G, Rに相当する[0], [1], [2]を指定
maskは画像中の全画素のヒストグラムを計算する場合はNone
histsizeはbin（階級）の数。
rangeはヒストグラムを計算したい画素値の範囲。通常は[0, 256]を指定

```python:
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 画像の読み込み
img = cv2.imread("Lena.jpg", 0)

# ヒストグラムの取得
img_hist_cv = cv2.calcHist([img], [0], None, [256], [0, 256])

# ヒストグラムの表示
plt.plot(img_hist_cv)
plt.show()
```
+使用した画像
![lena_gray.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339647/3df2cc7f-33a8-c42c-017a-2f1fb763d8e4.jpeg)




+得られたヒストグラム
![ヒストグラム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339647/90f673a5-d69f-5a30-6d1e-07fa64567136.png)



## まとめ
numpyの関数histogramとopencvのcalcHistを使う二種類の方法でヒストグラムを取得。
単に画像全体のヒストグラムを取るだけならnumpyでやったほうが簡単な印象
[Spring Boot Actuator] 独自のヘルスチェック処理をマニュアル登録する方法

Spring Boot Actuatorには、インスタンス自体やインスタンス内で依存している外部リソース（ディスク、DB、メッセージングサービス、キャッシュサービスなど）の稼動状態（ヘルスチェック結果）を提供するエンドポイント(`/actuator/health`, `/actuator/health/{name}`)があり、独自のヘルスチェック状態を提供することもできます。

# 独自のヘルスチェック処理を自動登録する方法

Spring Bootのリファレンスにサンプルコード付きで紹介されていますが、`HealthIndicator`インタフェースを実装したクラスをDIコンテナに登録すると、Spring Boot Actuatorが自動で検出してくれます。

```java
@Component // コンポーネントスキャンでDIコンテナに登録
public class MyHealthIndicator implements HealthIndicator {
  @Override
  public Health health() {
    return checkWeatherAvailable() ? Health.up().build(): Health.down().build();
  }
  private boolean checkWeatherAvailable() {
    boolean result = false;
    // 死活監視処理
    // ...
    return result;
  }
}
```

# 独自のヘルスチェック処理をマニュアル登録する方法

Spring Boot Actuatorはヘルスチェック処理を行うオブジェクトは`HealthIndicatorRegistry`で管理しており、DIコンテナから取得した`HealthIndicatorRegistry`を介して独自のヘルスチェック処理をマニュアルで登録することもできます。
例えば、ヘルスチェック処理の対象が設定値によって変えたい（増減させたい）場合は、マニュアル登録の仕組みが使えると思います。

```java
@Configuration
public class MyConfiguration {
  // ...
  @Autowired
  void addExternalServiceHealthIndicators(HealthIndicatorRegistry registry, MyProperties properties) {
    properties.getExternalServices().stream().filter(s -> StringUtils.hasText(s.getHealthCheckUrl()))
        .forEach(s -> registry.register(s.getName(), new UrlBasedHealthIndicator(s.getHealthCheckUrl())));
  }
}
```
```java
public class UrlBasedHealthIndicator implements HealthIndicator {
  private final String url;
  public UrlBasedHealthIndicator(String url) {
    this.url = url;
  }
  @Override
  public Health health() {
    return checkWeatherAvailable() ? Health.up().build(): Health.down().build();
  }
  private boolean checkWeatherAvailable() {
    boolean result = false;
    // 死活監視処理
    // ...
    return result;
  }
}
```

# まとめ

現在携わっている案件では商用アプリとしてはSpring Bootは使っていないのですが、外部システムのシミュレータ（テストでの利用がメインですが・・・商用環境でも内部管理向けに使用するシミュレータ）をSpring Bootで作成しており、シミュレータ内で扱うリソースの稼動状態を設定値によって増減できる仕組みにしたいな〜と思い実現方法を調べてみました。

# 参考サイト

* https://docs.spring.io/spring-boot/docs/2.1.7.RELEASE/reference/html/production-ready-endpoints.html#_writing_custom_healthindicators
Googleの検索結果から、日本語のページを対象外にするブックマークレット

## 英語のみでググりたい

技術系のことをググるとき、検索対象を英語のみにしたい(というか、日本語ページを除外したい)場合が多い

検索結果画面の「ツール」のところからだと

- すべての言語
- 日本語のみ

の2つしか選べない。

![検索結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45034/48236c63-1e04-b3c9-780e-cfe4b131174f.png)

ということで、「日本語ページ以外」の検索結果にさくっと切り替えられるブックマークレットを作った

こちら

```
javascript:location.href+='&lr=-lang_ja'
```

検索結果画面でこのブックマークレットを呼び出すと、検索結果が「日本語ページを除外したもの」になる

技術系のことをググるときなどにたぶん便利

## やっていること

雑に、クエリパラメタの末尾に `lr=-lang_ja` をつけているだけ

`lr=lang_ja` だと日本語のみが対象、値の前に `-` をつけることで日本語が除外対象になる

## 続き

押すたびに、検索結果を「日本語除外」←→「日本語のみ対象」に切り替えるブックマークレットも作った

そちらはブログに載せています

<https://matsuoshi.hatenablog.com/entry/2019/09/06/000000>
イノベーター理論とペルソナの考察

自社サービスの普及についてあれこれ考えたことを[イノベーター理論](https://www.jmrlsi.co.jp/knowledge/yougo/my02/my0219.html)を交えてまとめてみる。

|分類|サービスへの関心度|特徴|想定されるシナリオ|
|---|---|---|---|
|イノベーター|なし？|サービス自体に関心は無いが、新しいもの・自分が知らないものは試してみたい。|ニュースリリース、店内告知等を見て使い始める。|
|アーリーアダプター|高い|サービスを心から欲している。|検索等、自らサービスを探し、使い始める。|
|アーリーマジョリティ|それなり|サービスがあれば使いたいと考えているが、自ら探すほどではない。|広告・口コミ等でサービスの存在を知れば使い始める。|
|レイトマジョリティ・ラガード|低い|広告等を見ても基本スルーだが、サービスが必要ないわけではない。|キャッシュバック等のキャンペーンがきっかけで使い始めることもある。|

[リンク先](https://www.jmrlsi.co.jp/knowledge/yougo/my02/my0219.html)に『「アーリーアダプター」を狙う』とあるが、新しいサービスを企画する場合に設定するペルソナはアーリーアダプターのものであるべき、というのはしっくり来る。
しかし、ターゲットを見誤らないよう、また深く理解するためにはペルソナは複数、かつ他アーリーマジョリティ等のペルソナも設定すべきではないだろうか？そうしないと、「本サービスのターゲットは30～40代の女性です（ﾄﾞﾔｯ」（30～40代の女性と言っても未婚/既婚、専業主婦/共働き、子の有無・年齢で全然違うだろ）となりかねない。あ、これはそもそもペルソナを設定していないという話か・・・
[Rails] Grape をとにかく動かす 必要最小限 モジュール パス説明

# Rails 環境

* Rails 6.0.0(5.2系でも同様。**5.1系以下は要注意**。後述。)
* Ruby 2.6.4
* Grape 1.2.4

# モジュール・パスのルールがよくわからない?

Grapeの導入に関する情報は多いのですが、にもかかわらず、モジュール パスにまつわる問題に祟られて、初手から少しのサンプルコードすら動作しないことがあります。

特に、 **モジュール名やパスをいきなり思い通りに設定しようとした場合**、よく、`Uninitialized constant` エラーが出たりします。

https://stackoverflow.com/questions/24833131/why-does-mounting-a-route-in-rails-fail-with-uninitialized-constant-api

>Place API files into app/api. Rails expects a subdirectory that matches the name of the Ruby module and a file name that matches the name of the class. In our example, the file name location and directory for Twitter::API should be app/api/twitter/api.rb.

grape公式文書の記述ですが、要は`app/api`がロードの固定的なベースになり、それ以下にあるファイル名とクラス名、ディレクトリ名とモジュール名がマッチしないといけない。例えば、`Twitter::API`は、 `app/api/twitter/api.rb` 固定。(`app/api`部は強制なので、ありがちな`API::V1`などは、`app/api/api/v1`とか**apiがダブった変なパス**に入れざるを得ない)。

さらに、Railsのバージョン(5.1.x以下 or 5.2.x以上)によって、Grapeとして必要な初期設定や前提が異なることも、問題を複雑化させているようです。(最後に書きます)

ここでは、**不必要なものは取り除いて、階層構造もあえて最小限**にします。とにかくも、動くようにします。一度動いてしまえば、あとは各種情報を参考に、トライアンドエラーで、モジュール階層やパスを自分で追加できるはずです。

# 設定の手順

※以降、RailsのAPIモード(`rails new --api `)で作成したプロジェクトを対象にしています。

```bash:
bundle exec rails --version
Rails 5.2.x
```

Railsバージョンに注意してください。5.1.x以前、6.x.xでも最近のものは、最後の参考情報を見てください。

Gemfileに下記を追加。

```ruby:Gemfile
gem 'grape'
```

`bundle install --path vendor/bundle`します。

下記のファイルを作成、または編集します。

```ruby:config/routes.rb
Rails.application.routes.draw do
  mount Api => '/api'
end
```

```ruby:app/api/api.rb
class Api < Grape::API
  mount V1::Root
end
```

```ruby:app/api/v1/root.rb
module V1
  class Root < Grape::API
    format :json
    #version 'v1'
    version 'v1b'
    get '/' do
      { hello: 'world' }
    end
  end
end
```
# 確認

`bundle exec rails s`でサーバを起動し、
ブラウザで`http://localhost:3000/api/v1b`を見ます。

```json:ブラウザ表示
{"hello":"world"}
```

# 補足 

## Rails 5.1系以下

追加設定が必要なようです。
https://github.com/ruby-grape/grape#rails

```ruby:config/application.rb
config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]
```

*※上記定義のパス部分を独自に改変している例が散見されますが、互換性がなくなるので、詳しい人以外、やめたほうがいいような気はします。*

## Rails 6.0.0.beta2以降

'API'という識別子の利用のさい問題があり、下記の定義の追加が必要といった記述もみられるので、事の次第によっては、今後もフォローが必要かもしれません。

```ruby:config/initializers/inflections.rbの最後
ActiveSupport::Inflector.inflections(:en) do |inflect|
  inflect.acronym 'API'
end
```

本例では、上記不要なはずですが、ダメな場合ご確認ください。

# 参考

* Grape でAPIを作るときにハマったこと
https://qiita.com/emahiro/items/6b65b2bfe6878a63b3c0

以　上。