OmniAICreator/Qiita-1.07M huggingface dataset:
CSSがパワーアップ！:has()セレクタでフォームバリデーションを視覚化する


# 目次
1. [はじめに](#introduction)
2. [CSS :has() 擬似クラス](#has-pseudo-class)
3. [フォームバリデーションの視覚化](#visualizing-form-validation)
4. [注意点](#caution)
5. [まとめ](#conclusion)

## <a name="introduction">1. はじめに</a>

Web開発の中で、フォームのバリデーションは重要な役割を果たします。ユーザからの入力が期待通りの形式であることを確認し、不適切なデータの送信を防ぐことができます。そして、それらのバリデーション結果をユーザに視覚的にフィードバックすることで、ユーザ体験を向上させることができます。

本記事では、CSSの`:has()`擬似クラスを利用して、フォームバリデーションの結果を視覚的に表示する方法を紹介します。

## <a name="has-pseudo-class">2. CSS :has() 擬似クラス</a>

`:has()`はCSSの擬似クラスで、引数として渡されたセレクターに該当する要素が一つ以上の要素に一致することを表します。

```css
a:has(> img) {
  border: 1px solid black;
}
```

上記の例では、`<a>`タグが`<img>`タグを直接子要素として含んでいる場合に、その`<a>`タグに対して黒い境界線を適用します。

## <a name="visualizing-form-validation">3. フォームバリデーションの視覚化</a>

HTMLの`<form>`要素内の`<input>`要素のバリデーション結果を視覚化するために、以下のようなCSSコードを使用することができます。

```css
form:has(input:invalid) {
     background: red; 
}

form:not(:has(input:invalid)) {
     background: green 
}
```

1. `form:has(input:invalid)`： このセレクタは、`<form>`要素内に無効な（バリデーションルールに適合しない）`<input>`要素がある場合にマッチします。マッチすると、その`<form>`要素の背景色が赤になります。
2. `form:not(:has(input:invalid))`： このセレクタは、`<form>`要素内に無効な`<input>`要素がない場合、つまり全ての`<input>`要素が有効な（バリデーションルールに適合する）場合にマッチします。マッチすると、その`<form>`要素の背景色が緑になります。

## <a name="caution">4. 注意点</a>

このコードは`:has()`擬似クラスを使用しているため、このセレクタがサポートされているブラウザでのみ動作します。また、バリデーションルールは`<input>`要素の属性（例えば`required`や`pattern`など）によって定義されます。

## <a name="conclusion">5. まとめ</a>

CSSの`:has()`擬似クラスを利用すると、ユーザがフォームに無効なデータを入力した場合に視覚的なフィードバックを提供することが可能になります。これにより、ユーザ体験の向上に寄与することができます。ただし、`:has()`擬似クラスのブラウザ互換性を確認し、適切なバリデーションルールを設定することが重要です。
間違えて直接アプリファイルを削除した時の対処法

# はじめに

当然ですがアプリをゴミ箱に入れたからと言ってアンインストール出来るわけではありません。
ゴミ箱がちょっと大きくなるだけです。
アプリを消したい時は必ず設定のアプリ項目から「アンインストール」をしましょう。

人間なら誰しも過ちは犯します。
アプリをアンインストールせず、間違えてアプリ関連ファイルを削除してしまうなど、
親を殴ったり、子犬を蹴ったりすることに比べれば非常に些細な過ちでしょう。

# もし過ちを犯してしまった場合は
中世なら貴方は処刑されていたでしょう。
ですがここは現代日本。悪いことをしても高々ネットに晒されるくらい。

ここでは、わたくしは迷える子羊に救いを与える女神として以下の対処法を教えます。

# 対処法

まずレジストリエディターを開きます。
　1. 「Windowsキー + R」を押して「実行」ダイアログを開きます。
　2. 「regedit」と入力して「OK」をクリックします。
レジストリエディターが開かれたら、次の場所に移動します。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall


Uninstallキーの下で当該アプリに関連するエントリを探します。「DisplayName」に名前を含むことがあります。

該当するエントリを見つけたら、右クリックして「削除」を選択します。

これで、手動で削除したDockerに関連するエントリがレジストリから削除されるはずです。
窓から外を御覧なさい。
暗雲は明け、太陽の光が貴方の眼球を掠め取るでしょう。

その後は、普通にアンインストールしてみてください。
Notion APIでロールアップのカラムの検索をする


https://www.npmjs.com/package/@notionhq/client こちらの公式のSDKを使って試していて、

学籍番号で学生の検索をかけようとした時の話題です。

## 文字列プロパティからロールアップになる現象

元々は文字列で直接入ってましたが、管理する上でデータ定義がされていくとDBが分かれてリレーション/ロールアップになっていくのは必然な気もします。

元々は以下のような指定で学籍番号にPEO05が含まれたら検索するといった検索をしていました。

```js
const res = await notion.databases.query({
    database_id: studentDBId,
    filter: {
      or: [
        {
          property: '学籍番号',
          rich_text: {
            contains: "PEO05"
          }
        }
      ],
    },
});
```

データベースの正規化によってDBのプロパティが文字列ではなく外部のDBを参照するような形に変更になり、現状は以下のようなDBになっています。

> ![スクリーンショット 2023-08-04 17.09.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/32666ae0-2294-fead-4492-6a79d384bf30.png "スクリーンショット 2023-08-04 17.09.12.png")

## プロパティエラー

この状態で同じプログラムで検索をすると

```
@notionhq/client warn: request fail {
  code: 'validation_error',
  message: 'The property type in the database does not match the property type of the filter provided: database property rollup does not match filter text'
}
```
> 
データベースのプロパティ タイプが、指定されたフィルターのプロパティ タイプと一致しません: データベース プロパティ ロールアップがフィルター テキストと一致しません

まぁそうなります。

## ロールアップ指定の検索

検索するときのJSONはプロパティの種類によって検索の仕方が異なります。

https://developers.notion.com/reference/post-database-query-filter#rollup

こちらに記載がありました。

```js
{
  "filter": {
    "property": "Related tasks",
    "rollup": {
      "any": {
        "rich_text": {
          "contains": "Migrate database"
        }
      }
    }
  }
}
```

といった感じです。

```js
const res = await notion.databases.query({
    database_id: studentDBId,
    filter: {
      and: [
        {
            "property": "学籍番号",
            "rollup": {
                "any": {
                    "rich_text": {
                        "contains": "PEO05"
                    }
                }
            }
        }
      ],
    },
});
```

これでうまく情報取得ができました。

## 所感

結構めんどいです。検索するときくらいプロパティのタイプ関係なくこれくらいの書き方でいけるといいのに... 

```js
{
  property: '学籍番号',
  text: "PEO05"
}
```

↑で検索は現状のクライアントではできなさそうです。この指定だとバリデーションエラーになりますので悪しからず。
ゼロトラストアーキテクチャ


デジタルプラットフォーム構築事業報告書
https://www.meti.go.jp/meti_lib/report/2020FY/000143.pdf


NIST Special Publication 800-207 ゼロトラスト・アーキテクチャ
https://www.pwc.com/jp/ja/knowledge/column/awareness-cyber-security/assets/pdf/zero-trust-architecture-jp.pdf


ゼロトラストに向けての下地作り、Azure AD Connectの構築
https://tech.buysell-technologies.com/entry/adventcalendar2022-12-18
Windows 11 のタスクバーに秒表示を追加する。

# これは何？
Windows 11 にて、秒までの確認を常にしたい~~私みたいなせっかちな~~人向けの設定です。

# 設定方法
下記のレジストリを設定します。

``` regedit.exe
Key   : HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
Name  : ShowSecondsInSystemClock (DWORD)
Value : 秒数表示なし / 1 : 秒数表示あり
```

と思ってたんですが。

# かなしいけつろん
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/2a9804ae-a722-4fc3-de8d-651ecf2d80d4.png)


いつのまにか普通に設定に追加されてました。ウカツ！

# さらなるけつろん
2024/11/27 追記
いつのまにか移ってました。そういうとこやぞ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/8662a6ab-999c-ca43-ceff-49f7a2c74940.png)
メモリをケチるCubeIDEにメモリを食わせたい

# 環境
windows11
STM32CubeIDE ver1.11.0

# やりたいこと
メモリが余っているのにメモリをあまり使わず、なおかつ重いCubeIDEを軽くしたい

# やること
以下教えてくださったT先輩より引用
>(cubeIDEクソ重いという発言に対して)
>
>cube ideとか(特にmplabx)はjvmのメモリー割当を見直すと早くなるよ。
>
>cube ideのもととなるeclipseはJAVAの仮想マシン(JVM)で動くように作られている。 
なのでJVMで使用するメモリー割当が少ないとまともに動かない。

ということでメモリ割り当てをいじります。

# 手順
設定ファイルを探し当てます。
~~アプリ内から設定できる…と思うのだが設定画面が英語オンリーで断念~~
デフォルトなら`C:\ST\STM32CubeIDE_1.11.0\STM32CubeIDE\stm32cubeide.ini`にあるはず。
バージョン番号は各自の環境に合わせて読み替えてください。

`stm32cubeide.ini`を開くとこんな項目があるはず(数字は違うかも)
```
(中略)

-Xms256m
-Xmx1024m

(中略)
```

ここの数字を好きに設定して保存。以上。
気になる人はタスクマネージャー眺めながらSTM32と戯れてみましょう。
Linuxmintのアップデートマネージャーで、nvidia-firmwareをアップデートしたら画面が吹っ飛んだので修復した話

Linuxmintのアップデートマネージャーで、nvidia-firmwareをアップデートしたら、画面がブツッと真っ暗になり入力もしてるんだかよくわかんなくなってしまいました。

前もやったけど復旧の仕方を忘れてしまうので、
うまく動くようになったやりかたメモ。

## 以下手順

### 1) リセットボタンが効かない時のための事前に設定

ctrl+alt+deleteが効かない場合にリセットできるように設定

```terminal
xed admin:///etc/sysctl.d/10-magic-sysrq.conf
#または
sudo micro /etc/sysctl.d/10-magic-sysrq.conf
```

この変更する

```
#kernel.sysrq = 176
kernel.sysrq = 1
```

変更したら再起動

いざ、固まってどうしようもなくなったら、以下の手順でゆっくりキーをタイプ

Ctrl+Alt+PrintScr
↓
Ctrl+Altは押し続け
PrintScrは離して、
↓
R
↓
E
↓
10秒待つ (またはビジーカーソルが終わったら)
↓
I
↓
10秒待つ (またはビジーカーソルが終わったら)
↓
S
↓
画面に「Emergency Sync complete」と表示されるか
10秒待つ (またはビジーカーソルが終わったら)
↓
U
↓
B (Bで再起動、またはOで終了)


### 2) 事前の設定してない場合

おとなしく電源を落として再起動しましょう


### 3) 再起動しても止まってしまうので

もう一度再起動して、BIOS画面が消えた瞬間にshiftキーを連打して、grubの起動セレクトメニューを表示させる

メニューが表示したら、
Advanced options for Linux Mint 21.2 Cinnamon を選択
(※使用環境により表示が異なります)

起動できるカーネル一覧が表示されるので、

```terminal
Linux Mint 21.2 Cinnamon, with 5.15.0-78-generic
Linux Mint 21.2 Cinnamon, with 5.15.0-78-generic (recovery mode) 
```
セレクトメニューの (recovery mode) が付いてるカーネルを選択。殆どは上から2番目かも
(※使用環境により表示が異なります)

Recovery Menuが出るので、rootを選択

無事コマンドプロンプトが使えるようになります。


### 4) 最近アップデートしたパッケージ一覧を表示する

```terminal
cat /var/log/apt/history.log
```

すると、先程アップデートマネージャーでアップデートしたパッケージが表示されます。
historyに載っていた、

```
Install: nvidia-firmware-535-535.06.05:amd64 ...
```

をもう一度installしてみます。

```
apt install nvidia-firmware-535-535.06.05
```

としたら、いくつか、
half-configured
と表示されており、dpkg --configure -aしましょうとか書いてあります。

指示通りにします。

```
dpkg --configure -a
```

すると、パッケージの設定が無事完了したようです。


### 5) 再起動

```
reboot
```

で、再起動したら、無事動くようになりました。
ありがとうございます。
ラズパイ3B+をUSBブートしたい

# 環境
raspberryPi3B+(2017年製)
ubuntu desktop 23.04(64bit)

なぜかラズパイOSを受け入れてくれないんですよね(固まる)
# 状況
OSを書き込んだUSBメモリを刺すも沈黙
どうもファームウエアが古くてUSBブートに対応してないっぽい

# 参考資料
1.これでほとんど行けた
https://note.com/hitoshiarakawa/n/n4fe3efc9c2be

2.上で出たエラー(command not registered)を解決してくれた
https://qiita.com/KEINOS/items/060b5bf3b99e24be4a63

３.ファームウエアのアップデート
https://qiita.com/takeaship/items/5861660c11d9d434368f


# 手順
## 前準備

・ファームウエア更新するためのSDカードを用意(OSを書き込んでおくこと)
・USBメモリ(OSを書き込んでおくこと)
・電源その他諸々

・仮想環境ubuntu(あると楽…かもしれない。おそらく要らない。)
~~ぶっちゃけ趣味。~~
ラズパイ側で作成したファイルを見れる=データのバックアップをwindowsPCでできるのであると安心かもしれない。



## ファームウエア更新
```
sudo apt update
```
これで更新できました。

`sudo rpi-update`は非推奨っぽいです。

## 参考文献に沿って設定

文献1をベースに、`vcgencmd not registed`吐かれたら文献2に従って`libraspberrypi0`パッケージ入れましょう.

## 起動
SDカードを抜いたうえで適当なUSB端子にUSBメモリを刺せばOK。
なんか動かないときはちょっと待ちましょう。
動かないときはキーボードやマウスを抜いたり刺す場所を変えれば動くはず…。

~~5年前のラズパイを今更USBブートするとかいう記事正直要るんか？~~
Xcode15&iOS17でウィジェットに余白ができて表示が小さくなった。

Xcode15betaでウィジェットを確認した所、余白ができて表示が小さくなっていましたので解決方法をご紹介します。
（Small・Medium・Largeウィジェット共通）

#### ウィジェットのプレビュー画面比較
Xcode14：ウィジェットのプレビュー画面
![スクリーンショット 2023-08-04 15.59.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2370083/7c3eccec-1788-c5a5-50e3-062b8b6cd304.png)
Xcode15beta：ウィジェットのプレビュー画面
![スクリーンショット 2023-08-04 15.34.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2370083/63176928-7f14-b815-2d6e-88fabd1717a0.png)

:::note warn
なんか変な余白ができている…
:::

#### シミュレーターでの比較
Xcode14
![スクリーンショット 2023-08-04 16.01.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2370083/3a584f96-4cce-9afd-a759-61b468f5a98a.png)
Xcode15beta
![スクリーンショット 2023-08-04 15.29.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2370083/190b494a-fed7-acbf-29f7-a594cb5921ed.png)

:::note warn
実際にビルドしてみると余白が出来た分、ウィジェットの表示が小さくなっていた。
:::

## 解消方法
どうやらiOS17の場合、変な余白ができるらしい。
なのでiOS17の場合は、余白を無効にする処理が必要。
https://developer.apple.com/documentation/swiftui/widgetconfiguration/contentmarginsdisabled()

各ウィジェットに共通で入れたいのでextensionで以下の処理を準備する。
```swift
extension WidgetConfiguration {
    func contentMarginsDisabledIfAvailable() -> some WidgetConfiguration {
        if #available(iOSApplicationExtension 17.0, *) {
            return self.contentMarginsDisabled()
        } else {
            return self
        }
    }
}
```

Small・Medium・Largeのウィジェットに共通で追加する。
```swift
 var body: some WidgetConfiguration {
     .contentMarginsDisabledIfAvailable()
 }
```
Notionの関数(Formula)で、日付を便利に扱う

Notionのタイムラインビューとカレンダービューを、ちょっと便利に使うための関数の例を二つご紹介します。
[デモページ](#デモページ)も記事の後ろに用意しています、合わせてご覧ください。

## 1. テンプレートから作成したアイテム（繰り返しによる自動作成を含む）を、自動でタイムラインビュー上に配置する
テンプレートからアイテムを作成した際、日付を作成日にしてタイムラインビューに表示したいことはよくあるケースと思います。
しかし、そのためだけに作成日時プロパティをタイムラインビューに指定してしまうと、日付を変更したい時に困ります。
※変更方法は補足として後述 => [タイムラインビューで使用する日付プロパティを変更する](#タイムラインビューで使用する日付プロパティを変更する)

解決方法としては、作成日時と手動で操作可能な日付を両方とも用意し、その二つを関数で切り替えるというものがあります。
- 手動で日付を指定した場合はそちらを優先
- 指定されていない場合は、作成日時を参照する

```js
if(empty(prop("Date")), prop("Created time"), prop("Date"))
```

### 設定方法
1. 関数プロパティを追加する
![スクリーンショット 2023-08-04 17.08.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3468968/39705c41-1ef5-935e-f968-16232df86150.png)
1. 上記の関数を設定する
![スクリーンショット 2023-08-04 17.10.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3468968/57f5031c-9e04-6878-ddf4-1a082f5a84c4.png)


注意点として、タイムラインビュー上やカレンダービュー上で日付をマウスのドラッグで変更できなくなります。
これは、ビュー上で指定されているのはあくまで関数プロパティであり、手動で変更可能な日付(今回は`Date`)はビュー上には直接指定されていないためです。


## 2. 四半期単位でアイテムを分類する
アイテムを四半期ごとで分類したい場合、`formatDate`関数で直接指定可能です。
`formatDate`関数は、PostgreSQLの書式を使用しているようで、`Q`で四半期を表示してくれます。
https://www.postgresql.jp/document/15/html/functions-formatting.html

```js
formatDate(prop("Display Date"), "YYYY Q\\Q")
```
=> 投稿日現在の場合、`2023 3Q`と表示されます。

![スクリーンショット 2023-08-04 17.12.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3468968/051e1152-4ca7-acc7-500e-71fa9b7bc1ff.png)

## 補足
### デモページ
今回使用したデモページはこちらです。
https://csc-knowledge.notion.site/csc-knowledge/d2f6985382cc43ae90135ba76aef971a?v=223f85c9a0cd46458bfbd99b75e12645

### タイムラインビューで使用する日付プロパティを変更する
1. レイアウト設定画面を開く
![スクリーンショット 2023-08-04 16.45.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3468968/4516f522-5a8d-bc96-d67f-2ea33c918ca6.png)
1. 「タイムラインの表示基準」で、プロパティを選択
![スクリーンショット 2023-08-04 16.49.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3468968/73f8dfe3-0423-4704-4a04-f0e006f32463.png)
兼業フリーランスエンジニアの収入と単価公開（2023）

先日「稼ぎ方」と「収入」に関するご相談を頂いたので、自分（2023年）の単価と収入について、ざっとまとめてみました。稼働割合は「ソフトウェア開発業」と「業務委託」で1：1くらい。

## ソフトウェア開発（受託開発）
契約種別：請負、準委任（SES）として受けるとき、法人で請けるときなど様々です。
業務内容：PO（開発責任者）として、営業・契約⇒体制（チーム）作成⇒開発⇒納品⇒（保守）
必要スキル：責任能力
報酬：チーム作ってやることが多く、最後に手元に残った分（受注額 - 経費）が自分の報酬になります。
平均収入：2023手元予測は1000万くらいで、受注規模は1案件あたり数十万～3000万くらい。

## 業務委託
１．WEB開発の統括PM
契約種別：準委任契約
業務内容：プロジェクトのマネージメント業務、各相談
必用スキル：管理,経理,法務,AWS,WordPress,PHP,Go,Vue,React,Java
報酬：時給6800円
平均収入：40万円/月

２．業務アプリ開発のPM/PL
契約種別：業務委託
業務内容：顧客折衝、マネージメント、プロジェクトリード
必用スキル：管理,Azure,C#,DBA
報酬：固定30万円/月（時給10000円×30H稼働相当）
平均収入：30万円/月

３．エンジニア紹介と管理
契約種別：業務委託（管理報酬）
業務内容：人材・ベンダ紹介と稼働管理と調整、経理業務（月末月初のみ）
必用スキル：営業,管理,経理,法務,人脈
報酬：稼働単価✖0～5%、毎月固定1人月3万円など
平均収入：30万円/月

４．サイト保守
契約種別：準委任契約
業務内容：サイト保守業務（インフラとアプリ改修など）、開発作業あり
必用スキル：AWS,PHP
報酬：時給6000円
平均収入：2万円/月

５．教育
契約種別：準委任契約
業務内容：学生のソフトウェア開発教育を目的としたプロダクト開発業務とコーチング
必用スキル：AWS,Python
報酬：時給5000円
平均収入：2万円/月

６．アドバイザリー
契約種別：業務委託契約
業務内容：コンサル会社の技術、体制相談（MTG参加のみ）
必用スキル：アドバイザリ,英語,RPA,Python,C#(UiPath)
報酬：固定10万円/月
平均収入：10万円/月

７．Iot系開発支援
契約種別：準委任契約
業務内容：モノづくり（IOT、ハード）に関する相談、ベンダ調整（製造とIT）、申請支援
必用スキル：AWS-Iot,制御,RaspberryPi,Nodered,Kotlin
報酬：時給6000円
平均収入：3万円/月

８．情報システム部門（社内SE）の代行
契約種別：業務委託契約（保守）
業務内容：経理システム、オフィス系などの保守作業とヘルプデスク
必用スキル：AzureAD,VB.NET,Office,PHP,サポート対応力
報酬：固定費10万円＋作業時給5500円
平均収入：10万円/月

９．スポット相談
スポットの仕事相談（10分～1日）、無料～10万円/回でゲリラ的な収入
平均収入：2万円/月

## その他
「不動産・株」などの現金収入と趣味でやってる「農業・狩猟」や「田舎固有の大量おすそ分け」があります。

## まとめ
今の時代は、色々な選択肢（稼ぎ方）があると思います。

エンジニアからの収入相談については、エンジニアとしての`スキル`や`働き方`も大事なのですが、前提となるお金（経済）の基礎知識やコスト意識（業務価値）をもっておくと、いい感じになるので、「資産運用（投資価値）」や「家計管理（採算）」とかをオススメしたりもしてます。

僕自身は「楽しさ（人間関係含む）＞学び＞収入」の優先順で仕事しており、ライフステージによって変わってきてます。
共通して大事にしてるのは日々のチューニング「契約、人、技術の調整と選択肢を多く持つ」「市況と時代にアップデート＆予見」とかでしょうか。自身でもこのあたりは、日々勉強中です。
s3とslackに同じファイルをアップロードするとエラーになる原因と対処法

# 発生したエラー
下記のコードを実行すると```Slack::Web::Api::Errors::ParsingError (parsing_error):```になった。
```sample_controller.rb
def send_file
    file = params[:file]
    # s3にアップロード
    s3 = Aws::S3::Client.new
    s3.put_object(
      bucket: AWS_S3_BUCKET,
      body: file,
      key: file_path,
    )
    # slackにもアップロード
    client = Slack::Web::Client.new
    client.files_upload(
        channels: channel_id,
        file: Faraday::UploadIO.new(file.tempfile, file.content_type),
        initial_comment: 'ファイルです'
      )
end
```

# 結論：ファイルの読み込み位置
s3.put_objectでファイルの読み込みが行われ、slack apiでfiles_upload実行時にはファイルの読み込み位置が終端になっているのが原因。

そのため、slackのアップロード処理の前に```file.tempfile.rewind```で読み込み位置を先頭に戻すことで解決した。

```p file.tempfile.read```で出力すると空文字が返ってきたことで気づくことができた。
LinuxmintでDockerがアップデートマネージャーからアップデートしなかったのをするようにした話

LinuxmintでDockerがアップデートしなかったのでメモ

## 以下手順
LinuxmintでDocker公式の手順通りに進めて、途中1箇所だけ修正します。

公式のインストール手順
https://docs.docker.com/engine/install/ubuntu/

Installation methods
Install using the apt repository
Set up the repository

の3つめ、
3. Use the following command to set up the repository:
が以下のようになっています。

```terminal
echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```

ここがLinuxmintだと動かなくなる原因です。
. /etc/os-release && echo "$VERSION_CODENAME"
を実行すると、Linuxmintのコードネームが表示されてしまいます。

```terminal
. /etc/os-release && echo "$VERSION_CODENAME"
victoria
```

ですので、ここを改変。
Linuxmint公式でバージョンを確認すると
https://linuxmint.com/download_all.php
Ubuntu Jammyに当たります。

なので、公式のコマンドを書き換えます。

```
echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  jammy stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```

そして、アップデートマネージャーのソフトウェアソースの、追加のリポジトリの、
Docker / の項目が jammy stableに変わっていることを確認。

これで、無事アップデートマネージャーからDockerもアップデートできるようになりました。

しかし、この修正でDockerをアップデートしたおかげで、rootlessモードが動かなくなってしまい困ったのはまた別の話ですが、前回の記事に記載しました。
ASUS Chromebook CX34 Flipを一週間以上使ってみての評価

[前回の記事](https://qiita.com/zyake/items/7826ea22f1671c2653d1)から一週間以上経過しての気付き(と言う名のポエム)です。

## 応答性が高い

現在、以下の2つのWindows PCを保持しており、特にHPのEliteBook 830 G6は今現在でも業務で利用していますが、メモリ容量が倍違うにも関わらず、明らかに応答性が低下する場面が少ないです。

- HP EliteBook 830 G6
   - Windows 10, Core i5 8365U, 16 GiB memory, 256 GiB SSD(PCIe)
- Dell XPS13 9380
   - Windows 11, Core i5 8265U, 8 GiB memory , 256 GiB SSD(PCIe)

Windowsではsvhost.exeにCPUパワーが取られて応答性が低下することもありますし、特にCPU、ストレージの負荷が高くないにも関わらず応答性が低下する場面があります。
※Resource Monitorを見てもCPU、メモリ、ストレージのリソースに余裕があるときもあるので、原因がわからない...
また、再起動やChromeOSのアップデートも高速であることから全体的にストレスが少ないです。

## Androidアプリをそのまま使える

以下のようなAndroidアプリをそのまま利用できるのが便利です。
※意外にも(?)Androidアプリへの依存度が高いです
```
GMail, JetAudio+, Skype, Kindle, Prime Video, Prime Music, Panecal Plus, BingChat, Netflix, Message
```
 
いずれもAndroidの膨大なユーザー数に支えられてUIや機能が作り込まれており、タッチ操作も問題なく実施できます。
Androidでゲームを殆どやっていませんが、簡単に動作検証した限りではCOD Mobileのデモはフルスクリーンかつタッチ操作で問題なく操作可能でした。
※ゲームは動く、動かないの差が激しいようなので事前に要確認

SMSなのでAndroidスマホでしか使えなさそうな「Messageアプリ」に関しても、スマホとのペアリングによりChromebookで快適に操作できるのも地味に便利です。

 ## タッチ操作との親和性が高い

Windowsではタブレット向けのタッチ操作に対応したUIのアプリが少なく、以前Surface Pro 4を利用していた際にもブラウザと一部のアプリ以外では有効活用できているとは言えない状況でした。
※2023年現在でもWindowsのアプリはマウス、キーボード操作前提のものがほとんど
また、Windows11ではLive Tile/Continuumが廃止されてしまったこともあり、タッチ対応は宙ぶらりんな状態です。

一方でChromeOSではタブレットモード時にはAndroidに似たアプリが常に全画面表示になるUIに変化し操作性が洗練されていること、また対象とするアプリがWeb(ブラウザ, アプリ) + Androidアプリであることからタッチ操作で困ることはあまりなく、タッチ操作との親和性が高いです。

## Android連携が便利

Androidへのログインでロック解除はPINコードの入力よりも高速かつお手軽ですし、Androidで取得した写真や開いているファイル、Webページに即アクセスできるのも便利です。
動きがぎこちないことやIMEの動きが怪しいですが、Androidのアプリを直接操作する機能も、有用なユースケースがあるかもしれません。

## OSのシェル/GUIは作り込まれている

各種ショートカットキーやウインドウの整列、検索、ファイル・エクスプローラー、設定アプリ、タスクバー、タブレット・モードでの操作、通知領域等、OSとしての基本的な操作は(非常にシンプルではありますが)、作り込まれています。

## IME周りは若干改善が必要

Linux環境でIMEが動作しない問題、複数ウインドウのアプリにて、別ウインドウの移動時にIMEの切り替えを実施できない問題があるようです。
LinuxアプリでのIME対応については特定のアプリに限りベータ版が出ています(Watch機能はなさそう？)
[Issue 826614: Input Method support / integration with Linux app](https://bugs.chromium.org/p/chromium/issues/detail?id=826614)

IME自体はGoogle日本語入力(?)そのままなので、変換効率などは問題となっていないです。

まとめると、各種GUIの作り込みやAndroidのエコアシステムの活用、Androidスマートフォンと連携等、Googleとしてできそうなことは全部やっているようにみえました
GenServerで画像を送受信できるかやってみた

Elixirでの画像のやり取りはPhoenixやLiveViewのHTTPで送受信する記事が多く、例えばGenServerなどの他の通信方法でできるんかよく分からなかったのでやってみました。GenServerで。


# 環境
このような環境で確認しました。
```shell
❯ sw_vers
ProductName:            macOS
ProductVersion:         13.5
BuildVersion:           22G74

❯ asdf current
elixir          1.14.5-otp-25
erlang          25.2.2
```


# 画像送受信の流れ
テストってことで、画像フォーマットチェックやファイル名指定して送受信などは考慮していません。
1. プロジェクトの配下のディレクトリに画像ファイルを設置
    - `./data/IMG_9999.jpg` を設置
1. ローカルで起動しているGenServerのプロセスに `GenServer.cast()`
1. GenServerでは、受信した画像ファイルを `./data/receive/1.jpg` として保存


# プロジェクト作成
`ImageTransceiver` というプロジェクトを作成してモジュールを作っていきます。

```shell
❯ mix new image_transceiver
❯ cd image_transceiver
```


# 送受信のプログラム作成
`lib` ディレクトリの下に、送信用のモジュールと受信用のモジュールを作成します。
- 送信用：lib/send.ex
- 受信用：lib/reciev_server.ex

## 送信用：lib/send.ex
ファイルを読み込み、GenServer.castするプログラムとしています。
```elixir
defmodule ImageTransceiver.Send do
  def to(to_pid, image_path) do
    {:ok, image_file} = File.read(image_path)
    GenServer.cast(to_pid, {:send, image_file})
  end
end
```

## 受信用：lib/reciev_server.ex
handle_castで受信した画像を `1.jpg` として保存するプログラムとしています。
長くなるので必要最低限の関数のみ記載してます。
```elixir
defmodule ImageTransceiver.RecieveServer do
  use GenServer

  def start_link([my_pname]) do
    state = []
    GenServer.start_link(__MODULE__, state, name: my_pname)
  end

  @impl true
  def handle_cast({:send, image_file}, state) do
    File.write!("./data/receive/1.jpg", image_file)
    {:noreply, state}
  end

  @impl true
  def init(state) do
    {:ok, state}
  end
end

```

# いよいよやってみた
まずは受信ディレクトリに移動して、何もファイルがないことを確認。
```shell
❯ cd data/receive

❯ ls -l
total 0
```

プロジェクトフォルダ直下で、iexを実行し、サーバープロセスを起動して、画像ファイルを送信。
```iex
❯ iex -S mix

iex> ImageTransceiver.RecieveServer.start_link([:recieve_server])

{:ok, #PID<0.223.0>}

iex> ImageTransceiver.Send.to(:recieve_server, "./data/IMG_9999.jpg") 
:ok
```

受信ディレクトリでファイルができていることを確認。
```shell
❯ ls -l
total 3560
-rw-r--r--  1 kazuma  staff  1820267  8  4 15:06 1.jpg
```

# まとめ
はじめは、画像エンコードしなきゃーとかやっぱりBase64かねーとか思ってたんですが、特に考慮せずに画像を送受信することができました。いや、ホントは考慮しないといけないことはまだまだあるんでしょうけど。

今回はローカルでの確認となったのでファイルコピーになっちゃいましたけど、サーバープロセスをリモートで稼働していると、リモートのノードに画像ファイルコピーやり放題！ってなるので何かに使えるかもです :smile:
LinuxmintでDockerのupdateしたら、rootless modeで使っていたDockerが起動しなくなったけど、修復できた話


困ったことが起きたけど、現実逃避するのはやめて、ネタになるからいいじゃんとなだめながらうまく動くように取り計らったメモ。


##  概要
アップデートマネージャーで、追加のリポジトリ内のDockerを正常にしたら、無事、Dockerのアップデートがされるようになりました。

しかし、喜び勇んでDockerをアップデートしたら、Rootless modeで使っていたDockerが動かなくなりました。

Docker上で開発してるので、Rootless modeが動かないと、頭の中が現実逃避しだします。

なので、ズバッと解決しなくては。

弊環境はLinuxmint21.2なので、Linuxmint公式サイトによると、
https://linuxmint.com/download_all.php
ubuntu jammyなので ubuntu 22.04にあたります。

一応Docker公式
https://docs.docker.com/engine/security/rootless/
の通りにやったけどちゃんと動かなくすっかり沼ってしまいました。



## 以下、弊環境で動かした手順

Dockerのパッケージ一覧を表示して消していいかどうか確認し
Dockerを消し去る。

```terminal
sudo apt list --installed | grep docker
sudo apt remove 'docker*'
```

公式サイトのInstall欄のWithout packagesタブに記載されている方法のcurlでインストールしてみる。

```terminal
curl -fsSL https://get.docker.com/rootless | sh
```

すると、エラーで止まるので、指示通りにしてみる。

```terminal
cat <<EOF | sudo sh -x
cat <<EOT > /etc/sysctl.d/50-rootless.conf
kernel.unprivileged_userns_clone = 1
EOT
sysctl --system
EOF
```

ってやるけど、エラーで止まる。
仕方がないのでrootlessが何してるんだか見てみる。

```terminal
wget https://get.docker.com/rootless
xed ./rootless &
```

なんか、
kernel.unprivileged_userns_clone = 1
のエラー表示の箇所は、
cat /proc/sys/kernel/unprivileged_userns_clone
が1かどうかを判断しているので、

```terminal
cat /proc/sys/kernel/unprivileged_userns_clone
```

をしてみてると、"1"になっていない模様。
しかし、

```terminal
cat /etc/sysctl.d/50-rootless.conf
```
したら、
kernel.unprivileged_userns_clone = 1
はセットされている。

ということは、
sysctl --system
がうまく動いてない模様。

```terminal
sudo sysctl --system
```

するけど、
/etc/sysctl.d/50-rootless.conf
の項目はエラーにならない。

sysctl --systemのやっていることは、

> あれやこれやの設定ファイルから読み込むよ
> Load settings from all system configuration files.
> /run/sysctl.d/*.conf
> /etc/sysctl.d/*.conf
> /usr/local/lib/sysctl.d/*.conf
> /usr/lib/sysctl.d/*.conf
> /lib/sysctl.d/*.conf
> /etc/sysctl.conf

※感謝 https://wa3.i-3-i.info/word14684.html

ということなので、
/etc/sysctl.d/50-rootless.confは読み込んでないっぽい。

なので、ここに書き込んじゃう。

```terminal
sudo micro /etc/sysctl.d/99-sysctl.conf
```

に、
kernel.unprivileged_userns_clone = 1
を書き込む。

そしてまた読み込ませる。

```terminal
sudo sysctl --system
```

なんと今度がエラーが無い模様。

なので、再度公式の
```terminal
curl -fsSL https://get.docker.com/rootless | sh
```
をする。

ちゃんと、インストールされた模様。

/var/run/user/1000/にも、
dockerってフォルダが存在している模様。

Dockerを試す。

```terminal
docker ps -a
```
ああ、無事rootless modeで起動できた。

しかし、いつものdocker起動してみると、
docker-composeが無いですよ、と言われた。
普通に入れてみる。

```terminal
sudo apt-get install docker-compose docker-compose-plugin
```

無事、いつもの環境が起動しました。
ありがとうございます。
flutterでElevatedButtonがタップ処理無効の時の背景色を変更する


結論から書くと下記

    ElevatedButton(
      //条件分岐させるために３公演算子使用
      onPressed: pressOrNotPress()
          ? () async {
                
            }
          : null, // pressOrNotPress()がfalseの場合はnullを設定してボタンを無効にする
      child: const Text(
        "登録",
        style: TextStyle(
            fontSize: 16,
            fontWeight: FontWeight.bold,
            color: Colors.white),
      ),
      style: ElevatedButton.styleFrom(
        primary: getInputButtonColor(),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(10),
        ),
      ).copyWith(
        // 無効時の背景色を指定
        backgroundColor: MaterialStateProperty.resolveWith<Color>(
              (states) {
            if (states.contains(MaterialState.disabled)) {
              return Colors.grey; // 無効な場合の背景色
            }
            return getInputButtonColor();
          },
        ),
      ),
    )

上記はそのままでは動かないので中級者向けです

そしてその中でElevatedButtonがタップ処理無効の時の背景色を変更するで必要なのは下記です

    copyWith(
            // 無効時の背景色を指定
            backgroundColor: MaterialStateProperty.resolveWith<Color>(
                  (states) {
                if (states.contains(MaterialState.disabled)) {
                  return Colors.grey; // 無効な場合の背景色
                }
                return getInputButtonColor();
              },
            ),
          ),

タップ無効の時なんて別にデフォルトでええやんって思ってたんですが、案件でボタンが無効の時も色を変えてくれとのことだったのでそれ用に修正しました

copyWithというものがあるなんて知らなかったのでせっかくなので共有です

どなたかの参考になれば幸いです

ではまた
MVVMの誤解

#### 以下は全て誤解



# ViewModel

　ViewModelはバインドのためにある
　ViewModelはUIの都合で存在する
　ViewModelがバインドである
　ViewModelはUIスレッドで動く　　
　ViewModelにロジックは入れない
　ViewModelは薄くなければならない
　ViewModelはViewのModelである

# Model

　Model に INotifyPropertyChanged インターフェースを実装しなければならない
　Modelメソッドの戻り値はvoidでなければならない

# View

　Viewにロジックを入れる
　Viewに状態を持つ

# MVVM

　MVVMはMVCである
　MVVMはバインドを使う
　ViewModelにビジネスロジック　Modelにデータ
　MVVMは単方向データフロー
SwiftUIでPreviewの実行かどうか判別する

Previewがよく動かなくなるので分岐させたかった。

## 判別方法
`ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"]`
を利用する

```.preview
if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" {
}
```
Javaで「相対パスを絶対パスに変換する(Path.toAbsolutePath)」の動作を確認してみた

# 概要
Javaで「相対パスを絶対パスに変換する(Path.toAbsolutePath)」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/start/file/index13.html

# 実装
以下のファイルを作成しました。
```JSample13_1.java
import java.nio.file.Path;
import java.nio.file.Paths;

class JSample13_1{
  public static void main(String[] args){
    Path p1 = Paths.get("/code/java/file/report.txt");
    Path p2 = Paths.get("report.txt");
    Path p3 = p2.toAbsolutePath();

    System.out.println(p1);
    System.out.println(p2);
    System.out.println(p3);
  }
}
```
以下の通り実行しました。
```
$ javac JSample13_1.java
$ java JSample13_1 
/code/java/file/report.txt
report.txt
/code/java/file/report.txt
```

# まとめ
何かの役に立てばと。
2023/08 Glueについて〜２章〜（１からConnectorの作成をしたい）

# Glue Connectorとは

どの役割のConnectorになるかで意味は違ってくるので、今回の要件であるS3からデータを読み取りし、RDSへimportする場合についての意味で説明します。
簡単に言えば、crawlerやjob実行をする上での、dataのimport先のVPCやそのサブネット、セキュリティグループの情報を持って適用してくれるツールのようなものです。
例えば社内システムの場合、セキュリティをしっかり組んでいると思うので、Connectorの設定をしておかないと、接続時に弾かれるエラーが表示されてしまいます。
その接続を担保してくれるものだと認識してください。
Connector自体は作成しなくても、crawlerやJobを実行できるという話もあるのですが、僕は作成した方がいいと思います。
実際Connectorなしで試したのですが、うまくいきませんでした。（原因の追求は深く行なっていませんが）
先の話ですが、Job作成時にコンソール上でもスクリプト上でもVPCまでは設定することができるのですが、サブネットやセキュリティグループまでの設定を行うことができないので、やはり作っておくことをお勧めします。

# 実際に作成してみよう
![スクリーンショット 2023-08-04 13.31.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3004597/099deeec-7aaf-926b-ad4e-4fb82e8f70b2.png)
・まずはGlueのコンソール画面から、Connections→Create Connectionと進みましょう

![スクリーンショット 2023-08-04 13.33.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3004597/154c77a6-b2e4-88c5-1eeb-d9813f5bf7d9.png)
Nameに名前入力をし、Connection typeを選択しましょう。
今回はRDSに対して、crawlerでスキャンを行いたいので、JDBC or Amazon RDSを選択しましょう
今回はAmazon RDSを選択します。
〜一言〜
・JDBC = Java Database Connectivity
いろいろなリレーショナルデータベースに接続するために使われ、MySQL,PostgreSQL,Oraacle,SQL Server等に対応をしています。これを選択すると接続設定でデータベースのホスト名、ポート、データベース名等を指定して、接続を行います。
・Amazon RDS
これを指定するとARNを指定して、接続を行います。

どちらを選択しても接続できるので、好きな方を選択して適切な情報を入力してください。

![スクリーンショット 2023-08-04 13.45.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3004597/83617126-08d6-9865-b3fa-419e778886ee.png)
ARNを設定した後に、Database nameを指定します。
一つ困るのが、Credential typeのところです。
AWSを普段から使っている方々からすると、Secrets Managerを使いたいところですが、ここではUsername and passwordの方を選択してください。
ここでSMを選択すると、crawlerは適切に行われるのですが、job実行時にエラーが表示されてしまいます。

あとは右下にあるCreate Connectionを押下すればConnectorの作成ができます。

# crawlerでスキャンを行なった時のエラーについて
次の項目でも記述しますが、セキュリティグループで特定のportのみの接続許可を行なっていると、crawler作成→実行時に下記のエラーができることがあります。（今回直面しました）
```
At least one security group must open all ingress ports.To limit traffic, 
the source security group in your inbound rule can be restricted 
to the same security group 
(Service: AWSGlueJobExecutor; Status Code: 400; Error Code: InvalidInputException; 
Request ID: 76433951-299c-400d-92e4-67ba1347526e; Proxy: null)
```
少なくとも1つのセキュリティグループはすべてのイングレスポートを開放しなければならない。」とのことです。
AWSの知見の深い方に意見をお借りして、今回はGlueConnector用のセキュリティグループを作成するという方向で解決をしました。

次回　crawler作成・実行について
Pythonモジュールの基本

# モジュール、パッケージ、ライブラリ
### モジュール
関数や、クラスをコードで取り入れることができる定義や文が入ったファイル（スクリプトファイル、`.py`がついたファイル一つ一つ）

### パッケージ
複数のモジュールがまとまったもの
・__int__.pyという名前のファイルを持つ
・__path__属性を持つ

### ライブラリ
モジュールとパッケージを集めたもの

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3389633/ad90f55a-c55a-717e-2460-54a2c0765c82.png)

# ・import ・from ・asの使い方

### import

**calc.py**
```
def square(num):
    return num**2

def cube(num):
    return num***3
```

```
>>> import calc
>>> calc.square(2) # モジュール名.関数名
4
```
・関数にはモジュール名を使ってアクセス

・ローカルな名前に代入できる

### from
特定の関数をインポート

```
>>> from calc import cube
>>> cube(3)
27
```

from モジュール名　import *

_（アンダースコア）以外で始まる全ての名前（クラス・関数）
```
def _check_tzinfo_arg(tz):
    if tz is not None and not isinstance(tz, tzinfo):
        raise TypeError("tzinfo argument must be None or of a tzinfo subclass")

class timedelta:
```

・このようにアンダースコアがついてる関数は公開したくないもの
・内部で使いたい関数と外部で使いたい関数によって使い分ける

### as
指定した名前でインポート
```
>>> import calc as cl
>>> cl.cube(4)
64
```

モジュール名が長い時に、省略したい場合などに使用

# モジュールについて
・変数にもアクセス可能

**test3.py**
```
a = 5
```

```
>>> import test3
>>> print(test3.a)
5

>>> test3.a = 9
>>> print(test3.a)
9
```

・モジュールは１回しかインポートされない
モジュールを修正した場合は、再起動かimportib.reload()を使う(以下)
```
>>> import importlib
>>> importlib.reload(test_module)
```

・__name__の値がモジュール名

**test1.py**
モジュール名を出力する関数
```
def test_func():
    print(__name__)

test_func()
```

呼び出し
**test2.py**
```
import test1
>>> test1　# モジュール名が呼び出される
```

次のような書き方をすると出力値が変わる

```
python test1.py
>>> __main__
```

・トップレベルで使用する場合は__main__となる
・if __name__ == "__main__":
 このモジュールはトップレベルで実行するなら〜という意味になる
基本設計のやり方について教えた話

現場で3年目くらいの人が基本設計で四苦八苦していたので、設計過程とか成果物レビューとかで色々考えたり気付いたり事があったので共有します。
私個人の考え方ですので、明らかに間違っている点や説明不足などありましたらご指摘していただけると助かります。

# 基本設計の考え方
基本設計は、やりたい事をどうやったら実現できるかを設計することです。
事前に要件定義フェーズがあって、そこでやりたい事と言うのが決まっています。
それに対して、システムとしてどうやったらできるかな、と考えて、それを人に説明するお仕事です。
基本設計のレビュアーは、やりたい事がその設計で本当に実現できるか、もっと効率良い方法はないか、
実現方法にシステムの制約が抵触していないか、などを確認します。

# やりたい事の粒度を細かくする
要件定義フェーズで決まったやりたい事というのは、まだやりたい事としては大味です。
なので、まずは少し粒度を細かくして、説明しやすくします。
基本設計レビューとかでは、要件定義との認識違いが発生していないかの確認で有用です。

# 各項目の実現方法を説明する
実際に、どうやったら実現できるかを説明します。
基本設計にあまり慣れていない人は、ここだけ基本設計書に書いてレビュアーに
「何が書いてあるかわからない」「もっと具体的に」「そもそも要件理解してる？」とか言われます。

# 具体例１
要件：夜間実行のバッチ処理が遅すぎてそろそろシステム開始時間を超える恐れが出てきたので改善する

### 基本設計開始
私「調査した結果、取引数増大によってメインの会計処理の数が増えたからっぽい」
私「最近クラウドで流行りの並列でやれば処理あんまり変えずに短縮できるんじゃね？」

### やりたい事のリストアップ
・「メイン処理」を並列実行することによって速度を改善する
　→これにより、現状の処理にあまり手を入れずに速度改善が見込める
・バッチ処理を「前処理」「メイン処理」「後処理」に分割する
・「メイン処理」を並列実行できるように処理を変更する
・エラーが発生しても処理を止めない（既存通り）
・前処理から再実行することで、エラーが発生して未処理だったものだけが再実行されるようにする（既存通り）

### 実現方法
前処理で、会計処理を行う必要があるレコードを抽出し、レコードの主キーを100件ずつまとめて、新規作成する並列実行管理テーブルに登録する。
テーブルに登録するのは主キー100件と、並列実行管理用のIDとする。
テーブル登録をトリガーとしてメイン処理バッチが起動するようにする（複数起動可能）。
メイン処理では登録された主キー100件分を直列実行し、結果登録テーブルに実行結果を登録する。
　→エラーが発生した場合は、エラーが発生したレコードの主キーと、エラー内容を登録する
前処理バッチにエラー再実行用の引数を設定し、エラー発生レコードのみを抽出して再実行できるようにする
全てのメイン処理が終了後、後処理バッチで結果を統合する。

### レビュー指摘など
テーブル登録をトリガーにするのはどうやるのか？
並列実行管理テーブルのテーブル設計を書いて欲しい
後処理バッチの起動についての記載がない。どうやって全てのメイン処理が終わったことを判定するのか？
このシステム内で並列実行してる処理は一つもないのでそんな前例のない事はやめてくれ。

# 具体例２
要件：夜間実行のバッチ処理が遅すぎてそろそろシステム開始時間を超える恐れが出てきたので改善する

### 基本設計開始
私「だいたいこういうのはクソ重いSQLを改善すればどうにかなるんだよな」
私「やっぱり実行に20秒かかってる副問合せマシマシのSQLあるっぽいわ。直すべき。」

### やりたい事のリストアップ
・実行に時間のかかっているSQLの改善によって処理速度を改善する

### 実現方法
バッチ処理で実行している全てのSQLを洗い出し、SQLの実行計画を確認する。
重いSQLを改善する。

### レビュー指摘など
全てのSQLって何本くらいあるのか？
　→600本です
　　→それ全部確認するのものすごい時間かかるのでは？今遅いやつだけにしたらどうか。
システムがかなり売れていて、今後数年で規模が10倍くらいになりそうだが、すぐ同じ問題が発生する可能性があるのではないか？
バッチ処理はかなり複雑なのだが、SQLが本当に正しく修正できるか不安。そのリスクを負いたくない。
VSCodeをリアルタイムで共同編集するプラグイン

# Visual Studio Live Share

VSCodeを通じてリアルタイムでファイルを共同編集できるツールで
同じコードを見ながらお互いに編集できるので、テレワーク下での
コードレビューを行うツールとしてかなり重宝してます。

VsCodeがあればプラグインを設定するだけで、コードの共有ができるのが嬉しいです。
利用のためにはMicorosoftアカウントもしくはgithubアカウントが必要になるので注意してください。
 
https://visualstudio.microsoft.com/ja/services/live-share/

# 使い方

LivaShare拡張機能をインストールしてあると
VSCodeの左下のステータスバーに「Live Share」ボタンが表示されるのでクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/953141/8b6713a2-7e96-0525-e438-766d86de81c8.png)

Invite Othersで、招待用のURLをコピーして、共有したい相手に送ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/953141/56c9860d-092a-ded1-3966-21c481ccd485.png)

招待を受け取った側はURLにアクセスします。
ブラウザ版のVSCodeが開いたら、アプリケーションを開くボタンで、実際のVSCodeを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/953141/223a3476-9c16-cdca-2840-0fad01b8b7cd.png)

招待を開いてしばらくすると、共有元の画面には下記のように表示されます。
左側のメニューアイコンにLiveShareのマークが出ているので、クリックすると共有相手の名称が
表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/953141/e9f7a94c-966b-9cfd-2c45-a11c901c6b96.png)
【AtCoder】ABC235 D - Multiply and Rotate 

# 概要
AtCoderの[ABC235のD](https://atcoder.jp/contests/abc235/tasks/abc235_d)を解いた。解説に書かれているような実装をしたはずだったのにハマったので、解法のメモ。
※以下、本問に関する解法を含みます。

# アプローチ
まず前提となる、この問題を解く上での大まかなアプローチ。
始点が決まっていて、操作の種類も少ない。基本的に定数を乗じるか、数字を文字列とみなしてローテーションするだけなので桁が減ることもない。
1から始めて$N$までの最短路をグラフ上で探索するような問題になりそう。
ただ、増やす方向には無限にいくらでも操作できてしまうし、桁のローテーションにより桁数が減ることがなくても数字としては小さくなる場合があるので、探索中に得られた数字が探している$N$よりも大きくなったからといって探索を止めるわけにはいかない。なので、探索範囲が無限大になってしまう可能性があるように見える。[^1]
そこで、各操作を行う前の状態を復元することも容易であることに注目し、求めたい$N$から逆に辿って、1に行きつくまでの最短回数を求めることにする。これであれば、桁数は広義単調減少なので、いずれは1にいきつくか途中で息詰まるので、気持ちとしても安心。
この方法は、実は解説の末尾でも提示されている。

# 実装のハマりどころ
$a$を掛ける操作に対応する、$a$で割る操作については特に注意点はない。あらかじめ割り切れるかどうか確認してから割ってやるくらい。
問題は、末尾の桁を先頭に持ってくる右シフト的な操作である。
基本的には、数字が1桁ならシフトはしない、2桁以上であれば逆に左シフトしてあげる、でよい。
但し、左シフト後に0から始まるような数値になってしまう場合は、そのような復元はできないことに注意しなければならない。
例えば、706543を左シフトすると065437になる。しかしこれは整数として見ると65437であるから、右シフトしたら76543になるのであり706543にはならない。
このことに気を付けないと、正解よりも少ない回数で遷移できると判断してしまったり、本来は遷移できないのに遷移できると判断してしまう。

# 提出したコード
最短経路を求める問題に帰着できるということには解説を読んでから気づいたので、深さ優先探索してて恥ずかしい。
## 上記のミスに気づいておらずWA
https://atcoder.jp/contests/abc235/submissions/44220826

## 上記のミスに気付いてACしたもの
https://atcoder.jp/contests/abc235/submissions/44222081

# 注釈
[^1]: [解説](https://atcoder.jp/contests/abc235/editorial/3255)にも記載の通り、自明ではあるが、求める$N$より桁数が大きい数値に関してはそれ以上探索する必要がない。桁数が減ることはないため。したがって、$N$の十進法での桁数を$r$とすると$10^r$以上については調べる必要がない。これにより、計算量が有限に抑えられることが保証される。
Microsoft Teamsのあれこれ

# Microsoft Teamsのあれこれ

Teams、会社で使わされている人多いと思いますがいろいろ痒い所に手が届きづらいことがあるので私が蓄積したあれこれを共有します。

## チームの固定が消えた
よく使うチームは固定しておくと思いますが、時々この「固定」した部分が消えて「あなたのチーム」が一番上に来てしまいます。
### 解決策
適当なチームを選んで「固定」をすると出てきます

## グループチャットの固定が一定数以上できない
グルチャは更新されてないといつの間にか流れて検索もめんどくさくなります。
固定をしておけばいいのですが、グルチャの固定は15個以上できないようで「ピン留めされたチャット(および自分とのチャット)には 15 個のスペースしかありません。ピン留めを外して、もう一度やり直してください。」とメッセージが出て固定できなくなります。

### 解決策
固定をするという点において解決はできませんが、以下の方法でグルチャを保存しておくことで「グループチャットを検索してたどり着く」必要がなくなります。
1. Teamsをウェブブラウザで開く
1. 該当グルチャを開く
1. URLをお気に入りに入れる、あるいはURLをコピーして保管しておく

ちなみにSharepoint等にURLリンク集などを作った場合、正常にグルチャを開けません。
これは「&」などの文字をTeamsのURLではURLエンコードせずにURL欄に書かなければいけないのですが、リンクなどで開くとURLエンコードしてしまうからのようです。
「https://」を取り除いてURL欄に張り付けたりすればOKです。
jetpack composeで折り返しのViewを作る

# はじめに
今回はJetpackComposeを用いて画面いっぱいになったら自動的に折り返してくれるViewを紹介していきます
### 本文
`com.google.accompanist`にある`flowlayout`をプロジェクトに`implemention`することで使えるようになります
```kotlin
//横
FlowRow(
    modifier = Modifier
        .fillMaxWidth(),
    horizontalArrangement = Arrangement.Start,
    maxItemsInEachRow = 4
) 
```
`maxItemsInEachRow`は名前の通り何個までを許容するかです
`horizontalArrangement`は通常の`Arrangement`と同じで間隔や幅寄せを指定することができます。
ただし、注意が必要なのがまだBetaなのもあって`FlowRow`を使う場合該当の`Composable`関数に下記のアノテーションをつけなければいけません。
```kotlin
@OptIn(ExperimentalLayoutApi::class)
```
### 最後に
今回は非常に便利な折り返しのViewを紹介していきました
どなたかのお役に立てれば幸いです
Azure Active Directory　なぜAPIアクセス許可に管理者の同意を与える必要？

Dataverse関連を開発するとき、Azure ADでuser_impersonationのアクセス許可を追加する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/263c31b8-95f4-d7bc-104d-594f9f0e7e08.png)
管理者同意が必要かよく聞かれます。

# 管理者の同意を与えます
 
・同意しない場合、下記の同意画面がでます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/fbb82baa-921b-2996-1efd-89b1f32c6cb0.png)

・同意する場合、同意画面が表示されません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/1162b924-1b36-4b0e-93f5-6880d97b6eae.png)

# 参考サイト
https://learn.microsoft.com/ja-jp/azure/active-directory/develop/permissions-consent-overview?WT.mc_id=Portal-Microsoft_AAD_RegisteredApps

https://learn.microsoft.com/ja-jp/power-apps/developer/data-platform/walkthrough-blazor-webassembly-single-tenant
非同期処理を使っていないのにQueueServiceProviderを消したらエラーログが残った話

Laravelフレームワークでの開発中に起こった出来事を書きました。

## QueueServiceProviderとは

Laravelでは、`config\app.php`で使用するサービスプロバイダを定義しています。
プロジェクトを立ち上げると、デフォルト状態でいくつかのサービスプロバイダがすぐに使える様に用意されています。
その中のひとつに`Illuminate\Queue\QueueServiceProvider::class`というサービスプロバイダがあります。
このサービスプロバイダはChatGPTによると、以下の様な説明になっています。
> QueueServiceProviderは、Laravelにおけるジョブキュー処理の機能を提供します。キュー処理は、時間のかかるタスクをバックグラウンドで非同期に実行するためのものです。

## 何をしたのか
プロジェクトでは非同期処理を行っていないので、このサービスプロバイダは不要と判断し、削除しました。
動作確認やテストを実施し、その時はエラーログも記録されなかったので大丈夫だと思っていました。

## 何が起こったのか
ある日、ローカル開発環境のLaravelログを見ると、次の様なエラーメッセージが残っていました。
`production.ERROR: Target class [queue.listener] does not exist.`

前述の削除したサービスプロバイダが提供するクラス`queue.listener`が見付からないという旨のメッセージなので、このメッセージが出ない様にするには削除したサービスプロバイダを復活させれば解決します。
しかし、プロジェクトではこのクラスを使っていないのに、何故このメッセージがログに残るのかが謎です。
放っておくのも怖いので要因を調べてみました。

## 要因

2つ見付かりました。
それぞれ、どうやってその要因が見付かったかも書いています。

##### Visual Studio Codeの拡張機能`Laravel Extra Intellisense`で`queue.listener`が使用されていた。
「Visual Studio Codeを開いている時だけ再現する」という同僚の証言をヒントにChatGPTに聞いたところ、入れている拡張機能が怪しいと教えてもらえました。
どの様な拡張機能を入れているかを同僚にヒアリングし、それをChatGPTに伝えると絞り込んでくれました。
ChatGPTさまさまですね。

##### `artisan`で存在しないコマンドを入力した際の処理に`queue.listener`が使用されていた。
エラーログを追っ掛けると`artisan`実行時にエラーを吐いていたので、コマンドプロンプトでテキトーに`php artisan unko`とかやってたら再現しました。
ある程度の目星を付けたらあてずっぽうでいろいろやってみるのも要因発見の近道になるのかもしれません。

## 感想

デフォルトサービスプロバイダはプロジェクトで使用していなくても、こういうひょんなところで使われている事があるのだなぁというのが学びでした。
拡張機能とかは、デフォルトで入っているものをアテにしている場合が多そうです。
使ってないから消しちゃえーっていうのは割とやっちゃいそうなことではありますが、こういった弊害を伴うリスクを十分に理解した上で行うのが大切ですね。
Macのキーチェーンアクセスを使ってターミナルで安全にパスワードを取得する

こちらの記事([どうしてもコマンドライン上でCiscoのVPN接続をしたい](https://qiita.com/mr91i/items/b7770104a69fd87a52fd))を書いた際に、パスワードをスクリプト内にそのまま書いておりました。ただセキュリティ的によくないなと思っており、より安全にパスワードを取得する方法を調べたのでまとめておきます。私はMacユーザーなので、Macの場合のみを書きますが、同じような仕組みが他のOSにもあるんじゃないかと期待します。


やることは、
(1)キーチェーンアクセスにパスワードを登録し、
(2)CLIでパスワードを取得するということです。
主にこちらのサイトを参考にしました。
https://gotohayato.com/content/547/


## 1. キーチェーンアクセスにパスワードを登録
キーチェーンアクセスはMacのパスワードを安全に保管する仕組みだと理解しています。以下の通りに、まずはそこにパスワードを保存します。


キーチェーンアクセスを開き、デフォルトキーチェーン上で右上の書き込みアイコンを押す。
![スクリーンショット 2023-08-04 12.11.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278171/b1d4e421-3918-9645-6b44-8e217803fdc2.png)

適当なキーチェーン項目名とアカウント名を入力後（これらは項目を見つける際にのみ使います）、保存したいパスワードを入力し、追加を押します。このキーチェーン項目名とアカウント名は項目を見つける際にのみ使うので、なんでもいいのですが、見つけやすいような項目名とパスワードに対応するアカウント名を使うといいかなと思います。ここでは例として"cisco_vpn_password"と"account_name"としてみましょう。
![スクリーンショット 2023-08-04 12.14.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278171/35d4f625-d3d1-3683-07cd-2f6599960d8b.png)

そうするとこのように項目が追加されると思います。
![スクリーンショット 2023-08-04 12.15.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278171/a3062786-77da-3069-556e-d724ae87b7c6.png)


## 2. CLIでパスワードを取得する
次に登録したパスワードをターミナル上で取得してみます。

ターミナルやshellで
```
security find-generic-password -s [サービス名] -a [アカウント名] -w
```
とすると、キーチェーンアクセスに登録したパスワードを取得することができます。
上の例の場合なら、`security find-generic-password -s cisco_vpn_password -a account_name -w`と入力します。


初回アクセス時には使用しているMacのパスワードを求められます。ここで「許可」を押せば今回だけキーチェーンへのアクセスを許可することになりますし、「常に許可」を押せば以降のパスワードの入力は必要なくなります。
![スクリーンショット 2023-08-04 12.51.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278171/1413be45-23f8-a34f-2de3-04bc46dbcccc.png)

許可するとこのようにパスワードを取得することができました。
![スクリーンショット 2023-08-04 12.51.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278171/1280a857-45bd-a26d-384e-a46f434894ec.png)

## おわりに
このような仕組みを使えば、shell上で自動的にパスワードを入力するということが可能になるので、より柔軟にスクリプトを作成することができそうですね。
DP-900合格記(2023/9/2投稿)

# はじめに
この度MicrosoftのDP-900試験(Azure Data Fundamentals)を受験してきましたので、勉強した内容と受験した感想を書いておきます。
これから受験される方の参考になれば幸いです。


# 前提
* AZ-900/AZ-104/AZ-700/AZ-305/AZ-204は取得済み
* AzureはAPIM、DevOpsを少し触って、VMを作った程度
* AWSの実務経験あり
* AWS認定は全て取っています(詳細は[こちら](https://qiita.com/handy-dd18/items/d21d914bf1c475d777f2))
* Google Cloud認定は5つ取ってます


# 学習内容
今回は前々から気になっていた以下のチャレンジを使って学習を行いました。

- [MICROSOFT CLOUD SKILLS CHALLENGE '30 日間で習得'](https://developer.microsoft.com/ja-jp/offers/30-days-to-learn-it)

ざっくりどういうものか説明すると、
このチャレンジは30日以内に指定の資格に関連するMS Learnのラーニングパスを全て受講(無料)することで半額バウチャーがもらえるようになっていて、必要なラーニングパスの数は資格に関連するものが対象となっています。

今回受験したDP-900は大体10個近くのラーニングパスが対象となっていて、1つのラーニングパスが大体30分で終わるので、そこまで時間はかかりませんでした。

また、公式が出している模擬問題(無料)も併せて行うことで、より知識の習得につなげることにできます。
後述しますが、念のためUdemyの模擬問題も買って解いてみましたが、正直基本情報レベルの知識があれば↑の2つをやっていれば十分だと思いました。

- [Microsoft 認定資格のプラクティス評価](https://learn.microsoft.com/ja-jp/certifications/practice-assessments-for-microsoft-certifications)

## ①公式ラーニングパス
以下ページの受験したい資格の「始めましょう」を押下すると、資格のチャレンジページに飛ぶようになっています。
今回はそこにまとめられているラーニングパスを全て読むことで学習しました。

- [MICROSOFT CLOUD SKILLS CHALLENGE '30 日間で習得'](https://developer.microsoft.com/ja-jp/offers/30-days-to-learn-it)


実際の開始方法を載せたいのですが、DP-900は既に完了済みなので、前に受験したAZ-204のチャレンジを使用して開始方法を説明します。

上記ページで「始めましょう」を押下すると、以下のようなチャレンジページに飛ぶようになってます。
ここの右側にある「今すぐ開始」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/2a6d5ff7-6709-5c45-b3bb-288fedc095d5.png)

同意するにチェックを入れて続行を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/3c773feb-c663-d5f0-ec6c-31f141c83b8e.png)

学習を開始を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/a80b77d6-75a6-fca0-b0ab-51fe0f720f22.png)

ラーニングパスがまとまったページが表示されました。
上部に完了する必要があるトレーニングの数やその目安時間、進捗率等が表示されています。
AZ-204だと33個のトレーニングがあるようなので、30日以内に終わらすために根気強く進めていく必要がありそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/168596cb-be3c-861c-4e12-8c198960ff99.png)

尚、チャレンジのトップページのQAにも記載がありますが、バウチャーは6ヶ月に1つのみ発行されます。
なので、その間に複数のチャレンジを達成してもバウチャーをもらえるのは最初の1つのみになります。
複数もらいたい方はバウチャーを取得してから6ヶ月後に再度チャレンジしましょう。


## ②公式模擬問題
ラーニングパスでの学習が完了したら、知識確認のために以下の公式問題を解きました。
内容的にはUdemyにある問題よりは易しいのですが、ちゃんと理解しているかが問われるので、時間があればやっておくと良いと思います。
DP-900については寧ろこれを100%取れるようにしたら、あとはIT基礎がわかっていれば問題ないのではないかと思いました。

- [Microsoft 認定資格のプラクティス評価](https://learn.microsoft.com/ja-jp/certifications/practice-assessments-for-microsoft-certifications)


## ③Udemy
正直ここまでは要らないんじゃないかとは思ったんですが、今後受験される方にも参考になるかと思い以下のUdemy講座を購入してやってみました。

- [【2023年最新版】DP-900 Azure Data Fundamentals 模擬問題集](https://www.udemy.com/share/106ilQ3@VZT9xPlt4E-18aURbIx9T6cPL-4fOD1BS8h1xMpuiWvLEKaVvGiw6ssZ1kGSrZeL/)

感想としては公式模擬問題よりも若干深く問われる程度で、8割ぐらいは公式問題と同じレベルの難易度なので、DP-900ぐらいであれば買わなくて良いかなと思いました。
50問×4回分あるので、心配な方は購入して実施されると良いと思います。


# 受験した感想
Fundamentalsということでわかっていたことですが、基本的なサービスの機能やIT知識で答えられるレベルでしか聞かれないので、15分ぐらいで回答して退出しました。
ただ、Data系のサービスについては過去の資格でそこまで学習しなかったものも出題されるので、AzureのData領域のサービスについて知るという意味では良い試験でした。


# 受験結果
合格でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/60564604-5a80-6048-8df4-26fa815e2372.png)


# おわりに
無事合格できたので、今度はData系のAssociateレベルを目指したいと思います。

この記事がどなたかの参考になれば幸いです。
power-line風にターミナルを見やすくする方法（Macバージョン）

# ゴールは下図のような感じの画面です
![スクリーンショット 2023-08-04 11.36.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103633/55c8e8a0-d4ff-fad8-ed6d-904f7b9ff6f7.png)

`cdコマンド`や`git push`や`git checkout`などのコマンドを入力し、スペースキーを入力した後、tabキーか矢印キーを押すと画像のように背景が白色になり選択することができます。

早速手順をご紹介いたします！

# まず初めに私のマシンのスペック、環境は下記でございます
- MacBookAir M2チップ
- 8コアCPU
- 8コアGPU
- 8GBユニファイドメモリ
- 256GB
- 13.6インチ
- MacOS Ventura 13.5


# 1.`Hyper`というターミナルAppをインストール
homebrewからでも公式からでもどちらでもインストールできます！
コマンド：`brew install --cask hyper`
公式：https://hyper.is

#### ※もし`brew not found`というようなエラーが出た際は下記コマンドでhomebrewをインストールしてあげてください！
```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

# 2. `oh my zsh`をインストール

下記コマンドで`oh my zsh`をインストール

```
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
```

下記公式になります！

https://ohmyz.sh/#install

# 3.エディタで`.zshrc`ファイルを下記のように記述します
```.zshrc

# If you come from bash you might have to change your $PATH.
# export PATH=$HOME/bin:/usr/local/bin:$PATH

# Path to your oh-my-zsh installation.
export ZSH="$HOME/.oh-my-zsh"

# Set name of the theme to load --- if set to "random", it will
# load a random theme each time oh-my-zsh is loaded, in which case,
# to know which specific one was loaded, run: echo $RANDOM_THEME
# See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes
# ZSH_THEME="robbyrussell" ←←←←←←コメントアウトしてください！！
ZSH_THEME="agnoster" ←←←←←←こちらを書き足してください！！


下記省略

```

# 4.`.hyper.js`で文字化け対策の設定

下図14行目の青枠部分(`Monaco for Powerline`)を追記してあげます！

![スクリーンショット 2023-08-04 12.12.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103633/272f0c81-3834-d4d0-15b1-76fc748a5e90.png)

以上です！

# 最後に...

既存のターミナルとiTermは使用しておりません。
理由としてはHyperの方がカスタマイズ性が高く設定が簡単であると感じましたためでございます。

また`zprezto`でpowerlineのように設定できる方法もありましたが少し手間が多くなりこちらの方法を記載致しました。
ターミナルが見やすくなると作業の効率も上がってきますのでぜひお試しください！

毎度のことですが何か記事の内容等でご指摘部分ございましたらコメントでご教授いただければと思います。m(_ _)m
Xcode15&iOS17でウィジェットのプレビューが表示されない

Xcode15betaでウィジェットを確認した所、以下の画像の警告が出てプレビューが表示されなくなっていた。（Small・Medium・Largeウィジェット共通）
![スクリーンショット 2023-08-04 12.04.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2370083/f4a4aff1-d26f-6479-2a92-a26d3e16adcb.png)

:::note warn
どうやら、iOS17の場合には、modifierでcontainerBackgroundを設定する必要があるらしい。
:::

## 解消方法
各ウィジェットに共通で入れたいのでextensionで以下の処理を準備する。

```swift
extension View {
    func widgetBackground(_ color: Color) -> some View {
        if #available(iOSApplicationExtension 17.0, *) {
            return containerBackground(color, for: .widget)
        } else {
            return background(color)
        }
    }
}
```

Small・Medium・Largeの各Viewに共通で追加する。
```swift
    var body: some View {
        ZStack {
            // widgetの処理
        }
        .widgetBackground(.clear) //色は自由
    }
```
[PostgreSQL] created_at, update_atを自動で入力させる

# 実現したいこと
テーブルにcreated_at、updated_atのカラムを用意し、
- created_atはデータ挿入時
- updated_atはデータ挿入時とデータ更新時

に自動でそのときの日時が入るように設定し、アプリケーション側ではこの2つのカラムのことをなにも考えなくて良いようにしたい

MySQLであれば以下のように設定するだけだがPostgreSQLでは少し複雑なのでメモとして残す。
``` MySQL.sql
CREATE TABLE your_table (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
```

# 実現方法
## 1. 初期値を現在日時としてテーブル作成
「created_at」と「update_at」カラムのDEFAULTにCURRENT_TIMESTAMPを設定して「your_table」テーブルを作成している。
```PostgreSQL.sql
CREATE TABLE your_table (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
## 2. データが更新された時に日時を更新する関数を作成する
「update_at」カラムを現在時刻にする「update_timestamp()」という関数を作成している。
``` PostgreSQL.sql
CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = NOW();
  RETURN NEW;
END;
$$ language 'plpgsql';
```
## 3. テーブルのトリガーに作成した関数を設定する
「your_table」テーブルに「update_your_table_modtime」という名前のトリガー（your_tableを更新する前に「update_timestamp()を実行する）を作成している。
``` PostgreSQL.sql
CREATE TRIGGER update_your_table_modtime
BEFORE UPDATE ON your_table
FOR EACH ROW
EXECUTE PROCEDURE update_timestamp();
```