OmniAICreator/Qiita-1.07M huggingface dataset:
Terraform Cloud利用時のmodule参照エラーについて

# はじめに

どうも、@to-fmakです。最近Terraform Cloudを利用している際に発生したモジュール参照エラーについて、事象と対応方法をまとめました。同じような問題に直面した方の参考になれば幸いです。

# 事象

Terraform Cloudをバックエンドとして利用しているTerraformリポジトリがあり、以下のようなディレクトリ構成を採用しています。

```txt
sample-repo
├── modules
│   └── sample-module
└── pj1
    └── main.tf
```

この構成において、新しいモジュール (sample-module) を作成し、pj1ディレクトリ内のmain.tfからそのモジュールを参照する必要がありました。

```hcl:main.tf
module "sample" {
  source  = "../modules/sample-module"

  ...
}
```

上記のように、相対パスを使用してモジュールのsourceを指定しましたが、terraform planを実行した際に以下の参照エラーが発生しました。

```txt
╷
│ Error: Unreadable module directory
│
│ Unable to evaluate directory symlink: lstat ../modules: no such file or
│ directory
╵

╷
│ Error: Failed to read module directory
│
│ Module directory  does not exist or cannot be read.
```

::: note warn
実際の環境では、pj1と同じ階層に複数のディレクトリが存在し、それぞれのディレクトリ内のtfファイルからこのモジュール（sample-module）を参照する必要がありました。
各参照先でTerraformのバージョンが一致していない場合もありますが、今回の事象はTerraformのバージョンには関係ないことが判明しています。
:::

# 原因

この問題の原因は、Terraform Cloud上のデフォルトの作業ディレクトリ設定にあります。
Terraform Cloudでは、デフォルトではリポジトリのルートディレクトリが作業ディレクトリとして設定されています。そのため、pj1ディレクトリ内から相対パスでモジュールを参照しようとすると、Terraform Cloudはリポジトリのルートディレクトリからの相対パスとして解釈し、指定したパスが存在しないと判断してしまいます。

# 相対パス利用時の対応方法

この問題を解決するためには、Terraform Cloud上の該当するワークスペースの設定を変更する必要があります。
具体的には、該当ワークスペースの「Workspace Settings」→「General」→「`Terraform Working Directory`」にて、作業ディレクトリとして作業ディレクトリ（pj1）を指定する必要があります。
この設定を行うことで、main.tf内のmoduleブロックで相対パスを使用してモジュールを正しく参照できるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/f7207ec5-94ab-7e16-e8e2-4665b6ebd7af.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/07c7dae0-e11b-31ae-af07-6d6eed9f3725.png)

# 参考URL

- https://developer.hashicorp.com/terraform/cloud-docs/workspaces/settings

## エンジニア募集

Gakken LEAP では教育をアップデートしていきたいエンジニアを絶賛大募集しています！！
ぜひお気軽にカジュアル面談へお越しください！！

<https://gakken-leap.co.jp/recruit/>
外部クレートのバージョン記述/指定に関して注意すること

# 起きた問題
Rustで開発していたところ、Cargo.tomlで指定していたバージョンと異なるバージョンで依存先クレートがコンパイルされていた。

例えば
```toml
[package]
name = "tmp"
version = "0.1.0"
edition = "2021"

[dependencies]
rand = "0.8.0"
```

と記述していても、実際はrand 0.8.5でコンパイルされている (2024/08/28時点でのrand 0.8最新バージョン)

実際にCargo.lockの記述を見てみると、下記のようになっている。
```Cargo.lock
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
 "libc",
 "rand_chacha",
 "rand_core",
]
```
versionのフィールドを見てみると、"0.8.0"と指定したはずが、"0.8.5"となっている。 

# 詳細と解決方法
## 詳細
dependenciesに記述するversionフィールドは特定のバージョンを指定するものではなく、プログラムが正常に動作するためのバージョンの範囲を指定するもの。なので、"0.8.0"と指定していたとしても、実際は"^0.8.0"となっており、0.8.0かそれ以上の互換性のある最新のバージョンを参照する。

## 解決方法
```Cargo.toml
[dependencies]
rand = "0.8.0"
```

となっているところを、
```Cargo.toml
[dependencies]
rand = "=0.8.0"
```
とすると、正しくバージョン0.8.0を参照するようになる。

