OmniAICreator/Qiita-1.07M huggingface dataset:
Python3 DynamoDBにAWS Lambdaからkintoneのレコードを登録する方法

DynamoDBにLambdaからkintoneのレコードを登録する方法のメモです。

# 環境

* Cloud9
* Python3.9
* pykintoneライブラリ

# 環境構築

## Cloud9にPython3.9をインストールする。

・pyenvのインストール
・Python3.9のインストール

## Boto3のインストール
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html

・pip install boto3

## pykintoneのインストール
https://github.com/icoxfog417/pykintone

・pip install pykintone

## EBSボリュームサイズ変更
https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/move-environment.html#move-environment-resize


# サンプルコード

```python
import os
import botocore
import boto3
import pykintone

class FetchError(Exception):
    def __init__(self, error, message="kintone record fetch error:"):
        self.error = error
        self.message = message
        super().__init__(self.message)
    def __str__(self):
        return f'{self.message} -> {self.error}'

def lambda_handler(event, context):

    try:
        domain = os.environ['SUBDOMAIN']
        loginuser = os.environ['LOGINUSER']
        password = os.environ['PASSWORD']
        appid = os.environ['APPID']
        backuptable = os.environ['BACKUPTABLE']

        dynamodb = boto3.resource('dynamodb')
        table = dynamodb.Table(backuptable)

        app = pykintone.login(domain, loginuser, password).app(appid)
        response = app.select("order by $id asc limit 500")
        if response.ok:
            records = response.records
            for record in records:
                print(record["$id"]["value"])
                table.put_item(
                    Item={
                        'id': int(record["$id"]["value"]),
                        'record': record
                    }
                )
            return {
                "statusCode": 200,
                "body": {
                    "message": records,
                },
            }
        else:
            print(response.error)
            raise FetchError(response.error)
    except botocore.exceptions.ClientError as error:
        print(error)
        raise error
```

# 参考

https://boto3.amazonaws.com/v1/documentation/api/latest/index.html

https://github.com/icoxfog417/pykintone

https://www.programiz.com/python-programming/user-defined-exception
『React実践の教科書』の学習メモ

Reactの基礎を押さえようと、『React実践の教科書』を学習。
そこで得た学びメモ。

# 第４章　Reactの基本
- コンポーネントファイルの拡張子は``.jsx``
- 全コンポーネントを出力するファイルは``.js``

## useState
- コンポーネントの状態を管理
- Reduxよりもコード数が少なく書ける

```
//例)
const [num, setNum] = useState(初期値);

//num = 状態を保持した変数
//setNum = その変数を扱う関数
```

## useEffect
```
useEffect(実行する関数, [依存する値]);
```


# 第５章　ReactとCSS
ReactでCSSをかける方法は6種類

## ①インライン記法
- あまり使用しない方法
- すぐにstyleを試したい時などに使う
```
const childStyle = {
    height: "200px",
    backgroundColor: "lightblue",
    padding: "8px"
}

return (
    <div style={childStyle}>
        <p>Child1</p>
    </div>
)
```

## ②CSS Modules（別ファイル読み込み）
- node-sassモジュール（パッケージ）をインストール　``npm install node-sass``
    - CSS（SCSS)ファイルは別で用意し、コンポーネントファイルに読み込む
## ③Styled JSX（CSS in JS）
- styled-jsxをインストール ``npm install styled-jsx``
    - コンポーネント内にCSSを記述
    - scss記法はできない
        - 別途ライブラリのインストールが必要
- Nest.jsで使われている

## ④styled components（CSS in JS）
- styled-componentsをインストール ``npm install styled-components``

## ⑤Emotion（CSS in JS）
- @emotion/reactと@emotion/styledをインストール
``npm install @emotion/react @emotion/styled``

## ⑥TailwindCSS
- それぞれをインストール
``npm install -D tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9``
``npm install @craco/craco``

### ※npm install @craco/cracoがインストールできなかった → react-scriptsのバージョンを4に変更
調べてみると、react-scriptsパッケージのバージョンが5になっているから？
https://stackoverflow.com/questions/67056349/craco-could-not-resolve-dependency-error

### （※後に画面表示自体できなくなったので、やらない方が良い）

4系統に落としてみる。
``npm remove react-scripts``
``npm install react-scripts@4``

再度cracoのインストールコマンドを打ち込むと、うまくいった。
``npm install @craco/craco``

```
//package.json
"@craco/craco": "^6.4.3",
"react-scripts": "^4.0.3",
```

### （保留）TailwindCSS が適用されなかった
Tailwind CSSのクラスを指定したものの、適用されなかったので、今回は保留。

# 第６章 再レンダリングの仕組みと最適化
## 　レンダリングをコントロール可能
親コンポーネントがレンダリングされると、子コンポーネントもされる（負荷高い）。
これをコントロールするのが、``メモ化``と呼ばれる機能。

memo化したいファイルに以下を記述。
```
import { memo } from "react";

export const ファイル名 = memo(() => {

})
```

## useCallback


# 第7章 グローバルなstate管理
Vue.jsでもVuexの概念があったが、Reactでも多階層のバケツリレー対策が取られている。

- Context（機能）
- Redux（ライブラリ）
- Recoil（ライブラリ）
- Apollo Client(ライブラリ・GraphQL使用時のみ)

※親コンポーネント = ルートコンポーネントという



## おまけ
storybook = コンポーネントのカタログ がある。

・React 向け Storybook のチュートリアル
https://storybook.js.org/tutorials/intro-to-storybook/react/ja/get-started/
【CircleCI】サブディレクトリのプロジェクトをビルド対象にする書き方

タイトルの通りですが、調べてもなかなか方法にたどり着けなかったので記録しておきます。
今回は私がよく使っている **Rails** をサンプルにします。

## ルートディレクトリにプロジェクトがある

### フォルダ階層

```
root
├── .circleci
│   └── config.yml
├── app
├── bin
├── config
├── db
├── lib
:
```

### 設定ファイル

