OmniAICreator/Qiita-1.07M huggingface dataset:
MinIOで簡単AWS S3のテスト

# はじめに

AWS S3のテストをしたいときに、[MinIO](https://github.com/minio/minio#minio-quickstart-guide)を使って、ローカルにS3のモックを建てる方法を紹介します。

## MinIOサーバーの起動

MinIOは、下記を実行するだけで（インストールせずに）利用できます。

```bash
docker run -d -p 9000:9000 --name minio -v $PWD/data:/data \
  -e "MINIO_ACCESS_KEY=AKIA0123456789ABCDEF" \
  -e "MINIO_SECRET_KEY=0123456789/abcdefghi/ABCDEFGHI0123456789" \
  minio/minio server /data
```

- `MINIO_ACCESS_KEY`と`MINIO_SECRET_KEY`は20文字と40文字で適宜変更してください。
- `http://127.0.0.1:9000`でブラウザで管理できます。
- S3の内容はカレントディレクトリの`data`に作成されます。

## 環境変数によるboto3のサンプル

### 準備

```py
import os
import boto3

bucket_name = 'sample'  # バケット名
use_minio = True  # MinIOを使うかどうか
os.environ['AWS_ACCESS_KEY_ID'] = 'AKIA0123456789ABCDEF'
os.environ['AWS_SECRET_ACCESS_KEY'] = '0123456789/abcdefghi/ABCDEFGHI0123456789'
```

環境変数`AWS_ACCESS_KEY_ID`と`AWS_SECRET_ACCESS_KEY`にdockerで指定したものが入っているとします。

### バケットの作成

```py
kwargs = dict(
    region_name="ap-northeast-1",
    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
)

if use_minio:
    kwargs["endpoint_url"] = "http://127.0.0.1:9000"

bucket = boto3.resource("s3", **kwargs).Bucket(bucket_name)
```

MinIOを使う場合は、`endpoint_url`に`"http://127.0.0.1:9000"`を指定するだけで切り替えられます。

※ docker-composeを使う場合、`127.0.0.1`にはサービス名を指定します。


### 実行サンプル

カレントディレクトリにファイル`test_file`が存在するとします。

```py
bucket.create()  # バケット作成
bucket.upload_file("test_file", "upload_file")  # upload_fileとしてアップロード
print(list(bucket.objects.all()))  # ファイル一覧
bucket.download_file("upload_file", "download_file")  # download_fileとしてダウンロード
bucket.Object("upload_file").delete()  # ファイル削除
bucket.delete()  # バケット削除
```

通常のS3と同じように動作します。
適宜、`http://127.0.0.1:9000`で確認してください。

## プロフィールによるboto3のサンプル

環境変数を使うよりプロフィールを使う方法をおすすめします。

### 準備

- [aws CLI](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2.html)をインストールしてください。
- `aws configure --profile test`でプロフィールを作成してください。`test`は適宜変えてください。

### バケットの作成

作成したプロフィールを使ってバケットを作成します。
MinIOを使う場合は、`profile_name`と`endpoint_url`を指定することになります。

```py
profile_name = "test"

cr = boto3.Session(profile_name=profile_name).get_credentials()
kwargs = dict(aws_access_key_id=cr.access_key, aws_secret_access_key=cr.secret_key)

if use_minio:
    kwargs["endpoint_url"] = "http://localhost:9000"

bucket = boto3.resource("s3", **kwargs).Bucket(bucket_name)
```

作成したバケットは、前サンプルと同じように使えます。

以上
iPhoneをMacのローカル環境に接続し、Mac版Safariでデバック（Webインスペクタ）する方法

ウェブサービスとかを開発していると、エミュレーターでは起きないことが、実機で起きたりすることがままある。
iPhoneのjavascriptの挙動をconsole.logにだしてみたいこともある。
いちいちサーバーにプッシュして実機確認するわけにもいかないので、
ローカル環境にiPhoneをつないで、かつiPhoneのSafariのログをMacで取る方法を調べたが、
WifiにiPhoneを繋げてるとWebインスペクタが使えなかったり、そもそも情報が少なかったりするのでまとめました。

##用意するもの
- Mac(homebrewとかDockerで開発環境があるもの）
- iPhone
- ライトニングケーブル
- wi-fi環境

##事前準備
###共通
**iPhoneと、MacのSafariのバージョンを必ず揃えておく**
####Mac版Safari
Safari立ち上げ、メニューから、「Safari」＞「Safariについて」
![MacSafari.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229958/66c7fe0c-4ccf-794c-3075-b2872d6207de.png)

####iPhone版Safari
以下のようにまとめてくださっている方がいるので、参考にしてください
[iOSのバージョンと Safariバージョンの対応表](https://qiita.com/yoshitake_1201/items/05a13fd77c18ff380eb6)

###Mac側
- ローカルの開発環境を立ち上げ見れるようにしておく。
- wi-fiにつながった状態で、「システム環境設定」＞「ネットワーク」を開き、IPアドレスをメモ。（iPhoneの接続で必要）
![Mac Wifi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229958/57f52a83-134a-10e5-6cd6-ffc37db406fb.png)
- Safariを立ち上げ、メニューより「Safari」＞「環境設定」、詳細タブの「メニューバーに開発メニューを表示」にチェック
![スクリーンショット 2020-08-29 13.51.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229958/9813fb4f-b9f6-6d9b-78c2-425a0d87d8fb.png)


###iPhone側
- 設定より「Safari」＞「詳細」を開き、「Webインスペクタを表示」にチェック
![IMG_D7E7FA689565-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229958/0e800d39-e82f-9bc0-cf79-ed0ab974e358.jpeg)

##やり方

###1. Macのローカル環境をiPhoneで表示
MacとiPhoneが同じWifiに接続していることを確認したうえで、
事前に確認したMacのIPアドレスをiPhoneのSafariに入力。（今回は192.168.0.242)
場合によっては、接続に必要なポートも入力。（例 192.168.0.242:8080 など）

ここで表示できない場合は以下をチェック
- Macのセキュリティソフトとかでファイアウォールが動いていたら切る
- Macのローカル環境動いてる（Macのブラウザなどで確認）
- 同じWifi環境に接続しているかどうか

###2. 【重要】iPhoneのwi-fi接続を一旦切る

###3. iPhoneとMacを接続
iPhoneとMacを接続する。
Macとライトニングケーブルで接続すると、iPhone側に信頼するかどうか出てくるので「信頼する」を選択。

###4. Mac版SafariでiPhoneのWebインスペクタをチェック
Mac版Safariのメニュー、「開発」のなかに、自身のiPhoneが表示され、開いているタブが出るので選択。
![スクリーンショット 2020-08-29 14.07.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229958/7b7a626e-a535-dc7a-b3b1-1be2441c6c9b.png)

ここで表示できない場合は以下をチェック
- iPhoneロックかかってないか（ロック画面だとタブが出ない）
- Safariはシークレットモードになっていないか（なっていたら通常モードで開いておく）
- Wifiつながったままでないか（WifiつながっていたらiPhoneが出ないので、一旦切って、再度ケーブルを繋ぐ）
- ちゃんと信頼する、選択した？
- ケーブル抜き差ししてみる

うまく行くと、以下のような画面が出ます。
![スクリーンショット 2020-08-29 14.16.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229958/3294adb2-ff79-6f39-f4e3-4cc300c77ace.png)


###5. iPhoneのwi-fi接続を戻す
wifiにつながらないとローカル環境が見れないので、wi-fi接続をオンに戻す。
これで、コンソールでログを取ったりできるようになる。
![スクリーンショット 2020-08-29 14.11.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229958/ab40e27a-32b5-b121-aea1-adb7026c2f96.png)
画像はiPhoneのSafariでスクロール、console.logにスクロール値を吐き出している様子。
ScrapyとGitHub Actionsを使ってKindle Prime Readingの一覧サイトを作りました

## 経緯

外出自粛の中、アマゾンのプライム会員を参加したが、米とドリンクなどを購入する以外ほとんど使っていません。つい先日からPrime Readingという特典を利用し始めました。でも一体どんな本を読めるのかを確かめたいと思いますが、一ページ一ページチェックするのはやはり面倒で、Scrapyを使って一覧・検索のサイトを立ち上げました。

こちらへどうぞ: https://kpr.gimo.me/

## 使っているもの

- [Scrapy](https://scrapy.org/) (HTMLを取得、解析など)
- [DataTables](https://datatables.net/) (データをテーブルで格納)
- [GitHub Pages](https://pages.github.com/) (サイトの作り)
- [GitHub Actions](https://github.co.jp/features/actions)(自動化)

## 開発の流れ

### Scrapy
Spiderを書いてどんなデータを取得、抽出などを定義できます。詳しくこちら：https://github.com/masakichi/KindleSpider/blob/master/KindleSpider/spiders/PrimeReading.py

完成すれば `scrapy crawl PrimeReading -o public/output.json` というコマンドを使って一分程度すべての書目をゲットできますぞ。

### 最低限のindex.htmlを書きます

Scrapyで取得したデータを表現するのはHTMLに格納しなければならない、幸いDataTablesというjQuery Pluginを利用して楽です。大体に２０行位のコードで完成度高いテーブルを作れます。（ソートや検索機能完備）

```javascript
$('#prime-reading').DataTable({
    "paging": false,
    "order": [[4, 'desc']],
    "ajax": { "url": "./output.json", "dataSrc": "", "cache": true },
    "language": {
        "url": "./Japanese.json"
    },
    "columns": [
        { "data": "asin", "visible": false },
        { "data": "title", "render": function (data, type, row) { return `<div><a class="title" data-image="${row.cover}" href="https://www.amazon.co.jp/dp/${row.asin}/" target="_blank">${data}</a></div>` }, "width": "40%" },
        { "data": "author" },
        { "data": "star" },
        { "data": "rating_count" },
        { "data": "price" },
        { "data": "publish_date" },
        { "data": "cover", "visible": false },
    ]
});
```

### GitHub Pagesで公開

上記のindex.htmlとoutput.jsonを基づいてGitHub Pagesに公開できます。公開方法はネット上でたくさんあるため、ここは割愛します。

### GitHub Actionsの力で全て自動化

以下のようにyamlの形で要件を定義すれば、コードがpushされる時と毎日UTC０時（日本時間午前９時）自動的にデータ取得、抽出とサイトの立ち上げができます。

```yaml
name: publish to gh-pages

on:
  push:
    branches:
      - master
  schedule:
    - cron: "0 0 * * *"

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-python@v2
      - uses: dschep/install-pipenv-action@v1
      - run: pipenv install
      - run: TZ='Asia/Tokyo' date --iso-8601="minutes" > public/update_time.txt
      - run: pipenv run scrapy crawl PrimeReading -o public/output.json
      - name: Deploy to GitHub Pages
        if: success()
        uses: crazy-max/ghaction-github-pages@v2
        with:
          target_branch: gh-pages
          build_dir: public
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

## 感想

- Prime Readingの中に雑誌が多いようです。
- GitHub Actionsが便利で、しかも月2000分間無料なのはめちゃいいです。
- 吉川英治の三国志はいまPrime Readingに無料で読めます。
クリーンアーキテクチャ本 要点まとめ 第7章　

# クリーンアーキテクチャ本とは
皆さんご存知こちらの名著のこと。割と古い本のはずだけど最近あちこちでオススメされてる(自分の観測範囲だけ？)。

<a href='https://www.amazon.co.jp/Clean-Architecture-%E9%81%94%E4%BA%BA%E3%81%AB%E5%AD%A6%E3%81%B6%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%81%AE%E6%A7%8B%E9%80%A0%E3%81%A8%E8%A8%AD%E8%A8%88-Robert-C-Martin/dp/4048930656'>
  <img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227776/916d91d5-061a-b897-dbc3-89236b243998.png' width=200>
  </img>
</a>

本の構成は以下のようになっている。

- 第Ⅰ部 イントロダクション
  - 1章 設計とアーキテクチャ
  - 2章 ２つの価値のお話
- 第Ⅱ部 構成要素から始めよ: プログラミングパラダイム
  - 3章 パラダイムの概要
  - 4章 構造化プログラミング
  - 5章 オブジェクト指向プログラミング
  - 6章 関数型プログラミング
- 第Ⅲ部 設計の原則
  - 7章 単一責任の原則
  - 8章 オープン・クローズドの原則
  - 9章 リスコフの置換原則
  - 10章 インターフェース分離の原則
  - 11章 依存関係逆転の原則
- 第Ⅳ部 コンポーネントの原則
  - 12章 コンポーネント
  - 13章 コンポーネントの凝集性
  - 14章 コンポーネントの結合
- 第Ⅴ部 アーキテクチャ
  - 15章 アーキテクチャとは？
  - 16章 独立性
  - 17章 バウンダリー: 境界線を引く
  - 18章 境界の解剖学
  - 19章 方針とレベル
  - 20章 ビジネスルール
  - 21章 叫ぶアーキテクチャ
  - 22章 クリーンアーキテクチャ
  - 23章 プレゼンターとHumble Object
  - 24章 部分的な境界
  - 25章 レイヤーと境界
  - 26章 メインコンポーネント
  - 27章 サービス: あらゆる存在
  - 28章 テスト境界
  - 29章 クリーン組み込みアーキテクチャ
- 第Ⅵ部 詳細
  - 30章 データベースは詳細
  - 31章 ウェブは詳細
  - 32章 フレームワークは詳細
  - 33章 事例: 動画販売サイト
  - 34章 書き残したこと
  - 35章 アーキテクチャ考古学

この本で特に重要なのは第Ⅲ部〜第Ⅴ部にかけての部分なので、この要点まとめシリーズでは7章〜29章の要点と自分の所感を1章ずつ記事にまとめていく。

# 第Ⅲ部 7章 単一責任の原則
## SRPとは
単一責任の原則(SRP, Single Responsibility Principle)が言わんとするのはどのモジュール・関数もたった一つのことを行うべきということではなく、あくまで **「モジュールを変更する理由はたった一つだけであるべきである」** ということ。

ここでいう「変更の理由」とは、そのソフトウェアのユーザーやステークホルダーを指す。ユーザーは一人とは限らず、複数人がシステムを変更したいと望む場合もあるため、これらシステムの変更を望む人達をひとまとめにしたグループのことを **アクター** と呼ぶ。するとSRPはより正確には以下のように言い換えられる。

**「モジュールはたった一つのアクターに対して責務を負うべきである。」**

## 給与計算システムの例で考える
これを説明するために本文中で紹介されている給与計算システムの例が分かりやすかったので紹介する。この例では給与計算システムに従業員クラスが存在し、そこに以下2つのメソッドが実装されている状況で何が起こるかを考えている。

- 給料を計算するメソッド: calculatePay
    - 計算ロジックは経理部門が規定する
    - 計算結果の報告先はCFO
- 労働時間を計算するメソッド: reportHours
    - 計算ロジックは人事部門が規定する
    - 計算結果の報告先はCOO

このような設計では、給与計算と労働時間の計算の両方で同じように所定労働時間を算出している場合などに、開発者はコードの重複を排除するためこの計算をregularHoursメソッドに切り出そうと考えるはずである。
その後ある時CFOチームで所定労働時間の計算方法を変えたくなったため、regularHoursメソッドに手を加えたとする。するとその修正について何も知らされていないCOOチームは知らぬ間に数字がずれていることに気付かず、後になって大問題が発覚するというわけだ。

このような事故が起こった原因は、アクターが違う処理(この例でいうとregularHourメソッドが担当している処理)をメソッドに切り出して共通化しまったことにあるというわけだ。なので具体的な実装の観点でSRPを言い換えるなら、 **「アクターが異なる処理はメソッドやモジュールに切り出して共通化してはいけない」** という風に言えそうである。

自分はこの給与計算システムに関する説明を最初に読んだ時、
「テストコードがどのアクター目線でも網羅的に書かれていてCIで全てのテストケースをチェックする体制ができていればこういう事故はある程度機械的に防げるのでは？」
という想いが一瞬頭をよぎったが、冷静に考えると問題はそこではなく、**一つのアクター目線で修正を加える際に常に他のアクターの事情も考慮しなればならない**という時点でまず開発効率が落ちるということだと思う。

## Facadeパターンによるコード分割
SRPを説明する例としてもう一つ、複数のアクターが別々の理由で一つのソースファイルを変更したい状況(CTOチームとCFOチームがEmployeeクラスを共通で利用しており、そのクラスを変更したいような場合)の解決策についても触れられている。ここでも、**アクターの異なるコードは分割すべき** の原則に従うことになる。

やることとしては、

- Employeeクラスが持つメソッドを全て削除し、このクラスには最低限のデータ構造のみもたせる
- Employeeクラスが持っていた個々のメソッドの処理内容を対応するサービスクラスに実装し直す
- Employeeクラスが元々備えていたメソッドを呼び分けるためのEmployeeFacadeクラスを用意。このクラスの各メソッドで、実際に実行したい処理を担うサービスクラスをインスタンス化して処理を移譲する

これでEmployeeクラスが多方から修正されることを防ぎ、かつクラスを小さく保つことができるようになる。

# 参考
- Clean Architecture 達人に学ぶソフトウェアの構造と設計 (Robert C. Martin)
縦スクロールしたときにふわっと出てくるメニュー（SPとPCで全く異なる要素を出したい時）

PCとSPの時に全く異なる要素を、スクロールした時にふわっと出したい。
ただ画面幅を手動で変えた時にうまくいかず、意外とハマってしまったので、備忘録的にメモ。

onメソッドで、読み込み時・リサイズ時・スクロール時のイベントを設定して、画面幅とスクロール量を取得。
if文でそれぞれの条件を設定すれば、うまくいった。

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="html,result" data-user="SUKE_DESIGN" data-slug-hash="eYZRgxK" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="eYZRgxK">
  <span>See the Pen <a href="https://codepen.io/SUKE_DESIGN/pen/eYZRgxK">
  eYZRgxK</a> by SUKE (<a href="https://codepen.io/SUKE_DESIGN">@SUKE_DESIGN</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
ひかり電話　ip電話

Ip電話　050 070 　プロバイダーとの契約で与えられる
ひかり電話　03や07　　光回線へ追加で行ける NTTとの契約


２週間　　ひかり回線用のモデムが送られてくる
工事料金2000 　
500円　月額　
電話　３分8.4円
1ふん　１６.８円　携帯
18.64円　1分
MacでVSCode環境構築 Pythonのサンプル

# はじめに
ターミナル実行場所を間違えて、コードが反映さてれいなかった。
対象フォルダに移動して、「統合ターミナルで開く」のターミナル実行すると解決

# 参考ページ
https://qiita.com/YoshitakaOkada/items/6dfad94ab917053fcef7

最後の実行でつまづいた
![スクリーンショット 2020-08-28 23.44.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693241/cc72c653-76b9-d58c-4353-b0c0b7cb193f.png)

ここでグラフに反映されない、「python simpleserver-startup.py」の入力が途中に出来なかった。

>・VSCodeのターミナルで「basic_js_graph」に移動して「python simpleserver-startup.py」と打ち込んで実行

これが出来ていなかった。



# つまづいた場所

## 今回のタスク
今回のグラフのタスクってエディターが「index.html」なので、pythonではなく、「html」でコーディングするタスクでしょうか？
> いい質問。
この課題はブラウザのアドレスバーに 「<http://localhost:8000/>」 と打ち込んだら、作成したhtmlが表示される、という「pythonのwebサーバーとしての動き」を学ぶものです。htmlだけだと、通常はブラウザのアドレスバーに ファイルパス を入力するはめになります。ちなみにこれがpython部分のソース
`import http.server as server`
`server.test(HandlerClass=server.CGIHTTPRequestHandler)`

VScodeでpythonをインストールから実行するまでの資料（Pythonインストールの場合）
①インストール
https://qiita.com/ryo-sato/items/7d465e22c6d7a1e79803
②実行まで（インストールができたかの確認）

## Emmet
>まだ空っぽのhtmlファイル上で「!」を押すと、VSCodeがhtmlテンプレートを作ってくれる。すご！
これが全く起きないです。現状こんな感じです。

右側の index.html で半角で ! 押して tab 押してみる
https://tonari-it.com/python-vscode-input-save-run/ 

OK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94562/b53e28fe-b205-2203-aa9b-bd51a93ac6c3.png)

# STEP2
STEP2のWebサーバーからの打ち返しのところまで頑張ろうと思ったのですが、こういった状況で何も起きず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94562/72f92c65-835a-53f1-9cf2-7e67f2cc1fdf.png)
>simpleserver-startup.pyのある位置がちがくない？ 
図1の赤線が気になるんだよね。バージョンが見たいから、ターミナル上でpython -V って打ち込んで Enter してみて。
あとはあるとすれば  my python project っていう 空白付きのフォルダ名がヤバい（全角混在もやめたほうがいい）ので空白をアンダーラインにしてってあたり（いちおうwebサーバは起動してるっぽいけど）。
あとは、図2のように フォルダを開くで basic_js_graph のフォルダを開いてみて。そうすると python simpleserver-startup.py でwebサーバが起動する。

できました！basic_js_graphのターミナルが理解できておらず、途中にコードがかけなくてできていませんでしたが、表現できました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94562/31987fb9-22aa-c489-3875-153fd3930c32.png)
初めてのDjangoチャレンジ

Django触ってみたので自分用にやったことまとめ

# 参考サイト
こちらを参考に実施
https://docs.djangoproject.com/ja/3.1/intro/tutorial01/

# プロジェクトの作成
下記コマンドでプロジェクト作成

```
django-admin startproject mysite
```

## 作成されるファイル
- manage.py
    - コマンド操作のためのファイルっぽい
- settings.py
    - プロジェクト全体の設定ファイルっぽい
- urls.py
    - ルーティング定義のファイルっぽい
- asgi.py
    - プロジェクトを提供する ASGI 互換 Web サーバーのエントリポイントと書いていたけどあまりイメージできず...
        - あとで調べておこう
            - https://docs.djangoproject.com/ja/3.1/howto/deployment/asgi/
- wsgi.py
    - こちらもよくわからず...
        - あとで調べる
            - https://docs.djangoproject.com/ja/3.1/howto/deployment/wsgi/


# サーバ起動
```
python manage.py runserver
```
コマンド指定する時は`python manage.py`まではセットなのかな？

# プロジェクトの作成
```
python manage.py startapp polls
```

# viewの作成
## views.pyを編集
```
from django.http import HttpResponse


def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")
```

http周りのパッケージインポートして、indexっていう関数でリクエスト捌くって感じなのかな


## ルーティング定義
### `polls/urls.py`を作成


```
from django.conf.urls import url

from . import views

urlpatterns = [
    url('', views.index, name='index'),
]
```

### `mysite/urls.py`を編集


```
# from django.conf.urls import url
from django.contrib import admin
from django.conf.urls import include, url

urlpatterns = [
    url('admin/', admin.site.urls),
    url('polls/', include('polls.urls')),
]
```

なぜか参考にしたサイト通りにやるとできなかったのであとで調べておきたい
path じゃなくて url という関数を使用しないとなぜかうまくいかず...
バージョン問題ありそう... :thinking: 

これdocker上でDjangoで使用するpythonのバージョンうまく指定できていない気がする...

```
root@38153a1081ae:/code# python --version
Python 3.8.5
root@38153a1081ae:/code# python -m django --version
1.11.29
root@38153a1081ae:/code#
```

とりあえず問題っぽい箇所はわかったので次はdocker側かDjangoの設定を見直してみよう...
mplfinanceでローソク足チャート、出来高、移動平均線、ボリンジャーバンドを表示する

## mplfinanceでよくあるチャートを表示してみます。
３ヶ月で3.5倍になった ロコンド(3358) を例にします。
環境はGoogle Colaboratoryです。

### 事前準備
stooq で株価データを取得できるメソッドを作成しておきます。

```python
import pandas as pd
import pandas_datareader.data as pdr
import numpy as np
from pandas.testing import assert_frame_equal

def makeDataFrame(code):
  df_temp = pdr.DataReader("{}.JP".format(code), "stooq")
  df = df_temp.loc[:,['Open','High','Low','Close','Volume']].sort_values('Date')
  return df
```

確認
直近100営業日のデータを取得します。

```python
df = makeDataFrame(3558).tail(100)
df.tail()
```
![スクリーンショット 2020-08-29 14.07.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/d3a7fe4e-429a-4716-3479-156bc3e246ed.png)


## mplfinance インストール
pip でインストールします。
![スクリーンショット 2020-08-29 13.49.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/59fa7a4e-e12d-bbe0-ef37-bc5b15e94121.png)


## ローソク足チャートを表示

typeを指定してplotするだけで表示できます。

```python
import mplfinance as mpf
mpf.plot(df, type='candle')
```
![スクリーンショット 2020-08-29 13.46.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/29d7d413-756e-8f57-a85e-69238c567766.png)


## 出来高を表示
volume=True のオプションをつけるだけです。

![スクリーンショット 2020-08-29 13.47.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/c4c2d661-b51b-d4a1-279c-ecaa40e64263.png)

## 移動平均線を表示
移動平均線はmavオプションで日付を指定することで表示できます。5, 25, 75日線を表示する例です。

```python 
mpf.plot(df, type='candle', mav=(5, 25, 75), volume=True)
```
![スクリーンショット 2020-08-29 14.00.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/2c0b7634-da38-d6a9-1cb0-03e62be902b3.png)

## ボリンジャーバンドの表示
### pytiライブラリのインストール
ボリンジャーバンドを計算するライブラリ pyti をインストールします。

![スクリーンショット 2020-08-29 13.50.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/9219d61b-0726-13f2-9839-f64675013c1c.png)

### ボリンジャーバンドの計算
基準線20で計算します。

```python
from pyti.bollinger_bands import upper_bollinger_band as bb_up
from pyti.bollinger_bands import middle_bollinger_band as bb_mid
from pyti.bollinger_bands import lower_bollinger_band as bb_low

data = df['Close'].values.tolist()
period = 20
bb_up = bb_up(data,period)
bb_mid = bb_mid(data,period)
bb_low = bb_low(data,period)
df['bb_up'] = bb_up
df['bb_mid'] = bb_mid
df['bb_low'] = bb_low
```

### 確認
プロットして計算できているか確認してみます。
![スクリーンショット 2020-08-29 13.54.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/e4a00753-faba-2f80-21ec-a9be3c556352.png)

### mplfinanceで表示
mplfinanceはデフォルトでは 'Open','High','Low','Close','Volume' しか認識しません。
追加したい項目はmake_addplotでmplfinanceが認識できるようにします。
表示するときには、addplotのオプションで一緒に表示する項目を指定します。

```python
apd = mpf.make_addplot(df[['bb_up', 'bb_mid', 'bb_low']])
mpf.plot(df, type='candle', addplot=apd, volume=True)
```
![スクリーンショット 2020-08-29 13.57.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/caac5a6b-1d4c-d4a2-3a69-94d21950ea21.png)
初心者が、JavaとMySQLでWebアプリ制作（随時、加筆中）

#はじめに
この記事につきましては、前回書いた通り進めております。
[Qiitaはじめました。まずはポートフォリオ作成と就職を目標に。](https://qiita.com/begin_h/items/99efafb8947563d537d1)

過去のWebアプリケーション制作の過程を書いていき、
結果的にポートフォリオとしてまとめることが目標です。

分からないことは率直に記載するので、アドバイスいただけますと幸いです。
初心者が模索しながら、随時加筆しております。（2020年8月24日〜）

#背景
プログラミングスクールで、「Java」「MySQL」「サーブレットとJSP」を学び、
その集大成として、Webアプリケーションを作成することになりました。

グループ協議の結果、【買い物の時に役立つアプリ】を作ることに決めました。

私自身、買い物のたびに、
「あれ、洗剤ってなくなりそうだったっけ？他に何かストック切れのもの無かったっけ？」
と思うことに、わずらわしさを感じていたことがきっかけです。

日常的な課題を解決するアプリ制作を通して、プログラミングへの理解を深めようと思いました。

#メインとなる機能
- 定期的に購入する消耗品（アイテム情報）を登録する
- その商品について、毎度、購入日を入力する

上記情報から、各商品の購入履歴を自動計算することにより、
「そろそろ買ったほうがいいのでは？」というのを知らせてくれる。

他の詳細な機能は、後述します。

#スペック

**言語：**
&emsp;&emsp;&emsp; Java 8.0.14

**IDE：**
&emsp;&emsp;&emsp; Eclipse 4.8.0

**DB：**
&emsp;&emsp;&emsp; MySQL 8.0.19
&emsp;&emsp;&emsp; MySQL 5.7.26（MAMP 5.7）

**CSSフレームワーク：**
&emsp;&emsp;&emsp; Bootstrap 4.3.1

**開発環境：**
&emsp;&emsp;&emsp; Windows10
&emsp;&emsp;&emsp; MacOS Mojave 10.14.5
&emsp;&emsp;&emsp; Apache Tomcat 8.5.32
<br>

こちらの記述の仕方は正直自信がありませんが、バージョン等は調べてきました。

スクールと自宅で、それぞれWindowsとMacを併用しておりました。

残念ながら、現状ローカル環境開発止まりです。
これが書き終わる頃には、本番環境にも挑戦しようと思っております。

#参考文献
- [PHP+MySQLでポートフォリオ作成](https://qiita.com/RINYU_DRVO/items/6607a0aa7ca3294f8e47)
ルートの記述ミス

```routes.rb
   get 'missions' => 'missions#index'
   get 'missions/new' => 'missions#new'
   post 'missions' => 'missions#create'
   get 'missions/:id' => 'missions#show',as: 'mission'
   patch 'missions/:id' => 'missions#update'
   delete 'missions/:id' => 'missions#destroy'
   get 'missions/:id/edit' => 'missions#edit', as:'edit_mission'
   For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html

  # resources :missions 
  # root 'missions#index'
  resources :missions do
    resources :likes, only: [:create, :destroy]
    resources :comments, only: [:create, :destroy]
  end
```
#ルート設定の重複
上記のように、missionのルートを二重に設定すると、エラーの原因となるため、上の部分はコメントアウトしてあげる必要がある。
#正解
```routes.rb
   #get 'missions' => 'missions#index'
   #get 'missions/new' => 'missions#new'
   #post 'missions' => 'missions#create'
   #get 'missions/:id' => 'missions#show',as: 'mission'
   #patch 'missions/:id' => 'missions#update'
   #delete 'missions/:id' => 'missions#destroy'
   #get 'missions/:id/edit' => 'missions#edit', as:'edit_mission'
   For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html

  # resources :missions 
  # root 'missions#index'
  resources :missions do
    resources :likes, only: [:create, :destroy]
    resources :comments, only: [:create, :destroy]
  end
```
Railsプロジェクトを作ろうとしたら躓いた人のメモ

（筆者の現環境がMacなので一旦Mac編のみ。Windowsに関しては追々書くかも）

## 0. 結論
- 何はともあれrbenvをインストール。話はそれから。

## 1. プロジェクト作成 ([参考](https://openbook4.me/projects/92/sections/488))
Terminalで
```$ rails new {プロジェクト名}```
を実行すると、Railsアプリの型となるファイルが生成されたプロジェクトディレクトリが作成される

## 2. 各種gemをインストール（[gemとは](https://techplay.jp/column/529)）
1.で作成したプロジェクトディレクトリに入り
```$ cd ./{プロジェクト名}```
↓のコマンドを実行
```$ bundle install --path vendor/bundle```

私はここでエラーが出た。
エラー文はこちら（エラー部分だけ抜粋）

``` 
An error occurred while installing nokogiri (1.10.10), and Bundler cannot continue.
Make sure that `gem install nokogiri -v '1.10.10' --source 'https://rubygems.org/'` succeeds before bundling.
```
nokogiriなるもののインストールでエラーが出ているらしい（[nokogiriとは](http://hetaredream.hatenablog.com/entry/2014/12/20/163310#:~:text=Nokogiri%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B,%E8%A1%8C%E3%81%86%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82)）

## 3. エラー解決方法
-  単純に`gem install nokogiri`してみる
    - これもエラー
    ```You have to install development tools first.```と出る

- 開発者ツールが必要ということで、まずXcodeをAppStoreからインストールしてみる（結構時間かかる）
- Xcodeをインストールしたら起動して、
「Xcode」-> 「Preference」->「Location」で「Command Line Tools」を設定する
　（[ここ](https://qiita.com/kodai_0122/items/56168eaec28eb7b1b93b#bundle-install---path-vendorbundle%E3%81%A7an-error-occurred-while-installing-pg-122%E3%81%A8%E3%81%84%E3%81%86%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E5%87%BA%E3%81%9F%E5%A0%B4%E5%90%88)みると、Terminalからでもこの設定できるっぽい？）

- Terminalを再起動して、改めてnokogiriをインストールしようとすると、、
    - またエラー

``` 
ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions for the /usr/bin directory.
```
`/usr/bin`の書き込み権限が無いようだが、sudoでもchmodで権限変更しようとしても駄目

- どうやらシステムのRubyやgemは使い勝手が悪そうなので、rbenv（[rbenvとは](https://qiita.com/Kodak_tmo/items/73147ed4f0eec54d6e94)）で環境を作った方が良さそう（そもそもこれを最初にやるべきだった感）

- rbenvやそのインストーラーのbrewのインストール方法は [ここ](https://qiita.com/kodai_0122/items/56168eaec28eb7b1b93b#bundle-install---path-vendorbundle%E3%81%A7an-error-occurred-while-installing-pg-122%E3%81%A8%E3%81%84%E3%81%86%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E5%87%BA%E3%81%9F%E5%A0%B4%E5%90%88) 参照
- 既にプロジェクトディレクトリができている場合、Rubyのバージョンが設定されている筈なので、設定されたバージョンをrbenvでインストールする。(設定されたバージョンは`{プロジェクト名}/.ruby-version`の中身を見て確認できる）

- 三度目の正直、`gem install nokogiri`...

```
Fetching mini_portile2-2.4.0.gem
Fetching nokogiri-1.10.5.gem
Successfully installed mini_portile2-2.4.0
Building native extensions. This could take a while...
Successfully installed nokogiri-1.10.5
Parsing documentation for mini_portile2-2.4.0
Installing ri documentation for mini_portile2-2.4.0
Parsing documentation for nokogiri-1.10.5
Installing ri documentation for nokogiri-1.10.5
Done installing documentation for mini_portile2, nokogiri after 1 seconds
2 gems installed
```
できた！

## 4. エラー解消後、gemを再インストール
```$ bundle install --path vendor/bundle```
を再度実行

```
Bundle complete! 17 Gemfile dependencies, 74 gems now installed.
Bundled gems are installed into `./vendor/bundle`
```
のような画面が出たらインストール成功


## 5. まとめ
- rbenvを使いましょう

-----

【参考】
-  https://qiita.com/___xxx_/items/b18795056e98243568fe
Python で WSGI (Web Server Gateway Interface) に従ったシンプルな Web サーバで Hello World

## 概要

- Python で WSGI (Web Server Gateway Interface) に従ったシンプルな Web サーバを起動する
- Python 標準ライブラリの wsgiref を使用する
- 検証環境: Python 3.8.5 + macOS Catalina

## WSGI と wsgiref について

[Web Server Gateway Interface \- Wikipedia](https://ja.wikipedia.org/wiki/Web_Server_Gateway_Interface)

> Web Server Gateway Interface (WSGI; ウィスキー) は、プログラミング言語Pythonにおいて、WebサーバとWebアプリケーション（もしくはWebアプリケーションフレームワーク）を接続するための、標準化されたインタフェース定義である。また、WSGIから着想を得て、他の言語でも同様のインタフェースが作られた。

[wsgiref \-\-\- WSGI ユーティリティとリファレンス実装 — Python 3\.8\.5 ドキュメント](https://docs.python.org/ja/3.8/library/wsgiref.html)

> wsgiref は WSGI 仕様のリファレンス実装で、これは Web サーバやフレームワークに WSGI サポートを加えるのに利用できます。これは WSGI 環境変数やレスポンスヘッダを操作するユーティリティ、 WSGI サーバ実装時のベースクラス、WSGI アプリケーションを提供する デモ用 HTTP サーバ、それと WSGI サーバとアプリケーションの WSGI 仕様 (PEP 3333) 準拠のバリデーションツールを提供します。

## ソースコード

以下の内容を app.py というファイル名で保存する。

```py
# Hello World な WSGI アプリケーションを書く
def application(environ, start_response):
  status = '200 OK'
  headers = [('Content-type', 'text/plain; charset=utf-8')]
  body = 'hello, world'.encode('utf-8')
  start_response(status, headers)
  return [body]

# WSGI 仕様のリファレンス実装である wsgiref を利用する
from wsgiref import simple_server

if __name__ == '__main__':

  # WSGI HTTP サーバを起動
  host = ''
  port = 8000
  app = application # WSGI アプリケーションを指定
  server = simple_server.make_server(host, port, app)
  server.serve_forever()
```

## WSGI HTTP サーバを起動

```
$ python app.py
```

## WSGI HTTP サーバにアクセス

```
$ curl --include http://localhost:8000/
HTTP/1.0 200 OK
Date: Sat, 29 Aug 2020 04:33:33 GMT
Server: WSGIServer/0.2 CPython/3.8.5
Content-type: text/plain; charset=utf-8
Content-Length: 12

hello, world
```

## 参考資料

- [PEP 3333 \-\- Python Web Server Gateway Interface v1\.0\.1 \| Python\.org](https://www.python.org/dev/peps/pep-3333/)
- [wsgiref \-\-\- WSGI ユーティリティとリファレンス実装 — Python 3\.8\.5 ドキュメント](https://docs.python.org/ja/3.8/library/wsgiref.html)
Railsの中間テーブルをjquery,json非同期保存してみた

#はじめに
Railsでの中間テーブルをjquery,jsonを使って実装してみました。
**（*注意：この記事は学習の一環として実装した物の一部を記事にしています。本記事には正しくない情報、方法を含んでいる可能性があります。）**
##理由
個人的にあまりRailsに依存した書き方をしたくなかったのが理由でフロントエンドの勉強も踏まえて実装してみました。（Postモデルは全て非同期での実装をしてます。）

##環境

- Rails 5.2.4
- jquery

##モデル構成

*__Userモデル作成済み前提__

(__Post.rb__)

- __has_many :post_categroies, dependent: :destroy  
  has_many :categories, through: :post_categories__

(__Post_category.rb 中間テーブル__) 

- __belongs_to :post  
  belongs_to :category__

(__Category.rb seed.rbにカテゴリー名登録済み__)

- __has_many :post_cates, dependent: :destroy  
  has_many :posts, through: :post_cates__

|    Post    |  Post-category |  Category |
|:-----------:|:---------------:|:------------:|
|             |       中間テーブル|                |
|    id      |   id             |        id        |
|    content      |      post_id|    name    |
|         image   |  category_id   |          something       |

##チェックボックス

Postモデルに関してはタイトル通り、Rails依存を避けるために
Formから受け取った値からPostコントローラへのCSRFトークン認証はprotect_from_forgery :exceptにしてCSRF認証トークンを使っておりません。

```erb:form.html.erb
  <div class="field form-group form-catpy">
          <%=f.label :category_name, "*カテゴリーを選択してください"%><br/>
          <%= f.collection_check_boxes(:category_ids, Category.all, :id, :category_name) do |category|%>
            <%=category.label %>
            <%= category.check_box%>
          <%end%>
    </div>
```

この部分は同じです。

##フォームの値を送る

json形式でコントローラ先に送る説明は省略します。

```js:form.js
$("#save-button").on("click", function () {
//チェックしたカテゴリーのidを配列に格納
  var checks = [];  
  $("[name= 'post[category_ids][]']:checked").each(function() {
        checks.push(this.value);
      });
  $.ajax({
          url: "/generate", //指定したアクションに送る
          type: "POST",
          dataType: "json",
          async: true,
          data: {
            content: textVal, 
            category_ids: checks,　//ここに注目！！
          },
        }).done(function(data){
         //以下省略
       })
});

```

__category_ids: checks__の場所に注目してください。筆者はこの部分にめちゃくちゃはまりました。paramsで送る名前を__f.collection_check_boxes__のプロパティ名に合わせないと読み取ってくれないらしいです。  
あとjsonの場合、check_boxesにチェックしたidは、["1", "7", "8"]といったダブルクォーテーションで配列の中のidが囲まれているので中間テーブル(__post_id, __category_id__)に保存されないんじゃないかと思っていましたがうまく保存することができました。

あとは、Railsの中間テーブルの実装手順と同じです。

```ruby
   def post_params
    params.permit(:content, :image_title, :post_image, :film_date,:post_url,:overview, {category_ids: []} )
  end
```

最後に保存するとPost.rb,category.rbに紐付いた中間テーブル内にpost_id,category_idが保存されると思います。

以上です。

##最後に

json形式でPOSTする方法は省略しましたがjquery.jsonで実装してみたい、あまりRailsに依存した書き方をしたくない僕みたいな人の手助けになれば幸いです。
Next.jsのモジュールのImportを相対パスではなく絶対パスでも書かけるようにする方法

階層が深くなってきたときにいちいち `../../components/layout` などとしていて面倒だったことから、絶対パスで書きたくなりました。

## 結論

next.config.jsonに以下のようにすれば絶対パスで指定することができるようになります。

```js

module.exports = {
  webpack(config) {
    config.resolve.modules.push(__dirname)
    return config
  },
}
```



引き続き相対パスでも書くことも出来ます。

```bash

$ ls
components/  next.config.js  package-lock.json  pages/   README.md
node_modules/   package.json public/  stylesheets/
```

Before(相対パス)

```js
import Layout from "../../components/layout"
```

After(絶対パス)

```js
import Layout from "components/layout"
```
djangoに触れる

FlaskやDjangoを書籍で勉強開始したのでメモ代わりにアウトプット

###MTVフレームワーク
Model:心臓部、データベースにアクセスなど（SQlite/MySQL/PostgreSQL/Oracle）
Template:リクエストをhtmlと紐づける
View:ルーティング処理

リクエスト→View→Model→Template→レスポンス

##View
ルーティング設定
リダイレクト
エラー処理（404等）
クッキー、セッションの概念

##Model
モデルクラス：ＳＱＬでいうテーブル定義
フィクスチャ（JSON/YAML/XML）:データのひな型
マイグレーション
1:1,多:多,1:多のリレーションなど
{{...}},{%...%}で変数使用

Formオブジェクトを利用して簡単にユーザ入力を受け付ける
フラッシュ

##Template
html内にDjangoコードで記述できる
タグを駆使して条件分岐などの処理を行う
pythonと演算子の扱いが異なるため注意
HTMLエスケープ、テンプレートの継承（block）


##webアプリ作成の手順
1.Viewを作成、ルーティング設定登録、render関数でTemplateを呼び出す
2.Templateの用意、temp.html
PHP: Smarty の使い方

Ubuntu 20.04 で確認した方法です。

ライブラリーのダウンロード

```bash
wget https://github.com/smarty-php/smarty/archive/v3.1.35.tar.gz
```

インストール

>v3.1.35.tar.gz を解凍して、/usr/local/lib 以下に置く

サンプルプログラム

フォルダー構造

```text
$ tree 
.
├── templates
│   └── hello.tpl
├── templates_c
└── test.php
```

templates_c で書き込めるようにして置く。777 なら確実に書き込める。

```php:test.php
<?php
define('SMARTY_DIR', '/usr/local/lib/smarty-3.1.35/libs/');
require_once(SMARTY_DIR . 'Smarty.class.php');

 
$smarty = new Smarty();
 
$smarty->template_dir = "./templates/";
$smarty->compile_dir = "./templates_c/";

$name = $_GET['name'];
 
$smarty->assign("name", $name);

$smarty->display("hello.tpl");
?>
```

```text:hello.tpl
<!DOCTYPE html>
<html lang="ja">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Hello World!</title>
</head>
<body>
このページは Template です。<p />
<blockquote>
	<h2>こんにちは {$name}!</h2>
</blockquote>
<p />
<hr />
Aug/29/2020 PM 13:22<p />
</body>
</html>
```


実行結果

test.php?name=新美南吉

![smarty_aa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/aed3e514-1561-31a8-9147-125f5378fdde.png)

test.php?name=宮沢賢治

![smarty_bb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/d1f849ea-0b30-0acd-2759-89e3ba42ce76.png)
ローカル環境のアプリを一時的に手軽に公開できる ngrok / localhost.run

Slackと連携したサーバレスアプリを作りたかったりする場合や、ローカルのDockerで作ったアプリをチームのメンバに見てほしい時など、ローカルアプリを都度都度GCPやAWSに上げると効率が悪い時がある。

以下のサービスを使うと、開発効率が上がるときがある。

* ngrok
* localhost.run

serveroがちょっと前に流行ってたみたいだけど、今は利用できなくなっている。

## ngrok

[公式ページ](https://ngrok.com/)

使い方は簡単で、

公式ページにログインして、
OSに応じたバイナリファイルをダウンロードして、
以下のコマンドを実行するだけでフォワーディングできる。

```
# 認証
./ngrok authtoken {ページに記載のトークン}

# 8080は自分のローカルで起動しているアプリケーションのポート番号
./ngrok http 8080


ngrok by @inconshreveable                                                                               (Ctrl+C to quit)                                                                                                                        Session Status                online
Account                       xxxxx@gmail.com (Plan: Free)
Version                       2.3.35
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://xxxxxxxxxxxxx.ngrok.io -> http://localhost:8080
Forwarding                    https://xxxxxxxxxxngrok.io -> http://localhost:8080

Connections                   ttl     opn     rt1     rt5     p50     p90
                              1       0       0.00    0.00    5.52    5.52                                                                                                                                                                     
```

## localhost.run

[公式ページ](http://localhost.run/)

もっと簡単。ログインする必要もない。セキュリティは不安だが、
コマンド一つ。

```
# 8080はローカルアプリのポート番号
ssh -R 80:localhost:8080 ssh.localhost.run

Connect to http://xxxxxxxx-xxxxxxxx.localhost.run
{"domain": "xxxxxxxx-xxxxxxxx.localhost.run", "listen_port": 80, "status": "success", "message": "Connect to http://xxxxxxxx-xxxxxxxx.localhost.run"}
```
【初学者向け】Ruby 遅延鉄道路線名の入手方法

只今ruby勉強中です。
記録としてここに記載しておこうと思います。
  
# プログラム概要  
1. [鉄道遅延情報のjson](https://rti-giken.jp/fhc/api/train_tetsudo/)から遅延している鉄道情報を入手  
2. 遅延しているか確認したい路線名を入力してもらう
3. その文字情報をもとに、ゲットしたjson情報の中に該当する路線があるか検索  
4. 該当路線がある場合は、遅延情報アリと出力。ない場合は該当なしと出力

```getting_delayed_trains_info.rb
require 'open-uri'
require 'nokogiri'  #スクレイピングするためのgem
require 'json'  #jsonを使うための呼び出し

# urlを解析する
url = 'http://tetsudo.rti-giken.jp/free/delay.json'
html = open(url).read  
doc = Nokogiri::HTML(html, url)

#Json形式にパースし、ハッシュへ変換
hash = JSON.parse doc.css("body").inner_text

# 調べたい路線名を標準入力し、input_train へ格納
puts "遅延状況を知りたい路線を入力ください.例：京浜東北線"
input_train = gets.chomp

# delayed_trains 配列変数を用意
delayed_trains = Array.new
# input_trainの文字列が含まれた遅延路線名と更新日時を delayed_trains へ格納していく
hash.each {|train| delayed_train << train["name"] + \
            '(更新日時: ' + Time.at(train["lastupdate_gmt"], in: "+09:00").strftime("%Y-%m-%d %H:%M:%S").to_s + ')' \
            if train["name"].include? input_train }

# 配列が空であれば遅延対象路線はなく、そうでなければ路線名を出力する
if delayed_trains.empty?
  puts "送信頂いた『#{input_train}』の文字を含む路線に遅れは出ておりません"
else
  puts delayed_trains.join(",") + "に遅れが出ている模様です\n詳しくは鉄道会社HPを見てください"
end
```
LINE BOTでオウム返しを作成されている記事がいくつかありますが、それを参考にし、このアルゴリズムを入れれば、遅延しているか聞きたい路線を聞いたら答えてくれるLINE BOTができるのではと思います。
  
やっぱり、自分が作ったものがカタチになるのは勉強していてモチベーションが上がります。
【Railways】RubyMineプロジェクトルートがRailsルートディレクトリ以外の時、Railways が動作しない

# 結論

プロジェクトルートディレクトリに`Rakefile`を作成する。

```ruby
# Rakefile

# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

# 以下に、プロジェクトルートディレクトリからRailsルートディレクトリの application.rb への相対パスを指定する
require_relative 'path_to_your_rails_app_root/config/application'

Rails.application.load_tasks
```

# 原因
Railswaysプラグインは、内部的に`rake routes`を実行しているが、これはRubyMineのAPIを利用しているらしい。[^1]
（おそらく、RubyMineの`Run Anything`を利用していると思われる）
`Run Anything`でのコマンド実行は、プロジェクトルートディレクトリで行われる。
そのため、`Run Anything`でrakeコマンドを実行する場合、プロジェクトルートディレクトリに`Rakefile`を作成する必要がある。
これに関しては、公式ヘルプにも記述があった。[^2]


# 背景

個人的にRailwaysはとても重宝しており、多用していた。
しかし、アプリケーションにフロントエンドやTerraformを追加するにあたり、ディレクトリを分けて管理したくなった。
そうすると、今まではプロジェクトルートディレクトリ = Rialsルートであったが、以下のような構成になる。

```shell
.
├── terratorm 
├── frontend
├── backend # Rails App
├── docker-compose.yml
└── README.md

```

`Rakefile`さんがいなくなってしまった。

この状態ではRailwaysは動かず、困っていた。
`backend`ディレクトリをRubyMineで開けば動くが、それだと他のディレクトリにアクセスしづらく、利便性が落ちてしまう。
開発するにあたりRailwaysを手放したくはなく、なんとかならないかと考えていた。

# 追加情報

ちなみに、Railswaysの実行タスクは設定で変えることができる。
（Rialsways > Settings > Rake task name）
デフォルトでは`routes`になっており、プレフィックスで`rake`を与えてコマンドを実行していることがわかる。
そのため、最初はこの実行コマンドを変えることで対応できるのではないかと考えたが、無理だった。
内容を`-f path_to_your_rails_root/Rakefile rouets`に変更し、`rake -f path_to_your_rails_root/Rakefile rouets`が実行されるようにしたが、以下のエラーが出てしまった。

```ruby
rake aborted!
No Rakefile found (looking for: rakefile, Rakefile, rakefile.rb, Rakefile.rb)
/Users/xxxxxx/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:698:in `raw_load_rakefile'
/Users/xxxxxx/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:104:in `block in load_rakefile'
/Users/xxxxxx/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/xxxxxx/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:103:in `load_rakefile'
/Users/xxxxxx/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:82:in `block in run'
/Users/xxxxxx/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/xxxxxx/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:80:in `run'
/Users/xxxxxx/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/rake-13.0.1/exe/rake:27:in `<top (required)>'
```
`-f`オプションでRakeファイルを指定しているのに、なぜ、、、。
絶対パスで指定してもダメだった。

さらには、`Run Anything`では`-f`フラグを付けると、プロジェクトルートに`Rakefile`がなくても実行できた。
内部的に`Run Anything`を利用していると考えていたが、もしかしたら違うのかもしれない。

いったいRailswaysのタスクはどこで実行されているのだろうか、、、。

# まとめ

今まで`Rakefile`は特に意識しておらず、今回調べたときにその役割を知った。
調べる中で`rake`について詳しくなれたのは今回の収穫だった。

この記事がどなたかのお役に立てたら幸いです。

[^1]: [Github rialsways issues / Failed to load routes with docker. #43](https://github.com/basgren/railways/issues/43)
[^2]: [RubyMine 公式ヘルプ / Rakeタスクの実行](https://pleiades.io/help/ruby/rake.html)
Nuxt.jsでmp3を再生するためにnuxt.config.jsのbuild設定を追加

初投稿です

Nuxt.jsでmp3を再生しようとすると'mp3'を扱う適切なloaderがないとのエラー

```vue:Main.vue
export default {
  methods: {
    sound(name){
      if (name == 'SANA'){
        let audio = new Audio(require('@/images/TWICE/shyshyshy.mp3'))
        audio.play() }
    },
}
```


```
 ERROR  in ./images/TWICE/shyshyshy.mp3                                                                                                                                           friendly-errors 14:35:31
Module parse failed: Unexpected character '' (1:3)                                                                                                                                friendly-errors 14:35:31
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)                                                                                                                                                            friendly-errors 14:35:31
 @ ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options!./pages/Main.vue?vue&type=template&id=4630295c&scoped=true& 216:15-54
 @ ./pages/Main.vue?vue&type=template&id=4630295c&scoped=true&
 @ ./pages/Main.vue
 @ ./.nuxt/router.js
 @ ./.nuxt/index.js
 @ ./.nuxt/client.js
 @ multi eventsource-polyfill webpack-hot-middleware/client?reload=true&timeout=30000&ansiColors=&overlayStyles=&path=%2F__webpack_hmr%2Fclient&name=client ./.nuxt/client.js
```

versionは以下

```
$ npm -v
6.4.1
$ vue -V
@vue/cli 4.3.1
$ npx nuxt -v
@nuxt/cli v2.14.3
```

公式ドキュメントいわくwebpackの設定を拡張する必要があるとのこと
https://ja.nuxtjs.org/faq/webpack-audio-files/
ということでコピペして以下のようにnuxt.config.jsを修正

```javascript:nuxt.config.js
  build: {
    /*
    ** You can extend webpack config here
    */
    extend (config, ctx) {
      config.module.rules.push({
        test: /\.(ogg|mp3|wav|mpe?g)$/i,
        loader: 'file-loader',
        options: {
          name: '[path][name].[ext]'
        }
      })
    }
  }
```

無事再生できました。
インタープリタを作る その2

#概要

インタープリタを作ってみた。
電卓インタープリタを作って見た。

#出来ること。

3 + 3なら6を表示する。

#文法

演算子は+,-,/,*の４個。
数値、演算子は、スペース１個で区切る。
優先は、無い。左から順に実行。

#サンプルコード


```

var src = document.getElementById("src");

function isDecimal(operator) {
   var fc = operator.charAt(0);
   if (fc == "-")
   {
     return true;
   }
   else if (fc < '0') return false;
   else if (fc > '9') return false;
   return true;
}

function run() {
  var str = src.value;
  var code = str.split(" ");
  var l = code.length;
  var a = 0;
  var b = 0;
  var c = 0;
  for (var i = 0; i < l; i++)
  {
    switch (code[i])
    { 
    case "+":
      c = "+";
    break;
    case "-":
      c = "-";
    break;
    case "*":
      c = "*";
    break;
    case "/":
      c = "/";
    break;
    default:
      if (isDecimal(code[i]))
      {
        switch (c)
        { 
        case "+":
          a += parseInt(code[[i]]);
        break;
        case "-":
          a -= parseInt(code[[i]]);
        break;
        case "*":
          a *= parseInt(code[[i]]);
        break;
        case "/":
          a /= parseInt(code[[i]]);
        break;
        default:
          a = parseInt(code[[i]]);         
        }
      }
      else
      {
        alert("err");
      }
    break;
    }
  }
  alert(a);
  src.value = "";
}




```

#成果物

https://embed.plnkr.co/plunk/RG5OizOePm68zedv

#説明

字句解析は、スペースでsplitする。
3 + 3は、演算子＋を覚えておいて、数値がきた時に評価する。

以上。
[ESP32] メモリー

ESP32のESP32-WROVER-B MODULEのメモリーについて、メモします。
よく忘れてしまい
記憶にのこす。


### 1. Module
モジュールは実際に中にメソッドが二つある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137182/2e383209-5c40-4605-7f8d-63572d7517b7.png)

### 2. Spec

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137182/9a47ee2a-7b77-9ee0-1a74-b56cc1ce03d9.png)

https://www.wemos.cc/en/latest/d32/d32_pro.html


### 3. Schematic 

https://www.espressif.com/sites/default/files/documentation/esp32-wrover-b_datasheet_en.pdf

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137182/2e02b007-4416-61f6-cb24-2a76a788badc.png)


### 4. Memoryは

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/external-ram.html

メモリーはFlashとPSRAMがあり基本ESP32モジュールより活用度高い。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137182/01a9d38c-6a54-404b-c205-2c8564ad3e5d.png)


- PSRAMは自社のPSRAMを使っている。
- https://www.espressif.com/sites/default/files/documentation/esp-psram64_esp-psram64h_datasheet_en.pdf


### 5. Clock

- 使用するためにはCLOCKは必ず必要。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137182/cfd7877c-5d95-2f16-33d8-3edb53bd5680.png)

- Flash(4MB)はSCK/CLKからFLASH＿CLKの経路
- PSRAMはGPIO17からSRAM＿CLKの経路をもつ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137182/7ffe3775-40b1-8815-ba3e-a51adebebf02.png)

### 6. インターフェース

- SPI通信を使うので、CHIP　SELECTが必要。
- 回路図見てみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137182/bde93ffc-92ed-71ee-3ca5-d8d66bc69a2f.png)

- MOSI, MISOは共有する
お前まだTwitterの検索コマンド使ってるんw?

# Twitterの高度な検索が不便すぎる
みなさんご存知のTwitter.僕は最近ユーザー層の調査とかでTwitterの検索を使う機会が多いんだけどマジでこれ使いにくい．
![スクリーンショット 2020-08-29 12.26.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263501/d2f93c2c-de99-d3c3-ecb7-60663fa96a11.png)

使いにくい点
- 1回検索しないとこの表示が出ない
- 検索が毎回リセットされるので前の検索からちょっと変えるのが大変
- コマンドで検索に打ち込んでもいいけどそれもかなりめんどくさい
- 縦に長くて使わない項目も表示されていて見にくい

ということでこれらを解決していく．

# 作っていくぜ〜
## 完成品
まずは完成品を見てほしい
https://nyanko3141592.github.io/TwitterCustomSearch/

Twitterっぽいデザインにして公式感を出した．Bootstrapは偉大

## 検索の仕組み
Twitterの検索は検索の入力をそのままURLに反映しているだけなので，すごく簡単．
「あ」って検索すると"https://twitter.com/search?q=%E3%81%82&src=typed_query"
%E3%81%82は「あ」をURIエンコードしてるだけ．JSはencodeURI(string)で簡単にこれがあるので作るのも楽．「あ」を入れたくないときは「-あ」として-を入れるとその後ろのワードを除外できる．これもそのままエンコードしてURLにしてるだけなので簡単．詳しい検索のコマンドなどは自分でググってみよう．

## 検索の種類
Keyword
- キーワード検索
- 除外キーワード検索
- ORキーワード検索
- ハッシュタグ検索
Username
- @検索
- from検索
- to検索
Date
- since until検索
Engagement
- いいね数検索
- RT数検索
- 返信数検索
Filter
- リンクについて
- 返信について


こんなかんじのそれぞれについて検索のURLをみながらJSでいい感じにURLを作る．

## コード
全部公開してるのでこっち見て
https://github.com/nyanko3141592/TwitterCustomSearch.git

## 完成！
PC
![スクリーンショット 2020-08-29 12.42.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263501/54fca415-b2bc-e721-d14f-de2cf7754565.png)

スマホ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263501/55d8b8d3-5c1a-d1d1-bfd4-f04758977183.png)

# おわり
SCSS初めて使ったけどめちゃめちゃ便利だな
放置してたGCPを復活させる（１）- プロジェクト作成 -

今年1月にGCPを登録したが、なんだかめんどくさくなり放置。
初投稿もかねてGCPを復活させよう！！

GCP復活の作業履歴
[今回：放置してたGCPを復活させる（１）- プロジェクト作成 -](https://qiita.com/3S_Laboo/items/62322280d1844d461bab)
[放置してたGCPを復活させる（２）- VMインスタンス作成 -](https://qiita.com/3S_Laboo/items/03b54621479e193101f7)
[放置してたGCPを復活させる（３）- gcloud CLIインストール -](https://qiita.com/3S_Laboo/items/75682b3d008d0fdce355)
[放置してたGCPを復活させる（４）- PC(Windows10)からVMにssh接続 -](https://qiita.com/3S_Laboo/items/63a17738071a171decb1)
[放置してたGCPを復活させる（５）- VMのIPを固定する -](https://qiita.com/3S_Laboo/items/c897628aec6d04f4fe5f)
[放置してたGCPを復活させる（６）- nginxインストールとhttp設定 -](https://qiita.com/3S_Laboo/items/9a8446f84baa80252cb9)
[放置してたGCPを復活させる（終わり）- 独自ドメインの設定 -](https://qiita.com/3S_Laboo/items/cce944d49cbd1d4aa745)

# 現状確認

![2020-08-29_12h03_15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/ae38258f-cd3b-e926-41df-2f747f6e1f05.png)

．．．うん。何にもしてないね。

# プロジェクトを作成
![2020-08-29_12h32_16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/25de47f6-5689-71fb-958c-e43d856a1341.jpeg)
プロジェクト数のワーニングは出ているが、その他プロジェクトがないし無視しとこ。
作成！
![2020-08-29_12h36_22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/597dd8bd-df09-60a1-8473-1fe83debe4aa.jpeg)
ダッシュボードが出来た！

# 今後なにしよう？
うーん。。。VM作ります！

初投稿だからとりあえずここまで！
今後ともよろしくお願いします。

次回
[放置してたGCPを復活させる（２）- VMインスタンス作成 -](https://qiita.com/3S_Laboo/items/03b54621479e193101f7)
Windows環境でPycharmにPipenvをセットアップ

# はじめに
仕事でPython環境の構築が必要になりましたが、「手順書？無いよ」と言われたので今後のためにメモ。
また、環境構築の際に「pipenv又はanacondaでパッケージ管理した方が良いよ」とアドバイスを受けたので、PycharmとPipenvで初期設定をしてみたいと思います。

# 環境
- windows 10 professional
- Python 3.8.5

# 1.Pythonのインストール
Pythonは[こちら](https://www.python.org/)から自身のPC環境に合うものをダウンロードして下さい。
今回は何も考えずに最新版のPython 3.8.5をダウンロードします。

ダウンロードが完了したらpython-3.8.5.exeを実行しましょう。
![ins.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699822/9c708680-260a-66d7-b6c7-0ac6b99a8fa5.jpeg)
「Add Python 3.8 to PATH 」にチェックを入れることで環境変数PATHを設定できます。
チェックを入れた方は【2.環境変数の設定】はスキップして構いません。

# 2.環境変数の設定
以下のパスを環境変数のPATHに設定します。
`C:\Users\<ユーザ名>\AppData\Local\Programs\Python\Python38-32\`
`C:\Users\<ユーザ名>\AppData\Local\Programs\Python\Python38-32\Scripts\`

`<ユーザ名>`はPCのログインユーザ名に置換してください。
![ins - コピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699822/9e365743-6b72-f3b3-80ff-8f8b66d8b4eb.jpeg)
このような感じになっていればOKです。


# 3.Pipenvのインストール
- PowerShellを管理者権限で起動します。
- 念のため、pipを最新化しておきましょう。
`pip install --upgrade pip`
- pipenvをインストールします。
`pip install pipenv`

# 4.Pycharmのインストール
Pycharmは[こちら](https://www.jetbrains.com/ja-jp/pycharm/)からダウンロードして下さい。
コミュニティ版であれば無償で使用できます。

インストールが完了したらプロジェクトを作成します。
![a - コピー (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699822/24408b07-04b1-9c4d-7d81-3769af1dae81.jpeg)
+New Projectを選択
![a - コピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699822/786c8e7b-dcdd-e1af-874f-0933e215fe3e.jpeg)
`Location` プロジェクト保管先を任意で。
`New environment using` Pipenvを選択。
`Base interpreter` python.exeを指定。
`Pipenv executable` pipenv.exeを指定。

設定が完了したらCreateしましょう。
ここまででプロジェクトへのPipenv導入は完了です。

# 5.ライブラリのインストール
Pycharで`ctrl+alt+s`を押すと設定画面が開きます。
![a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699822/cab6fc47-acb0-159a-384a-f0c3caf96254.jpeg)
Project: pythonProject > Python Interpreterを開いて右上の+を押し、Available Packages画面を開きます。
![b.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699822/ccd20f83-ff2a-20fc-b62c-028cecdfc8ad.jpeg)
任意のライブラリ(今回はnumpy)を検索し、左下のInstall Packageボタンからインストールを行います。

# 6.Pipenvの使い方
【5.ライブラリのインストール】の完了後、Pipfileに加え、Pipfile.lockが生成されています。
![a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699822/76cfee8e-1682-19cb-b36c-93e54e6a1d94.jpeg)

Pipfile及びPipfile.lockには簡単に説明すると
- `Pipfile`　ユーザによるパッケージ及びバージョンの指定
- `Pipfile.lock`　実際にインストールされたバージョン
が書かれています。

そのため、最初にPipfile.lockを作成した人と同じ環境を再現したい場合は、Pipfile.lockを再現先のプロジェクトに移した上でターミナルから以下コマンドを実行すれば良いでしょう。
`pipenv install`

簡単になりましたがPycharmとPipenvの導入に関する解説は以上になります。
増産された Apache (httpd) の子プロセスを消すスクリプト

Apache のプロセスが大量にできてしまった時の急場凌ぎのスクリプトです。

「[プロセスの実行ディレクトリをリストアップする](https://qiita.com/KenjiOtsuka/items/3d0ce6effdcdc59944a8)」 に似た感じでスクリプトを書きます。

```sh
# EC2 で動くスクリプト
for pid in `ps aux | grep httpd | grep -v root | grep -v grep | tr -s ' ' | cut -d ' ' -f2`
do
  echo $pid
  sudo kill $pid
done
```

`grep -v root` を使って Apache の親プロセスは消さないようにしています。