OmniAICreator/Qiita-1.07M huggingface dataset:
Gravio 4で呼び鈴をバージョンアップしてLINE通知を追加してみる

[LINE通知ができるようになった][Prev-2]ので、[前に作った呼び鈴][Prev]もLINE通知使ってどこでも受け取れるようにしてみる。

# 使用環境

* Windows 10 20H2 (19042.746)
* Gravio HubKit v4.1.4049.0
* Gravio Studio v4.1.5432.0
* Gravioライト
* Gravioワイヤレススイッチ
* Amazon Polly
* LINE Notify

※GravioライトとGravioワイヤレススイッチはBasicプラン(月額500円)を契約するとレンタルすることができます。

# 事前準備
* [「Gravioで呼び鈴」][Prev]で、ボタンを押してライトが点き、スピーカーで通知されるところまでやっておく
* [「Gravio 4で温度をLINEに通知してみる」](https://qiita.com/zrock/items/d6bee5110ddff5b911da)を参考にLINE Notifyでトークンを取って通知できるようにしておく

# 手順
[「Gravioで呼び鈴」][Prev]で使ったアクションに**LINE Notify**コンポーネントを追加してプロパティを設定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/defebb46-0311-d2b3-ca98-22ed802c99ae.png)

| プロパティ | 値 | 例 |
|:-----------|:------------|:---|
|メッセージ  |投稿したいメッセージ|`お客様がいらっしゃいました`|
|トークン   |LINE Notifyで取得したトークン||

今回は、センサーのデータを埋め込まないのでそのまま メッセージ プロパティに通知メッセージを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/e326c2b0-9e0a-1be8-1a0e-2d4d37056103.png)

これで、ライトが見えなくても、スピーカーの音が聞こえなくても、スマホさえあれば気づくことができますね。