実際にCargo.lockでもバージョン0.8.0でコンパイルされたことが示されている。
```Cargo.lock
[[package]]
name = "rand"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a76330fb486679b4ace3670f117bbc9e16204005c4bde9c4bd372f45bed34f12"
dependencies = [
 "libc",
 "rand_chacha",
 "rand_core",
 "rand_hc",
]
```
## 細かいこと
このバージョン指定はセマンティックバージョニングというマニュアルに沿っていて、実際にCargoで行われるバージョン管理はこのマニュアルに準拠している。
[セマンティックバージョニングのドキュメント(日本語)](https://semver.org/lang/ja/)

# 参考
1. Rust公式フォーラム, https://users.rust-lang.org/t/cargo-lock-dependency-versions-do-not-update-to-match-cargo-toml-dependency-versions/664/2
2. セマンティックバージョニング, https://semver.org/lang/ja/
第六回: HTMLの書き方

こんにちは、[株式会社カスタマトリックス](https://www.customatrix.co.jp/)の寺尾です。

こちらは **新卒社員と学ぶWEBプログラミング** 企画になります。
可能な限り毎日更新していくのでご期待ください。

本日は第六回、「**HTMLの書き方**」を説明していきます。

前回はこちら
https://qiita.com/r-terao/items/b081eecf54d4d4e52e8f

第一回はこちら
https://qiita.com/r-terao/items/e6237c4dc59db9e96ec6

# HTMLの書き方
HTMLの書き方には少しだけルールがあります。
このルールはどこまでが「表示する内容」でどこまでが「表示しない情報」かを切り分けるために存在します。

```構造.html
<!-- DOCTYPE宣言 --> 
<!DOCTYPE html>

<!-- ルート要素 --> 
<html lang="ja">
    <!-- メタデータ --> 
    <head>
        <title>文書のタイトル</title>
        <link rel="stylesheet" type="text/css" href="test.css" />
    </head>

    <!-- コンテンツ --> 
    <body>
        <header>
        </header>
        <main>
            <div>
                Test
            </div>
        </main>
        <footer>
        </footer>
    </body>
</html>
```

最上部に「**DOCTYPE宣言**」を記述します。
これはこのドキュメントがHTMLの文書である事を示します。書かなくても動きはしますがブラウザの挙動を統一するために一応書くのが慣例です。

次に「**htmlタグ**」を記述します。
これはHTML全体の最上位タグになっており、言語設定などの全体設定の記述などが可能です。

その後に「**head**」「**body**」と続きます。
headタグはこの文書のタイトルや、読み込む外部ファイル、文字コードなどの文書の内部設定を記述します。
bodyタグは文書コンテンツそのものを入れます。一般的に「**header**」「**main**」などで区切って文書を分かりやすく構成します。

### HTMLコンテンツの種類
HTMLでは**メタデータコンテンツ**と**フローコンテンツ**が存在します。それぞれざっくり`headタグ`で使うのはメタデータ、`bodyタグ`で使うのはフローと覚えれば問題はありません。

フローコンテンツ内は更に細かいコンテンツに分類が存在します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2273193/7ea46495-365f-f0af-d6c5-258fef3671e6.png)
[画像参照元](https://www.asobou.co.jp/blog/web/html5-3)

- セクショニングコンテンツ
    文章の区分などを表す
- ヘッディングコンテンツ
    見出しを表す
- フレージングコンテンツ
    文章内部で利用する
- エンベッディッドコンテンツ
    動画などを埋め込む
- インタラクティブコンテンツ
    リンクなどのユーザ操作が可能な要素

このように記述するコンテンツが要素ごとに定められているマークアップの構造を**コンテンツ・モデル**と呼びます。
また、このようにコードの一部を切り取っても意味が伝わるように構造情報自体に意味を与えたものを「**セマンティクス**」と呼称する事があります。

HTMLには現在110種類ほどのタグが存在します。
全てを使う機会はそうそうないですが、正しい要素を利用する事で検索性を高めたり、自動読み上げなどのアクセシビリティ対応を高める事が可能です。

### 透明な要素
`aタグ`や`videoタグ`など、一部の要素は「**機能のみを与えて構造それ自体に影響は与えない要素**」が存在します。

これらの要素を「**トランスペアレント・コンテンツ・モデル**」と呼びます。

トランスペアレントは特徴として「**親要素の構造を引き継ぐ**」という機能があります。
そのため、リンクなどの機能を構造を崩す事なく与える事が可能なのです。

```透明.html
<p>
    フレージングコンテンツしか入れられない
</p>

<span>
    <a>
        フレージングコンテンツしか入れられない
    </a>
</span>

<div>
    <a>
        ほかのフローコンテンツも入れられる
    </a>
</div>
```

# まとめ
- HTMLは構造に意味を持たせる事で「どんな機能（内容）か」「何を子要素に入れられるか」をシンプルに定義している
- トランスペアレントという、構造に影響をほぼ与えず機能を付加する要素が存在する
- 文書の意味や内部情報を定義するメタデータというコンテンツが存在する

HTMLはコンテンツ・モデルを利用する事である程度の自由さを残しつつ、最低限のルールを簡単に守れるようになっている事が分かります。
実際にモデルを厳密に意識しながら記述する事は多くないですが、例えば

- 読み上げ機能に読み上げ不要な情報を読み上げさせない
- 支援技術利用者に「ここはナビゲーションである」と伝えたい

などのUXを高めるプログラミングが可能になります。

次回はCSSのルールなんかを取り扱おうと思います。

# おまけ
株式会社カスタマトリックスはエンジニアを募集しています！
完全未経験でも可！

- 新卒の方
https://www.customatrix.co.jp/newgrads/index.html

- 中途の方
https://customatrix.co.jp/career/index.html

https://www.instagram.com/cmx_pr/
Uno CSS: Warning: Received `true` for a non-boolean attribute `flex`.

UnoCSSの適用で詰まったとこのエラー対処のメモです。
あとで見たら思いっきり公式ドキュメントに書いてありましたが。

# 環境
Vite
React
TypeScript


# 経緯
これ見てUnoCSSてなんかいいなと思って軽い気持ちで触ってみようとインストールしました。

https://www.youtube.com/watch?v=ymEF5u5m4Hw



UnoCSSをインストール 
参考: https://unocss.dev/integrations/vite
```zsh
yarn add -D unocss
```
設定
```diff_typescript: vite.config.ts
+ import UnoCSS from 'unocss/vite'
+ import React from '@vitejs/plugin-react'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [
+    UnoCSS(),
+    React()
  ],
})

```

```diff_typescript: uno.config.ts(新規作成)
+ import { defineConfig } from 'unocss'
+ 
+ export default defineConfig({
+   // ...UnoCSS options
+ })
```

main.tsxに下記を追加
```
import 'virtual:uno.css'
```


動画見てカッコ良さそうだったから
@unocss/preset-attributify　を追加した。

```zsh
yarn add -D @unocss/preset-uno
yarn add -D @unocss/preset-attributify
```


参考: https://unocss.dev/presets/attributify
```diff_typescript: uno.config.ts
import {
  defineConfig,
+  presetAttributify,
+  presetUno,
} from "unocss";

export default defineConfig({
  presets: [
+    presetAttributify(),
+    presetUno()
  ],
})
```

TypeScriptで属性が解釈できなくてエラー
> Typescript errors: Property xxx does not exist on type
的なの

参考: https://github.com/unocss/unocss/issues/742
を見て、

```diff_typescript: shims.d.ts (新規作成)
+ import type { AttributifyAttributes } from '@unocss/preset-attributify'
+ 
+ declare module 'react' {
+   interface HTMLAttributes<T> extends AttributifyAttributes {}
+ }
```

```diff_json: tsconfig.json

    (略)
    "include": [
             "src", 
             "images.d.ts", 
+            "shims.d.ts"
         ],
```
公式にも書いてあった: https://unocss.dev/presets/attributify#react



# で、エラー
JSXにflexを追加したら
> Warning: Received `true` for a non-boolean attribute `flex`.


ちゃんとvite.configで`React()`より`UnoCSS()`を前に書いてるけどな...🤔
参考: https://unocss.dev/integrations/vite#frameworks


# エラー対処
https://unocss.dev/transformers/attributify-jsx

```diff_typescript: uno.config.ts
import {
  defineConfig,
  presetAttributify,
  presetUno,
+  transformerAttributifyJsx,
} from "unocss";

export default defineConfig({
  presets: [presetAttributify(), presetUno()],
+  transformers: [transformerAttributifyJsx()],
});
```

したら治った。

思いっきり　https://unocss.dev/presets/attributify#valueless-attributify に書いてあった。
OpsRamp - SLAを超過したチケットをダッシュボードで表示する方法

本記事では、OpsRampのダッシュボードにおいてSLAを超過したチケットを表示する方法について説明します。

# 概要
OpsRampのダッシュボードでは、さまざまなタイルを表示することができます。

# 設定方法
ダッシュボードの設定は、Dashboards > Dashboardから設定可能です。
![dashboard.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/f753e5f3-006b-d2c6-4b22-ac4448485c9f.png)

タイルを追加し、TicketのBuild my ownを選択します。
![dashboard-tikcet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/645c0128-73b1-b50e-bc2b-8a725cc8a4fa.png)

SLAに関連するresponseBreachまたはresolutionBreachを選択し、オペレータに=、値にtrueを設定します。
![dashboard-sla1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/15110b88-982c-1024-b198-50ccebd62fa3.png)
![dashboard-sla2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/623d3e5e-61a1-8438-0cf6-8c7c59fd1d40.png)
ReactでTodoアプリを作成した話（Astroの学習を兼ねて）

今後仕事でAstroを使った開発が必要になりそうなのですが、そのためにはJavascript関連の学習をしていこうと思いまして（重い腰を上げて）Reactの学習に取り掛かったのでした。

Reactを使えるようになるとコンポーネントベースで開発ができるようになって、フロントエンドの仕事もやりやすくなるようなぁと思いつつも、あれこれ言い訳を考えていて手をつけなかった日々。

やっぱり必要に迫られないとやらないなぁと反省しながらもまずはプロジェクト作成からやっていきました。

今回の目標としては、Reactを利用してコードを書いて形問わずデプロイまで持っていくこと。
結論としては1時間かからずに公開まで持っていくことができました。

[完成形](https://react-todoapp-virid.vercel.app/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524273/0c4598a5-e6dc-8d4f-20c7-75f3ae1b826c.png)

登録したTodoを保存する仕組みは用意していないので、リロードすると消えます。
あとは削除ボタンの大きさとか、登録したTodoの表示とか調整箇所は多々ありますが、まずは公開することが大事ってことでこんな感じで落ち着きました。

- 利用ホスティングサービス：Vercel
- 使用エディタ：Cursor


## プロジェクトの作成

ターミナルで任意のディレクトリに移動してからプロジェクトを作ります。

```
npm create-react-app "プロジェクト名"
```

プロジェクトに移動してローカルホストを立ち上げます。

```
cd "プロジェクト名"
npm run start
```

ローカルホストが立ち上がります。合わせてエディタを開いておきます。
自分はCursorを利用していますが、VScodeの場合はcodeから始めて下さい。
```
cursor -n .
```

## ローカルホストで動作確認
ポート番号：3000で立ち上がるので、Reactプロジェクトが立ち上がっていることを確認します。

## コーディング：コンポーネントの作成
今回のコーディングではTodoクラスを作成し、その中に入力値を受け取るメソッド、リストとして追加するメソッド、削除するメソッドを用意しました（たぶん）

```
import React, { Component } from 'react';

export default class Todo extends Component{
    constructor(props){
        super(props);
        this.state = {
            todos: [],
            name: ''
        };
    }

    onInput = (e) => {
        this.setState({
            name: e.target.value
        });
    }
    addTodo = () => {
        const {todos, name} = this.state;
        this.setState({
            todos: [...todos, name]
        });
    }
    removeTodo = (index) => {
        const { todos, name} = this.state;
        this.setState({
            todos: [...todos.slice(0, index), ...todos.slice(index + 1)]
        });
    }



// HTML描画のためのrenderメソッドを定義
// todo名を入力するためのテキストフィールドを作成
// 入力したtodoをリストに追加するためのボタンとtodo一覧を表示するリストを作成
    render(){
        const { todos } = this.state;

        return (
            <>
                <div className="container mx-auto flex flex-col ">
                    <h1 className='text-xl text-center mb-10 p-3 font-bold'>ReactでのTodoアプリ制作Version1</h1>
                    <input type="text"  onInput={this.onInput} className='text-lg rounded border-grary-400 border-4 p-1 mb-3'/>
                    <button onClick={this.addTodo} className='btn bg-blue-500 p-2'>登録</button>
                    <ul className='mt-5 flex flex-col'>
                        {todos.map((todo, index) => <li key={index} className='gap-3'>{todo}
                        <button onClick={ () => { this.removeTodo(index) }} className='btn bg-red-400 p-2 ml-3 rounded'>削除</button>
                        </li>)}
                    </ul>
                </div>
            </>
        )
    }
}
```

## 参考記事
- レイアウトにはTailwindCSSを利用したので、その辺のセッティングで調べました。
https://qiita.com/y_kato_eng/items/439dae65ba13d050c91e

- 実際のコードはこちらのサイトをサンkのウニしています。
https://wk-partners.co.jp/homepage/blog/hpseisaku/javascript/react-start/
WordPressでカテゴリーの設定

WordPressでホームページ・ブログサイトを構築した時のカテゴリ設定方法についてまとめています。
使用テーマはSnow monkeyです。

## この記事を読んだ方がいい人

- WordPressでのホームページを初めて作った人
- Snow monkeyのテーマを利用している人
- ホームページは外注して作ったけど実際の運用は自分（自社）で行う人

## ブログ記事のカテゴリ：初期値
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524273/705093ff-9bb8-72cd-b1ef-82fda71452eb.png)

WordPressでのブログ記事投稿をしていった時、何も気にせず投稿すると記事のカテゴリは『Uncategorized』になります。

このままでも表示自体はされますが、投稿記事が増えていった時に、閲覧しにきてくれた人が記事を探しにくくなるというデメリットが生じます。

閲覧ユーザーがホームページ・ブログサイトを回遊しやすくするためにもカテゴリの設定は必須となります。

## カテゴリの新規作成

カテゴリを新規に作成する方法は2種類あります。
記事の編集画面から作成する場合と、管理画面から作成する場合です。

### 記事の編集画面からカテゴリを新規作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524273/b230f686-e878-bc55-a50b-d75dd66a2574.png)

記事の編集画面からカテゴリを作成するには、編集画面の右側の『投稿』タブ下側にある『カテゴリー』からできます。

『新規カテゴリー追加』をクリックするとカテゴリー名と親カテゴリー名を入力することができます。

ここでは、後述するスラッグを入力できないことが特徴です。

### 管理画面からカテゴリを新規作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524273/034f8ae4-ef0e-e395-4e26-f61f7753efff.png)


管理画面からカテゴリを新規に作成するには、投稿＞カテゴリーをクリックします。
この時、名前以外にスラッグを入力することができます。

スラッグはURLに表示される部分で、これを英文字にしておくと見栄えが良くなります。

逆に日本語でそのままにしておくと、URL表示が％E%2〜のような（コード変換された）文字列になってしまって非常に見にくくなってしまいます。

なので、スラッグは英単語1・2語程度で作ることをお勧めします。

## カテゴリ初期値の変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524273/e4fc3340-faf9-fab2-2b90-2846877a74e9.png)

先ほど書いた通り、投稿用のカテゴリは初期値で『Uncategorized』になっています。

これを記事作成ごとにカテゴリを設定してもいいのですが、初期値自体を変更することも可能です。

管理画面から設定＞投稿設定と遷移し

投稿用カテゴリーの初期設定の部分をUncategorizedから好きなものに変えればOKです。

カテゴリが見やすくなればユーザーも記事を見つけやすくなり、サイトの滞在時間が増えればサイトのSEO効果も高くなって上位表示されやすくもなるので頑張っていきましょう！
PL-200 学習メモ (15) : Power Pages (サインイン、アクセス制御、管理センター)

# はじめに
この投稿は PL-200: Microsoft Power Platform 業務コンサルタントの学習をした内容のメモです。

投稿の一覧は以下のリンク先にあります。

https://qiita.com/atsmin77/items/f25bd707921c421cee03

# 前の投稿

https://qiita.com/atsmin77/items/7c43b446c15fdc741ccd

# サインイン

Web サイト独自のアカウントや Entra ID のアカウントによってサインインすることができます。サインインすることで、アカウントのもつ権限によってサイトにアクセスすることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/7f94f98e-44c4-9033-c8e7-845ac7e3fe23.png)

## サインイン方法の設定

[セキュリティ] - [ID プロバイダー] から、ユーザーに許可するサインインの方法を設定します。
既定では [ローカル サインイン] と [Azure AD] が有効になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/5714950d-7029-69ee-adaa-86f2b885996b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/33dbaa39-5731-ce73-8a44-2f0c27932076.png)

