OmniAICreator/Qiita-1.07M huggingface dataset:
PythonでWatson DiscoveryのCollectionの情報を取得

```python
# %%
from ibm_watson import DiscoveryV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
import json

# %%
apikey='APIKEY'
version='VERSION'
authenticator = IAMAuthenticator(apikey=apikey)
discovery = DiscoveryV2(version=version, authenticator=authenticator)

# %%
service_url='SERVICE_URL'
discovery.set_service_url(service_url=service_url)

# %%
response = discovery.list_projects().get_result()
print(response)

# %%
projects = response['projects']
for project in projects:
    print(project)

# %%
name = 'PROJECT_NAME'
projects = [project for project in projects if project['name'] == name]
for project in projects:
    print(project)

# %%
project = projects[0]
print(project)

# %%
response = discovery.list_collections(project_id=project['project_id']).get_result()
print(response)

# %%
collections = response['collections']
for collection in collections:
    print(collection)

# %%
name = 'COLLECTION_NAME'
collections = [collection for collection in collections if collection['name'] == name]
for collection in collections:
    print(collection)

# %%
if len(collections) != 0:
    for collection in collections:
        response = discovery.get_collection(project_id=project['project_id'], collection_id=collection['collection_id']).get_result()
        print(response)
        print(json.dumps(response, ensure_ascii=False, indent=4))
# %%
```
[備忘録]　読んだUnityの記事をまとめました

# はじめに
　こんにちは，Umamusume22です．最近，業務の関係でUnityの勉強をしています．Unityは初心者なので様々なUnityの記事を読み漁っています．読んだ記事の内容を忘れないようにurlを貼っておきます．なお，気になった本のurlも載せます

# Unityに関する記事
[1] "2021-06-15 クォータニオンとは何ぞや？：基礎線形代数講座"
https://techblog.sega.jp/entry/2021/06/15/100000

#### [1]の内容
　クォータニオンに関する説明でSEGAが発信しているテックブログです．SEGAが無料で線形代数のpdfを公開しています．なんとpdfのページ数が150枚です．SEGAさん，無料公開してくれてありがとう．

[2] "Unity(ゆにてぃ）で車を動かしてみよう"
https://jps-code.com/unity_car

#### [2]の内容
 Unityで車を動かす方法が説明されています．ソースコードも丁寧に説明されています．
Unityではタイヤの滑りやすさや車体の重さなども考慮した上で車を動かすことが可能です[2]．

# Unityに関する書籍
[3] "ゲームアプリの数学 Unityで学ぶ基礎からシェーダーまで"
https://www.sbcr.jp/product/4797384260/

# 最後に
　Unityに関する書籍はまだ購入していません．あくまで候補です．Unityを扱う上で座標変換やプログラミングなど沢山のことを勉強しないといけませんが少しずつUnityに慣れていきます．

 ここまで記事を読んでいただきありがとうございました

 ※ウマ娘の声をフーリエ変換した記事や水栓の開閉判定をLineに通知する記事も書いています．suzuが私です．興味がある方はぜひご覧ください！
https://vigne-cla.com/31-1/#toc5

※noteも始めました．
https://note.com/madoka235/n/nbba2153326e1

ぜひフォローよろしくお願いします!
PythonでWatson DiscoveryのCollectionにDocumentを追加

```python
# %%
from ibm_watson import DiscoveryV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

# %%
apikey='APIKEY'
version='VERSION'
authenticator = IAMAuthenticator(apikey=apikey)
discovery = DiscoveryV2(version=version, authenticator=authenticator)

# %%
service_url='SERVICE_URL'
discovery.set_service_url(service_url=service_url)

# %%
response = discovery.list_projects().get_result()
print(response)

# %%
projects = response['projects']
for project in projects:
    print(project)

# %%
name = 'PROJECT_NAME'
projects = [project for project in response['projects'] if project['name'] == name]
for project in projects:
    print(project)

# %%
project = projects[0]
response = discovery.list_collections(project_id=project['project_id']).get_result()
print(response)

# %%
collections = response['collections']
for collection in collections:
    print(collection)

# %%
collection = collections[0]
response = discovery.get_collection(project_id=project['project_id'], collection_id=collection['collection_id']).get_result()
print(response)

# %%
fp = 'CSV FILE PATH'
with open(file=fp, mode='rb') as file:
    response = discovery.add_document(
        project_id=project['project_id'],
        collection_id=collection['collection_id'],
        file=file,
        file_content_type='text/csv',
    ).get_result()
print(response)

# %%
```


とりあえずすげーでかいデータはCUIで登録しておいて、以下を参考にするのが吉な気がしている…
https://qiita.com/nax/items/9037e511c0948eb5a173
PythonでWatson DiscoveryのCollectionを削除

```python
# %%
from ibm_watson import DiscoveryV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
import json

# %%
apikey='APIKEY'
version='VERSION'
authenticator = IAMAuthenticator(apikey=apikey)
discovery = DiscoveryV2(version=version, authenticator=authenticator)

# %%
service_url='SERVICE_URL'
discovery.set_service_url(service_url=service_url)

# %%
response = discovery.list_projects().get_result()
print(response)

# %%
projects = response['projects']
for project in projects:
    print(project)

# %%
name = 'PROJECT_NAME'
projects = [project for project in projects if project['name'] == name]
for project in projects:
    print(project)

# %%
project = projects[0]
print(project)

# %%
response = discovery.list_collections(project_id=project['project_id']).get_result()
print(response)

# %%
collections = response['collections']
for collection in collections:
    print(collection)

# %%
name = 'COLLECTION_NAME'
collections = [collection for collection in collections if collection['name'] == name]
for collection in collections:
    print(collection)

# %%
if len(collections) != 0:
    for collection in collections:
        response = discovery.delete_collection(project_id=project['project_id'], collection_id=collection['collection_id']).get_result()
        print(response)
        
# %%
```
CSSを学びたい Step17 擬似クラス(is, has, where)

## はじめに
CSSを学びたい！Step17です！今回は擬似クラスの**is**,**has**,**where**に関して学んでいきます！！

## 1. is
:isはCSSの擬似クラスセレクタで、複数のセレクタをまとめて指定するために使用されます。これにより、コードの冗長性を減らし、スタイルの適用を簡潔にすることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/effcd023-ffcc-8042-7b85-1a99119fa29e.png)

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Example</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <h1>見出し1</h1>
  <h2>見出し2</h2>
  <h3>見出し3</h3>
</body>
</html>
```

```css:styles.css
:is(h1, h2, h3) {
    color: blue;
    font-family: Arial, sans-serif;
}
```

## 2. has
:hasはCSSの擬似クラスセレクタで、特定の子要素を持つ親要素を選択するために使用されます。これにより、特定の条件を満たす要素にスタイルを適用することができます。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/9afe6263-c59c-7a38-08a4-9e19a8416589.png">

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Example</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <div>
    <p>この段落はdiv内にあります。</p>
  </div>
  <div>
    このdivには段落がありません。
  </div>
</body>
</html>
```

```css:styles.css
div:has(p) {
  border: 2px solid red;
  padding: 10px;
}
```

## 3. where
:whereはCSSの擬似クラスセレクタで、複数のセレクタをまとめて指定するために使用されます。:isと似ていますが、:whereは特異性(詳細度)がゼロであるため、他のスタイルルールと競合しにくいという特徴があります。

:::note warn
ん？ 特異性？詳細度？って何？？同じに見えるけど、どう違うの？？と思いましたが、一旦置いておきます。次回以降に紹介します！
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/c615dde4-ec5c-1811-b98e-fa9cd146f242.png)

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Example</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <h1>見出し1</h1>
  <h2>見出し2</h2>
  <h3>見出し3</h3>
</body>
</html>
```

```css:styles.css
:where(h1, h2, h3) {
  color: green;
  font-family: Verdana, sans-serif;
}
```

## おわりに
擬似クラスは便利でいいですね！！
Javaでマウスポインタを動かしたい

以下のステップでマウスポインタを動かすことができます。

1. `MouseInfo.getPointerInfo`で現在のマウスポインタの位置を取得する
2. `Robot.mouseMove`を利用してマウスポインタを動かします

例: x軸方向に1ピクセル、y軸方向に1ピクセル、マウスポインタを1分おきに動かす

```java
import java.awt.AWTException;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;
import java.util.concurrent.TimeUnit;