# 参考
* [Gravio][]
* [LINE Notify Component](https://doc.gravio.com/manuals/gravio4/1/ja/topic/line-notify-action-component)
* [LINE Notify][LINENotify]

[Prev]:https://qiita.com/zrock/items/388903d398477bb3e4cd
[Prev-2]:https://qiita.com/zrock/items/d6bee5110ddff5b911da
[LINENotify]:https://notify-bot.line.me/ja/
[Gravio]:https://www.gravio.com/jp
【Ruby】 かけ算メソッド

【コード】

```
def Multiplication (a, b)
 puts a * b
end

Multiplication(8, 9)
```

【出力結果】

```
72
```

【解説】
test.rbファイルを作成し、
メソッドMaltiplication(英語でかけ算の意)を定義して、(仮引数a,b)に数値を渡し、メソッド内の実行したい処理 puts a * bで出力します。

実引数Multiplication(数値,数値)の数値に値を入力すると、かけ算の結果を得ることが出来ます。

VSコードのRails環境では、ターミナルにてruby test.rbで実行することが出来ます。

*defはDeginition(定義の略)
Kotlin Json文字列のserialization　正しい対処できなかったので逃げ対応で対処しました

　金田著「[はじめてのandroidプログラミング 第５版](https://www.sbcr.jp/product/4815607968/)」を使って、勉強しています。

　「第１０章アニメーションする　ツーリスト情報アプリを作ろう」の第一段階ｐ３９３まで、写経が進みました。コンパイルしたところ、次のようなエラーが発生しましたので報告します。

　また、より正しそうな変更方法が、@Teramonte4 さんのご教示により分かりましたので、本レポートの続編「[Kotlin Json文字列のserializationのParseが使えなくなったので、使えるように修正しました。](https://qiita.com/guijiu/items/9314ce8c4dd8af4d40cb)」も参照してください。（2021/02/02追記)

　以下、本書を持っている前提で説明します。本書を使って勉強中の方、一緒に勉強しましょう。

##1.エラーの発生状況

```
e: E:\Engineering\AndroidStudioProjects\hajimeteno5\TouristSights\app\src\main\java\com\example\touristsights\Sight.kt: (12, 1): 
Your current kotlinx.serialization core version is too low, 
while current Kotlin compiler plugin 1.4.21 requires at least 1.0-M1-SNAPSHOT. 
Please update your kotlinx.serialization runtime dependency.
（現在のkotlinx.serializationコアのバージョンが低すぎます。
現在のKotlinコンパイラプラグイン1.4.21では1.0-M1-SNAPSHOT以上が必要です。
kotlinx.serialization のランタイム依存関係を更新してください。）
```

　これは、次のコードで発生していました。

```Sight.kt
package com.example.touristsights

import kotlinx.serialization.Serializable
// 省略
@Serializable    // ここで発生
class Sight ( )

```
##2.調査
　付属のソースコードと比較してみると、build.gradle(Project)ファイルの次の部分で差異がありました。（コメントアウト削除の方が、エラーが発生した時。）


```build.gradle 
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
//    ext.kotlin_version = "1.4.21"     // 削除
    ext.kotlin_version = "1.3.72"       // 修正
    repositories {
        google()
        jcenter()
    }

```

##3.一時対策
　修正の通り、変更しSyncNowを実行し、再コンパイルしたところ、成功しました。（とりあえず、現状、写経を目的としているため、とりあえずこれで良しとします。）

##4.原因として考えられること
AndroidStudioのバージョンの違い、或いはKotlinのバージョンの違い
私　　　：ver.4.1.2
本の推奨：ver4.1


##5.本当の対策方法
　ググったところ、「[【2020年秋版】kotlinx.serializationで配列のJson文字列をパース](https://qiita.com/Teramonte4/items/041c792339d28189a787)」という資料を見つけた。試してみようと思いましたが、

```
plugins {
    id 'org.jetbrains.kotlin.jvm' version "$kotlin_version"
    id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version"
}
```

を入れる部分が分からなかったので、今日は諦めました。今後、写経が終わったら、gradleを勉強しつつ、また[kotlinx.serialization 1.0 released](https://blog.jetbrains.com/kotlin/2020/10/kotlinx-serialization-1-0-released/)といった資料を物色して、再挑戦したいと思います。
　どなたか、対策を見つけられたら教えてください。

##6.その他追記：表示の回転について
　本アプリは、表示を回転させ、横画面でも表示できるように作られているが、エミュレータの端末（Nexus5x API30）で回転すると、なぜか縦表示のままです。本書指定のpixel2 api30や実機huawei nova lite（CAZ-TL10）、そしてhuaweiP10lite（was-lx2j)では正常動作を確認しました。
Permission Denied Error Doker Laravel 

Dockerでlaradockを導入し、laravelを起動したとき、以下のエラー文が出ました。
```docker The stream or file "/var/www/storage/logs/laravel.log" could not be opened in append mode: failed to open stream: Permission denied
```
```chown -R www-data:www-data /var/www
chmod -R 777 /var/www/storage
```

権限を変更してあげると、無事にlaravelを表示することができました。

以下のサイトを参考に、しました。
https://stackoverflow.com/questions/48619445/permission-denied-error-using-laravel-docker
[未経験エンジニア]のオリジナルアプリ制作の反省1.「ビューは先にしっかり作っとけ」

## 誰なのか
某短期集中エンジニア養成プログラムでエンジニア転職を目指している者です。
エンジニアとして学習を始めて、現在2ヶ月になります。

## 何を書くのか
- オリジナルアプリを制作した過程で「もっとこうしておけばよかった...」と後悔した部分
- 「ここは、実装難しかったな...」と、思った部分

について,**1日1つ取り上げ、ネタがなくなるまで投稿します。**

基本的には、自分の備忘録としての記録となりますので、至らない点も多々あるかと思います。
**それでも、もし僕みたいに「未経験からエンジニアになろう！」と思っている人の参考になれば**幸いです。

## 環境
ruby: 2.6.5
Rails: 6.0.3.4

# 今回の結論
タイトルの通りです。**ビューをあらかじめ作っておくことの重要性**をひしひしと感じました。
ソースコードも交えてお話しします。

## こうしとけばよかった！
具体的には、開発を始める前の企画段階で
- リセットcssについての知識が足りておらず、とりあえずcssの設定を機能実装の都度ちょこちょこしていたこと
- レスポンシブデザインを考慮しない設計構造になっていたこと

の2つを課題として考えています。

## なぜそうなってしまったのか
要件定義の段階で、実装したい機能は決まりました。しかし、それを支えてくれるページレイアウトに関しては、当初、フロントエンドに対して苦手意識もあり、**「機能を開発する度に」**html, cssを作成するやり方で進めていたのが、失敗の原因だと思います。一般的な開発ではどうなのか分かりませんが、これは自分にとって最終的に悪い形で帰ってきました。

## 今後に向けて考えたこと
個人開発、ポートフォリオ向けの開発には、webフレームワーク（有名なのは[boostrap](https://getbootstrap.jp/)）などを用いて大体のレイアウトを整えるのも一つの手段だと思います。
しかし、今回あげた課題に共通するのは、そもそもwebアプリケーション全体としてのゴールを見通せてなかったことにあると思います。

ゴールは、最初に決めておいた方がいいですよね。すなわち、要件定義の際に、ページレイアウト、画面遷移図などを、メモの時点でほとんど完成系に近づけるべきだということです。

このように提案する理由は、サーバーサイドとフロントエンドがお互いに影響を及ぼす可能性を排除できないことにあります。一つ例を挙げます。form_with, link_toのようなヘルパーメソッドのブラウザ上の表示は、html, cssの言語に変換されて表示されます。

例えば、[form_with](https://pikawaka.com/rails/form_with)は、フォームを作成することができるヘルパーメソッドです。

```erb

<%= form_with url: "/posts", method: :post, local: true do |f| %>
  <%= f.text_field :title %>
  <%= f.submit '投稿する' %>
<% end %>
```
このように記述された場合、ブラウザ上では

```html
<form action="/main" method="post">
  <input type="text" name="title">
  <input type="submit" value="投稿する">
</form>
```
と表示されます。

以上から、サーバーサイドとフロントエンドは密接に関わり合っていることがわかってもらえたと思います。

## アクションプラン
- ページレイアウト（ビュー）は、サーバーサイドやJavaScriptなど、レイアウトに影響を及ぼす要素を踏まえて完成度60~70%くらいまで企画で決めておき、先に実装を進めておく。
- リセットcssは、レイアウト全体（物によっては字体まで！）に影響を及ぼすので、一番最初に導入し、読み込ませる。
- レスポンシブなサイトになるように、企画の時点で、少なくとも「その箱の中でどのくらいの存在感を持たせるのかという割合（％」）」を決めておく。できるなら、もっと細かくpx単位で考えぬく。
- もしサーバーサイドとして活躍したいなら、時には[boostarp](https://getbootstrap.jp/)などのフレームワークも用いる。

## 最後に
最後まで読んでいただいた皆様、ありがとうございます。
ソースコード、記事の書き方について**「もっとこうしたほうがいいよ！」というご意見**、**「そこどうなっているの？」というご質問**など、お待ちしております。

## 参考文献
・【Rails】form_withの使い方を徹底解説！
https://pikawaka.com/rails/form_with

・【個人開発・ポートフォリオに】簡単にいい感じのデザインにできるサービスまとめ
https://qiita.com/aiandrox/items/4196c8f5b564d29fdce7
UbuntuでのWebcam確認

# 背景

[Azure IoT Edge](https://azure.microsoft.com/en-us/services/iot-edge/)で[Live Video Analytics](https://azure.microsoft.com/en-us/services/media-services/live-video-analytics/)というモジュールがあり、カメラソース情報を設定しなければいけません。もし、Webcamなど複数カメラを接続している状態ならどのカメラがどちらにつながっているか動作確認と共に事前確認すべきなので困らないようにarm64またはx86-64アーキテクチャのUbuntuで確認する方法についてまとめておきます。
Webcamは[UVC](https://help.ubuntu.com/community/UVC)タイプならLinuxで問題なく使えます。

# 確認方法

## 1. CLIコマンド

```bash
$ ls /dev/video*
$ lsusb -v
```

## 2. Cheese Webcam Application

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/35b02ead-0d52-35e0-21eb-b47f6d504de0.png)

```bash
$ sudo apt-get install cheese
$ cheese
```
### カメラ切り替え

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/382c07b0-4ac6-aa9f-5aad-216e67ff594e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/6806ca74-d84c-9f4b-411a-ff2da9457331.png)

## 3. VLC media player

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/f2c7ca45-df9b-84aa-daad-87ba69ded258.png)

```bash
$ sudo apt-get install vlc
$ ls /dev/video*
$ vlc v4l2:///dev/video0
```
レポートのエクスポートでxlsx形式を選択する

とっくの昔に対応できていると思っていましたが、実はspring 21対応みたい。
改めてsandboxを調べると対応している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/4a72368e-2a0a-b91c-3910-36d561ba31e5.png)



このアイデアは既に提供済となっているんだけど...
https://trailblazer.salesforce.com/ideaView?id=08730000000jWLvAAM


最新のリリースノート
https://help.salesforce.com/articleView?id=release-notes.rn_rd_reports_details_email.htm&type=5&release=230
Github+Cloud9連携

#1 git init+git add -A

```
$ cd アプリ名
$ git init
$ git add -A
```

#2 git commit+git remote add

```
$ git commit -m "first commit"
$ git remote add 登録名　登録したいgithubレポジトリURL
```

#3 git push

```
$ git push 登録名　master
```
Pycharm　キーボードショートカット

Matlabからpythonに移住するにあたって、Pycharm(professional版)を使うことにしたので、キーボードショートカットをメモ。


#まずはセルの区切り方
キーボードショートカットのメモといいつつ、まずはセクショニング。

matlab

```matlab
hoge
%%
fuga
```


pycharm

```python
hoge
#%%
fuga
```
これでhogeとfugaの間でセルが区切れる。
#pycharmの細かい設定とか
・表示メニューからscientific modeをオンへ
・pycharm > preference > tool > python scientificと進み、ツールウィンドウにプロットを表示　をオフに

これで大体matlabチックな感じになる。
あと、macのデフォルトだと^Spaceが日本語英語切り替えとかぶるので、環境設定>キーボード>ショートカット>入力ソースから設定を変えておくと良い


#キーボードショートカット
（ちなみに、macを使っているのでMatlabのショートカットはmac版のもの）
⇧ shift　⌘ command　⌥ option　^ control　⏎ return

|操作内容|Matlab|PyCharm|
|---|---|---|
|選択範囲を実行|⇧F7|⌥⇧E|
|セルを実行|⌘⏎|
|セルを実行して次へ|⌘⇧⏎|^⏎|
|ファイルを実行|⌥⌘R|^R|
|設定|⌘,|⌘,|
|コメント|⌘/|⌘/|
|アンコメント|⌘T|⌘/|
|コード補完|Tab(?)|^Space
|コードの整形|⌘I|⌘⌥L|
|クリップボードの履歴から貼り付け| |⌘⇧V
|保存|⌘S|⌘S|


思い出したら足すかも。
Windows環境のCognosでtempディレクトリの使用状況を確認する

#はじめに

Cognosのレポート実行時に一時ファイルがどの程度生成されているか、tempディレクトリの使用量はどの程度かを確認したいことって多いですよね。
Linux環境だとNMONなどで簡単に取得できるのですが、Windows環境だとなかなかそうはいかないです。

Windows環境においても特定のレポート実行時のtempの使用状況をモニターしたい場合の手法を確立することができましたのでご紹介します。


#Windows環境でtempディレクトリの使用状況をモニターする

tempディレクトリの使用状況をモニターするPowerShellを仕掛けます。
PowerShellの中身はこんな感じです。

```PowerShell:cognos_temp_monitor.ps1
$i = 1

cd E:\cognos\temp

while ($i -le 5) {
date >> 'F:\work\cognos_temp_monitor\cogtempmonitor.txt'
ls | ForEach-Object -Process { "$_"; Get-ChildItem -Path "$_" -Recurse -Force | ForEach-Object -Begin { $Len = 0 } -Process { $Len = $Len + $_.Length } -End { $Len / 1024 / 1024 / 1024 }; " " } >> 'F:\work\cognos_temp_monitor\cogtempmonitor.txt'
sleep 1;
}
```

※tempディレクトリ、ログ出力先ディレクトリ、ps1ファイル名、ログファイル名などは各環境に合わせて設定してください
※ps1コマンドを使用するので最小時間間隔は1秒となります

レポート実行前にps1スクリプトを実行し、temp使用状況を確認したい時間が終了したらps1スクリプトを停止します。


#取得した結果をテキストエディタで整形する

PowerShellのログをExcelでグラフ化する事前準備としてテキストエディタで整形をします。
下記が手順になります。

1. 取得したログファイルをテキストエディタで開きます。※ここではsakuraエディタで開いています
2. 「置換」を開く (Ctrl+r でショートカット)
3. 「正規表現」にチェックを入れる
4. 1回目の文字列置換を行う


置換文字列は下記の通り
置換前： \r\n
置換後：  <半角スペース1文字>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/3f3499d1-3103-7c31-5483-bfc338f29630.png)


5. 2回目の文字列置換を行う

置換文字列は下記の通り
置換前： 2020年
置換後： \r\n2020年

※計測年によって2021年に読み替えてください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/6df1f3c7-efe1-a166-88ff-00b56cfb7d8e.png)

この置換処理により1行1秒ごとのデータに整形されます。
エディタでの事前作業は以上になります。



#Excelにデータをコピーする

エディタで整形したデータをExcelにコピーしグラフを作成していきます。
手順は下記の通りです。

1. テキストエディタ上の全文字列を全選択 & コピーをする
2. 空白のExcelファイルを開き、エディタでコピーしたデータを貼り付ける
3. Import Wizardを開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/0276eb1f-054c-b85e-391f-d1c4c4244678.png)

4. 「スペース」をキーに列を分割する。
※特に意識することなく「Next」で進み「Finish」を押していけば、列の分割は完了します。


#グラフ化して結果を確認する
最後に必要なデータを使ってグラフを作成します。

1. vmmで始まる列の有無を確認する
※今回の環境ではだいたいAO列あたりから左側にありました。
※udaファイルがあれば合わせてハイライトし合計する
2. vmm列の右側のセル（ファイル容量が記載された列）を黄色くハイライトする (目印を付ける)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/07c6fb01-8e22-49d7-db9d-6dcc43f866cb.png)


3. 1列ずつ左にズレながらデータがあるか確認する (ctrl+↓ や ctrl+↑ を使ってカーソル移動するとデータ探すのが簡単です)
4. 目印を付けた列を合計する列を準備する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/9f7d1609-bd24-6df7-96b5-312af4af524a.png)



