OmniAICreator/Qiita-1.07M huggingface dataset:
【Django】複合主キー制約は使えない？The model cannot have more than one field with 'primary_key=True'.と表示された場合

# 概要
* Djangoでは複合主キー制約がないらしいということがわかりました。
* 本記事では、複合主キー制約に関して遭遇したエラーの原因と解決方法を記載します。

# エラー内容
* `Customer`モデル（テーブル）で`Primary Key`を2つのフィールド（カラム）に設定。
* その状態でマイグレートを実施すると、以下のエラーが出てきました。

```
SystemCheckError: System check identified some issues:

ERRORS:
customer.Customer: (models.E026) The model cannot have more than one field with 'primary_key=True'.
```

# 原因
* Djangoの設計思想では複合主キー制約がないらしい。
* Djangoで直接のサポートはないので、複数のフィールドを組み合わせたユニーク制約を使用することで実現できます。
* 解決策は、以下の記事を参考にしました。
    * [複合主キーは使えない](https://note.com/biz_yasu/n/nbbee332dace7)

# 解決策
* まず、`id`フィールドとかで良いのでサロゲートキーを追加します。
    * サロゲートキー（代理キー）とは、データベース内での検索や参照を容易にするために使用されるもので、対象のデータとは直接関係のない特に意味を持たない主キーのこと。一意である必要があるため、データの重複や不整合を防止することができます。
* 次に、`UniqueConstraint`を定義して複合主キー制約を設定します。
    * 複数のフィールドを組み合わせて一意性を確保する制約です。
    * モデルの`Meta`クラス内で定義します。
    * `fields`引数に一意の制約に含めるフィールドをリストで指定すればOKです。
    * `unique_together`属性は現在非推奨となっています。
* コードとしては以下のようになります。

```models.py
from django.db import models


class Customer(models.Model):
    id = models.IntegerField(db_column="id",
                                  primary_key=True)
    abc_id = models.CharField(db_column="abc_id",
                                  max_length=6,
                                  null=False)
    xyz_cd = models.CharField(db_column="xyz_cd",
                                max_length=5,
                                null=False)
    customer_key = models.CharField(db_column="customer_key",
                                max_length=100,
                                null=False)
    create_date = models.CharField(db_column='create_date',
                                   max_length=100,
                                   default='',
                                   null=True)
    update_date = models.CharField(db_column='update_date',
                                   max_length=100,
                                   default='',
                                   null=True)

    class Meta:
        constraints = [
           # abc_idとxyz_cdでユニーク制約
           models.UniqueConstraint(fields=['abc_id', 'xyz_cd'], name='unique_customer')
        ]
        db_table = 'customer'

```

* これで、`abc_id`と`xyz_cd`の組み合わせが一意であることを保証するユニーク制約が完成しました。
「デカ文字」「デジタル日日(64x128)」をST7735で作る2(頑張ってパターンを作る)



上側0-9


![o_cop502.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/290e927c-5f31-bcf9-ea60-f8a0cc04dbbe.jpeg)



下側0-9

![o_cop503.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/81f3d4ad-eab3-55f4-923f-c65e50899d1b.jpeg)
Godot4.0でAndroid端末に1クリックでリモートデプロイ＆リモートデバッグする

# 1.目的
　Godot4.0でAndroid端末に1クリックでリモートデプロイ＆リモートデバッグしましょう。
　とても便利です。もっと早く調べればよかったです。

# 2.準備
## USBケーブルの準備
　100均のUSBケーブルで良いですが、充電専用のケーブルではデバッグできません。
　ファイル転送できるものを選びましょう。

## ホストPCの準備
　必要に応じて、Android端末に対応したUSBドライバのインストールをします。
　PC⇔Android端末間でファイル転送ができるなら大丈夫だと思います。

> OEM USB ドライバのインストール
> https://developer.android.com/studio/run/oem-usb?hl=ja

## Android端末の開発者向けオプションとUSBデバッグを有効にする
 Android端末の開発者向けオプションを有効にします。またUSBデバッグもオンにします。

> デバイスの開発者向けオプションを設定する
> https://developer.android.com/studio/debug/dev-options?hl=ja

## Androidのエクスポート設定をする
　デバッグ対象のGodotプロジェクトでAndroid APKのエクスポート設定をします。

https://qiita.com/FootInGlow/items/cde673e0a424413ca109

　その際に実行可能が「オン」になっている必要があります。ディフォルトはオンです。
![スクリーンショット (773).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/b4dd611d-f15e-e4ed-0a6c-858d185e778a.png)

## リモートデバッグでデプロイを有効にする
　デバッグメニューの「リモートデバッグでデプロイ」を有効にします。
　オフの場合でもデプロイ・実行はできますが、デバッグできません。
![スクリーンショット (777).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/e0743261-566c-75ce-2e11-4eab81f53587.png)

## ホストPCとAndroid端末をUSBケーブルで接続
　ホストPCとAndroid端末をUSBケーブルで接続します。
　Android端末にUSB設定画面が表示されると思いますが、「ファイル転送」にします。
　「充電」や「データ転送なし」ではできません。

　GODOTエディタの右上にリモートデバッグボタンがあります。Android端末未接続や準備できていない場合は無効になっています。
![スクリーンショット (774).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/0ee21d0d-a429-b332-2071-51e22d93f3b2.png)
　準備がすべて完了すると下図のように有効になり、リモートデプロイ＆デバッグができるようになります。
![スクリーンショット (775).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/c24281cc-1a67-c4d9-f6d5-329f764c8251.png)

# 3.Android端末にリモートデプロイ＆デバッグする
　リモートデバッグボタンを押下すると、実行可能な接続中のAndroid端末が選択できます。
　マウスオーバーすると詳細情報も表示されます。
![スクリーンショット (776).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/ff9fa7f7-23ab-e72d-1d4f-0c75c7fd129a.png)
　端末名を選択すると、下図のダイアログが表示されて、Android用にエクスポート後、インストールしてAndroid端末で実行されます。
![スクリーンショット (779).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/2d2d846b-2303-fd81-4703-0443503f6588.png)

　実行すると、シーン内の「リモート」が表示されてAndroid端末で実行されているノードの状態を確認することができます。またprint文の表示もGODOTエディタの出力に出力されます。
![スクリーンショット (782).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/a3db1e2b-d48e-04a4-96c6-055f935467ec.png)

以上
Laravelのmake:migrationコマンドでひな形を作る際の挙動メモ

# Laravelのmake:migrationコマンドでひな形を作る際の挙動メモ

### テーブルを新しく作る場合(Schema::create)
コマンドを打ち込んだだけでこのようなusersテーブルを作るひな形が生成されている状態にしていきます。

```
public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->timestamps();
    });
}
```
 

マイグレーションファイル名によっては自動でテーブル名付きのひな形が生成される
たとえばこのようにコマンドを入力すると自動でテーブル名付きのひな形が生成されます

```php artisan make:migration create_users```
 

マイグレーションファイル名がcreate_から始まる場合は自動でテーブル名を読み取り、Laravelがひな形を作ってくれます。

 

ちなみにcreateUsersのようにキャメルケースでファイル名を指定してもひな形が生成されます。

```php artisan make:migration createUsers```
 

パスカルケース(CreateUsers)でもひな形が生成されます。

```php artisan make:migration CreateUsers```
 

ケバブケース(create-users)ではひな形は生成されませんでした。

```php artisan make:migration create-users```
 

この項目のまとめ

 * createからファイル名が始まることが条件
 * 〇 スネークケース(create_users)ではひな形が生成される
 * 〇 キャメルケース(createUsers)ではひな形が生成される
 * 〇 パスカルケース(CreateUsers)ではひな形が生成される
 * × ケバブケース(create-users)ではひな形は生成されない
 

コマンドを追加してテーブル名を指定することもできる
通常このようにコマンドを打つとひな形は生成されませんが

```php artisan make:migration users```
 

このように--create=テーブル名とするとひな形が追加されます。

```php artisan make:migration users --create=users```
 

この項目のまとめ

 * --create=テーブル名をコマンドに追加でひな形が生成できる
 

### テーブルをアップデートする場合(Schema::table)
```
public function up()
{
    Schema::table('users', function (Blueprint $table) {
        //
    });
}
```
テーブルを更新する場合はこのようなひな形を作ります。

 

マイグレーションファイル名によっては自動でテーブル名付きのひな形が生成される
こちらもマイグレーションファイル名によっては自動でひな形が生成されます。

 

```php artisan make:migration add_to_users```
 

このようにadd_to_ から始まるファイル名を指定すると自動でひな形が生成されます。

 

先ほど同様、スネークケース(add_to_)、キャメルケース(addTo)、パスカルケース(AddTo)であればひな形が生成されます。

ケバブケース(add-to-)はやはりひな形は生成されません。

 

この項目のまとめ

 * add to からファイル名が始まることが条件
 * 〇 スネークケース(add_to_users)ではひな形が生成される
 * 〇 キャメルケース(addToUsers)ではひな形が生成される
 * 〇 パスカルケース(AddToUsers)ではひな形が生成される
 * × ケバブケース(add-to-users)ではひな形は生成されない
 

### コマンドを追加してテーブル名を指定することもできる
このように--table=テーブル名をコマンドに追加することでひな形付きのマイグレーションファイルを生成することができます。

```php artisan make:migration update_users --table=users```
 
----

こちらのブログに更新したものです
[Laravelのmake:migrationでテーブル名を指定して作成する方法](https://mashmy.net/blog/Laravel%E3%81%AEmake-migration%E3%81%A7%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E5%90%8D%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%97%E3%81%A6%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95)
boto3-stubsでBoto3の利用を楽にしたい

# はじめに

AWSを利用した開発をするにあたり、Boto3を使い始めました。
基本的には便利なのですが、type hintを使えず、IDEのコード補完も効かないので、
開発中は公式ドキュメントとIDEを何往復もし、何渡すんだっけ、何返ってくるんだっけしながらコピペするみたいなことをしていてとてもめんどくさいです。
そんなめんどくささから解放され、開発のスピードも上げていきたいということで見つけたのが[boto3-stubs](https://pypi.org/project/boto3-stubs/)です。
今回はそれを試してみようというのが本記事の目的です。

# やっていく
基本的にはPyCharm Community Editionでやっていきますが、
最後にVSCodeでもやります。

### 1. Project作成
pipenvを利用するところ以外は適当に入力して作成。
![スクリーンショット 2023-05-08 13.58.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602038/d442b086-81c8-b4de-5344-cbddd008916d.png)

### 2. パッケージのインストール

以下のコマンドを利用してboto3とboto3-stubsをインストールします。
```bash
pipenv install boto3
```
```bash
pipenv install 'boto3-stubs[sqs]'
```
今回はさっくりと試したいのでSQSのみをインストールしていますが、
複数のサービスを利用したい場合には`boto3-stubs[sqs, dynamodb]`のようにカンマ区切りでインストールすることができます。(大文字でもいけました)

### 試す

##### stubsを使わないパターン
```python
import boto3

def test() -> str:
    sqs = boto3.client("sqs")
```
よくあるクライアントを作成する時のコードです。
このままこのクライアントを使ってメッセージを受信する処理を作ろうと思ってもコード補完は効きません。
`boto3.client("service_name")`はメソッドの定義上Anyを返すので、返ってきたインスタンスで何ができるのかIDEでは予測しようがないためです。

##### stubsを利用してみる

クライアントを作るところはstubsを使わないパターンと一緒ですが、type hintの指定が異なります。
```python
import boto3
from mypy_boto3_sqs.client import SQSClient

def test() -> str:
    sqs_stubs: SQSClient = boto3.client("sqs")
```
`SQSClient`をtype hintに指定することでコード補完が可能になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602038/237e2bb5-bae0-07c2-b322-99f7c96f70cb.png)
これなら、ある程度用語などわかっていれば公式ドキュメントを見なくてもSQSの操作ができそうです。
さらに以下のようにレスポンスにもtype hintを適用することができます。
```python
def test() -> str:
    sqs_stubs: SQSClient = boto3.client("sqs")
    result: ReceiveMessageResultTypeDef = sqs_stubs.receive_message(QueueUrl="url")
    messages: List[MessageTypeDef] = result.get(key="Messages")
    message: MessageTypeDef = messages[0]
    body: str = message.get(key="Body")

    return body
```
定義されているkeyについては定義を見に行くことになりますが、
IDE内で完結しているため手間はかなり減りました。

## おまけ: VSCodeでもやってみる
VSCodeには便利な拡張機能があり、PyCharmよりもより便利にboto3-stubsを利用することができます。

利用するのは[AWS boto3](https://marketplace.visualstudio.com/items?itemName=Boto3typed.boto3-ide)です。
拡張機能のインストール後、Command Paletteから`AWS boto3: Auto-discover boto3 services in current project`を実行します。
すでにコードがある場合にはよしなにコード内を探して利用されているサービスにチェックを入れてくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602038/0051ffe0-cc26-5571-a5bd-aac3a92e21df.png)
調整してOKをすると、インストールが走ります。

そうするとこんな感じでtype hintなしでもコード補完が効くようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602038/ed7cf4b7-2eb7-5b5f-2532-044e59a73023.png)

type hintは書きたくないけどコード補完は欲しい場合にはこちらが有効そうです。
スクショ等は載せませんが、クライアント作成時点時に、SQSClientが返却されるようマウスオーバー表示があるのでその辺りも便利な拡張機能です。

# まとめ
使ってみた感じですが、type hint + コード補完によってかなり開発の速度が上がりそうな気がしています。
PyCharmとVSCodeで試し、拡張機能がある分VSCodeのほうが少し便利に使えますが、
PyCharmの方がレスポンスのキー確認などがしやすかったりします。
完全にお好みで問題ない範囲だと思います。

お疲れ様でした :coffee: 

# 参考
[Boto3の補完を可能にするboto3-stubsを使ってみる](https://dev.classmethod.jp/articles/try-boto3-stubs/)
[boto3-stubs を使って、boto3 でコード補完を有効にしよう](https://qiita.com/smatsumt/items/5235bcd794e634153982)
[Git] 動作を試す 実行例22：revertでコミットを削除する(コミット履歴に削除の記録が残る)

Gitの動作を理解するために、Gitのコマンドを実際に試して、結果を見てみました。

1つの記事内で一連のGitコマンドが完結しているので、これら一連のコマンドを順に実行させて結果を見ることで、一連のGitの動作を実際に体感でき、一通り独習することが可能です。

※前回記事のリポジトリ状態からの続きになっています。
| [前回記事へ](https://qiita.com/dl_from_scratch/items/3bd37ccf9b5afb1f7036) | [目次へ：Git関連記事のまとめページ](https://qiita.com/dl_from_scratch/items/597bc28a4787a7901d21) | [次回記事へ](https://qiita.com/dl_from_scratch/items/4046dd791d0beed50680) |
|:-:|:-:|:-:|

# 実行例

【Git入門】git commitを取り消したい、元に戻す方法まとめ - RAKUS Developers Blog | ラクス エンジニアブログ
https://tech-blog.rakus.co.jp/entry/20210528/git
↓
引用: 
「revert」はpush済みのコミットを打ち消したいときに便利です。
push済のコミットの上に、新しいコミットを乗せる形でコミットを元に戻すことができるからです。
コミット自体を削除するわけではないので、安全にコミットを元に戻すことができます。

```
(※ひとまず適当に変更の操作)
echo Sample-Added-15(before-revert) >> test1.txt
git commit -a -m "message7"
type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-14
Sample-Added-15(before-revert)

git log --oneline
↓
結果: 
f6715f9 (HEAD -> master) message7
94996a0 message4
20bbab7 message3
00cad71 message2
4ace194 message1

-----

※HEADは最新のコミットを指し、最新のコミットを削除して1つ前へ戻す。
※「--no-edit」でコミットメッセージを編集しない(エディタを開かない)。Windowsのコマンドプロンプトで実行するとエラーとなる為、エディタを開かない。
git revert HEAD --no-edit
↓
結果: 
[master b7cf3a2] Revert "message7"
 Date: Sun Jan 1 20:04:14 2023 +0900
 1 file changed, 1 deletion(-)

type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-14

git log --oneline
↓
結果: 
b7cf3a2 (HEAD -> master) Revert "message7"
f6715f9 message7
94996a0 message4
20bbab7 message3
00cad71 message2
4ace194 message1

-----

git revert "HEAD^^^..HEAD" --no-edit
↓
結果: 
[master 143bc5a] Revert "Revert "message7""
 Date: Sun Jan 1 20:10:41 2023 +0900
 1 file changed, 1 insertion(+)
[master 524cb9e] Revert "message7"
 Date: Sun Jan 1 20:10:41 2023 +0900
 1 file changed, 1 deletion(-)
[master 307814b] Revert "message4"
 Date: Sun Jan 1 20:10:41 2023 +0900
 2 files changed, 2 deletions(-)
 delete mode 100644 test4.txt

type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13

git log --oneline
↓
結果: 
307814b (HEAD -> master) Revert "message4"
524cb9e Revert "message7"
143bc5a Revert "Revert "message7""
b7cf3a2 Revert "message7"
f6715f9 message7
94996a0 message4
20bbab7 message3
00cad71 message2
4ace194 message1

git status
↓
結果: 
On branch master
nothing to commit, working tree clean

-----

(※以降は内容確認用のコマンド実行)
git checkout 20bbab7
↓
結果: 
Previous HEAD position was 307814b Revert "message4"
HEAD is now at 20bbab7 message3

type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13

git checkout 94996a0
↓
結果: 
Previous HEAD position was 20bbab7 message3
HEAD is now at 94996a0 message4

type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-14

-----

(※始めの状態に戻す)
git reset --hard 94996a0
git log --oneline
↓
結果: 
94996a0 (HEAD -> master) message4
20bbab7 message3
00cad71 message2
4ace194 message1
```

# 環境

Windows 10、PortableGit-2.40.0-64-bitを使用、全てローカルPC上で実施、GitHub等は不使用。
[Git] 動作を試す 実行例21：--amendで前回コミット内容を修正する

Gitの動作を理解するために、Gitのコマンドを実際に試して、結果を見てみました。

1つの記事内で一連のGitコマンドが完結しているので、これら一連のコマンドを順に実行させて結果を見ることで、一連のGitの動作を実際に体感でき、一通り独習することが可能です。

※前回記事のリポジトリ状態からの続きになっています。
| [前回記事へ](https://qiita.com/dl_from_scratch/items/ef2484788126226ea5cc) | [目次へ：Git関連記事のまとめページ](https://qiita.com/dl_from_scratch/items/597bc28a4787a7901d21) | [次回記事へ](https://qiita.com/dl_from_scratch/items/3b05caf020d621d89568) |
|:-:|:-:|:-:|

# 実行例

```
git log --oneline
↓
結果: 
94996a0 (HEAD -> master) message4
20bbab7 message3
00cad71 message2
4ace194 message1

(※ひとまず適当に修正する操作)
echo Sample-Added-14(corrected) >> test1.txt
echo Sample-Added-41(corrected) > test4.txt
type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-14
Sample-Added-14(corrected)

※前回のコミットを上書き修正する。
git add .
git commit --amend -m "message4(corrected)"
↓
結果: 
[master baaf962] message4(corrected)
 Date: Sun Jan 1 18:10:58 2023 +0900
 2 files changed, 3 insertions(+)
 create mode 100644 test4.txt

git log --oneline
↓
結果: 
baaf962 (HEAD -> master) message4(corrected)
20bbab7 message3
00cad71 message2
4ace194 message1

※コミットSHA値が変化する

-----

(※始めの状態に戻す)
git reset --hard 94996a0
git log --oneline
↓
結果: 
94996a0 (HEAD -> master) message4
20bbab7 message3
00cad71 message2
4ace194 message1

type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-14
```

# 環境

Windows 10、PortableGit-2.40.0-64-bitを使用、全てローカルPC上で実施、GitHub等は不使用。
[Git] 動作を試す 実行例20：reflogでこれまでの操作を戻す

Gitの動作を理解するために、Gitのコマンドを実際に試して、結果を見てみました。

1つの記事内で一連のGitコマンドが完結しているので、これら一連のコマンドを順に実行させて結果を見ることで、一連のGitの動作を実際に体感でき、一通り独習することが可能です。

※前回記事のリポジトリ状態からの続きになっています。
| [前回記事へ](https://qiita.com/dl_from_scratch/items/1a664d561e03b54587b9) | [目次へ：Git関連記事のまとめページ](https://qiita.com/dl_from_scratch/items/597bc28a4787a7901d21) | [次回記事へ](https://qiita.com/dl_from_scratch/items/3bd37ccf9b5afb1f7036) |
|:-:|:-:|:-:|

# 実行例

【Git入門】git commitを取り消したい、元に戻す方法まとめ - RAKUS Developers Blog | ラクス エンジニアブログ
https://tech-blog.rakus.co.jp/entry/20210528/git
↓
引用: 
「git reflog」を使用すると過去の操作履歴(HEADの動き)を確認することができます。
「git reflog」で「reset」を取り消すことができます。
　1. git reflogで操作履歴を見る
　2. 戻りたい地点の数字を指定してgit resetする(resetで過去のresetを元に戻す)

```
(※ひとまず適当に変更の操作)
echo Sample-Added-15(after-reset) >> test1.txt
git commit -a -m "message6(after-reset)"
type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-14
Sample-Added-15(after-reset)

git reset --hard 00cad71
git log --oneline
↓
結果: 
00cad71 (HEAD -> master) message2
4ace194 message1

-----

※gitの操作履歴を表示する
git reflog
↓
結果: 
00cad71 (HEAD -> master) HEAD@{0}: reset: moving to 00cad71
814bbc1 HEAD@{1}: commit: message6(after-reset)
94996a0 HEAD@{2}: reset: moving to 94996a0
9559e87 HEAD@{3}: commit: message5(after-reset)
00cad71 (HEAD -> master) HEAD@{4}: reset: moving to 00cad71
94996a0 HEAD@{5}: reset: moving to 94996a0
...省略...

※操作履歴から選んで戻す
git reset --hard HEAD@{2}
↓
結果: 
HEAD is now at 94996a0 message4

git log --oneline
↓
結果: 
94996a0 (HEAD -> master) message4
20bbab7 message3
00cad71 message2
4ace194 message1

type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-14
```

# 環境

Windows 10、PortableGit-2.40.0-64-bitを使用、全てローカルPC上で実施、GitHub等は不使用。
特許情報取得APIのワンポータルドシエ情報提供対応 easy_patentsアップデートのお知らせ

# 概要
 特許情報取得APIのワンポータルドシエの情報提供に対応してeasy_patentsをアップデートした。

# インストール/アップデートの仕方
```py
pip install easy-patents==1.0.13
```

# 使い方の例

```py
>>> from easy_patents.get_info import family
>>> family_info = family("JP.2015500001.A", "application")
>>> family_info['api-data']['family-data']['families']['family'][0]['country']
'JP'
```

上記のように、apiの名前と同一の関数名を指定し、第１引数にDOCDB形式の出願番号又は公開・登録番号、第２引数に必要に応じて"application", "publication"のような種別(seed)か書類IDを指定する。

取得されたデータは以下の通りとなる。
XMLの場合、xmltodictによりdict形式またはjson形式に変換される。
zipの場合、unzip後のファイルパスが返される。
pdfの場合、保存先のファイルパスが返される。

# 追加した関数
```py
family(case_number, seed, reget_date=1)
family_list(case_number, seed, reget_date=1)
global_doc_list(case_number, reget_date=1)
global_cite_class(case_number, reget_date=1)
jp_doc_cont(case_number, document_id, reget_date=1)
global_doc_cont(case_number, document_id, reget_date=1)
```

case_numberは、DOCDB形式の出願番号又は公開・登録番号
 case_numberについての変換等は行われない。
seedは、"application", "publication"のような種別
document_idは書類ID
Python　アルファベット順に並べる

# Pythonでアルファベット順に並べる方法

## 説明
[公式ドキュメント](https://docs.python.org/ja/3/howto/sorting.html)
list.sort()メソッド、またはsorted()関数を使います。

```python:sample.py
sorted([5, 2, 3, 1, 4])
#[1, 2, 3, 4, 5]

a = [5, 2, 3, 1, 4]
a.sort()
#[1, 2, 3, 4, 5]
```

## The Zen of Pythonを並べ替え

**The Zen of Python**を使って試してみましょう。

``` :The Zen of Python
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those! 
```

```python:abc_order.py
with open("zen-of-python.txt") as f:
    data = f.read().split()
    new_data = sorted(data)
    print(new_data)

#実行結果
['*right*', '--', '--obvious', 'Although', 'Although', 'Although', 'Beautiful', 'Complex', 'Dutch.', 'Errors', 'Explicit', 'Flat', 'If', 'If', 'In', 'Namespaces', 'Now', 'Peters', 'Python,', 'Readability', 'Simple', 'Sparse', 'Special', 'The', 'There', 'Tim', 'Unless', 'Zen', 'a', 'a', 'ambiguity,', 'and', 'are', "aren't", 'at', 'bad', 'be', 'be', 'be', 'beats', 'better', 'better', 'better', 'better', 'better', 'better', 'better', 'better', 'break', 'by', 'cases', 'complex.', 'complicated.', 'counts.', 'dense.', 'do', 'do', 'easy', 'enough', 'explain,', 'explain,', 'explicitly', 'face', 'first', 'good', 'great', 'guess.', 'hard', 'honking', 'idea', 'idea.', 'idea.', 'implementation', 'implementation', 'implicit.', 'is', 'is', 'is', 'is', 'is', 'is', 'is', 'is', 'is', 'is', 'it', "it's", 'it.', "let's", 'may', 'may', 'more', 'nested.', 'never', 'never', 'never.', 'not', 'now.', 'obvious', 'of', 'of', 'of', 'often', 'one', 'one', 'one--', 'only', 'pass', 'practicality', 'preferably', 'purity.', 'refuse', 'rules.', 'should', 'should', 'silenced.', 'silently.', 'special', 'temptation', 'than', 'than', 'than', 'than', 'than', 'than', 'than', 'than', 'that', 'the', 'the', 'the', 'the', 'the', 'those!', 'to', 'to', 'to', 'to', 'to', 'ugly.', 'unless', 'way', 'way', "you're"]
```

## まとめ
アルファベット文字列が要素のリストをソートすると、アルファベット順になって返ってきます。
Python3: OracleDB のデータを削除 (Delete)

## プログラム

```py:oracle_delete.py
#! /usr/bin/python
#
#	oracle_delete.py
#
#					May/09/2023
#
# --------------------------------------------------------
import	sys
import	oracledb
#
# --------------------------------------------------------
def	sql_delete_proc(cursor_aa,key_in):
#
	sql_str="delete from cities where id = '%s'" % key_in
	cursor_aa.execute(sql_str)
# --------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
id_in = sys.argv[1]
print("%s" % id_in)
#
host = "172.17.0.2"
user = "scott"
password = "tiger123"

str_connect = user + "/" + password + "@" + host + ":1521/XEPDB1"
conn = oracledb.connect(str_connect)
#
cursor = conn.cursor()
#
sql_delete_proc(cursor,id_in)
#
cursor.close()
conn.commit()
conn.close()
#
sys.stderr.write("*** 終了 ***\n")
#
# --------------------------------------------------------
```

## 実行コマンド

```bash
./oracle_delete.py t0138
```

## 確認したバージョン

```text
$ python --version
Python 3.11.3
```
Python3: OracleDB のデータを更新 (Update)

## プログラム

```py:oracle_update.py
#! /usr/bin/python
#
#	oracle_update.py
#
#					May/09/2023
#
#	to_date ('2009/7/23 16:20:15','YYYY/MM/DD HH24:MI:SS')
# --------------------------------------------------------
import	sys
import	oracledb
import	string
from time import localtime,strftime
#
# --------------------------------------------------------
def	oracle_sql_update_string_gen_proc(id_in,ipop_in):
	date_mod = strftime ("%d-%b-%Y",localtime ())
	ft_aa=u"update cities set population = %d, " % ipop_in
	ft_bb=u"date_mod='%s' " % date_mod
	ft_cc=u"where id = '%s'" % id_in
	sql_str=ft_aa + ft_bb + ft_cc
	print (sql_str)
#
	return	sql_str
# --------------------------------------------------------
def	oracle_sql_update_proc(cursor_aa,id_in,ipop_in):
#
	sql_str = oracle_sql_update_string_gen_proc(id_in,ipop_in)
	cursor_aa.execute(sql_str)
# --------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
id_in = sys.argv[1]
population_in = int(sys.argv[2])
print("%s\t%d" % (id_in, population_in))
#
host = "172.17.0.2"
user = "scott"
password = "tiger123"

str_connect = user + "/" + password + "@" + host + ":1521/XEPDB1"
conn = oracledb.connect(str_connect)
#
cursor = conn.cursor()
#
oracle_sql_update_proc(cursor,id_in,population_in)
conn.commit()
#
cursor.close()
conn.close()
sys.stderr.write("*** 終了 ***\n")
#
# --------------------------------------------------------
```

## 実行コマンド

```bash
./oracle_update.py t0132 45621300
```

## 確認したバージョン

```text
$ python --version
Python 3.11.3
```
Python3: OracleDB のデータを読む (Read)

## プログラム

```py:oracle_read.py
#! /usr/bin/python
#
#	oracle_read.py
#
#					May/09/2023
# --------------------------------------------------------------
import	sys
import	oracledb
#
# --------------------------------------------------------------
def	sql_display_proc(cursor):
	sql_str="select id, name, population, date_mod from cities order by id"
	cursor.execute(sql_str)
	rows = cursor.fetchall()
	for row in rows:
		print(row[0],row[1],row[2],row[3])
#
# --------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
host = "172.17.0.2"
user = "scott"
password = "tiger123"
#
str_connect = user + "/" + password + "@" + host + ":1521/XEPDB1"
conn = oracledb.connect(str_connect)
cursor = conn.cursor()
#
sql_display_proc(cursor)
#
cursor.close()
conn.close()
#
sys.stderr.write("*** 終了 ***\n")
#
# --------------------------------------------------------------
```

## 実行コマンド

```bash
./oracle_read.py
```

## 確認したバージョン

```text
$ python --version
Python 3.11.3
```
AWS Summitに参加してみた

# 目次
* はじめに
* 会場の雰囲気
* 基調講演、スペシャルセッション
* 企業ブース巡り
* 昼食
* 特に面白かったセッション
* あとがき
# はじめに
こんにちは、元先生のインフラエンジニアです。
今回は研修としてAWS Summitに行って来たので、その報告をしようと思います。
弊社の中で報告会をする予定なので、その資料を流用させていただきます。
# 会場の雰囲気
![51E2535C-B3B0-45A0-A2D0-05010959D324.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2773852/e0ad2f22-75e1-bbf8-ed42-eb030438fbb3.jpeg)
久方ぶりの開催となりましたが、大盛況でした。
歩くのに困る混雑があったり、ブースによってはしっかり行列ができたりする様子もありました。
先着でお弁当の配布やクッションの配布があったので、会場前から入場待ちの行列もできていました。
面白かったのは昼過ぎに、「サステナビリティを考慮して、余ったお弁当を配布する」というイベントが突如あったことです。
私は初めての参加でしたが、飽きずに最後まで楽しめました。
# 基調講演、スペシャルセッション
大きくまとめると
「AIにも力入れたよ、他にも色々新しいもの出るよ」
「色々な企業に使ってもらってるよ」
「サステナビリティ頑張るよ」
の3点が印象に残りました。
ぶっちゃけ、話が全体的にフワフワし過ぎて間延び感がありました。
# 企業ブース巡り
なかなか楽しかったです。
ノベルティを沢山もらえたし、実りのある話を色々聞けました。
特にスタートアップさんの導入事例が多いとは思いましたが、多種多様な企業が参加していました。
所構わずノベルティをもらっていたら、後で営業メールが沢山来ていました。
# 昼食
私は1日目だけもらいましたが、まい泉のカツサンド弁当でした。豪華。
先着でチケットを配布していましたが、ある程度時間が経つと余った分を配布していました。サステナなんちゃらへの配慮でしょう。
# 特に面白かったセッション
某ゲームソフト企業さんが、「開発環境をオンプレからクラウドに移行してみた」という事例を発表していました。空いたスペースが立ち見で埋まるほどの盛況で、予算と導入ペースの話なんかも含めて、とても現実味のある話が聞けました。
# あとがき
今回は以上になります。
後半は諸々の権利が怖くなって画像を控えましたが、とにかく感想は「直接行って良かった楽しかった」でいいかなと思います。
また似たような機会があれば、ぜひ参加したいです。
最後までお読みくださり、ありがとうございました。
Python3: OracleDB のデータを作成 (Create)

## プログラム

```py:oracle_create.py
#! /usr/bin/python
#
#	oracle_create.py
#
#					May/09/2023
#
# --------------------------------------------------------
import	sys
import	datetime
import	string
import	oracledb
#
# --------------------------------------------------------
def	create_table_proc(cursor_aa):
	sql_str="create table cities (id varchar(10) primary key, name varchar(20)," \
		+ " population int, date_mod date)"
#
	try:
		cursor_aa.execute(sql_str)
	except Exception as ee:
		sys.stderr.write("*** error *** create_table_proc ***\n")
		sys.stderr.write(str (ee) + "\n")
#
# --------------------------------------------------------
def	drop_table_proc(cursor_aa):
	sql_str="drop table cities"
	try:
		cursor_aa.execute(sql_str)
	except Exception as ee:
		sys.stderr.write("*** error *** drop_table_proc ***\n")
		sys.stderr.write(str (ee) + "\n")
#
# --------------------------------------------------------
def dict_append_proc(dict_aa,key,name,population,date_mod):
	dict_aa[key] = {'name':name,'population':population,'date_mod':date_mod}
#
	return dict_aa
#
# --------------------------------------------------------
def	data_prepare_proc():
#
	dict_aa = {} 
#
	dict_aa = dict_append_proc(dict_aa,'t0131','函館',38172,'2003-4-30')
	dict_aa = dict_append_proc(dict_aa,'t0132','札幌',47935,'2003-5-10')
	dict_aa = dict_append_proc(dict_aa,'t0133','帯広',21354,'2003-6-14')
	dict_aa = dict_append_proc(dict_aa,'t0134','釧路',83672,'2003-2-9')
	dict_aa = dict_append_proc(dict_aa,'t0135','旭川',42391,'2003-8-4')
	dict_aa = dict_append_proc(dict_aa,'t0136','北見',35187,'2003-1-21')
	dict_aa = dict_append_proc(dict_aa,'t0137','室蘭',81246,'2003-7-23')
	dict_aa = dict_append_proc(dict_aa,'t0138','根室',24784,'2003-10-26')
	dict_aa = dict_append_proc(dict_aa,'t0139','稚内',75823,'2003-12-15')
#
	return	dict_aa
#
# --------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
dict_aa = data_prepare_proc()
#
host = "172.17.0.2"
user = "scott"
password = "tiger123"
#
str_connect = user + "/" + password + "@" + host + ":1521/XEPDB1"
conn = oracledb.connect(str_connect)
cursor = conn.cursor()
drop_table_proc(cursor)
create_table_proc(cursor)
#
for key in dict_aa:
	unit = dict_aa[key]
	name = unit['name']
	population = unit['population']
	date_mod = unit['date_mod']
	ddx = datetime.datetime.strptime(date_mod, '%Y-%m-%d')
	dd_oracle = ddx.strftime('%d-%b-%Y')
	ft_aa="insert into cities (id,name,population,date_mod) values ("
#
	ft_bb ="'%s','%s',%d,'%s')" % (key,name,population,dd_oracle)
	sql_str=ft_aa + ft_bb
	cursor.execute (sql_str)
#
conn.commit ()
#
#sql_display_proc(cursor)
#
cursor.close()
conn.close()
sys.stderr.write("*** 終了 ***\n")
#
# --------------------------------------------------------
```

## 実行コマンド

```bash
./oracle_create.py
```

## 確認したバージョン

```text
$ python --version
Python 3.11.3
```
RustでHelloWorldプログラムを実装してみた

# 概要
RustでHelloWorldプログラムを実装してみました。以下のページを参考にしました。
https://doc.rust-jp.rs/book-ja/ch01-02-hello-world.html

# 環境構築
以下のコマンドを実行しました。コンパイラをインストールしています。
```
$ sudo apt install rustc
```

# プログラム実装
以下の通りソースコードを実装しました。上記のページを参考にしました。
```main.rs
fn main() {
    // 世界よ、こんにちは
    println!("Hello, world!");
}
```

# コンパイル
以下のコマンドを実行しました。
```
$ rustc main.rs
```

# プログラム実行
以下のコマンドを実行しました。
```
$ ./main
Hello, world!
```

無事動いているようです。

何かの役に立てばと。
Cloud RunとAlloyDBでWEBアプリを作った話

## はじめに
Cloud RunとAlloyDBでWEBアプリを作ったので、こういった構成を考えている方にとって参考になればと思い書いておく。公式ドキュメントに設定方法はあるので、設定方法と言うよりは使ってみた感想に重きをおいて書く。

## 筆者について
Google Cloudは触ったことが無いが、今回Webアプリを作成することになったので、アーキテクチャを考えた。
それに先立ち、Google Cloudの資格(Google Cloud Certified Associate Cloud Engineer)を取得したり、GCEやGKEとCloud Runを比較したりして今回の構成にした。

## 構成図
![スクリーンショット 2023-05-09 18.47.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3361865/de8ab4b3-4f82-21e0-16e5-d17524748eaf.png)

## 構成図の環境の作成方法
[Connect from Cloud Run(公式ドキュメント)](https://cloud.google.com/alloydb/docs/quickstart/integrate-cloud-run)を参考にすればCloud RunとAlloyDBの環境ができる。
ちなみに、AlloyDBのIPアドレスは自動で割り当てられるので、自動で割り当てられたIPアドレスを、Cloud Runの環境変数([INSTANCE_HOST](https://cloud.google.com/alloydb/docs/quickstart/integrate-cloud-run#:~:text=DB_PORT%3A%205432-,INSTANCE_HOST,-%3A%20The%20IP%20address))に設定する。AlloyDBに対してIPアドレスの範囲のVPCネットワークを設定するので致し方ない。

Cloud Load BalancingとCloud Runの設定方法は他の記事を参考にして頂ければと思う。

デプロイの設定に関してはCloud ConsoleでCloud Runを開くと[**継続的デプロイを編集します**]のボタンがあり、そこから設定できる。GitHubのリポジトリとブランチの設定くらいなので難しくない。

## 感想
### Cloud Run
- Good
  - デプロイが簡単。GitHubのリポジトリとブランチを設定すれば、そのブランチにpushすると自動でCloud Runにデプロイされる。
  - 従量課金で無料枠もそれなりにある([毎月200万リクエストとか色々](https://cloud.google.com/run/pricing?hl=ja#:~:text=%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%AE%E5%87%A6%E7%90%86%E4%B8%AD%E3%81%AB%E3%81%AE%E3%81%BF%20CPU%20%E3%82%92%E5%89%B2%E3%82%8A%E5%BD%93%E3%81%A6%E3%82%8B%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%81%AE%E6%96%99%E9%87%91))ので、無料枠内で収めることも可能。ただし、常時インスタンスを起動するような設定だと月数千円はかかるかもしれない。

- Bad
  - 今回触った感じでは見つからなかった。

### AlloyDB
- Good
  - 設定が簡単。高可用性、CPUとメモリの設定とかくらい。
  - 自動バックアップ機能があり、設定した時間帯に取得してくれる。
  - Query Insightsでクエリの負荷が見える。
  - Postgresとの能力比較は行なっていないが、ハイパフォーマンスらしい
  - 現在Postgresで動作している場合は、そのまま移行ができるらしい([参考記事](https://zenn.dev/google_cloud_jp/articles/0ad5a4dd22c7cd))


- Bad
  - 最低スペックでも常時稼働するなら月8万程度の費用が必要。
  - 自動バックアップの取得もできるが、詳細な設定はCloud Consoleではなくgcloud CLIで操作([公式リファレンス](https://cloud.google.com/sdk/gcloud/reference/alloydb/clusters/update))。
  - 再起動しかできず、停止ができない。そのため、開発環境のように停止したい場合に困る。停止しないとお金がかかるので。私の場合は、Cloud ConsoleからAlloyDBのバックアップを取得して、インスタンスを削除して運用をしている。必要があれば、バックアップを復元すれば良いので。ただしIPアドレスが変わってしまうため、DBへの接続するアプリ側の接続先IPの変更も必要なのが厄介。

## 終わりに
初めに調べていた時は色々つまづいたが、最終的にはスッキリした構成でWEBアプリの作成ができた。Cloud Runは費用が安価で、デプロイも簡単なので良いコンポーネントと言う感想。また、AlloyDBは能力が活かせれたら強い味方になると信じて終わりの言葉とする。
imdb clone Part10　8 TMDBのAPIからデータ取得 レスポンスをコンソール結果で確認

# 概要
今回はTMDBのAPIからデータ取得 そのレスポンスをコンソール結果で確認します。
以下画像はTMDBのAPIのレスポンス結果をコンソール上で確認しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/91a44941-a912-d6e6-f654-663e73fba3dc.png)


# 開発環境

OS:Windows10
IDE:VSCode

"@next/font": "13.1.5",
"autoprefixer": "10.4.14",
"eslint": "8.39.0",
"eslint-config-next": "13.3.1",
"next": "13.3.1",
"postcss": "8.4.23",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-icons": "^4.8.0",
"tailwindcss": "3.3.2"

# TMDBのAPIを使う
The Movie Database (TMDB)に会員登録してAPIキーを取得します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/85eab89d-c4f7-3cf6-f8a1-796913ebf69c.png)


# 実装のポイント
TMDBのAPIを叩きます。APIキーは.env.localから入手します。
レスポンスはconsole.logでターミナル上で確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/5731c619-c33d-992f-4de5-58e42918020e.png)




# コード部分
## page
```diff_jsx:page.jsx
import { Inter } from "@next/font/google"

+ const API_KEY = process.env.API_KEY;


+ export default async function Home({searchParams}) {
+  const genre = searchParams.genre || "fetchTrending";
  
+  const res = await fetch(
+    `https://api.themoviedb.org/3/${
+      genre === "fetchTopRated" ? "movie/top_rated" : "trending/all/week"
+  }?api_key=${API_KEY}&language=en-Us%&page=1`,
+  {next:{revalidate: 10000}}
+  );

+  if(!res.ok){
+    throw new Error("Failed to fetch data");
+  }

+  const data = await res.json();
+  console.log(data);

  return (
    <h1 className='text-red-300'>HOME</h1>
  )
}
```




# 参考

TMDB

https://www.themoviedb.org/

API ドキュメント

https://developers.themoviedb.org/3/getting-started/introduction

Trending
https://developers.themoviedb.org/3/trending/get-trending


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/ce250515-6355-9297-fdb9-b725355ae907.png)

top_rated

https://developers.themoviedb.org/3/movies/get-movie-details

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/18fac6be-36a8-c912-9ca6-2ebc1a906ccf.png)




## その他



Udemy

githubコミット分

https://github.com/RYA234/imcbclone/commit/2ac6da1b058beb2f8529c847d705fd0c84cbbea0
imdb clone Part9　7 navbar実装 2/2  hover処理追加　開いているNavの下線部をハイライト

# 概要
目次

https://qiita.com/RYA234/private/045f3d2c03684572d3f9

今回はナビゲーションバーの選択しているNavにハイライトが入るよう実装します。
下gifアニメは実装後にアイテムを切り替えている様子です。

![fffffff.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/3db131f5-0e6b-4f18-240c-30a07a246811.gif)


# 開発環境

OS:Windows10
IDE:VSCode

"@next/font": "13.1.5",
"autoprefixer": "10.4.14",
"eslint": "8.39.0",
"eslint-config-next": "13.3.1",
"next": "13.3.1",
"postcss": "8.4.23",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-icons": "^4.8.0",
"tailwindcss": "3.3.2"

# 実装のポイント
ハイライトを実装するには現在のURLのパラメーターとコンポーネントのパラメーター比較してcssの切り替えをできるようにします。
例えばTrendingを選択している場合
Trendingのコンポーネントはgenreとparamが一致しているのでハイライトのcssは反映されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/54834bd1-c26f-19c6-6499-fde9550004ba.png)


一方でTopRatedのコンポーネントはgenreとparamが値不一致しておりハイライトのcssは施されません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/0b9a3cf2-6e2b-4a2e-be34-5ce3a1e3bbea.png)


# コード部分
## NavbarItem
```diff_jsx:NavbarItem.jsx
+"use client"

import React from 'react'
import Link from "next/link";
import { useSearchParams } from "next/navigation";

export default function NavbarItem({title,param}) {

+    const searchParams = useSearchParams();
+    const genre = searchParams.get("genre");

-  return (
-    <div className={`font-semibold p-2`}>
+    return (
+    <div className={`m-4 hover:text-amber-600 font-semibold p-2 ${
+        genre &&
+        genre === param &&
+        "underline underline-offeset-8 decoration-4 decoration-amber-500 rounded-lg"
+    }`}>
           <Link href={`/?genre=${param}`}>
                {title}
           </Link>    
    </div>
  )
}

```




# 参考

useSearchParam

https://nextjs.org/docs/app/api-reference/functions/use-search-params


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/a6e5a450-ee84-76c2-d12c-6f4759a29d45.png)




## その他



Udemy

https://www.udemy.com/course/react-js-tutorial/learn/lecture/36119274#overview

githubコミット分

https://github.com/RYA234/imcbclone/commit/256846d8e03dcf3e243bf09c49e6d5b4f5b2be26
imdb clone Part8　7 navbar実装 1/2 基本的な実装

# 概要
目次

https://qiita.com/RYA234/private/045f3d2c03684572d3f9

今回はナビゲーションバーの基本部分を実装します。
以下gifアニメは実装後の様子です。ナビゲーションのアイテムを押すとURLが変更されます。

![uuuuuuuuuuuuuu.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/38b055a6-d172-8413-f930-85916dde01a1.gif)




# 開発環境

OS:Windows10
IDE:VSCode

"@next/font": "13.1.5",
"autoprefixer": "10.4.14",
"eslint": "8.39.0",
"eslint-config-next": "13.3.1",
"next": "13.3.1",
"postcss": "8.4.23",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-icons": "^4.8.0",
"tailwindcss": "3.3.2"

# 実装のポイント
1.ナビゲーションを押したときの動き（下図）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/78a1c911-0801-2200-9fbe-8b8675a55a61.png)


2.レイアウトのCSS
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/0405bce4-c369-2236-8965-134db2010ccc.png)


# コード部分

## layout
```diff_jsx:layout.jsx
import './globals.css'
import Header from '@/components/Header'
import Providers from './Providers'
+import Navbar from '@/components/Navbar'

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <Providers>
          {/* Header */}
          <Header />

          {/* Navbar */}
+          <Navbar />

          {/* SearchBox */}

          {children}
        </Providers>
      </body>
    </html>
  );
}
```

## Navbar
```diff_jsx:Navbar.jsx
import React from 'react'
import NavbarItem from './NavbarItem'

export default function Navbar
() {
  return (
    <div className="flex justify-center dark:bg-gray-600 bg-amber-100 lg:text-lg p-4">
            <NavbarItem title="Trending" param="fetchTrending" />
            <NavbarItem title="Top Rated" param="fetchTopRated" />

    </div>
  )
  }

```

## NavbarItem
```diff_jsx:NavbarItem.jsx
import React from 'react'
import Link from "next/link";

export default function NavbarItem({title,param}) {
  return (
    <div className={`font-semibold p-2`}>
           <Link href={`/?genre=${param}`}>
                {title}
           </Link>    
    </div>
  )
}

```





# 参考

## css




### font-semibold p-2

https://tailwindcss.com/docs/font-weight

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/bd02a188-d438-fd41-8f47-b150d7490d10.png)

### flex justify-center


https://developer.mozilla.org/ja/docs/Web/CSS/justify-content

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/232125bd-4cfa-d250-84c7-23fdabbc84e1.png)


## その他

Udemy

https://www.udemy.com/course/react-js-tutorial/learn/lecture/36119280#overview

githubコミット分

https://github.com/RYA234/imcbclone/commit/862b119fe6ba8b81e9bd8066082f3fb694155502
【TypeScript】開発環境の準備方法メモ

## はじめに
どうも、TypeScript勉強中の👶です。
理解を深めるために日々の学びを記事にしています。
初心者の記事なので言い回しや記載に誤りがあるかも知れませんが、暖かく見守っていただけると幸いです。
<font color="gray">(よろしければ間違いをコメントいただけると学び、励みになります！)</font>

## 学んだこと
・TypeScriptの開発環境の準備方法

## 前提
node.jsインストールは完了しているところからのスタートです。

## ディレクトリ作成
```console
$ mkdir ディレクトリ名
$ cd ディレクトリ名
```
## npmインストール
```console
$ npm init --yes
```
package.jsonが作成されるので、下記内容を変更
```json
"main":"index.js",
↓↓↓
"main":"index.js",
"type":"module",
```
## Typescriptと@types/nodeのインストール
```console
$ npm install --save-dev typescript @types/node
```


### (補足)gitをcloneしてきた場合
gitをcloneしてきた場合、package.jsonやpackage.lock.jsonはあるが、module_nodeはない（gitignore設定のため）状態なので、下記を実行して生成する。
```console
$ npm install
```


## tsconfig.jsonの準備
```console
$ npx tsc --init
```
`tsconfig.json`はTypeScriptコンパイラの設定ファイルです。

tsconfig.jsonを編集します。
```json
{
    "compilerOptions":{
        // トランスパイルの程度(デフォルト: "es2016")
        "target": "es2020",
        
        // moduleコンパイラ(デフォルト: "commonjs")
        "module":"esnext"
        
        // moduleResolutionコンパイラオプションをnode(コメント解除)する
        "moduleResolution":"node"
        
        // outDirコンパイラオプション(コンパイラ出力ディレクトリを指定）
        // コメントアウトを解除して出力ディレクトリを変更
        ↓
        "outDir": "./dist"
    },
            
    // includeオプション (コンパイル対象の指定)
    "include":["./src/**/*.ts"]
}
```

## ファイル作成
srcディレクトリを作成し、その中にTypeScriptを記載するファイル(.ts)を作成します。

## コンパイル実行
```console:
$ npx tsc
```

実行すると、なんと摩訶不思議！
distファイルにコンパイル後のコード(.js)が出力されます。

## コードをNode.jsで実行する
動くのはコンパイル後のファイルです。
```console
$ node dist/index.js
```
imdb clone Part7　5 Add a darkMode 5/5　cssの設定ダークモードの色　アイコンのカーソル

# 概要
目次

https://qiita.com/RYA234/private/045f3d2c03684572d3f9


今回は　cssの設定ダークモードの色　アイコンのカーソルを合わせたときにアイコンの色が変わるように変更します。

以下gifアニメは実装後の様子です

![ccccccccccc.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/60507840-9a8b-9ba2-31ff-6bcf0ad782d0.gif)



# 開発環境

OS:Windows10
IDE:VSCode

"@next/font": "13.1.5",
"autoprefixer": "10.4.14",
"eslint": "8.39.0",
"eslint-config-next": "13.3.1",
"next": "13.3.1",
"postcss": "8.4.23",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-icons": "^4.8.0",
"tailwindcss": "3.3.2"

# 実装のポイント
1.ダークモード時背景と文字の色を変更する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/3c5acc93-441d-3cb7-4924-7e4f29252c07.png)


2.アイコンにカーソルを合わせたときの処理

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/5921d6cc-0887-5cc2-2290-d72041d650f1.png)





# コード部分
## Provider
```diff_jsx:Provider.jsx
"use client"
import { ThemeProvider } from 'next-themes'
import React from 'react'

export default function Providers({children}) {
  return (
    <ThemeProvider enableSystem={true} attribute="class">
+        <div className="dark:bg-gray-700 dark:text-gray-200 transition-colors duration-300 min-h-screen select-none">
        {children}
+        </div>
    </ThemeProvider>
  )
}

```

## DarkModeSwitch
```diff_jsx:DarkModeSwitch.jsx
"use client";
import {useEffect, useState } from 'react'
import {MdLightMode} from "react-icons/md";
import {BsFillMoonFill} from "react-icons/bs"
import {useTheme} from "next-themes";


export default function DarkModeSwitch() {
    const{systemTheme,theme,setTheme} = useTheme();
    const [mounted,setMounted] = useState(false);

    useEffect(() => setMounted(true),[]);
    
    const currentTheme = theme === "system" ? systemTheme : theme;
    
    return (
    <>  
        {mounted && ( currentTheme === "dark" ? (
            <MdLightMode 
+                className="text-xl curor-pointer hover:text-amber-500"
                onClick={() => setTheme("light")}/>) : (
-         <BsFillMoonFill onClick={() => setTheme("dark")}/>))}
+        <BsFillMoonFill className="text-xl cursor-pointer hover:text-amber-500" onClick={() => setTheme("dark")}/>))}
    </>
  )
}


```




# 参考

next-theme githubの公式ドキュメント


https://github.com/pacocoursey/next-themes


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/e00fc5fa-3b26-faa7-d153-03006af82e32.png)