public class MoveMouse {
    public static void main(String[] args) throws AWTException, InterruptedException {
        Robot robot = new Robot();
        while (true) {
            Point point= MouseInfo.getPointerInfo().getLocation();
            robot.mouseMove(point.x + 1, point.y + 1);
            Thread.sleep(TimeUnit.MILLISECONDS.convert(1, TimeUnit.MINUTES));
        }
    }
}
```

このようなプログラムをバックグラウンドを実行しておくと、一定時間無操作でスリープするのを防ぐことができます。スリープになると、監視アプリがアラートをあげたり、チャットアプリのステータスが離席中になって、チームメンバーや上司に離席していることがばれたりすることがあります。

通常はPC側で設定可能ですが会社によっては、セキュリティ上の観点から、スリープ設定を解除できないようにしている場合があります。このプログラムはその対策ですね。

ところで、なぜ業務中にPCが無操作になるのかって? てへぺろ(・ω<)

**環境情報**

```
D:\>java -version
openjdk version "21.0.3" 2024-04-16 LTS
OpenJDK Runtime Environment Temurin-21.0.3+9 (build 21.0.3+9-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.3+9 (build 21.0.3+9-LTS, mixed mode, sharing)

D:\>javac -version
javac 21.0.3

D:\>ver

Microsoft Windows [Version 10.0.22631.3880]
```
PythonでWatson DiscoveryのCollectionを作成

```python
# %%
from ibm_watson import DiscoveryV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
import json

# %%
apikey='APIKEY'
version='VERSION'
authenticator = IAMAuthenticator(apikey=apikey)
discovery = DiscoveryV2(version=version, authenticator=authenticator)

# %%
service_url='SERVICE_URL'
discovery.set_service_url(service_url=service_url)

# %%
response = discovery.list_projects().get_result()
print(response)

# %%
projects = response['projects']
for project in projects:
    print(project)

# %%
name = 'PROJECT_NAME'
projects = [project for project in projects if project['name'] == name]
print(projects)

# %%
project = projects[0]
print(project)

# %%
response = discovery.list_collections(project_id=project['project_id']).get_result()
print(response)

# %%
collections = response['collections']
for collection in collections:
    print(collection)

# %%
name = 'COLLECTION_NAME'
collections = [collection for collection in collections if collection['name'] == name]
for collection in collections:
    print(collection)

# %%
if len(collections) == 0:
    response = discovery.create_collection(project_id=project['project_id'], name='test', language='en').get_result()
    print(response)
# %%
print(json.dumps(response, ensure_ascii=False, indent=4))

# %%
#response = discovery.update_collection(project_id=project['project_id'], collection_id='87025aee-6019-f8b6-0000-0192efdda89a', enrichments=[{'enrichment_id': '701db916-fc83-57ab-0000-000000000002', 'fields': ['English Claims']}]).get_result()
#print(response)

# %%
#print(json.dumps(response, indent=4, ensure_ascii=False))

# %%
```
【Rails】polymorphicリレーションとhas_and_belongs_to_many

### 【Rails】polymorphicリレーションとhas_and_belongs_to_many

Railsには、モデル同士の関係を設定するリレーションの仕組みがあります。その中でもpolymorphicリレーションとhas_and_belongs_to_many（HABTM）リレーションは、多対多の関係を表すリレーションです。ただし、用途や機能が異なるため、使い分けが大切です。この記事では、それぞれのリレーションの違いや使い方について解説します。

### 1. has_and_belongs_to_many（HABTM）リレーション

has_and_belongs_to_many（HABTM）は、「多対多」のリレーションを定義する方法の1つです。2つのモデルが対等な関係でお互いに関連し合うことを表します。

使用例：コースと学生の関係

例えば、1人の学生が複数のコースを履修し、1つのコースに複数の学生が参加するという関係は、多対多の関係に当てはまります。この場合、StudentとCourseのモデルにHABTMを設定します。
```rb
class Course < ApplicationRecord
  has_and_belongs_to_many :students
end

class Student < ApplicationRecord
  has_and_belongs_to_many :courses
end
```
中間テーブル

HABTMを使う場合、中間テーブルというテーブルが必要です。このテーブルは、courses_studentsという名前になり、course_idとstudent_idが含まれます。この中間テーブルにより、CourseとStudentの関連が保存されます。

使いどころ

	•	単純な多対多の関係が必要なとき。
	•	学生とコース、タグと投稿など、どちらのモデルも複数の関連を持つ場合に適しています。

### 2. polymorphicリレーション

polymorphicリレーションは、1つのモデルが複数の異なるモデルと共通の機能で関連付けられる場合に使います。例えば、複数の異なるモデルにコメントやタグをつける場合、polymorphicを使うと便利です。

使用例：コメントを投稿と写真に共通で付ける

例えば、ブログの投稿（Post）と写真（Photo）にコメントを付ける場合、polymorphicを使ってCommentモデルを設定できます。
```rb
class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true
end

class Post < ApplicationRecord
  has_many :comments, as: :commentable
end

class Photo < ApplicationRecord
  has_many :comments, as: :commentable
end
```
この例では、Commentモデルがpolymorphic設定を使ってPostとPhotoのどちらにもコメントをつけられるようになっています。

マイグレーションの設定

polymorphicリレーションには、対象のモデルを識別するためにcommentable_idとcommentable_typeが必要です。以下のコマンドでマイグレーションを生成できます：
```
rails generate model Comment content:string commentable:references{polymorphic}
```
この設定により、CommentはPostやPhotoなど複数のモデルに共通で使えるようになります。

使いどころ

	•	複数の異なるモデルに共通の機能を持たせたいとき。
	•	コメントやタグのように、どのモデルに対しても同じ機能を追加したい場合に適しています。

has_and_belongs_to_manyとpolymorphicの違いまとめ

リレーションの種類	特徴	使用例
has_and_belongs_to_many（HABTM）	2つのモデルが対等な多対多の関係を持つ。中間テーブルが必要	学生とコース、タグと投稿など
polymorphic	1つのモデルが複数の異なるモデルに対して共通の関連を持てる。_typeと_idで識別	コメント機能（投稿や写真に共通のコメント）

違いのポイント

	•	関連の対象：HABTMは2つのモデルが対等な関係で関連し、polymorphicは異なるモデルに共通の機能を関連付ける際に使用します。
	•	中間テーブルの有無：HABTMは中間テーブルを使用し、polymorphicは外部キーとタイプでモデルを識別します。
	•	使いどころ：HABTMは単純な多対多の関係で、polymorphicは複数のモデルに同じ機能を持たせたい場合に適しています。
PythonでWatson Discoveryのプロジェクトを削除

```python
# %%
from ibm_watson import DiscoveryV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
import json

# %%
apikey='APIKEY'
version='VERSION'
authenticator = IAMAuthenticator(apikey=apikey)
discovery = DiscoveryV2(version=version, authenticator=authenticator)

# %%
service_url='SERVICE_URL'
discovery.set_service_url(service_url=service_url)

# %%
response = discovery.list_projects().get_result()
print(response)

# %%
projects = response['projects']
for project in projects:
    print(project)

# %%
name = 'PROJECT_NAME'
projects = [project for project in projects if project['name'] == name]
print(projects)

# %%
if len(projects) != 0:
    for project in projects:
        response = discovery.delete_project(project_id=project['project_id']).get_result()
        print(response)

# %%
```
Pythonでwatson discoveryのプロジェクトを作成

```python
# %%
from ibm_watson import DiscoveryV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
import json

# %%
apikey='APIKEY'
version='VERSION'
authenticator = IAMAuthenticator(apikey=apikey)
discovery = DiscoveryV2(version=version, authenticator=authenticator)

# %%
service_url='SERVICE_URL'
discovery.set_service_url(service_url=service_url)

# %%
response = discovery.list_projects().get_result()
print(response)

# %%
projects = response['projects']
for project in projects:
    print(project)

# %%
name = 'PROJECT_NAME'
projects = [project for project in projects if project['name'] == name]
for project in projects:
    print(project)

# %%
if len(projects) == 0:
    response = discovery.create_project(name=name, type='content_mining').get_result()
    print(response)

# %%
print(json.dumps(response, indent=4, ensure_ascii=False))
# %%
```
パスワードの書き方を間違えた！！【Supabase での PostgreSQL 接続 URL 設定と「P1001: Can't reach database server」エラーの対処法】

Supabase を使って PostgreSQL データベースに接続しようとした際に、次のようなエラーに遭遇することがあります：

```
P1001: Can't reach database server at `aws-0-ap-northeast-1.pooler.supabase.com:6543`
```

このエラーは、接続 URL の設定ミスが原因であることが多いです。私の場合、接続 URL 内のパスワード設定が原因でこのエラーが発生しました。以下で、このエラーの原因と解決方法について解説します。

## エラーの原因とパスワード設定ミス

まず、自分が最初に設定していた（誤った）接続 URL は以下のようなものでした。

```
postgresql://postgres.efwkrqqalkbvtezrygfl:[mypasswordstring]@aws-0-ap-northeast-1.pooler.supabase.com:6543/postgres
```

この例では、`[mypasswordstring]` のように角括弧 `[]` でパスワードを囲んでいました。このような記述は PostgreSQL の接続 URL ではエラーの原因となります。角括弧はプレースホルダーとして使用されるものであり、実際の設定では使用しません。

## 正しい URL の記述例

正しい記述方法は以下のとおりです。パスワード部分に角括弧をつけず、そのまま書き込む必要があります。

```
postgresql://postgres.efwkrqqalkbvtezrygfl:mypasswordstring@aws-0-ap-northeast-1.pooler.supabase.com:6543/postgres
```

このように、`mypasswordstring` をそのまま入力することで、エラーを回避し、データベースに正常に接続することができます。

## 「P1001: Can't reach database server」エラーが出るその他の原因

もしパスワード設定を修正してもエラーが解消しない場合、次の点も確認してください：

1. **データベースの稼働状態**：Supabase のダッシュボードでデータベースが稼働中であることを確認してください。停止中の場合、接続できません。
   
2. **ネットワークの問題**：インターネット接続が不安定な場合にも、データベースサーバーに接続できないことがあります。安定したネットワークを確保してください。

3. **ホワイトリスト設定**：Supabase では、データベースへのアクセスを特定の IP アドレスからのみ許可する設定ができる場合があります。必要に応じて、接続元の IP アドレスをホワイトリストに追加してください。

## まとめ

Supabase の PostgreSQL に接続する際に、接続 URL のパスワードには角括弧 `[]` をつけずにそのまま入力する必要があります。また、「P1001: Can't reach database server」エラーが出た際には、以下の点を確認しましょう。

- URL の形式が正しいか（特にパスワード部分）
- データベースが稼働しているか
- ネットワークが安定しているか
- ホワイトリスト設定が正しいか

これらの点を確認し、修正することで Supabase データベースへの接続が正常に行えるようになります。同様のエラーが出た場合にはぜひ試してみてください。
型 LocationQueryValue | LocationQueryValue[] への1つの回答 (Nuxt3)

## A. 

さらに Composables でラップして使いやすくしてしまおう

## Motivation

- Nuxt3 でクエリパラメータから値を取り出すときの配列処理が面倒だった
- useRoute() と同様の操作感で、欲しいものを取り出す処理が欲しかった
- 取り出す過程で、特定のクエリパラメータへの操作を追加したかった（今回はピリオド区切りで分割して返却する）

→ それなら、 composables で定義して使おう！


※こんなことを実現したい

![貼り付けた画像_2024_11_03_19_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44871/7aa00698-5e1d-4ed1-03f0-f30afcadf7d4.png)

## Requirements

- "nuxt": "^3.13.2",
- "vue": "^3.4.21",
- "vue-router": "^4.3.0",

## Snippets

### ① composables 定義側

[Composables](https://nuxt.com/docs/guide/directory-structure/composables) ディレクトリを使って useXXX として処理を記述

```vue
const defaultDelimiter = "."

export const useQueryParam = (key: string, delimiter = defaultDelimiter): string[] => {
    const { query } = useRoute()
    if (query[key] instanceof Array) {
        return query[key].flatMap((v) => v?.split(delimiter) ?? [])
    }
    else {
        return query[key]?.split(delimiter) ?? []
    }
}
```

### ② 利用側

利用側で実行していたコードをcomposablesに持っていっただけです。特別代わり映えはしませんがBefore,Afterを載せておきます。

```vue
function getParam1Before() {
  const { query } = useRoute();
  if (query.param1 instanceof Array) {
    return query.param1.flatMap(
      (p: LocationQueryValue) => p?.split(".") ?? []
    );
  } else {
    return query.param1?.split(".") ?? [];
  }
}
function getParam1After() {
  return useQueryParam("param1");
}
```

## Result

以下のようにクエリパラメータが指定されたとき、思ったようにパースできました

| パターン | パラメータ | 返却値 |
|:-:|:-:|:-:|
| 指定なし | none | `[]` |
| 1個指定 | param1=apple | `["apple"]` |
| 2個指定 | param1=apple&param1=orange | `["apple", "orange"]` |
| デリミタ付 | param1=apple.orange&param1=lemon | `["apple", "orange", "lemon"]` |

## Opinion

#1
composables 自体は、状態を持ったオブジェクトを包みこんで使いやすい機能を提供するもの、と捉えていました。

それ自体が state を持たない composables を作ることには少し抵抗がありましたが、 `use〇〇` をラップして使い勝手のよい `use〇〇` を新設するのは、そんなに悪くない手法と感じました。

これまでは面倒くさいが勝ってしまって、「同一のクエリパラメータを複数指定したリクエストは捨てる」ような [ADR](https://adr.github.io/) を設けて、配列の1個目しか取らないようなコードを書いたこともありますが、そこまでしなくても良かったのかもしれません。

#2
展望としては、今回のコードは追加のオプションとしてデリミタを渡すようなものを用意しましたが、 `LocationQueryValue` 型から何かしらの他のドメインモデル配列を生成する関数を渡すように作り変えるとより汎用性は上がるかもしれませんね。

#3
頭で貼付したキャプチャに補足すると、「くさ・どくの複合、みずのみ、をそれぞれ並べたい」ケースもあるかもしれませんが、今回は考慮外です。ただパラメータに列挙させるようなケースで、万が一パラメータの指定をミスした場合へのケアを考えるような文脈と捉えてくださいませ。

#4
composables とは何なのか、まだ理解できていない部分もあるので、ご指導ご鞭撻、そのほかのユースケースなどございましたら、是非コメントへ！
【Rails】Rails APIでログイン、ログアウト

前回、Rails APIでUser周りの実装をしました。
[【Rails】JWTを用いたUser周りのAPI実装](https://qiita.com/kay903347/items/3847a5cf4642e122128c)
その記事のログイン、ログアウトで気になったことをまとめます。
先にmodel、controllerを貼り付けておきます。
```ruby:models/usr.rb
class User < ApplicationRecord
  before_save { self.email = email.downcase }
  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: true
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }
end
```
```ruby:controllers/api/v1/users_controller.rb
module Api
  module V1
    class SessionsController < ApiController
      # ログイン
      def create
        user = User.find_by(email: params[:email])

        if user&.authenticate(params[:password])
          token = encode_token(user_id: user.id)
          render json: { message: "ログインに成功しました。", token: token }, status: :ok
        else
          render json: { error: "メールアドレスまたはパスワードが無効です。" }, status: :unauthorized
        end
      end

      # ログアウト
      def destroy
        render json: { message: "ログアウトしました。" }, status: :ok
      end

      private

      # JWTトークンをエンコード
      def encode_token(payload)
        JWT.encode(payload, Rails.application.secrets.secret_key_base)
      end
    end
  end
