OmniAICreator/Qiita-1.07M huggingface dataset:
【GitHub Actions】プルリクエスト作成時にCIが流れるか確認

## はじめに
GitHub にてプルリクエスト作成時に GitHub Actions のCIが流れるかテストをしたので記事としてアウトプットをしたいと思います。

## イメージ図

![CI CD-CI.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/abd07bf0-1149-5eb2-3886-016047604b04.png)


## 前提
- GitHub上に既にリポジトリが存在する状態
- GitHub上にGitからPushできる環境が整っている状態


## 作業手順

- `.github/workflows`直下に以下のファイルを配置します。

```sample.yml
name: Action Sample

on:
  pull_request:
    types: [opened]

jobs:
  print-hello-world:
    runs-on: ubuntu-latest
    steps:
      - name: execute echo command
        run: echo "Hello World!"
```

今回は、`Hello World!`と表示させるだけの処理になります。

- GitHub上にコードをPushすると、以下のように自動で処理が流れる。


![スクリーンショット 2023-01-11 1.08.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/841510ad-7d57-e703-1949-f3de23924f31.png)


```zsh:出力
Run echo "Hello World!"
  echo "Hello World!"
  shell: /usr/bin/bash -e {0}
Hello World!
```

## 参考
https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions

https://helve-blog.com/posts/git/introduction-to-github-actions/
Predicate interface

test methodは、引数に対し、booleanを返す。

```java
public class Outer {
    public static void main(String[] args) {
        Predicate<Integer> p1 = x -> x > 0;
        Predicate<Integer> p2 = x -> x > 100;
        Predicate<Integer> p3 = p1.or(p2);
        System.out.println(p3.test(50));
    }
}
```
```
true
```
IE・EdgeのIEモードでデバッガ起動していないとjavascriptが動かなかった

地味にはまったことメモ


# 状況
デバッガ（F12、EdfeのIEモードはIEChooser）を起動していないとjavascriptが動かなかった。
jsでバリデーション後、ajaxで送信するというコードだったが
バリデーションも開始しない状況だった。
コンソールに「関数を指定してください」と出ることもあった。

# 試したこと

ajax処理前に以下を追加したが改善せず

```
$.ajaxSetup({
    cache: false,
});
```

ここを参考にした
https://ja.stackoverflow.com/questions/11204/ie11-%E3%81%A7%E9%96%8B%E7%99%BA%E8%80%85%E3%83%84%E3%83%BC%E3%83%AB%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%81%A8-consoleapi-%E3%82%84-ajax-%E9%80%9A%E4%BF%A1%E3%81%8C%E6%9C%9F%E5%BE%85%E3%81%97%E3%81%9F%E6%8C%99%E5%8B%95%E3%82%92%E3%81%97%E3%81%AA%E3%81%84

# 原因と解決方法

- `start()`という関数から`isValid()`というバリデーションのコードを呼び出しており、
trueだったらajaxで送信する、というコードになっていた。
結果の返却が間に合わなかった模様。
（trueなのかfalseなのか判定不能になっていた、もしくはfalseに入っていたと思われる。おそらく前者）
→ `validate()` という関数名にしてそちらにまとめたところ改善。

- `</body>`タグの後に`<script></script>`タグを書いていた。
bodyタグの内側にないとだめだった。
これは多分「関数を指定してください」の方の原因だったと思われる。
Amplifyのビルド時に表示されたエラー

## はじめに
フロントエンドの勉強をしていて、作成したWebサイトをAmplifyでホスティングすることにしました。
その中でAmplifyのビルド時にエラーが表示されたため、その内容を記載します。

## ビルドの設定
Amplifyのビルドの設定として、最初は下記の設定をしていました。
```php:amplify.yml
version: 1
frontend:
  phases:
    preBuild:
      commands:
        - nvm install v12.16.2
        - nvm use v12.16.2
        - npm install -g yarn
        - yarn install
        - node -v
    build:
      commands:
        - yarn run build

  artifacts:
    baseDirectory: dist/
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*
```

## エラー文
上記の設定にてビルドしたところ、下記のエラーが表示されました。
```
2022-XX-XXTXX:XX:XX.XXXZ [INFO]: yarn install v1.22.19
2022-XX-XXTXX:XX:XX.XXXZ [INFO]: [1/4] Resolving packages...
2022-XX-XXTXX:XX:XX.XXXZ [INFO]: [2/4] Fetching packages...
2022-XX-XXTXX:XX:XX.XXXZ [WARNING]: error vuetify@3.0.0-beta.10: The engine "node" is incompatible with this module. Expected version "^12.20 || >=14.13". Got "12.16.2"
2022-XX-XXTXX:XX:XX.XXXZ [WARNING]: error Found incompatible module.
2022-XX-XXTXX:XX:XX.XXXZ [INFO]: info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
2022-XX-XXTXX:XX:XX.XXXZ [ERROR]: !!! Build failed
2022-XX-XXTXX:XX:XX.XXXZ [ERROR]: !!! Non-Zero Exit Code detected
```

## 原因
指定していたNode.jsのバージョンと互換性がないことが原因でした。

## 対処方法
まずは、Amplify上で動作しているNode.jsのバージョンを確認することにしました。
ビルド設定のpreBuildの先頭に「node -v」を追加して確認したところ、「v14.19.0」と表示されました。
ビルド設定の「v12.16.2」部分を「v14.19.0」と変更することで、無事にビルドすることができました。

## ビルド設定
最終的なAmplifyのビルドの設定は、下記の通りです。
```php:amplify.yml
version: 1
frontend:
  phases:
    preBuild:
      commands:
        - nvm install v14.19.0
        - nvm use v14.19.0
        - npm install -g yarn
        - yarn install
        - node -v
    build:
      commands:
        - yarn run build

  artifacts:
    baseDirectory: dist/
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*
```
【個人開発】料理人のための仕込み管理アプリCucina-クッチーナ-を作りました

## はじめに
こんにちは！@harufumi03と申します。
この記事は初学者が初めて個人開発したWebアプリの紹介記事です。
ちなみに「クッチーナ」という名前はイタリア語で「キッチン」という意味です。

アプリURL：http://cucina-app.com/
「仕込み」とは？...お客様に素早く料理を提供するための下準備のこと

## 開発の経緯
私は調理師として働いていた経験があり、困り事がありました。
###### それは日常業務の「仕込み」についてです。
私の経験上「仕込み」を行う時は担当している仕込みを個人的に管理してホワイトボードやメモなどに書き出して管理していました。それにより他の人と使用する食材が重なってしまったり、気をつけていても忘れてしまって仕込みが出来ず、関連する料理の提供ができないという事もありました。この問題点をチーム内で共有して誰が何の仕込みをしてどの食材を使用するのか分かるようになれば解決できてお客様にも問題なく料理を提供できるのではないかと考え開発しようと考えました。
<img width="600" alt="kaiketsu.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2874920/dcc092a0-7eff-6181-c4d5-863961dbcffe.png">

## 使用環境
ruby 3.0.1
Ruby on Rails 6.1.7
PostgreSQL 14.5

## 実装した機能
#### 【TOP画面】
全体的にさわやかな印象で作成しました。
![スクリーンショット 2023-01-12 16.35.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2874920/e55581e3-3e74-69fd-905e-527344f77811.png)

#### 【グループ機能】
あらかじめ登録したユーザのメールアドレスを入力する事でチーム内への招待が可能になります。
![add_group.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2874920/a5d106a2-0b39-fe7f-32a4-3d032909819d.gif)

#### 【仕込み管理機能&コメント申し送り機能】
日々行う仕込みを雛形として登録しておきます。
![スクリーンショット 2023-01-12 17.13.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2874920/7d4a32b5-701b-2257-d27a-85dcc8bcc3e6.png)

登録した仕込みを日にちを指定して選択することで予定に追加することができます。
リストには当日のみの仕込みだけが表示されるため、担当者や使用食材が確認できます。
またカレンダー上で過去の仕込みや今後の予定も確認することができるので、前回の仕込みから何日経過しているかなども視覚的にわかりやすくなっています。

![shikomi2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2874920/a53e9725-eb8e-51e7-4c43-cb262b44df4d.gif)

仕込み予定に対してコメントできる機能を実装しており、引き継ぎのための申し送りなどもすることが出来ます。

![comment.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2874920/f39b0d6d-2e7f-6603-d31d-3d9ec3af46a4.gif)


## 今後追加したい機能
- 食材の在庫管理機能
- 消費期限の追加→期限が近づいた時の通知機能
- グラフなどを用いたUIの修正

## さいごに
最後までご覧いただきありがとうございます！
至らないところも多かったと思いますが、まだまだ技術をみがいて自分自身もアプリも成長させていきたいと思います。
【初心者専用】ガベージコレクションについて

# 0. はじめに
新卒社員がJavaを初めて学習している際の備忘録のようなものです。超入門だと思うので同郷を救いつつ自分の知識も再確認といったところで、今回初耳だった「ガベージコレクション」について問題を通してまとめました