## その他

Udemy

https://www.udemy.com/course/react-js-tutorial/learn/lecture/36119274#overview

githubコミット分


https://github.com/RYA234/imcbclone/commit/aa8dce6a053e4e64d6e827b6db653c4abcdd132e
imdb clone Part6　5 Add a darkMode 4/○　hydration Errorを修正

# 概要
目次

https://qiita.com/RYA234/private/045f3d2c03684572d3f9

今回はhydration errorが出ているので改善を行います。

hydration errorとは最初のレンダリングにおいて、SSR or ISRとCLRが一致してないことによるエラーのようです。（詳細は参考の部分参照）



改善前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/0eb65593-0e6a-450b-a39e-ae0c6fd76d15.png)




改善後　hydarion Errorが無くなっていることを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/b4a412ff-85c7-4430-7ae5-30c5a4240c66.png)




# 開発環境

OS:Windows10
IDE:VSCode

"@next/font": "13.1.5",
"autoprefixer": "10.4.14",
"eslint": "8.39.0",
"eslint-config-next": "13.3.1",
"next": "13.3.1",
"postcss": "8.4.23",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-icons": "^4.8.0",
"tailwindcss": "3.3.2"

# 実装のポイント
react-themeのドキュメントに回避方法があるのでそれを参考にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/05e570af-8cd9-fea4-8eaf-8c2d17f1c142.png)