end
```
## encode_token
JSON Web Token (JWT) を生成するためのものです。この関数は、渡された payload（トークンに含めたいデータ）をエンコードし、署名付きのトークンを作成します。
```ruby
def encode_token(payload)
  JWT.encode(payload, Rails.application.secrets.secret_key_base)
end
```
* payload
トークンに含めたい情報をハッシュの形式で payload に渡します。今回は、ユーザーIDです。
* JWT.encode
payload を指定された秘密鍵でエンコードして、JWT（JSON Web Token）を生成します。JWTは、3つの部分から構成される文字列です（ヘッダー、ペイロード、署名）。生成されたトークンは、この3つの部分を結合したもので、後でトークンを検証するときに利用されます。
* Rails.application.secrets.secret_key_base
トークンを署名するための秘密鍵として、Railsの secret_key_base を使用しています。secret_key_base はアプリケーションの機密情報であり、トークンの署名に利用することでトークンの安全性を確保しています。
CSSを学びたい Step16(Formの入力結果に応じてCSSを変更する)

## はじめに
CSSを学びたいのStep16です。Formの入力結果に応じて、CSSを変更する処理を実現します！
FormはJavaScriptと合わせて利用する事が多いですが、今回はCSSのみでできる範囲で実現します！

## 成果物
![form.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/8656d523-c9f5-ad50-ae02-8721bb83e393.gif)

## ソースコード
```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>無効な入力の赤枠表示</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <form>
        <label for="email">メールアドレス:</label>
        <input type="email" id="email" name="email" required>
        <br>
        <label for="username">ユーザー名:</label>
        <input type="text" id="username" name="username" required minlength="3">
    </form>