# 1. ガベージコレクションについて
ガベージコレクションとは「メモリ上使われなくなったインスタンスを探し、見つかればそのインスタンスを探し、見つかればそれを破棄しメモリを開放すること」です。

そのガベージコレクションのタイミングが問われるのが以下の問題になります

```java
public class Main {
	public static void main(String[] args) {
		Object a = new Object();  //A
		Object b = new Object();  //B
		Object c = a;

		a = null;
		b = null;

	}
}

```
上記のプログラムを実行し、7行目が終了したときにガベージコレクションの対象となるインスタンスはどれか？

1. A
2. B
2. AとB両方
2. 対象はない

:::note info
正解：2. B
:::

正直、初見で見た際にガベージコレクションを知らなくても、英語の意味合いやBだけCに参照していないな。などの判断材料でなんとなく2が正解というのは分かったのですが、4の理由が言えず、、、、

ということで解説していきたいと思います


# 2. 解説

そもそも、「**メモリ上使われなくなった**インスタンス」 とはどういうインスタンスなのか？
先ほどもちらっと推測で述べましたが、「**参照されなくなった**インスタンス」のことです。
また参照がされなくなったインスタンスで代表的なものがnullですね。

```java
Object a = new Object();
a = null; //参照されなくなったインスタンス
```

nullが代入されたタイミングで変数aは参照されなくなります。

しかし、
```java
Object a = new Object();
Object b = a;
a = null;
```
上記のコードであると
変数aは参照されなくなりますが、変数bにはインスタンスが生成されたままになっています。

この２点を抑えて、問題を見てみると３行目でインスタンスが生成された後、５行目で別の変数に参照しているので、Aの変数はガベージコレクションの対象にならないことが明白ですね。

またBに関しては、そのままnullが代入されて参照されなくなっているので、ガベージコレクションの対象になります。

よって、この問いの答えは「**2. B**」となるわけです。


# 3. 番外編

参照されなくなるタイミングは以下のように明示的に示す場合も存在します。

```java
var fs = new System.IO.FileStream("test.txt",System.IO.FileMode.Open);

//fsを利用して何か処理...

//ストリームを閉じる
fs.Close(); //参照されなくなる
```
パス情報をApp.configで指定する

Excelのパスをハードコードしていたため、App.configで指定する方法に変更した。

