OmniAICreator/Qiita-1.07M huggingface dataset:
WordPressで閲覧パスワードを設定、URLクエリパラメータで認証する

## 背景
- ログイン認証が必要なページに、パスワード付きのWordPressのサイトをiframeで埋め込みたい
- ユーザーのログイン操作は元サイトの1度に留めたい

## 注意事項
- ソースやリクエストにはパスワードが含まれる為、iframe呼び出し元サイトの認証後にのみDOMへの反映、アクセスするようにすること（SPA要注意）
- ソースを公開している場合には（Github等）環境変数などを使用してパスワード付きURLクエリを生成するようにし、ソース上に直接パスワードが記述されないようにすること

## 手法
1. [Password Protected](https://ja.wordpress.org/plugins/password-protected/
) WPプラグインにてWordPress側にパスワードを設定
1. iframeに```https://example.com/?password_protected_pwd=password&redirect_to=https://example.com/```を指定
※ password_protected_pwd=設定したパスワード



引用：
> https://wordpress.org/support/topic/pass-password-as-url-parameter/
【Terraform x Snowflake】Terraformで外部テーブルを定義するときのlocation指定方法

# 結論

Terraform Snowflakeプロバイダの[外部テーブル](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/external_table)より、locationの指定は「`Required`」との事だが、ドキュメントには具体的な記載方法が載っていないためよくわからなかったが、以下のように書くとよい。

```hcl
resource "snowflake_external_table" "external_table" {
  database    = "MY_DATABASE"
  schema      = "MY_SCHEMA"
  name        = "MY_EXTERNAL_TABLE"
  location    = "@MY_DATABASE.MY_SCHEMA.MY_EXTERNAL_STAGE/path_to_file/"
  file_format = "TYPE = PARQUET"

  column {
    name = "ID"
    type = "VARCHAR"
  }

  column {
    name = "DATA"
    type = "VARCHAR"
  }

}
```

# 背景