5. Time列とGB列を選択してF11キーでグラフを作成する


以上でtempフォルダの一時ファイル使用量がグラフ化できます。
仕様業況を確認し、想定以上に大きな一時ファイルが作成されていないか、tempディレクトリの容量は適切化などの判断材料に活用ください。
CakePHP4 国際化の日本語対応

あまりまとまった方法が無かったので
国際化の日本語対応について、まとめてみました。

## 翻訳ファイル作成
```
cd Cakeフォルダ
./bin/cake i18n extract
```
（全部否定しないで実行する）

## ファイル確認

```
ls -al resources/locales
```
以下の２ファイルが作成される。

1. cake.pot(Cake本体システムで利用されているメッセージ)
2. default.pot(独自で作成したメッセージ)

## 日本語ロケールフォルダの作成
```
mkdir resources/locales/ja_JP/
```
## 日本語翻訳ファイルの作成

```
cp resources/locales/cake.pot resources/locales/ja_JP/cake.po
cp resources/locales/default.pot resources/locales/ja_JP/default.po
```
出来上がったファイルが翻訳対象のファイルになります。
これをPoeditなどで開いて翻訳処理をします。


## 日本語翻訳ファイルの反映方法
```
./bin/cake cache clear_all
```

ローカル開発の場合の確認方法

```
./bin/cake server
ls -al tmp/cache/persistent/
```


## 更新方法

再度翻訳ファイルを作成して、既存のファイルに差分を取り込みする。

```
cd Cakeフォルダ
./bin/cake i18n extract

msgmerge -U  resources/locales/ja_JP/default.po resources/locales/default.pot
msgmerge -U  resources/locales/ja_JP/cake.po resources/locales/cake.pot
```
コードによるimageの切り替え

flagを立ててimageの切り替えを制御



```ViewController.swift
var flg = false


@IBAction func button(_ sender: Any) {      
  if flg {
            flg = false
            //画像なし
            self.button.setImage(nil, for: .normal)
        } else {
            button.setImage(pause, for: UIControl.State())
            flg = true
        }
```
Railsでrails sしてもサーバーが立ち上がらない

# 起きた現象
ターミナルでいつもどおり「rails s」コマンドでローカルサーバーを立ち上げようと思ったら以下のエラーが出た。

```ruby
A server is already running. Check /Users/terashimatakaya/projects/chat-app/tmp/pids/server.pid.
```

「サーバーはすでに動いています」と指摘されました。

# 解決①
ご指摘のパスにあるserver.pidファイルを削除し、もう一度「rails s」を実行。
すると、、、


```ruby
(略) Address already in use - bind(2) for "127.0.0.1" port 3000 (Errno::EADDRINUSE)
```

またエラー。
どうやら http://localhost:3000 のアドレスで使っているポート番号がすでに使われているということらしい。

ポート番号を3000以外の3001とかに指定する方法も見つかりましたが、根本解決にならないので別の方法で解決します。

# 解決②
ググって以下のコマンドを見つけたので実行。

```ruby
terashimatakaya@MacBook-Air chat-app % ps ax | grep rails
49845 s003  S+     0:00.01 grep rails
terashimatakaya@MacBook-Air chat-app % kill -9 49845
kill: kill 49845 failed: no such process
```

１つ目のコマンドで実行中のプロセスを検索し、処理を止めるようkillコマンドを実行。
→「そんなプロセスはないぜ？」と指摘されました。

# 解決③
もう少しググって以下のコマンドを実行したら無事にサーバーが動き出しました！

```ruby
terashimatakaya@MacBook-Air chat-app % lsof -i :3000
COMMAND   PID            USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ruby    48924 terashimatakaya   12u  IPv4 0xedd14d7d782588d1      0t0  TCP localhost:hbci (LISTEN)
ruby    48924 terashimatakaya   13u  IPv6 0xedd14d7d73022519      0t0  TCP localhost:hbci (LISTEN)
ruby    48924 terashimatakaya   25u  IPv6 0xedd14d7d77b10b79      0t0  TCP localhost:hbci->localhost:58238 (CLOSE_WAIT)
terashimatakaya@MacBook-Air chat-app % kill -QUIT 48924
```

今の時点では「実行中のプロセスのPID番号を指定して処理を停止した」くらいの理解ですが、**そもそものエラーの原因はサーバーが起動したままターミナルを終了したこと**だと思います。

今後はサーバーは必ず「Ctr + C」でストップさせてからターミナルを終了するようにします！
エンジニア独学者は暇なときに言語リファレンスを読むべき

# 言語リファレンスを見ていないとどうなるのか？
エンジニアの独学にありがちなのが、手探りで調べながらものづくりをすることだと思う。
例えば、LaravelでWebアプリを作る際に、「テンプレートってどうやって書くんだろう」「認証ってどう作るんだっけ」など、必要になった機能をその都度検索しながら新しい知識を得ていく。

しかし、それでは自身の想像の範囲の知識しか得られない上に、せっかくLaravelを触っているのに言語のことを学びにくい。
さらに、フレームワークで対応しきれないケースや、バージョンによる不具合に遭遇して詰まったときに打つ手なし、といった事態に陥る。

# なぜ言語リファレンスを見るべきなのか？
そんなときに助けになるスキルとして、「言語そのものの機能で実装できる力」だと思う。
そのため、言語で出来ることをできるだけ多く頭に入れておくことが鍵となってくる。

# 言語リファレンスは全部頭に入れるべき？
だからといって、すべてを暗記する必要はない。
(暗記できるならそれに越したことは無いが…)
通勤時間の5分だけでもいいし、寝る前の5分でも良いので、使っている言語のリファレンスを眺めるだけでいい。
その言語にどんな関数があって、どんなことが出来るのかを頭に入れておいて、「あんなことができたなぁ」と思い出せるようにしておくだけで、打つ手なしな状況はかなり減る。

熱心な学習者さんは眺めた関数を使って見ると良いだろう。

# まとめ
独学だと即ものが出来るフレームワークをいじって遊ぶのが楽しい(筆者もそう)。
しかし言語そのものの学習もちゃんとやると後に活きてくるので、是非やってみてほしい。

# (参考)言語リファレンスリスト
参考までに筆者が触っている言語のリファレンスリストを記す。
(極力1次情報を見るように英語も頑張って読む)

|言語等|URL|
|---|---|
|PHP|https://www.php.net/manual/ja/langref.php|
|JavaScript|https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference|
|Go(Jan 14,2020)|https://golang.org/ref/spec|
|Python(3.9.1)|https://docs.python.org/ja/3/reference/index.html|
|Ruby(3.0.0)|https://docs.ruby-lang.org/ja/3.0.0/doc/index.html
Jenkinsfileのlintをローカルマシンで行うための覚書

## 参考記事