※ClosedXMLライブラリを使用しています。
詳しくは↓
[ExcelのデータをC#で取得する](https://qiita.com/suzuki_q/items/502bf2bc1df7ec209333)

## 指定方法

ソリューションエクスプローラーから**App.config**ファイルを開く。

\<configuration>\</configuration>
の中に、以下の設定を記述していく。
```App.config
<appSettings>
<add key="FilePath" value="C:\Users\example..." />  
</appSettings>
```
※パスの区切りのバックスラッシュ(\\)は、実際のApp.configの見た目では¥になっています。(おそらく日本語環境を使用しているとそうなる)

## 指定した設定の取得方法
**必要なusing記述**
```c#
using System.Configuration;
```
※using System.Configurationの記述だけでうまくいかない場合、ソリューションエクスプローラーにある参照を右クリックして、参照の追加を選択。
System.Configurationを検索して、チェックボックスにチェックを入れると使用できるようになる。
### App.configで指定したパスを取得する
[]の中にはadd keyで指定した名前を入れる。
```c#
var wb = new XLWorkbook(ConfigurationManager.AppSettings["FilePath"])
```
<br>
<br>

#### 関連記事
https://qiita.com/suzuki_q/items/e0e061c559b3f3f22a64

<br>
手順: JWTを使用してHasuraの認可トークンを生成する

HasuraとJWTは、Webアプリケーション開発において重要な役割を担う技術です。Hasuraは、GraphQL APIを構築するためのオープンソースのプラットフォームであり、JWTは、Webアプリケーションでの認証と認可に使用される標準規格です。

今回は、HasuraでJWTを使用して認可トークンを生成する手順を紹介します。


# STEPS:

有シークレットキーを生成し https://cloud.google.com/network-connectivity/docs/vpn/how-to/generating-pre-shared-key

![Pasted Graphic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1034667/5e2ea710-3aaa-b7c1-7957-d603b4ba5bc8.png)

私の場合、このキーを生成しました。“Pn/t8ZuDDsja1wkTSQyXbqnDT/N8X0SG”

ステップを追って、サイトを開きます。 https://jwt.io 

そして、私たちのデコードされたキーとエンコードされたキーを作成します


![Pasted Graphic 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1034667/0b584c6b-f995-ae45-6c7d-143f0e6c0149.png)

ここに、生成したキー（私の場合は「Pn/t8ZuDDsja1wkTSQyXbqnDT/N8X0SG」）を入力します。

ペイロードを宣言します。
```
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "https://hasura.io/jwt/claims": {
    "x-hasura-allowed-roles": ["admin", "user"],
    "x-hasura-default-role": "user",
    "x-hasura-user-id": "1234567890",
    "x-hasura-org-id": "123",
    "x-hasura-custom": "custom-value"
  }
}
```


私は役割として管理者とユーザーを使用しています。詳細については、こちらをご覧ください: https://hasura.io/docs/latest/auth/authentication/jwt/

![Pasted Graphic 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1034667/051cc2c2-dfe4-84d1-3fc9-ddf79dea91a2.png)

次に、HasuraのWebページのenv変数に移動します。そして設定します。

HASURA_GRAPHQL_JWT_SECRET 

この内容で：
```
{
    "key": "Pn/t8ZuDDsja1wkTSQyXbqnDT/N8X0SG",
    "type": "HS256"
}
```


私の場合、私は前にGoogle Cloudサービスで生成した秘密鍵（Pn/t8ZuDDsja1wkTSQyXbqnDT/N8X0SG）を使用しています。覚えていますか？

![Pasted Graphic 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1034667/bfd2f2ce-3707-34b9-d574-64823e4cc81f.png)


更新してから1分間待ちます。その後、コンソールに移動して、ヘッダーにJWT.ioから生成された認可（エンコードされたコード）を設定します。
「Bearer」というワードを追加し、スペースを確認してください。
例: 「Bearer あなたのエンコードされたコード」

現在、テスト中：

![Pasted Graphic 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1034667/ea9578a8-bfca-2342-6b38-7039dafa4e6c.png)

JWTを使用してHasura APIを保護することで、APIへのアクセスを制御し、APIからの取得データを保護することができます

この後、バックエンドを生成するか、FirebaseやAuth0のようなサービスを使用してトークンを自動生成することができます。

そして完了です！
コピペで出来るDjangoアプリケーション開発環境構築（その１）

# はじめに

https://www.udemy.com/share/103OHY3@Hp1LP8z4636rKvwf7s6WkJUqqjnfnoWk1ugFKS8PxdYwWkOnNH9OsoDQnZhF7KisUg==/

この講座を見てDjangoの勉強をしています。
今後の開発のために簡潔に開発の流れをまとめました。
その１です
[その２](https://qiita.com/scythercas/items/f960a50b3639e864aae2)
[その３](https://qiita.com/scythercas/items/a55548db6dd4e8edc59b)

# 開発環境構築の流れ
## Miniconda(Anaconda)のインストール

https://docs.conda.io/en/latest/miniconda.html

ここから使用pcのビット数に合ったものをインストール

## 仮想環境を作成する
```terminal
$ conda create -n sample python=3.10
```
```
Proceed ([y]/n)?
```
と出るので、`y`と入力


## ディレクトリを新規作成し、VSCodeで開く
## ターミナルをコマンドプロンプトで開く
今回パワーシェルだとあんまよくないらしい

## 仮想環境を有効化する
```terminal
$ conda activate sample
```
`C:`などの左に`(sample)`とあればおｋ
## Djangoをインストールする
```terminal
$ conda install django
```
```
Proceed ([y]/n)?
```
と出るので、`y`と入力

## Djangoの雛形を作る
```terminal
$ django-admin startproject sample_project
```
## 作成されたディレクトリ内の`settings.py`を少し修正する
107行目くらい
```diff_python
- LANGUAGE_CODE = "en-us"
+ LANGUAGE_CODE = "ja"

- TIME_ZONE = "UTC"
+ TIME_ZONE = "Asia/Tokyo"
```
のように直す。
また、DATABASEもデフォルトはSQLiteになっているので場合によっては修正する。
## 実行

### 作成したプロジェクトをカレントディレクトリにする

```terminal
$ cd sample_project
```

### Djangoを立ち上げる
```terminal
$ python manage.py runserver
```
ポート番号を指定したい場合はこう(デフォルトは`8000`)
```terminal
$ python manage.py runserver 8080
```

## 定義したテーブルをDBに作成する
```terminal
$ python manage.py migrate
```

## アプリケーションを作成する
```terminal
$ python manage.py startapp sample_app
```




# その他のコマンド
## 仮想環境を非アクティブにする
```terminal
$ deactivate
```

## 作成済み仮想環境の一覧を確認する
```terminal
$ conda env list
```

## 作成した仮想環境の削除
```terminal
$ conda remove -n sample --all
```

# 以上
細かい説明は全くしていないので、各コマンドの説明やDjangoに関する説明などは動画を見ることをお勧めします。

続きはこちら！↓

https://qiita.com/scythercas/items/f960a50b3639e864aae2

ジャンゴジャンゴ～
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2666100/c2f3eef2-e338-2501-f497-97373da75deb.png)
Azure Administrator(AZ-104)：Azureストレージアカウントの種類と冗長性について

この記事は、Microsoft Azure Administrator(AZ-104)の受験勉強の中で、自分が間違えやすい、覚えにくいと思ったポイントの一つをまとめたものです。同じく資格取得に向けて勉強されている方の参考になれば幸いです。

## Azureストレージアカウントの種類

Azureストレージアカウントには、Standard汎用v2 や PremiumブロックBLOB などの種類が存在し、利用できるサービスや冗長性のオプション、アクセス層の利用が異なります。
詳細は[MS Learnのドキュメント](https://learn.microsoft.com/azure/storage/common/storage-account-overview#types-of-storage-accounts)を参照ください。
ここでは、Azureストレージアカウントの種類と冗長性オプションの利用可否について記載します。
（冗長性オプション以外に、Azure Import/Exportの利用可否やライフサイクル管理機能の利用可否などもストレージアカウントの種類に依存しており、自分は混同することがありました）

## 冗長性オプション

冗長性オプションとしては下記のようなものがあります。
|冗長性オプション|プライマリリージョン|セカンダリリージョン|
|:----|:----|:----|
|ローカル冗長ストレージ (LRS) |1 箇所でデータを同期的に 3 回コピー|コピーされない|
|ゾーン冗長ストレージ (ZRS) |3 箇所の Azure 可用性ゾーン[^1]間でデータを同期的にコピー|コピーされない|
|geo 冗長ストレージ (GRS) |1 箇所でデータを同期的に 3 回コピー|プライマリリージョンから非同期的にコピー後、LRSで 3 回コピー|
|geo ゾーン冗長ストレージ (GZRS)|3 箇所の Azure 可用性ゾーン[^1]間でデータを同期的にコピー|プライマリリージョンから非同期的にコピー後、LRSで 3 回コピー|

[^1]:各可用性ゾーンは、独立した電源、冷却装置、ネットワークを備えた独立した物理的な場所。

イメージにすると下記のように、LRS -> ZRS -> GRS/GZRS となるにつれコピーされる場所が広くなっています。LRS/ZRSではコピーは3回、GRS/GZRSでは6回となります。

![スクリーンショット_20230112_082309.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/988bd522-62b6-c54c-ee21-11a666dbe631.png)

ZRSを使うと、データセンターの障害などで1ゾーンが使えなくなっても、データにアクセス可能です（厳密にはアクセス先変更に伴うネットワーク更新前だと使えない可能性があるようです）。
GRS/GZRSを使うと、リージョン規模の障害が起きてもデータにアクセス可能となりますが、そのためにはフェールオーバーという手順が必要になります。
ただし、セカンダリリージョンへのコピーは、上記の通り、非同期で欠落している可能性がありますので、フェールオーバーしてこちらに書き込むと、データが失われるかもしれません。
別の冗長性オプションとして、読み取りアクセスgeo冗長ストレージ (RA-GRS) 、読み取りアクセスgeoゾーン冗長ストレージ (RA-GZRS) というものもあります。これらはフェールオーバーすることなく、セカンダリリージョンからの読み取りが可能です。
冗長性オプションをどれにするべきかは、一般的にはコストと可用性を考慮して決めるものと思います。リージョンによっては使えない冗長性オプションがある点にも注意が必要です。
ちなみに、Azure価格表で、東日本のGRSとRA-GRSを比較するとRA-GRSの方がコストがかかるようです。読み取りしかできない、と解釈してしまうとRA-GRSの方が割安な気がしてしまいますが、フェールオーバーなしで読み取りできるもの、と考えるとコストがかかるのも納得、でしょうか...？

## ストレージアカウントの種類と冗長性オプション

本題となりますが、ストレージアカウントの種類によって、利用できる冗長性オプションが異なります。

|ストレージアカウントの種類|LRS|ZRS|GRS/RA-GRS|GZRS/RA-GZRS|
|:----|:----|:----|:----|:----|
|Standard 汎用 v2|〇|〇|〇|〇|
|Premium ブロック BLOB|〇|〇|×|×|
|Premium ファイル共有|〇|〇|×|×|
|Premium ページ BLOB|〇|×|×|×|
|Standard 汎用 v1|〇|×|〇|×|
|レガシ BLOB|〇|×|〇|×|

GZRSはZRSとGRSのAND条件になりますね。

ちなみにAzureポータルでストレージアカウントを作成する際、何故かPremiumページBLOBでもZRSが選択できてしまったので、そのまま作成してみたところ、デプロイに失敗する結果となりました。
Looker Studio（旧Google Data Portal）で数値データを日付にする

年度のセルに`2021`みたいな書き方をされていることがある。
まあうん、年度、そうだよね……。とフィールドを作成しようとするたび忘れちゃうのでメモです。

```java
PARSE_DATE("%Y", CAST(フィールド AS TEXT))
```

キャストしないと動かない！
なお月や日を省略すると1がセットされて作成されるので、`"%Y"`が`2021`であれば`2021-01-01`の日付データとして作成されます。

[テキストと数値を「日付」および「日時」に変換する](https://support.google.com/looker-studio/answer/10309432?hl=JA)
CloudFrontの地理的制限とカスタムエラーページを検証する

# 地理的制限とは

CloudFrontの地理的制限を利用することで、所定の地域からのIPアドレスを許可したりブロックしたりすることができます。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudfront-geo-restriction/

例えばこのようにアメリカのみに制限してみます。

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/3c168362-7a3b-75d4-f804-d213b06e498c.png)

すると、日本のプロバイダを通してインターネットへアクセスしている私からは、このCloudFrontディストリビューションで配信しているサイトにアクセスできず403エラーが返ります。

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/5325837f-6a3c-62f6-65f6-1166610126a6.png)

ですが、バージニア北部（us-east-1）リージョンでCloudShellを起動してcurlしてみるとコンテンツが返却されます。

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/09a05150-9278-adb8-aba8-d70fbfcef1e6.png)

とまあこのようにIPの属する地域に応じてアクセス制限をかけることができます。
もちろんプロキシサーバー等を使えば本当のアクセス元のユーザー所在地は偽装できてしまいますが。

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

ただし、リージョンごとにばらつきもあるそうで、全体的な正確性は「**99.8%**」とのことですので完全に制御できるわけではないことは留意が必要です。

# エラーページのカスタマイズ

https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/GeneratingCustomErrorResponses.html

デフォルトの403ページだと色気がないのでカスタマイズしてみます。
これは地理的制限を関係なくCloudFrontの機能です。

```html:403.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>403</title>
</head>
<body>
<h1>アクセスが制限されています</h1>
</body>
</html>
```

上記のHTMLファイルをオリジンにおいて、カスタムエラーレスポンスを設定します。

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/d52e0d98-d939-fb91-3332-50b1c07475a3.png)

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/d201f77d-4c5c-0248-49e9-083686a4d023.png)

先ほどと同じようにアクセスするとHTMLファイルの内容が表示されるようになりました。

注意点としてエラーページは単一のファイルしか返せないので、

```html:403.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>403_plus_image</title>
</head>
<body>
<h1>アクセスが制限されています</h1>
<img src="computer_sagi_error.png"alt="画像です" />
</body>
</html>
```

こんな感じで例えば同一ドメインにある画像を埋め込もうとしても、そのリクエストは403で返ってしまうのでうまく行きません。

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/026861a4-bebc-f8c7-00ab-796fedd5f95f.png)

エラーページにCSSや画像を入れたい場合は、外部のサイトから読み込むか、syleタグやsvgを使ってHTML内に文字列情報として埋め込む必要がありますね。
WindowsのタスクスケジューラがイベントID153で失敗する時のリトライ設定

# 概要

タスクスケジューラの実行履歴で下記のように失敗している時。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/d02c99b6-2330-9c5e-d39c-de9ead26787f.png)

# やり方

下記ようにする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f09c1449-68f8-7d0e-6837-2f9e597fdca9.png)

# 蛇足

:::note warn
下記設定に効果があるかどうかは未検証です。
（あくまで個人メモ）
:::

そもそもイベントID153で失敗しないように、下記のような設定を試した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/9201f26b-a9d4-cf98-95d1-4034a9d68335.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/0e8b4eae-fbcf-3956-4bfe-90f21621c152.png)

 ↓ もしかしたらスリープ設定が原因かも。

https://qiita.com/waokitsune/items/07c8b4876e84cbc1c56e