前述の通り、Terraformでのlocationの記述方法がわからなかったため、Snowflake公式ドキュメントの[外部テーブル](https://docs.snowflake.com/ja/sql-reference/sql/create-external-table)の記載を参考にTerraformに書いてみた。

その結果はエラー。どうやら書き方が違うらしい。
同じlocation(外部ステージ)を認識させるのに複数の書き方が考えられるが、なかなか正解に辿り着かなかったため記録に残しておこうと思った。

# ぼやき

公式ドキュメントに記載例が書いてないパターン。
さらに、Terraform上の記載と、Snowflake(SQL)上の記載とではまた勝手が違うのも厄介。

- ステージを参照する書き方のバリエーション
    - @指定の省略表記

        ``` hcl
        # SnowflakeのSQLではOK、TerraformではNGな書き方
        @MY_EXTERNAL_STAGE
        ```

        これがTerraformで通らないのは、納得がいかない。

        なぜなら、外部テーブルを定義する際はdatabaseとschemaも必須パラメータであり、これら指定する時点でどのスキーマオブジェクトであるのかは(=どのスキーマ配下に存在する外部ステージなのか)は明確であるはずなので。

        だが、Terraformでは認識できない仕様らしいので仕方ない。

    - @を付けない完全修飾表記

        ``` hcl
        # SnowflakeのSQLではOK、TerraformではNGな書き方
        MY_DATABASE.MY_SCHEMA.MY_EXTERNAL_STAGE
        ```

    - @指定の完全修飾表記

        ``` hcl
        # これで通るんかい...
        @MY_DATABASE.MY_SCHEMA.MY_EXTERNAL_STAGE
        ```

        Snowflake上ではまずこのような指定はしないんじゃなかろうか。

        ``` sql
        -- SQLワークシートで書く時は、大体こうやるはず
        USE MY_DATABASE.MY_SCHEMA;
        CREATE EXTERNAL TABLE MY_EXTERNAL_TABLE(
             -- 中略
             LOCATION=@MY_EXTERNAL_STAGE/path_to_file/
             FILE_FORMAT = (TYPE = PARQUET)
             -- 中略
        ;
        ```

よくわからんものですな...
10年前からあるSafariのメモリリーク問題が結構やばい


# 背景
個人的なプロジェクトでTauriを使った画像解析(WaveformやVectorScopeの計算)アプリを作ろうとしていた。
しかし、フロントエンド側(WebView)で画像を表示/更新する度にアプリのメモリ使用量が増え、プロセスが死ぬまで解放されないことに気がついた。

結論としては、「**Safari自体が、表示しなくなった画像のメモリを解放していない**」というのが原因のようだった。


# 発生環境
CPU: Apple M1 Pro
OS: macOS 13.4.1 (22F82)
Safari: Version 16.5.1 (18615.2.9.11.7)



#### 再現方法
以下のStackOverflowの回答にあるRun CodeSnipetを連打すると確認できる。

https://stackoverflow.com/questions/38781947/create-base64-data-from-html-canvas-imagedata-without-canvas-element

ページ表示直後
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3361273/df9f5340-405f-34dd-d663-5cbcf6be49f6.jpeg">

Run CodeSnipetを30回押した後
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3361273/2a7c1a14-265d-ff15-5a6f-578fe7844f71.jpeg">

何が問題かって、「同じ内容を再描画するだけでもメモリ使用量がどんどん増える」ってとこ

# なぜSafariが悪いと気づいたか(原因調査)
### Tauri / WRY
初めはTauriの問題かと思い調査
TauriとWryのGitHubで情報を集め、似たようなメモリリークのIssueを発見

https://github.com/tauri-apps/tauri/issues/4026

このIssueでは、TauriのAPIでバックエンドから大量のデータを送信する度にメモリ使用量が増えるというものだった。
残念なことに、このIssueはまだOpenであり、根本解決はできていないようだ。
ただコメントにWebViewが悪いという指摘があったりして、役立つ情報は結構あった。



### Rust
バックエンドからデータを送信する際に起きる問題であれば、Rust側には問題がないかも調査する必要がある。
通常フロントエンドから呼び出す処理を、バックエンドでループさせてメモリ使用量を確認した。

```:Rust側確認コード
fn main() {
    loop {
        create_big_blob();
    }
...
}
```

一秒間におおよそ10MB~20MB程度のBlobが生成される処理スピードだったが、一分間回して250MB程度のメモリ使用量で落ち着くことが確認できた。(ピーク時でも300MBを超えない程度)
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3361273/a3762e47-be61-d5ed-1eae-872dd7dfe1c8.jpeg">


***つまりRust側ではメモリリークは発生していない。(流石Rust)***

### Safari
結局これ単体で問題は発生した。
Tauriも使わず、HTMLファイルだけでBase64エンコードした画像を表示するだけでも発生した。

WRYはWebViewを使いGUI表示をするため、MacにおいてはSafariが使われることになる。
Safariのコードを変えることはできないので、JSなどの実装をどうにかして対策するしかなさそう。

# 10年以上前からある問題?

色々対策のため調査をしていたところ、以下のStackOverflowの質問を見つけた
なんと**2011年12月**の投稿である。


https://stackoverflow.com/questions/8538917/data-uri-leak-in-safari-was-memory-leak-with-html5-canvas

> I have created a webpage that receives base64 encoded bitmaps over a Websocket and then draws them to a canvas. It works perfectly. Except, the browser's (whether Firefox, Chrome, or Safari) memory usage increases with each image and never goes down. So, there must be a memory leak in my code or some other bug.


この人の報告では、画像を描画する度メモリ使用量が増えるが、下がることはないとのこと。
(SafariだけでなくChromeやFirefoxでも発生していたらしい)

実装が悪いようにも見えないけど、なんでこれでリークするんだろうか?
一応Updateで解決したとは言ってるけど、ワークアラウンド対応も面倒そうで困る・・・

# 疑問
まだGUIについて詳しく無いが、色々調べた結果Safariが悪いという結論に至った。
WebViewとして画像をずっと保持するっていうのは正常な動作なのかもしれないけど、
何GBもキャッシュするのはどうなんだろうか?

そもそもページを切り替えてないからこれはメモリリークとは言わないとかあるかも?

もしこの記事に間違いがあったり、技術的背景がわかる人がいらっしゃったら是非ご教授願います。

# 2023-07-04追記
WebkitのBug報告としても2010年から上がっていました
しかし、この挙動が仕様として正しいというような回答もあり、やはりそういうものだと諦めるしかないのでしょうか・・・

https://bugs.webkit.org/show_bug.cgi?id=31253

同様にElectronでもImageを多く読み込むとメモリ使用量が増え続けるという相談も多々見つけられました
WebViewが嫌いになりそう


https://github.com/electron/electron/issues/11550

https://github.com/electron/electron/issues/24835
13年間落ち続けた基本情報技術者試験に受かった件

<h1>初めに</h1>
今回受けた基本情報から大幅に試験形式が変更となりました。
<h1>本題</h1>
試験形式が変わったから受かったと思われても仕方無いような合格の仕方をしましたが、
気合で受かります。
重要なものは<strong>気合</strong>です。これはガチです。
一分も無駄にしないように問題に食らいついて行きましょう。
１３年間落ち続けた理由は根性と問題にずっと食らいついて一瞬でも気をそらす
時間があったのが敗因です。
持病で頭がぼーっとして集中力が散漫になるというのもありますが、その辺も今回は薬でカバーできたのも大きいでしょう。
<h1>根本的にした対策一覧</h1>
<ul>
    <li>朝は眠くならない程度に食べる</li>
    <li>コーヒーは一杯だけ摂った</li>
    <li>今回はAとB試験が同日程で受けたので良い感じで頭が働く状態になった</li>
</ul>
<h1>最後に</h1>
緊張しない対策、眠くならない対策をすることが重要だったと思います。
１３年間受からなかった理由としてはメンタルとか戦略的な部分にフォーカスしないで、
ずっと過去問やテキストを読み込みずっと対策してたことですね。トータルとして一万時間は勉強したと思います。
Pythonで計算問題の小テストを一瞬で作成する方法

Pythonで計算問題の小テストを一瞬で作成する方法を紹介します。

## 作り方

あらかじめ、Pythonで計算問題を作るプログラムを作成し、保存しておきます。

つぎに、別のPythonファイルを作成し、先に作っておいたファイルを読み込みます。

ファイルを2つ作る理由は、計算問題を扱う複数のPythonファイルをフル活用するためです。

計算問題の内容が変わっても、テストの形式（書式）は変わりません。

## 計算問題のサンプルを作成する

ここでは前回作成したプログラムをそのままコピーして計算問題のサンプルを作成します。

※ファイルはホームディレクトリに保存します。

```Python:keisan1.py
import random

a=random.randint(0,9)
b=random.randint(0,9)

o=random.randint(0,9)
p=random.randint(0,9)
q=random.randint(0,9)
r=random.randint(0,9)
s=random.randint(0,9)
t=random.randint(0,9)

c="+"
d="-"

e="("
f=")"




print(e,c,str(a),f,"+",e,c,str(b),f)
print('\n')
print(e,d,str(o),f,"+",e,d,str(p),f)
print('\n')
print(e,c,str(q),f,"+",e,d,str(r),f)
print('\n')
print(e,d,str(s),f,"+",e,c,str(t),f)

```


## ファイルを複数する

先に作ったkeisan1.pyファイルをコピーし、同じファイルを合計で4つ作ります。

次に以下のように名前を変更します。

keisan1.py

keisan2.py

keisan3.py

keisan4.py

ファイルの中身は全く同じです。

※ファイルはホームディレクトリに保存します。




## テストを作成する

ここでは先のプログラムを読み出して、テストを作成します。

```Python:test-mondai.py
print('問題1\n')

print('次の問題を解きなさい。\n')

import keisan1

print()

print('\n')

print('問題２\n')

print('次の問題を解きなさい。\n')

import keisan2

print('\n')

print('問題３\n')

print('次の問題を解きなさい。\n')

import keisan3

print('\n')

print('問題４\n')

print('次の問題を解きなさい。\n')

import keisan4

```

## 出力結果のサンプル

先のファイルを実行すると、以下のように出力されます。

```:test-mondai.pyの出力結果
問題1

次の問題を解きなさい。

( + 6 ) + ( + 7 )


( - 6 ) + ( - 6 )


( + 8 ) + ( - 0 )


( - 3 ) + ( + 1 )



問題２

次の問題を解きなさい。

( + 2 ) + ( + 0 )


( - 2 ) + ( - 3 )


( + 3 ) + ( - 2 )


( - 0 ) + ( + 3 )


問題３

次の問題を解きなさい。

( + 1 ) + ( + 9 )


( - 9 ) + ( - 1 )


( + 1 ) + ( - 3 )


( - 7 ) + ( + 9 )


問題４

次の問題を解きなさい。

( + 7 ) + ( + 5 )


( - 7 ) + ( - 1 )


( + 9 ) + ( - 6 )


( - 9 ) + ( + 6 )

```


## 別の小テスト問題を作成する

別のテスト問題のファイルを作成することで、新しい小テストを作成することができます。

コードはこちら。

Pythonで正負の数 （減法）の問題を自動作成する方法 - Qiita https://qiita.com/akiba_burari/items/3948eef74dd9f9b100ba

pythonファイルを作成したら、

test-mondai.pyの中にあるファイル名を書き換えてください。

**import ファイル名**








## 参考

【Python】別の.pyファイルを呼び出して実行する方法とその意義 - ゆんの業務改善ブログ https://www.mutable.work/entry/import-other-scripts

## 関連記事

Pythonで正負の数 （加法）の問題を自動作成する方法 - Qiita https://qiita.com/akiba_burari/items/777dec85e9fcd59d1f49

【超基礎編】Pythonで中学 数学の問題を自動作成する方法 - Qiita https://qiita.com/akiba_burari/items/f8a11cf0533b889e0af3
【TypeScript】型エラーを無視する方法


## 無視する方法

以下のように記述するとどちらも次の行の型エラーを無視できます。  

```ts
// @ts-ignore
```

```ts
// @ts-expect-error
```

![スクリーンショット 2023-05-11 21.38.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/f9128db7-30da-633e-8747-34faeb9dc550.png)

画像のようなエラーが発生している場合に以下の画像のようにするとエラーが出なくなります。

![スクリーンショット 2023-05-11 21.38.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/1e4a188b-49f3-393f-9664-07ec0ede1419.png)
![スクリーンショット 2023-05-11 21.39.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/b018f1e2-6965-423f-b06d-b4393187d42f.png)

## 2つの違い

次の行にエラーがない場合の挙動に違いがあります。  
`@ts-ignore`は何も起こらないのに対し、`@ts-expect-error`はエラーとなります。  

エラーのあった`<List />`を削除すると`@ts-expect-error`ではエラーが出ています。

![スクリーンショット 2023-05-11 21.40.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/cd100d54-a7d7-cc09-0104-6b1120585f61.png)
![スクリーンショット 2023-05-11 21.40.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/36dbcd58-aabb-9050-69fd-f2d3d12a3807.png)

## 参考

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#-ts-expect-error-comments
Qiitaはじめました

# はじめに
　Youtubeを見ていたら、エンジニアはテックサイトに投稿することで、いろいろな良いことがあると聞き、Qiitaを始めました。学んだことをアウトプットすることで記憶に残りやすくなったり、就職の際にアピールにもなるなど、これは始めるしかないと思いました。テックサイトと言ってもQiitaのほかにZennやWordPressを使用した個人ブログも考えましたが、手軽に始めることができるQiitaを選択しました。
　私は趣味でWebサイトを作ろうとしているただの一般人です。C言語を授業で学びましたが、if文やwhile文が書ける程度で、ポインタまで行くと少し怪しいです。投稿する内容も初歩的なものになると思います。私と同じレベルの初学者の参考になればうれしいです。
# 目標
　現在の目標は、あるゲームの攻略サイトを作ることです。HTMLとCSSについての勉強は大方終了したので、今後はPHPやMySQLなどのバックエンドの勉強をしていきたいと思っています。そのため、投稿内容はPHP、MySQL関係になると思います。SNSなどでは見る専だったので、インターネット上で情報を発信すること自体が初めての経験です。いろいろ疎いところがあると思いますが、お手柔らかにお願いします。
# 最後に
　今回は初めての投稿ということで、コードなどを一切載せていませんが、今後はちょっとづつ載せていきたいと思います。
Djangoでアップロードした画像が表示されない問題の解決法

# はじめに
画像をアップロードしてるし，mediaにもしっかり入っているのに表示されなくて，1日費やしたので備忘録としてのこしておく

# 直し方は簡単
DEBUG = False
にして公開しているところを
Trueに戻した後に
Falseにもどせ！！


# 問題点
FalseとTrueを変えると，mediaやstaticを読みに行く場所が変わるようです
以下参考
https://rurukblog.com/post/Django-debug-false/
EC2 instance connect で RDS に接続してみる

## EC2 のセットアップ

まずは EC2 インスタンスのセットアップから始めます。

- 参考：[EC2 Instance Connect を使用して接続 - Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-connect-methods.html)

### やったこと

コンソール上で選択した項目などをリストにしています。

- EC2インスタンス作成・起動
  - amazon linux 2023 を選択しサイズなどもろもろ設定
  - サブネットをパブリックに
  - パブリックIP有効化
  - 適宜 VPC 選択
- RDS の SG に EC2インスタンスのプライベートIPを設定

## `psql` のインストール

このとき、インスタンスが Amazon Linux 2023 であることを失念しており少し手惑いました。

- 参考：[Linux に psql をインストールする - ablog](https://yohei-a.hatenablog.jp/entry/20170826/1503713318)
- 参考：[Amazon Linux 2023にはamazon-linux-extrasが入っていなかったお話](https://zenn.dev/techa_log/articles/d2f766d38c0407)
- 参考：[Amazon EC2でAmazon Linux 2023を選んだら、nginxのインストールでハマった件 – インターステラ株式会社 技術ブログ](https://blog.interstellar.co.jp/2023/05/11/amazon-linux-2023-nginx-install/)

```
sudo dnf search postgresql
```

```
sudo dnf install -y postgresql15-server
```

```
which psql
/usr/bin/psql
```

インストールできました。

```
psql "host=hogehoge.cluster-xxxxxxxxxx.ap-northeast-1.rds.amazonaws.com user=postgres dbname=fugafuga port=5432"

Password for user postgres: 
psql (15.0, server 13.6)
SSL connection (protocol: TLSv1.2, cipher: DHE-RSA-AES128-SHA, compression: off)
Type "help" for help.

fugafuga=> 
```

RDS の PostgreSQL にログインできました。
（サーバーが13.6なのは意図的です）

```
fugafuga=> \dt;
                 List of relations
 Schema |          Name          | Type  |  Owner   
--------+------------------------+-------+----------
 public | failed_jobs            | table | postgres
 public | folder_item_orders     | table | postgres
 public | migrations             | table | postgres
 public | password_resets        | table | postgres
 public | personal_access_tokens | table | postgres
 public | users                  | table | postgres
(11 rows)
```

テーブル一覧も確認することができました。

いろいろやり方はあるとは思いますが EC2 Instance Connect を利用することで比較的手間なく RDS に接続することができたと思います。

以上です。
AWSクラウドの概念　AWS Well-Architectedフレームワーク


AWS Well-Architectedフレームワークとは、信頼性、セキュリティ、効率、コスト効果が高いシステムを設計してクラウドで運用するために作られたアーキテクチャのベストプラクティス。

https://d1.awsstatic.com/whitepapers/ja_JP/architecture/AWS_Well-Architected_Framework.pdf

AWS Well-Architectedフレームワークは、5つのことを基本としている。

1. 運用上の優秀性
2. セキュリティ
3. 信頼性
3. パフォーマンス効率
3. コスト最適化
【AES256-GCM】暗号化メソッドをNode.js・TypeScriptで実装する

Node.js・Express・TypeScriptを使い、自前で暗号化処理を作成したので備忘録として書きます。この記事では、AES256-GCMという強固な暗号化アルゴリズムを利用して、データを安全に暗号化する方法を解説します。

## はじめに
この記事では、Node.js、Express、およびTypeScriptを使用して、AES256-GCM暗号化アルゴリズムを使ってデータを暗号化するプロセスを書いています。AES256-GCMは共通鍵暗号化方式の一部で、安全なデータ保護を目的として広く使用されています。

## AES256-GCMとは
暗号化方式には主に以下の2種類が存在します。

- 共通鍵暗号化
- 公開鍵暗号化

AES256は共通鍵暗号化方式の一つで、特にセキュリティが強化されています。AES256には、ECBモードとGCMモードの2種類があり、GCMモードは認証付き暗号化を提供し、データの機密性と完全性の両方を保護するため、より堅牢です。

## bcryptとの違い
bcryptは、主にパスワードのハッシュ化に使用される一方向性関数です。ハッシュ化されたデータは元に戻すことが非常に困難です。これは、ソルトと呼ばれるランダムな文字列を平文に付与し、ストレッチング（ハッシュ値への変換を数千〜数万回行うこと）を行うためです。

AES256-GCMは二方向性の暗号化方式であり、適切なキーを持っていれば暗号化されたデータを復号化することができます。

## AES256-GCMで必要なもの
AES256-GCMを使用する際には、以下の要素が必要です。

- 平文: 暗号化する対象のデータ
- Key: 暗号化および復号化の際に使用する秘密鍵
- IV: 初期化ベクトル。暗号文のパターンを予測困難にするためのランダムなデータ

## TypeScriptでの実装
以下にTypeScriptで実装したコードを示します。この例では、暗号化プロセスを関数として定義しています。
なお、実際に使用した内容からは改変しております。

```ts
const crypto = require('crypto');

export const encrypt = async (original: string): Promise<string> => {
	const cipher = crypto.createCipheriv(
		// AES-256-GCM暗号化アルゴリズムを使用します。
		"aes-256-gcm",
		// 256ビット（32バイト）の暗号化キーを指定します。
        // 実際の開発では、このキーは秘密にしておく必要があります。
        // 環境変数などを利用して外部から読み込むのが一般的です。
		Buffer.from("6927bb1e3619a9db79432f99b8cb237a8d70c5272b6e72d0321d40f8e3c35e18", 'hex'),
		// 初期化ベクトル（IV）を指定します。
        // IVは暗号化の過程で使われ、暗号文のパターンをより予測困難にします。
        // これも秘密にする必要があり、実際の開発では外部から読み込むのが一般的です。
		Buffer.from("55d7b7025ba6e8a5a5aa5b5c", 'hex')
	);

	// 平文をUTF-8エンコーディングで暗号化し、cipher.final()を呼び出して暗号化プロセスを完了させ、結果の暗号化されたデータをバッファとして取得します。
	const encrypted = Buffer.concat([
		cipher.update(original, 'utf8'),
		cipher.final(),
	]);

	// 暗号化されたデータをBase64エンコーディングして文字列として返します。
	return encrypted.toString('base64');
};
```
この関数は平文、暗号化キー、および初期化ベクトルを引数として受け取り、暗号化されたデータをBase64エンコーディングの文字列として返します。

注意点として、暗号化キーと初期化ベクトルは安全に管理する必要があります。これらは外部の設定ファイルや環境変数から取得するのが一般的です。

## まとめ
この記事では、Node.js, Express, TypeScriptを用いてAES256-GCM暗号化アルゴリズムでデータを暗号化する方法を解説しました。AES256-GCMは強固な暗号化を提供し、データの機密性を保護します。暗号化キーと初期化ベクトルは慎重に管理し、.envなどで保管することが重要です。
[SwiftUI] SwiftUIでCoreDataのデータ読み込み中にスピナーを表示する

# **背景**

CoreDataは、データの永続化を容易にします。しかし、データを読み込む際に時間がかかる場合、画面が一時的に空の状態になったり、表示が不自然になる場合があります。

# **問題の詳細**

例えば、CoreDataから大量のデータを非同期で読み込む場合、データの読み込みが完了するまで一部のUIが空白になることがあります。これはユーザー体験において理想的ではなく、ユーザーがアプリケーションがフリーズしていると誤解する原因となり得ます。

# **環境**
Xcode : 14.3

Swift : 5.8

SwiftUIを使用



# 解決策

この問題を解決するためには、データが完全にロードされるまで一時的にスピナーを表示します。これによりユーザーはデータがまだロード中であることを知ることができ、安心してアプリを使用することができます。

以下に、この手法を適用したサンプルコードを示します。

```swift
struct ContentView: View {
    @ObservedObject var dataStore = DataStore()

    var body: some View {
						//データがまだ空の場合Spinnerを表示
        if dataStore.items.isEmpty {
            SpinnerView()
        } else {
            DataBasedView(items: dataStore.items)
        }
    }
}

struct SpinnerView: View {
    var body: some View {
        ProgressView()
            .progressViewStyle(CircularProgressViewStyle(tint: .blue))
            .scaleEffect(2, anchor: .center)
    }
}
```

このサンプルコードでは、**`dataStore.items`** が空（つまり、データがまだロードされていない）の場合、スピナーを表示します。データがロードされると、**`dataStore.items`** にアイテムが追加され、Viewが再描画されます。このとき、データを元にしたViewが表示されます。

![RPReplay_Final1688221549.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3352230/c2ae7a92-9375-6bd8-bc61-d94a0c700ba3.gif)


# **まとめ**

SwiftUIとCoreDataを使用してアプリケーションを開発する際、データの読み込みが完了するまでスピナーを表示することで、ユーザー体験を大いに向上させることができます。

いいね、ブックマーク、フォローしていただけると勉強の励みになりますので是非お願いします。😉

追伸　--
Twitterで日々の学習風景を投稿してます。

@Ren_yello
【2023年7月版】AWS認定 クラウドプラクティショナー メモ

# はじめに

新人教育用に、AWS認定クラウドプラクティショナーの範囲の知識でしらないことがないようにするためのメモ
書籍、AWS認定資格試験テキスト　AWS認定 クラウドプラクティショナー　改訂第2版 (ＡＷＳ認定資格試験テキスト)を読んでのメモ

# AWS認定 クラウドプラクティショナー 出題範囲
- クラウドのコンセプト
- セキュリティとコンプライアンス
- テクノロジー
- 請求と料金設定

# クラウドの概念
## クラウドとは
## AWSの長所と利点
- 固定費が柔軟な変動費へ
    - 買い切りでなくなる、使用した分だけ、その分割高
- スケールによる大きなコストメリット
    - これはほんとかなぁ
- キャパシティ予測が不要に
    - 不要ではないが、マックスを意識して調達とかいらなくなる
    - マックスの時だけリソースを使用すればいいので楽
- 速度と俊敏性の向上
    - ハードの調達や、クラスタの設定などの速度が向上
- データセンタの運用と保守への投資が不要に
    - これはほんと、けど、全体を見ると安くなることはほぼ無い
- わずか数分で世界中にデプロイ
    - これはマジ、けど、ほとんどすることない
## クラウドアーキテクチャの設計原理
- 故障に備えた設計
    - 第一に、オンプレより格段にクラウドはプロセスが落ちる、落ちるのが前提の作り込みが必要　＝　工数がかかる
- コンポーネントの分離
    - マイクロアーキテクチャはおわりつつあるかも、一極集中のほうがパフォーマンスが良く、開発工数も運用工数も安い
- 弾力性・伸縮性の実装
    - スケールアップ・スケールアウトともにクラウドでは簡単
    - スケーリング
        - 巡回スケーリング
        - イベントベーススケーリング
            - スケジュールドスケールアウトパターン
        - オンデマンドの自動スケーリング
            - スケールアウトパターン
- 並列化を考慮する
- 動的コンテンツと静的コンテンツの配置
    - 動的コンテンツは物理的にコンピュータの近くに
    - 静的コンテンツは物理的にエンドユーザーの近くに
## AWS Well-Architectedフレームワーク
### 6本の柱
- 運用上の優秀製
- セキュリティ
- 信頼性
- パフォーマンス効率
- コスト最適化
- サステナビリティ
### AWS Well-Architected Tool 
# AWSのセキュリティ
## AWSの責任共有モデル
## AWSクラウドのセキュリティ
## IAM
## セキュリティグループ
## AWS Shield と AWS WAF
### AWS Shieldd
- AWS Shield Standard
- AWS Shield Advanced
    - DDoSへの対応を、DDoS Response Team(DRT)へのアウトソース
    - レイヤー７
    - レイヤー3/4 通知・レポート
    - DDoS対応チームの7D24Hのサポート
    - DDoSによるコスト増加分の払い戻し
### AWS WAF
- 適用サービスは、ALB, CloudFront、API Gateway
## Inspector
- AWS Inspector
    - EC2上のアプリケーションのセキュリティとコンプライアンスを向上させるため、脆弱性診断を自動で行うサービス
- AWS Artifact
- AWS Key Management Service(KMS)
    - CloudTrailと統合された
# AWSのテクノロジ
## AWSのサービス
### AWSサービスのカテゴリ
- コンピューティング
- ストレージ
- データベース
- 移行
- ネットワーキング＆コンテンツ配信
- 開発者用ツール
- 管理ツール
- メディアサービス
- 機械学習
- 分析
- セキュリティ、アイデンティティ、コンプライアンス
- AWSコスト管理
- モバイルサービス
- ARとVR
- アプリケーション統合
- カスタマーエンゲージメント
- ビジネスの生産性
- デスクトップとアプリケーションのストリーミング
- IoT
- ゲーム開発
- その他
## グローバルインフラストラクチャ
# コンピューティングサービス
## EC2
### インスタンスタイプのファミリー例
| ファミリー | ユースケース |
|:-:|:-:|
| T  | 汎用、検証  |
| M  | 汎用  |
| C  | コンピューティング  |
| X, R  | メモリ最適化  |
| P, F, G  | 高速コンピューティング  |
| H, I, D  | ストレージ最適化  |
## ELB
## Auto Scaling
- 水平スケーリング
- 垂直スケーリング
## Lambda
## その他のコンピューティングサービス
- ECS
- Amazon Lightsail
- AWS Batch
# ストレージサービス
## EBS
- 汎用SSD
    - 最大16000IOPS
- プロビジョンドIOPS SSD
    - 最大64000IOPS
- スループット最適化HDD
    - コスト節約
- Cold HDD
## S3
- ACLは2021年に無効化できるようになり、バケットポリシーのみでアクセス制御することが推奨
## その他のストレージサービス
- EFS
- Storage Gateway
- DataSync
- Snowball
- Snowmobile
# ネットワークサービス
## VPC
## CloudFront
## Route 53
# データベースサービス
## RDS
### データベースエンジン
- Amazon Aurora
- MySQL
- PostgreSQL
- MariaDB
- Oracle
- Microsoft SQL Server
## DynamoDB
## その他のデータベースサービス
- Amazon Redshift
- Amazon ElastiCache
- Amazon Neptune
# 管理サービス
## CloudWatch
## Trusted Advisor
- コスト最適化
- パフォーマンス
- セキュリティ
- フォールトトレランス（耐障害性）
- サービス制限
## その他の管理ツール
### CloudTrail
### CloudFormation
### Elastic Beanstalk
# 請求と料金
## AWS料金モデル
## 請求ダッシュボード
## マルチアカウント運用
### AWS Organizations
### 一括請求
## AWSのサポートプラン
## その他の請求サポートツール
### AWS Pricing Calculator

# さいごに
ぜんぶおぼえておこう

# 参考資料
[AWS認定資格試験テキスト　AWS認定 クラウドプラクティショナー　改訂第2版 (ＡＷＳ認定資格試験テキスト)](https://www.amazon.co.jp/dp/4815622744)
【App Store】OpenAI APIを使う時の注意点

# はじめに
先日、App StoreでOpenAI APIを使ったアプリを提出したところ、リジェクトされました。この記事では、その原因を紹介します。

# リジェクト内容
リジェクトされたときのメッセージは以下の通りです。

## 原文
```
Guideline 3.1.1 - Business - Payments - In-App Purchase


In-app purchase gives developers the flexibility to support a variety of business models in their apps. However, your app unlocks or enables additional functionality with mechanisms other than the App Store, which is not appropriate under App Store Review Guideline 3.1.1.

Specifically, 
- your app uses OpenAI API keys to unlock paid OpenAI subscription.
- your app is referring to the OpenAI platform to get a paid API Key to be used in the app.


Next Steps

It would be appropriate to remove these features from your app and any other feature that unlocks or enables functionality with mechanisms other than the App Store. 
```

## 翻訳（DeepLを使用）
```
ガイドライン3.1.1 - ビジネス - 決済 - アプリ内課金


アプリ内課金は、デベロッパーがアプリにおいて様々なビジネスモデルをサポートするための柔軟性を提供します。しかし、貴社のアプリは、App Store以外の仕組みで追加機能をアンロックまたは有効化しており、App Store審査ガイドライン3.1.1では適切ではありません。

具体的には 
- アプリがOpenAIのAPIキーを使用して、有料のOpenAIサブスクリプションをアンロックしている。
- あなたのアプリは、アプリで使用する有料のAPIキーを取得するために、OpenAIのプラットフォームを参照しています。


次のステップ

あなたのアプリからこれらの機能を削除し、App Store以外のメカニズムで機能をアンロックまたは有効にするその他の機能を削除することが適切でしょう。
```

# 原因
ユーザーがAPIキーを入力できたことが原因でした。
OpenAI APIは有料のAPIであるため、APIキーを入力できると、App Store以外の仕組みで課金できてしまうためです。

# 対処法
対処法は、APIキーを入力できないようにすることです。
しかし、既存ユーザーにはこれまで通り入力したAPIキーでサービスを利用してもらいたいので、以下のような対処法をとろうと思います。
- 新規ユーザーには課金画面を表示する
- APIキーが保存されている既存ユーザーは、入力したAPIキーでサービスを利用できるようにする

これで審査に通ることを祈ります🙏

# おわりに
この記事では、OpenAI APIを使った私のアプリがApp Storeでリジェクトされた原因を紹介しました。参考になったと思った方は、いいねしていただけると嬉しいです❤️
zabbix-serverを6.4にアップグレード

## 概要

raspberry piのzabbix serverを標準リポジトリの4系から、zabbixのリポジトリの6.4にアップグレードしたときのメモ

## bullseyeへアップグレード

6.4にするには、bullseye でないといけない。

## mariadbを10.5から10.6へアップグレード (これは要らなかった)

1. mariabackupでバックアップを取る
1. mariadb 10.5をアンインストール
1. 10.6のリポジトリをセットアップして
1. mariadb 10.6をインストール
1. mariadb-upgradeでアップグレード
1. zabbix-serverでセットアップをいろいろ試していたらzabbixデータベースが無くなったので、mariabackupでリストアしてmariadb-upgradeをやり直した

## zabbix-serverをアップグレード

1. zabbix-serverをアンインストール
1. zabbixのリポジトリをセットアップして
1. zabbix-serverをインストール
1. zabbix-server.serviceを起動すると、データベースのアップグレードが行われる
1. アップグレードが失敗することがあるので、ログを見ながらデータベースを修正する。
1. アップグレードが終わったら、Web UIの設定を行う。
No overload matches this call… の解決方法

## 何が起きたのか？

以下のコードを書きました。

```tsx
// index.tsx

window.addEventListener("keydown", handleKeyDown); <== ＠ココ！

function handleKeyDown(event: KeyboardEvent) {
      if (event.code === arrowKeys.left.keyCode) {
        // なにかのコード
      }
    }
```

”＠ココ！” の行の、`handleKeyDown`に対して、TypeScript が次の問題を指摘しました。

```tsx
No overload matches this call.
  Overload 1 of 2, '(type: "keydown", listener: (this: Window, ev: KeyboardEvent) => any, options?: boolean | AddEventListenerOptions | undefined): void', gave the following error.
    Argument of type '(event: KeyboardEvent<Element>) => void' is not assignable to parameter of type '(this: Window, ev: KeyboardEvent) => any'.
      Types of parameters 'event' and 'ev' are incompatible.
        Type 'KeyboardEvent' is missing the following properties from type 'KeyboardEvent<Element>': locale, nativeEvent, isDefaultPrevented, isPropagationStopped, persist
  Overload 2 of 2, '(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | undefined): void', gave the following error.
    Argument of type '(event: KeyboardEvent<Element>) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'.
      Type '(event: KeyboardEvent<Element>) => void' is not assignable to type 'EventListener'.
        Types of parameters 'event' and 'evt' are incompatible.
          Type 'Event' is missing the following properties from type 'KeyboardEvent<Element>': altKey, charCode, ctrlKey, code, and 15 more.
```

ただ、実際の動作は問題なく、こちらが期待した通りでした。

しかし、問題ないとは言っても、いちいち指摘されると気になります。どこを直せばいいのでしょう？

## エラーの解決方法

結論として、コードを以下のように書き換えました。

```tsx
function handleKeyDown(event: KeyboardEvent) {

function handleKeyDown(event: globalThis.KeyboardEvent) {
```
`event` の型定義を厳密にしろということですね。

TypeScriptも納得してくれたみたいで、エラーは表示されなくなりました。

## `globalThis`とは？

＊GPT-3.5

> The **`globalThis`** is a built-in global variable in JavaScript that provides a reference to the global object in any environment (including browsers and Node.js). It was introduced in ECMAScript 2020 to provide a consistent way of accessing the global object, regardless of the runtime environment.

> globalThis は JavaScript の組み込みグローバル変数で、あらゆる環境（ブラウザや Node.js を含む）でグローバルオブジェクトへの参照を提供します。これは、実行環境に関係なくグローバルオブジェクトにアクセスする一貫した方法を提供するために ECMAScript 2020 で導入されました。


## `globalThis`が必要なことにどのようにして気づいたか？

`addEventListener` 内で関数を直接書きます。

```tsx
window.addEventListener("keypress",(e)=>{console.log(e.type)})
```

VSCodeであれば、`e`の部分にカーソルを合わせると、次のメッセージが現れるかと思います。

```tsx
(parameter) e: globalThis.KeyboardEvent
```

画像だとこんなかんじ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552712/660fdc25-7b9c-797a-4a69-978ddbaf5a2d.png)


これで必要な型が`globalThis.KeyboardEvent` であることがわかります。

以上です。
[備忘録] KMM触ってみた

## 概要
[Get started with Kotlin Multiplatform for mobile](https://kotlinlang.org/docs/multiplatform-mobile-getting-started.html)をやった。
気になったことを書き残しておく。

## kdoctor
名の通りKMMに必要なコンポーネントがすべて適切にインストールされているかを診断する。
- システム
- JDK
- Android Studio
- Xcode
- Cocoapods

MacOS 上でのみ動作する。

https://github.com/Kotlin/kdoctor

## @Serializable アノテーション
意味：直列化。
ファイルへのデータ保存・読込を行う際に使う。
ポインタを使用している関係から、通常の状態だとデータの保存・読込ができない。
データの保存・読書が可能なようデータを整形する処理が直列化(Serialize)らしい。

## @SerialName アノテーション
JSONとDataClassで名前が不一致の場合など、キー名と違ったパラメータを紐づける場合に使う。
対応するSerialDescriptorのクラスまたはプロパティの名前をオーバーライドする。

## 感想
iOS周りが全くわからんかった。それ以外は特になし。

## 参考
- https://www.ne.jp/asahi/hishidama/home/tech/java/serial.html
- https://smile-jsp.hateblo.jp/entry/kotlin/serialization-basic
シェルスクリプトでLet's encryptの無料SSL証明書を発行(追加情報)

# Let's encrypt の無料SSL証明書 発行の追加情報
これは、以前Qiitaに投稿した
　<a href="https://qiita.com/mighty-n/items/5d63c90a204318a5fc7c">シェルスクリプトでLet's encryptの無料SSL証明書を発行(CentOS6対応)</a>
の追加情報です。
Let's encrypt の SSL発行は前記のリンクを参照して下さい。

# SANsに対応させた証明書を発行したい
1枚のSSL証明書で複数ドメインの設定が可能な、SSLサーバー証明書の拡張機能に「SANs」という機能があります。
使い方としては、 www.yourdomain.com でも、wwwをつけない yourdomain.com でアクセスされてもSSL証明書を有効にしたい場合などに使えます。
つまり１つのSSL証明書に、www.mysite.com と mysite.com の２つのドメインを入れることができるのです。実際には２つとは限らず複数ドメインに対応させることが可能です。
対応させるには、ACLの項目を追加し、認証用のacme-challengeファイルの格納される位置を、スペースで区切って複数指定します。

```.getssl/yourdomain.com/getssl.cfg
SANS="www.yourdomain.com"
ACL=('/var/www/html/.well-known/acme-challenge' '/var/www/html/.well-known/acme-challenge')
```
上記は、yourdomain.com に www.yourdomain.com のSANsを追加対応させる例です。

# 証明書を強制的に作成したい
設定を間違えってしまった場合など、もう一度設定ファイルを書き換えても、 オプションをつけてコマンドを実行しないと証明書を上書き再発行できません。
こういう場合には、 -f オプションで強制再発行を実行して下さい。
```
#./getssl -f yourdomain.com
```

# 証明書を自動更新したい
Let's encrypt の無料SSL証明書は、証明書の有効期限が90日です。有効期限内に更新しなくてはなりません。
こういう場合は、CRONtabに下記の１行を追加設定して自動的に証明書が更新されるように設定します。

```crontab -e.
00 04 01,15 * * /root/getssl -u -a -q
```
上記は。毎月1日と15日の午前4時に更新チェックをして、必要なら更新する例です。 -a オプションで全てのドメイン(~./getssl/以下にある全てのドメイン設定ファイル)を更新します。

# 証明書が更新された後にWEBサーバーを再起動したい
前項のように証明書が延長再発行されても、再読込しなければ有効にはなりません。
この場合、更新後にWEBサーバーの設定を再読み込みするように設定できます。
```.getssl/yourdomain.com/getssl.cfg
RELOAD_CMD=('systemctl reload httpd')
```
ログファイルのローテション等で別途再起動していれば、これは設定しなくても問題ありません。

# WordPress対策
Let's encryptでは、証明書を発行する際のチェックとして、.well-known/acme-challengeファイルを置き、ポート80をhttpアクセスしてこのファイルを確認して認証を行います。
WordPressでは、URLをリダイレクトするので、そのままでは正常に認証できません。
また、常時SSL環境ではWordPressに限らず、httpをhttpsにリダイレクトする場合も多々あります。
この場合、下記のように httpd.conf ファイルのVirtualHost部分を書き換え、alias設定をして、WEBサーバーを再起動することにより対応可能です。
```/etc/httpd/conf/httpd.conf
<VirtualHost *:80>
    DocumentRoot /var/www/html
    ServerName www.yourdomain.com
    # for Let's Encrypt
    Alias /.well-known/ /var/www/html/.well-known/
</VirtualHost>
```
WordPressを置いてある .htaccess を書き換えるほうが簡単で事例も多いのですが、WordPressやプラグインは.htaccessファイルを書き換えることがあるので、alias設定をしてしまったほうが運用上安心です。

# nginxサーバーに対応した証明書を発行したい
nginxでは、Apacheのように中間証明書が設定できず、ドメインの証明書と中間証明書を１つのファイルに連結させて指定する必要があります。
.getssl以下のドメインのディレクトリに、 fullchain.crt というファイル名でドメインの証明書と中間証明書を１つのファイルにして生成されています。
生成後に他のディレクトリにコピーする場合は、以下のように設定を追加します。
```.getssl/yourdomain.com/getssl.cfg
DOMAIN_CHAIN_LOCATION="/etc/ssl/fullchain.crt"
CodeSandboxでReactプロジェクトの「react」ライブラリをv18→v17に変更した際に起きる「ModuleNotFoundError」を解決する

# はじめに
Udemyでじゃけぇさんの講座（https://www.udemy.com/course/react_stepup/）
を受講中に、Reactのバージョンをv18からv17に戻そうとしてエラーが起きたので、その解決方法を共有したいと思います。

# 結論
「react」ライブラリのバージョンを17に変更後、index.jsを以下のように変更すると直りました。
```index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

```

# まとめ
初学者だったので知りませんでしたが、どうやらReactのv17とv18ではindex.jsの記述が異なるようで、そのせいで起こったエラーでした。
【docker-composeデータ永続化】Django + MySQLのDocker環境のデータ永続化

## はじめに
以前構築したDjango + MySQLのDocker環境について、コンテナの停止・削除(docker-compose down)を行なってもDBに保存したデータが消えないよう、データ永続化のための設定をdocker-composeに追記しました。

以前書いた[環境構築の記事](https://qiita.com/mei2678/items/ebf2b3311965eb649a93)も更新済みです。

## 前提環境
PC: MacBook Air M2
OS: macOS Ventura Ver. 13.2.1
Homebrew: 4.0.9
Docker: 20.10.23
docker-compose: v2.15.1

## 設定内容
設定変更後のdocker-compose.ymlの内容は次の通りです。

```yml:docker-compose.yml
version: '3.9'
services:
  db:
    container_name: mysql
    image: mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    volumes:  #追記
      - db_data:/var/lib/mysql
  
  django:
    container_name: django
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:  #追記
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db

volumes:  #追記
  db_data:
```

## 参考サイト
[Docker 上で MySQL データを永続化する](https://kiyobl.com/docker-mysql-persistence/)
テーマの指定方法

Flutter Studioの操作方法メモ。
テーマは、画面表示のベースとなるウィジェットで設定します。ここでのサンプルならば、MyApp内で作成されるMaterialAppインスタンスで指定する。テーマは、画面表示のベースとなるウィジェットで設定する。Flutter Studioで、何もウィジェットを配置していない部分をクリックし、背景部分を選択する。右側に「Scaffold properties」と表示がされる。
項目名と場所は次のとおり
- Dark Theme
ダークテーマをON/OFFするもの。通常の表示はOFFに、暗い背景をベースにした表示にしたければONにしておく
- Primary Swatch
テーマの基本的な色を指定する。
- Primary Color
標準のテキストなどの色
- Accent Color
アクセントの色
- Devider Color
仕切り線の色
- Canvas Color
キャンバス（グラフィック描画の部分）の色
- Background Color
背景色として表示を作る際に使われる色
- FontFamily
使用するフォントファミリーの指定

色の値部分をクリックするとカラパレットがプルダウンで表示されます。
【SwiftUI】Viewを透過画像として保存する(iOS16)

# はじめに
https://qiita.com/SNQ-2001/items/0c88b01bf63322fbaa04

昨日、【SwiftUI】Viewを画像として保存する(iOS16)という記事を書きました。
今回は昨日の応用版の記事です

Viewがない場所は透過させます。

# 前提
画像を保存するためにはユーザーからの許可が必要です。
リクエストを表示させるために、以下のキーをInfo.plistにセットします
```
Privacy - Photo Library Usage Description
```

![スクリーンショット 2023-06-30 20.44.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/40db01c7-86ef-f713-af53-44a02ad8b0fd.png)

# 実装
```swift
import SwiftUI

struct ContentView: View {
    @Environment(\.displayScale) private var displayScale
    
    var body: some View {
        VStack(spacing: 50) {
            sampleView()
            
            Button {
                if let image = render(), let data = image.pngData(), let png = UIImage(data: data) {
                    UIImageWriteToSavedPhotosAlbum(png, nil, nil, nil)
                }
            } label: {
                Text("保存")
            }
        }
    }
    
    private func sampleView() -> some View {
        Text("テスト")
            .font(.largeTitle)
            .foregroundColor(.white)
            .frame(width: 400, height: 250)
            .background(Color.green, in: RoundedRectangle(cornerRadius: 10))
    }
    
    @MainActor
    func render() -> UIImage? {
        let renderer = ImageRenderer(content: sampleView())

        renderer.scale = displayScale

        return renderer.uiImage
    }
}
```

# 解説
ここが保存したいViewです。
メソッドとして定義しています。
```swift
private func sampleView() -> some View {
    Text("テスト")
        .font(.largeTitle)
        .foregroundColor(.white)
        .frame(width: 400, height: 250)
        .background(Color.green, in: RoundedRectangle(cornerRadius: 10))
}
```

ここで`sampleView()`をUIImageに変換しています。
```swift
@MainActor
func render() -> UIImage? {
    let renderer = ImageRenderer(content: sampleView())

    renderer.scale = displayScale

    return renderer.uiImage
}
```

ここでUIImageをpngに変換してから端末に保存しています
```swift
if let image = render(), let data = image.pngData(), let png = UIImage(data: data) {
    UIImageWriteToSavedPhotosAlbum(png, nil, nil, nil)
}
```

# おわり
いい感じですねー
【WordPress】get_template_parts()で読み込んだファイルで使うには明示的にglobalで宣言が必要なんだってさ

## はじめに

WordPressのオリジナルテーマ開発をしていて、page.phpやindex.phpといったテンプレートファルではfunction.phpで宣言したグローバル変数使えるのに、 `get_template_parts()` で呼び出しているテンプレートパーツファイル内ではグローバル変数が使えない！という現象に悩まされたので、なんとなくコード書いちゃう仲間に向けて

## 現象が起きるコード

現象が起きる状態はこんな感じ

```php
// function.php

// 前後省略...

$GlobalText = 'テキスト';

// 前後省略...
```

```php
// テンプレートファイル（page.phpとか）

// 前後省略...
echo $GlobalText; // ○ 表示される
// 前後省略...
```

```php
// テンプレートパーツファイル（get_template_parts()で呼び出して使うファイル）

// 前後省略...
echo $GlobalText; // × 表示されない
// 前後省略...
```

## 解決方法

グローバル変数をテンプレートファイルで使えるようにするには次のように呼び出します

```php
// テンプレートパーツファイル（get_template_parts()で呼び出して使うファイル）

// 前後省略...
global $GlobalText
echo $GlobalText;
// 前後省略...
```

PHPをちゃんと学んでいる人からすると「あーね」となる感じがしますね。

グローバル変数は、どの関数からも呼び出すことができますが、関数で使う際はglobalという宣言をする必要があります。それを知っていればなんとなく想像ついたんだろう！

テンプレートファイルとテンプレートパーツで呼び出し方に違いが出た理由は、テンプレートファイルとテンプレートパーツのファイルの読み込み方法の違いに起因しています。

WordPressはテンプレートファイルを読み込む際に、自動的に`functions.php`を読み込み、その中で定義されたグローバル変数や関数が使用可能になります。

テンプレートファイルではWordPressが自動的に`functions.php`を読み込むため、グローバル変数や関数を直接使用できます。

一方、`get_template_part()`で呼び出したテンプレートパーツは個別のファイルとして扱われ、`functions.php`が読み込まれないため`global`キーワードを使って明示的に宣言する必要があります。

## おわりに

言語理解はしてないんだけど調べながらなんとなく動くものは書ける！状態なのでPHPをわかっていればすぐに辿り着けそうな解決方法でした。

```php
// function.php
$GlobalText = 'テキスト'

function sampleFunc2(){
	global $GlobalText2;
	$GlobalText2 = 'テキスト2'
}

function sampleFunc(){
	echo $GlobalText; // 「Undefined variable '$GlobalText'.」というエラーが出る
  echo $GlobalText2 // 同じくエラーが出る
}
```

globalという書き方が存在すること自体はよくわかんないけど知っていました。

globalで書けばグローバル変数になってどこでも使える変数になるという理解。

で、解決のために色々試しているうちに上のコードを書いてみたら自分の理解ではどこでも呼び出せるはずのグローバル変数が未定義と言われる…で、これはglobalの理解がおかしいかもとなって解決のきっかけになりました。
Microsoftの対応が神過ぎた件（Azureの利用料14万円を返金してくれた話）

# はじめに
私が新卒1年目の時、意図しないAzure利用料が発生してしまった際にMicrosoftがとってくれた神対応を紹介します。

なお、本記事は数年前に例外的にとっていただいた対応であり、現在も同じ対応をとっていただけるとは限りませんの。

また、故意に課金を取り消すような行為は犯罪となる恐れがあります。**悪意を持った返金依頼は絶対に行わない**ようにしてください。

## 発生した事象
- Azureの無料枠を使用
- 勉強のため、従量課金サービスである`Azure Database for MySQL General Purpose` をデプロイ **←無料枠を超えると自動で課金される**
- 勉強終了後、`Azure Database for MySQL General Purpose`を削除する**予定だった**が削除を忘れ1か月間放置
- 1か月後、**14万円**の請求書が届く


## Microsoft Azure 課金サポートに謝罪
MicrosoftはAzureの全ユーザに課金サポートというサービスを提供してくれています。まずこちらから、

> Azureの勉強のため無料枠でサービスを利用していたが、リソースを削除するのを忘れてしまい、課金されてしまった。可能であれば返金を検討していただきたい。

というような形で、全力で謝罪しました。
※実際はもっと丁寧な文章で謝罪しています

### サポートへの問い合わせ方法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647774/d2869e88-7a80-7ae2-52fb-cd4414574704.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647774/5f463ef7-7dc0-607f-e76b-2c76abd6fc49.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647774/72b16737-939e-1374-990a-a92f0c325849.png)

## Microsoftからの返信
数日後、Microftからメールで連絡が来ました。
> ご要望いただいておりますご返金などの対応は、弊社では、障害にともなう対応のみご案内が可能でございます。
しかしながら、今回のご請求につきましては、Azureご利用に際し、お客様にて意図しない高額な請求が発生しているとお伺いしております。

> 本件該当請求につきましては、お客様のご事情を考慮させていただき、該当請求の全額のご対応はむずかしい状況ではございますが、弊社返金ポリシーに準じてご利用料金の一部返金ならびに、請求取り消しを以下の内容にておこなわせていただきたく存じますがいかがでしょうか。



・・・・**控えめにいって神過ぎる**・・・・


**約14万円の請求の内、9万円を返金・請求取り消し**していただきました。

## 終わりに
さすが天下のMicrosoftさんです。
当時、新卒1年目、貯金2万円程度だった私の生活費が0円になる危機を救っていただき大変感謝しています。

また、この時の事象は、Azureの無料枠の仕組みを正確に理解せずに利用した利用者側(私)の責任です。これから無料枠の利用を検討している方は、必ず以下2点を実施しましょう
1. **無料枠のサービス内容を正確に理解する**
    参考） [無料の Azure サービス](https://azure.microsoft.com/ja-jp/pricing/free-services)
1. **コストアラートを設定する**
    参考）[Azureの予算アラート（コストアラート）を設定する](https://zenn.dev/tomot/articles/4208151708ce00)
【VSCode】拡張機能を自作する方法

## はじめに
VScodeの拡張機能作成は大きく､

- 自作する ← 【今回】
- 公開する ← 【[次回](https://qiita.com/yusu79/items/44520c4c67864b0bb3e9)】

の2つのプロセスを踏みます｡
今回は､「**作る**」方法を解説します｡

VScodeを作成するには[Yeoman](https://yeoman.io/)というアプリを使います｡
Yeomanとは「使用人」という意味で､Google社が開発したnode.jsのツールです｡

`yo 雛形のジェネレーター`とすることで､あらゆるWEBアプリケーションのベースを自動で作成します｡
当然､VScodeの雛形ジェネレーターも配布されています｡



## インストール
まずはYeomanとVScodeの雛形ジェネレーターを`npm`でインストールします｡

```bash:Windowsでインストールする場合
> npm install -g yo
> npm install -g generator-code
```
```bash:Linuxでインストールする場合
$ sudo npm install -g yo
$ sudo npm install -g generator-code
```


## テンプレート作成
任意のフォルダでターミナルを開き､`yo code`と入力します｡
すると､**7つ**質問されるので､それらに全て答えます｡

- 第一の質問:「どんなタイプの拡張機能を作りたいのか？」
  - 基本的には`TypeScript`か`JavaScript`を選びます｡
- 第二の質問:「拡張機能はどんな名前にするのか？」
  - 拡張機能の名前を入力します｡
- 第三の質問:「拡張機能の識別子はどうする？」
  - デフォルト｡何も入力せず､Enter｡
- 第四の質問:「拡張機能の説明はどうする？」
  - 拡張機能の説明を入力｡
- 第五の質問:「Gitリポジトリは初期化するか？」
  - デフォルトはYesですが､あらかじめGitHubにリポジトリを作成しているならNoにします｡
- 第六の質問:「WEBパックにソースコードを同梱するか？」
  - デフォルト｡何も入力せず､Enter｡
- 第七の質問:「どのパッケージマネージャーを使う？」
  - `npm`がよく使われます｡


```bash:第一の質問「どんなタイプの拡張機能を作りたいのか？」
$ yo code

     _-----_     ╭──────────────────────────╮
    |       |    │   Welcome to the Visual  │
    |--(o)--|    │   Studio Code Extension  │
   `---------´   │        generator!        │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |     
   __'.___.'__   
 ´   `  |° ´ Y ` 

? What type of extension do you want to create?
 (Use arrow keys)
❯ New Extension (TypeScript) 
  New Extension (JavaScript) 
  New Color Theme 
  New Language Support 
  New Code Snippets 
  New Keymap 
  New Extension Pack 
  New Language Pack (Localization) 
  New Web Extension (TypeScript) 
  New Notebook Renderer (TypeScript) 
```
```bash:第二の質問「拡張機能はどんな名前にするのか？」
? What's the name of your extension? 
```
```bash:第三の質問「拡張機能の識別子はどうする？」
? What's the identifier of your extension?  
```
```bash:第四の質問「拡張機能の説明はどうする？」
? What's the description of your extension? 
```
```bash:第五の質問「Gitリポジトリは初期化するか？」
? Initialize a git repository? (Y/n) n
```
```bash:第六の質問「WEBパックにソースコードを同梱するか？」
? Bundle the source code with webpack? (y/N) 
```
```bash:第七の質問「どのパッケージマネージャーを使う？」
? Which package manager to use? (Use arrow 
keys)
❯ npm 
  yarn 
  pnpm 
```

これでテンプレートが作成されます｡



## デバッグしてみる
あとは生成したフォルダで開発していくだけですが､その前にデバッグをしてちゃんと動くか確認します｡

1. VScodeで生成したフォルダを開きます｡
2. 次に､左側の「デバッグビュー」の`Run Extension`をクリックすると､**拡張機能がインストールされた状態のVScodeウィンドゥ**が立ち上がります｡
3. このウィンドゥでコマンドパレットを開いて､デバッグ用に用意された「hello world」を実行します｡

![VScodeの拡張機能の作り方をまとめる_1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395294/7c95330a-086f-c31d-b765-5043f9b05d57.gif)

無事動いたので､あとは`extension.ts`や`extension.js`に記述していけば､VScode拡張機能を作ることができます｡
アメージングQR

# きっかけ

Datamatrix (データマトリックス) を無料で作れるAPIやライブラリないか探していたら、  [EFQRコード](https://github.com/EFPrefix/EFQRCode) に出会い、[アメージング-QR](https://github.com/x-hw/amazing-qr)にインスピレーションを得たと書いてある。じゃあ自分なりのメモを残そうと思った。

会社ロゴとかを中心に置いたQRコードよりインパクトがあっていいなと思った。

## Amazing-QR のAPI日本語訳(非公式)

[サンプル](https://github.com/x-hw/amazing-qr#examples)はここから見れます。

## インストール

```shell
pip install amzqr
```

## 使用方法

### ターミナル

```shell
amzqr Words
      [-v {1,2,3,...,40}]
      [-l {L,M,Q,H}]
      [-n output-filename]
      [-d output-directory]
      [-p picture_file]
      [-c]
      [-con contrast]
      [-bri brightness]

```

#### Words(第一引数)*必須

```shell
amzqr https://github.com
```

カレントディレクトリに qrcode.png が出力され `Words`の部分のデータが書かれたQRコードを得ることができる。

#### -v オプション (サイズオプション)

```shell
amzqr https://github.com -v 10
```

QRコードの大きさを指定することができる。

**最小値 1**
**最大値 40**

#### -l オプション (誤り訂正レベル)

誤り訂正レベル の指定

* `L` 最低レベル(損傷に最も弱い)
* `M`
* `Q`
* `H` 最高レベル(一般的,最も損傷に強い)

#### -n オプション (出力名オプション)

```shell
amzqr https://github.com   -n github_qr.jpg
```

出力名を変更することができる。

拡張子は、 `jpg`,`.png`,`bmp`,`gif` のどれかである。

#### -d オプション (出力ディレクトリオプション)

出力ディレクトリを変更することができる。

```shell
amzqr https://github.com   -n github_qr.jpg   -d .../paths/
```

#### -p オプション (画像埋め込みオプション)

```shell
amzqr https://github.com -p github.jpg
```

カレントディレクトリ の画像を読み込み QRコード結合する。

`-c` を付けない限り白黒出力となる。

##### アニメーション

アニメーション付きのQRコードにするためには、 `.gif` で画像を入力し `-n` オプションを付けて `.gif` で出力しなければならない。

私の経験としては、 PNG画像はあまり使わないほうが良い。理由として背景透過があると、それが台無しになる。背景透過が無ければPNGでもよいと思う。

#### -c オプション (画像カラー化オプション)

`-p` スイッチ の結果をカラーにする。

#### -con オプション (コントラストオプション)

画像のコントラストを変更する。低い数値は低コントラストに対応し、高い数値は高コントラストに対応する。

デフォルト値: 1.0

#### -bri オプション (輝度オプション)

画像の輝度を変更する。
デフォルト値:1.0
ABC306 - A - Echo 自己解法

# 問題
https://atcoder.jp/contests/abc306/tasks/abc306_a

# 考察
与えられた文字列を各文字2個ずつ並べてくださいという問題です。文字列を1文字ずつ取り出し、それぞれ2回ずつ出力していきましょう。1文字ずつ取り出すのを繰り返す処理を書くには`for`文が便利です。

# 提出コード(コンテスト後)

https://atcoder.jp/contests/abc306/submissions/43087106

ご不明点などがあれば教えていただけると幸いです。
WSL2のEmacsからWindows側のブラウザを開く

いろいろあってWindows上にメインの開発環境を構築しています。とはいってもだいたいのものはWSLで動くので楽なものです。ターミナルは最初から入っているWindows Terminalが十分な機能を持っていますし。

Windowsを起動するといきなり全画面のターミナルでDebian GNU/Linuxのシェルが起動しているというのは、なかなかに壮観で20年ほど前のことを思い返すとまさに隔世の感がありますね。GUIのEmacsすら深いことは考えずともGTK付きでビルドすればWSLgで動いてしまいました。

小さな問題はいくつもありましたが、だいたいのことはごにょごにょすれば解決できます。今回Emacsの環境を構築するまでしばらく気にも留めていなかったことですが、GUIのEmacsを使っていてURLをブラウザで開く機会は思いのほか多くありました。

Emacsはこういう場面でもカスタマイズできるようにできています。

## ステップ1

いま自分がWSL2の中に居ることを知ります。

```elisp
(defconst my-system-is-wsl2
  (eval-when-compile
    (getenv "WSL_DISTRO_NAME")))
```

変数名は自分の好きなように、というか変数にしなくてもいいです。好みで。

## ステップ2

URLブラウズ関数を書きます。[なんかぐぐったら](https://superuser.com/questions/36728/can-i-launch-urls-from-command-line-in-windows)Windowsの`start`コマンドをいうやつに渡してやればいいらしい。

```elisp
(defun my-browse-url-wsl-host-browser (url &rest _args)
  "Browse URL with WSL host web browser."
  (prog1 (message "Open %s" url)
    (shell-command-to-string
     (mapconcat #'shell-quote-argument
                (list "cmd.exe" "/c" "start" url)
                " "))))
```

## ステップ3

WSLだったらブラウザ関数を上記のものに設定します。

```elisp
(when (eval-when-compile my-system-is-wsl2)
  (setopt browse-url-browser-function #'my-browse-url-wsl-host-browser))
```

Emacs29では`custom-set-variables`の`setq`っぽく使える`setopt`ができたので使ってきましょ。

## 試しかた

WSLgで動かしてるEmacsの適当なバッファでURLっぽい文字列を書いてカーソルを合わせて`C-x C-f`を押すか、`goto-address-mode`が有効になっていることを確認してクリックしましょう。

## まとめ

WSLは適当にぽちぽちやってるのでも案外使えるのでびっくりしました。
Railsチュートリアル　１章　エラーまとめ

# render へのデプロイができない😰
### 環境
・codespace（クラウドIDE）
・Macbook Air M1
### エラー
・render（本番環境）に何度デプロイしても失敗する。
・エラー表示
⇒「ArgumentError: key must be 16 bytes」、「openssl::cipher::ciphererror:」など・・・
### 原因
・config/master.keyが存在しない。
### 解決方法
【準備】
・credentials.yml.encファイルがある場合は、削除しておく。

① EDITOR="vi" rails credentials:edit を実行すると、エディタが開かれるので、 :wq でそのまま保存して閉じる。
すると、crendcredentials.yml.enc　と master.key が自動で作成される。
※このとき、rendcredentials.yml.enc は作成されるのに、 master.key　は作成されなければ、作成した rendcredentials.yml.enc を一度削除して、 vi master.key でファイルを作成・保存・閉じる。その後、　master.key を削除。これを実行した後に、もう一度①を試してください。私はこの手順で自動作成されました。
② master.key が作成されてたら vi master.key で開いて、中身を確認。後で、render　の　value　にコピーできるようにしておく。
③　commit　⇒　push で　Github に反映。
④ render　の　value　にmaster.key を入力。

これでできました。私はこれを解決するのに５時間かかりました。
Flaskで動的なWebアプリを作成

前回はFlaskの環境構築について説明しました。
今回はFlaskで動的なWebアプリの作成についてまとめました

・前回の記事

https://qiita.com/wooooo/items/195f90b483aaafdf765f

・前々回の記事

https://qiita.com/wooooo/items/e9f96c10f870c5124d8b

# テンプレート使用
flaskのrender_templateを使ってテンプレートを使用できます
```python:index.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    title = 'demo'
    return render_template('index.html', title=title)
```

ルートパス'/'にアクセスすると、リクエストを受け付け、
index()が呼び出されて'index.html'のテンプレートのレスポンスが返されます

このレスポンスを画面に表示させるためにtemplateが必要です。
templateディレクトリを作成します
```
mkdir template
```

templateディレクトリに移動し、index.htmlファイルを作成します
```
cd template
touch index.html
```

```html:index.html
<!DOCTYPE html>
<html>
<head>
    <title>demo site</title>
</head>
<body>
    <h1>{{ title }}</h1>
</body>
</html>
```

実行します
```
flask run --app index
```
このコードで画面上に「demo」という文字が出力されます

index.pyでrender_template()のパラメータで渡した'title'の値を
index.htmlの{{ title }}に渡しています

render_template()のパラメータを増やすことが可能です
```python:index2.py
(省略)
@app.route('/')
def index():
    title = 'demo'
    message = 'Hello World'
    return render_template('index.html', title=title, message=message)
```

```html:index2.html
<!DOCTYPE html>
<html>
<head>
    <title>demo site</title>
</head>
<body>
    <h1>{{ title }}</h1>
    <br>
    <h1>{{ message }}</h1>
</body>
</html>
```

こうすると画面上に「demo」という文字の下に「Hello World」という文字が出力されます

# ルーティング
GET、POST、PUT、DELETEの4つのHTTPメソッドに対応するルーティングのリクエスト処理をFlaskで実装してみます

Flaskでルート'/*'を設定するにはroute()というデコレータを使用します
こうすることで、URLのパスやHTTPメソッドに応じて異なる処理を実行することができます
ユーザーがGETメソッドで特定のURLにアクセスした場合は、GETメソッドに対応する関数が呼び出されます。同様に、POSTメソッドやPUTメソッド、DELETEメソッドなどのHTTPメソッドに対応する関数を設定することもできます

例としてGETメソッドを作成してみます

```python:get.py
from flask import Flask, request

app = Flask(__name__)

@app.route('/get', methods=['GET'])
def get_data():
    return 'GET Request'

if __name__ == '__main__':
    app.run()
```

GETリクエストを受け取ると、get_data()が呼び出され'GET Request'という文字列が返されます

```python:put.py
from flask import Flask, request

app = Flask(__name__)

@app.route('/put/user_id', methods=['PUT'])
def put_user(user_id):
    data = request.get_json()
    user = data['user'][user_id]
    ...
    # update
    ...
    return {200, f'{user[user_name]} update success'}

if __name__ == '__main__':
    app.run()
 ```
これはPUTリクエストを受け取ると、put_user()が呼び出され、対象のuser_idのユーザ情報を更新した後に、レスポンスでステータス200と更新完了のメッセージを返しています

このようにルーティングにより様々なリクエストを処理することができ、ユーザがアクセスするURLに応じてFlaskが様々な方法でデータを処理することができます
iOSのNewsアプリを日本で見る方法

# まず
皆さんは"Apple純正"のNewsというアプリをご存じですか？
地域設定をアメリカにしてないとみることができないので知っている人は少ないんじゃないかと思います。
日本でもNewsが見たい!!!!!ということで、アプリを表示する方法をまとめました。
# 準備するもの
脱獄されたデバイス(脱獄は自己責任で!!)
Filza File Manager
# Tweakを使ったNewsの表示
「NewsOfTheWorld」というTweakをダウンロードして、再起動...
あれ？表示されない...!?
筆者の環境が悪いのでしょうか...表示されませんでした。
# Filzaを使用して無理やり表示
①まず、Filzaを開いて、rootフォルダ(左上が押せなくなるまで)に行きます。
ここから、/Applications/News.app/MCRestrictions.plistを開きます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490143/92b6a9e4-5443-0d80-95b1-038445f93ad5.jpeg" width="50%">
②そして、MCWhite~の右のほうにある🛈(矢印)を押し、
矢印のAdd item...を押します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490143/6efb9a89-a9ae-a37f-833a-de927c3aa0d7.jpeg" width="50%">
③その次は新しくできたNew stringを押して、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490143/0e2d279e-a4a4-027c-808b-8e6d1805ee6e.jpeg" width="50%">
④そして、値というテキストボックスを押して、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490143/075db0f5-fe4c-5b0b-f9a7-e456a24ac726.jpeg" width="50%">
⑤New stringをJPに変更します。
(多分このJPを買えたらほかの地域でも見れるかも?)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490143/c197bc01-6403-76dc-53c7-5eac3ca700ad.jpeg" width="50%">
⑥そして、左上を何回か押して「すべての変更を保存しますか？」と表示されたら「はい」を押します。
# おつかれさまでした
再起動(Respringではない)して、表示されたら完了です!!
このNewsというアプリ、もちろん英語です!!!(イキれるね!!!!!!!)
# おまけ(考察)
⑤で[JP]という値にしましたが、[ja]だと駄目だったんで、
言語などの[ja-JP]や[en_US]の大文字側なのでしょうね。
GoogleColab×DataScience


本記事では、GoogleColab上で、データサイエンス(分析, 可視化)に取り組む際の参照コードを集めています。



## GitHub
- Publicリポジトリの場合
    ```
    !git clone [gitのHTTPS]
    ```
- Privateリポジトリの場合
    ```
    %env TOKEN=[アクセストークン]
    !git clone https://$$TOKEN@github.com/[アカウント名]/[リポジトリ名].git
    ```
    参考LINK:
https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token

## DataFrame×JSONL
- JSONLファイルをDataFrameへ読み込む
  ```python
    df = pd.read_json('readfile.jsonl', orient='records', lines=True)
    df.head()
   ```
- DataFrameをJSONLファイルへ書き込む
  ```python
    df.to_json('writefile.jsonl', orient='records', lines=True, force_ascii=False)
  ```

## DataFrame×GoogleSpreadseets
- GoogleSpreadseetsをDataFrameへ読み込む
    ```python
    #spreadsheets認証
    from google.colab import auth
    auth.authenticate_user()
    
    import gspread
    from google.auth import default
    creds, _ = default()
    
    gc = gspread.authorize(creds)
    
    #spreadsheets-URL
    url = "[URL]"
    ss = gc.open_by_url(url)
    
    #spreadsheet指定
    st = ss.get_worksheet(0)
    
    #データフレーム化
    import pandas as pd
    df = pd.DataFrame(st.get_all_values())
    df.columns = list(df.loc[0, :])
    df.drop(0, inplace=True)
    df.reset_index(inplace=True)
    df.drop('index', axis=1, inplace=True)
    
    df.head()
    ```

## Download
```py
!zip -r dirname.zip dirname
from google.colab import files
files.download('dirname.zip')
```