# コード部分
## Layout
```diff_jsx:Layout.jsx
"use client";
import {useEffect, useState } from 'react'
import {MdLightMode} from "react-icons/md";
import {BsFillMoonFill} from "react-icons/bs"
import {useTheme} from "next-themes";


export default function DarkModeSwitch() {
    const{systemTheme,theme,setTheme} = useTheme();
+    const [mounted,setMounted] = useState(false);

+    useEffect(() => setMounted(true),[]);
    
    const currentTheme = theme === "system" ? systemTheme : theme;
    
    return (
    <>  
+        {mounted && ( currentTheme === "dark" ? (
            <MdLightMode 
                onClick={() => setTheme("light")}/>) : (
        <BsFillMoonFill onClick={() => setTheme("dark")}/>))}
    </>
  )
}
```




# 参考
Hydration Error

https://masahosono.dev/posts/react-hydration-error


https://nextjs.org/docs/messages/react-hydration-error

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/a15d2cb1-55ae-3cc2-0253-15d5a3a7f1a8.png)



react-theme

https://github.com/pacocoursey/next-themes

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/205e2a2d-7fa6-dbfd-c767-38c1db42a8d6.png)



## その他


Udemy

https://www.udemy.com/course/react-js-tutorial/learn/lecture/36592888#overview