# 参考サイトさん

http://yuruse.tou3.com/windows/-%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%B9%E3%82%B1%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%A9-%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%B9%E3%82%B1%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%A9%E3%81%AF%E3%82%B9%E3%82%B1%E3%82%B8%E3%83%A5%E3%83%BC

# バージョン

Windows 10 Pro 21H2 OSビルド 19045.2364
【要注意】ハッカー向けたまごっち「Flipper Zero」のフィッシングサイト

# １．はじめに
ポータブルなペンテストツールとしてオンラインストアで200ドルに販売されている **[Flipper Zero](https://flipperzero.one/)** は、最近ペネトレーションテスターとハッカーの間では品切れの人気商品です。まるでたまごっちのような見た目をしているため、「ハッカー向けたまごっち」と呼ばれるこのツールは各種セキュリティコミュニティ、TikTok、Twitter、Telegramなどにレビューされてから人気が高まり、オンラインストアはほぼ毎日売れ切りの状態です。その隙を狙うフィッシング攻撃者が **[Flipper Zeroのフィッシング サイトを公式販売サイトのように見せかけ、ビットコインなどの仮想通貨を払うようにするというニュース](https://www.bleepingcomputer.com/news/security/ongoing-flipper-zero-phishing-attacks-target-infosec-community/)** が最近Bleeping Computerの記事で報道されました。むろん、購入者はFlipper Zeroをもらえません。一般人でもなく、なんとハッカーとペネトレーションテスター、セキュリティ研究員を対象としたこのフィッシング詐欺は、売れ切る前に買っておきたい被害者の心理を利用します。

# ２．Flipper Zero - 公式 vs フィッシングサイト
URLとファビコンまで巧妙に公式ストアと同じく作っておいたフィッシングサイトは肉眼では見分けることは難しいです。Twitter、Telegramなどで知られているFlipper Zeroの詐欺販売サイトにアクセスし、確認してみました。
![official.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003594/825f2a58-e905-1f4c-6df6-870f3e230ac0.png)
左側が本物のFlipper Zeroのオンラインストアの販売ページで、右側は偽物だと知られている Flipper Zeroのフィッシング サイトの販売ページです。公式ストアをよく使う購入者はサイトがおかしいと直ちに気づけるだろうが、そうではない人はフィッシングサイトを気付くことは難しそうです。

# ３．偽Flipper Zero販売サイトを見分ける方法
Flipper Zeroのフィッシング サイトと公式販売サイトを綿密に調べるとURL、ロゴ、ページUIなどの違うところを確認することができますが、それよりもっと正確で早く確認する方法は、**OSINT検索ツール**を用いることです。

Criminal IPのドメイン検索でTwitter、コミュニティなどにフィッシングだと知られていないFlipper Zeroのフィッシングサイト2つを検索してみました。
> _**flipperzerovendoronline[.]com の検索結果**_ ▶ **<https://www.criminalip.io/ja/domain/report?scan_id=2878623>**

![Flipper Zero1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003594/3cdc299b-78a2-feba-66b6-d42add931195.png)
> _**flipperzeroinstock[.]net の検索結果**_ ▶ **<https://www.criminalip.io/ja/domain/report?scan_id=2880403>**　

![Flipper Zero2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003594/758bb14f-0300-a6cc-b68c-87b8853a2e5c.png)

フィッシングサイトのURLを検索した結果、悪性ドメインとして判断され、フィッシングのアルゴリズムは50%以上で判断されました。

特に、検知された項目の中で「新規ドメイン」情報を見ると、この投稿を作成している時点でわずか１ヶ月半前に生成されたドメインに見えます。 Flipper Zeroのフィッシング サイトが今までも生じ続けることから、攻撃と被害が続くことを予想できます。

フィッシングを検知する方法の中には利用者の通報、Google検索、フィッシング・チェックサイトを使う方法もありますが、このような方法は既に知られているフィッシングサイトだけ見分けすることができます。生成されたばかりのフィッシングサイトは、実際の被害者が多数発生する前には検知しにくいです。

![Flipper Zero3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003594/ea4590dd-e1f8-8496-e525-3025e72ed0bc.png)
また他の Flipper Zeroフィッシングサイト のドメイン検索スキャンの結果を見ると、リアルタイムのサイトスクリーンショット、使用された技術および繋がったIPアドレスの悪性可否を確認できます。

# ４．おわりに
Flipper Zeroフィッシング 攻撃の対象はハッカー、ペネトレーションテスターにとどまりません。動画プラットフォームのTikTokでは今も多くのレビュアーがFlipper Zeroを使って興味深そうに見えるハッキングコンテンツを掲げて数千～数百万の再生数を得ています。

情報セキュリティのコミュニティでない一般的なプラットフォームを通じて拡散されているほど、偽販売サイトの点検方法を確認し、被害を予防する必要があります。

また、このような被害が続くのは、セキュリティ関係の人以外の一般インターネットユーザーにもOSINT検索エンジンを活用したフィッシング予防法が必要な理由の一つとも言えます。
MaterialUIで色の型補完が効くようにする（無理やり）

# 解決できること
<font color="red"><b>色指定する時に「primary.main」「error.main」などのカラーテーマが出てこない</b></font>のを改善します。

# 具体的にこういう場面
<b>colorプロパティにprimary.mainを使いたいが…</b>
↓ そもそもprimaryが出てきていない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311883/d0b86998-4591-1dac-c4db-68eeb840e792.png)


# 解決策
### createThemeの後にpaletteをエクスポートする。
theme.paletteにはパレットで設定したカラーが入っています。

```diff_typescript 
// App.ts

import { createTheme, ThemeProvider } from "@mui/material";
import React from "react";
import { RouterProvider } from "react-router-dom";
import { router } from "./routers/router";

export const theme = createTheme({
    //　カスタムする場合、ここでパレットの色を設定
    palette: {
        primary: {
            main: "#EF6E6E",
        },
    }
});

    // themeのpaletteオブジェクトをエクスポート 
+ export const palette = theme.palette;

export const App: React.FC = () => {
    return (
        <ThemeProvider theme={theme}>
            <RouterProvider router={router} />
        </ThemeProvider>
    );
};
```

色を指定する時はpaletteをインポートして使っていく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311883/1af4dfcf-c034-76f9-6203-0f890666f653.png)
primary以外の色もpaletteから指定できるので多少は便利になった。

# 結論
MUIで色指定に型補完を付ける記事が見当たらなかったので、オレオレ実装してみました。<b>(ChakraUIの型補完の記事はたくさんありました）</b>

このやり方で問題ないのか、保守性は良いのか、そこら辺はワカランです。
そもそも他の書き方があるのかもしれません。

::: note
他のやり方があればコメントで教えて頂ければ幸いです。
:::
KMSポリシー作成時の注意点

## CloudFormationでKMSポリシーを作成する際の注意点

①principalには別アカウントのIAMユーザーやロールを指定することは出来ない。つまりKMSを作成するアカウント内にあるIAMユーザーやロールだけ指定できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/0849aeed-5c50-d7ec-dddb-2e21406149e9.png)
コンソール上だと別アカウントのロールやユーザーは選択できないが、
CFnでは別アカウントのユーザーやロールを記載することは可能だが、
エラーになります。
空間ベクトル「20年大阪工大公募推薦1(2)」をsympyとFreeCADでやってみた。

...垂直になるのは、...平行になるのは、...

オリジナル

http://kamelink.com/blog/2023/01/05/6-4-20-osakakodai-kobosuisen-1-2/

上と同じです。大学入試数学問題集成＞
未登録
大阪府

https://mathexamtest.web.fc2.com/daigakubetumj/index.html#osaka

# sympyで(オリジナルのやり方)
勉強中