- [VSCode上でのJenkinsfileのチェック(lint)](https://qiita.com/hisato_imanishi/items/6300105c39ccb922da97)
- [Jenkinsをdocker上に構築](https://qiita.com/legitwhiz/items/e6ac1f5a94f09ff2bb1d)
- [docker run --restart=alwaysがどれくらいrestartしてくれるか調べた](https://qiita.com/manabuishiirb/items/f7edf11572f9256018b2)
- [Jenkins を触ってみよう](https://iij.github.io/bootcamp/cicd_infra/jenkins/#%E4%BA%8B%E5%89%8D%E6%BA%96%E5%82%99)

## 前提

- Docker for Windows と VSCode を入れる
- Jenkinsを起動(とりあえずローカルの50100/50101番ポートを使う|自動起動設定)  
  `docker run -d -p 50100:8080 -p 50101:50000 --restart=always jenkins/jenkins:lts`
    - 起動したコンテナIDを落とすには  
      `docker kill $(docker ps -qf "ancestor=jenkins/jenkins:lts")`
- JenkinsのAdminパスワードを取得しておく  
  `docker logs $(docker ps -qf "ancestor=jenkins/jenkins:lts")`
- Jenkinsの初期セットアップをしておく(ここ自動化したいところ)
  - http://localhost:50100/ を開く
  - ↑で取得したパスワードでログイン
  - `Install suggested plugins`
  - ユーザー作成はスキップ
  - URL作成はそのまま進む
  - ログイン画面でadminを入力
  - JenkinsHomeに行ったら成功
- VSCodeに`Jenkins Pipeline Linter Connector`を入れる
- `Jenkins Pipeline Linter Connector`の設定をする  

    |パラメータ名|値|
    |---|---|
    |`Connector: Url`|`http://localhost:50100/pipeline-model-converter/validate`|
    |`Connector: Crumb Url`|`http://localhost:50100/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,%22:%22,//crumb)`|
    |`Connector: User`|`admin`|
    |`Connector: Pass`|↑で取得したパスワード|
    |`Connector: Strictssl`|`false`|

- あとはJenkinsfileを開いて`validate jenkinsfile`を実行する
Homebrew 経由の anyenv 経由の tfenv 経由で Terraform をインストールする

## はじめに

anyenvのインストール自体は、こちらの記事を参考にしてください。

- [Homebrew 経由の anyenv 経由の nodenv 経由で Node.js をインストールする](https://qiita.com/ucan-lab/items/ce35bcaf2562054917a8)

## anyenvのアップデート

```shell-session
$ anyenv update
```

anyenv, anyenv のプラグイン, **env, **env プラグインをまとめてアップデートしてくれます。

## anyenvのバージョン

```shell-session
$ anyenv -v
anyenv 1.1.2
```

## anyenv でインストール可能なenv系一覧

```shell-session
$ anyenv install -l
```

今回は `tfenv` をインストールします。

## インストール済みのenvツール一覧

```shell-session
$ anyenv versions
```

tfenvがインストールされてなければ、インストールします。

## tfenvのインストール

```shell-session
$ anyenv install tfenv
$ exec $SHELL -l
```

```shell-session
$ tfenv --version
tfenv 2.0.0-37-g0494129
```

## Terraformのインストール可能なバージョン

```shell-session
$ tfenv list-remote
```

## Terraformのインストール

```shell-session
$ tfenv install latest
$ tfenv install latest:^0.12 # 0.12系の最新バージョン
$ tfenv install 0.12.0 # バージョン指定
```

## Terraformのバージョン切り替え

```shell-session
$ tfenv use 0.14.5
$ tfenv use 0.12.30
```

## terraformのバージョン確認

```shell-session
$ terraform -v
Terraform v0.12.30
```

## terraformのバージョン一覧

```shell-session
$ tfenv list
tfenv list
  0.14.5
* 0.12.30 (set by /Users/ucan/.anyenv/envs/tfenv/version)
  0.12.0
```

## .terraform-version

プロジェクトルートに `.terraform-version` を置くとファイルに書かれたバージョンを
優先して利用します。

```shell-session
$ echo 0.14.5 > .terraform-version

$ terraform -v
Terraform v0.14.5
```

```shell-session
$ echo latest:^0.12 > .terraform-version

$ terraform -v
Terraform v0.12.30
```

## Terraform 実行

```
$ terraform init
```

```
$ terraform plan
```

```
# 適用されるので注意して実行する
# terraform apply
```
f-stringsで衛星画像ファイルに名前を付けながら保存(Python)

##概要
こんにちは。
衛星画像ファイルを処理して作成したファイルを保存する際に、逐一ファイル名を手動で付けていくのは面倒です。Linuxなりのコマンドラインでやってしまうのも一手ですが、pythonでNumpy Arrayの形で保持しているものをそのまま画像として保存できれば手間が少なくて済みそうです。f-stringsを使うことで「Numpy array→いい感じのファイル名で保存」手順が自動で進むので、簡単にご紹介できればと思います。f-stringsについての詳しい説明はこちらなどを参考にしてみてください⇒[Pythonのf-stringsについてしっかり調べてみた](https://qiita.com/simonritchie/items/74f544944ee11a226613,"Pythonのf-stringsについてしっかり調べてみた")

##前提条件
1. Google Colabで実行 (記事執筆時点でのバージョンはpython 3.6.9)
2. 辞書型配列の形で年月日とNumpy Arrayが紐づけられていること

##コード
```python:SaveImages.py
from PIL import Image

#database_arrayは辞書型配列で、keysには対象年、valuesには画像として保存したいarrayが入っています

for y in database_arary.keys():
 img=Image.fromarray(database_array[f"{y}"].astype(np.uint8))
 img.save(f'/content/drive/My Drive/Colab Notebooks/outputs/output_{y}.png')

```
コードとしてはこれだけですが、沢山ある処理結果に名前を付けるのがとても楽になったので、よろしければお試しください！
WEB負荷ツール

## ApacheBench

#### インストール
```
yum install apr-util
```

#### 使い方例
```
ab -n 1 -c 2 -t 3 http://hogehoge
```

#### usage
```
Usage: ab [options] [http[s]://]hostname[:port]/path
Options are:
    -n requests     Number of requests to perform
    -c concurrency  Number of multiple requests to make at a time
    -t timelimit    Seconds to max. to spend on benchmarking
                    This implies -n 50000
    -s timeout      Seconds to max. wait for each response
                    Default is 30 seconds
    -b windowsize   Size of TCP send/receive buffer, in bytes
    -B address      Address to bind to when making outgoing connections
    -p postfile     File containing data to POST. Remember also to set -T
    -u putfile      File containing data to PUT. Remember also to set -T
    -T content-type Content-type header to use for POST/PUT data, eg.
                    'application/x-www-form-urlencoded'
                    Default is 'text/plain'
    -v verbosity    How much troubleshooting info to print
    -w              Print out results in HTML tables
    -i              Use HEAD instead of GET
    -x attributes   String to insert as table attributes
    -y attributes   String to insert as tr attributes
    -z attributes   String to insert as td or th attributes
    -C attribute    Add cookie, eg. 'Apache=1234'. (repeatable)
    -H attribute    Add Arbitrary header line, eg. 'Accept-Encoding: gzip'
                    Inserted after all normal header lines. (repeatable)
    -A attribute    Add Basic WWW Authentication, the attributes
                    are a colon separated username and password.
    -P attribute    Add Basic Proxy Authentication, the attributes
                    are a colon separated username and password.
    -X proxy:port   Proxyserver and port number to use
    -V              Print version number and exit
    -k              Use HTTP KeepAlive feature
    -d              Do not show percentiles served table.
    -S              Do not show confidence estimators and warnings.
    -q              Do not show progress when doing more than 150 requests
    -g filename     Output collected data to gnuplot format file.
    -e filename     Output CSV file with percentages served
    -r              Don't exit on socket receive errors.
    -h              Display usage information (this message)
    -Z ciphersuite  Specify SSL/TLS cipher suite (See openssl ciphers)
    -f protocol     Specify SSL/TLS protocol
                    (SSL3, TLS1, TLS1.1, TLS1.2 or ALL)
```
NetCommons2でxampp環境に復元した時に_INVALID_INPUTエラーがでたので対応

NetCommons2で開発環境に復元した時に、トップページで`_INVALID_INPUT`が表示されて、この画面をリダイレクトし続ける症状がでました。
原因を調査したので、記事として残します。

`_INVALID_INPUT`エラーは入力不備の内容のため、原因が他の場合があります。

## 原因

DB復元時に必要なテーブルが抜けていたため、`_INVALID_INPUT`エラーがでてました。
全DBテーブルを復元したら直りました。

## エラー画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109904/3a8f6bb3-02d8-a46c-57a1-3795df1956df.png)

## `_INVALID_INPUT`発生個所

https://github.com/netcommons/NetCommons2/blob/develop/html/maple/nccore/db/DbObjectAdodb.class.php#L920

```php:maple/nccore/db/DbObjectAdodb.class.php
	/**
	 * エラーメッセージ追加処理
	 * @param	string	error_no
     * @param	string	error_mes
	 * @access	public
	 */
	function addError($error_no=null, $error_mes=null)
	{
        $container =& DIContainerFactory::getContainer();
	    $actionChain =& $container->getComponent("ActionChain");
		$errorList =& $actionChain->getCurErrorList();
		if($error_no == null && $error_mes == null) {
			$session =& $container->getComponent("Session");
			if(isset($session) && $session->getParameter("_php_debug") == _ON) {
				$errorList->add($this->ErrorNo(), $this->ErrorMsg(). ":\n". $this->_bck_sql);
			} else if (defined('_INVALID_INPUT')) {
				// ここで落ちていた。
				$errorList->add($this->ErrorNo(), _INVALID_INPUT);
				// 下記を追記。落ちが原因のSQLを画面表示できます。
				$errorList->add($this->ErrorNo(), $this->ErrorMsg(). ":\n". $this->_bck_sql);
			} else {
				$errorList->add($this->ErrorNo(), "Security Error!  Unauthorized input.");
			}
		} else {
			$errorList->add($error_no, $error_mes);
		}
	}
```

## 原因２

xampp環境にmysqlインポート時に`default-character-set`オプションを付け忘れ、エラーがでてDBテーブルを全て復元しきりませんでした。

正解コマンド

```
> mysql -u root --default-character-set=utf8 db_name < dump.sql
```

間違いコマンド

```
> mysql -u root db_name < dump.sql
ERROR at line 2612: Unknown command '\n'.
```



## 参考URL

【MySQL】Unknown command ‘\”. at softelメモ
https://www.softel.co.jp/blogs/tech/archives/3397
RDBまとめ

##リレーショナルデータベース(RDB)
```
現在もっとも広く利用されているデータベース
エクセルのシートのように列と行からなる2次元の表形式（テーブル）でデータを管理。
複数の表が項目の値で関係付けられている。
SQLという専用の言語を使ってデータを操作す
2次元の表形式（リレーション）でデータを管理する
表と表との間に「関係（リレーション）を定義する」ことができる。
関連を利用してデータを定義することで効率的なデータ管理が可能になる。

2次元の表形式（リレーション） = RDBでデータを管理する
表と表との間に「関係（リレーション）を定義する」ことができる。
関連を利用してデータを定義することで効率的なデータ管理が可能になる。

```

##データベースマネジメントシステム（DBMS）とは
```
データベースを管理するコンピュータシステムのこと。
データを操作する手段や、操作の整合性管理、バックアップや障害対策など、さまざまな機能をもっている
```


##DBMSの種類

```
– 階層型データベース（ツリー型）

–ネットワーク型データベース(Network (CODASYL) Data Model)

–リレーショナルデータベース(Relational Database : RDB)

– XML型データベース(XML Database : XMLDB)

– オブジェクト型データベース(Object Oriented Database : OODB
```
addChildでUIViewControllerに親子関係を持たせる


`addChild(childController: UIViewController)`を使うとUIViewControllerの階下にUIViewControllerを持たせることができます。UI部品を配置するための`addSubView()`と違い`addChild()`はUIViewControllerそのものを重ねることができます。


![スクリーンショット 2021-01-29 14.01.45.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/71a44724-21c0-6cd0-6dfd-9bf6a55b83bf.jpeg)

### ソースコード

親となるViewControllerでは`addChild()`だけでなく`addSubview()`も呼ばないと階層関係になっていることを確認できなかった。

```Swift:ParentViewController
class ParentViewController: UIViewController {
    
    override func viewDidLoad() {
        let childVC = ChildViewController()
        super.viewDidLoad()
        view.backgroundColor = .red
        view.addSubview(childVC.view)
        addChild(childVC)
        childVC.didMove(toParent: self)
    }
}
```

```Swift
class ChildViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .blue
    }
}
```
Active Strageを用いた複数画像の投稿

# 1.Active Strageのインストール
まずターミナルでactive strageのインストールの実行、そしてrails db:migrateの実行をします。

```
% rails active_storage:install
```

```
% rails db:migrate
```

# 2.モデルにてアソシエーション
次に紐付けをしたいテーブルにアソシエーションをします。この時に使うのがhas_one_attachedです。has_one_attachedというのは各レコードとファイルを紐付けます。複数の画像を投稿する場合この数を増やせば良いです。

```ruby:post.rb
      has_one_attached :image1
      has_one_attached :image2
```

# 3.コントローラーにてストロングパラメターの追加
コントロラーのファイルにて画像のストロングパラメターの記述をします。これを追加したらバックエンドの記述は終了です。

```ruby:post_controller.rb

      #中略
     
   private 

  def post_params
   params.require(:post).permit(:image1, :image2).merge(user_id: current_user.id)
  end
```

# 4.自分の好きなようにビューファイルに記述をする
後はビューファイルにて画像の記述を名前通りに記述して反映します。

# 5.最後に
大体は画像は一枚で終わらしてしまうような作りにしてしまいますが、今回は2枚以上貼り付けつような仕組みを紹介いたしました。記事を読んでいただきありがとうございました。
bootstrapのモーダルを複数開いたときの問題と対処法

##標準の挙動
背景（.modal-backdrop）はmodalごとに、bodyにappendされる（z-indexは.modalのz-index設定値 - 10）

z-indexのスタック文脈について詳しい記事
[z-index再入門 - z-indexの仕組み | CodeGrid](https://www.codegrid.net/articles/z-index-1)

##問題点
モーダルの数、重なりに関係なく .modalは.modal-backgroupより上に表示される。

##対処法
.modalと.modal-backdropのz-indexをstackされている要素を考慮するようにhackする

```common.js
$(document).on('show.bs.modal', '.modal', function () {
    var zIndex = 1040 + (10 * $('.modal:visible').length);
    $(this).css('z-index', zIndex);
    setTimeout(function() {
        $('.modal-backdrop').not('.modal-stack').css('z-index', zIndex - 1).addClass('modal-stack');
    }, 0);
});
```

>[参考になったURL](http://sissoko.hatenablog.com/entry/2019/03/24/103235)
PIL.UnidentifiedImageError: cannot identify image fileの解決に時間を費やし過ぎた

## 問題
pythonでPillowを用いて, 画像読み込もうとしていたときに次のエラーが発生
```PIL.UnidentifiedImageError: cannot identify image file
```

画像を入れているディレクトリも合っていて, 画像にも問題無しで原因が分からず.

## 解決策
.DS_Storeを読み込もうとしていたのが原因だった.
削除すれば問題無かった.
RPCとは何かを友達に説明する方法

#	<center>RPCとは友達も理解できる説明方法</center>

## 1.基本的なPRCモジュール

RPCとは何か？RPCとRESTの区別

## 2.概念

- RPC(Remote Procedure Call)主にクライアントノードとサービスノード間に呼び出し方式です。

  

- ローカルでよびだしの場合はsetName(String name)のようなローカル関数を呼び出して、データをメモリに渡し、関数ポインタでsetName();を呼び出して、データを処理します。

  

- RPCの場合は以下のstepを実現されます

  1.まず、クライアント端はさーばサーバーに保存したの関数のプロセスIDを見つけ、そして関数を実行する

  2.クライアントはローカルデータがサーバーに伝送する必要があります。そのため、クライアントはデータをバイトストリームに変換してサーバー側に送り、サーバー側はバイトスクリームをデシナリオして、クライアントからのデータと関数IDを取得ます。

  3.サーバー側に関数を実行して、結果がシナリオとデシナリオを通ってクライアント側に返送します。

  <center>![clientserver.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517198/be663edc-e4b9-37c1-1a6f-991bfec075e6.png)</center>


- 分散システムでは、サーバーaがサーバーbにアクセスする場合。http restを用いてデータを伝送し、データもシナリオ化を処理する。

 ![serverserver.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517198/d81c3ff1-9a37-acdd-1f9e-78d06c4a6aca.png)

HTTPはアプリケーション層のプロトコールです、Headerの内容が重いので、通信のコストが高いです。

RPCは主にSocketを依頼して通信効率は向上することができますが下層の実装はRESTよりもっと複雑である。


![timeline.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517198/7aef1253-28f5-85c5-9889-de1cd0a826ec.png)

この文章は個人の学習記録です，指摘を歓迎する。
【2021年1月】CentOS 6 でのリポジトリ設定手順

# はじめに
CentOS 6 は 2020年11月30日にサポートが終了しているが、今なお残っている CentOS 6 システムのメンテナンス用サーバを構築する必要があったため、手順をメモ書きとしてアップ。
なお、現時点では使用可能なリポジトリであっても、OS自身のサポートが切れている以上いずれ次第に使用できなくなることが予想される。もし気づいたら、あるいは対応方法が見つかったらこのエントリを随時更新する予定。

# 2021年1月時点でのCentOS 6の従来のリポジトリの使用可否
サポート終了まで自身がよく使用していたリポジトリの現時点での使用可否

|リポジトリ|可否|対応方法|
|---|---|---|
|CentOS|×|従来の mirror.centos.org リポジトリを vault.centos.org に変更する（下記参照）|
|epel|〇||
|remi|〇||
|ius|×|従来の repo.ius.io リポジトリを dl.iuscommunity.org に変更する（下記参照）|
|elrepo|×||
|mysql-community|〇||
|pgdg|〇||

# リポジトリ変更内容
## CentOS
以下は /etc/yum.repos.d/CentOS-Base.repo 内の記述（* にはos, updates, extras, centosplus, contrib が入る）

- 使用不可になったリポジトリ
 - mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=*&infra=$infra
 - baseurl=http://mirror.centos.org/centos/$releasever/*/$basearch/
- 現在も使用可能なリポジトリ
 - baseurl=https://vault.centos.org/6.10/*/$basearch/

## ius
**CentOS 6用パッケージはiusからすでに削除されていて使用できない（2022/4確認）**
第14回 無線LANとWi-Fi


前回のクラウド記事からまた時間が空いてしまいました。。
今回は今までの流れに戻って、ネットワーク技術の**無線LAN**に関しての内容になります。

今や当たり前となった**Wi-Fi**ですが、どういう技術が使われ、なぜ通信速度の問題が発生するのか？
なぜインターネットにケーブルなしでもつながるのか？
ここに疑問を持った方も多いのではないでしょうか


#そもそも無線LANとは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559536/7d705027-7595-dae1-a5d7-ff5de466a57c.png)

・ケーブルなどの**物理機器を使用せずにLAN内の通信を実現**する技術

・無線LAN=Wi-Fiではない。
Wi-Fiは**無線LAN規格のうちの一つ**

・スマートフォンが普及した2010年以降急速に発展
(普及した理由の一つ)スマホでインターネットを見すぎた結果起こる
通信速度低下などを防ぐため人々はWi-Fiポイントにつなぐ機会が増えた

・規格は”IEEE802.11”
**アイトリプルイー・ハチマルニ・テン・イチイチ**と呼ぶ

・周波数は 主に**2.4GHzと5GHzの2つ**
2.4GHz 
多くの機器が対応しているため電波の干渉を受けやすいが**手軽に利用**できる 
5GHz 
ルーター以外で使用されないので**電波干渉を受けずらく安定した通信**ができる
※60GHzというのもあるが、特定の規格でしか使用されていない


#無線LANの技術進化① 登場からスマホ普及前まで
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559536/080f551b-6107-7790-933c-4e5f91ad9fd0.png)
IEEE 802.11a(5GHz帯)/b(2.4GHz帯)
・この２つの規格が**以降に策定されている規格の基盤**になる

IEEE 802.11g
・2.4GHzの通信速度を保ちつつ、54Mbpsの通信を行なう

IEEE 802.11j
・ **japan(日本)**における4.9-5GHz帯無線LAN 

IEEE 802.11n
・2.4/5ＧＨzの2つの周波数帯を使用できる
(使用例)
Wi-Fi 4とも呼ばれ任天堂のWiiをインターネットにつなぐ際、無線LANのUSBを使用していた時に使われていた規格

#無線LANの技術進化② 2010年以降
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559536/10412ac2-ae45-1c40-e3e0-d6104f5b98f3.png)
IEEE 802.11ac/ad/axなど**より高速化に対応した規格**が登場

 IEEE 802.11ad
・ WirelessGigabit(WiGig)機能を持ち60GHz帯の高い周波数帯を利用

 IEEE 802.11ac
・ Wi-Fi 5に対応した現在の主流規格。**802.11nの11.5倍以上の通信速度**を実現しより速い通信が可能になる

 IEEE 802.11ax
・ Wi-Fi 6と呼ばれる最新規格。 **802.11acの4倍以上の実効通信速度**により、常に早く使える通信を実現
　多数のユーザーが同時接続する、オフィスのような環境でも、**ユーザーの平均通信スピードを維持**することが可能になる

#無線LANのセキュリティリスク
###通信内容の盗聴
・暗号化通信をしないことによるスキミング
地下鉄や公共のアクセスポイントは、通信内容がSSL対応していないことがあり、**通信内容を盗聴されるリスク**がある

・偽のアクセスポイントを設置し、そこにログインさせて通信内容を抜き取る
例)officeのSSID名を**office.**など、**本物のようにふるまい**、接続した人の通信内容を盗み取る

・Wi-FiのSSIDの名前がわかりやすいことで誰の通信内容なのか特定されてしまう
例)EigyobuのWi-Fi(**どの部署の通信**なのかわかりやすい)
     TarouのWi-Fi(**誰の通信なのか**本人の名前が入ってしまっている)

###不正アクセス
・IDとパスワードを知っている**退職者などが不正ログインし情報を盗み取る**

・単調なパスワードにすることでの見破り
例)誕生日と自分の名前を混合する。**SNSなどを調べれば人の誕生日はすぐにわかってしまう**

#無線LANのセキュリティ対策

###PSK(Pre Shared Key/事前共有鍵)の設定
アクセスポイントへログインする時、**SSIDとパスワードを設定**することで誰でもログインすることを禁止

###無線LANの暗号化方式(WPA/WPA2)
※最新はWPA3
**2018年6月**にWi-Fiアライアンスが発表した最新規格であり、従来よりも**セキュリティ機能が強化**

認証方法
①パーソナル/個人がインターネットを接続する際に私用
**事前共有鍵(PSK)**を使っての認証

②エンタープライズ/企業のオフィスなど多数の人がアクセスする際に使用
**認証(RADIUS)サーバ**を使って認証


#最新の無線LAN技術

###WPA3 (WPA2の後継規格 パーソナルとエンタープライズに対応)
①**SAEハンドシェイク**による通信内容の防護
WPA2で脆弱性とされていた**KRACKsへの対策技術**
盗聴によるパスワード漏えいが起きた場合でも、**通信内容を暗号化し解読不可能**にする

②**辞書攻撃・総当たり攻撃**からの防護
誤ったパスワードによるログイン試行が一定回数続くと、ログインをブロックする

③WPA3-Enterpriseでは**192ビット**の暗号化システムCNSAを実装
192ビット暗号化システムの**CNSA（Commercial National Security Algorithm）**を実装

Wi-Fi CERTIFIED Enhanced Open(オープンWi-Fi)による防護
公共のWi-Fiにおいて**認証不要で暗号化通信を実現**

#参考
[Wi-Fiセキュリティの新規格WPA3]
(https://workit.vaio.com/i-wpa3/)

[アライドテレシス社:無線LANの基礎知識]
(https://www.allied-telesis.co.jp/products/list/wireless/knowl.html)
蟹さんのPCIe

蟹さん(RTL8196C)のPCIeを調べてみました。

PICeはPCIと同じようにコンフィグレーションレジスタ、IO領域、メモリ領域が用意されています。

PCIeのバスはシリアルでPCIはパラレルになりますが、制御は同じようにできます。

余談ですが、昔はパレレルの方が通信速度を上げられると思われていましたが、極端に処理速度が上がってしまい、信号間の同期のコストがかかりすぎるため、シリアルの方が有効になったようです。

それぞれの物理アドレスはPCIコントローラーによって決められていて、蟹さんの場合は以下になります。

```
#define BSP_PCIE0_H_CFG     0xB8B00000

#define BSP_PCIE0_D_CFG0    0xB8B10000

#define BSP_PCIE0_D_IO      0xB8C00000

#define BSP_PCIE0_D_MEM     0xB9000000
```

コンフィグレーションレジスタはホスト分とそれぞれのデバイスのものがあり上の定義ではBSP_PCIE0_H_CFGがホストのアドレスでBSP_PCIE0_D_CFG0    がデバイスのアドレスになります。

コンフィグレーションレジスタの先頭にはベンダーとデバイスのIDが16Bitづつあります。これを見てOSはどのデバイスドライバーを使うか判断します。

IO領域とメモリ領域はx86の様にIO空間がある場合はIO領域はIOアクセスでメモリ領域はメモリアクセスで処理を行います。蟹さん(MIPS)の場合はIO空間がないのでIO領域とメモリ領域はメモリアクセスで処理を行います。

PCI以前のISAカードではカード自体にアドレスが設定されていて、それが変更ができない場合は同じカードを2枚さすと、アドレスが重複してカードが使用できなくなりました。これを回避するためにPCIではOSからカードのアドレスを設定できるようになりました。その設定はコンフィグレーションレジスタのBAR(0x10から)の6つになります。BARの下位ビットは属性の設定に利用されていて0ビットが1の場合はIO領域になり、0の場合はメモリ領域になります。

BSP_PCIE0_D_CFG0のIO領域をBSP_PCIE0_D_IOで見えるようにするにはBSP_PCIE0_D_CFG0のBARにBSP_PCIE0_D_IOのアドレスを設定するのですが、蟹さんの場合は0x18C00000を設定しています。

一つ目のデバイスがたとえば64KのIO領域を使う場合は、二つ目のデバイスは64K後のアドレスをBARに設定します。デバイスからは必要領域のサイズの情報は取れないので、デバイスドライバーにハードコードされています。

なぜか蟹さんの場合BAR0がIO領域でBAR2がメモリ領域に固定されているようです。

割り込みもコンフィグレーションレジスタで設定できます。
WindowsでGit サーバーを建てる。

需要が増えそうなので雑に書きます。

# サーバー・クライアント共通
[Git for Windows](https://gitforwindows.org/)をダウンロードします。

インストールはほぼデフォルトの設定で問題ないですが、
Configuring the line ending conversions に関しては

+ Checkout as-is, commit as-is

に設定してください。OSを跨ぐと改行文字が死にます。

# サーバー側でGit の設定
<>内は適宜置き換えてください。
コンソールで以下のコマンドの実行

```
# ユーザー設定
git config --global user.email "<メールアドレス>"
git config --global user.name "<ユーザー名>"

# push 時にコンソールがハングするときは以下を設定
git config --global sendpack.sideband false

#Git デーモンの起動(外部接続用)
git daemon --verbose --export-all --base-path=<ファイルパス>
(--enable=receive-packをつけると認証無しでGitの操作ができる)
```

# クライアント側でGit の設定

```
# ユーザー設定
git config --global user.email "<メールアドレス>"
git config --global user.name "<ユーザー名>"

# push 時にコンソールがハングするときは以下を設定
git config --global sendpack.sideband false
```

これで適当にサーバーにリポジトリを作って

```
git clone git://<サーバーIP>/<設定したファイルパス以下>
```
を実行すればクローンできると思います。
出来なかったら、ファイアウォールとウイルス対策ソフトのport : 9418(TCP)を確認してください。
許可していないと送受信できません。
追記:9418はGit protocolが使用するものなので、sshやhttpの人はしなくても問題ないです。
GitHub ActionsでPDFをPNGに変換できなくなったときの対処法

## 発生した問題
CarrierWave + MiniMagickを使ってPDFをPNGに変換する処理を書いており、今までGitHub Actionsでそのテストを回していたが、昨日（2021-1-28）から以下のようなエラーが出てテストが落ちるようになった。

```
Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: `convert /home/runner/work/project-name/tmp/1611830955-943232923084175-0016-3156/thumb/sample.pdf -auto-orient /tmp/image_processing20210128-5864-128hawr.png` failed with error:
convert-im6.q16: no images defined `/tmp/image_processing20210128-5864-128hawr.png' @ error/convert.c/ConvertImageCommand/3258.
```

## 原因

ghostscriptがデフォルトでインストールされなくなっていたため。

UbuntuのVirtual Environmentのバージョンが変わったのでインストールされなくなった？（詳細未確認）

- [before = 20210111.1](https://github.com/actions/virtual-environments/blob/ubuntu18/20210111.1/images/linux/Ubuntu1804-README.md)
- [after = 20210123.1](https://github.com/actions/virtual-environments/blob/ubuntu18/20210123.1/images/linux/Ubuntu1804-README.md)

## 対応

ghostscriptをインストールするようにした。

```diff
 - name: Install packages
   run: |
-    sudo apt-get -yqq install libgbm1
+    sudo apt-get -yqq install libgbm1 ghostscript
```

## その他メモ

- 冒頭に挙げたエラーメッセージでネットを検索すると、`/etc/ImageMagick-6/policy.xml` で `<policy domain="coder" rights="none" pattern="PDF" />` を `<policy domain="coder" rights="read|write" pattern="PDF" />` に変更しろ、という話がよく載っているが（[参考](https://askubuntu.com/questions/1181762/imagemagickconvert-im6-q16-no-images-defined)）、これはすでに対応済みだったので今回の件には関係なかった。
- ghostscriptがインストールされていないのでは？という観点は[このQ&A](https://superuser.com/questions/819277/cant-convert-pdf-into-image-because-of-no-images-defined-error)を見て思いついた。RSpecのテストコード内で ``puts `which gs` `` のように書いてGitHub Actions上でgsコマンドが見つからないことを確認した。
- ImageMagickのconvertコマンドに`-debug All`というオプションを渡すと、convert実行時の詳細情報が表示されるので、この情報をGitHub Actions上で出力させると詳細な原因がわかるかもしれない。（例 ``puts `convert -debug All #{Rails.root.join('path/to/your.pdf')} /tmp/foo.png` ``）
- rspecコマンドに`-b`オプションを渡すと詳細なバックトレースを出力してくれるので、GitHub Actionsのコマンドに付けておくとヒントが得られるかもしれない。（例 `run: bundle exec rspec -b`）
sagemakerでEFSまたはAmazon FSx for Lustreを使用すると、どんなメリットがあるのか？

#結論

トレーニングジョブを行う際、EFSまたはAmazon FSx for Lustreを使うと、高速な開始と短いトレーニング時間に短縮できる。
次の段落では、EFSまたはAmazon FSx for Lustre使用せず、S3に格納されている場合について説明する。

参照：https://aws.amazon.com/jp/blogs/news/speed-up-training-on-amazon-sagemaker-using-amazon-efs-or-amazon-fsx-for-lustre-file-systems/


#SageMakerの全体像とs3にデータを格納した場合のフロー

sagemakerのデフォルトの設定では、以下のアーキテクチャが採用される。
データは、全てS3バケットに集約されている状態。
この状態だと、トレーニングジョブを開始する際、
S3バケット→トレーニングインスタンスにアタッチされた EBS ボリュームにダウンロードのフローになる。
一方、EFSまたはAmazon FSx for Lustreを使用した場合は、ダウンロードの手間が省かれる。

![スクリーンショット 2021-01-29 11.50.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784921/f142727f-2144-52f7-dbf5-dad1fffa4ad8.png)

参照:https://www.accenture.com/jp-ja/blogs/cloud-diaries/amazon-sage-maker
Djangoで500が出たらエラー内容のログを取る。または通知。

## 環境
- django 3.0.3

## やりたいこと
`DEBUG=True`としている環境でのエラー画面は
Server Error (500)
とだけ出て、エラーの内容が見れない。
デバグができない。

`DEBUG=True`としている環境で起きたエラーを何かしらの方法で知りたい。

## 方針
ログ出力にloggingがあるが、loggingは使わない。
[Django 公式 ロギング](https://docs.djangoproject.com/ja/3.0/topics/logging/)
loggingを使いたい場合はこちらの記事がわかりやすい。
[【Django】ログ出力機能について簡単にまとめる](https://qiita.com/mth1209/items/4fe17c427e6f917248f4)

サーバーエラーが出たときに発火する`handler500 `を上書きして、自作のサーバーエラーハンドラーを作って発火させる。
[Django 公式 handler500](https://docs.djangoproject.com/en/3.0/ref/urls/#handler500)


## 開発環境と同じエラーを出す

```python:common/error_log.py
import sys
from django.views import debug
from django.http import HttpResponseServerError


def server_error_display(request):
    error_html = debug.technical_500_response(request, *sys.exc_info()).content
    return HttpResponseServerError(error_html)
```

## Slackにエラー内容を通知する
エラー画面は
Server Error (500)
のままで、エラーの内容だけSlackに送信。

```python:common/error_log.py
import requests
import json
import traceback
from django.http import HttpResponseServerError


def server_error_send_to_slack(request, webhook_url="slack_webhook_url"):
    
    requests.post(
        webhook_url,
        data=json.dumps({
            'text': '\n'.join([
                f'Request uri: {request.build_absolute_uri()}',
                traceback.format_exc(),
            ]),
            'username': 'Django 500',
            'icon_emoji': ': smiling_imp:',
        })
    )
    return HttpResponseServerError('<h1>Server Error (500) Sended To Slack!</h1>')
```

```urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from apps.accounts import views
from common.error_log import server_error_send_to_slack

handler500 = server_error_send_to_slack # DEBUG=True のときのみ発火

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


## ハングアウトにエラー内容を通知する
エラー画面は
Server Error (500)
のままで、エラーの内容だけハングアウトに送信。

```python:common/error_log.py
import requests
import json
import traceback
from django.http import HttpResponseServerError


def server_error_send_to_hangout(request, webhook_url="hangout_webhook_url"):
    requests.post(
        webhook_url,
        data=json.dumps({
            'text': '\n'.join([
                f'Request uri: {request.build_absolute_uri()}',
                traceback.format_exc(),
            ]),
        })
    )
    return HttpResponseServerError('<h1>Server Error (500) Sended To Hangout!</h1>')

```

```urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from apps.accounts import views
from common.error_log import server_error_send_to_hangout

handler500 = server_error_send_to_hangout # DEBUG=True のときのみ発火

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


## 参考
https://qiita.com/mth1209/items/4fe17c427e6f917248f4
https://qiita.com/yuu-eguci/items/a1e4b0a2f238d5ccc985
マネージドプレフィックスリストはどういうケースで使うのか？

#マネージドプレフィックスリストとは？
複数のCIDRブロックをグループ化させ、管理できるサービス。
例えば、0.0.0.0/16と0.0.0.0/24というCIDRがあった場合、別名＋グループ化させて管理する。
また、マネージドプレフィックスリストはルートテーブルとセキュリティグループに適用可能。
それでは、この機能がどういうケースで有効か？をセキュリティグループの設定を例に次の段落で説明する。


#具体的なユースケース
以下画像は、セキュリティグループの編集画面である。
3つのルールのうち、sshに関するルールが2つある。
sshの設定は重複しているが、ソースが異なるため設定項目が増えてしまう。
ソースをまとめて、設定を2つから1つに減らすことができないものか...?
そんな時に役立つのがマネージドプレフィックスリストである。

![スクリーンショット 2021-01-29 12.32.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784921/e6dc87c7-666b-777c-96ad-701bc6135c39.png)

sshのの2つCIDRに「test」というマネージドプレフィックスリストを作成し、ルールを編集すると3つ設定していたルールを2つに減らすことができる。
![スクリーンショット 2021-01-29 12.50.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784921/9586098b-eaf5-1b06-429f-f5acd249b8da.png)



#設定方法
コンソール上で、VPC→マネージドプレフィックスに遷移すると以下の画面にたどり着く。
デフォルトで2つのマネージドプレフィックスが設定してあり、それぞれS3とDynamoDBのCIDR範囲を管理するものである。
![スクリーンショット 2021-01-29 12.39.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784921/938dff7c-11be-b6ed-3bce-2a5fa195980e.png)

プレフィックスリストを作成をクリックすると、以下画面に遷移するので、実現したいリストを作成する。
![スクリーンショット 2021-01-29 12.48.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784921/31bf6e99-3877-32d4-94d0-814c85ebc37c.png)

下記画像より、作成が確認できる。
![スクリーンショット 2021-01-29 12.48.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784921/33e1c7ec-4522-81c0-7088-bbee733578a6.png)
sFlow® エージェントの設定およびトラブルシューティングガイド

#sFlow® エージェントの設定およびトラブルシューティングガイド
##概要
ここでは、Traffic Sentinelに新しいsFlowエージェントを追加するためのステップバイステップガイドと、発生する可能性のある問題の詳細を提供します。他のsFlowマネージャーでも参考になるかと思います。
##新しいsFlowエージェントの追加
###推奨手順-スイッチ側
1. スイッチのCLIを使用して、サンプリングレート（例：1/2048）、ポーリング間隔（例：30秒）、コレクターIPアドレスを設定します。
以下で、いくつかのメーカー(Juniper/Arista/Brocade/Force10/Hewlett-Packard ProCurve/Extreme Networks/Alcatel-Lucent OmniSwitchなど)の設定例を参照ください；  
[Frequently Asked Questions](https://inmon.com/support/faq.php)
2. 必要であれば、スイッチが適切なsFlowエージェントアドレスを設定しているかを確認します。これは通常、loopbackアドレスを選択して自動的に設定されますが、設定出来ないケースもあります。 sFlowエージェントアドレスはsFlowフォーマットの情報をして伝送され、TrafficSentinelに送信されるsFlowデータグラムそのものの送信元アドレスとは異なる場合があることに注意してください。
3. スイッチのすべての物理ポートの入力（Ingress）でサンプリングを適用します。
4. ```shows flow```コマンドまたは同等のものを使用して、スイッチがUDPデータグラムを送信していることを確認します。

###推奨手順-サーバー（マネージャー）側
1. Traffic Sentinelサーバーで、以下コマンドで、パケットが到着していることを確認します。
```sudo /usr/sbin/tcpdump -i any udp port 6343```

2. ソフトウェアファイアウォールが6343/udpのパケットの通過を許可していることを確認します。
```sudo iptables –list```
3. Traffic Sentinel Web UIで、[イベント]＞[コンフィグレーション]＞[リスト]で、新しいエージェントイベントが表示されることを確認します。コメントフィールドには、データグラムの送信元アドレスが示されます。
4. 数分経過したのち、新しいエージェントが[トラフィック]＞[ステータス]画面の、設定された[ゾーン]＞[グループ]に表示されることを確認します。
優先ルールは次のとおりです。
sflowエージェントアドレスに一致する<agent>セクション
sflowエージェントアドレスを含む<agentrange>セクション
sflowエージェントアドレスを含む<subnet>（CIDR）セクション
sflowエージェントアドレスとは別のアドレスで、ICMPやSNMP通信行う場合や個別のしきい値設定する場合では、必要に応じてオーバーライド用に<agent>セクションのコンタクト・アドレスを指定し、CIDRを利用することをお勧めします。
5. SNMPでの接続機能が動作することを確認します;
（[ファイル]> [設定]> [ステータス]> [ディスカバー・エージェント]の選択> [SNMPのテスト]）

###一般的な問題
1. ファイアウォール：iptablesファイアウォールは、6343/udpへのパケットを許可する必要があります。受信確認の為のtcpdumpコマンドは、パケットがファイアウォールに到達する前のパケットの状態を表示することに注意してください。
2. sFlowエージェントアドレス：sFlowエージェントアドレスが予期しない値で設定され、エージェントが間違ったゾーン+グループに表示されることがあります。 sflowエージェントアドレスがCIDR、エージェント範囲、またはエージェントのいずれとも一致しない場合、「other」ゾーンに表示されます。デバイスと通信するためのパラメータが未定義になるため、これは問題のある状態です。

###稀な問題
1. Martians：パケットをサーバーの間違ったインターフェースで受信した場合、つまり、そのソースIP上のスイッチとの応答に使用されるものではない場合：  
```
sudo ip route get <sourceIP>
```  
その後、それらは「Martians」としてサーバーのOSによってドロップされます。スイッチCLIを使用して、別のソースIPまたはコレクターIPに変更する必要があります。
2. 管理ポート（Management Port）：いくつかのスイッチは、sFlowを管理ポートに送信することを躊躇します。スイッチCLIにより回避策を実施する必要がある場合があります。たとえば、直接経路をオーバーライドすることや、管理ポートをデータ側のポートの1つとして指定するなど。
NetCommons2で会員検索したら xmlがダイアログに表示された場合の対処方法

旧会社HPからの転記です。

netcommons2 で会員検索したら xmlがダイアログに表示されて
結果が表示されない問題がでました。

対処方法を書きます。

### 画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109904/583b0b46-1946-3dd5-8202-bd86a3b58b15.png)


### 環境
 
```
$ php -v
PHP 5.6.8 (cli) (built: Apr 15 2015 15:07:09)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies
```
 
NetCommons2.4.2.0

### 対応

NetCommons2.4.2.1にバージョンアップすると解消します。


### 感想

PHP 5.6.8、NetCommons2.4.2.0
PHP 5.6.10、NetCommons2.4.2.0

でこの症状が出たので、おおよそPHP5.6系でNetCommons2.4.2.0を使うと出るようです。

PHP5.5系以下であれば下記の方法もあるようです。


### その他方法1
 
php.iniのdefault_charset = UTF-8 をコメントアウトする。
 
http://www.netcommons.org/index.php?action=pages_view_main&active_action=bbs_view_main_post&post_id=2426&block_id=124#_124
http://www.netcommons.org/?block_id=6666&page_id=0&action=bbs_view_main_post&nc_session=qadv40t81i6ddq5lvvun5mrkt7&post_id=14140
### その他方法2

システム管理＞開発者向け（タブ）＞PHPデバッグ
のチェックを外す。
 
ではでは。
ransackを使った検索結果を表示する

## ransackとは
シンプルな検索機能から複雑な検索機能まで幅広く使える検索に特化したgem

```ruby
<%= search_form_for @p, url: "検索結果を表示したいパス" do |f| %>
  <%= f.label :"カラム名", '表示される文字' %>
  <%= f.collection_select :"カラム名", "配列のデータ", :"参照してくるDBのカラム名", :"表示されるカラム名", "オプション設定" %>
  <br>
  <%= f.submit '検索' %>
<% end %>
```

こちらが検索機能の形となっています。
`search_form_for`を使うことでransack特有の検索フォームを生成できます。


## 下準備

```ruby:gemfile
gem 'ransack'
```

```ruby:ターミナル
bundle install
```

# 表現したかったこと
1:編集するというボタンを押すと、どのアイテムを編集するか？という検索ページへ飛ぶ
2:検索結果にマッチしたものを表示するページへ遷移
3:編集したいアイテム（画像）をクリックするとそのアイテムの編集ページへ遷移

## 実践
#### 1:ルーティングの設定

```ruby:config/routes
resources :posts do
  collection do
     get 'search_edit' #どのアイテムを編集するかの検索ページへ
     get 'search_edit_result' #検索結果へのページへ
  end
end
```

`seach_edit`と`search_edit_result`というルーティングを新しく定義します。
（私の場合は、可読性の考慮と詳細設定、削除設定も同じ流れにしたかったので、このような名前で定義してます）

#### 2.コントローラーへ定義

```ruby:postscontroller
before_action :search_post, only: [:search_edit, :search_edit_result]

  def edit
    @post = Post.find(params[:id])
  end

  def update
    @post = Post.find(params[:id])
    if @post.update(post_params)
      redirect_to root_path
    else
      render :edit
    end
  end

  def search_edit
    @post = Post.find_by_id(params[:id])
  end

  def search_edit_result
    @post = Post.find_by_id(params[:id])
    @results = @p.result
  end

private

  def post_params
    #省略
  end

  def search_post
    @p = Post.ransack(params[:q])
  end
```

この後作るビューで検索機能を入れます。
その検索結果を`@p`として変数にして渡しています。
`:q`とは、検索する際に入力した内容である検索パラメータのキーです

#### 3.ビューを作成

```ruby
#省略
<%= link_to 'スタイルを編集', search_edit_posts_path %>
#省略
```
まずはこれで
`1:編集するというボタンを押すと、どのアイテムを編集するか？という検索ページへ飛ぶ`
を実行できます。

```ruby:検索ページ
#省略
<%= search_form_for @p, url: search_edit_result_posts_path do |f| %>
#条件を入力
  <%= f.submit '検索' %>
<% end %>
#省略
```
こちらで条件を検索します。
`url: search_edit_result_posts_path`とすることで、検索結果のページへ遷移することができます。
よって、
`2:検索結果にマッチしたものを表示するページへ遷移`
を実行できます。

```ruby:検索結果ページ
#省略
<% @results.each do |result| %>
  <%= link_to edit_post_path(result) do %>
  <%= image_tag result.image.variant(resize: '100x100') %>
   <% end%>
 <% end %>
#省略
```

これで検索の結果が出力されます。

`<%= image_tag result.image.variant(resize: '100x100') %>`
こちらは投稿の時に画像を投稿していた場合は、その画像が出力されます。
（ここでは例として、画像の大きさを100x100にしていますが大きさはお好みで）

`edit_post_path(result)`と指定することで、その画像をクリックすると編集画面へ遷移できるようになります。

これで
`3:編集したいアイテム（画像）をクリックするとそのアイテムの編集ページへ遷移`
が実行できます。

## 終わりに
今回は編集画面への遷移までの流れでしたが、これに詳細、削除の機能を落とし込もうとすると、単純にルーティングとコントローラーの記載が３倍になってしまいます。
もう少し上手くまとめられないか模索中です。
Dartメモ

#HasNextIterator 
hasNextを持ったイテレーターがありましたのでメモ。

```dart:コード
import "dart:collection";

void main() {
  List list = [1, 2, 3, 4, 5];
  HasNextIterator hnit = new HasNextIterator(list.iterator);
  while (hnit.hasNext) {
    print( hnit.next());
  }
}
```

```text:結果
1
2
3
4
5
```