[認証設定] からはページにアカウントの登録フォームを表示するかどうかなどを制御することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/b1b11272-4078-24fd-87d5-45e6014c5bc0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/978205db-c6d7-0f99-9526-83a684415f83.png)

# アクセス制御

ユーザーのアクセス制御は **Web ロール** で行います。既定では以下の 3 つの Web ロールがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/00a8379e-b67a-5354-d0fc-4d3596468d1a.png)

| 名前 | 説明 |
|:-:|:-:|
| 管理者  | 管理者権限を持つユーザーの既定のロール  |
| 認証されたユーザー  | サインインしたユーザーの既定のロール  |
| 匿名ユーザー  | サインインしていないユーザーの既定のロール  |

Web ロールに対して、ページやテーブルについてのアクセス許可を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/39f39177-b4fe-aa7b-40e5-3e4e7f6260ae.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/d7d17625-0050-d2a8-c4bf-f4fdc7ef4bbd.png)

https://learn.microsoft.com/ja-jp/power-pages/security/create-web-roles

# 管理センター

PowerPlatform 管理センター の [リソース] - [Power Pages サイト] - [サイト アクション] から、サイトの再起動や診断ログの有効化などの操作が行えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680397/a2dd2f0b-2c0f-c5a1-1042-093b386d27d8.png)

https://learn.microsoft.com/ja-jp/power-pages/admin/admin-overview
Azure の仮想マシンを Hyper-V 環境で起動させる

Azure の仮想マシンを手元の物理端末の Hyper-V 環境へ持ってきて起動しようという話です。

Azure の仮想マシンの仮想ディスクは、以下の Web サイト記載の方法で Azure Portal からダウンロードできますが、なぜかファイル名が **"abcd"** という謎のファイルがダウンロードされます。

https://learn.microsoft.com/en-us/azure/virtual-machines/windows/download-vhd?tabs=azure-portal

実態は、仮想ディスクで、Azure 仮想マシンが第1世代であれば、abcd.vhd と名前を変更するだけで問題ありませんが、第2世代だどそのまま起動することができません。

第2世代の Azure 仮想マシンの仮想ディスクファイル "abcd" から Hyper-V 仮想マシンを起動させるまでは、ちょっとやることが多いので、PowerShell で自動化してみました。

## やること
1. abcd ファイルに拡張子 .vhd を付ける
1. vhd 形式の仮想ディスクを vhdx 形式の仮想ディスクへ変更
1. 仮想マシン作成、仮想マシンの設定を変更
1. 仮想マシン起動

## PowerShell スクリプト
```powershell:AzureVM2HyperVVM.ps1
# 1. ファイル名 C:\Path\To\abcd を C:\Path\To\abcd.vhd に名前変更
$downloadFilePath = "C:\Path\To\abcd"
$newFileName = "abcd.vhd"

# ファイルが存在するか確認し、存在する場合は名前変更
if (Test-Path $downloadFilePath) {
    Rename-Item -Path $downloadFilePath -NewName $newFileName
    Write-Host "Renamed file to: $newFileName"
} else {
    Write-Host "File not found: $downloadFilePath"
    exit -1
}

# 2. 仮想ディスク abcd.vhd を abcd.vhdx [可変ディスク]へ変換
$directoryPath = Split-Path -Path $downloadFilePath
$vhdFilePath = "$directoryPath\$newFileName"
$vhdxFilePath = "C:\Path\To\abcd.vhdx"

Convert-VHD -Path $vhdFilePath -DestinationPath $vhdxFilePath -VHDType Dynamic
Write-Host "Converted VHD to VHDX: $vhdxFilePath"

# 3. 第2世代の Hyper-V 仮想マシンを変換した仮想ディスク (.vhdx) を指定して作成
$vmName = "TestVM"
$vmMemory = 8GB
$cpuCount = 4

# 仮想マシンの作成
New-VM -Name $vmName -Generation 2 -MemoryStartupBytes $vmMemory -BootDevice VHD -VHDPath $vhdxFilePath

# CPUコア数設定、静的メモリに設定、自動チェックポイント機能をOFF
Set-VM -VMName $vmName -ProcessorCount $cpuCount -StaticMemory -AutomaticCheckpointsEnabled $false
Write-Host "Created VM: $vmName with $cpuCount CPUs and $vmMemory memory."

# DVDドライブを追加（任意）
Add-VMDvdDrive -VMName $vmName -ControllerNumber 0
Write-Host "Added DVD drive to VM: $vmName"

# セキュアブートを解除（任意）
Set-VMFirmware -VMName $vmName -EnableSecureBoot Off
Write-Host "Disabled Secure Boot for VM: $vmName"

# 仮想マシンのチェックポイントを取得（任意）
$checkpointName = "Init Checkpoint"
Checkpoint-VM -Name $vmName -SnapshotName $checkpointName
Write-Host "Checkpoint '$checkpointName' has been created for VM '$vmName'."

# 4. 仮想マシンを起動する
Start-VM -Name $vmName
Write-Host "Started VM: $vmName"
```

## 参考URL
New-VM (Hyper-V) | Microsoft Learn
https://learn.microsoft.com/en-us/powershell/module/hyper-v/new-vm

Set-VM (Hyper-V) | Microsoft Learn
https://learn.microsoft.com/en-us/powershell/module/hyper-v/set-vm

Add-VMDvdDrive (Hyper-V) | Microsoft Learn
https://learn.microsoft.com/en-us/powershell/module/hyper-v/add-vmdvddrive