# sympyとFreeCADのマクロで
![png3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/766a6a8c-8ad8-835d-3c96-3fc5f1fdc6a8.png)
FreeCADのマクロからsympyを使っています。
OA1⊥OB1,OA2//OB2
ワイヤーフレームです。
```python
import FreeCAD
import Part
import DraftTools
import Draft
import Mesh
############################################################################
# 計算
from sympy import *
t,k,t1,k2,t2 = symbols("t,k,t1,k2,t2",real=True)
O,A,B=map(Point,([0,0,0],[1,2*t,-5],[t,t**2+1,2*t**2+3]))
#
t1=solve((A-O).dot(B-O),t)[0]
mySubs1={t:t1}
print("#",t1)
ans=solve([A.x-k*B.x,A.y-k*B.y,A.z-k*B.z],[k,t])
k2=ans[0][0]
t2=ans[0][1]
mySubs2={k:k2,t:t2}
print("#",t2)
######################################################################
A1=A.subs(mySubs1)
B1=B.subs(mySubs1)
A2=A.subs(mySubs2)
B2=B.subs(mySubs2)
######################################################################
# 3D作図
def myXYZ2Txt(A):
    return '(' + str(A.x) + ',' + str(A.y) + ',' + str(A.z) + ')'
def myTxtXYZ(A,myWedgei):
    P5x=float(A.x)
    P5y=float(A.y)
    P5z=float(A.z)
    p5 = FreeCAD.Vector(P5x, P5y, P5z)
    myText = Draft.makeText(myWedgei, p5)
    myText.Label = myWedgei
    # FreeCADGui.ActiveDocument.ActiveObject.FontSize = '0.2 mm'
    FreeCADGui.ActiveDocument.ActiveObject.FontSize = '4.0 mm'
    return
def myTxtXYZ_S(*xy_tx):
    for i in range(1,int(len(xy_tx)/2)+1):
        myTxtXYZ(xy_tx[2*i-2],xy_tx[2*i-1]+myXYZ2Txt(xy_tx[2*i-2]) )
    return
def myLine(A,B):
    Ax,Ay,Az=float(A.x),float(A.y),float(A.z)
    Bx,By,Bz=float(B.x),float(B.y),float(B.z)
    pl = FreeCAD.Placement()
    pl.Rotation.Q = (0.4247081540122249, 0.17592004639554645, 0.33985110062924484, 0.8204732460821097)
    pl.Base = FreeCAD.Vector(-3.9166066876399563, -2.1670824762243774, 1.7495260956243028)
    points = [FreeCAD.Vector(Ax,Ay,Az), FreeCAD.Vector(Bx,By,Bz)]
    line = Draft.make_wire(points, placement=pl, closed=False, face=True, support=None)
    Draft.autogroup(line)
    return
def myLine_S(*args):
    for i in range(1,len(args)):
        myLine(args[i-1],args[i])
    return
myTxtXYZ_S(O,"O",A1,"A1",B1,"B1",A2,"A2",B2,"B2")
myLine(O,A1)
myLine(O,B1)
myLine(O,A2)
myLine(O,B2)
#
doc = App.activeDocument()
App.ActiveDocument.addObject("App::Origin", "Origin")
App.ActiveDocument.getObject('Origin').Visibility = True
App.ActiveDocument.recompute()
Gui.activeDocument().activeView().viewAxonometric()
Gui.SendMsgToActiveView("ViewFit")
# 5
# -1
```
sigfoxをESP32で使ってみる②(sigfoxクラウド~AWSIoTCoreとの連携)

# はじめに
前回はモジュールを接続して、sigfoxクラウドにメッセージ送信まで確認できました。
今回はもう少し踏み込んで、AWSのIoTCoreと連携させDynamodbやTimeStreamなどのDBに情報を書き込むまでをゴールにしたいと思います。

前回その①

https://qiita.com/taiyyytai/items/4b83aba34c1626a6f2b5


# AWSIoTCoreの設定
先にエンドポイント側を設定しておく必要があります。
IoTCoreでデバイスを登録してトピック名まで設定してください。

詳細は私の過去記事を参照ください。

https://qiita.com/taiyyytai/items/b7bbc16efe8eba0dac78

:::note info
MQTTによる通信確認であればルール設定までは不要です。
IoTCoreのMQTTモニタリングで通信確認可能です。
:::


# Sigfoxクラウド側での設定
## 位置情報オプションの確認
**DeviceType→information**内にある**Options**を確認します。
```Sigfox geolocation service```が```Network location``` であることを確認します。
![](https://i.imgur.com/xlKDg4k.png)

## Callbackの設定
**DeviceType→CallBacks**にでAWS IoTを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/e24515b5-79dd-7646-7b96-b9ea21895076.png)

設定画面が表示されるので、下記手順の通り設定を行います
①```ExternalId```をコピーして```Lanch Stack```をクリックしてAWSへ遷移
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/e24515b5-79dd-7646-7b96-b9ea21895076.png)
②AWSのCloudformationでは特に編集せずにそのまま進める
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/cc2d6e4b-37d6-d9c4-3602-e9ab3a63464c.png)
③```ARNRole```が表示されるのでコピーして、sigfoxクラウドへコピーする
④```Topic```にトピック名を入力します。

::: note info
ワイルドカードを使ってデバイスＩＤなどを埋め込むことができます。
**トピック名の例**
AWSIoTCore：ESP32/+/pub
Sigfoxクラウド:ESP32/{device}/pub
:::

⑤```Json Body```に下記Jsonを入力する。（ここはお好みで編集してください）

```json
{
  "device":"{device}",
  "time":{time},
  "data":"{data}",
  "seqNumber":"{seqNumber}",
  "lqi":"{lqi}",
  "fixedLat":"{fixedLat}",
  "fixedLng":"{fixedLng}",
  "operatorName":"{operatorName}",
  "countryCode":"{countryCode}",
  "deviceTypeId":"{deviceTypeId}",
  "computedLocation":{computedLocation}
 }
```

### センサーからのデータを挿入したい場合
**Sigfox Payload configuration（Payload display）機能**で実装することができます
その際はエッジ側でセンサデータ16進数に変換する必要があります。

詳細は下記をご覧ください。

https://www.kccs.co.jp/sigfox/blog/technical/2018/0205-02/

### Callback作成時にエラーがでる場合
下記のようなエラーがでた場合の対処です。
```Your entered information doesn''t allow us to retrieve the endpoint from AWS. Please try to configure again your information through the button ''Launch Stack'' or change the method of configuration.```

このエラーはCloudformationで作成したロールにIoTCoreの権限がないときにでるエラーです。
IAMロールに各権限(AWSIoTFullAccessなど)をアタッチして再トライすることで解決することができます。
**IAM→Roles→作成されたロール**
![](https://i.imgur.com/addpu2c.png)

## メッセージを送信してCallbackを確認する
ATコマンドよりメッセージを送信してみます。

```Name:example
AT$SF=1234567890
```

再度メッセージを確認するとCallbackがあることが確認できます。内容を確認すると緯度経度情報なども確認できると思います。
AWS側もIoTcoreのMQTTモニタリングやルール設定した各DBへ通信が上手くいっているか確認してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/adc8b561-a184-9377-5162-fe86e1d3d462.png)
Chromeのタブが移動できない、VScodeでドラッグで範囲選択できない、Shift＋一部のキーが反応しないトラブルの解決法

## 起こったこと
キーボードとマウス周りで、次のような不調が同時に発生しました。

- ブラウザのタブをドラッグして別ウィンドウに移動させられなくなった
- VScode上で、コードをドラッグして範囲選択できなくなった（他のテキストアプリでは特に問題なし）
- Shift + 一部のキーが反応しなくなった（キーボード右側のPからアンダーバーあたり。Shiftとの同時押しが反応しないだけで、それぞれのキー自体は反応する）
## 解決法
キーボードをひっくり返して裏からパンパン叩きました。
すきまからゴミが出てきて、元通り使えるようになりました。
ドラッグができないトラブルもなぜか一緒に解決しました。

詳しい理屈はまったくわからないのですが、とにもかくにもこれで解決しました。
再起動とか設定変更とかドライバのアンインストールなど試してみたのですが、なんともすっとこどっこいなオチでした。
もしなぜキーボードのごみ（あるいは接触不良？）で同時押しが反応しなくなったのか、マウスまでおかしな挙動になったのかわかる方がいたらコメント等で教えていただけたら嬉しいです。
Consumer interfaceを使用してconstructorの引数追加の影響を減らす

constructor使わずbuilderでinstance生成する
builderにItemと同じフィールドを持たせる
builderに値設定するロジックをconsumerとして引き渡す
builder内部でconsumer実行
builder内容でItemを生成するコンストラクタ実行

```java
class Item {
    private int price;
    private String name;
    public Item() {}
    private Item(Builder build) {
        this.price = build.price;
        this.name = build.name;
    }
    public String toString() {
        return "name:" + name + " price:" + price;
    }
    
    static class Builder {
        int price;
        String name;
        
        Builder method(Consumer<Builder> c) {
            c.accept(this);
            return this;
        }
        Item build() {
            return new Item(this);
        }
    }
}
public class Outer {
    public static void main(String[] args) {
        Item i = new Item.Builder().method(b -> {b.name = "suzuki"; b.price = 90;}).build();
        System.out.println(i);
    }
}
```
```
name:suzuki price:90
```
さくらサーバー内のサイト移転

今回さくらのレンタルサーバーの中でプランが違うサーバーに、運用中のWordPressのサイトを移転する際に、色々苦労したので備忘録を兼ねて記録します。

##出来るだけサーバーダウンの時間を無くしたい
実際に運用されているサーバーなので、出来るだけサイトにアクセス出来ない状態を短くしたいと思い、色々と方法を模索していました。

自分のパソコンのホストのファイルを書き換えて、ネームサーバーを書き換える前に強制的にサーバーにアクセスして、テストする方法を試しました。

https://site-hikkoshi.com/1803/

この方法は、ネームサーバーが変更されていなくても、サーバーの中でドメインが紐ついている必要があると分かりました。

