OmniAICreator/Qiita-1.07M huggingface dataset:
【rails aborted!】An error has occurred, all later migrations canceledになった時の対処方法

# rails db:migrateをしたらエラー発生
テーブルを作ろうと`rails db:migrate`をしたら
[![Image from Gyazo](https://i.gyazo.com/a2603d7694817413d232e432d862671c.png)](https://gyazo.com/a2603d7694817413d232e432d862671c)
というエラー文が出てしまいました。
検索してみると[こちらの記事](https://qiita.com/terufumi1122/items/9ea764618eba01144e09)を参考にさせていただき、解決することができました！

# なぜエラーが発生したのか
それは文字コードの種類が適切ではなかったからです。デフォルトでは`utf8mb4`という文字コードが設定されています。ですが`utf8mb4`は1文字4バイトで記述できる文字数が少なく、文字数がオーバーしてしまい、エラーが発生してしまいました。

# 結論・解決方法
文字コードを`utf8mb4`から`utf8`へ変更することで解決できました。
ただし、___database.yml___ファイルを修正するため、すでにマイグレーションされたファイルがある場合は注意が必要です。以下はマイグレーションされたファイルがすでにある場合の解決方法です。

1, データベースを削除する
一度作ったデータをコマンドで削除します。

```
% cd ~/projects/データベースを作り直したいディレクトリ
% rails db:drop
```

2, database.ymlを修正する
データベースを削除できたら、database.ymlを修正します。

```database.yml
  .
  .
default: &default
  adapter: mysql2
  encoding: utf8 #元々がutf8mb4と記述されていた部分を修正する
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  .
  .
```

3, データベースを再度作成する
そして、`rails db:create`でデータベースを再度作成します。

```
% cd ~/projects/データベースを作り直したいディレクトリ
% rails db:create
% rails db:migrate
```

# 最後に
バージョンや作り方によっても解決できないこともあるかと思いますが
どなたかのお役に立てたら嬉しいです☺️
ご覧いただき、ありがとうございました。

# 参考記事
[Mysql2::Error](https://qiita.com/terufumi1122/items/9ea764618eba01144e09)
[utf8mb4で巻き起こったトラブル](https://qiita.com/jkr_2255/items/74fc79e764378b59355a)
【メモ】DockerのIPアドレスが足りなくなった時の対応方法

* 製造業出身のデータサイエンティストがお送りする記事
* 今回はメモとして、DockerでIPアドレスが足りなくなった際の対応方法について整理しておきます。

##発生した現象
`docker-compose`を使っていて、IPアドレスが足りないみたいな現象が発生しましたので、解決方法を含めて残しておきます。

```php
Creating network "hogehoge_default" with the default driver
ERROR: could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network
```

##解決策
IPアドレスをクリアすることで解決できることが分かりました。

```php
docker network prune
```
【Python】DataFrameの2次元配列とその中の1行 / 1列との演算

備忘録として

DataFrameの作成

```py
import numpy as np
import pandas as pd

A = np.random.randint(10, size=(3, 4))
df = pd.DataFrame(A, columns=list('QRST')
df
#    Q  R  S  T
# 0  1  5  4  1
# 1  9  5  9  1
# 2  2  4  1  5
```

DataFrameの各行から0行目を引く

```py
df - df.iloc[0]
#    Q  R  S  T
# 0  0  0  0  0
# 1  8  0  5  0
# 2  1 -1 -3  4
```

列単位で引き算する場合は、axisキーワードで指定する
axisキーワードは0が縦(row)方向、1が横(column)方向。それぞれaxis='rows', axis='columns'でも指定できる
DataFrameの各列から0列目を引く場合

```py
df.subtract(df.iloc[:, 0], axis=0)
#    Q  R  S  T
# 0  0  4  3  0
# 1  0 -4  0 -8
# 2  0  2 -1  3
```

Seriesオブジェクトで引く場合も同様
DataFrameオブジェクトとSeriesオブジェクトのインデックスが一致している必要がある

```py
s = pd.Series(np.full(3, 10))
s
# 0    10
# 1    10
# 2    10
# dtype: int64

df.subtract(s, axis=0)
#    Q  R  S  T
# 0 -9 -5 -6 -9
# 1 -1 -5 -1 -9
# 2 -8 -6 -9 -5
```
ニコ動にローカルソースを読み込んでコメント付きで見る

ニコ動の video 要素にローカルソースを読み込んでコメント付きで見るためのスニペット

```javascript
var v = document.getElementsByTagName("video")[0];
v.style.display = "";
v.style.visibility = "visible";

var h = document.getElementById("CommonHeader");
h.style.backgroundColor="white";
h.innerHTML = "<input type='file' id='mySource'>";

var mySource = document.getElementById("mySource");
mySource.addEventListener("change", function(){
    var mySourceURL = window.URL.createObjectURL(this.files[0]);
    v.src = mySourceURL;
    v.play();
});

v.controls=true;

var payments = document.getElementsByClassName("p_x2 w_[680px] text_textOnLayer.highEmWhite bg_layer.surfaceMediumEmBlack rounded_m");

if(payments.length != 0){
    payments[0].style.visibility = "hidden";
}

// video 要素のマウス操作をブロックしている要素を除去
sc=document.querySelector("div[data-name='supporter-content'");
sc.remove();

```
ポートフォリオの基本設計のような物を考えてみた。

#はじめに
ポートフォリオの設計設計を考えてみました。
まだ設計段階ですが、設計書の書き方などの参考になれば幸いです。

##コンセプト

毎週アニメが更新されたら教えてくれるサイト

##作ろうと思った経緯

* 自分が毎週何時にどんなアニメが更新されるのか忘れることが多かったから。
* アマプラを使っていると、アニメが更新されたかどうか分かりにくいのでそれを改善したい。
* 自分の周りでも何時に更新されるかわからなくて困っている人が多かった。
* なにより自分が欲しいから。

##開発目的

* ユーザーに自分に合う面白いアニメを見つけてもらう。
* 継続的にアニメを見てもらう。
* アニメの面白さを人々に伝える。

##必要な要素

* ログイン機能
* お気に入りのアニメを設定出来る。
* お気に入りのアニメが更新されたら新着アニメ欄に追加される。
* アニメページからアマプラ、ネトフリ、Dアニメのページに飛べるようにリンクを貼る。
* アマプラ、ネトフリ、Hulu、Dアニメそれぞれの更新時間が見れる。
* 新着アニメ欄を追加
* →面白いアニメを追加出来るようにするため。
* Graph QLを使用して自動化
* アンケートを答えたらアンケートに応じて使用者が好きそうなアニメのPVを表示。
* 今期のおすすめランキングを追加
* グループが作れて友達同士で見ているアニメを共有

##必要じゃない要素

* アニメ以外は載せない
* →ドラマなども含めてしまうとコンセプトに反する
* アニメの概要・説明などは載せない
* →あくまでお気に入りのアニメが更新されたら教えてくれるサイトを意識する

#必要なスキル
・React hookを理解している
・ReactでAPIを叩ける
・カスタムフックを実装できる
・Reduxが触れる
・ログイン機能を実装できる
・routerをコンポネートで分けて管理できる
・適切なディレクトリでコンポネートを分ける事ができる
・TypeScriptの必要性を理解している
・Gitの基本的な操作が出来る

##開発環境
OS:Mac OS 11.2.3
言語:TypeScript
ライブラリ:React
エディター:VScode
データーベース:AWS
その他:ESlint


##技術選定
###フロントエンド
* React
* React Redux
* TypeScript


###バックエンド/DB
* AWS Amplify
* AWS DynamoDB

###API
* GraphQL

###デザイン
* Adobe XD
* Tailwind CSS

##技術選定理由

###フロントエンド
・**React**
パーツ単位でcomponentsを分けるので保守性・再利用性が高く開発がとてもしやすい。
TailwindやMaterial-UIなどの素晴らしいCSSフレームワークがある。
・**React Redux**
どうしてもReactだけだと、コンポネートの受け渡しが多くなるので採用。
contextと迷いましたが、非同期処理を多く使用するためReduxを採用しました。
・**TypeScript**
何度もアップデートしていきたいと考えているので、保守性が高くする必要があるため採用。
・**TailwindCSS**
カスタマイズ性が高く、予めpadding,margin,font-sizeの値が設定されているので迷うことがなくなる。
class名を考える時間を減らせるので時短になる。



###バックエンド
・**AWS**
GraphQLとの互換性が高く、GraphQLを構築するための手助けを多くしてくれるので今回の開発に合っているため採用。
・**Graph QL**
Annict APIを使用するため。
必要な時にのみデータを取得するため、過不足なくデータを受け取れる。

##ポートフォリオがサービスとして成立するものか

作成した段階で知り合いやエンジニアの友人にフィードバックをもらい改善していく。
Twitterでも宣伝し、サービスとして成立しそうならリリース。

##ポートフォリオで苦労した点 4/15


###環境構築
ESlint,TypeScript,Material-Ui,Firebaseなどの環境構築がLinuxだったので、初めてのコマンドプロンプトということもあり苦戦しました。
これを期に様々なLinuxコマンドを覚えたので良い経験になりました。

###UI/UX
Material-UIの使い方が最初はわからず、ひたすら色々なUIを試していました。
友人のフィードバックを頂き、なんとか良いものになりました。

##ポートフォリオで楽しかった点


##今後改善したい点、実装したい機能

サービスが完成したら随時追加予定

#さいごに
ここまで読んで頂きありがとうございました。
サービス開発が終了したら必ず公開するので完成までお待ち下さい。
【Laravel】Collectionを使おうぜって話だよね

今回はコレクションの利用を促進するのが目的の記事。
と言っても自分も理解が浅いのでぜひともつよつよからの
ご助言も頂けたらうれしいです。

### Collectionとは？
>`Illuminate\Support\Collection`クラスは
配列データを操作するための、書きやすく使いやすいラッパーです。
参照：https://readouble.com/laravel/8.x/ja/collections.html

配列データを書きやすく使いやすくとありますね
でもそもそも配列に対しても色んな関数があるし
今はコレクションなんて使わなくてもコード書けているから必要ないかな
なんて自分は考えていました、はい、、。

それではなんでコレクションを使ったほうがいいのか、
また、配列と何が違うのかを纏めていきます。

### Collectionと配列の大きな違い
これは実務で自分もなるほど、たしかにな！と感じたことなのですが
通常の配列ってエラーが出やすいですよね？？？
なんのことかって

```PHP
$user = [
    'name' => 'daikin', 
    'age'  => 31
];
```

上記のような情報があったときに

```PHP
$user = [
    'name' => 'daikin', 
    'age'  => 31
];
 {{ $user['name'] }} // daikin
```
`daikin`が返ってくる
だけどもし`name`がなかったらどうなるかと言うと

```PHP
$user = [
    'age'  => 31
];
{{ $user['name'] }} // Undefined array key "name"
```

といった感じにエラーが返ってくる
今回は簡単なコードなのですが
案件によっては複雑な処理で求めたKeyが
取得出来てなかったりすることもあったりなかったり。
これがコレクションだとどうなるでしょう

```PHP
$user = collect([
    'name' => 'daikin', 
    'age'  => 31
]);
{{ $user->get('name') }} // daikin
```
上記はコレクションになっているので`get`を使ってます。
ここまでは普通の配列と変わらないですね。
では`name`をなくしてみましょう。

```PHP
$user = [ 
    'age'  => 31
];
{{ $user->('name') }} // null
```
なんと`null`が返ってきてるじゃないですか！
だからなんだよという声も聞こえてきそう、、僕がそうだったんですよね。
なにが変わるかと言うと
Keyが無いときの処理を考えなくてよくなります！
全く考えないこともないですがなにをしたいかというと
下記のときには条件をつけてエラー画面を出さないようにしないといけないです。

```PHP
$user = [
    'age'  => 31
];
@if (isset($user['name']))
    {{ $user['name']}} // nameはないのでこの処理は通らない
@endif
```

はいはいとなりますね。
これがコレクションだと、、、気づきましたか？
下記のような実装になりますよね。

```PHP
$user = [ 
    'age'  => 31
];
{{ $user->('name') }} // nullなのでエラーも出なければ何も出力されない
```
そうなんですよ！
表示しないという処理が許容されるのであれば
コレクションだと変に条件を書かなくてよくなります！
Bladeに条件を書きなぐるのって悪いことではないけど
テストが手間になるのもあるし
その前の処理で変更があるとBladeにも修正を加えないといけなくなりますよね。
それがコレクションをうまく使うことで全体的にも整ったコードになるので
運用もしやすくなるんじゃないのって話だよね←言いたいだけ

僕はまだまだ未熟なのでもっともっとメリットがあるはずなので
これをきっかけにぜひともコレクションについて深堀りしてみてください

最後まで読んでいただきありがとうございます！
閉じる前にLGTMだけクリックお願いしますm(__)m
M5StickCがCOMポートとして認識されない


新しいPC(Windows 10 Pro 64ビット)に、新規にArduinoIDEをインストールしました。このような機会はめったにありません。

インストール手順はこの記事を参考に進めました。
M5Stackシリーズ製品をArduinoIDEで使う
https://qiita.com/akita11/items/f896346d4e8be4673553

結果、M5StackはCOMポートとして認識されました。よし問題なし！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269534/60e6cf39-783b-7a3f-9c2d-87cd2185f326.png)




しかし、M5StickCとATOM LiteはCOMポートとして認識されずに、デバイスマネジャ上で、ほかのデバイス-->M5Stackと表示されました。今まで見たことのない表示でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269534/188e0cb5-be8a-ed4e-825b-bf115c0f40c7.png)

##対処方法

行きついたのはこの記事
M5StickC/ M5StickC Plusの困った時の対処や注意事項
https://zenn.dev/mongonta/articles/dca118b555ef128c2c62
「6.ドライバを最新にしてみる
M5StickCはUSB-シリアル変換にFTDI互換のデバイスを使っています。通常はOSのデフォルトドライバで動きますが、デバイスドライバ入れ替えて認識したという情報もあるので入れ替えてみましょう。」

以下のサイトからデバイスドライバをダウンロードしてインストールしました。
https://www.ftdichip.com/Drivers/VCP.htm
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269534/6d8db4a8-faf8-369f-032b-91575ea2ae29.png)

めでたくM5StickCとATOM LiteはCOMポートとして認識されました。よかった！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269534/c005279c-6fe2-fe6a-cb59-f9cc891f037f.png)
Java とは？

#まずJavaとは？

Javaは、1995年にSun Microsystemsにより初めてリリースされたプログラミング言語およびコンピューティング・プラットフォームでプログラミング言語の一つです。Googleが開発に用いている「Google三大言語（Java、C++、Python）」の一つでもあります。応用力がある言語として昔から根強い人気を誇り、日本でも昔から変わらず人気が高い言語です。

Javaの人気が根強いのは、基本的にどんな環境でも使える言語だというのが大きいということ。システム開発、Web開発、アプリケーション開発と、使える場面が多岐にわたり、さまざまな開発に利用されているからです。特に、大企業での大規模システム開発やAndroidアプリの開発を得意としています。

また、Javaがさまざまなプログラミング言語の元になっているのも、ほかの言語と比較して優れている点です。

# Javaのメリット、デメリット

##メリット
 ・処理速度が速い
 ・プラットフォームがない
 .オブジェクト指向である


##デメリット
 ・学習コストがかかる
 ・環境構築が大変
 
#Javaの書き方
javaはオブジェクト指向言語で書きます。
＊オブジェクト指向＝現実世界をモデル化し、物とその操作のあり方をプログラミングで表現する方法。
EC2サーバーでlaravelのサービスを動かしていたらzip化の処理でエラーが発生した

# 目的

- 記事の主題のエラーが出たので解決方法をメモ的にまとめる

# エラー部分

1. 下記のソースの最後の部分でエラーが発生した。

    ```php
    $zip = new ZipArchive();
    $zip->open('zipファイルのパス', ZipArchive::CREATE | ZipArchive::OVERWRITE);
    $zip->addFromString('ファイル名', 'ファイルパス');
    ```

# エラー内容

1. ZipArchive()を使用したzip化処理で「Invalid or uninitialized Zip object」のエラーが発生した。

# 解決までの経緯

1. 原因はzipファイルがopenされたディレクトリの権限がなかった。
1. zipファイルがopenされるディレクトリの権限を770に設定したところ問題は解決した。
テストって何のためにやるのか分からないよね！（初心者の叫び）

# 取り敢えず、分からんけども、テスト書いてみるか！！しかし・・・
最近、企業さんからいただいたアプリ作成の課題でテストをする必要があり、

（別に書かなくても良いのですが、テストコードを書いたほうが品質に気を使っているのだなと評価されるので）

テストの学習を始めました。

早速、Android全書やその他記事諸々を読み始める。

しかし、それらは前提知識がないと読めないので、かなり難しい…

取り敢えず、クラス名の上にカーソルを合わせて、右クリックすると「Show Context Actions」と表示されるので、クリックし、そして、「Create Test」みないなものが出てくると思うので、それもクリックすると、そのクラスに対応したテストクラスができます。

超入門以外の記事を読んで、分かることはこれくらい笑

でもでも、諦めず自分に適したレベルの記事を読み漁りながら、この記事を完成させたいと思います。

### 実機テストで良くね？
まず、ここっすね。

色々と記事を読み漁っていると、「なぜ、テストを書くのか？」「弊社では、テストを書く必要性がますます高まっています。」という文言を目にすることがある。

つまり、テストはしなければならないものではないらしい。

知り合いのエンジニアの方に聞くと、テストコードを書くか否かは、コストパフォーマンスによるらしい。

当然、書いた方がいいに越したことはないらしいが、そこまで優先順位は高くないみたい。（なのかな？）


また、例えば、１という数字を画面上に表示させたときに、それがString型なのか？Int型なのか？一発で判別することが難しい。

それが原因でエラーが起こることを考慮すると（例えばね笑）、それの判別を自動で出来るテストコードは、まぁ割と恩恵を与えているのかな？と思う。

こんな記事を見つけましたが、やっぱりそんなにやらないといけないものでもない？

「テストを出来るだけ、ポジティブに捉える」という表現をされているので（笑）

https://qiita.com/halkt/items/930097f76f5d82f9079b

### 結論：手動だと面倒な時があるから
こちらの記事のサンプルテストが、読みやすいものだったので、初級者がテストの意味をじんぐり考える材料としては、良質なものだと思う。

https://qiita.com/marienplatz/items/29865b0520efc992dcdb

上記の記事であるように、EditTextに入力した値を用いて、なんかメソッドを実行するようなとき、エミュレータや実機で動かすことでも確認できるが、例えば予期しない値を入れた時ちゃんとはじいてくれるのかどうか？を手動で確かめるより自動でやってくれた方が、速い。

（例えば、氏名を入力する欄に数字を入れた場合、falseを返してくれるのかどうか的な？）

そう考えると、テストの意義は見えてきて、やっと書き始めることが出来るのではないのか？

例えると、買い物のレシートとか、スマホ契約したときの契約内容の確認書類とか、なくてもいいけど、ざっくりと「しっかりしたもの」にするために必要なものなのかなと思った笑。
Dockerコンテナが上手く立ち上がらない時の便利コマンド

# はじめに
Dockerコンテナが立ち上がらない時困らないように忘備録つくりました！

### コンテナ・イメージ一括削除系
```text:滅びの呪文
# コンテナ、イメージ、ボリューム、ネットワーク一括完全消去
$ docker-compose down --rmi all --volumes --remove-orphans

# 全コンテナ停止
$ docker stop $(docker ps -q)
# 全コンテナ削除
$ docker rm $(docker ps -q -a)
# 全イメージ削除
$ docker rmi $(docker images -q)

# 上記コマンドをまとめて実施
docker stop $(docker ps -q) && docker rmi $(docker images -q) -f
```

### 面倒なのでエイリアスコマンドで登録
```text:エイリアスコマンド登録
$ vi ~/.bashrc

# 登録したいエイリアスコマンドを書く(例)
alias docker-rmi='docker stop $(docker ps -q) && docker rmi $(docker images -q) -f'

# 保存
:wq

# .bashrcファイル有効化
$ source ~/.bashrc

$ docker-rmi
$ docker rm $(docker ps -q -a)
```

### ポートの衝突を解決
```text
ERROR: for db  Cannot start service db: Ports are not available: listen tcp 0.0.0.0:3306: bind: address already in use
ERROR: Encountered errors while bringing up the project.

# ホスト側で3306ポートが使われていないか確認
$ sudo lsof -i -P | grep "LISTEN"
mysqld    118         _mysql   27u  IPv6 0x8941af447fb23fc3      0t0    TCP *:3306 (LISTEN)

# 見つけたら削除
$ sudo kill 118     
```
### A server is already running.
```text:pidファイル削除
$ sudo rm tmp/pids/server.pid
```

### dockerコンテナ一気に立ち上げ
```ruby
$ docker-compose up -d --build
```

# さいごに
システムを複数動かしたりDoker関連を変更すると、しょっちゅうシステムが動かなくなることがあります。いつでも振り返って直ぐに解決できるように、解決方法をまとめてみました。Dockerは環境を簡単に壊したり作り直したりできるので、設定は難しいけど、便利さも最近感じてきています。

### 今回主に参考にさせていただいた記事
https://qiita.com/suin/items/19d65e191b96a0079417

https://qiita.com/shisama/items/48e2eaf1dc356568b0d7

https://qiita.com/terufumi1122/items/8253a47ff24b64455fe5

https://gabekore.org/shell-alias
MySQLのjson_dataを使ってはまったこと

twitter API v2でツイートを収集して，MySQLに格納しようとしてはまったのでメモする．

# 環境
WSL2(Ubuntu 20.04.2 LTS)+Python 3.7.9+MySQL 8.0を使っている．
PythonからのMySQLへのアクセスには，mysql.connectorを使っている．

# やろうとしたこと
よく使う属性の値はvarcharやintで宣言したカラムに格納し，一応APIの返却した各ツイートの情報全体をjson_dataに格納することにしたが，insertに失敗する．

```
alldata = requests.get(endpoint, params=params, headers=headers)
obj = json.loads(alldata.text) # dictに変換
data = obj['data']

cur.execute(insert_tweet_sql, (中略, data))
```
エラーメッセージ

```
mysql.connector.errors.InterfaceError: Python type dict cannot be converted
```

dictをstr()で文字列に変換して突っ込んだら，またエラーが出た．

```
cur.execute(insert_tweet_sql, (中略, str(data)))
```

エラーメッセージ

```
mysql.connector.errors.InterfaceError: Error while executing statement: Invalid JSON text: "Missing a name for object member." at position 1 in value for column 'テーブル名.カラム名'.
```

dataはこんな感じ．

```
{'referenced_tweets': [{'type': 'replied_to', 'id': (後略)
```
試してみると，引用符が'ではダメで"なら通ったのでsingle quoteをdouble quoteに文字列置換

```
cur.execute(insert_tweet_sql, (中略, str(data).replace("'", '"'))
```

またエラーが出た．

```
mysql.connector.errors.InterfaceError: Error while executing statement: Invalid JSON text: "Invalid value." at position 216 in value for column 'テーブル名.カラム名'.
```

JSONの216字目を見たら，'possibly_sensitive': Falseがあった．Falseを"False"に置換したら，無事レコードが追加できた．

本文中にシングルクォートや，TrueとかFalseがあった場合への対処は残っているが，ひとまず道筋はついたので投稿．
自分自身のHTMLをダウンロードさせる方法

# このようにするのだ

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Myself</title>
</head>
<body>
    <div contenteditable="true" style="width: 500px; height: 300px; border: solid 1px black;">
    ほげほげ
    </div>
    <button onclick="download()">このページをダウンロード</button>
    <script>

    function download() {
        // DOCTYPE宣言とhtmlタグとその内部のコードの文字列から自分自身のHTMLのコードの文字列を生成
        const htmlText = "<!DOCTYPE html>" + document.getElementsByTagName("html")[0].outerHTML;
        // HTMLのコードの文字列をBlobにし、aタグに紐づけてダウンロードさせる。
        const blob = new Blob([htmlText], {type:"text/plan"});
        const link = document.createElement("a");
        link.href = URL.createObjectURL(blob);
        link.download = "index.html";
        link.click();
        URL.revokeObjectURL(link.href);
    }
    
    </script>
</body>
</html>
```

なおIEでは動きません。
Flutter image_pickerで最初に遭遇するエラー　Failed assertion: line 853 pos 14: 'file != null': is not true.

#画像が必ずセットされていないとエラーになる
初めて`image_picker`を使ってみると、大体発生するエラー。。。:disappointed:

こういうコードの場合、**画像が何も選択されていないからエラーが発生します**

```console

════════ Exception caught by widgets library ═══════════════════════════════════
'package:flutter/src/painting/image_provider.dart': Failed assertion: line 853 pos 14: 'file != null': is not true.
The relevant error-causing widget was
UserImagePicker
lib/…/auth/auth_form.dart:60
════════════════════════════════════════════════════════════════════════════════
```

```dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';

class UserImagePicker extends StatefulWidget {
  @override
  _UserImagePickerState createState() => _UserImagePickerState();
}

class _UserImagePickerState extends State<UserImagePicker> {
  File _pickedImage;
  void _pickImage() async {
    final pickedImage =
        await ImagePicker().getImage(source: ImageSource.gallery);
    final pickedImageFile = File(pickedImage.path);
    setState(() {
      _pickedImage = pickedImageFile;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        CircleAvatar(
          radius: 40,
          backgroundImage: FileImage(_pickedImage),
        ),
        TextButton.icon(
          onPressed: _pickImage,
          icon: Icon(Icons.image),
          label: Text(
            'Add Image',
            style: TextStyle(color: Theme.of(context).primaryColor),
          ),
        ),
      ],
    );
  }
}
```

#「nullの場合」を追加するだけで解決！
もしnullじゃなければ**左（`FileImage(_pickedImage)`）**、nullなら**右（`null `）**

と言うような処理で解決です！

```dart
 CircleAvatar(
          radius: 40,
          backgroundImage:
              _pickedImage != null ? FileImage(_pickedImage) : null,
        ),
```
Ruby on Railsでエラーメッセージを日本語化する

# 環境
* Ruby 2.6.5
* Rails 6.0.0
* devise 4.7.3

# 日本語化の設定
アプリケーションでのエラーメッセージを、英語から日本語表示にするための設定をします。

## 言語設定

まず、application.rbを編集して`config.i18n.default_locale = :ja`を追加します。
`:ja`は日本語という意味です。
myappの記述は、自分のアプリケーション名と読み替えてください。

```ruby:config/application.rb
module myapp
  class Application < Rails::Application
    config.load_defaults 6.0
    
    config.i18n.default_locale = :ja  # 追加

    config.generators do |g|
      g.stylesheets false
      g.javascripts false
      g.helper false
      g.test_framework false
    end
  end
end
```
:heavy_exclamation_mark:**上記の記述を行わないと、日本語で反映されません。**

## Gemの導入

Gemの [**rails-i18n**](https://github.com/svenfuchs/rails-i18n.git) を導入します。
このGemを導入することによって、日本語に対応できるようになります。


```ruby:Gemfile
gem 'rails-i18n'
```
Gemfileに記述後、`bundle install`を忘れずに実行しましょう。

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

これで完了です！！
と、言いたいところですが、今のままでは日本語化が不十分です。
ブラウザでエラーメッセージを確認すると、日本語化しきれていないのがわかるかと思います。
（サーバー起動中の場合は、再起動してから確認）
そこで、次のファイル作成が必要になってきます。

## devise.ja.ymlの作成

以下のディレクトリに、devise.ja.ymlファイルを作成します。

```:config/locales/devise.ja.yml
config
└── locales
    └── devise.ja.yml
```
作成したファイルに、以下のサイトからコードを丸コピして貼り付けてください。
[**devise.ja.yml**](https://github.com/tigrish/devise-i18n/blob/eabac2689592b6e856aaf1bd41e1fd444767f97a/rails/locales/ja.yml)

ブラウザで確認すると、deviseにて設定されているカラム（emailやpassword等）は日本語化されているはずです。
しかし、Gemのrails-i18nやdevise.ja.ymlに含まれない日本語、つまり自分で追加したカラム（nickname等）は英語で表示されてしまいます。
カラムを追加していたら、次のファイルも作成しましょう。

## ja.ymlの作成

devise.ja.ymlファイルと同様で、localesディレクトリにja.ymlファイルを作成します。

```:config/locales/ja.yml
config
└── locales
    ├── devise.ja.yml
    └── ja.yml
```

ja.ymlファイルを編集し、以下の様に記述してください。
モデル名とカラム名は、適宜自分のアプリケーションに合わせて変更しましょう。

```ruby:config/locales/ja.yml
ja:
  activerecord:
    attributes:
      user:
        nickname: ニックネーム
      item:
        description: 説明
        price: 値段
```
以上でアプリケーションのエラーメッセージを日本語化する設定は完了になります。
誤った情報などありましたら、ご教示いただけると幸いです。

# 参考
https://qiita.com/shimadama/items/7e5c3d75c9a9f51abdd5#7-%E6%A7%98%E3%80%85%E3%81%AA%E8%A8%98%E8%BF%B0%E6%96%B9%E6%B3%95-%E5%8A%A0%E3%81%88%E3%81%A6yaml%E3%81%AE%E8%A8%98%E6%B3%95%E3%82%92%E5%AD%A6%E3%81%B6%E3%81%A8%E8%89%AF%E3%81%84
情報処理安全確保支援士試験頻出のCVSSの評価基準は紛らわしいので備忘録メモ

先日情報処理安全確保支援士試験(以下SC試験)の令元年秋の午後Ⅱの過去問を解いている時に、CVSS(Common Vulnerability Scoring System: 共通脆弱性評価システム)の評価基準名を選ばせる問題を間違えました。しかも各々の評価基準の違いを覚えようと[IPAのサイト](https://www.ipa.go.jp/security/vuln/CVSSv3.html)を見てみた所、一読では分からない。。。。！！そこで試験前に再確認できるように備忘録をまとめておくことにしました。

# CVSSとは

以下IPAの解説ページの引用です。

>CVSSは、情報システムの脆弱性に対するオープンで汎用的な評価手法であり、ベンダーに依存しない共通の評価方法を提供しています。CVSSを用いると、脆弱性の深刻度を同一の基準の下で定量的に比較できるようになります。また、ベンダー、セキュリティ専門家、管理者、ユーザ等の間で、脆弱性に関して共通の言葉で議論できるようになります。

脆弱性を共通の言葉で議論できるようにするために共通の指標を提供する評価手法だと説明が有ります。CVSSには3つの評価基準が有ります。その解説を以下に引用します。

>　CVSSでは次の3つの基準で脆弱性を評価します。

>(1)基本評価基準(Base Metrics)
　脆弱性そのものの特性を評価する基準です。情報システムに求められる3つのセキュリティ特性、『機密性(Confidentiality Impact)」、『完全性(Integrity Impact)」、『可用性(Availability Impact)」に対する影響を、ネットワークから攻撃可能かどうかといった基準で評価し、CVSS基本値(Base Score)を算出します。この基準による評価結果は固定していて、時間の経過や利用環境の異なりによって変化しません。ベンダーや脆弱性を公表する組織などが、脆弱性の固有の深刻度を表すために評価する基準です。

>(2)現状評価基準(Temporal Metrics)
　脆弱性の現在の深刻度を評価する基準です。攻撃コードの出現有無や対策情報が利用可能であるかといった基準で評価し、CVSS現状値(Temporal Score)を算出します。この基準による評価結果は、脆弱性への対応状況に応じ、時間が経過すると変化します。ベンダーや脆弱性を公表する組織などが、脆弱性の現状を表すために評価する基準です。

>(3)環境評価基準(Environmental Metrics)
　ユーザの利用環境も含め、最終的な脆弱性の深刻度を評価する基準です。脆弱性の対処状況を評価し、CVSS環境値(Environmental Score)を算出します。この基準による評価結果は、脆弱性に対して想定される脅威に応じ、ユーザ毎に変化します。ユーザが脆弱性への対応を決めるために評価する基準です。

筆者が解いた問題では「入手した脆弱性情報についてその時点で自社にとっての深刻度を評価する」評価基準を選ぶ問題が有り、筆者は「現状評価基準」を選び間違えました。(正解は環境評価基準)しかし上の説明文を読んだだけでは頭の整理が付かずまた同じ間違えをしそうなのでまとめておくことにします。


(1) 基本評価基準(Base Metrics)
脆弱性そのものの特性を評価。この基準の評価結果はセキュリティシステムに求められる3つの特性(CIA)で評価されるため固定で、時間の経過や利用環境の差違では変化しない。

(2) 現状評価基準(Temporal Metrics)
脆弱性に対する今現在の(世間での対応状況などを鑑みた)深刻度の評価。時間の経過とともに(対応などがなされるので)評価値は変化する。

(3) 環境評価基準(Environmental Metrics)
ユーザーの"環境"における脆弱性の深刻度を評価。ユーザー毎で深刻度は変化する。


もうちょっと分かりやすく覚えやすいネーミングを求む！！というのが正直な感想です。
【Mac】AWS CLI インストール手順の備忘録

## はじめに
- Mac環境に [AWS CLI](https://aws.amazon.com/jp/cli/) をインストールする機会があったので、その備忘録です。

## 動作環境
- macOS Catalina 10.15.7


## 手順
### AWS CLI のインストール
1. [インストーラ](https://awscli.amazonaws.com/AWSCLIV2.pkg)をダウンロードします。
2. DLしたインストーラ(pkgファイル)を実行し、インストールします(全てデフォルト設定でOK)。
3. インストールを確認します。

```Bash:shell
$ which aws
# → /usr/local/bin/aws
$ aws --version
# → aws-cli/2.1.32 Python/3.8.8 Darwin/19.6.0 exe/x86_64 prompt/off
```

### AWS CLIの設定

- ```aws configure```コマンドで実行ユーザの認証情報(プロファイル)を紐付けます。

```Bash:shell
$ aws configure
# IAMユーザのアクセスキー設定
AWS Access Key ID [None]: xxxxxxxx
# IAMユーザのシークレットアクセスキー設定
AWS Secret Access Key [None]: yyyyyyyy
# リージョン設定：東京
Default region name [None]: ap-northeast-1
# 出力設定：json
Default output format [None]: json
```

- ホームディレクトリ直下に```.aws```フォルダが作成され、そのフォルダ内に```config```ファイルと```credentials```ファイルが出力されます。

```Bash:.aws\config
[default]
region = ap-northeast-1
output = json
```
```Bash:.aws\credentials
[default]
aws_access_key_id = xxxxxxxx
aws_secret_access_key = yyyyyyyy
```

- CLIに紐付いているプロファイルを確認します。

```Bash:shell
$ aws configure list 
#      Name                    Value             Type    Location
#      ----                    -----             ----    --------
#   profile                <not set>             None    None
# access_key     ****************xxxx shared-credentials-file    
# secret_key     ****************yyyy shared-credentials-file    
#     region           ap-northeast-1      config-file    ~/.aws/config
```

- CLIのプロファイルを一時的に変更してみます。

```Bash:.aws\config
[default]
region = ap-northeast-1
output = json

[profile user1]
region = ap-northeast-1
output = json
```
```Bash:.aws\credentials
[default]
aws_access_key_id = xxxxxxxx
aws_secret_access_key = yyyyyyyy

[user1]
aws_access_key_id = zzzzzzzz
aws_secret_access_key = aaaaaaaa
```

```Bash:shell
$ aws configure list --profile user1
#      Name                    Value             Type    Location
#      ----                    -----             ----    --------
#   profile                <not set>             None    None
# access_key     ****************zzzz shared-credentials-file    
# secret_key     ****************aaaa shared-credentials-file    
#     region           ap-northeast-1      config-file    ~/.aws/config
```
コーパスとしての法律文書（条文データ）の取得


# はじめに
法律文書を集めようとすると、初めに考えうるのはeGovの条文と思われる。
条文データはXMLで公開されており、構造化されているためである。
他方、例えば裁判所の判例データは、PDFで公開されており、テキスト化すると少々崩れる（大きくは崩れなかった）。

筆者にとっての一番の問題は「XMLとは何ぞ？」な状態なことである。
ここでは、eGovデータを活用するにあたって、調べたXMLの使い方を記載する。

## XMLとは
2000年頃、JSONが流行る前に使われていたデータを表現する技術。仕様が巨大すぎてよくわらからぬ。が、プログラム（クラス）も生成することができる模様。
パーサは機能が多くなりがちであり、それゆえ脆弱性を産みやすい。今も生き延びている亜流にHTMLがある。

# やったこと
やらないといけないことは、
1. XSD（xml schema definition：XMLのスキーマ定義）からクラスを生成する
2. XMLデータを読み込み、オブジェクト（インスタンス）を生成する
の二つである。

XSDは以下から取れる。
https://elaws.e-gov.go.jp/help/

ちなみにXML（データ自体）は以下から取れる。
https://elaws.e-gov.go.jp/download/

## 1. XSDからクラスの生成
Java 8のJDK付属xjcを用いる。Java 9以降では付いていないらしい。

```shell-session
$> xjc XMLSchemaForJapaneseLaw_v3.xsd
```

### トラブルシューティング（というか応急処置）

なんかエラーが出たので、とりあえずメモっとく。

```shell-session
$> xjc XMLSchemaForJapaneseLaw_v3.xsd
スキーマの解析中...
スキーマのコンパイル中...
[ERROR] 同じ名前"generated.Sublist3Sentence"のクラス/インタフェースがすでに使用されています。この競合を解決するには、ク ラス・カスタマイズを使用してください。
行1761
[ERROR] (前述のエラーに関連して)別の"Sublist3Sentence"がここから生成されます。
行1766
[ERROR] 2つの宣言により、ObjectFactoryクラスで衝突が発生しました。
行1761
[ERROR] (前述のエラーに関連して)これは他方の宣言です。
行1766
コードの生成に失敗しました。
```

なんか競合したので該当行において以下の処置を実施した（正直わかっていません）。

```xml
 <xs:element name="Sublist3" type="Sublist3Sentence"/>
  <xs:complexType name="Sublist3Sentence">
    <xs:sequence>
      <!--xs:element ref="Sublist3Sentence"/-->  ★この辺（コメントアウト）
      <xs:element ref="Sublist3SentenceE"/>★この辺（追記）
    </xs:sequence>
  </xs:complexType>
  <!--xs:element name="Sublist3Sentence"-->  ★この辺（コメントアウト）
  <xs:element name="Sublist3SentenceE">★この辺（追記）
    <xs:complexType>
      <xs:choice>
        <xs:element maxOccurs="unbounded" ref="Sentence"/>
        <xs:element maxOccurs="unbounded" ref="Column"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>
```

## 2. XMLデータを読み込み、オブジェクトを生成する

読み込めば、自由に編集できる。
読み込むだけなら以下でできるが、構造を考えてのプログラミングは複雑なコードになっていく。別記事で記載する予定。

```java
File file = new File(fileName + ".xml");
JAXBContext context = JAXBContext.newInstance(Law.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Law law = (Law)unmarshaller.unmarshal(file);
```


# 付録
[生成されたクラス](https://github.com/foj05123425/lawtech/tree/main/src/generated)はGitHubに置いています。
Linux コマンドの学習

○Linuxのコマンド

1.cd hogehoge
→ディレクトを選択して移動する
・「.」 カレントディレクトリを選択
・「..」　親ディレクトリ

2.pwd
→カレントディレクトリのパスを表示する
・現在の場所がわからなくなることが多いので、その時に使用する

3.ls
→現在いるディレクトリにあるファイルを一覧で表示する
→オプション
・「-a」　隠しファイルを含めた全てのファイルを表示させる 
・「-l」　ディレクトないに存在するファイルの詳細情報を表示してくれる

4.mkdir
→ディレクトリを作成する
→オプション
・「-p」 深い階層で作成したい場合、一気に作成する
→例）mkdir -p hello/hogehoge/foo

5.rmdir
→空のディレクトリを削除する

6.<command> -help
→commandの使い方を表示する
※-helpではなくて--helpのことも多い

7.man <command>
→-helpよりも詳しい使い方を表示する
→オプション
・「-K」 hogehoge
→hogehogeが含まれているコマンドを表示する
「'utf-8' codec can't decode byte 0x91 in position 42: invalid start byte」の解決方法

# 事象

Azure Sphere を開発者モードに切り替え（`azsphere device  enable-development`）するときに、`'utf-8' codec can't decode byte 0x91 in position 42: invalid start byte`エラーが発生した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/aac8dd31-ddff-2f04-7561-4f737dae88b2.png)

# 解決方法

デバイスのリブートとのタイミングで、エラーが発生している模様。
もう一度、実行すればOK。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/03ce9c74-9586-44bc-da84-5dae67869fce.png)
ビット(bit)とかn進数とか

コンピュータの成り立ちとか、基礎とか理解できればこれから先どんなことをやるにしても理解が早いのではないかと思い勉強を始めました。
[キタミ式イラストIT塾 基本情報技術者](https://www.amazon.co.jp/%E3%82%AD%E3%82%BF%E3%83%9F%E5%BC%8F%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88IT%E5%A1%BE-%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85-%E4%BB%A4%E5%92%8C03%E5%B9%B4-%E3%81%8D%E3%81%9F%E3%81%BF%E3%82%8A%E3%82%85%E3%81%86%E3%81%98/dp/4297117819)で勉強させていただいております。

まとめます！

## ビット(bit)

>こんなに色々なことができるコンピュータですが、0と1の2つしか理解することができません。

と、ここで早速「うん！意味分からない！」ってなりました:joy:
本では電球に例えていて`ONかOFFの2つしか理解できない`と言う意味だと。

その電球1つを`1ビット`と言う単位で表すということでした。
確かに電光掲示板とか電球をたくさん並べれば色々な文字や形や図を表現できますよね:thinking:


## n進数

>コンピュータは基本2進数です。

そうですね。確かにONとOFFの2つしか理解できないと考えると0と1しか理解できないというのも分かります。

で、2進数ってどう考えればいいの？ということになります。

私たちが普段使っているのって10進数ですのでそれに例えてみます。
(自分たちが普段使っている数の数え方を10進数ということすら知らなかったんですけどね...)

```
0→1→2→3→4→5→6→7→8→9
```

上記のように0~9までの数字を使って数を表すことを10進数と言います。
9まできたら10になりますよね。
これは普段からやっているので普通にできますね。

で、これを2進数にすると

```
0→1→10→11→100→101→110→111→1000
```

上記のように0と1を使って数を表現します。

そしてこの2進数を扱うコンピュータは8進数と16進数と相性がいいみたいです。
8進数は0~7までの数字で数を表し、16進数は0~9の数字とアルファベットのA~Fで数を表します。
何で相性がいいかというと8進数は3ビット分、16進数は4ビット分にまとめられるのでちょうどいいんだそうです:thinking:

うん。まだよく分かりません。

分からないので表にしてみます。

| 10進数 | 2進数 |  8進数 | 16進数 |
|:-----:|:-----:|:-----:|:-----:|
| 0     | 0     | 0     | 0     |
| 1     | 1     | 1     | 1     |
| 2     | 10    | 2     | 2     |
| 3     | 11    | 3     | 3     |
| 4     | 100   | 4     | 4     |
| 5     | 101   | 5     | 5     |
| 6     | 110   | 6     | 6     |
| 7     | 111   | 7     | 7     | 
| 8     | 1000  |       | 8     |
| 9     | 1001  |       | 9     |
| 10    | 1010  |       | A     |
| 11    | 1011  |       | B     |
| 12    | 1100  |       | C     |
| 13    | 1101  |       | D     |
| 14    | 1110  |       | E     |
| 15    | 1111  |       | F     |


なるほど。
8進数は3桁分(0~111まで)の情報を表現できるから3ビットで、16進数は4桁分(0~1111まで)の情報を表現できるから4ビット何ですね。


## バイト

1ビットは最小の単位ですが、ビットだけだと桁が大きくなりすぎるので不便だと。
で、8ビットを1つにまとめたものをバイト(Byte)という単位で使います。
やっと聞き慣れた言葉が出てきました。

ビットはbで小文字で表し、バイトはByteで大文字で表すんだそうです。
だからSDカードとかって256GBって大文字なんですねー。

私は前職でスマートフォンを販売していたのでバイトの単位はスッと理解できましたー。

```
バイト(B)→キロバイト(KB)→メガバイト(MB)→ギガバイト(GB)→テラバイト(TB)
```

1000倍ずつ増えていきます。

全然関係ないんですけど、スマホって今「ギガ使い放題」とかってプランですけどそのうち「テラ使い放題」みたいになるのかな。いや、そもそも制限をつけること自体ナンセンスになるんですかね。

でも携帯電話のプランってコロコロ変わりすぎて現場のスタッフ大変なので本当にやめてほしいと思ってました。条件とか諸々多すぎ。
総務省からの指示なのは分かるんですけど、本当にシンプルにして欲しかった。
それを考えると新しいahamoとかpovoとかシンプルでいいですよね。

はい。関係ない話ですみません。


ビットとかn進数のことを学んでみて、今のところ全く理解できてないですけどSDカードとかメモリ系が2のn乗の理由は分かりました！
8GBとか256GBとか。

以上です。
Flaskのsessionでmutableなオブジェクトを扱う

Flaskのsessionではmutableなオブジェクトの変更は検知されず、変更が反映されない。
例えば以下のコードがそれに該当する。

```python
from flask import Flask, session

app = Flask(__name__)
app.secret_key = b'a'

@app.route('/')
def index():
    if not 'mutable' in session:
        session['mutable'] = []
    session['mutable'].append(1)
    return str(session['mutable'])

if __name__ == "__main__":
    app.run('localhost', port=80, debug=True)
```

`http://localhost/`にアクセスした時に期待する挙動は`[1]`、`[1,1]`、`[1,1,1]`のようにアクセスするたびに配列に1が追加されていくものだが、実際には1つ目以降の1は追加されていくことはない。

これはバグではなく仕様らしく、公式のドキュメントにも書かれていた。
>Be advised that modifications on mutable structures are not picked up automatically, in that situation you have to explicitly set the attribute to True yourself. 
>(出典)https://flask.palletsprojects.com/en/1.1.x/api/#flask.session.modified

以下Google翻訳
>可変構造の変更は自動的に取得されないことに注意してください。そのような状況では、属性を明示的にTrueに設定する必要があります。

変更を反映するには明示的に示す必要がある。
方法は簡単で`session.modified`の値をTrueすれば良い。

```python
from flask import Flask, session

app = Flask(__name__)
app.secret_key = b'a'

@app.route('/')
def index():
    if not 'mutable' in session:
        session['mutable'] = []
    session['mutable'].append(1)
    session.modified = True # 変更を明示的に示す
    return str(session['mutable'])

if __name__ == "__main__":
    app.run('localhost', port=80, debug=True)
```

`http://localhost/`にアクセスすれば期待通りの挙動になっていることが分かる。

ちなみに、オブジェクトの変更のほかに代入などを行っている場合は変更が検知されるため`session.modified = True`を行う必要がなくなる。

```python
from flask import Flask, session

app = Flask(__name__)
app.secret_key = b'a'

@app.route('/')
def index():
    if not 'mutable' in session:
        session['mutable'] = []
    session['mutable'].append(1)
    session['hoge'] = 1
    print(session.modified) # 変更が検知されているためTrueが出力される
    return str(session['mutable'])

if __name__ == "__main__":
    app.run('localhost', port=80, debug=True)
```
Node-REDにおけるnpm installの正しい位置

```
c:\users\<your username>\.node-red
```

です。参考例は

``` command
cd c:\Users\torisan\.node-red
npm install node-red-contrib-....
```
です。
npm globalの位置は

```
c:\users\<your username>\AppData\Roaming\npm
```
にあります。
Re:dash APIを利用してRe:dashのお引っ越しする

# 概要
昔雑に立ててたRe:dashから新しいRe:dash環境にクエリをお引っ越しする。

Re:dashを雑に立てた結果さまざまな問題に直面したため新しくRe:dash環境を立ち上げて引っ越すことを決めた。
既存の環境を頑張っていい感じにすることも考えられるが利用者が少ない(私とディレクター1人だけ)&query以外そこまで利用していない背景があり、新しい環境立てて引っ越した方が早いのではと言う試みをしました。

# 成果物
https://github.com/tatematsu-k/redash_transport

# 実現したこと
旧環境のqueryを全て取得し、利用中のものだけ新しい環境に全てインポートする。

本家のドキュメントはGET系はそこそこわかりやすいのですが登録系はだいぶ苦戦しました....

# ポイントだけ
## APIキーの種類
Re:dashの認証には `User API Key` と `Query API Key` のに種類があります。
`Query API Key` はそのクエリのみに限定された権限のAPI Keyになっており、本家のドキュメントでは可能な限りこちらを使用するようにと推奨しています。
=> 今回はQueryの全件取得を行うのと登録を行うため `User API Key` を利用します。管理画面から簡単にRegenerateできるので他で利用してないなら実行後にRegenerateしておくといいかもしれません。

## 認証方式
公式のドキュメントではquery parameterでapi_keyを設定する方法が書かれています。

```bash
$ curl https://{your redash domain}/api/queries?api_key={your user api key}
```

これとは別方式でAuthorization Headerに入れて検証する方式もあるようです。
query parameterで渡すよりもこちらの方がコードがシンプルになるので今回はこちらを採用。

```bash
$ curl -H "Authorization: Key {your user api key}" https://{your redash domain}/api/queries
```

他にも `request.view_args.get("token")` で渡す方法があるらしく、Flaskの機能らしいのですがちゃんと確認してないです。とはいえエンドポイントにapi key入れ込む手法らしくヘッダーに入れる方がシンプルかなと思って見切ってないです。

cf: https://github.com/getredash/redash/blob/2992c382d12ba0ddb23dd1886b38c00c0d8b67cc/redash/authentication/__init__.py#L142-L154

## post /api/queriesが通らん...
エラーもそこまで詳細が詳しく返ってこないので割と手探りでやりまくりました。
=> Re:dashの管理画面からのリクエスト情報を参考に情報を絞っていくとわかりやすいと思います。

今回は以下のパラメータを投げることにしました。

- name: queryのタイトル
- query: 実際のSQL
- description: よくわからん...(管理画面からだと登録できないのか？と思ったら左側にありました...)
- schedule: 定期実行情報
- data_source_id: データソースid(これは新旧で一致するとは限らないのでmapで対応表を噛ませました。(とはいえデータソース一つなのでどちらでもでしたが...))

後追いですがここら辺見るとパラメータについて書かれてました。上のものが必須でそれ以外はoptionalみたいですね。
https://github.com/getredash/redash/blob/2992c382d12ba0ddb23dd1886b38c00c0d8b67cc/redash/handlers/queries.py#L330-L342

```py
        """
        Create a new query.
        :<json number data_source_id: The ID of the data source this query will run on
        :<json string query: Query text
        :<json string name:
        :<json string description:
        :<json string schedule: Schedule interval, in seconds, for repeated execution of this query
        :<json object options: Query options
        .. _query-response-label:

        .........

        """
```

実行後に全部unpublish状態で :scream: だったのですがどうやら固定でdraft状態になるっぽいです。。
https://github.com/getredash/redash/blob/0e1587a0687838b934c90c2b066ae0aa7db0af83/redash/handlers/queries.py#L257

# Re:dash APIと戦う時の心得
まず前提として公式のドキュメント以外の非公式？なAPIがとてもたくさんありました...。

Re:dashのAPIはここにまとめられていました。
https://github.com/getredash/redash/blob/0e1587a0687838b934c90c2b066ae0aa7db0af83/redash/handlers/api.py

この中からそれっぽいエンドポイントを探し当てて `**Resources` クラスを特定する。
あとはそのクラスで全件検索なりドリルダウンなりして該当のエンドポイントの実装を探す。
=> 大体コメントで必要なパラメータを記載してくれてます。

素敵なRe:dashライフをgood luck!

# 参考
https://redash.io/help/user-guide/integrations-and-api/api
https://qiita.com/sakatukitukasa/items/18012b7bed4aec437ae5
GatsbyJSがメジャーアップデート。いつの間にかgatsby-cliが3.x.xになっていたので2.x.xに戻した件

## gatsby updateしたよ

over40webclub のピータンさんから「gatsbyアップデート」の一報にふれました。
gatsbyのバージョンが2.x.xから3.x.xになりました。
１つ目の数字が変わるのはかなり大きな変更なので
意識せずにアップデートしてしまうと
前のバージョンで作ったサイトなどが動かなくなることも多いそうです。
「自分はまだあまり触っていないし」と思っていたら
gatsby-cliのバージョンがいつの間にか3.0.0になっておりました😅

ターミナルに出てくる

```
   ╭───────────────────────────────────────╮
   │                                       │
   │    Update available 3.0.0 → 3.1.0     │
   │   Run npm i -g gatsby-cli to update   │
   │                                       │
   ╰───────────────────────────────────────╯
```

これのいうとおりにしていたようです。
これは、今回出てきたやつなので、
これを見て「3.0.0になってる！と気づいたわけです。

教訓　アップデートやればいいというものではない

## バージョン戻しを試みる

cliとgatsby本体の関係が今ひとつわかっていないのですが
とりあえず、自分の勉強も含めて
gatsby-cliのバージョンをもどすために
少し調べてみました。

### アンイストール

```
npm uninstall gatsby-cli -g
```

オプションで「このPCどこでも使えるように」の　-gオプション（global)つけていたので、
ちゃんと-gをつけてアンインストーる

### gatsby-cliのバージョン履歴を調べる
　
npmパッケージなのでnpmのページで調べました。

https://www.npmjs.com/package/gatsby-cli?activeTab=versions

3.x.xになる直前の2.19.1を入れることにしました。
なにかコメントついているのを見ると、「test」とかもあるので
何もついていないやつで2.x.xで数字大きいやつという基準。

### バージョン指定してインストール
パッケージ名のあとに@で指定します。
-gオプションも忘れずに付けました。

```
npm install gatsby-cli@2.19.1 -g
```

gatsby -vで調べてみると、新しいのあるよのめっせーじでしょうか。
出てきました。

```
Gatsby CLI version: 2.19.1
Gatsby version: 3.0.1  Note: this is the Gatsby version for the site at: 
```

どう影響するのかよくわからずにやりましたが、
このままbuildしたりするとエラーが出そうな感じがしました。

でも、もしかしたらNetlifyとかにデプロイしているやつは
そちらのサーバーでbuildしているのだから
ローカル環境だけで変えても意味がないのかな？

分かる人ご指摘いただけると嬉しいです！
C# csv→xmlでLINQで簡単に扱う[LINQ to XML]

#うわ、定義データが全部CSVファイルだ。
Exelなどで定義され出力されたファイルによって、WinFormsで扱いたいデータがcsv形式ということが多々ありました。csvを読み込みそのまま扱うこともできますが、数百から数千あるとxmlで生成しておく方がC#のlinqで恩恵を受けやすく操作が簡単かと思いました。今回はcsvを読み込みxmlとして生成→定義しlinqで簡単にデータを扱っていきます。

#csvからxml
例ですが、対象のcsvファイルは以下のようになっているとします。
1番目の要素は男性ID、2番目の要素は女性ID、3番目は出力文章です。

```english.csv
1,25,This season's anime is abundant,
2,26,I eat jam bread every day, 
....続く
```
これらのcsvファイルをxmlに変換していきます。

```C#:mendoi.cs
using System.Xml.Linq

string[] csvfile = File.ReadAllLines("english.csv");
XElement parent = new XElement("EngishConfigs",
    from str in csvfile
    let items = str.Split(',')
    select new XElement("EnglishConfig",
        new XElement("ManID", items[0]),
        new XElement("WomanID", items[1]),
        new XElement("Sentence", items[2])
    )
);
parent.Save("English.xml")
```
とすると以下のようにxmlファイルが生成されます。

```English.xml
<EngishConfigs>
  <EnglishConfig>
    <ManID>1</ManID>
    <WomanID>25</WomanID>
    <Sentence>This season's anime is abundant</Sentence>
  </EnglishConfig>
  <EnglishConfig>
    <ManID>2</ManID>
.....続く

</EngishConfigs>
```

#XMLファイルをLINQで扱う
csvからXMLを生成したところで、これらの定義ファイルをLINQを使って操作していきたいと思います。今回のケースとしては、受信したデータや条件判定されたID(男性または女性)の値から出力する文章を取得し扱う。というケースでいきます。

```C#:sample.cs
var xelm = XElement.Load( @"C:\Gomibako\English.xml" );
var emp = (
     from p in xelm.Elements( "EnglishConfig" )
     where p.Element( "ManID" ).Value == "条件から取得した値" ||
       p.Element( "WomanID" ).Value == "条件から取得した値"
     select p ).Single();

MessageBox.Show( emp.Element( "Sentence" ).Value );
```

#まとめ
このようにcsvからXMLファイルとして定義しておくことで、LINQの恩恵によりデータを扱いやすくなりました。今回は紹介しませんでしたが、LINQでXMLを操作することで、複数要素の選択や集計した値、ソートなど様々な関数が使えるみたいでC#のLINQ最高ですね。これらのデータを保持しておく方法は他にも多々あるかと思いますが、数千行ある情報をコピペでxmlファイルにコピペしている人を目撃したので、今回はその代用としてこの方法を使いました。
ラップトップのキーボードを無効にする

ラップトップのキーボードで、押下しても機能しないキーがいくつも出てきてしまいました。

USB キーボードを買ってきましたけど、オンボードキーボードの上に置いて使うと、その自重のせいで反応するキーが悪さをしてしまい、USB キーボードが上手く使え（うまく入力でき）ません。

コマンドでラップトップのキーボードを無効にしてしまうことはできないものか。

先ずは、以下のコマンドを実行して、オンボードキーボードの id を取得してみました。

```
$ xinput list
⎡ Virtual core pointer                    	id=2	[master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer              	id=4	[slave  pointer  (2)]
⎜   ↳ ELECOM ELECOM TK-FCP097 Consumer Control	id=13	[slave  pointer  (2)]
⎜   ↳ ELECOM ELECOM TK-FCP097 Mouse           	id=16	[slave  pointer  (2)]
⎜   ↳ SynPS/2 Synaptics TouchPad              	id=18	[slave  pointer  (2)]
⎣ Virtual core keyboard                   	id=3	[master keyboard (2)]
    ↳ Virtual core XTEST keyboard             	id=5	[slave  keyboard (3)]
    ↳ Power Button                            	id=6	[slave  keyboard (3)]
    ↳ Video Bus                               	id=7	[slave  keyboard (3)]
    ↳ Video Bus                               	id=8	[slave  keyboard (3)]
    ↳ Power Button                            	id=9	[slave  keyboard (3)]
    ↳ Sleep Button                            	id=10	[slave  keyboard (3)]
    ↳ Chicony USB 2.0 Camera: Chicony         	id=11	[slave  keyboard (3)]
    ↳ ELECOM ELECOM TK-FCP097                 	id=12	[slave  keyboard (3)]
    ↳ ELECOM ELECOM TK-FCP097 System Control  	id=14	[slave  keyboard (3)]
    ↳ ELECOM ELECOM TK-FCP097 Wireless Radio Control	id=15	[slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard            	id=17	[slave  keyboard (3)]
    ↳ ELECOM ELECOM TK-FCP097 Consumer Control	id=19	[slave  keyboard (3)]
```

ここで、AT Translated Set 2 keyboard の id に着目します。
今回は、id=17 となっています。

では、この id を、xinput コマンドで無効にしてみます。

```
$ xinput set-prop 17 "Device Enabled" 0
```

悪さをしなくなりました。

ついでに、起動時にオンボードキーボードが使えなくなるように、設定してみます。

```
$ vim ~/.bashrc

ID=$(xinput list | grep "AT Translated Set 2 keyboard" | awk -F '=' '{ print $2 }' | awk '{ print $1 }')
xinput set-prop "${ID}" "Device Enabled" 0
```

マシン再起動後、当該ユーザの環境ではオンボードキーボードは無効になっており、別途接続した USBキーボードのみが働いています。うまくいった。

(参考)
https://askubuntu.com/questions/160945/is-there-a-way-to-disable-a-laptops-internal-keyboard
血圧管理システムをWeb化しました

血圧管理システムをWebシステム、MariaDBでの移行に成功いたしました。
次の課題は
①AWSのクラウド基盤にシステムを移行
②1週間の平均血圧のデータ取得機能の追加
以上2点のうち②からやっていこうと考えています。
開発中のiPhoneアプリのデータを実機から取得する方法

たまに必要になっていつも忘れるのでメモ。
realmやuserdefaultsのデータとか見たいことがある。

* Window→Devicesウィンドウから対象の実機を選択
* INSTALLED APPSからデータを取得したいアプリを選択
* INSTALLED APPSの下にある歯車アイコンクリック
* Download Containerをクリック

参考
https://stackoverflow.com/questions/6121613/browse-the-files-created-on-a-device-by-the-ios-application-im-developing-on-w
Laravelのマイグレーションファイルを統合しても良いか

## 背景

マイグレーションの管理を続けていると、テーブルを作成するだけでなく変更するマイグレーションファイルも増えてくる。
ファイル数が増えると見通しも悪くなるし、ファイルが分かれているとテーブルの中に特定のフィールドがあるかどうかを調べるのも面倒になる。

## 結論

もう部分的にロールバックすることがなければ、マイグレーションファイルを統合しても構わない。

## Laravel 8 の動作確認

`migrate:fresh` してから、テーブルを変更するマイグレーションファイルを削除して、続くコマンドの動作を確認する。

### migrate

マイグレーションファイルを削除しても問題なし。

### migrate:rollback

マイグレーションファイルを削除すると、その部分のロールバックは実行されない。
ただし、エラーにはならず、削除したマイグレーションファイルについては "Migration not found" とだけ表示される。

### migrate:reset, migrate:refresh

マイグレーションファイルを削除しても問題なし。
全てのロールバックが実行されるので、`dropColumn()` がなくなっても最終的に `drop()` が走ればよい。

### migrate:status

マイグレーションファイルを削除しても問題なし。
削除したファイルは一覧に表示されない。
コマンドを実行する Deb ファイル (その2)

こちらのプログラムを改造して、コマンドをインストールして実行するようにしました。
[コマンドを実行する Deb ファイルの作成](https://qiita.com/ekzemplaro/items/9687ad6f6e2f0db34865)

ファイル構成

```text
$ tree package-test_1.0-1_amd64
package-test_1.0-1_amd64
├── DEBIAN
│   ├── control
│   └── postinst
└── usr
    └── share
        └── doc
            └── package-test
                └── go_inst.sh
```

postinst go_inst.sh のファイル属性は 0755 です。

```text:package-test_1.0-1_amd64/DEBIAN/control
Package: package-test
Version: 1.0.1
Architecture: all
Maintainer: ekzemplaro
Section: education
Priority: extra
Description: Packaging test.
```

```text:package-test_1.0-1_amd64/DEBIAN/postinst
#! /bin/bash
# postinst.skeleton
# Skeleton maintainer script showing all the possible cases.
# Written by Charles Briscoe-Smith, March-June 1998.  Public Domain.
# Abort if any command returns an error value
#

set -e

#        written Tue Jan 20 2015

# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.

echo 'postinst' > /tmp/postinst.txt


/usr/share/doc/package-test/go_inst.sh

echo 'postinst *** end ***' >> /tmp/postinst.txt

exit 0
```

```text:package-test_1.0-1_amd64/usr/share/doc/package-test/go_inst.sh
#! /bin/bash

set -e
#


echo 'go_inst.sh' > /tmp/go_inst.txt

cd /tmp
git clone https://github.com/ekzemplaro/storytelling

echo 'go_inst *** end ***' >> /tmp/go_inst.txt

exit 0
```

パッケージの作成

```bash
dpkg-deb --build package-test_1.0-1_amd64
```

package-test_1.0-1_amd64.deb が作成されます。

実行

```bash
sudo dpkg -i package-test_1.0-1_amd64.deb
```
query = query.decode(errors='replace') AttributeError: 'str' object has no attribute 'decode'の解決方法

#◆タイトル記載のエラー解決方法

以下サイトを参考にする。
https://stackoverflow.com/questions/56820895/migrations-error-in-django-2-attributeerror-str-object-has-no-attribute-dec

コード書き換え時にはvimなどのテキストエディタを用いる。
ubuntuにvimをインストールする際は以下を実行する。

```
apt-get update
apt-get install vim
```
学んだこと 2021/03/week4



###TreeViewを開いたままにする対応


https://github.com/mui-org/material-ui/issues/19953



```

  const [expanded, setExpanded] = React.useState<string[]>([]);

  
  ...
       <TreeItem nodeId={child.nodeId}
                          onClick={() => {
                            setExpanded(["1"])
                            history.push(child.link)
                          }
                          }
                          icon={child.icon}
                          label={child.title}
                          classes={{
                            iconContainer: classes.icon,
                            root: classes.treeItem,
                            label: classes.label
                          }}
                />
```

単純だけどこんな感じでクリックした時に
useStateで
セットしてあげることで

初期表示時はclose
クリック後はopenを再現できる。

クリック後閉じたい場合は

```
setExpanded(["1"])
↓
setExpanded([])
```

にしてあげる。
Docker-Composeで3306以外のポートでmysqlを起動

# 複数のMySQLコンテナを建てる時に、一方のポート番号を変更

- ポートを3307で起動。

```yaml

version: '3'

services:
  mysql_srv:
    image: mysql:8.0
    volumes:
      - ./docker/mysql/data:/var/lib/mysql
      - ./docker/mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnf
    ports:
      - 3307:3306
    expose:
      - 3307
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=test
      - MYSQL_USER=test
      - MYSQL_PASSWORD=test
      - MYSQL_TCP_PORT=3307
  phpmyadmin_srv:
    image: phpmyadmin/phpmyadmin
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOST=mysql_srv:3307
      - PMA_USER=root
      - PMA_PASSWORD=root
    links:
      - mysql_srv
    ports:
      - 4001:80
    volumes:
      - ./docker/phpmyadmin/sessions:/sessions

```

- ポイントは以下。

```yaml

# フォワードポート部分を変更
    ports:
      - 3307:3306
    expose:
      - 3307

# MYSQLのport設定変更
    environment:
      - MYSQL_TCP_PORT=3307
```

- phpMyAdminも変更

```yaml
  # port番号を設定
  phpmyadmin_srv:
    environment:
      - PMA_HOST=mysql_srv:3307

```
初学者のプログラミング　dockerの周辺用語

dockerを学んでいくうちに出会った新たな用語を書き留めていく。

| 用語      | 内容 |
| -------- + --- |
| 仮想環境 | パソコンやサーバーなど一つのハードウェアの中で、仮想的な環境を構築したもの。1台のサーバーの中に複数の仮想環境を作ることで、１つのハードウェアで複数のサーバーを仮想的に動作させることができる|
|レガシーソフトウェア|過去の技術やシックみで構築されているソフトウェア。|
|Dockerイメージ|Dockerコンテナを作成するための雛形。アプリケーション、ライブラリ、設定ファイルなどの一式をまとめたもの。保存し別のサーバーと共有をすることで、環境の共有が可能になる。|
|Dockerコンテナ|Dockerイメージを元に作成されるコンテナ型仮想環境のこと。コンテナとも呼ぶ。イメージから作成することで、何度でも簡単に同じコンテナ作成することができる。起動すると、あらかじめセットアップしておいたアプリケーションの機能を提供することができる。|
|nginx / Apache|Webサーバーのソフトウェア。|
|MySQL|データベースサーバーのソフトウェア。RDBMSの一種。|

###参考
udemy ゼロからはじめる Dockerによるアプリケーション実行環境構築

## さいごに
プログラミングの初学者です。その日に学んだことを学習の一環としてアウトプットしています。より深く学習していきたいと考えておりますので、内容に誤りがございまいたらご指摘等いただけますと幸いです。
楽天ブックスAPIを用いた書籍検索機能のRequest Spec

楽天ブックスAPIを用いたアプリを作成するにあたり書籍検索機能でリクエストスペックを書きたくなった。
調べてもあまり出てこなかったので手探りで実装してみました。

## ①楽天ブックスAPIの導入

下記サイトが非常に参考になりました。
https://www.for-engineer.life/entry/rails-rakuten-book-api/

ほぼほぼここに書いてあるとおりなので詳細な説明は割愛します。

## ②テストファイルの生成

```
rails g rspec:request books
```

こちらのコマンドでリクエストスペックファイルを生成

## ③ダミーデータの作成

```ruby
require 'rails_helper'

RSpec.describe "Books", type: :request do 
  let(:book_search_params) { {keyword: '７つの習慣'} }
end

```

ダミーデータをテスト上で作ります。パラメータとして送信するので名前はbook_search_paramsとしました。

## ④searchアクションでパラメータを受け取れるようにする

```ruby
def search
    return nil if params[:keyword] == ""
    @books = RakutenWebService::Books::Book.search(title: params[:keyword])    
    render json: { books: @books }  
```

記事では検索クエリが固定値だったので任意のパラメータで検索できるようにします。
ここでの疑問としては複数のパラメータで同時に検索できないか？ということなのですが果たしてできるのでしょうか…
パラメータで空文字列が飛んできた時はreturn nilとして処理を止めます。

フロントエンドから検索を実装したときに何も入力してなくても空文字列が送られてくると思ったからです。

## ⑤実際にテストコードを書く

```ruby
RSpec.describe "Books", type: :request do 
    let(:book_search_params) { {keyword: '７つの習慣'} }
describe "書籍の検索" do
    context "検索に成功" do
      it "パラメータが存在すればリクエストに成功する" do
        get search_api_v1_books_path, xhr: true, params: book_search_params 
        expect(response).to have_http_status(200)
      end

      
      it "レスポンスがJSON形式で返却される" do
        get search_api_v1_books_path, xhr: true, params: book_search_params 
        json = JSON.parse(response.body) 
        expect(json['books']).not_to eq nil
      end

    end

    context "検索に失敗" do
      it "パラメータが空文字列の時ステータス204が返却される" do
        get search_api_v1_books_path, xhr: true, params: {keyword: ""} 
        expect(response).to have_http_status(204)
      end
      
      it "パラメータが空文字列の時レスポンスは空文字列である" do
        get search_api_v1_books_path, xhr: true, params: {keyword: ""} 
        expect(response.body).to eq ""
      end
    end
  end
end
```

正常形、異常形それぞれでステータスとレスポンスの中身をチェックした。
これで実際にAPIと連携してテストが通った。

### 気になるところ

上にも書いたけど検索クエリって一つのパラメータでしか検索できないのかな？
だとするとキーと値を同時にparamsから取得して検索するような処理にしたほうがいいかも？