Set-VMFirmware (Hyper-V) | Microsoft Learn
https://learn.microsoft.com/en-us/powershell/module/hyper-v/set-vmfirmware

Start-VM (Hyper-V) | Microsoft Learn
https://learn.microsoft.com/en-us/powershell/module/hyper-v/start-vm
【自己紹介】worldtoprank：世界のトップランキングを収集、スタートアップ企業とAIに特化 


worldtoprank: 世界のトップランキングを収集、スタートアップ企業とAIに特化

ランキングサイト：www.worldtoprank.com

## プラットフォーム  
独立サイト

## 推薦タイプ  
【自己紹介】

概要  
世界のトップランキングを収集、教育、人口、経済、金融、スタートアップ企業、AI、テクノロジー、ビジネス、スポーツ、エンターテイメントなど

## 今後のロードマップ:  
⌛ AIエージェントを導入し、毎年変わるリンクを自動的に収集する機能を追加。例：MIT 10 Breakthrough Technologies  
⌛ 上記の基準を満たすランキングを投票で追加する機能を導入  
⌛ その他、計画中の機能多数
Next.jsでtailwind cssが効かない原因😭

## 解決策
```tailwind.config.ts
content: [
        "./pages/**/*.{js,ts,jsx,tsx,mdx}",
        "./components/**/*.{js,ts,jsx,tsx,mdx}",
        "./app/**/*.{js,ts,jsx,tsx,mdx}",
        //！！追加忘れているかも！！
        "./features/**/*.{js,ts,jsx,tsx,mdx}",
    ],
```

tailwind.config.tsを見ればおそらく解決します。
昨今のNext.jsプロジェクトにはsrcディレクトリを削除できるオプションがあるかと思います。それにより、今までsrc利用時は下記のようなcontentにより全てのディレクトリ配下でtailwind cssが効いていたのですが、srcディレクトリを採用しない場合、効かなくなってしまいます。
```tailwind.config.ts
"./src/**/*.{js,ts,jsx,tsx,mdx}",
```
自身で追加したディレクトリがcontentに追加されている確認しましょう
Paiza×Qiitaキャンペーン Javaで解説してみた【B 名刺バインダー管理 編】

# 問題へのリンク

https://paiza.jp/works/mondai/b_rank_skillcheck_archive/name_card

# 解答コード

<details><summary>詳細</summary>

~~~

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		final int N = scanner.nextInt();
		final int M = scanner.nextInt();
		scanner.close();

		int page = (M - 1) / N + 1;
		int index = M - (page - 1) * N;

		if ((page & 1) == 1) {
			page++;
		} else {
			page--;
		}
		
		System.out.println((N * (page - 1)) + (N - index + 1));
	}
}


~~~

</details>



# 解説

<details><summary>詳細</summary>

paizaで重要なのは、コードの記述能力というよりも、どれだけ問題を整理できるかです。

まず、Mが何ページ目の何番目にあるかを考えます。

ページ
・先頭のページを1とすると M から N で割った時、端数切り上げにする必要があります
⇒ M / N だと端数切捨てになってしまいます。切り上げるためには (M - 1)  / N + 1　にする必要があります。 

閾値(境界線にあたる値)を意識したら気づけます
例1: M = 1 N = 3
1 / 3 ⇒ 0
( 1 - 1 ) / 3  + 1 ⇒ 1
例2:M = 3 N = 3
3 / 3 ⇒ 1
( 3 - 1 ) / 3  + 1 ⇒ 1
例3:M = 4 N = 3
4 / 3 ⇒ 1
( 4 - 1 ) / 3  + 1 ⇒ 2


次にそのページの何番目のポケットに入っているかを計算します
M から N * (page - 1) を引くと良いでしょう

では、page と index を使って目的の数値を求めます
page が奇数の場合、裏面は次のページになります(page++)
page が偶数の場合、裏面が前のページになります(page--)
例ではbit演算で行っていますが(一番右のbitが1なら奇数)2で割って余り0なら偶数です(余り1なら奇数で覚えると、マイナスの時困るので気をつけましょう)

index = 1 の時、裏から見るとポケットは一番右(N)に
index = N の時、裏から見るとポケットは一番左(1)になります

ですのでN - index + 1 番目のポケットに入っていることになります

ですので数字になおすと  N * (page- 1) + (N - index + 1 )
になります。

</details>

# Paizaのコツ
プログラミングのコツは、やりたいことをしっかり分解して、自分のできることに細分化していくことです。
数億行クラスの複雑な処理を行うプログラムも、一行単位なら初心者でもかけるものしか使ってません。
Bランクだと、まだ特殊なアルゴリズムは要求されません。
素直かつ冷静に、コードに落とし込めるよう練習していきましょう。
Phoenix Projectの作成からモーダル経由でのポストの作成と一覧への反映の処理の流れ part2

https://qiita.com/akiraarika932/items/1453857f6d227d7d2572

前回の続きとなります
現時点でプロジェクトの作成までが完了しています
続いてルーティングの追加と実際にどの関数が機能しているのかを１つ１つ確認していきます

ルーティング
リンクにnewを追加してポストを追加できるようにします
```/lib/hogehoge_web/router.ex
defmodule
    # other code

    scope "/", HogehogeWeb do
        pipe_through :browser

        get "/", PageController, :home
        get "/test", PageController, :test
    end

    # other code

end
```
これでlocalhost:4000/testにアクセスした際にルーティングが機能します
但しルーティング先であるPageControllerのpage_controller.exにhomeの記述が追記されていないためアクセスしても動作はしません
ただ設定されているだけの状態になります
UndefinedFunctionError
function HogehogeWeb.PageController.test/2は未定義かプライベートという文面が表示されています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/2cb1d9a1-3c05-f468-4d5c-12f12e651b60.png)



次にget "/test", PageController, :homeの第二引数で設定したPageControllerについて解説していきます
この第二引数に合致したlib/hogehoge_web/controllers/page_controller.exを新規に作成
この内部に関数を作成します
ここで作成する関数は第三引数の:testを定義する必要があります
``` page_controller.ex
  def test(conn, _params) do
    render(conn, :test, layout: false)
  end
```

``` lib/hogehoge_web/controllers/page_html/test.html.heex
<p>Test</p>
```

この状態でlocalhost:4000/testへアクセスすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/7d9e65d0-0dba-006d-eb76-7b0a64f83249.png)
test.html.heexで記述したTestが表示されました

一連の流れ
リンクの情報を解析し、router.ex内で一致する関数を調査
一致した値を調べて（今回はget "/test", PageController, :test）controllersの配下にある第二引数の名称の.exにアクセス
第三引数のtestに合致した関数を実行する
page_html配下にあるtest.html.heexにアクセスしRender内容を実行する


まとめ
ここまでの情報を整理します
今回修正、追加するファイルは以下
・router.ex
・page_controller.ex
・test.html.heex（追加）

プログラミングで厄介なことの１つに作る際に記述した名称が単に作り手が自分で定義したものなのかそれともアプリケーションで重要な機能を持ったものなのかといった違いがあるでしょう
例えばrouter.exの
> get "/test", PageController, :test

を分解するとgetを除く用語は作り手が自由に決めれます
そして作った要素に合わせてプロジェクトファイルの追加や修正が発生します（今回は特になし）
反対にpage_controller.exを見てみると
>  def test(conn, _params) do
    render(conn, :test, layout: false)
  end

はtestは今回routerで作成した内容と一致しますが、renderやconnというのはphoenixでの基礎的な要素となり作り手が好きに定義する箇所ではありません
こういった差異を意識しないと今自分は自由に変更できるところを触っているのか？それとも処理の流れ上書き方が決まっている箇所を触っているのかの区別がつかなくなります

以下参考サイト

https://hexdocs.pm/phoenix/Phoenix.Router.html

https://zenn.dev/tkrd/books/live_view_primer_1/viewer/ch04_controllers_and_actions
Hugging Face のキャッシュ操作 / huggingface-cli と HF_HOME 環境変数

Hugging Faceで公開されている基盤モデルを利用する際には、ダウンロード(キャッシュ)したり、そのモデルファイルをコードから参照できるようにする必要があります。

* キャッシュの操作には `huggingface-cli` コマンド
* キャッシュ参照には `HF_HOME` 環境変数

これらを使用します。

## キャッシュの操作 - huggingface-cli