さくらのレンタルサーバーは、プランが違うサーバー移転の場合、ネームサーバーに入力するIPアドレスが、同じなのです。
そのため、ドメイン管理している会社のネームサーバーを書き換えなくても良いので楽です。

でも、サーバーにドメインを設定するときに、以降元のサーバーからひっこすドメインを削除していないと、新しいサーバーに設定できないのです。

そのため自分のパソコンだけ強制的にドメインに接続する方法を試そうとしても、サーバーにドメインが設定されていないので使えないです。

実際、何度試しても、４０４エラーとなりアクセス出来ませんでした。

それで方法がないか色々検索していたら、さくらのレンタルサーバーの無料の機能で、バックアップ＆ステージング機能があることを知りました。

https://knowledge.sakura.ad.jp/14143/

このバックアップ＆ステージング機能は、サイトのバックアップだけでなく、テスト環境を作ったり、他社サーバーからWordPressをさくらのレンタルサーバーに移転する際にも活用できる便利なものです。

## 注意点
バックアップ＆ステージング機能は、稼働しているWordPressは、設定できます。
でも、移転したばかりで稼働するかテストしたい場合は、スナップショットを撮ることができないのです。
そのためディレクトリで、指定しました。

### ディレクトリでは、ステージングサーバーを使えない
HTMLまたは、WordPressを選んだときに、ステージングサーバーを利用できます。

### SSH接続のアカウントを確認
SSH接続するためのユーザー名とパスワードは、サーバーのユーザー名とパスワードで使えます。

## 引っ越し元のさくらサーバーを指定
最初に選択されている移転先のサーバーではなく、移転元のサーバーを追加します。

## 動いているWordPressを指定
引っ越すWordPressのスナップショットを撮ります。

## 気をつけるプラグイン
301リダイレクトをするプラグイン「Redirection」がインストールされていると、テスト環境を作っても、転送エラーとなります。
このプラグインを無効にしてから、スナップショットを撮りましょう。
エラー：bundler: command not found: unicorn_rails Install missing gem executables with `bundle install`

## はじめに
プログラミング初心者による備忘録です。

AWSでデプロイするために`unicorn`でrailsを起動させようとした所、エラーが発生。

## エラー内容
```
[ec2-user@ip-000-00-00-00 hoge]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D
bundler: command not found: unicorn_rails
Install missing gem executables with `bundle install`
```

## 試したこと
下記のサイト様の症状と同じなので解決方法を試す。
参考サイト　https://teratail.com/questions/315531

❶rbenvをrehash
❷bundlerの入れ忘れ
❸GitHubへの反映（push,bundle install）

しかし、解決できず。

## 解決方法
```
% cat .bundle/config
```
でconfigファイルの設定を確認すると
```
BUNDLE_WITHOUT: "production"
```
productionグループで設定しているgemがインストールされていなかったみたいです。

そこで
```
bundle install --with production
```
で`prodection`をしっかり読み込むように。

これで正常にrailsサーバーが立ち上がりました！
DDBJからsraをダウンロードするためのURLを列挙する

## はじめに