</body>
</html>
```

```css:styles.css
input:invalid {
    border: 2px solid red; /* 無効な入力に赤枠を設定 */
}

input:valid {
    border: 2px solid green; /* 有効な入力に緑枠を設定（オプション） */
}
```
ゼロからのOS自作入門 その2

1～2章が完了しました。
以下は、勉強になった部分と詰まったところ。

## 1章

実行可能ファイル：CPUが実行可能な機械語を含んだファイルのこと。

64ビットCPUは、一回の計算で64桁の2進数を扱えるということ。
32ビットなら32桁。

BIOSは、ファームウェア（PCnお電源を入れて初めに実行されるプログラム。）

1. 電源を入れるとCPUはBIOSを実行
1. BIOSは接続されているストレージを探す
1. 実行可能ファイルを発見
1. CPUはBIOSの実行を中止
1. 実行可能ファイルの実行

という順序で実行可能ファイルを実行している。

qumuの起動には、vcxsrvの起動の必要がある。
てっきり、一度インストールしてしまえば、毎回自動で立ち上がっているものだと思っていた。

## 2章

buildをするところが上手くいかずにだいぶ詰まってしまった。
→target.txtの値を手動で変更すると本に記載があったのだが、見落としており、コマンドで生成されたままの状態で、buildしていたため。

メモリのそれぞれのバイトには連番が降られており、この連番を使用して、データをバイト単位で読み書きすることができる。

メモリマップとは、メモリのどの部分がどの用途で使用されているのかが記載されている地図。

## 終わり

ちまちまと進めていきたいですねー。
GitとGithubの連携のやり方

久々にこの作業をしてみると、
完全に忘れていて、時間を無駄にしたので忘備録。

連携したい環境のターミナルで、以下を入力する。

まずは、キー作成をする。
githubで使用しているアドレスを入力すること

ssh-keygen -t ed25519 -N "" -C メールアドレス


これで生成された　id_ed25519.pub をgithubのSSH and GPG keyに追加する。

以下を試して、通ればOK
ssh -T git@github.com

~/.ssh$ ssh -T git@github.com
Hi　〇〇(github ID)! You've successfully authenticated, but GitHub does not provide shell access.


これで完了
Burp Suite 自分用メモ


引用元：https://portswigger.net/burp/documentation/desktop/getting-started/download-and-install

### Burpをとりあえず使用したい（リクエストをインターセプトしたい）

>[Proxy] > [Intercept]タブ に移動します。
>
>Interceptトグルを「Intercept on」に設定します。
>
>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636207/08759d05-07ed-0839-71da-7f9714f07358.png)
>
>[Open browser] をクリックします。
>これにより、Burp のブラウザが起動します。
>このブラウザは、Burp ですぐに動作するように事前設定されています。
>Burp と Burp のブラウザの両方が表示されるようにウィンドウを配置します。

### HTTP通信の履歴を確認したい

>Burp で、[Proxy] > [HTTP history]タブに移動します。
>ここでは、InterceptがOFFになっている場合でも、Burp Proxy を通過したすべての HTTP トラフィックの履歴を確認できます。
>
>履歴内の任意のエントリをクリックすると、生の HTTP 要求と、サーバーからの対応する応答が表示されます。

>読みやすくするには、リクエストが降順で並べ替えられるまで、左端の列のヘッダー ( # ) をクリックし続けます。
>こうすると、最新のリクエストが一番上に表示されます。

### HTTP historyをフィルタリングする

>[Target] > [Sitemap] に移動します。
>左側のパネルには、ブラウザがやり取りしたホストのリストが表示されます。
>ターゲット サイトのノードを右クリックし、[Add to Scope]をクリックします。
>ポップアップ ウィンドウが表示されたら、[Yes]をクリックしてスコープ外のトラフィックを除外します。

>HTTP 履歴の上にある表示フィルターをクリックし、「Show only in-scope Items」を選択します。
>
>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636207/a2ceef3b-f0f4-9155-b4e9-8ad038649f72.png)

### Burp Repeaterにリクエストを送信する(リクエストを再送信できるようにする)

>いずれかのリクエストを右クリックし[Send to Repeater]を選択します。
>
>「Repeater」タブ に移動して、リクエストが専用の番号付きタブで待機していることを確認します。

リクエストを改変してラボに攻撃している様子
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636207/32436aff-446b-c193-e3ed-a011da9556fd.png)


それ以外の機能を公式で紹介
https://www.youtube.com/watch?v=nECt-0zW0O4&embeds_referring_euri=https%3A%2F%2Fportswigger.net%2F&embeds_referring_origin=https%3A%2F%2Fportswigger.net&source_ve_path=MjM4NTE&themeRefresh=1
データベース入門（環境構築〜初めてのデータベース，SQL）

## はじめに
Yasuと申します．2週間ごとに学習成果をアウトプットする目的で記事を作成しています．自分のための記事にはなりますが，同じように学習している初学者の方にも参考になれば嬉しいです．

今回はデータベースを触るのが初めてだったので，環境構築を中心に記述します．

---

## 1. 環境構築

### MySQLのインストール
まずはターミナルを開き，macOS向けのパッケージ管理ツール「Homebrew」を利用してMySQLをインストールします．

``` shell
brew install mysql
```
### サーバの起動・停止・状態確認
MySQLサーバの起動，停止，および状態を確認するには以下のコマンドを使用します．

``` shell
mysql.server start   # サーバを起動
mysql.server stop    # サーバを停止
mysql.server status  # サーバの状態を確認
```

### MySQLサーバへの接続
MySQLサーバを起動したら，次にサーバへ接続します．

``` shell
mysql -u root -p
Enter password: 
# 初回ログイン時はパスワードが設定されていないため，そのままEnterを押してログインできます．
```
### 初回パスワードの設定
初回ログイン後，セキュリティを高めるためにパスワードを設定します．

``` SQL
ALTER USER 'root'@'localhost' IDENTIFIED BY '新しいパスワード';
exit;  -- ログアウト
```
## 2. VSCodeの設定
### MySQLのGUI操作拡張機能
VSCode上でMySQLをGUIで操作するために，「MySQL Shell for VS Code」という拡張機能をインストールします．これにより，GUIから視覚的にデータベースを操作できるようになります（私は基本的にターミナルで操作していますが，GUIでもできるようにしておくと何かと便利だと思います）．

### ER図作成のための拡張機能
データベース設計時に役立つER図をVSCodeで描くために，以下の拡張機能とアプリをインストールします．

- 拡張機能：PlantUML
- 必要なアプリ：openjdk と graphviz
``` shell
brew install openjdk
brew install graphviz
```
これで，`.puml`ファイルを作成し，`opt`+`d`でER図をコードから生成できます．

## 3. データベースの作成
### データベースの新規作成
新しいデータベースを作成し，使用するためのコマンドです．

``` SQL
-- データベース「sample_db」を新規作成
CREATE DATABASE sample_db;
-- 作成したデータベースを使用
USE sample_db;
```
### テーブルの作成
次に，データベース内にテーブルを作成します．ここでは主キーと外部キーの設定方法も示します．

``` SQL
CREATE TABLE example_table (
    table1_id INT NOT NULL AUTO_INCREMENT,
    table2_id INT,
    name VARCHAR(50) NOT NULL,
    PRIMARY KEY (table1_id),
    FOREIGN KEY (table2_id) REFERENCES another_table(table2_id)
);
```
## 4. データの挿入
### データの挿入方法
作成したテーブルにデータを挿入します．

``` SQL
INSERT INTO example_table (name, table2_id) VALUES
('サンプル1', 1),
('サンプル2', 2);
```
### .sqlファイルを使った大量データの挿入
大量のデータを一括で挿入する場合は，.sqlファイルを作成して次のように読み込みます．

``` SQL
source ファイル名.sql;
```
### データの削除とAUTO_INCREMENTのリセット
テーブル内のデータを消去し，AUTO_INCREMENTの値をリセットする方法です．全データが消去されるため，注意が必要です．

``` SQL
DELETE FROM example_table;  -- テーブルの全データが消去されます
ALTER TABLE example_table AUTO_INCREMENT = 1;  -- AUTO_INCREMENTをリセット
```
これで，基本的なMySQLの設定と操作方法が整いました．

## 5. クエリの記述

### 全カラム・全データの表示
テーブル内のすべてのカラムとデータを表示したい場合は，以下のようにクエリを記述します．

```SQL
SELECT * FROM example_table;
```
このクエリは example_table テーブル内のすべてのデータを取得し，結果を表示します．* は「すべてのカラム」を意味します．クエリについての詳細は本記事では割愛します．

### クエリのファイル実行
データ挿入と同様に，クエリをファイルから実行することができます．これにより，長いクエリを直接ターミナルに入力する手間を省き，簡単に実行できます．

- SQLファイルの作成
テキストエディタを使用して，例えば`query.sql`ファイルを作成します．

- ファイルからのクエリ実行
MySQLに接続後，以下のコマンドでファイル内のクエリを実行します．

``` SQL
source query.sql;
```
こうすることで，複数行にわたるクエリや複雑なクエリをターミナルに入力することなく，一度に実行することが可能です．


## 終わりに

データベースはプログラミングにおいて欠かせない知識の一つです．データベース設計やSQLの学習が重要なのはもちろんですが，初学者にとってはその前段階の環境構築が難関であるのも事実です（実際，私も環境構築にかなりの時間を費やしました）．

この記事が，環境構築をスムーズに進め，早くSQLの学習に取り組める一助となれば幸いです．
comelangで例外処理を廃止。パターンマッチングを入れました。

ごめんなさい。やっぱりVMがない言語で例外は無理でした。バグだらけだったため、廃止。
代わりにパターンマッチングを入れました。

```C
#include <comelang.h>