下記の例は公式から持ってきたものです。
本当はjobsの中に `test` も合ったのですが、今回の説明では不要だったので削除しています。
- [言語ガイド: Ruby - CircleCI](https://circleci.com/docs/ja/2.0/language-ruby/)

```yml:.circleci/config.yml
version: 2.1

orbs:
  ruby: circleci/ruby@1.0
  node: circleci/node@2

jobs:
  build:
    docker:
      - image: cimg/ruby:2.7-node
        auth:
          username: mydockerhub-user
          password: $DOCKERHUB_PASSWORD
    steps:
      - checkout
      - ruby/install-deps
      - node/install-packages:
          pkg-manager: yarn
          cache-key: "yarn.lock"

workflows:
  version: 2
  build_and_test:
    jobs:
      - build
```

## サブディレクトリにプロジェクトがある

### フォルダ階層

下記のようにルート直下にプロジェクトがない場合は上記の書き方では失敗します。

```
root
├── .circleci
│   └── config.yml
└── project
    ├── config.yml
    ├── config
    ├── db
    ├── lib
    :
```


### 設定ファイル

`working_directory` と `checkout - path`を明示的に記述することで実現できます。

```yml:.circleci/config.yml
version: 2.1

orbs:
  ruby: circleci/ruby@1.0
  node: circleci/node@2

jobs:
  build:
    working_directory: ~/root/project    <---
    docker:
      - image: cimg/ruby:2.7-node
        auth:
          username: mydockerhub-user
          password: $DOCKERHUB_PASSWORD
    steps:
      - checkout:
          path: ~/root    <---
      - ruby/install-deps
      - node/install-packages:
          pkg-manager: yarn
          cache-key: "yarn.lock"

workflows:
  version: 2
  build_and_test:
    jobs:
      - build
```

## 参考
- [CircleCi 2.0 working with project inside the subdirectory - Stack Overflow](https://stackoverflow.com/questions/50570221/circleci-2-0-working-with-project-inside-the-subdirectory)
- [【CircleCI】working_directoryの挙動を実験して確かめてみた｜Webエンジニア研究室](https://www.engilaboo.com/circleci-working-directory/)
「ファイル名を指定して実行」ダイアログを使わずにファイル名を指定して実行する

# 結論

```bat
start ファイル名
```

# 背景

「ファイル名を指定して実行」ダイアログは、何を指定したかによって挙動が変わる。

* 実行可能ファイルが指定されたなら、そのファイルを実行する
* 実行可能でないファイルが指定されたなら、そのファイルの拡張子に紐づいたアプリケーションでそのファイルを開く
* フォルダが指定されたなら、explorerでそのフォルダを開く

指定したのが実行可能ファイル/実行可能でないファイル/フォルダのどれなのかを自動で判別してくれるという、便利で他には無い特性である。
それをコマンドラインで使う方法があるはずだ...と思って探した結果が上記の結論である。

# おまけ

startはcdやdelと同じくWindowsコマンドなので、start.exeというファイルは存在しない。
Pythonで使用する if __name__ == '__main__': の意味

## 概要
Pythonを学習していると`__name__ == '__main__'`という謎の構文が出てきて、
それについて調べたのでアウトプットしたいと思います。

## 使い方
`__name__ == '__main__'`は簡単に言うとファイルを読み込んだ際に
関数などの実行を制御してくれるものです。
例えば下記のようなファイルがあるとします。

```sample.py
def hello():
  print("Hello!")

hello()
```
`hello()`を別ファイルで使用しようとしたときファイルをimportします。

```example.py
from sample import hello

hello()
```
このとき`example.py`ファイルを実行するとどうなるか

```
python example.py // pyファイルの実行コマンド
// => Hello!
      Hello!
```
`Hello!`が2度表示されてしまいます。
これはファイルをimportすると読み込み先のファイルに記載されている関数が実行されるためです。
これを制御するために`if __name__ == '__main__':`を使用します。
先程の`sample.py`ファイルを下記のように修正します。

```sample.py
def hello():
  print('Hello!')

# 追加
if __name__ == '__main__':
  hello()
```
こうすることで`sample.py`をimportした際に`hello()`は実行されなくて済みます。

## 仕組み
`__name__`というのはPythonの特殊な変数で、モジュール名の文字列が格納されます。
`import hello`のようにモジュールが呼ばれることによって`__name__`に`'hello'`が格納されます。
しかし`__name__ == '__main__'`が記載されたファイルを直接実行（`python hello.py`）すると`__name__`が`'__main__'`という文字列になります。
つまり`if '__main__' == '__main__'`となり定義元のファイルを実行したときだけ呼び出すということになります。
なので`example.py`を`python example.py`で実行した場合、`'hello' == '__main__'`となり実行されない。
ディレクトリ内の全てのZipファイルを解凍【Shell】

# 複数のZipを一括解凍
たくさんのZipを一個一個解凍するのは面倒

# これで一発

```shell
unzip 'path_to_dir/*.zip'
```

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
SSHによるDynamic port fowardingとSocksプロキシのオンオフを自動でやる

## 動機と目指すこと
- 学内限定とかのコンテンツを触れる状態で長時間作業したい。
- ネットワーク遮断とかでsshが死んだときにsocksプロキシの設定を戻さないとwebページ見れなくなるのだるい。
- ssh接続→socksプロキシonの作業を毎回ポチポチやるのが面倒なので自動化したい。

## 環境
- MacOS Big Sur (11.6.2)
- ポートフォワード飛ばす先にはssh公開鍵によりパスワード無しで入れること前提。（パスワードを都度求められるだけなので実行はできる。）

## 手順

### autossh

ssh接続が切れたら自動で再接続してくれる。brewから簡単に入手できる。

```bash
$ brew install autossh
```

### スクリプト組む

スクリプトを組んでいく。ファイルの場所はどこでもいいが、とりあえずデフォルトでパスが通っているところで解説する。

スクリプトを書く。
```bash
$ vi /usr/local/bin/sproxy
```

中身はこれ。

~~~bash:sproxy
#!/bin/zsh
 
port=10080
method='wi-fi'

#--------------------------------------------------------------------
function trap_exit() {
   networksetup -setsocksfirewallproxystate $method off
   echo 'display notification "OFF" with title "proxy"' | osascript
}

trap trap_exit 1 2 3 15
#--------------------------------------------------------------------

networksetup -setsocksfirewallproxy $method localhost $port

echo "Turning on proxy"
networksetup -setsocksfirewallproxystate $method on
echo 'display notification "ON" with title "proxy"'  | osascript

echo "Starting SSH Dynamic Port Forwarding to Port $port..."
autossh -M 0 -D $port -C -Nv host
~~~

- `port`は好きなのを使っていい（5桁台がベター）。
- `method`は有線なら`ethernet`を指定する。
- 最後の行の`host`は自分のssh接続先を指定。いつもの書き方でok。ログが鬱陶しければ`v`オプションを消しても良い。



実行権限の付与をしておく。
```bash
chmod +x /usr/local/bin/sproxy
```



### 実行

```bash
$ sproxy
```
これでsocksプロキシが`on`になった。

### 終了したいとき
放って置くと常にプロキシを介した通信になる。終了したいときは`Ctrl+C`でスクリプトを止めてやれば良い。

## スクリプトの簡単な解説
- `networksetup -setsocksfirewallproxy $method localhost $port`は`wi-fi`のsocksプロキシで利用するサーバーを`localhost`の`10080`ポートに指定している。
GUIで言うと↓を指定していることに対応する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579569/8aeb967f-1157-c4f1-64fa-ad2f261443da.png)
- `networksetup -setsocksfirewallproxystate $method on`はsocksプロキシを`on`にする。画像で言えばチェックボックスにチェックを入れる作業。
- `autossh -M 0 -D $port -C -Nv host`で`autossh`によるsshコネクションの半永続化をする。`-M`は`0`を指定すると、ssh切断時に再接続するようになる。その他のオプションは通常の`ssh`と同じ。
- 最後に`trap trap_exit 1 2 3 15`でプロセスの終了前にsocksプロキシの`off`をねじ込む。本当は`trap trap_exit EXIT`だけでいいはずだが、なぜか動かない。。。まあ基本`Ctrl+C`での終了により異常終了シグナルが出るので問題ない。



## 参考
- [SSHのDynamic Forwardで学内ネットワークに入る](https://qiita.com/mu373/items/8236c3931e72194b4678)
- [sshのポートフォワーディングを維持するシェルスクリプト](https://hakobe932.hatenablog.com/entry/20080429/1209451898)
- [#Mac で SOCKS proxy の設定をコマンドだけで実行する](https://qiita.com/YumaInaura/items/7e1fcf9c23e7ba15e25b)
- [シグナルと trap コマンド](https://shellscript.sunone.me/signal_and_trap.html)
多言語対応のAtCoderテストツールをJavaで作成した話

初めまして、初投稿になります。記事というものを始めて執筆するため読みづらい部分がありますが、ご了承ください。  
私は最近趣味で競技プログラミングを触っていて主にAtCoderと呼ばれるサイトでプログラミングをしています。  
AtCoderでは大量の過去のコンテスト問題を触って勉強することができますが、いちいち入力例・解答例をコピーペーストでターミナルに張る作業がめんどくさいと感じてきてしまいました。  
そこで過去問をターゲットとして自動で入力例・回答例から正解・不正解を出力してくれるテスト自動化ツールをJavaを使って作成しました。  

## はじめに  
この記事では以下の記事を参考に作成をしています。  
実際に以下記事では私のツールでは賄えない部分まで賄えているため一度ご確認お願い致します。  
- https://github.com/kyuridenamida/atcoder-tools  
- https://github.com/nodchip/OnlineJudgeHelper  
- https://qiita.com/EngTks/items/a542c8f8585ca9e3f23f  

現時点(2022/04/08 04:00)では以下の8言語に対応しています。  
- Java. 
- Python3. 
- COBOL-Free. 
- GoLang. 
- Perl. 
- Ruby. 
- Dart. 
- C++.  

## 動作環境・ソースコード  
先にソースコード、動作環境を上げておきます。  
ソースだけ見たいという方もこちらからご覧ください。  

### ソースコード
https://github.com/xrozl/AtCoder-CuiTools

### インストーラー  
https://github.com/xrozl/AtCoder-CuiTools/releases/tag/1.0

### 動作環境
- OS: MacOSX (Monterey 12.2.1)
- Java 17.0.2 Amazon Corretto
- MacBook Pro 14'inch M1 Pro (16GB RAM)

## 1. 作りたいものを書き出す  
- AtCoderのコンテストページを取得して入力例・回答例のペアを作る
- 上記ペアと実際のプログラムの出力を確認して一致（正解）するか確かめる  
- ターミナルから1コマンドで実行できるようにする  
- 複数言語に対応する。（コンパイラ・非コンパイラ双方対応したい）
- 過去問を主として考えているのでレイテンシは最悪遅くてもかまわない。  
- ファイル管理・フォルダ整理等は自分で行うからとりあえずテストが楽になればいい（コンセプト）  
- 自分以外の人にも使ってもらいたい！  

作り始めるときに上記のコンセプト・計画で作り始めました。  

## 2. 実装等  
普段Javaを使用していることからJavaで作ろうと思い、JavaのライブラリであるJsoupを用いスクレイピングをして、コンテスト情報を取得しました。  
実際のテストには`ProcessBuilder`を使用し、新規プロセスを立ち上げそこに入力をし、出力を取得する方法でプログラムを作成しました。  
TLE等の実行時間の判定は`Process#waitfor`を使用して実装した。  
複数言語に対応するとのことでコンパイラ->実行の形式と実行の2形式で実装し、言語ごとに簡単に追加できるようにしました。  
zsh / fish用のインストーラを作成し、インストールを簡単にできるようにしました。  

## 3. 動作例
以下の写真は実際の動作例です。  
写真の中ではJava・Pythonのみになっていますが、現在は複数言語に対応しています。  
実際にコンテストページにアクセスし、時間制限・入力例・出力例を取得しAC等の判定を出しています。  
![](https://raw.githubusercontent.com/xrozl/AtCoder-CuiTools/master/sample.png)  

## 4. 問題点  
主にJava用で作り始めたため、Python等インタープリタ言語でCE・RE（判定は謎）が出る場合が稀にある。  
COBOL・GO等のコンパイル方式を導入している言語で1回目の実行が200~300msほど遅くなってしまう場合がある。  
インストールが少し複雑かつ`zsh` `fish`のみの対応となっておりWindowsでのテストが未確認。（実装上OS依存の実装はない為、恐らくできるがコマンドプロンプトからは試していない。）  

## 5. あとがき
実際にテストに使用してみて結構便利なのでこれからも言語を追加してみてどうなるか試してみたいと思いました。  
今回で別の言語もさわりだけ勉強し、楽しい言語が沢山あったので色んな言語を触れてみたいと思いました。  

もし記事が面白いなと思いましたらLGTMをぽちっとして頂けるとやる気につながります。
Phaser3.jsとTypeScriptで作成した4人UNOのソースコードを公開しました

作成した4人UNOのソースコードを公開しました。
全く綺麗ではないし、巧妙な書き方もできていません・・・が
どういうふうに作っているのだろうと興味を持たれた方の為に
公開しました。
Phaser3.jsが非常に優れているのでコードは非常に簡潔です！
一度理解してしまえば「なんだ、こんなものか」と感じると思います。

Git Hub のURL
https://github.com/new-doumeishi/new_vsUno

4人UNOをブラウザで遊ぶ（ネイティブアプリはありません）
https://www.new-doumeishi.me/vsUno_/
コピペで完結 超簡単 JavaScript クイズ 記述式

## はじめに
こちら開発の雑メモです。
JavaScriptの記述式のクイズの記事は案外探してみると少なかったり、理想のものが出てこなかったので、もし役に立てれば幸いです。
## 完成イメージ
完成イメージです！gifが小さいのでクリックして拡大してみていただければと思います。
![quiz.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/92191fac-1523-a1c8-0a00-939e96085d75.gif)

## 実際のコード
```html:quiz.html
 <form name="form">
  Q1)日本で一番大きい山はなんでしょう？<br>
  <font size="2" color="#FF0000">
    （答え記入後、「回答する」をクリックしてください）
  </font><br>
    答え：<input type="text" name="anser">
  <input type="button" value="回答する" onClick="check()">
</form>
<div id="feedback"></div>

<script>
function check(){
  const feedback = document.getElementById("feedback")
  if (document.form.anser.value=="富士山"){ 
    feedback.textContent = "正解！富士山の標高は3776mです。ちなみに2番目に高い山は北岳で3193mです。"}
  else {alert("残念、間違いです")}
}
</script>
```
JavaScript用のファイルを作って記述するのもありだと思いますが、今回は全てhtmlページに記述しております。ご了承くださいませ。
## 最後に
いかがでしたでしょうか？少しでも役に立てれば幸いです。
[ポートフォリオの技術選定について] Laravel Docker AWS GitHubActions

## はじめに
今回ポートフォリオとして、自宅の食品や日用品を管理できるような在庫管理アプリを作りました。
以下の技術を使って作成しました。
この記事では各技術の選定理由についてまとめていこうと思います。

## 使用技術
フロントエンド：HTML5、CSS、Tailwindcss2.2.15、Livewire
バックエンド：PHP7.4.15、Laravel8.34.0、Jetstream1.0
インフラ：Docker20.10.2、nginx1.18、MySQL8.0.23/phpMyAdmin、AWS EC2 ALB S3 RDS
デプロイ：GitHubActions（CI/CD） Deployer

## 技術選定理由
### フロントエンド
フロントエンドは主にTailwindcss（テイルウィンドシーエスエス）を使って実装しました。
TailwindcssはCSSのフレームワークです。

以下のような理由から技術選定。
・`ユーティリティファースト`
→CSSは使わずに`TailwindCSSが提供しているクラスのみを使用して実装`する考え方で、`クラスを追加するだけで定義できる`ため、`コードの量が少なくなる。`
・`便利で汎用的なクラスがたくさん用意されている`
・既存のクラスを`直接HTMLに書き込む`ことで要素のスタイルなどを実装できる

以下の記事に作成されたクラス一覧等が載っています。

https://tailwindcss.com/

### バックエンド
バックエンドはLaravel8（Jetstream、Livewire）で実装。

以下のような理由から技術選定。
・元々PHPを学習していた為、そのままPHPのフレームワークを学習した方が学習コストが少なく済む
・丁度Laravel8が新しくリリースされたばかりだった為、新しい技術にチャレンジできるチャンスだった
・MySQLなどデータベースとの連携が簡単
・`MVCモデルの採用`
→処理をModel（データ処理）View（画面表示）Controller（全体制御、MとVの架け橋）の3つに分別し、機能ごとに開発する手法。
　　`処理の内容とそれを書く場所が明確`になり、`開発の実務経験が浅い方でも学びやすく扱いやすい開発が行える。`

### インフラ
開発環境はDocker、デプロイ先のサーバはAWSのEC2を使用。

以下のような理由から技術選定。
「Docker」
・`他の仮想マシンと比較して軽量で速い為、作業が効率的`
→開発環境に変更が生じた場合、コンテナのイメージは軽量なので時間をかけずにダウンロードが可能。
・`コード化されたファイルで構築されてる為、容易に同じ環境が作れる`
→ミドルウェアのインストールや各種環境設定をコードで管理できるため、同じ環境で本番環境をつくることができる。
`毎度一から仮想マシンを構築しなくて済む`
これにより、開発環境では動いたが本番環境ではうまくいかないといった`環境によるリスクを軽減`できる。

「AWS EC2」
・`仮想サーバの構築が容易`
・`コンソールから簡単にスペックの変更やアップデートが行える`
・`無料枠で利用できる`
・`サーバーの複製が可能`
→AMIを作成しておけば、そのAMIから同じ仕様のEC2インスタンスを作成できる。

「RDS」
RDSはMySQLを構築するために使用しました。
・`サーバの準備が不要で構築後すぐにデータベースの利用が可能`
→通常データベースを利用する際はサーバを準備し、データベースのライセンスをインストールする必要がある。
・MySQLは複数のテーブルの結合がしやすい
・処理速度も速く、使いやすい

「S3」
S3は画像ファイルのアップロードに使用しました。
・無料枠がある
・EC2との連携が可能
・セキュリティ的に優れている。
→所有者ユーザーのみがアクセス可能。

### 自動テスト/デプロイ
CI/CD（自動テスト/デプロイ）パイプラインはGitHubActionsで構築。

以下のような理由から技術選定。
・`GitHubにそのまま統合できることから導入が簡単`
・`publicリポジトリだと無料で利用可能`
AZ-500用備忘録

PL-900をもってファンダメンタルを一通り取得したので今週はAZ-500を目標にしました。

4月3日よりマイクロソフトのeラーニングを読み込んで、知識チェック。
https://docs.microsoft.com/ja-jp/learn/certifications/exams/az-500

そして、measureup.comの模擬試験を8割取れるまで繰り返します。

英語なのでエッジのブラウザ翻訳を使用しましたが、

LOGの和訳が「丸太」でした。

4月9日に受験してきました。
模擬で学習したところは１割も出題されず、１問目から埴輪顔になりました。
AZ-104の内容+セキュリティ+ちょびっとMicrosoft365といった感じです。
SC-900と比べてシチュエーション等の「このシナリオならどうする？」
的な考えさせられる問題が目立ちました。
結果は何とか合格しました。AZ-104がベースにないと厳しいです。

受験にあたって知らないことが多すぎるので、ちょっとまとめます。

# 用語/使用方法
Azure Firewall
IP・ポートも含め、ドメイン・URLへのアクセス制限も可。

Azure Application proxy
ネットワーク上の内部リソースへのアクセスを許可できる。

ISO/IEC 27001
情報セキュリティマネジメントシステムに関する国際規格
Microsoft Defender For cloudで確認したりする。

MMK
Microsoft Managed Key

# Tips
・多要素認証用端末で認証用アプリが起動しないとき、一回限りのバイパスを作成して回避できる。

・Azure AD 条件付きアクセス(Conditional Access)
ユーザーがパスワード認証をした後にポリシーが適用される。

・Azure Key Vault　からのシークレットの読み取り
→ユーザーの承認を使用してのキーコンテナへのアクセスは管理者の同意を必要としない。書き込みの場合は同意が必要。

・セキュリティ監査ログについて
ＶＭの診断設定からゲストレベルの監視を有効にする。
→デフォルトは失敗のログのみなので、成功の監査も記録したい場合はログのタブに移動し、成功の監査をオンにして保存する。

・キーコンテナについて
管理プレーン・・・キーコンテナの作成、削除、ポリシー更新、プロパティの取得等
データプレーン・・・データの表示と管理

・Azure Files SMB
→Azure AD DS認証とオンプレのAD DS認証をサポート

・動的メンバーシップ規則
Premium P1以上のライセンスが必要

・プライベートエンドポイント接続
仮想ネットワーク外にトラフィックが出ないように使用する
【新人応援】分からないこと・知らないことを質問する勇気

# はじめに
率直に申し上げます、経験ベースのただのポエムです。
過度な期待はしないでください。

自身の来歴等について述べていますが、お忙しい方は「自身の結論」章を御覧ください。

現在27歳で転職SEをしている私が、
「数年前に大卒で新入社員として入社した時」の
「誰かに質問する」ということについて悩んだ話(やグダクダ)を書きます。

技術的・論理的な話は皆無な
経験則の話ですのでご了承下さい。

「有益な書籍」や「すべきこと」のような素晴らしい記事は
他のエンジニアの方々が既に記述されたモノがあるので探してみてください。

## 自身の結論
先に、以下の6点を結論として述べます。

　1. 怖いと思っても質問してみる(教えるのが仕事だろ！？くらいの勢いでガツガツいってみる)
　2. 同じ(似たような)質問はだいたい2回までにする(それまでにメモをきちんととって頭に落とし込む)
　3. なるべく箇条書きのような質問をする(結論と試してみたことを述べてから質問してみる)
　4. 業務上クリティカルな質問(例えば環境構築時の留意点など)は後続のためにドキュメント化する
 　　(もしそうでなくても、思い出すのが難解そうであれば積極的に実施した方がいいです)
　5. 質問方法・内容が間違っていたとしても恐れない！(失敗を踏まえて改善する)
　6. 悩みすぎて固まるより質問して進める
　　　(1時間の悩みより15分で質問に切り替える、のような)

人によってもちろん違うのですが、
個人的に「この辺が大切かな」と思うポイントをピックアップしました。

## 来歴
全く大した来歴ではないのですが、補足程度に書いておきます。
　1. 工業高校でC言語をメインで学ぶ。
　　卒業間近にJavaという存在を知り、少し触ってみる(環境構築、Hello,World 程度)  
　2. 情報系の四大に進学し、講義にてニッチな言語とJavaを学ぶ(入門書1冊分くらい)
　3. 就活を経て入社後、未経験が混ざる研修にて「俺、できる方やん(うへへ)」、などと
　　考えていたらテンプレのように配属後に叩きのめされる
　4. (この記事には無関係ですが)なんやかんやあって転職して今に至る

## 配属後について(この内容から「質問フェーズ」章に繋がります)
※ちょっと暗いかもしれませんが、愚痴ではないので、
　なんとか読んでいただければありがたいです。

(Java開発現場での話です)
　※既に自分で1から個人開発・デプロイしている方には恐らく無縁です。

　「教科書通り」より「ちょっと上」で過ごしていて
　「なんとなく通じるだろ」と思い込んでいた自分には衝撃の世界が広がっていました。

　「来歴」の「3.」で定期試験が実施されていたのですが、
　　好成績だったようで「今日から即戦力だ！」と(後の)上長から言われ
　　数十人いた研修組とは別に一人だけ現場配属され、ウッキウキでした。

　しかし、ここから「分からないこと」のオンパレードでした。
　まず、フルスクラッチでシステム構築中の現場に配属されました。(開発と単体テストの同時進行中)
　「最初は現場コードが分からないだろうからテストを通して知る」
　みたいな流れは往々にしてあると思います。
　当然ですがそういった役割にアサインされました。
　
　意訳含めですが、配属初日の指示は以下のようなものでした。(環境構築は除きます)
　__「JUnitでテスト回してC1のカバレッジが100%になるようにして。
　　テスト外の部品はmock使って実施して、必要だったらリフレクションも使っていいから。
　　バグやテスト完了の報告はチケット登録でよろしく。」__

　冗談を考えている暇はなかったのですが
　思わず「ルー語か何かかな？」と思ったことを今でも覚えています。
　あとは「デザインパターン」の話も出てきて尚更混乱しました。(こちらについては省略します)

## 質問フェーズ
　前章の指示をされた後、
　まず、知らない単語は、「JUnit」、「C1」、「カバレッジ」、「リフレクション」、
　「mock」、「チケット登録」、「デザインパターン」だと洗い出しました。

　その後、
　「ググった結果、実際の導入から利用方法・本当に意味が分からないこと」について
　絞って質問しました。
　
　例ですが、おおまかに以下のように分類して、
　後者について正直にそのまま言って質問しました
　
　■ググって「意味が分かった」もの
　・「C1」、「カバレッジ」
　
　■ググって「単語の意味は分かったけど、結局、何をどうするのか分からなかった」もの
　・「JUnit」、「リフレクション」、「mock」、「チケット登録」、「デザインパターン」

　結果として、「怒られる！！！」と思っていた自分の想像とは
　全く異なりすんなり指導してもらうことができました。
　
　「新人」という期間であれば、
　極論「何をどう調べたけれど(自分なりの努力をしたけど)、分かりませんでした！！」
　くらいに質問しても許容してもらえることが多いと思います。
　(自分なりに色々試してみたけど、ということが重要な感じです)

　仮に、「怒鳴る」、「露骨に態度に出す」等の極端な反応があった場合は、
　ご自身のせいではないのですぐに転職を視野に入れましょう。

　現場独特の「ピリピリした空気」や「誰に質問していいか分からない」
　などで日和ることがあるかもしれませんが、「分からなくて当然だろ！！」
　くらいの強気で「とりあえず配属後に現場で会った人」に質問してみましょう。

　タイトル通りですが、「質問する勇気」を持って質問してみましょう！！！

## さいごに
　もし、それでも不安なら、このQiitaで質問や記事の投稿をしてみましょう。
　私自身もこの記事を書いているだけで不安だらけですが、
　「やってみて」「改善点を認識したら」「直す」、
　いわゆる「PDCAサイクル」の「DCA」の部分を
　私みたいに思いつきで「仕事」ではなく試せるので、
　やってみる価値は充分にあると思います。(PLANの部分は各々計画してください。)

　アウトプットを色々してみることで
　確実に自身の力になると思います。

　勢いで書きましたが、誰かの何かの役に立つことがあれば幸いです。
　
　グダグダしましたが、新しい1歩を踏み出す方々を応援しております。
ProcessXの実装から振り返るC#と.NETの進化 

C#で外部プロセス呼び出しをかんたんに扱えるようになるライブラリ ProcessX を使う機会があったんですが、その使い勝手のよさとc#/.NETの進化に驚いたので感動ポイントを共有します！ 

機能概要とGitHubリポジトリはこちら↓

https://neue.cc/2021/08/23_602.html

https://github.com/Cysharp/ProcessX

# 対象読者

- C#/.NETの知識が数年前で止まっている＆最近の動向が気になる方
- ProcessXの実装に興味がある方
※ライブラリの使い方については本記事では扱いません

# サンプル実装

この４行のソースだけで、「dotnet --version」のコマンドを実行し、結果をコンソール出力できます。素敵。

```Program.cs
using Zx;
using static Zx.Env;

var currentVersion = await "dotnet --version";
log($"現在の.NET SDKバージョン： {currentVersion} ");
```
すこしC#をかじっていればなんとなく読めると思いますが、なぜこれでコンパイルエラーなく動作してるのかキチンと説明しろといわれると困ってしまう人もいるかとおもいます。ひとつずつみていきます。

## usingの数が少ない件
### 注目点
いつもの「Program.cs」だと

```csharp
using System;
using System.Collections.Generic;
...
```

のようにたくさんusingが並んでいたはずですが、今回のソースにはそれが見当たりません。
意識して使わないといけない名前空間だけ記述してます。

### 新機能｜global using
これはC# ver10.0で追加された *global using* という機能によるものです。
ポイントとしては下記２点。

 - global using という C# の文法を追加
 （globalという修飾子をつけることでプロジェクト全体に影響を及ぼすusingが定義できるように）
 - .NET SDK 側で、コンパイル開始時に所定の global using コードを生成

コンソールアプリの場合、以下のようなソースコードが自動生成・コンパイルされるため、ソース本体に記述するusingの数が減らせる、という仕掛けのよう。

```csharp
// <autogenerated />
global using global::System;
global using global::System.Collections.Generic;
global using global::System.IO;
global using global::System.Linq;
global using global::System.Net.Http;
global using global::System.Threading;
global using global::System.Threading.Tasks
```
### 参考文献
https://ufcpp.net/blog/2021/8/newprojecttemplate/


## いつもの「おまじない」がない件

### 注目点
いつものProgram.csだとあるはずの「おまじない」

```csharp
    class Program
    {
        static void Main(string[] args)
        {
            // hogehoge
        }
    }
```

「class Program」も「static void Main...」も見当たりません 👀

### 新機能｜top-level statements
これはC# 9.0で追加されたトップレベルステートメントという機能によるもの。
最上位に記述したメソッドがコンパイル時におまじないに包まれる形で展開されるようです

## await "コマンド" 

今回、一番謎だったのが
```Program.cs
var currentVersion = await "dotnet --version";
```

なんだこれ。 awaitのあとに文字列??
neueccさんのブログでもコメントされてました

>stringをawaitしていることに一瞬違和感はめちゃくちゃあるでしょうが、DSLだと思って慣れれば全然自然です（そうか？）。

めちゃくちゃ違和感あります。

### async/awaitの仕様を再確認
普通ならコンパイルエラーになるはずなのになぜ動くのか。
ヒントはここに

https://blog.xin9le.net/entry/2012/08/10/124154

> await演算子に渡すことができるインスタンスは、以下の条件を満たす必要があります。
> Awaiterを返すGetAwaiterメソッドを持つ

なるほど。IFもいらなくてダックタイピング的な仕様になっていると。
ライブラリのソースを探してみるとたしかにありました

```StringProcessExtensions.cs
namespace Zx
{
    public static class StringProcessExtensions
    {
        public static TaskAwaiter<string> GetAwaiter(this string command)
        {
            return ProcessCommand(command).GetAwaiter();
        }
        ....
    }
}
```

string型の拡張メソッドとしてGetAwaiterが定義されてます。
stringのインスタンスをawaitにわたすと非同期処理が可能になるってことですね。
ナルホド。

# まとめ

そんなこんなで、いろいろとc#/.NETが進化した結果このような便利なライブラリが誕生してました、というお話でした。C# 10.0で追加されたInterpolatedStringHandlerも活用されてるようで少し気になるところですが長くなってきたのでとりあえずこのへんで。
最後までお付き合いありがとうございました〜
vscode rails環境構築時のエラー rails s

```rails s```でエラーが起こった。
```
********@mbp jisaku_app % rails s                 
=> Booting Puma
=> Rails 7.0.2.3 application starting in development 
=> Run `bin/rails server --help` for more startup options
Exiting
/Users/********/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/webpacker-5.4.3/lib/webpacker/configuration.rb:103:in `rescue in load': Webpacker configuration file not found /Users/********/jisaku_app/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /Users/********/jisaku_app/config/webpacker.yml (RuntimeError)
```
```rails webpacker:install```した方がいいらしい。
行ったが下のエラーが出た。
```
********@mbp jisaku_app % rails webpacker:install 
sh: node: command not found
sh: nodejs: command not found
Node.js not installed. Please download and install Node.js https://nodejs.org/en/download/
Exiting!
********@mbp jisaku_app % node -v
zsh: command not found: node
```
node.jsをダウンロードした方がいいらしい。
```
********@mbp jisaku_app % brew install node
.
.
.
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
```
ダウンロード成功。

もう一回　```rails webpacker:install```してみた。
```
********@mbp jisaku_app % rails webpacker:install
Warning: you are using an unstable release of Node.js (v17.8.0). If you encounter issues with Node.js, consider switching to an Active LTS release. More info: https://docs.npmjs.com/try-the-latest-stable-version-of-node
Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/
Exiting!
```
```yarn```をインストールした方がいいらしい。
```
********@mbp jisaku_app % node -v                
v17.8.0
********@mbp jisaku_app % brew install yarn
.
.
.
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`)
```
もう一回```rails webpacker:install```
```
*******@mbp jisaku_app % rails webpacker:install
.
.
.
Webpacker successfully installed 🎉 🍰
```
成功。
どうやら```node.js```と```yarn```をダウンロード、インストールを行わなければならなかったらしい。

肝心の```rails s```は...
```
＊＊＊＊＊＊＊@mbp jisaku_app % rails s                
=> Booting Puma
=> Rails 7.0.2.3 application starting in development 
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
.
.
.
Use Ctrl-C to stop
```
成功！
業務時のGitなどの操作

インターンに入って時間が経ち、そろそろgitの使い方にも慣れてきたと思っていましたが、まだいくつか間違えそうなところがあるので自分のためにも記事に残しておきます。

## タスクのブランチ操作
[こちら](https://qiita.com/iguchan_4649/items/6c74779d73e31856c78f#%E4%BC%9A%E7%A4%BE%E3%81%AEgit%E7%8A%B6%E6%B3%81%E3%81%8C%E6%9B%96%E6%98%A7%E3%81%AA%E3%81%BE%E3%81%BE%E9%80%B2%E3%82%81%E3%81%AA%E3%81%84)でPR作成までの流れをgitで行い、次のタスクを行うときは以下の流れで行うようにします。

1. `git checkout master`でmasterやstagingなどのメインブランチに移動
2. 常に最新の情報を取得したいため、`git pull origin master`でmasterやstagingなどのリモートリポジトリの変更内容を取り組む
3. `git checkout -b branch`で作業ブランチ作成&移動

作業後、他のメンバーの開発がマージされてるかもしれないので、push前に`git pull origin master`を行なってコンフリクト解消しても良いかもしれません。 

## マイグレーションやり直して過去のタスクのマイグレーションが反映しないようにする(Rails)
上記のようなタスクの流れで行い、タスクでテーブルを追加するようなマイグレーション操作を行なった場合、その後別のタスク（別ブランチ）で`rails db:migrate:status`を行うと

```:Rails
 Status   Migration ID    Migration Name
--------------------------------------------------
...
   up     20220117124649  ********** NO FILE **********
```

のように`********** NO FILE **********`として別ブランチに含まれてます。
同じように`db/schema.rb`にも前タスクのマイグレーション操作が含まれるので、これによる不具合を防ぐためにも`rails db:migrate:reset(rails db:reset)`を行なってマイグレーションをリセットします。

しかし、`rails db:migrate:reset`だとデータが全て消えてしまうので、大体の場合は`rails db:migrate:rollback`で巻き戻すのが良いと思います。

## PR時作成にマージ先を間違えない
最初の頃はマージ先を設定することを知らず、今でもたまに忘れちゃいそうになります。後から対処するのもめんどいので忘れないようにしたいです。マージ先はタイトル上のbaseのセレクトボタンで変更できます。
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/848640/57abd1ac-215b-2d50-95fc-7196b9da019f.png">


PR作成後にマージ先を間違えたと気づいた場合、タイトルの横のEditボタンを押すと変更できます。
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/848640/aee33777-1940-9f55-f7d5-3f4f4e46fafa.png">


## マージの打ち消し
CIの不具合などでマージ自体を打ち消したいことがないこともないと思いますが、そんな時はGitHub上で簡単に打ち消すことができます。
1. PRのコミットの横にRevertボタンがあるのでクリックします。
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/848640/5c18f9c8-c0c7-1fa2-128e-f600bfc53ddf.png"><br>
2. 打ち消しPR作成画面が表示されるので、タイトルや説明を好きに編集して作成します。このとき、ブランチ名は先頭に`revert-2-`がついていると思います。また、打ち消しPRの内容を確認すると、追加した内容が打ち消されています。
3. 打ち消しPRを作成し、マージすると追加した内容が無かったことになっていると思います。

打ち消し自体をまた無くしたい（元に戻したい）場合は、打ち消しPRのRevertボタン押して同じように進めるだけです！


また気をつけるべきことがあったら追記します。

## 参考
https://konaga-k.hatenablog.com/entry/2021/09/19/103446
https://saikeblog.com/2020/03/09/github%E3%81%A7pull-request%E3%81%AE%E3%83%9E%E3%83%BC%E3%82%B8%E3%82%92%E6%89%93%E3%81%A1%E6%B6%88%E3%81%99%E6%96%B9%E6%B3%95/#toc2
GPG キーを他のデバイスと共有する方法

# この記事を読むと実現できること
既存の GPG キーを新しいデバイスにコピー・移動させることができる。

# GPG キー ID の取得
GPG キーが存在するデバイスで、以下のコマンドを実行する。

```shell
gpg -k
```

上記コマンドを実行すると以下のように表示されるはずだ。

```
pub   ed25519 2022-04-03 [SC]
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
uid           [ultimate] noraworld <mail@noraworld.com>
sub   cv25519 2022-04-03 [E]
```

`XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` となっている部分をコピーする。

# 秘密鍵のエクスポート
先ほど取得した GPG キー ID をもとに、秘密鍵をファイルにエクスポートする。

GPG キーが存在するデバイスで、以下のコマンドを実行する。

```shell
gpg --export-secret-key -a XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX > private_key
```

カレントディレクトリに秘密鍵が生成される。

`private_key` は秘密鍵なので、**誰かが画面を見ているときやシェルのログを記録している場合などは不用意にファイルの中身を開かないほうが良い** だろう。

# 秘密鍵のコピー
先ほど生成した `private_key` を、新しいデバイスにコピーする。USB メモリなどに `private_key` をコピーし、それを新しいデバイスにコピーする。

`private_key` をコピーする際は、**ネットワークを介さないほうが理想だが、ネットワーク経由でないとコピーできない場合は必ず `scp` などの暗号化された通信で行う** こと。

# 秘密鍵のインポート
`private_key` をインポートする。

新しいデバイスで、以下のコマンドを実行する。

```shell
gpg --import private_key
```

これで GPG キーが新しいデバイスで使えるようになった。

# 確認
新しいデバイスで、以下のコマンドを実行する。

```shell
gpg -k
```

同じ GPG キー ID が表示されたら正しくインポートされたことがわかる。

# 秘密鍵の安全な削除
**この作業は絶対に怠ってはいけない**。

エクスポート・インポートのために生成した `private_key` を完全削除する。

ここで注意すべきは、**`rm` コマンドを使って削除してはいけない** ということだ。ましてやゴミ箱に移動させるだけなどもってのほかだ。

代わりに `shred` コマンドを使う。

`shred` コマンドの詳細については、「[ハードディスク内のデータを本当の意味で完全消去する方法](https://zenn.dev/noraworld/articles/delete-data-in-hdd-completely)」を参考にしてみてほしい。

以下のコマンドを、GPG キーがもともと存在するデバイスと新しいデバイスの両方で実行する。USB メモリなどにコピーした場合は、その USB メモリ内でも同様に実行する。

```shell
shred -uvz private_key
```

これでほぼ復元不可能な状態で `private_key` を削除することができた。

# 注意点おさらい
* 不用意に秘密鍵のファイルの中身を開かない
* 秘密鍵は安全にコピーする
* インポートし終わったら秘密鍵は完全に削除する

# 参考サイト
* [How can I use my gpg key with other devices?](https://dotmethod.me/posts/pass-password-manager-share-gpg-key/)
L2コンストラクトからL1コンストラクトにリファクタリングしたときにIDを保持する


```python
l2_resource.node.default_child.override_logical_id(id)
```

# 参考
* https://bobbyhadz.com/blog/override-logical-id-aws-cdk
* https://docs.aws.amazon.com/cdk/api/v1/python/aws_cdk.core/CfnResource.html#aws_cdk.core.CfnResource.override_logical_id
* https://docs.aws.amazon.com/cdk/api/v1/python/aws_cdk.core/ConstructNode.html#aws_cdk.core.ConstructNode.default_child

# メモ
aws-glue.Jobの場合はdefault_childでCfnJobにアクセスすることができた。
が、default_childの説明を読んでもよくわからず。わかったら追記する。
AWS CDKでL2コンストラクトとL1コンストラクト間で依存関係を貼る

```python
l1_resource.node.add_dependency(l2_resource)
```
リソース.nodeに対して処理を行えばよい。

# 参考
* https://docs.aws.amazon.com/cdk/api/v1/python/aws_cdk.core/ConstructNode.html#aws_cdk.core.ConstructNode.add_dependency
【ImageMagick】windows11でImageMagick入れて、Railsでrmagickを使う手順

<h2>環境</h2>
windows11

Rails 6.0.4.1
ImageMagick 6.9.12-44
rmagic4.2.5

<h2>概要</h2>
Railsでrmagckを入れる際にwindowsでやってる記事が見つからなかったので、書きます。

rmgcik2.16.0までではimageMagick７バージョンに未対応らしいので、ImageMagick６バージョンを入れていきます。
引用元↓

https://www.ownway.info/Ruby/rmagick/howtoinstall/windows

<h2>ImageMagickを入れる</h2>

以下のサイトのWindows版のところからダウンロードします。

https://legacy.imagemagick.org/script/download.php

ダウンロードしたら、起動。すると下記の画面が表示されます
「Iaccept the agreement」を選択して、規約に同意します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927880/dfbc7e4a-6bae-a284-1b12-cc5a6d196ce5.png)

「Next」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927880/d01c5b28-ea70-d561-9b3b-eaed890aca5d.png)

インストールする場所を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927880/2266029d-cb19-7e71-9c01-8a489ab094b5.png)

その他オプションも選択します。
下記のように選択しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927880/fd147b03-2787-0cc9-1e52-deb0f3c84a6d.png)


インストール前の確認画面です。そのまま「install」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927880/e37a107d-1c58-c195-b5cf-0f8f1c0e0a76.png)

インストールのバーが100%になったら、この画面になります。「Next」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927880/9b5aadb4-dcd8-8167-fc44-efa139c3b85e.png)

完了画面です。｛Finish」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927880/e8a59310-21a5-658a-7dd4-10ebe2d281f7.png)

一応、きちんと入っているかをバージョン確認します。
convert --versionコマンドを実行します。

```terminal:バージョン確認
$convert --version  
Version: ImageMagick 6.9.12-44 Q16-HDRI x64 b350dd1:20220327 https://imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Visual C++: 193131104
Features: Cipher DPC HDRI Modules OpenCL OpenMP(2.0)
Delegates (built-in): bzlib cairo flif freetype gslib heic jng jp2 jpeg lcms lqr lzma openexr pangocairo png ps raqm raw rsvg tiff webp xml zlib
```

<h2>Railsにrmagickを入れる</h2>
Gemに書いて、bundle installするだけです。

```ruby:Gemfile
gem 'rmagick','4.2.5'
```

```terminal:bundleinstall
$bundle install
(中略)
Using rmagick 4.2.5
```

これで完了！Railsサーバーも起動して正常に動作しました。

<h2>参考</h2>

https://workabroad.jp/tech/1118

https://legacy.imagemagick.org/script/download.php

https://www.ownway.info/Ruby/rmagick/howtoinstall/windows
基本情報技術者試験対策　26日目

基本情報技術者試験勉強　26日目
-
この記事の目的
-
今年の5月に基本情報技術者試験を合格するために、過去問で間違えた箇所をただまとめる自分のための記事

プロフィール
-
・文系大学の３年生
・ITパスポートは保有
・ウェブアプリやサイト作成を個人で行ったことがある程度
・猫好き

今日の目標
-
今日も引き続き、午前問題を30問は解くことと午後問題を2問は解く。

間違った箇所
-
1、IDS
ホストやネットワークへの不正アクセスを監視し、検知した不正挙動をネットワーク管理者に通知する機能を持つソフトウェア、ハードウェア

2、メモリ管理ユニット(MMU:Memory Management Unit)
仮想記憶のページング処理を高速に行う
ページング処理は、メモリ領域を決まった大きさに分割し、管理する。メモリを効率的に使用できる

3、RADIUS
認証情報と認証手続き、および利用ログの記録をネットワーク上のサーバに一元化することを目的としたシステム

4、スナップショットダンプ
指定した命令が実行されるたびに、レジスタや主記憶の一部の内容を出力することによって、正しく処理が行われていることを確認

5、インスペクタ
プログラムの実行中、必要に応じて変数やレジスタなどの内容を表示し、必要であればその内容を修正してテストを継続する

6、ドライバ
プログラムを構成するモジュールの単体テストを行うとき、そのモジュールを呼び出す仮の上位モジュールを用意して、動作を確認する
周辺装置を扱うために、必要なプログラム

7、ミラーポート
ネットワーク上の通信パケットを取得して通信内容を見るために設けられたスイッチのLANポート
データをコピーして、別のポートに流す

8、SOAP 
HTTPプロトコルを用いて，XML形式やHTML形式のデータがファイアウォールを通過できるようにした通信方式

9、TLB(Translation Lookaside Buffer）
仮想記憶のアドレス変換を高速に行う

振り返り
-
今日もとりあえず30問解いたが、答えを見ても、イメージできない部分もあるので、自分の言葉でよりわかりやすくまとめることとなるべくイラストを見て学ぶ。

>引用
基本情報技術者試験ドットコム
https://www.fe-siken.com
【Next / React】「Unhandled Runtime Error.ChunkLoadError: Loading chunk node_modules_next_dist_client_dev_noop_js failed」エラーが出た

個人の備忘録です。

# 環境
- Node.js 16.10.0
- Next.js 11.1.3
- React.js v17.0.2

# 現象
`yarn dev` でブラウザ表示をしたら以下のようなエラーが出ました。

![Screen Shot 2022-04-07 at 19.05.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/b6276c2e-e5c9-1c31-242f-ef6312dcc829.png)

```text:原文
Unhandled Runtime Error.
ChunkLoadError: Loading chunk node_modules_next_dist_client_dev_noop_js failed. 
(error: http://localhost:3000/_next/static/chunks/fallback/node_modules_next_dist_client_dev_noop_js.js)
```

# 解決策
筆者の環境の場合、以下で解決しました。

- /.next フォルダーを削除
- `yarn dev` で再度ブラウザ表示
- ブラウザキャッシュの削除 (Shift+F5 / Cmd+Shift+R)


# 文献
https://stackoverflow.com/questions/67652612/chunkloaderror-loading-chunk-node-modules-next-dist-client-dev-noop-js-failed
【Rails】Could not find gem 'rmagick (= 2.16.0)' in locally installed gems.の対処法【rmagick】

<h2>症状</h2>
rmagickをinstallして、Railsサーバーを起動したところ、下記のエラーメッセージが表示されました。
翻訳すると、「ローカルにインストールされたgemでgem'rmagick（= 2.16.0）'が見つかりませんでした。
ソースには、次のバージョンの「rmagick」が含まれています。4.2.5
`bundle install`を実行して、不足しているgemをインストールします。」

```terminal:error
$ gem install rmagick
Could not find gem 'rmagick (= 2.16.0)' in locally installed gems.
The source contains the following versions of 'rmagick': 4.2.5
Run `bundle install` to install missing gems.```

一応Gemfileのrmagickも記載します。

```ruby:Gemfile
gem 'carrierwave'
gem 'rmagick','2.16.0'
```

<h2>解決策</h2>
エラーメッセージ通り、Gemfileのrmagickのバージョンを書き換え、指示通りにbundle installをすると、Railksサーバーが動くようになりました！

```ruby:Gemfile
gem 'carrierwave'
gem 'rmagick','4.2.5'
```
PHPのexec()で正しくPythonを実行してるのに、なんかModuleNotFoundErrorになるんですけど！？

## はじめに
みなさま、PHP使っていますか。

PHPからPythonを呼び出す用事があり、やむなくPHPで外部プログラムを実行できるexec()を使いました。
自称PHPerとしては断腸の思いの決断です。

cronやシェルスクリプトなど、こういう系では**フルパス**を使うのが定石と存じ上げています。
なので
```php
$path="/usr/bin/python3 /...フルパス/.py";
```
として、exec()に渡しました。
```php
exec($path,$output);
```
## パスは正しいのに、動かないときがある？
ちゃんとPythonのコードは実行されていて、print文だけみたいな**簡単なコード**なら動くんです。
ちゃんと$outputにprint()などで入れた標準出力が帰ってきています。

でも本来動かしたい、少し規模の大きいコードを動かすと$outputがすっからかんに……

これはどこかでエラーが出ている可能性大なので、エラーを出させてみます。

このような形で
```php
$path="/usr/bin/python3 /...フルパス/.py 2>&1";
```

2>&1を末尾につけると、$outputにエラーメッセージも含ませることができます。
## ModuleNotFoundErrorが何故か出ていた……
エラーを見てみると
```
ModuleNotFoundError: No module named "モジュール名"
```
です。
もちろん**pipし忘れていたてへぺろ☆的なこと**ではありません。

間違いなく
```
pip3 install モジュール名
```
しました。

で、最大の厄介は**SSHしたターミナルから同じPythonソースファイルを実行するとエラー無く動く**ことです。
最初に挙げた通り**フルパス**で指定していますから実行されるPythonは同じです……

## 同じPythonでも、呼び出されるモジュール先が違った
タイトルのとおりです。
と、その前にPythonが**どこからモジュールを呼び出しているか**確認してみましょう。
### 確認方法
下記のようなコードを書き連ねて、
```python
import sys
import pprint

pprint.pprint(sys.path)
```
このPythonファイルをexec経由で実行すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621241/93f78bab-9a6d-952e-c409-c4d820db5135.png)
モジュール検索パスが出力されます。

で、同じPythonファイルをターミナルから実行すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621241/63f0c191-cee3-8972-d593-bc3554f53a3e.png)


exec()で実行したときには**モジュール検索パスにsite-packageが含まれていない**のです！
### ユーザーによる違い

PHPからexec()経由だと**www-data**ユーザーで実行され、SSHから実行すると**自分でログインしたユーザー**で実行されます。
私はsudo pip3 install は非推奨とどこかで聞いていたので、自分でログインした一般ユーザーでpip3 installしていました。
これが元凶です。

Ubuntuを初めとしたDebian系だと起きるらしいのですが
```
pip3 install mysqlclient
```
と
```
sudo pip3 install mysqlclient
```
では**インストール先が違うんです！！**
前者だと**site-packages**、後者だと**dist-packages**にインストールされるみたいです。
で、普段一般ユーザーでPythonを実行する時は**site-packages**、**dist-packages**どちらも含めてPythonがモジュールを探し出してくれます。
なので、どちらのコマンドで実行しようがModuleNotFoundErrorにはなりません。

しかし、exec()での実行だとwww-dataユーザーでの実行扱いになり、**site-packages**にインストールされたモジュールを探し出してくれないのです。
## そして解決へ
exec()でPythonを実行するとdist-packagesを読みに行くので、そこにモジュールがインストールされる形でpipコマンドを走らせます。
sudoするだけですが(これで良いのか……)
```
sudo pip3 install mysqlclient
```
こういった要領で、必要なモジュールを改めてインストールしていきました。

そして、解決。
モジュール検索パス側を変えるという手もあるみたいですが、サーバー上のPythonでは他に用途がないので、ワイルドにsudoしちゃえってことにしました。~~簡単ですから……~~
Pythonの仮想環境ことvenvを使えばいいじゃんという意見もあるのですが、execコマンドで非同期的な実行をさせたい場合には、仮想環境立ち上げと破棄を&で繋いだものをexecに渡す形となってしまい、うまく非同期的な実行できないんですよ……
## 編集後記
エラーのハンドリング、めちゃ大事ですね……
私はそもそもModuleNotFoundErrorであることに気づくまで、めちゃくちゃ時間かかりました。
2>&1をつければすぐ出来るのに、それそら忘れていました。
ちゃんと**フルパスで指定**してる上、**ターミナル**からなら実行できるの謎だ……世の中は不条理だって諦めかけていたのも良くなかったという反省をしています……
さらにDockerによるローカル開発環境では正常動作しており、それがまた厄介さを極めました……本番と完全同じなテスト環境が欲しくなります。
[Rails6/TailwindCSS] No route matches [GET] "/packs/js/*.js")が出た時に行った修正

## 結論

これを

```erb:application.html.erb
<%= stylesheet_link_tag 'application', 'data-turbolinks-track': 'reload' %>
```

こうした。

```erb:application.html.erb
<%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
```

## 背景
[DMM WEBCAMPの卒業生コミュニティ](https://twitter.com/Webcamp_COMM)でDocker環境でチーム開発をして勉強をしていた際に、Rails6にTailwindCSSを導入して開発を進めるタイミングがありました。

Gemの`gem 'tailwindcss-rails'`を使用して読み込ませていたのですが、何らかの作業ミスか設定が原因で、作業中にCSSが自動で更新されなくなることが起こりました。

## 問題
コンテナの中に入り、`webpack`コマンドの実行でコンパイルをするとCSSの修正が反映されるのですが、毎度毎度実行するのは非常に苦でした。

修正方法を調べてみると`webpack-dev-server`の実行でホットリロードができるようなのですが、もう一つターミナルを立ち上げて実行した結果、掲題のエラーが出ました。

## 調査結果
色々調べた結果、なぜか該当のタグが`link`になっており、うまくコンパイルできていなかったので、コンパイル先のファイルを参照できなくなって、Routing Errorが起こっておりました。

なかなか時間を取られてしまったのでまとめてみました。

同様のエラーが出た際は、ぜひチェックしてみてください。
CloudFrontでリダイレクトするメモ

## CloudFront Functionsを使う

CloudFront Functionsを使うと、ビューワー（クライアント）に送信する前にHTTPレスポンスを変更することができる。
CloudFront Functionsの利用例にも下記の記述がある。

> URL リダイレクトまたは書き換え: リクエスト内の情報に基づいてビューワーを他のページにリダイレクトしたり、すべてのリクエストをあるパスから別のパスに書き換えたりできます。
> https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/cloudfront-functions.html

## CloudFront Functionを作成する

CloudFrontのマネジメントコンソールから関数を作成し、下記のような関数コードを書いて発行する。

```handler.js
function handler(event) {
    var response = {
        statusCode: 302,
        statusDescription: 'Found',
        headers: {
            'location': { value: 'https://qiita.com/' }
        }
    };
    return response;
}
```

リダイレクトさせたいディストリビューションの**ビューワーリクエスト**に対してこの関数を関連づけると、ディストリビューションのデプロイが完了した後、ディストリビューションのドメイン名にリクエストを送信するとリダイレクトされるようになる。

## ビューワーリクエストに関連付ける理由

ビューワーリクエストで関数を実行した場合、キャッシュされたレスポンスやCloudFrontによるそれ以降の処理をチェックすることなく、ビューワー（クライアント）に直接返すため。
関数で`return response`すると、直ちにビューワーに返される。

## 参考
https://aws.amazon.com/jp/blogs/news/introducing-cloudfront-functions-run-your-code-at-the-edge-with-low-latency-at-any-scale/

https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/cloudfront-functions.html

https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/writing-function-code.html
Rechart を Next.js で使うと「Warning: Prop id did not match. Server:」 が発生


# 結論

回避する一つの方法は、コンポーネントをサーバーレンダリングしないことです。
![Screen Shot 2022-04-07 at 22.45.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/942749/086f27b0-3fb8-cb10-5e06-45fa37d4df5d.png)

## default export で Rechart のコンポーネントを使用している場合
```ts
const MyChart = () => {
  return (
    <BarChart data={data}>
      <XAxis type="number" />
      <YAxis dataKey="name" />
      <Bar dataKey="name" stackId="hogeId" fill={"red"} />
    </BarChart>
  );
};
export default MyChart;
```

```ts
import dynamic from "next/dynamic";
const DynamicMyChart = dynamic(() => import("./MyChart"), { ssr: false });
```

## named export の場合

```ts
export const MyChart = () => {
  return (
    <BarChart data={data}>
      <XAxis type="number" />
      <YAxis dataKey="name" />
      <Bar dataKey="name" stackId="hogeId" fill={"red"} />
    </BarChart>
  );
};
```

```ts
import dynamic from "next/dynamic";

const DynamicMyChart = dynamic<Record<string, unknown>>(
  () => import("./MyChart").then((module) => module.MyChart),
  { ssr: false }
);
```

## 解説

> 「Warning: Prop id did not match. Server:」

これは Next.js の一般的な警告です。
クライアントの DOM とサーバーでレンダリングされた DOM が正確に一致しない場合に発生します。この場合、recharts の ID がクライアント側で異なるために表示されます。

dynamic import を利用すると**非同期**で import 処理ができます。

dynamic メソッドの SSR 回避のオプションを付与することでこのエラーを回避しています。SSR 回避とは、通常はサーバサイドで実行される制御をクライアントサイドで処理させてしまうことです。

# 余談 dynamic の他の使い方など

## ローダーとパフォーマンス改善に使える

ダイナミックコンポーネントのロード中にローディング状態をレンダリングすることができます。
また動的にインポートすることで初回レンダリングの量を削減し、ページロードの読み込み時間を削減することができます。

```ts
const DynamicMyChart = dynamic<Record<string, unknown>>(
  () => import("./MyChart").then((module) => module.MyChart),
  { ssr: false, loading: () => <p>Loading...</p> }
);
```

Github の Issue：
[Prop id did not match between server and client](https://github.com/recharts/recharts/issues/2272#issuecomment-802096207)

Next.js 公式サイト：
[Dynamic Import](https://nextjs.org/docs/advanced-features/dynamic-import)
sort()の中身のkeyとlambdaが分からない

## sort()のlamdaって何者？

python3エンジニア認定基礎試験問題集に以下のようなコードの記載があります。

```
toshi_code = [(42, 'naga'), (41, 'saga'), (40, 'fuku'), (43, 'kuma')]  
pref = toshi_code  
pref.sort (key = lambda pref: pref[0])  
print( pref) 

>>>[(40, 'fuku'), (41, 'saga'), (42, 'naga'), (43, 'kuma')]

```
outputがなぜこうなるのかわからなかったので、公式ドキュメントを漁ってみました。

### pref.sort(key=lambda pref: pref[0])の解説
まずは[sort()の公式ドキュメント](https://docs.python.org/ja/3/howto/sorting.html)を確認します。
すると、このような記述が。
「list.sort() と sorted() には key パラメータがあります。 これは比較を行う前にリストの各要素に対して呼び出される関数 (または呼び出し可能オブジェクト) を指定するパラメータです。」
すなわち今回は、prefの要素ひとつひとつに対してlambda関数が適用されているようです。

（lambda関数がわからない方は、[こちら](https://note.nkmk.me/python-lambda-usage/)を参照されて下さい。）

pref.sort (key = lambda pref: pref[0]) 
は、prefの各要素の0番目の要素でprefをsortするということになります。
Javascript if文でメッセージを出し分ける

## はじめに
javascritのif文の書き方を学ぶ
### 参考書
https://www.sbcr.jp/product/4815601577/
## ゴール
if文でダイアログのボタンごとにメッセージを出し分ける
## 手順
```js:ダイアログボックスを表示してOKまたはキャンセルでメッセージを出し分ける
<script>
'use strict';

if (window.confirm('ゲームを開始します。準備はいいですか？')){
 console.log('ゲームスタート!'); //OKを選択するとtrueの分岐へ
} else {
 console.log('ゲームオーバー・・・'); //キャンセルを選択するとfalseの分岐へ
}
</script>
```

### メモ
`window.confirm`これで確認ダイアログボックスが出せる
[随時更新] M1 Mac Setup

# 概要

転職後のチームで開発環境を構築するとき、
「あれ、なんか手順通りにやると上手くいかない・・・」
「はっ！M1 Macだからか！」
となることが多々あったので、次回&後輩のための備忘録
※汎用的ではなく、あくまで現在の業務において必要なもののみ。

# Iterm2

**何はともあれまずはこれ。これさえやっておけばどうにかなる。**
ダウンロードした後、下記の設定を実施。
- Finder > Application > Iterm2を右クリック > 情報を見る > Rosettaを使用して開くにチェックを入れる

これをしてないと、javaやmysqlなど諸々インストールする際に面倒なことになる。

# Homebrew

例の如く[公式のコマンド](https://brew.sh/index_ja)を実行。
もしrosettaでterminalを起動していない場合は、頭に`arch -x86_64`をつけて実行すればintelチップ等と同じアーキテクチャ扱いでinstallできる。

# brew install hogehoge 系

前段のIterm2(その他ターミナル), Homebrewが正しくinstallできていれば、これまで通り`brew install hogehoge`をしてOK。
但し、javaやmysqlなど、指定したバージョンをinstallしようとしたら失敗する！となった場合には、ARMアーキテクチャ扱いでinstallしようとしているケースがあるので注意。

# mysqlコンテナ

ローカルでmysqlの環境を構築するために、Dockerコンテナを使おうとした。
```
FROM mysql:5.7.34
```

↑だとM1 Macの場合コンテナ起動できないため、
```
FROM --platform=linux/x86_64 mysql:5.7.34
```

このように書く必要がある。
こちらの記事([M1Mac環境でDockerのMySQLを動かす](https://qiita.com/toyoyuto618/items/f225e1b2ab22ca5adf33))で詳しく書かれているので参考にしてください。

# その他

※初M1 Macなので、今後も何か起き次第随時更新
基本情報技術者試験(CBT)に合格しました

※markdown練習用の記事です。はい。

# 受験の目的
はるか昔に紙の試験で合格したことあり。CBTを試しに受けてみたかったのでなんとなくおためし。

# ひとまず結果
午前：83.75 (67/80)
午後：94 (2問間違えた)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527830/847dfc25-3ea6-c735-7eba-2495f815b334.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527830/9b4b4126-c13d-f0c0-da32-df13f42c61fd.png)

# 出題されたこと
書いちゃだめ。

# とにかく過去問をやる
* コツ？対策？いいから過去問。（少なからず知識のベースがあることが前提）
* 午前：基本情報ドットコムでひたすらまわす。知識がある程度身に付いたと思ったらまわす頻度を落とす。
* 午後：午前で知識がついてからやる。ただ解くのではなく、解説を読んで理解することが大事。
    * 問題文のどこに根拠があるか。
    * 午前問題に相当する知識として何が必要か。
* ちなみに午後はIPAの過去問を紙で大量印刷して線引きながら解く派。

# CBTに思うこと
### 過去問がない、と思いきや、ある
最新の過去問はないけど、公開されている紙の過去問で十分。

### 線が引けない、と思いきや、とりあえず引ける
画面上で、ハイライトはできる。

### 文字を書きこめない
紙のメモはもらえるので、手元で計算はできる。でも問題冊子（画面）に書けないので解きにくい。

### 問題文の行ったり来たりがとにかくしにくい
マウスでスクロールするのではなく、PDFのように前ページ/次ページで切り替えるべし。プログラミング系はきつい。

### 選択問題の指定が漏れにくい
全部解答すると、その問題を自動的に選択した扱いにしてくれる。（手動でも指定できる）

### 試験結果がすぐ分かる
これが唯一の、かつ、最大のメリット。結果が出るまでのもやもやがない。

### 自分の解答した内容が分からない
これは仕方ない。

### 講評がない
どれだけ需要があるか分からないけど。あぁ、基本情報の講評はいらないかな。

# まとめというか、言いたいこと
1. ハイライトで画面に線を引きまくれ。
1. マウスでぐりぐりスクロールするな、ページを切り替えるべし。
1. 公開されている過去問は大事。古いから要らないなんて思うな。いじょ。
ラズパイ RTKGNSS ドコモ RTKLIB

## 環境
raspberry pi 4B
Raspbian
F9P
RTKLIB 2.4.3
ドコモ補正情報（契約要）

## 全体像
<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378923/e50799f9-f0ee-4b31-c98d-9c64fee5a314.png">



## インストール
・RTKLIB 2.4.3 b34を以下のコマンドでインストール
ソース取得
```
git clone -b rtklib_2.4.3 https://github.com/tomojitakasu/RTKLIB.git
```
コンパイル
```
cd RTKLIB/lib/iers/gcc/
```
```
make
```
```
cd RTKLIB/app/consapp
```
```
make
```
インストール
```
cd RTKLIB/app/consapp
```
```
sudo make install
```
## RTK測位
以下のコマンドを実施することで、RTK測位を開始し、TCP port:1111に出力する
```
cd RTKLIB/app/consapp/str2str/gcc
```
```
./str2str -p 緯度 経度 高さ -n 1000 -in ntrip://ユーザーアイディ:パスワード@サーバユーアールエル:ポート/マウントポイント
#rtcm3 -out serial://ttyACM*:115200#1111 -b 1
```
※緯度、経度、高さは今の測位位置
※ユーザーアイディ、パスワード、サーバーＵＲＬ、ポート、マウントポイントはドコモの情報から入力
※ttyACM*はF9Pのシリアルポート
　シリアルポートの確認方法：https://qiita.com/m2_labo/items/7823fb26197fa5f5ff23

## 測位結果確認
別のコマンドを開き以下のコマンドを実施すると測位結果が表示される
```
nc localhost 1111
```

## 参考サイト
https://qiita.com/k-koh/items/3cf612eb7428375ef2cf
https://github.com/tomojitakasu/RTKLIB/tree/rtklib_2.4.3
http://www.rtklib.com/
http://gpspp.sakura.ne.jp/index.shtml
Rails 7.0.2にアップグレード後、SQLインジェクションの危険性のあるクエリがエラーになった

# エラー内容

エラー内容は以下。

```text
ActiveRecord: :UnknownAttributeReference: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "field(id, ?)".This method should not be called with user-provided values, such as request parameters or model attributes. Known-safe values can be passed by wrapping them in Arel.sql().
```

要は、「field(id, ?)はSQLインジェクションの危険があるから、危険じゃないことを確認できてるならArel.sql()で囲め」とのこと。

エラー出た部分のコードは以下の様な感じ。


```ruby
User.where(id: ids).order(['field(id, ?)', ids])
```

whereしてきたid一覧と同じ順番でレコードを取得したいときにやるやつですね(MySQL限定)。

以前のRailsでも警告はされていた様ですがRails7からはエラーとして上がってくる様になったみたいです。


# 解決法

言われた通りArelで囲んでも解決しますが、この様なケースの時に使えるメソッドがRails7から追加されています。
https://techracho.bpsinc.jp/hachi8833/2021_10_28/113117

この`in_order_of`を使って書き換えてみることにします。

```ruby
user = User.in_order_of(:id, [3, 5, 2, 4, 1])
# => User Load (0.6ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` IN (3, 5, 2, 4, 1) ORDER BY FIELD(`users`.`id`, 1, 4, 2, 5, 3) DESC

user.pluck(:id)
# => [3, 5, 2, 4, 1]
```
正しい順番で取れてきている様です。field句を使っているみたいですがMySQL以外の時はどうなるのか気になるところですね。また、配列逆順にしてDESCで取ってくるのはなんでなのか気になりますね。普通に同順にしてASCでもいいのではないかという気はします。

Rails 7にアップグレードする際は事前に上記の警告を潰しておいた方がよさそうです。