SRAをダウンロードする際には、[fasterq-dump](https://github.com/ncbi/sra-tools)などのツールがありますが、日本国内から利用する場合は、国内のDDBJのサーバーを利用することで、通信速度が速く、便利なことが多いです。しかし、ブラウザからダウンロードするためのURLを一つ一つ取得するのは手間がかかり面倒です。そこで、DDBJからSRAをダウンロードするためのURLをリストアップするスクリプトを書きました。

意外と需要のあるかもしれないのと、（あとでやり方を忘れてしまう可能性があるため）Qiita記事にしました。

## Requirements

スピナーを表示するために、tty-spinnerをインストールしておく必要があります。

```
gem install tty-spinner
```

## スクリプト

下記のスクリプトをパスの通っている場所に保存し実行権限をつけておきます。 `sudo chmod +x ./ddbj_sra_urls.rb` 

```ruby:ddbj_sra_urls.rb
#! /usr/bin/env ruby
# DDBJ SRA URL Getter
# author: kojix2

require 'net/http'
require 'json'
require 'optparse'
require 'tty-spinner'

urls = []
ftp = false

# ftpオプション
OptionParser.new do |op|
  op.banner = "Usage: #{__FILE__} [options] <BioProject>"
  op.on("--ftp", "FTPのURLを表示する"){ ftp = true }
end.parse!(ARGV)

# プロジェクトIDを取得する
project_id = ARGV[0]
if project_id.nil?
  warn 'エラー：BioprojectのAccessionが必要です。'
  exit 1
end

# URLからJSONデータを取得する
def json_url(uri)
  uri = URI.parse(uri)
  dat = Net::HTTP.get(uri)
  JSON.parse(dat)
end

# プロジェクト情報を取得
bioproject = json_url("https://ddbj.nig.ac.jp/resource/bioproject/#{project_id}.json")

# Loading中にスピナーを表示する
spinner = TTY::Spinner.new('[:spinner] Loading ...', format: :pulse_2)
spinner.auto_spin

if bioproject['dbXrefs'].nil?
  warn "エラー：データを取得できませんでした。"
  exit 1
end

# sra-run タイプのURLを取得し、URLの配列に格納
bioproject['dbXrefs'].each do |i|
  next if i['type'] != 'sra-run'

  sra_run = json_url(i['url'] + '.json')
  sra_run['downloadUrl'].each do |u|
    next if u['type'] != 'sra'

    # https か ftp か
    urls << (ftp ? u['ftpUrl'] : u['url'])
  end
end

# Loadingスピナーを停止し、完了を知らせる
spinner.stop('Done!')

# 取得したURLを表示
puts urls
```

## 使い方 

```
Usage: ./ddbj_sra_urls.rb [options] <BioProject>
        --ftp                        FTPのURLを表示する
```

私は動物のタヌキがすきです。そこでタヌキのプロジェクトがないか探してみました。
[PRJNA341783](https://www.ncbi.nlm.nih.gov/bioproject/341783)は中国のタヌキの皮膚のトランスクリプトームのデータです。（日本のタヌキのデータを探したかったけど見つかりませんでした）

ここでは例として、引数に `PRJNA341783` を指定して、タヌキのトランスクリプトームのデータをDDBJから取得するためのURLを取得します。

```
ddbj_sra_urls.rb PRJNA341783 > tanuki.txt 
```

ダウンロード用のURLが tanuki.txt に保存されます。

```
https://ddbj.nig.ac.jp/public/ddbj_database/dra/sralite/ByExp/litesra/SRX/SRX213/SRX2134150/SRR4158183/SRR4158183.sra
https://ddbj.nig.ac.jp/public/ddbj_database/dra/sralite/ByExp/litesra/SRX/SRX213/SRX2134151/SRR4158184/SRR4158184.sra
https://ddbj.nig.ac.jp/public/ddbj_database/dra/sralite/ByExp/litesra/SRX/SRX213/SRX2134152/SRR4158185/SRR4158185.sra
https://ddbj.nig.ac.jp/public/ddbj_database/dra/sralite/ByExp/litesra/SRX/SRX213/SRX2134153/SRR4158186/SRR4158186.sra
https://ddbj.nig.ac.jp/public/ddbj_database/dra/sralite/ByExp/litesra/SRX/SRX213/SRX2134154/SRR4158187/SRR4158187.sra
https://ddbj.nig.ac.jp/public/ddbj_database/dra/sralite/ByExp/litesra/SRX/SRX213/SRX2134155/SRR4158188/SRR4158188.sra
```

得られたURLのリスト利用すれば、手元のNASなどに簡単にデータをダウンロードすることができます。

この記事は以上です。
MySQLで小数点を挿入できるフィールドdecimal

金額を管理するデータベースでintを使って値を扱っていましたが、
小数点の単価を入れたいと言われたので、利用したdecimal型についてメモ。

```
decimalは、桁数を(M,D)の形で指定。内訳は以下の通り。

M…扱う少数の最大桁数
D…小数点以下の桁数
```

decimal(6.3)だと全桁数が6桁、小数点3桁の範囲の桁数であれば挿入可能。
Databricksの課金データをクイックに集計する

こちらの延長です。

https://qiita.com/taka_yayoi/items/182327e06f09acaf803e

アカウントコンソールで参照できるデータはクイックに現状を確認するには向いていますが、月毎の合計を集計したいという場合には一手間が必要です。[使用量ログのデリバリー](https://qiita.com/taka_yayoi/items/90c7767025ee3feb3640)を設定し、集計処理をジョブ化するなどして全てを自動化することもできますが、ここではクイックにExcelを使って集計する方法を説明します。

# ログデータのダウンロード

1. [アカウントコンソール](https://accounts.cloud.databricks.com/)にログインし、使用量アイコンをクリックします。
1. **合計使用量**が選択されている状態で、**時間範囲を選択**で集計したい月の初日から最終日までを選択します。以下の例では2022/5/1から2022/12/31までを選択し、2022年5月から2022年12月までを対象としています。
![スクリーンショット 2023-01-12 15.35.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/93757883-79e6-9961-8c38-42adbfb40e9b.png)
1. **適用**をクリックしてグラフを更新します。
![スクリーンショット 2023-01-12 15.37.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/2bb57ac1-fb04-f60f-f394-f4a7cf822df3.png)
1. グラフが更新されたら、グラフ右上にあるダウンロードボタンをクリックして、CSVファイルをダウンロードします。
![スクリーンショット 2023-01-12 15.37.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/c1199f95-daec-de50-8d85-409fce93cffe.png)

# CSVデータの集計

1. このCSVデータは日毎のDBU、費用のデータとなっています。これを月別に集計します。
![スクリーンショット 2023-01-12 15.42.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/5efc031d-9b7c-36b8-9bd3-62ce7cd69e6f.png)

1. 集計用のExcelファイルはこちらに置いてあります。

    https://sajpstorage.blob.core.windows.net/yayoi/Databricks月額使用料集計_20230117_v0.xlsx

1. Excelファイルをダウンロードし開きます。このシートのA列からC列にCSVファイルのデータを貼り付けます。
![スクリーンショット 2023-01-12 15.41.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/2d5a981e-34bc-a744-be34-363373780998.png)
![スクリーンショット 2023-01-12 15.43.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/76b33888-7ad3-253c-910c-07d6afbc2281.png)
1. I列にあるピボットテーブルにカーソルを移動します。
![スクリーンショット 2023-01-12 15.43.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/00df9942-d31f-9464-d698-1440e8aeef1b.png)
1. メニューの**ピボットテーブル分析**を開き、**更新**をクリックします。
![スクリーンショット 2023-01-12 15.44.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/7fab8fab-dc5e-78a8-e8e0-d290958e3ef6.png)
1. ピボットテーブルに月毎の合計金額が表示されます。
![スクリーンショット 2023-01-12 15.44.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/78df9b9e-d20c-8dc2-c1e3-4ef367118f75.png)
1. L2セルに契約金額($)を入力すると、L5セルに残額が表示されます。
![スクリーンショット 2023-01-17 12.27.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/48feca10-e168-1e21-21d3-f71e708bf039.png)



### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
【FileMaker】計算式に使用したフィールドが空欄だった時の計算結果について

# 記事の概要
タイトル通りです．
FileMakerで開発をしていて，変数の設定や計算フィールドなど，何かと計算式を定義する場面が多くあると思います．そしてその計算式にフィールドを直接使用することも多々あると思います．
今回，計算フィールドの計算式に使用したフィールドが空欄だった場合の計算結果を検証してみたため，記事に残してみます．

# ケース：計算フィールドの計算式にフィールドを使用した場合
以下のようなテーブル，フィールドを用意しました．

* テーブル名
test

* フィールド名（フィールドタイプ）（計算式）
F_1（数字）
F_2（数字）
calc_multi（計算）（ = F_1 * F_2）
calc_add（計算）  （ = F_1 + F_2）

このとき，二つのフィールドF_1，F_2の中身と対応する計算結果は下記の通り．

①二つとも空欄の時
![空欄空欄.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393766/c057ddcc-6623-584c-c968-f214050b2f5f.png)
この時は計算フィールドも空欄になるみたいです．


②片方が空欄の時
![片方空欄.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393766/13012571-437a-35d7-34dc-091b67357304.png)
この時は，空欄のフィールドを0として扱い，計算結果が返るみたいです．

（おまけ）両方とも値が入っている時
![空欄なし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393766/6a9ae93b-0ace-2bbc-a1b6-2db77109885c.png)
両方とも値が入っているため，普通に計算結果が返ってきます．


# 終わりに
「空欄の場合は常に0扱い！」というわけではないようですね．場合によるみたいです．
ただ，「計算結果は場合による」みたいな状態にしておくとシステムに不具合が発生した時に原因を掴みづらいので，計算式に使うフィールドにはデフォルト値（０など）を設定しておくのが吉なんでしょうかね．
今回はかなり狭い範囲の検証に留まりましたが，本テーマに関する新しい情報を得たら追記しようと思います．
【jquery】timepickerで時刻を選択できない

# はじめに
timepickerライブラリを使用して時刻をプルダウンで選択できるようにしたのですが、
01時~09時が選択できなかったので対応策を簡単にまとめてみました。

# 事象
01時~09時を選択すると以下のように時刻を選択できない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/6e2b7b26-9e9a-473b-48b4-4d1fc9b944ca.png)

エラーメッセージは以下のとおり
```
does not conform to the required format timepicker The format is "HH:mm", "HH:mm:ss" or "HH:mm:ss.SSS" where HH is 00-23, mm is 00-59, ss is 00-59, and SSS is 000-999.
```

# 対応策
timepickerを使わずにtype="time"のみにする

https://developer.mozilla.org/ja/docs/Web/HTML/Element/input/time

# おわりに
type="text"にすればtimepickerを使用しても01時~09時を選択できるのですが、
プルダウンで選択できなくなってしまうことからtype="time"のみにしました。
SQL 備忘録

個人的に忘れがちなSQLの処理をまとめました。
良かったらいいねオナシャス
# DBとは
__データベースとは何か__
大量の情報を効率よくアクセスできるように成形されたデータの集合

__DBMSとは__
データベースをいじくり倒すためのコンピューターシステム
なんかカッコいい

__DBMSの種類__
- 階層型データベース
  - 木構造で表現するDB　今はあんまり使わない  
- リレーショナルデータベース
  - 2次元表形式のDB　エクセルみたいな感じ
  - 操作にSQLを用いる
- オブジェクト指向DB
pandasのデータフレームみたいなもの

- キー・バリュー型DB
辞書型配列みたいなもの
- XML　DB
タグでデータ構造を処理

した3つは理解が浅いのでwiki参照

## SQLの分類
### 1. DDL
DataDefinitionLanguageの略
データベースやテーブルの作成するタイプの命令
(例) 
__CREATE
DROP
ALTER__

### 2. DML
DataManipulationLanguageの略
テーブルの操作を行うタイプの命令
(例)
__SELECT
INSERT
UPDATE
DELETE__

### 3. DCL
DataControlLanguageの略
DBに関する処理の確定と変更や　configの変更などを行うタイプの命令
(例)
__COMMIT
ROLLBACK
GRANT
REVOKE__

## CREATE DATADASE; 関連の話

__命名ルール__
→半角数字のアルファベット、数字、アンダーバーに限る
先頭は必ずアルファベット

__データ型__
- INTEGER型
整数型
- CHAR型
固有文字列
- VARCHAR型
可変長文字列
- DATE型
日付

制約も付けられる　NOT NULL とか

__主キー設定__
CREATE TABLE分の最後に
PRIMARY KEY (カラム名)をつけることでデータを一意にするカラムの設定ができる。

## テーブルの定義操作関連の処理
__列の追加__
```
ALTER TABLE テーブル名　ADD　COLUMN　列名　列の定義　列の制約;

```
列の削除はADDがDROPになる
オンラインゲーム開発に向けて

エンジニアになるために友人とゲーム開発をする計画を立てているが、全くの無知からのスタートである少しの段差でも躓いている。

ゲームと言ったらやはりオンラインでマルチプレイが出来るものを想像する。
友人と計画したゲームはネプリーグであるクイズに対して複数人で１文字ずつ答えるというマルチプレイを想定したものだ。

はじめはUnityでの実装を考えたが、Unityは多機能なゲーム開発が可能な分オンラインゲームを最初に開発しようと言うのは中々に愚かな話だ。

そこで、socket.ioを用いてJavaScriptで開発するという手段を取ることにした。

この手段に至る理由は大きく3つである。

・JavaScriptの学習が容易であるという点。
・我々が作成するゲームがJavaScriptで十分作成可能であるという点。
・socket.ioは比較的日本語の情報があるという点。

友人と私はJavaScriptの学習を済ませたばかりである。また、1から学ぶのはモチベーションにつながらない。
Unityは後々学ぶにしても1回ゲームを作りたいのである。
我々が目指すゲームが複雑な処理が不要であり、JavaScriptで十分可能なのである。

さらに、Unityで作成する場合、
Photon FusionやNetcode for GameObjectのような最新の技術を学ぶことになる。
勉強にはなるが日本語で体系的にまとめられた資料が少ないのはかなり挫折の可能性が高い。

ということで初めてのゲーム制作はJavaScriptをフロントエンド、バックエンドにNode.jsを用いて、socket.ioを通信に使うという形で作成していく。

そして、ブログという形で毎日進捗や学んだことをここに記録していく。
アプリケーションサーバー、プロキシサーバー

# アプリケーションサーバー
Webアプリケーションの中核となる```業務処理を行う```プログラムです。
具体的にはWebサーバーから転送されてきたユーザーからのデータを受け取り、サーバーサイド・プログラムを実行することでそのデータを加工したり、データベースのデータを検索・加工した後、Webサーバーに応答を返します。

### 出典
https://www.sbcr.jp/product/4797388817/

# プロキシサーバーとは？
```クライアントからインターネットに対する通信を代理で行う```サーバーです。
これによってインターネットに対する通信を一元的に管理できるようになり、その通信を効率化できるようにする。

# 用途
Webサイトを一次的に貯めておいて、クライアントに返す「キャッシュ機能」をメイン利用していました。キャッシュ機能は、限りある```インターネット回線帯域を効率化に利用```できるようなるため、回線帯域が細い環境で一定の効果を発揮していました。
しかし、最近は、キャッシュ機能の効果が薄い動的なWebページが多くなり、また、そもそもの回線帯域が太くなったためそれだけの目的でプロキシサーバーを導入することは少なくなりました。

# セキュリティ機能の強化
p98 最近のプロキシサーバーは```URLフィルタリング```や```アンチウイルス```などセキュリティ機能を強化することによって進化を続けています。

### URLフィルタリング
アクセスできるサイトを限定する機能です。
プロキシサーバーは色々なサイトの```URLをカテゴリ別に分類して、データベースとして保持```しています。
それによってアクセスの許可・不許可を判断します。

### アンチウイルス
ウイルス対策の機能です。
ウイルス対策ソフトの定義ファイルのようなものを```シグネチャ```として保持しています。```プロキシサーバーはクライアントがやり取りする```ファイルを一旦内部で展開し、シグネチャと照合```します。

# 出典
https://www.sbcr.jp/product/4797386660/
paizaラーニング レベルアップ問題集 二分探索メニュー JavaScript ある範囲に含まれている整数の個数

ある範囲に含まれている整数の個数 (paizaランク B 相当)

https://paiza.jp/works/mondai/binary_search/binary_search__basic_boss

# 解答例(Python3 の場合参考)
前問までのbinary_search関数は、指定した値が最初に現れる位置を求めるものです。
なので、前問までで学習した lower_bound や upper_bound を用いることができます。
l_i以上の値が最初に現れる位置lpos(l positionの略)を求める→lower_bound
r_iより大きい値が最初に現れる位置rpos(r positionの略)を求める→upper_bound
l_i以上r_i以下に含まれる整数の個数は、rpos-lposで求まります。

(または、r_iが最初に現れる位置をrpos1とすると、答えはrpos1-lpos+1でも求まります)

```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//二分探索の関数定義
const binary_search = (A, n, k) => {//(A : 数列, n : 数列のサイズ, k : 基準)
    // 探索範囲 [left, right]
    let left = 0;
    let right = n;
    
    // 探索範囲を狭めていく
    while (left < right) {
        // 探索範囲の中央
        const mid = Math.floor((left + right) / 2);

        if (A[mid] < k) {
            left = mid+1;
        } else {
            right = mid;
        }    
    }
    // 狭め終わったら最初に現れた位置を返す
    return right;
};

//メイン
const n = Number(lines[0]);
const A = lines[1].split(" ").map(Number).sort((a, b) => a - b);
const q = Number(lines[2]);

//各l,rについて調べる
for (let i = 1; i <= q; i++) {
  const [l, r] = lines[i + 2].split(" ").map(Number);
  const lpos = binary_search(A, n, l);
  const rpos = binary_search(A, n, r + 1);//r+1はrより大きい数
  console.log(rpos - lpos);
}
```
MicroStrategyにおけるリンク設定方法

# はじめに
こんにちは。
本記事ではMicrostrategyにおいてオブジェクトにリンクを埋め込む方法をご紹介します。

# ケース
以下のようなフォルダを作成しました。
こちらのフォルダから特定のリンクに飛べるような設定を想定します。
今回は「Qiita記事はこちら」という文言から過去の投稿記事に移動できるような設定を例にご紹介いたします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737479/b87a8ced-e03b-c35c-4a26-32d1c5994a0e.png)

# 操作方法
①対象のオブジェクトを右クリックし「プロパティ」を押下します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737479/049cdc1c-d8af-6a3d-66f4-65054df21647.png)
②赤枠のような文言を入力し、保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737479/089038f3-0338-8d5a-c1ef-c2f89508901e.png)
③この状態ではリンク化されず文字のままなので、リンクの有効化をします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737479/df13293f-daad-711f-d3d4-abd7258d6510.png)
④WebのAdminページからオブジェクト説明を有効にすると、さきほど実装したリンクが有効になっており、Webページへ移動することを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737479/40b53ae1-bf42-0155-de4b-1ec196b9d9ff.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737479/25c02bef-af75-2ace-dc02-821d12a6d2c6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737479/11ea6f97-c537-f473-07be-c08da3ee9460.png)

# さいごに
こちらは上記ケースのような業務がある場合、有効的な操作です。
こちらの記事が、みなさまの調査・業務のお役にたてれば幸いです。
[Python]左から一文字ずつ別の文字に置き換える

```
------
*-----
**----
***---
****--
*****-
******
```

みたいなのがコンソールで書きたい。

# 結論
`str.ljust()`を使う。
```py
n = int(input())
s = ""

for i in range(n+1):
    print(s.ljust(n, "-"))
    s += "*"
```

```console
6
------
*-----
**----
***---
****--
*****-
******
```

`ljust()`はいわゆる0埋めとかに使われる関数で、「文字列の長さが第一引数に満たなかったら空いてるスペースを第二引数の文字で埋めるで～」というもの。

`rjust()`もあるが、両者の違いは **元の文字列をどちらに寄せるか** という点。
`ljust()`は左、`rjust()`は右。わかりやすいね。
Serverlessのインストール

Serverless Frameworkを使用するにあたってのインストール手順をまとめてみた。

▼前提
Ubuntu20.04

▼参考サイト
https://serverless.co.jp/blog/25/

## １．Node.jsのインストール
Serverless Frameworkを利用するには**Node.js12以上**が必要。
必要に応じてインストールやバージョンアップを行う。
（詳細は省略）

## ２．Serverlessのインストール
以下のコマンドでServerlessをインストールする。
```
$ sudo npm install -g serverless
```

念のためインストールの確認をおこなう。
バージョンが出力されたらOK。
```
$ serverless --version
```

## まとめ
Serverlessのインストールだけでいえば手順はこれだけ。

おわり。
エラー：An error occurred while installing pg (1.4.5), and Bundler cannot continue.

## はじめに
プログラミング初心者による備忘録です。

今回はrenderにデプロイされているアプリをAWSのEC2環境へ移す際にエラーが発生したので、その原因と解決方法です。

## 何をしている時にエラーが出たのか
以下のコマンドでEC2内にローカルと同じバージョンの　`bundler`をインストールしようとしました。
```
[ec2-user@ip-000-00-00-000 hoge]$ gem install bundler -v 2.1.4

[ec2-user@ip-000-00-00-000 hoge]$ bundle install
```
すると以下のエラーが発生。
```
[ec2-user@ip-000-00-00-000 hoge]$ bundle
The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby, x86_64-linux but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
Fetching gem metadata from https://rubygems.org/.........

    中略

Fetching pg 1.4.5
Installing pg 1.4.5 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/pg-1.4.5/ext
/home/ec2-user/.rbenv/versions/2.6.5/bin/ruby -I /home/ec2-user/.rbenv/versions/2.6.5/lib/ruby/2.6.0 -r ./siteconf20230111-21011-1k4naz0.rb extconf.rb
Calling libpq with GVL unlocked
checking for pg_config... no
checking for libpq per pkg-config... no
Using libpq from 
checking for libpq-fe.h... no
Can't find the 'libpq-fe.h header
*****************************************************************************

Unable to find PostgreSQL client library.

Please install libpq or postgresql client package like so:
  sudo apt install libpq-dev
  sudo yum install postgresql-devel
  sudo zypper in postgresql-devel
  sudo pacman -S postgresql-libs

or try again with:
  gem install pg -- --with-pg-config=/path/to/pg_config

or set library paths manually with:
  gem install pg -- --with-pg-include=/path/to/libpq-fe.h/ --with-pg-lib=/path/to/libpq.so/

*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

    中略

An error occurred while installing pg (1.4.5), and Bundler cannot continue.
Make sure that `gem install pg -v '1.4.5' --source 'https://rubygems.org/'` succeeds before bundling.

In Gemfile:
  pg

```


##  解決した方法
①Gemfileで、「gem 'pg'」の記述を完全削除する

②Gemfile.lockを削除、ローカル環境でbundle installをおこなう

③GitHubにコミットとプッシュ

④EC2環境でgit pull origin master

⑤EC2環境でbundle install

これで無事インストールできました。

## 原因
今回、AWSに移行するにあたってDBは「MariaDB」を使うので「postgreSQL」のGemである`pg`があることでエラーが発生していたようです。
## あとがき
よくよく考えれば当たり前のようなことですが、勉強不足でそこまで気がまわっていませんでした。
サーバー周りは特に知識不足なのでよく考えて実装していきたいと思います。