huggingface-cli は Python ライブラリ [huggingface_hub](https://github.com/huggingface/huggingface_hub) の中にあります。

インストールは Getting Started の通りです。

```shell
pip install -U "huggingface_hub[cli]"
```

venv 等で隔離もできます。

```shell
python3 -m venv foobar
source foobar/bin/activate
pip install "huggingface_hub[cli]"
## 以降 `source foobar/bin/activate` すれば `huggingface-cli` コマンドが使える
```

### ダウンロード - download

基盤モデルのダウンロードは `download` サブコマンドです。

例えば Microsoft の SLM「Phi-3」の一番小さいモデル [microsoft/Phi-3-mini-4k-instruct](https://huggingface.co/microsoft/Phi-3-mini-4k-instruct) をローカルにダウンロードするなら、以下の通りです（小さいといっても約8GBあるので、ネットワーク環境にはご注意を）。

```shell
huggingface-cli download microsoft/Phi-3-mini-4k-instruct
```

:::note
`You must be authenticated to access it.` としてダウンロードできなかった場合は `huggingface-cli login` で認証を得てください。
:::

### キャッシュを確認 - scan-cache

キャッシュを確認するには `scan-cache` サブコマンドです。

```shell
huggingface-cli scan-cache
```

以下のように、サイズや保存先パスが確認できます。

```shell
$ huggingface-cli scan-cache
REPO ID                          REPO TYPE SIZE ON DISK NB FILES LAST_ACCESSED LAST_MODIFIED     REFS LOCAL PATH

-------------------------------- --------- ------------ -------- ------------- ----------------- ---- -------------------------------------------------------------------------------
amazon/chronos-t5-large          model             2.8G        3 3 days ago    4 days ago        main /home/USER/.cache/huggingface/hub/models--amazon--chronos-t5-large
amazon/chronos-t5-tiny           model            33.8M        6 2 days ago    4 days ago        main /home/USER/.cache/huggingface/hub/models--amazon--chronos-t5-tiny
microsoft/Phi-3-mini-4k-instruct model             7.6G       19 3 minutes ago a few seconds ago main /home/USER/.cache/huggingface/hub/models--microsoft--Phi-3-mini-4k-instruct

Done in 0.0s. Scanned 3 repo(s) for a total of 10.5G.
Got 1 warning(s) while scanning. Use -vvv to print details.
```

### キャッシュの削除 - delete-cache

削除は `delete-cache` サブコマンドです。
実行するとTUI(Terminal User Iterface)が立ち上がり、インタラクティブに削除できます。

```shell
huggingface-cli delete-cache
```

引数に REPO ID を指定した削除はできません。カーソルで削除対象を選んで、削除しましょう（なぜ指定できないのか🤔）。

## キャッシュの参照先を設定 - HF_HOME 環境変数

キャッシュのディレクトリ構造は [Manage huggingface\_hub cache-system](https://huggingface.co/docs/huggingface\_hub/guides/manage-cache) の通りです。

`<CACHE_DIR>` は、通常は `~/.cache/huggingface` です。
そして `<CACHE_DIR>` は、`HF_HOME` 環境変数に設定したディレクトリへ変更できます。

例えば `/tmp/new_hf_home/` にしたければ、以下のようにします。

```shell
export HF_HOME="/tmp/new_hf_home/"
huggingface-cli download REPO_ID
python3 foobar_genai_exmaple.py
```

他の環境変数は [Environment variables](https://huggingface.co/docs/huggingface_hub/package_reference/environment_variables) をご覧ください。

これでコンテナ内に押し込めることもできますね。コンテナ化で有用そうなのは [`HF_HUB_OFFLINE`](https://huggingface.co/docs/huggingface_hub/package_reference/environment_variables#hfhuboffline) あたりでしょうか。

## あとがき

ちょっとググってみたが無かったので、ササッと書いた。

EoT
pandas: PostgreSQL のテーブルの更新

## プログラム

```py:postgre_drop.py
#! /usr/bin/python
#
#	postgre_drop.py
#
#					Aug/28/2024
# ------------------------------------------------------------------
import sys
import pandas as pd
#
from sqlalchemy import create_engine
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
engine = create_engine('postgresql://scott:tiger123@127.0.0.1/city')
#
df=pd.read_sql_query('SELECT * FROM cities', con=engine)
print(df)
print(df.shape)
#
try:
	dg = df.drop([0,1,2,3])
	print(dg)
	print(dg.shape)
	try:
		dg.to_sql(name='cities',con=engine,if_exists='replace', index=True)
	except Exception as ee:
		sys.stderr.write("*** error *** in db.to_sql ***\n")
		sys.stderr.write(str(ee) + "\n")

except Exception as ee:
	sys.stderr.write("*** error *** in df.drop ***\n")
	sys.stderr.write(str(ee) + "\n")
#
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

## 実行結果

1回目

```text
$ ./postgre_drop.py
*** 開始 ***
       0    1      2           3
0  t1271   千葉  58471   2003-9-25
1  t1272   勝浦  49523   2003-3-16
2  t1273   市原  27461   2003-6-21
3  t1274   流山  39872   2003-8-27
4  t1275  八千代  21576   2003-11-5
5  t1276  我孫子  53271   2003-1-12
6  t1277   鴨川  81326   2003-5-22
7  t1278   銚子  95142  2003-10-18
(8, 4)
       0    1      2           3
4  t1275  八千代  21576   2003-11-5
5  t1276  我孫子  53271   2003-1-12
6  t1277   鴨川  81326   2003-5-22
7  t1278   銚子  95142  2003-10-18
(4, 4)
*** 終了 ***
```

2回目

```text
$ ./postgre_drop.py
*** 開始 ***
   index      0    1      2           3
0      4  t1275  八千代  21576   2003-11-5
1      5  t1276  我孫子  53271   2003-1-12
2      6  t1277   鴨川  81326   2003-5-22
3      7  t1278   銚子  95142  2003-10-18
(4, 5)
Empty DataFrame
Columns: [index, 0, 1, 2, 3]
Index: []
(0, 5)
*** 終了 ***
```

## 参考ページ
[pandas で PostgreSQL の読み書き](https://qiita.com/ekzemplaro/items/ce0768d2102c6ef3c82e)
Amazon RDS for PostgreSQL11の延長サポートでマイナーバージョンが発表されました

こんにちは、Koderaです。
Amazon RDS for PostgreSQL11で新しいマイナーバージョン「11.22-RDS.20240808」が発表されました。
https://aws.amazon.com/about-aws/whats-new/2024/08/amazon-rds-postgresql-minor-11-22-rds-20240808/

## RDS延長サポートとは
2024年4月から延長サポートに入られている方、既にバージョンアップされた方様々かと思いますが、改めてAWSから発表された「Amazon RDS Extended Support」についてお伝えします。
Aurora/RDSに関係なく、延長サポートは「Amazon RDS Extended Support」と「RDS」で名称が統一されます。

#### 延長サポートの目的
オープン ソース コミュニティのサポート終了後にアプリケーションが重大なセキュリティの脆弱性や解決できないバグ出て解決できない事象を防ぎます。

#### サポート内容
Amazon AuroraとAmazon RDS は、PostgreSQLとMySQLが提供するサポート期間を超えても最大で**3年間**、AWSからエンジンの修正と CVE パッチを含む新しいマイナーバージョンをリリースします。

#### サポート対象のバージョンとサポート期間
RDS 延長サポートは、RDS for MySQL 5.7 および 8.0、RDS for PostgreSQL 11 以降で利用できます。

以下がRDS for MySQLの延長サポートです。
MySQL5.7は延長サポートでのみ利用が可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858908/12e2aae1-bae5-ab75-f562-07cc1c751ac2.png)

続いて以下がRDS for PostgreSQLの延長サポートです。
現状では、PostgreSQL 11のみが対象ですが、来年2025年3月1日からは、PostgreSQL 12も延長サポート対象ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858908/d687cd90-df23-2ad3-0c76-ed0a8b74d6ad.png)

Aurora MySQLの延長サポートです。Auroraの延長サポートの課金は本記事執筆時点では開始されておらず、2024年12月から開始されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858908/da1f1ca2-2049-b9d9-80de-9d15f5eebcf7.png)

Aurora PostgreSQLの延長サポートです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858908/3b878c5d-bd48-84d6-16ab-2f2a679b3590.png)



#### どんな時に役立つ？
特定のプラグインやカスタム機能との互換性など、特定の MySQL または PostgreSQL メジャー バージョンに特定の依存関係がある場合、RDS 延長サポートはアプリケーションのビジネス要件を満たすのに役立つ場合があります。

#### 延長サポートの料金
延長サポートの費用はvCPU数に応じて課金が発生します。
単価は**1年目、2年目**と**3年目**の2つの課金体系に分かれており、3年目は1年目と2年目の2倍です。また、1時間あたりの料金はインスタンスと同じくリージョンによって異なります。

RDS for MySQLおよびRDS for PostgreSQLでは、以下の通りです。

・1年目・2年目：0.12USD/vCPU
・3年目:　0.24USD/vCPU


以下がAuroraの料金です。サーバレスでなければ、RDS for MySQL、RDS for PostgreSQLと同じ価格です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858908/31908a92-3e13-af54-d663-0a8a199ae1c1.png)


## アップデート内容
Amazon RDS for PostgreSQL11で新しいマイナーバージョン「11.22-RDS.20240808」がサポートされました。
該当バージョンでは、[CVE-2024-7348](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-7348)パッチの修正が含まれています。

PostgreSQL の pg_dump実行時の Time-of-check Time-of-use (TOCTOU) 競合状態により、オブジェクト作成者は pg_dump を実行しているユーザー (多くの場合スーパーユーザー) として任意の SQL 関数を実行できてしまうという脆弱性に対応したものです。

本アップデートにより、RDS for PostgreSQLの延長サポートでは3つのバージョンがサポートされています。

・[Amazon RDS Extended Support version 11.22-RDS.20240808](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extendedsupport.html#postgresql-versions-version11.22-rds.20240808)
・[Amazon RDS Extended Support version 11.22-RDS.20240509](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extendedsupport.html#postgresql-versions-version11.22-rds.20240509)
・[Amazon RDS Extended Support version 11.22-RDS.20240418](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extendedsupport.html#postgresql-versions-version11.22-rds.20240418)

## まとめ
2024年8月8日に作成されたAmazon RDS マイナーバージョンが発表されました。
また、サポート期限についても最新情報をまとめてみました。
アップグレード方法などはまた改めて記載してみたいと思います。
C++のコピーコンストラクタと代入演算子

C++のコピーコンストラクタと代入演算子についての疑問が解決したので、備忘録として書いておきます。
まず記法についてですが、
```diff_cpp
class example(const example& A){/*処理内容*/} //コピーコンストラクタ
class example& operator=(const example& A){/*処理内容*/} //代入演算子
```
となります。代入演算子の方は所謂演算子のオーバーロードというやつです。
2つともイコール"="によって呼び出されるのですが、イコールの場所によってどちらが呼び出されるかが変わります。コピーコンストラクタはあくまでコンストラクタである為、初期化と同時に呼び出されます。一方代入演算子はすでに生成されたインスタンス間にイコールを用いたとき呼び出されます。
 つまりこういうこと
 ```diff_cpp
 int main(){
     example A;
     example B = A; //コピーコンストラクタが呼び出される
     example C;
     C = A; //代入演算子が呼び出される

     return 0;
}
```
ちなみにこの2つは定義しなくても良いのですが、定義しない場合、右辺の値(例ではA)のメンバ変数がすべてコピーされます。なのでコピーの際に特殊な処理が必要ない場合、書かなくてもOKです。
VS Code の機能拡張のバージョンを戻す方法

先日まで動いていた Tailwind CSS IntelliSense が動かなくなった。

数日前に自動更新された v0.12.7 に問題があるのかもしれません。

とりあえず v0.12.6 に戻したところ正常動作しました。

# VS Code の機能拡張のバージョンを戻す方法

コマンドパレットを開く`Cmd+Shift+P`し、`Extensions: Install Specific Version`を検索して選択します。

`Tailwind CSS IntelliSense`の名前を入力し、戻したいバージョンを選択します。

あとは、 VS Code の再起動でこれまで通り動作させることができました。
なぜ、LINEに誘導するのか

エックスをやっていると
「いいねして！LINEに登録するとプレゼントあるよ」

まぁ、儲かる系はだいたいこんな感じ。

どういうことなんだろうなと思い調べてみた

参考
https://note.com/houkano_note/n/n2a67e3b95438


2021年～2024年の間、合計32人へフォロー＆リツイート
→ 30人が同じように公式LINEへ誘導してきた

# アフィへ誘導

1.BrainやTipsの有料記事の宣伝
友達登録特典として、こちらの情報をプレゼントします！
無料で読めるnoteやブログなどの記事へ案内される。

→ ゴミのような情報だらけ

2.有料記事への誘導

友達登録してくれた人限定で、僕が初月から30万を達成したロードマップを公開しますと有料記事や商材へのリンクへ誘導される。

安いものでは1980円〜9800円
高額なものだとだいたい10000円〜49800円

ほんとは稼いでないからチマチマ稼いでるんじゃないの？


# 詐欺へ誘導

クレジットカードがいくら使えるか？
また購入代行と称し何かを購入させようとしてくる。

# マーケティング手法

SNS
→ プル型

LINEやメルマガ
→ プッシュ型

# webマーケティングの基本は、AES

Attract（引きつける＝集客）
Education（教育する＝商品の価値を教える）
Sales（販売する）

いわゆる洗脳。これを今ではファン化と言葉を変えている人がいる。

# まとめ

ただサイトにアクセスさせるだけでは申込みが少ない。
よって、申し込みさせる前にLINEで洗脳してコンバージョン率を高めるという手法なのですね。
Pythonを実行しても，Rye を再インストールしても，Bad CPU type in executableと出る．

# TL;DR;
- `rm -r ~/.rye` を実行する．
- `curl -sSf https://rye.astral.sh/get | bash` で入れ直す．


# 経緯
- ~~あまり無いケースかもしれないが，~~ とある理由で，`M1` に入っていた内容を `Intel` に入れ直した．
- `python` コマンドが `Bad CPU type in executable` となって実行できない．
- `which python` と入力すると，`~/.rye` を参照していることがわかる．
- [公式サイト](https://rye.astral.sh/guide/installation/#installing-rye) にあるインストール方法を試す． `curl -sSf https://rye.astral.sh/get | bash`
- しかし，インストール途中で `Bad CPU type in executable` と出てしまう．
- インストール中のエラー出力で，`Detected outdated rye internals. Refreshing` と出ていることから，既存の(`Intel` に移行する前に入れた) `~/.rye` を消してから再インストールすればいんじゃね？


# 修正
まず，既存の `rye` を消す．
```shell
rm -r ~/.rye
```
次に，`rye` を[公式サイト](https://rye.astral.sh/guide/installation/)に従って，入れ直す．
```shell
curl -sSf https://rye.astral.sh/get | bash
```
対話は以下のように答えた．(ここは好みで分かれるでしょう．)
```
Details:
  Rye Version: 0.39.0
  Platform: macos (x86_64)

✔ Continue? · yes
✔ Select the preferred package installer · pip-tools (slow, higher compatibility)
? What should running `python` or `python3` do when you are not inside a Rye managed project? ›
✔ What should running `python` or `python3` do when you are not inside a Rye managed project? · Run a Python installed and managed by Rye
? Which version of Python should be used as default toolc
✔ Which version of Python should be used as default toolchain? · cpython@3.12
Installed binary to ~/.rye/shims/rye
Bootstrapping rye internals
Fetching requested internal toolchain 'cpython@3.12.5'
Downloading cpython@3.12.5
Checking checksum
Unpacking
Downloaded cpython@3.12.5
Updated self-python installation at `/.rye/self

All done!
```

# 余談
- `Intel` -> `M1` に移行した時は， `Rosetta 2` を導入すれば解決するかもしれない．
- だけど，私の場合はおそらく特殊で， `M1` -> `Intel` に移行したので，それに対応するやつが見つからない(~~探してないだけ~~)．
- `brew` も動かないし，結構面倒なことになりそう．．．
[Legal]

# 不正アクセス禁止法
|条項|||
|:--|:--|:--|
|3条|不正アクセス||
|4条|他人の認証情報を取得する行為||
|5条|他人の認証情報を提供する行為||
|6条|他人の認証情報を補完する行為||
|7条|管理者になりすます行為||

# 製造物責任法
|条項|||
|:--|:--|:--|
|対象|製造物の欠陥によって、身体・財産への損害が生じた場合の製造者の損害賠償責任を定める||
|対象外|ソフトウェアやデータは``無形``のため対象外||


# 参考リンク
- [令和4年春78](https://www.ap-siken.com/kakomon/04_haru/q78.html)
- [令和3年秋78](https://www.ap-siken.com/kakomon/03_aki/q78.html)
vscodeとVM環境をSSHキーを使って疎通接続した

# 前置き

ローカルPC上にインストールしたvscodeを使って試験環境のVMへ接続する。

VM先でsshdが許可されていれば、vscodeからSSH接続を実行することで接続することが可能であるが、毎回パスワードを求められてめんどうである。

そのため、SSHキーを作成しやり取りすることで、接続時に逐一パスワードを求められる工程をスキップすることができる。

今回は実施方法を残す

# 作業1 SSHキーの発行

ローカルPC上でSSHキーを新規に発行する

コマンドプロンプトを立ち上げて下記コマンドを実行する(vscodeのターミナルでもOK)

```
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
```

:::note info 
**メモ**
自身がログインしているアカウントの登録アドレスを指定する

**引数**
-t rsa はRSAアルゴリズムを使用することを指定しています。
-b 4096 はキーの長さを4096ビットに設定しています。
-C はキーのコメントで、通常はメールアドレスを指定します。
:::

保存先のディレクトリを聞かれます。デフォルトであれば **~/.ssh/id_rsa**です。
下記パスにファイルが生成されたことを確認してください。
```
C:\Users\ログインユーザ名\\.ssh
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596363/c11b3467-11f8-f011-87a6-f4528cf79096.png)

# 作業2 公開キー格納先ディレクトリの作成

VM環境へログインします。
/home/user/直下に.sshディレクトリを作成します。
作成したディレクトリへローカル環境で生成した公開キーをコピーし、格納します
```
mkdir ~/.ssh
```

# 作業3 公開キーをVMへコピー

生成されたSSH公開キーをSSH接続したいVMの環境へ移動させます。
コピーする方法は色々ありますが、今回はOSS(無料)のWinSCPツールを利用します。
GUIで操作できます。作業2で作成したディレクトリへ格納しましょう。

DL参考サイトはこちら
https://www.rouge.gr.jp/~fuku/tips/winscpstd/

# 作業4 権限変更および公開キー名変更

公開キーファイル名を変更します。
```
mv id_rsa.pub authorized_keys
```
ファイル名変更ごはディレクトリとファイルの権限を変更しておきます。
```
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
```

# 作業5 SSH接続確認

公開キーをVMへ正しく追加出来たら、再度ローカルPCからVMにパスワード無しで接続できるか確認します。
コマンドプロンプトから下記コマンドでログインできるか確認します。

```
ssh 'vmのログインユーザ'@'接続先VMのIP'

例 ：user1@192.168.10.1
```

以上で終了です。

コマンドプロンプトでパスワードを求められずに実行が確認出来たら、VSCODE上からのSSH接続時もパスワードを求められることなく接続できます。
springbootをざっくり図でつかむ

springbootを勉強するにあたり、まずはざっくり掴むために全体図を作ってみました。
まだ理解が浅いため、ご指摘いただけますと嬉しいです。
![IMG_6725.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3845328/05e6fef4-1ecf-f8ce-ed9e-d326f81f2300.png)
Jetpack 6.2 production releaseにmozcをインストールし日本語入力できた

覚書です。もし読まれた方のご参考になれば幸いです。

[Jetson Orin Nano Developer Kit Getting Started Guide](https://developer.nvidia.com/embedded/learn/get-started-jetson-orin-nano-devkit)
[JetPack 6.2](https://developer.nvidia.com/embedded/jetpack-sdk-62)

定番を実施
```
$ sudo apt update
$ sudo apt upgrade -y
$ reboot
```

mozc 日本語入力をインストール
```
$ sudo apt install ibus-mozc -y
$ ibus restart
$ gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'jp'), ('ibus', 'mozc-jp')]"
$ reboot
```
・[参考 : Ubuntu20.04で日本語入力(Mozc)を可能にする方法](https://novicengineering.com/ubuntu_mozc_install/)
Pythonユーザーのためのデータの保管方法

## この文書の目的
pythonプログラマのためのスキルを標準化するための情報へのリンクを示します。
個別の内容については、それぞれ詳しい記事がネット上に書かれているので、
この文章では詳細は省略します。


## 想定する読者
- [Python プログラマのスキル標準化のための項目](https://qiita.com/nonbiri15/items/6461aa4dd82183fa7014)を気にかけてくださっている方
- 機械学習をしているPythonユーザー



# gitリポジトリに少量のテスト用データファイルを置く
- リポジトリのモジュールのテストのために少しだけデータをおかなきゃならないことがある。
#### git lfs
リポジトリのルートで以下のコマンドを入力する。
```
git lfs track "*.jpg" "*.png" "*.ply" "*.npy"
```
そうすると.gitattributes ファイルに以下の内容が追加される。

```
 cat .gitattributes 
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.ply filter=lfs diff=lfs merge=lfs -text
*.npy filter=lfs diff=lfs merge=lfs -text
```

そうすると、これらのパターンにマッチするファイルは、Git LFS (large file system) を使って管理されるものになる。
その分、gitサーバーの負担が少し軽くなる。
fileのチェックサムを使ってファイルに変更があるかどうかを管理するようになる。
テキストの場合のようにdiffを参照しようとはしなくなる。

## Google Drive 上にデータをおいて、そこからダウンロードさせる場合
[【Python】GoogleDriveからファイルをダウンロード](https://touch-sp.hatenablog.com/entry/2022/01/09/112413)

gdown --fuzzy についても調べてみてください
#### 難点
- Google Drive のアカウントがなくなると、Google　Drive上のデータも削除されてしまう。
- 組織として恒久的にデータ管理するには向かない
- Google Drive上のデータはアクセス管理に適さない
- データのバージョン管理がむずかしい。

## 標準的なツール
- curl
- wget
- scp
    - sshやscpでパスワードの入力を不要にするには、キーの設定をします。
記事の例：
[SSH公開鍵認証で接続するまで](https://qiita.com/kazokmr/items/754169cfa996b24fcbf5)

## pythonでの標準的なツール
- [urllib](https://docs.python.org/ja/3/library/urllib.html)
- [requests](https://pypi.org/project/requests/)
- [Pythonで特定URLの画像ファイルを取得する](https://qiita.com/kusunamisuna/items/3e1fdf0a04130208cbf2)

## local とremoteとのフォルダ構成を比較しながら対話的に操作するには
- 例: [FileZilla](https://filezilla-project.org/) 

- [【FTPソフト】FileZillaの使い方を初心者向けに解説する](https://miyashimo-studio.jp/blog/detail/filezilla-how-to-use/)

## Google Cloud Storage
[【Google Cloud Platformの使い方】GCP Storage にファイルの出し入れ(python3/Web API)](https://qiita.com/XPT60/items/2d362af37a64b6418d0a)

アクセス権の設定を必要とします。
アクセスにはTOKENを必要とします。
認証されたマシンにかぎってアクセスが可能になります。

## DVC(Data Version Control)
[DVC](https://dvc.org/)
[Git LFS からDVC(Data Version Control) に移行した話](https://qiita.com/nonbiri15/items/54c1fac76a8af5e51fdf)


## huggingface に重みデータを登録する
- あなたの実装がOSSであって、重みファイルも公開するものである場合には、huggingfaceに重みデータを登録するということが可能である。
- そうすれば、コミュニティにも寄与できます。

## Google Colab で使うためのデータ
Google Colab はJupyter notebook と同様なインタフェースでpythonを使える環境です。

[Google Colaboratoryでのファイル読み込み方法](https://www.ushiji.online/colab-file-upload)
> Google Colabのはじめ方
> Google Colab ファイル読み込み方法
>1. Google Colabで、Google Driveをマウント
> 2. Google Driveに、対象のファイルをアップロード
> 3. Google Colabで、対象のファイルを読み込んで利用
などが書かれています。

これらを使うことで、Google Driveにあるデータを使ってGoogle Colab 上でnotebook を実行できます。

# チームとして機械学習を行うためには
- 一人の作業PCで動くだけではだめ。
- 結果をすぐに、関係者に共有できることが大事
## 日々の推論の実行環境の案
- 学習済みのファイルがあれば、各人の環境で簡単に推論できるように環境構築を自動化することが必須。
例： git clone して  pip でインストールすれば環境構築できるようにしてしまう。
一連のスクリプトの実行の中で、最新のpretrained-modelをダウンロードするようにしておく
ユーザはそのことを意識しなくても済むように作っておく。
```
git clone git@github.com:someone/foo.git
python3 -m pip install .
```

## 日々の推論の実行環境の案（その２）
- 推論を行う環境を作ったサーバーを用意しておいて、それをネットワーク越しに接続してもらう。
- 例：jupyter notebookのページにネットワーク越しにアクセスしてもらう。
bin/devについて

## はじめに

Rails7 x Tailwind CSSでアプリを作成しようとした際、bin/devコマンドを忘れてCSSデザインが適用されず、原因究明に時間がかかってしまったため記事にすることにしました。

## bin/devって何

Rails7ではrails sコマンドの代わりにbin/devコマンドを打つことで、JavaScriptやCSSがビルドされるようになっています。

:::note 
ビルドとは

JSやCSSはいろんなファイルに分散して書いてある。これらを本番環境に持っていく際、下記の作業を行うことを「ビルド」という

- minify：インデントやコメントを取り除く
- transpile：新しい規格を古い規格に変換（新しい規格に対応していないブラウザがあるため）
- bundle：色んなファイルや外部ソースに散っているコードを集めて一つのファイルにまとめる

参考：[なぜJavascriptにビルドが必要？フロントエンド開発の知識をアップデートしよう](https://blog.tyspine.com/why-build-javascript/)

:::

bin/devの中身を見てみると、

```ruby
#!/usr/bin/env sh

if gem list --no-installed --exact --silent foreman; then
  echo "Installing foreman..."
  gem install foreman
fi

# Default to port 3000 if not specified
export PORT="${PORT:-3000}"

exec foreman start -f Procfile.dev --env /dev/null "$@"
```

「gem foremanが入ってなければインストールして、そのforemanでProcfile.devを実行する」というような内容です。

## foremanって何

https://github.com/ddollar/foreman

> Using foreman you can declare the various processes that are needed to run your application using a `Procfile`.
> 

Procfileというファイルに設定を書き込むと、複数のプロセスをまとめて立ち上げてくれるようなツールらしい。

## Procfileって何

アプリケーション直下に、Procfile.devというファイルがあります。development環境用のProcfileというところでしょうか。

```ruby
web: bin/rails server -p 3000
js: yarn build --watch
css: yarn build:css --watch
```

書き方は下記の通り、`プロセス名: コマンド`という形式になっています。

> A Procfile should contain both a name for the process and the command used to run it.
> 
> 
> ```
> web: bundle exec thin start
> job: bundle exec rake jobs:work
> ```
> 
> https://ddollar.github.io/foreman/#PROCFILE
> 

Procfileの中で、rails sやJS、CSSのビルドが行われているのがわかります。

ちなみにここのbuildやbuild:cssはpackage.jsonで定義されています。

```ruby
  "scripts": {
    "build": "esbuild app/javascript/*.* --bundle --sourcemap --format=esm --outdir=app/assets/builds --public-path=/assets",
    "build:css": "tailwindcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css --minify"
  },
```

## まとめ

bin/devコマンドを実行すると、Procfile.dev内で定義された`rails s`とJS、CSSのビルドをforemanが実行していることがわかりました。

## 参考

[Rails 7.0 + Ruby 3.1でゼロからアプリを作ってみたときにハマったところあれこれ - Qiita](https://qiita.com/jnchito/items/5c41a7031404c313da1f)

[[rails7] bin/devの役割とその仕組み - Qiita](https://qiita.com/sinke_123/items/20f93bdcf7cefce11da9)
[vscode]文字コードの設定を変更する

vscodeで文字コードを変更したときの手順をまとめる。

ファイルをクリックし、「ユーザ情報」⇒「設定」を選択。
![タイトルなし1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759593/e8d61747-3c69-c86b-68ab-6a76a22f8687.png)



設定の検索に「encoding」と入力し、変更した文字コードを入力する。
![タイトルなし２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759593/0be00130-284a-d3b2-db2b-839b96d3853d.png)



以上。
vagrant destroy と vagrant box コマンドの違いを整理した

# vagrantとは
詳しくは下記の記事を読んでください。
https://t-cr.jp/article/5a179bc8febae3aa 

【vagrant】コマンド一覧
https://qiita.com/oreo3/items/4054a4120ccc249676d9

# 【vagrant destroyとvagrant box removeコマンドの違い】
**vagrant destroy:**
Vagrantで作成した**特定の仮想マシンを削除する**ためのコマンドです。
この操作は、仮想マシンが占有するリソース（ディスク、メモリ、ネットワーク設定）を解放しますが、ボックスは削除しません。

**vagrant box:**
ボックスは**仮想マシンを作成するためのテンプレート**であり、仮想マシンを作成する際に使用されますが、ボックス自体は仮想マシンとは別に管理されます。
ボックスを削除しても、すでにそのボックスから作成された仮想マシンには影響しませんが、新しい仮想マシンを作成する際にそのボックスを使うことはできなくなります。


# 【仮想マシンを削除するまでの手順】

* 全仮想マシンの一覧を表示する
```rb
$ vagrant global-status

id       name              provider   state    directory                        
------------------------------------------------------------------------------------
12abcde  vagrant1  virtualbox running  C:/Users/xxx/xxx/vagrant
34fg5hi  vagrant2  virtualbox poweroff  C:/Users/xx/xxx/vagrant
```
* 仮想マシンの停止
仮想マシンが「running」の場合、vagrant destroyコマンドは仮想マシンを**停止**した後に削除します。
```rb
$ vagrant halt <id>
```

* 仮想マシンを削除する
```rb
$ vagrant destroy <id>
```
* 確認プロンプト
vagrant destroyコマンドを実行すると、仮想マシンを削除するかどうかの確認プロンプトが表示されます。
「y」を入力して確定します。
```rb
vagrant<番号>: Are you sure you want to destroy the 'vagrant<番号>' VM? [y/N] y
```

* 強制削除
確認プロンプトをスキップして強制的に削除したい場合は、-fオプションを使用します。
```rb
$ vagrant destroy <machine_id> -f
```

# 【仮想マシンを作成するためのテンプレートを削除するまでの手順】
* boxの一覧を表示
```rb 
$ vagrant box list

ubuntu/test1    (virtualbox, 1708.01)
ubuntu/test2    (virtualbox, 1353.1.0)
```
* 指定されたボックスを削除するコマンド
```rb
$ vagrant box remove ubuntu/test1
 ```

* 仮想化プロバイダを指定して削除する場合

```rb 
$ vagrant box remove ubuntu/test1 --provider virtualbox
```

* 特定のバージョンを削除する場合
*リストされたボックスにはバージョン番号が0としか表示されていないため、通常はバージョンを指定する必要はありません。
```rb 
$ vagrant box remove ubuntu/test1 --box-version 0
```
Finaleが終了だって？

やられました・・・

せっかく気合を入れて、浄書を習得し直そうとしていた矢先・・・

「Doricoへの乗り換えを勧めます」って、いや、そう言うことじゃないでしょ！
そのうちクロスグレード版を買おうかな、と、ちょうど考えてはいたけれど、それは浄書用のソフトウェアとしてではなく、楽譜作成にちょっと力が入っているDAWのような意味合いで考えていただけだから。

あぁ～、どうしようかね。
Sibeliusへの乗り換えは考えてません。今のところ。

Finaleは使いづらいから、Sibeliusでしょ？　MuseScoreでしょ？って言う人を結構見かけますが、そう言うことではないんだよね。
まぁ、確かに操作性は良いとは言えない。　だけど、他のソフトウェアがFinaleみたいにどんな楽譜でも作ることが出来るの?

もしそうなら、そんなに躊躇はしないけどね。

一晩悶々として、考えましたが、ユーザー側としていろいろ思うところはありますが、出版業界は大丈夫なのだろうか？
楽譜の浄書として問題アリでも今まで通り、販売するのかな？
CakePHP4.xのアプリをCakePHP5にアップグレードする　エラー解消編

## はじめに
CakePHP5にアップグレードしたところまではいいが、ここからはひたすらエラーを解消する作業になります
ここまでの手順は
とりあえずアップグレード編
にまとめてあります

### env()エラー
まず遭遇したのがこちら
PHP Fatal error: Uncaught Error: Call to undefined function env() 
です

https://zenn.dev/snake12379/articles/fc7146484152cc

こちらのおかげで解消
config/bootstrap.phpの　33行目辺りに
```
require CAKE . 'functions.php';
```
を追加しました

### RequestHandlerComponentエラー
Component class `RequestHandlerComponent` could not be found.
って言われちゃいました
どうやら無くなったようなので、AppControllerから
```
$this->loadComponent('RequestHandler');
```
をコメントアウトしました
```
//$this->loadComponent('RequestHandler');
```

### DebugKitエラー
認証のためAuthenticationプラグインを使用しています
こちらがルーティングエラーになり、DebugKitが使えなくなっていました

こちらを
```
        $service->setConfig([
            'unauthenticatedRedirect' => Router::url(['controller' => 'users', 'action' => 'login']),
            'queryParam' => 'redirect',
        ]);
```
こちらに
```
 $authenticationService = new AuthenticationService([
        'unauthenticatedRedirect' => Router::url('/users/login'),
        'queryParam' => 'redirect',
    ]);
```
https://book.cakephp.org/5/ja/tutorials-and-examples/cms/authentication.html#id3

### config/app.phpを修正

Deprecated: Since 5.0.0: Using `false` to disable logging scopes is deprecated. Use `null` instead. 
と言われちゃいました

config/app.phpの
```
/*
     * Configures logging options
     */
    'Log' => [
        'debug' => [
            'className' => FileLog::class,
            'path' => LOGS,
            'file' => 'debug',
            'url' => env('LOG_DEBUG_URL', null),
            'scopes' => false,
            'levels' => ['notice', 'info', 'debug'],
        ],
        'error' => [
            'className' => FileLog::class,
            'path' => LOGS,
            'file' => 'error',
            'url' => env('LOG_ERROR_URL', null),
            'scopes' => false,
            'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'],
        ],
```
の'scopes' => false,を'scopes' => null,に修正します

### Filesystemが無い
Class "Cake\Filesystem\File" not found
ファイル関連のclassが無いといわれます

https://book.cakephp.org/5/ja/core-libraries/file-folder.html

上記を見ると廃止になったわけではなさそう
vender/cakephp/src　を確認すると以前はあった「Filesystem」というフォルダがなくなっています
CakePHP4のvender/cakephp/srcからFilesystemフォルダをコピーしてとりあえず解決

追記：
削除されてるんですね

https://book.cakephp.org/5/ja/appendices/5-0-migration-guide.html#filesystem

>Filesystem
Filesystem というパッケージは削除されました。 Filesystem というクラスは Utility のパッケージに移動されました。

ということなので、
use Cake\Filesystem\File;
を
use Cake\Utility\Filesystem;
に置き換えて書き換えるか、当てにしないで自前で自前で処理するかって感じでしょうか？


### Entity::has()を修正
has()で空かどうかを判定していましたが、ちゃんとhasValue()で判定するようにしました

https://book.cakephp.org/5/ja/orm/entities.html#id4

## 終わりに
まだまだテストしていくうちに出てきそうですが、とりあえず一旦終了
出てきたら追記します