struct Data
{
    int a,b;
};

int main(int argc, char** argv)
{
    var data = Data { a:123, b:234 };

    data.case {
        (Value === Data {a:wildcard, b:234} {
            puts("MATCH");
        }
        else {
            puts("NO MATCH");
        }
    }

    return 0;
}
```

[1,2,3].case { (Value === [wildcard,2,3]) puts("MATCH"); }などもOKです。
wildcardはcaseとif, elif, lessなどのみ有効です。

lessはUNIXとCのエラー処理で便利で以下のように使います。

```C
#include <comelang.h>

int main(int argc, char* argv)
{
    system("lllll").less {
        perror();
        return 1;
    }

    return 0;
}
```

lessが<0でマッチ、ifが!=0でマッチ, elifが==0でマッチです。
戻り値も取れるため、使い勝手がいいと思います。
例えば

```C
#include <comelang.h>

char* fun(int value)
{
    if(value == 0) {
        return null;
    }
    else {
        return xsprintf("%d", value);
    }
}

int main(int argc, char** argv)
{
    puts(fun(0).elif { s"null" });
    return 0;
}
```
などです。この場合funの引数が1など>0ならputsは数値を出力して、0ならnullを出力します。
NextJSサーバーアクションにおけるSupabase共通関数を用いたクエリ生成の効率化

## はじめに

今回はNextJSのサーバーアクションを実装する際に、
Supabaseのクエリ生成を共通関数内に実装したことで、
より好ましいコードとなったことを共有したいため記事にしました！

時は深夜、NextJSでユーザーを挿入するサーバーアクションを作成していたところ、
supabaseのimportが何度も現れていることに気付き、疑問が浮かびました。


## 問題：同じimportを何度も行うべきか？

```元のinsertUser.ts
// 全てのサーバーアクションでインポートするべきか？
import { supabase } from '@/utils/server/supabaseClient'; 

import type { User } from '@/customTypes/User';
import { handleSupabaseRequest } from '@/utils/server/handleSupabaseRequest';

export async function insertUser(userName: string): Promise<User> {
  const data = await handleSupabaseRequest( // ここで使用する
    supabase
      .from('users')
      .insert({ user_name: userName })
      .select()
      .single()
  );

  return data;
}
```

たかが1行のimport文ですが、
サーバーアクションが1兆個存在すれば1兆行に増えてしまうでしょう！
DRY(Don't Repeat Yourself)原則の信者である私は許すことができませんでした :(

さらに、supabaseへのアクセスは必ずsupabaseの共通関数を通すように実装したかったので、「共通関数内でこれを定義できないか？」と思いました。

そこで見つけた解決策が次のとおりです。

## 解決策：共通関数を使ったSupabaseクエリの管理

私が採用したのは、共通関数でsupabaseインスタンスを管理する方法です。
まず、元のsupabase共通関数は以下のようになっていました。

``` 元のsupabase共通関数.ts
export async function handleSupabaseRequest<T>(supabaseQuery: Promise<{ data: T | null; error: any }>): Promise<T> {
  const { data } = await supabaseQuery;
  
  return data;
}

```

この共通関数はsupabaseQueryを引数として受け取るため、
呼び出し側でsupabaseをimportしてクエリを作成する必要があります[^2]。
[^2]: 依存性の注入の観点からは、これは好ましい状態ですが、今回の場合は全て同じsupabaseインスタンスを使用していたため、共通化を行うべきではないかと判断しました。

そこで、共通関数側でクエリを作成できるよう、以下のように変更しました。

```supabase共通関数.ts
import { supabase } from '@/utils/server/supabaseClient';

// クエリビルダー関数の型
type QueryBuilder<T> = (supabaseClient: typeof supabase) => Promise<{ data: T | null; error: any }>;

export async function handleSupabaseRequest<T>(queryBuilder: QueryBuilder<T>): Promise<T> {
  const { data, error } = await queryBuilder(supabase);

  return data as T;
}

```

supabaseの"クエリ作成関数"をコールバック関数とすることで、
**共通関数内**でsupabaseインスタンスを使い、クエリを生成できるようになりました。

``` insertUser.ts
import type { User } from '@/customTypes/User';
import { handleSupabaseRequest } from '@/utils/server/handleSupabaseRequest';

export async function insertUser(userName: string): Promise<User> {
  const data = await handleSupabaseRequest(async (supabase) => {
    return supabase
      .from('users')
      .insert({ user_name: userName })
      .select()
      .single();
  });

  return data;
}
```

これにより、呼び出し側でsupabaseのクエリを作成することなく、
コールバック関数からsupabaseのクエリビルダーを呼び出せるようになりました。

また、「supabaseのインスタンスをどこで呼び出しているのか？」と疑問に思った場合、
必然的にsupabase共通関数に行き着くため、全体像を理解しやすくなるのではと思います。

サーバーアクション側のコードも簡潔になり、エラーハンドリングも共通関数内で一度行えばよいため、今回のケースではより良いコードになりました。

ご一読いただきありがとうございました！

## 参考

https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
Good Commitを学ぶ

チーム開発を行う上で、必ずと言っていいほど使用するGitだが、自分自身あまり意識できていなかったので、Git Commitに関するベストプラクティスを下記にまとめます。

- 1.Commit Often,but Not Too Often
- 2.Write Clear and Descriptive Messages
- 3.Use Branches Effectively
- 4.Review and Squash Commit
- 5.Automate Testing
- 6.Use Husky


1.Commit Often,but Not Too Often
-
コミットの頻度が多すぎても、少なすぎてもよくありません。バランスをとるように努めます。
各コミットは意味のある変更を表す必要があります。
無関係な変更を 1 つのコミットにプッシュしないでください。

2.Write Clear and Descriptive Messages
-
コミット メッセージでは、コミットの内容と変更を加えた理由を説明する必要があります。
コミットする内容に合わせて、タイプを使用します。

タイプ一覧：
feat　　　・・・　新しい機能
fix　　 　・・・　バグ修正
docs　　　・・・　ドキュメントのみの修正
style　　 ・・・　コードに影響を与えない変更(空白、書式、コメントなど)
refactor　・・・　バグを修正したり機能を追加したりしないコード変更
perf　　  ・・・　パフォーマンスを向上させるコード変更
test　　  ・・・　不足しているテストの追加
chore     ・・・　ビルドプロセスや、ドキュメント生成などの補助ツールやライブラリのへんこう

3.Use Branches Effectively
-
新しい機能、バグ修正、実験には機能ブランチを使用します。
これらのブランチに対してプル リクエストを発行すると、プロジェクト マネージャーまたは管理者がコードを確認し、メインにマージします。

4.Review and Squash Commit
-
プロジェクトの所有者、リーダー、管理者、またはコードをレビューする人の場合は、ブランチをマージする前に、小さなコミットまたは修正コミットをレビューして論理的な単位にまとめます。
この方法により、コミット履歴が整理され、追跡しやすくなります。

5.Automate Testing
-
継続的インテグレーション ツールを使用して、コミットごとにコードを自動的にテストします。
これにより、変更が検証され、バグが発生するリスクが軽減されます。

6.Use Husky
-
husky のようなライブラリを使用すると、git スキルを向上させることができます。
husky で設定されたルールに違反している場合は、コミットが許可されません。


参考記事：
https://dev.to/sheraz4194/good-commit-vs-bad-commit-best-practices-for-git-1plc?ref=dailydev

https://ec.europa.eu/component-library/v1.15.0/eu/docs/conventions/git/
CSSを学びたい Step15(雪を降らせる)

## はじめに
CSSを学びたいStep15です。今回は雪を降らせるアニメーションを作成してきいきます！！

## 成果物
![snow-flake.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/6801ca49-69aa-9410-03ec-45c1794616eb.gif)

## ソースコード

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>雪が降るアニメーション</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="snowflake">❄</div>
    <div class="snowflake">❄</div>
    <div class="snowflake">❄</div>
    <div class="snowflake">❄</div>
    <div class="snowflake">❄</div>
    <div class="snowflake">❄</div>
    <div class="snowflake">❄</div>
    <div class="snowflake">❄</div>
    <div class="snowflake">❄</div>
    <div class="snowflake">❄</div>
</body>
</html>
```


```css:styles.css
body {
    margin: 0;
    padding: 0;
    overflow: hidden; /* スクロールバーを非表示にする */
    background: #000; /* 背景色を黒に設定 */
    height: 100vh; /* 表示エリアの高さを100vhに設定 */
    position: relative; /* 相対位置指定 */
}

@keyframes fall {
    0% {
        top: -10%; /* 画面の上から開始 */
    }
    100% {
        top: 100%; /* 画面の下まで移動 */
    }
}

@keyframes sway {
    0%, 100% {
        transform: translateX(0); /* 初期位置と終了位置は水平移動なし */
    }
    50% {
        transform: translateX(20px); /* 中間地点で右に20px移動 */
    }
}

.snowflake {
    position: absolute;
    top: -10%; /* 初期位置を画面の上に設定 */
    color: #fff; /* 雪の結晶の色を白に設定 */
    font-size: 1em; /* フォントサイズを1emに設定 */
    user-select: none; /* ユーザーによる選択を無効化 */
    pointer-events: none; /* ポインターイベントを無効化 */
    animation: fall linear infinite, sway ease-in-out infinite; /* 落下と揺れのアニメーションを設定 */
}

.snowflake:nth-child(odd) {
    animation-duration: 10s, 2s; /* 奇数番目の雪の結晶のアニメーションの持続時間を設定 */
}

.snowflake:nth-child(even) {
    animation-duration: 15s, 3s; /* 偶数番目の雪の結晶のアニメーションの持続時間を設定 */
}

.snowflake:nth-child(1) { left: 10%; } /* 雪の結晶の位置を設定 */
.snowflake:nth-child(2) { left: 20%; }
.snowflake:nth-child(3) { left: 30%; }
.snowflake:nth-child(4) { left: 40%; }
.snowflake:nth-child(5) { left: 50%; }
.snowflake:nth-child(6) { left: 60%; }
.snowflake:nth-child(7) { left: 70%; }
.snowflake:nth-child(8) { left: 80%; }
.snowflake:nth-child(9) { left: 90%; }
.snowflake:nth-child(10) { left: 100%; }
```
Anki用インポートデータ作成Webアプリケーション(記録用)

## 概要
Google Apps Script(以下GAS）の練習も兼ねてAnkiという有名な暗記アプリのインポートを楽にしたいので作成。筆者はHTMLやCSSは苦手なのでChatGPTを介し作成。

## 機能
* リスト形式での単語追加
    - リストの長さはボタンで行を追加して可変的に対応可能
* リストごとの削除ボタン
* CSV出力機能
    - 出力前に確認メッセージ
    - 出力CSV名は"Anki_import.csv"

```javascript:main.gs
function doGet() {
  return HtmlService.createHtmlOutputFromFile('index');
}
```
```haml:index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <style>
      .header-container {
        display: flex;
        justify-content: space-between;
        align-items: center;
      }
      .container {
        display: flex;
        flex-direction: column;
        margin-top: 20px;
      }
      .row {
        display: flex;
        align-items: center; /* 縦方向に中央揃え */
        margin-bottom: 15px;
      }
      .textbox {
        width: 10%;
        margin-right: 10px;
      }
      .add-button, .csv-button {
        margin-top: 20px;
      }
      .delete-button {
        margin-left: 10px; /* 左側にスペースを追加 */
      }
    </style>
  </head>
  <body>
    <h2>Ankiデータ作成</h2>
    <button class="add-button" onclick="addTextbox()">テキストボックスを追加</button>
    <button class="csv-button" onclick="exportCSV()">CSV形式で出力</button>
    <div class="container" id="textboxContainer">
      <div class="row">
        <input type="text" class="textbox" placeholder="表">
        <input type="text" class="textbox" placeholder="裏">
      </div>
    </div>
    
    <div id="output"></div>

    <script>
      function addTextbox() {
        const container = document.getElementById("textboxContainer");
        const newRow = document.createElement("div");
        newRow.className = "row";
        newRow.innerHTML = `
          <input type="text" class="textbox" placeholder="表">
          <input type="text" class="textbox" placeholder="裏">
          <button class="delete-button" onclick="deleteTextbox(this)">削除</button>
        `;
        container.appendChild(newRow);
      }

      function deleteTextbox(button) {
        const row = button.parentElement; // ボタンの親要素（行）を取得
        row.remove(); // 行を削除
      }

      function exportCSV() {
        const confirmation = confirm("CSVを出力しますか？"); // 確認メッセージを表示
        if (!confirmation) return; // ユーザーが「いいえ」を選択したら処理を中止

        const rows = document.querySelectorAll(".row");
        const csvData = [];

        rows.forEach(row => {
          const inputs = row.querySelectorAll(".textbox");
          const rowData = [];
          inputs.forEach(input => {
            rowData.push(input.value);
          });
          csvData.push(rowData);
        });

        const csvContent = csvData.map(e => e.join(",")).join("\n");
        const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
        const link = document.createElement("a");
        const url = URL.createObjectURL(blob);
        link.setAttribute("href", url);
        link.setAttribute("download", "Anki_import.csv");
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      }
    </script>
  </body>
</html>

```
【Laravel】テストデータの登録をTraitで共通化する方法！

泉（[@izumin_0401](https://twitter.com/izumin_0401)）です。

今回は、Laravelでテストデータの登録を共通化する方法を解説しやす！

# ブログ記事はこちら

https://traveler0401.com/laravel-testdata-trait/

# Laravelでテストデータの登録を共通化する方法

## Traitの作成
```php
<?php

namespace Tests\Traits;

trait SeedTestData
{
    public function seedTestData()
    {
        \DB::table('your_table_name')->insert([
            'hoge' => '1',
        ]);
    }
}
```
データを登録するTraitを作成します。

## テストデータでTraitを使う
```php
<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use Tests\Traits\SeedTestData;

class SampleTest extends TestCase
{
    use RefreshDatabase, SeedTestData;

    public function testSuccessfulResponse()
    {
        $this->seedTestData();

        $response = $this->get('/api');

        $response->assertOk();
    }
}
```
テストコードでTraitを使えばOKです。

# まとめ
Trait、便利だな〜

ではまた。

# 最後に
暇つぶしに[Twitter](https://twitter.com/izumin_0401)と[ブログ](https://traveler0401.com/)もやってるので見てね。
ChakraUIのv3による変更点

## はじめに
ChakraUIのバージョンが<font color="red"><strong>3</strong></font>にアップデートされたので、バージョン2以前との変更点をまとめます。

## 主な変更点
### 1. @emotion/styledとframer-motionのパッケージは不要

既にインストールしていた場合は、アンインストールする。
```terminal
npm uninstall @emotion/styled framer-motion
```
そして、パッケージの最新化を行う。
```terminal
npm install @chakra-ui/react@latest @emotion/react@latest
```

### 2. cli snippetをインストールすることで、補完してくれる
```terminal
npx @chakra-ui/cli snippet add
```

:::note info
Node.jsのバージョン18の場合は、上記のコマンドを実行しても`@/components/ui/*`をimportできませんでした。
そのため、Node.jsのバージョンを22にアップデートして、再度上記のコマンドを実行するとimportが行えました。

:::

### 3. テーマのカスタマイズ構成に、defaultConfigを使用する
```diff_typescript:theme.ts
- import { extendTheme } from "@chakra-ui/react"
+ import { createSystem, defaultConfig } from "@chakra-ui/react"

- export const theme = extendTheme({
-  fonts: {
-    heading: `'Figtree', sans-serif`,
-    body: `'Figtree', sans-serif`,
+ export const system = createSystem(defaultConfig, {
+  theme: {
+    tokens: {
+      fonts: {
+        heading: { value: `'Figtree', sans-serif` },
+        body: { value: `'Figtree', sans-serif` },
+     },
+    },
  },
})
```


### 4. Providerを使用する 
ChakraProviderは使わなくなり、Providerをルートに設定することとなった。
```diff_typescript:App.tsx
- import { ChakraProvider } from "@chakra-ui/react"
+ import { Provider } from "@/components/ui/provider"
+ import { defaultSystem } from "@chakra-ui/react"

export const App = ({ Component }) => (
- <ChakraProvider theme={theme}>
+ <Provider value={defaultSystem}>
    <Component />
- </ChakraProvider>
+ </Provider>
)
```
### 5. アイコンの変更
`@chakra-ui/icons`のパッケージが削除され、`lucide-react`または`react-icons`を使用する。

### 6. プロップの変更
- bool型プロパティの命名規則が`isOpen`から`open`に変更。
- `colorScheme`から`colorPalette`に変更され、すべてのコンポーネントで使用できるようになった。
- スタイルプロパティの命名規則の変更。`noOfLines`から`lineCamp`へなど。

..etc

## おわりに
他にも様々な変更点がありました。
まだアップデートされたばかりで、追いきれていないことろも多々ありますが、使用していくにつれ関係のある箇所から加筆していければと思います。

## 参考サイト
https://www.chakra-ui.com/docs/get-started/migration
ChakraUI使ったら、Uncaught TypeError: Cannot read properties of undefined (reading '_config')のエラーが出た

## はじめに
ChakraUIを導入して、`<ChakraProvider>`を使用した際にエラーが生じて解決に時間がかかったので、その内容をまとめます。

## 開発環境
| 言語・フレームワーク   | バージョン |
| ------------------  | ---------- |
| react               | 18.3.1     |
| react-dom           | 18.3.1     |
| typescript          | 5.5.3      |
| vite                | 5.4.8      |
| chakra-ui/react     | <font color="red">3.0.2</font>      |
| emotion/react       | 11.13.3    |
| emotion/styled      | 11.13.0    |
| frame-motion        | 11.11.11   |

## エラー内容
まずは、以下のように`ChakraProvider`のタグを使用しました。
```react:<font color="red">【修正前】</font>App.tsx
import { ChakraProvider } from '@chakra-ui/react';

export const App = () => {
  return (
    <ChakraProvider>
        <h1>Home</h1>
    </ChakraProvider>
  );
};
```
すると、コンソール上に以下のエラーが発生しました。

![ChakraUIエラー①.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3851095/b9e1bfdd-ad9b-597c-12b2-4843bfcf0da9.png)

そして、vscode上では`value`に何か値を設定してくださいという警告文が表示されていました。

![ChakraUIエラー②.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3851095/6e85f89e-40c6-125a-0471-c6cb609a0952.png)

## 解決方法
修正方法としては、valueに`defaultSystem`を設定することで、解消されました。
```react:<font color="blue">【修正後】</font>App.tsx
import { ChakraProvider, defaultSystem  } from '@chakra-ui/react';

export const App = () => {
  return (
    <ChakraProvider value={defaultSystem}>
      <h1>Home</h1>
    </ChakraProvider>
  );
};
```
バージョンが3に変わったことで、今までとは設定内容も変わったみたい。
ChakraUIのバージョン3の変更点については、また別でまとめようと思います。

## おわりに
ChakraUIの導入初っ端からエラーが出るとは、予想もしていなかった。
時間はかかったが、解決できて良かったー
やっと次に進める！


## 参考記事

https://stackoverflow.com/questions/79148516/property-value-is-missing-in-type-children-element-but-required-in-typ

https://www.chakra-ui.com/docs/get-started/migration
AndroidStudioのエミュレータで回線速度を指定する

# はじめに
以前こちらの記事で５Gを指定できるという旨の記事を書きましたが、それ以外に何が指定できるのか調べたので、その内容を備忘録としてここに残します。



https://qiita.com/Tsubasa12/items/58633af6460c59449ea2

# 一覧表

※以下の表はそれぞれの環境によるところもあるので、参考までに
|NetworkType|回線速度|
|:---|:---|
|GSM|14.4kbps||
|HSCSD|下り43.2Kbps、上り14.4Kbps||
|GPRS|～171.2kbps||
|EDGE|384kbps||
|UMTS|最大2Mbps||
|HSDPA|最大14Mbps||
|LTE|37.5Mbps〜112.5Mbps||
|Full|下り24Mbps～88Mbps　上り6Mbps～14Mbps|
|5G|下り最大10〜20Gbps　上り480Mbps|


それぞれ使用してみましたが、私の環境ではLTE以下のものはほとんど使い物になりませんでした。


# 参考

https://aitech.ac.jp/~furuhasi/gmpc/data/index.html

https://www.mobile-kun.jp/words/detail-1541.html

https://www.google.com/search?sca_esv=ac906d086053e2fc&rlz=1C5GCEM_enJP1131JP1132&q=UMTS%E6%96%B9%E5%BC%8F%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%A7%E3%81%99%E3%81%8B%EF%BC%9F&sa=X&ved=2ahUKEwilnMqv8beJAxWvra8BHU7aOFMQzmd6BAgYEAY&biw=1200&bih=741&dpr=1


https://kotobank.jp/word/hsdpa-3144720#:~:text=%E3%80%8Ahigh%2Dspeed%20downlink%20packet%20access,%E3%81%A6HSPA%E3%81%A8%E3%82%88%E3%81%B0%E3%82%8C%E3%82%8B%E3%80%82


https://www.itmedia.co.jp/mobile/0311/04/n_hscsd.html

https://www.google.com/search?q=LTE%E3%80%80%E9%80%9F%E5%BA%A6&sca_esv=12ce420749b4de42&rlz=1C5GCEM_enJP1131JP1132&ei=VD0nZ9H1BcvW1e8Pxtab0Q4&ved=0ahUKEwjR77H857-JAxVLa_UHHUbrJuoQ4dUDCA8&uact=5&oq=LTE%E3%80%80%E9%80%9F%E5%BA%A6&gs_lp=Egxnd3Mtd2l6LXNlcnAiDExUReOAgOmAn-W6pjIFEAAYgAQyBRAAGIAEMgUQABiABDIFEAAYgAQyBRAAGIAEMgUQABiABDIFEAAYgAQyBRAAGIAESNUQUKUFWKcNcAJ4AZABAJgBoQGgAbIFqgEDNi4xuAEDyAEA-AEBmAIJoALZBcICChAAGLADGNYEGEfCAgcQABiABBgEwgIKEAAYgAQYQxiKBcICBhAAGAQYHsICCBAAGAQYHhgPwgIIEAAYBBgFGB6YAwCIBgGQBgqSBwM3LjKgB_8S&sclient=gws-wiz-serp


https://www.docomo.ne.jp/area/technology/premium_4g/#:~:text=4G%E3%81%AE%E5%AE%9F%E5%8A%B9%E9%80%9F%E5%BA%A6%EF%BC%88%E5%8F%82%E8%80%83,%E6%99%826Mbps%EF%BD%9E14Mbps%E3%81%A7%E3%81%99%E3%80%82

https://www.commufa.jp/article/0142#:~:text=%E5%89%8D%E8%BF%B0%E3%81%AE%E9%80%9A%E3%82%8A%E3%80%815G%E3%81%AE,%E3%81%A8%E3%81%84%E3%81%86%E3%81%93%E3%81%A8%E3%81%8C%E5%88%86%E3%81%8B%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82
【パーティションキー】MySQLにパーティションキーを設定したら5倍クエリが早くなった件【Laravel】

# 結論
100,000件のtestsテーブルからyearカラムに対してパーティションキーを設定して比較した結果はこちら
```php
// クエリ
DB::table('tests')->where('year', 2023)->get();

// パーティションを設定した結果
結果: 0.47547888755798 seconds

// パーティションを設定していない結果
結果: 2.206062078476 seconds
```
**約5倍** は早くなりました...タイトルとおりです。

# パーティションキーとは
パーティション = 仕切り というようにデータを指定した値ごとに仕切ることで、読み込み速度が高速化されます。

2022年、2023年、2024年...ごとにデータが積まれていく場合、年カラムにパーティションキーを設定することで検索結果が早くなります。

※パーティションキーにはいくつかの種類がありますが、今回は特定の範囲に絞り込む「レンジパーティション」に絞り込んで紹介します。


# migrationファイルで設定する
Laravelの機能でパーティションを設定することはできないので、`DB::statemant`でSQL文を記載します。
```php
public function up()
{
    Schema::create('tests', function (Blueprint $table) {

        $table->bigInteger('id', false)->unsigned()->comment('ID');
        $table->integer('year'); // パーティションの対象
        $table->timestamps();
        $table->softDeletes()->comment('削除日');
        $table->comment('テスト');
    });


    //yearカラムに対して2020,2021,2022,2023,2024のパーティションを設定
    DB::statement("
        ALTER TABLE orders
        PARTITION BY RANGE (year) (
            PARTITION p2020 VALUES LESS THAN (2020),
            PARTITION p2021 VALUES LESS THAN (2021),
            PARTITION p2022 VALUES LESS THAN (2022),
            PARTITION p2023 VALUES LESS THAN (2023),
            PARTITION p2024 VALUES LESS THAN (2024)
        );
    ");
}

public function down()
{
    Schema::dropIfExists('tests');
}
```

# 設定してみた感想
使用する用途としては、**データの作成更新を行わず検索のみ行う**場合が最も使いやすいかなと思います。（自分の知識がないだけかもしれません...）

#### 理由その１：`id`に自動インクリメントを設定している場合、パーティションを設定できないため
通常、`id`に対して自動インクリメントをオンにして使用することが多いと思います。
```php
$table->bigInteger('id', true)->unsigned()->comment('ID');
```
しかしこの状態でパーティションを追加しようとすると以下のエラーが表示されます。
```
SQLSTATE[HY000]: General error: 1503 A PRIMARY KEY must include all columns in the table's partitioning function (prefixed columns are not considered).
```

パーティションキーにはプライマリーキーの指定が必要
↓
プライマリーキーはテーブルに対して1つのため、`id`を使用している場合複合キーとして設定する（今回は`id`と`year`）
↓
複合キーに使用するキーは、自動インクリメントがついていると使えない
↓
`id`使えないやん...

というオチです。
そのため自動インクリメントを使用する場合は設定ができません。

#### 理由その２：毎年の設定が必要
migrationファイルからわかるように**どの範囲までを仕切る対象とするか**を記載しないといけません。
そのため、cron等で年を超えた際に新しく追加しなければいけません。

以上の理由から、ユーザーからのデータ作成や更新が行われないデータに対して設定する場合に限定されるかなと思いました。
ただ、検索処理は爆速になるため
- 過去データから新しくデータを作成する際、過去データに設定
- 年や月ごとの入会者数や決済数をカウントするために、バックアップデータを複製して設定

などのケースに使用したいなと思ってます。

# 最後に

https://www.amazon.co.jp/dp/B0D8N5G9GT/ref=sspa_mw_detail_0?ie=UTF8&psc=1&sp_csd=d2lkZ2V0TmFtZT1zcF9waG9uZV9kZXRhaWwp13NParams#atwl_secondary_view_1730526228636

こちらの神良本を読んでパーティションという機能があることを知りました...
よく紹介されていますが第二版が出版され、AWSといったクラウド環境におけるデータベースの取り扱いについての記載が増え、とても勉強になりました...
おすすめです！！
Gitで500KB以上のファイルを自動で無視する方法

以下に、500KB以上のファイルを検出し、`.gitignore`に追加する方法の概要と、500KB以下のサイズ制限をおすすめする理由を含めてまとめました。これにより、プロジェクトのサイズを効果的に管理し、リポジトリのパフォーマンスを維持することができます。

---

## Gitで大容量ファイルを自動で無視する方法（500KB以上推奨）

大規模なプロジェクトやデータファイルを扱う際、大容量ファイルがリポジトリのパフォーマンス低下を引き起こすことがあります。GitHubなどでは100MBを超えるファイルはアップロードできないため、ファイルサイズを管理することが重要です。500KB以上のファイルにサイズ制限をかけることで、効率的に管理できます。

### ステップ 1: `.gitignore`ファイルの作成

リポジトリのルートディレクトリに`.gitignore`ファイルを作成し、無視するファイルやディレクトリをリストに追加します。以下は一般的な例です。

```gitignore
# Python関連の一時ファイル
__pycache__/
*.pyc

# 大容量ファイル
*.zip
*.tar.gz
```

### ステップ 2: `find`コマンドで500KB以上のファイルを検出

以下のコマンドを使用して、500KB以上のファイルをリストアップし、`.gitignore_large_files`に保存します。

```bash
find . -size +500k > .gitignore_large_files
```

このコマンドでは、プロジェクト内の500KB以上のファイルを検出し、そのパスを`.gitignore_large_files`というファイルに記録します。

**ポイント:** 個人的には500KB以下のサイズ制限を推奨します。500KB以上のファイルは、リポジトリの肥大化やパフォーマンス低下の原因となり得ます。

### ステップ 3: `.gitignore`に大容量ファイルを追加

次に、`.gitignore_large_files`の内容を`.gitignore`に追加し、Gitがこれらのファイルを無視するように設定します。

```bash
cat .gitignore_large_files >> .gitignore
```

### ステップ 4: 一時ファイルの削除

作業が完了したら、`.gitignore_large_files`を削除してクリーンアップします。

```bash
rm .gitignore_large_files
```

---

この方法を使えば、リポジトリ内の500KB以上のファイルを簡単に管理でき、プロジェクトのパフォーマンスも向上します。
scopeをif文のように使う

## 初めに

疑問に思ったことや上手くいかなかったことのアウトプットをしています。
自分なりの理解でアウトプットしていきます。初学者なので誤りもあると思います。
その際はご指摘いただけると幸いです。

## scopeでのwhereの役割
whereはデータベースからレコードを絞り出す役割がありますが、
フォームから送信されてまだ保存されていないレコードも保存できます。

**この絞り出す機能が、結果的にif文のような役割を果たします。**

## scopeにおいての比較演算子を使用する際の注意点
```
scope :exampled, -> { where('aaa_at <= ?', Time.current) }
```
のように、
```
scope :exampled, -> { where('aaa_at <= Time.current') }
```
と書かないのは、理由があります。

1．SQLインジェクション対策
直接値を埋め込むと、意図しないSQLコードが実行される恐れがあります。

2．時間の評価
'aaa_at <= Time.current'と書くと Time.currentが文字列として認識され、正しく評価されません。

安全で正確にクエリを実行するために、以上のように書く必要があります。