githubコミット分

https://github.com/RYA234/imcbclone/commit/94f3b5a7281e9367488da4cf6595ecb45f0d995f
imdb clone Part5　ヘッダー作成　テンプレート 5 Add a darkMode 3/5　React-icon実装　ダークモードに切り替えできるよう実装

# 概要
目次

https://qiita.com/RYA234/private/045f3d2c03684572d3f9

今回はダークモードに切り替えができるように実装します。
以下gifアニメは切り替えているときの様子です。

![bbbbbb.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/fced7677-7ce8-b518-e0b7-a22e378d1f81.gif)


# 開発環境

OS:Windows10
IDE:VSCode

"@next/font": "13.1.5",
"autoprefixer": "10.4.14",
"eslint": "8.39.0",
"eslint-config-next": "13.3.1",
"next": "13.3.1",
"postcss": "8.4.23",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-icons": "^4.8.0",
"tailwindcss": "3.3.2"

# 実装のポイント
DarkModeからLightModeに切り替えるときの処理の流れ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/916f5399-89e4-5a74-acaa-1a8b705f6aef.png)




# コード部分
## DarkModeSwitch
```diff_jsx:DarkModeSwitch.jsx
"use client";
import React from 'react'
import {MdLightMode} from "react-icons/md";
import {BsFillMoonFill} from "react-icons/bs"
import {useTheme} from "next-themes";


export default function DarkModeSwitch() {
    const{theme,setTheme} = useTheme();
    const currentTheme = theme;
    return (
    <>  
        { currentTheme === "dark" ? <MdLightMode onClick={() => setTheme("light")}/> :
        <BsFillMoonFill onClick={() => setTheme("dark")}/>}
    </>
  )
}

```




# 参考
next-themes

https://github.com/pacocoursey/next-themes

![aaaaaaa.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/8d6791a8-c45f-272b-bf25-c79204ace21e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/3449165d-e0bf-0862-254e-ac56b485fcaf.png)








## その他



Udemy

https://www.udemy.com/course/react-js-tutorial/learn/lecture/36592888#overview


githubコミット分


https://github.com/RYA234/imcbclone/commit/c8c6210ea6ca3699c78e8272f2057f6d614679bc