OmniAICreator/Qiita-1.07M huggingface dataset:
GPUメモリ8GBでStable Diffusionを動かす

# 概要

GPUが8GBのマシンでStable Diffusionなモデルを動かした記録．
Windows10, Python3.9.13, CUDA11.2, Torch1.8.1+cu111です．

# 動かしたもの

waifu-diffusion v1.4 - Diffusion for Weebs　の最小モデル．

https://huggingface.co/hakurei/waifu-diffusion

https://huggingface.co/hakurei/waifu-diffusion-v1-3/blob/main/wd-v1-3-float16.ckpt

# 結果
・入力　"1girl, simple background, open mouth, cute girl, blond hair, blue eye, upper body."
・出力1 生成時間は20-30秒
![22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242971/7a1ca572-4671-77dd-e64d-b980fa6108b1.png)
・出力2
![test0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242971/5ddc796f-6d8a-7168-8b11-15644b6579aa.png)

・入力　"1girl, simple background, close mouth, red hair, black eye, upper body."
・出力1
![33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242971/05b87d6f-6fd5-1f8a-33a1-bec59c6016ff.png)
・出力2
![44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242971/1cf680f5-fb28-4f69-7485-64ecc270a0f0.png)

# コード

https://huggingface.co/hakurei/waifu-diffusion

のExample Codeの修正．そのままではエラーとメモリ不足で動かなかったため
+ 一部の書き換え
+ 最も軽量なモデルの利用．リンク先Open in Colab参照．

```python
import torch
from torch.cuda.amp import autocast
from diffusers import StableDiffusionPipeline

pipe = StableDiffusionPipeline.from_pretrained(
    'hakurei/waifu-diffusion',
    torch_dtype=torch.float16,
    revision='fp16'
).to('cuda')

prompt = "1girl, simple background, blue hair, blue eye, upper body."
num_samples = 1 # 一度に出力される画像の数
with autocast(True):
    image = pipe([prompt] * num_samples, guidance_scale=7.5)["images"]

# pipe()の出力
# StableDiffusionPipelineOutput(images=[<PIL.Image.Image image mode=RGB size=512x512 at 0x20C34C33FA0>])

image[0].save("test0.png")
```

## 以下，細かいこと

### エラー1：cannot import name 'autocast' from 'torch'
リンク先のように書き換えればいい．

https://github.com/pesser/stable-diffusion/issues/14

### エラー2：cannot import name 'CLIPImageProcessor' from 'transformers' 
既存の環境が原因らしい．仮想環境に入れ直せとのこと．

https://ja.stackoverflow.com/questions/75443/transformers%E3%81%8B%E3%82%89tfgpt2lmheadmodel%E3%82%92%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84-cannot-import-name-tfgpt2lmheadmodel

### Pythonの仮想環境

https://www.python.jp/install/windows/venv.html

VSCodeがデフォルトでターミナルにPowerSellを使うのでコマンドプロンプトに変更．PowerShellのままだとactivate.batが機能しない．

https://note.affi-sapo-sv.com/vscode-use-cmdprompt.php

### 仮想環境にPytorchインストール

https://pytorch.org/get-started/previous-versions/

本マシンではRTX3070TiとCUDA 11.2を用いているため，上を参考に
```bat
# CUDA 11.1
pip install torch==1.10.1+cu111 torchvision==0.11.2+cu111 torchaudio==0.10.1 -f https://download.pytorch.org/whl/cu111/torch_stable.html
```
CUDAのバージョンが異なるがいいらしい．

https://discuss.pytorch.org/t/want-to-install-pytorch-for-custom-cuda-version-cuda-11-2/141159

### guidance_scale=について

リンク先が詳しい．見た方が早い．

https://harusdia.hatenablog.com/entry/2023/03/05/234202
オブザーバビリティ（可観測性）について

# 1 オブザーバビリティ（可観測性）
Observe （観察する）+ ability （能力）
システムやアプリケーションの状態や挙動を監視、分析し、理解する能力


# 2 オブザーバビリティ（可観測性）３つの観点
3種類のテレメトリデータ
## 2-1. ロギング（Logging）:
システムやアプリケーションが生成するログデータを収集し、分析することで、問題発生時に原因を特定しやすくします。

## 2-2. モニタリング（Monitoring）: 
システムやアプリケーションのパフォーマンス指標やリソース使用状況を監視し、異常が発生した場合に通知を行うことで、問題を早期に検出・対処できるようにします。

## 2-3. トレーシング（Tracing）: 
リクエストや処理の流れを追跡することで、システム全体の挙動や相互作用を把握し、パフォーマンスやエラーの原因を特定できるようにします。

# 3　従来のモニタリング(監視)とオブザーバビリティの違い

- モニタリング
    「システム単体ごとに異常があるかどうかずっとみている」
- オブザーバビリティ
    「既存のシステム全体を常に観測、可視化できており原因特定までできる状態」

**モニタリングはオブザーバビリティの要素の一つ**

CPUやメモリなどメトリクスの閾値超過だけをモニタリング(監視)すれば良いという考え方ではなく。

システムのアキレス腱となる、メトリクスやログを可視化ダッシュボードで経時的に見ていく。
システムの可視性を高める事が、オブザーバビリティという考え方

## 日常に落とし込んで、モニタリング(監視)とオブザーバビリティの違いを考えてみる。
### 【従来のモニタリング(監視)を、医療に置き換える】
病院） Aさん最近お元気ですか？
↓
Aさん） はい元気です！
↓
Aさん） 年に一回健康診断受けてA判定だし大丈夫だろ
↓
Aさん） 最近飲みすぎだな
↓
Aさん） 最近忙しいな
↓
Aさん） 最近寝れていないな
↓
【Aさん倒れる】
↓
病院) Aさんが倒れたって！大丈夫?
↓
【治療】
↓
x回繰り返し

### 【オブザーバビリティを、医療に置き換える】
病院） Aさん最近お元気ですか？
↓
Aさん） はい元気です！
↓
Aさん） 年に一回健康診断受けてA判定だし大丈夫だろ
↓
病院） Aさん！AppleWatch持っておられますよね！それでヘルスケア情報を病院に送ってくださいね毎日
↓
Aさん） はい
↓
Aさん） 最近飲みすぎで運動もしてないな
↓
病院） あれAさん最近活動量少ないな
↓
Aさん） 最近忙しいな
↓
病院）　あれAさん最近脈拍早いな
↓
Aさん） 最近寝れていないな
↓
病院）　あれAさん最近睡眠時間も短いし、ヤバそうだな。訪問しよう！
↓
Aさん倒れる前に、発見できる！
↓
【治療】
↓
x回繰り返し

これがオブザーバビリティが実現できるという事かなと思います。

つまり医療であってもシステムであっても、監視する側が**能動的な体制**でいる事
またそれらを発見できるようにメトリクス、ログ、トレースを常に収集し見れるように可視性を高めることも重要→ダッシュボード化

# 4 もともとの監視設計も大事
## 適切なモニタリングをしよう
例えばこんな背景があった場合：
・開発環境でEC2を動作させている
・費用削減のため、T系インスタンスを使いたいので採用
・でもリソース超過するのであればC系に切り替える事も考慮にある

※T系とは100%のCPUリソースを超過した性能を発揮できるバーストが可能。
しかし、バーストできる量には制限がある。これをバーストクレジットという形で消費される。

### 【問題のある監視設計】
CPUが高いのでアラート発報→サービスURL閲覧→OK→問題なし！（x繰り返し)
このモニタリングでは原因にたどり着けない＋**意味のないアラートが多発してしまう。**

### 【適切な監視設計】

CPUが高いけどアラート発報させない→バーストクレジット0を監視→0に近くなったらアラート発報→クレジットないからタイプ変更しよう

**これだと意味のあるアラート発報が可能。**


## 可視化ツールの選定
ダッシュボードで一元管理する方法が情報も多く構築しやすそう。
Grafana,Datadog,Newrelic...etc

# オブザーバビリティを高めるために、まずやる事
・既存システムの概要を把握する

・既存システムのアキレス腱となる、メトリクスやログ取得タイミングの把握する
    **これらはダッシュボードなどペライチで見れる可視性が必要**

・既存システムの満足度調査→実際に使用されているツールにオブザーバビリティを導入するべき。使用されていないツールは優先度を下げるとか?

## 参照：

https://newrelic.com/sites/default/files/2022-03/ModernizingWithAWSReplatforming_WhitePaper_jaJP.pdf

https://www.youtube.com/watch?v=QCNqJNXxwmk
【エラー】SourceTreeで「git applyがコード1で終了しました」と出たときの直し方

## 不具合現象

SourceTreeのファイルステータスで、
作業ツリーのファイルを、Indexにステージしたファイルに追加しようとした時に標題のエラーが発生。  

Diffから「Hunkをステージへ移動」ボタンを押した時と、  
行(ハンク)を選択して「選択した行をステージへ移動」にした時のみ不具合が発生しました。  

ファイルを選択して、「選択をインデックスに追加」を押してもエラーにはなりません。
また、「全てインデックスに追加」を押してもエラーにはならなかったです。  

## 解決方法

Diffが表示されている画面の右上の歯車から、
「空白文字を無視」を「空白文字を表示」に切り替えることでステージ出来る様になりました。  
（元が「空白文字を表示」の場合は逆にしても問題ないかもしれません。）

![2023-04-26_17h28_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1718976/4327070f-8ba8-3d57-0b2a-2d4ce3607d52.png)


細かい原因は不明ですが、おそらく文字コードが関連した不具合だと思います。  
改行コードが混在している場合に起こる気がします。  

gitは改行コードの差分まで判別しますが、SourceTreeはしないので、  
SourceTreeには改行コードの変更まではDiffには表示されないようになっています。  
そこらへんが影響してそうです。参考までに。
【ServiceNow】ダッシュボードのデータを更新セットに格納する方法

ServiceNow ベストプラクティスでは更新セットを用いて Production 環境へ移送することになります。

通常更新セットに含めるためには更新セットピッカーを指定するだけで OK です。
ただ、一部の機能は更新セットに含めるうえで特殊な手順を行う必要があります。

ダッシュボードを作成する際、元となるレポートは自動で更新セットに格納されますが、ダッシュボードは格納されません。

そのため、ダッシュボードは本番環境で作成することになってしまいますが、手動で更新セットに格納してしまえば、レポートと一緒に本番環境に移送することが可能です。

本記事では、ダッシュボードのデータを更新セットに格納する方法をご紹介します。

操作方法
---
１．データを格納する更新セットを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/fa42ca23-1a55-3b47-0f84-b5c682b07800.png)

２．ダッシュボードを開き、ハンバーガーメニューから「Launch Dependency Assessment」をクリックします。
（「Dashboard Properties」でも良いです。その場合、４の画面に遷移します。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/3b92c5e2-c312-3997-94ac-d0856e1173de.png)
３．ｉマークのボタンから、「Open Record」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/d9634890-3d64-41ea-c9c8-e689ce51bd74.png)
４．ハンバーガーメニューから「Unload Dashboard」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/f79910dd-2368-a5a8-65a4-5cc47212cb6c.png)
更新セットへの格納が完了すると、その旨が青いバーで表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/1a274db5-ff89-f518-706d-4489e9f3f38d.png)

以上で、更新セットへの格納は完了です。

補足
---
更新セットに自動で格納されるデータとされないデータの一覧は以下です。
（参考：Tokyo バージョン CSA のテキスト）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335478/6dee6408-0903-0c92-acde-b3192d8853e2.png)

おわりに
---
本記事では、ダッシュボードのデータを更新セットに手動で格納する方法についてご紹介しました。

ダッシュボードは作成が簡単なので本番環境にリリースした後に作成するのでも十分ですが、開発環境で作成したものをそのままリリースしたい！という場合には、更新セットに入れて持っていくのが楽だと思います。

是非ご活用ください。
WSL でも簡単に open (Windows の規定のアプリで開く) したい

## 概要

WSL 上の特定のファイルを Windows の規定のアプリで開きたいという内容です。同じことをしている記事は他にもありましたが Powershell を使って簡単に規定のアプリで実行する方法を書いているところがあまりなかったので書きました。

## スクリプト

スクリプト全体です。

```bash
function open_in_windows() {
    path=$(wslpath -aw $1 | sed -e 's/ /\ /')
    "/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe" -Command "& {Invoke-Item $path}"
}

if [ $# -lt 1 ]; then
    open_in_windows "$(pwd)"
else
    for path in "$@"; do
        if [ -e "$path" ]; then
            open_in_windows "$path"
        else
            echo "file or directory $path does not exist."
        fi
    done
fi
```

### open_in_windows 関数

特定のパスを Windows の規定のアプリで開く関数です。以下の動作をしています。

1. WSL 上でのパスを Windows 上でのパスに変換する
2. powershell.exe を呼び出し `Invoke-Item` コマンドレットでパスに対し規定のアクションを実行する

powershell.exe はコマンドライン引数で `-Command` オプションを指定し、先頭に `&` をつけてコードブロックを文字列として渡すとそのコマンドを実行してくれます ([ドキュメント](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_powershell_exe?view=powershell-5.1#-command)) 。また、Powershell の [`Invoke-Item` コマンドレット](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.management/invoke-item?view=powershell-7.3)はパスに対して規定のアクションを実行します。

### その他の部分

引数がある場合そのパスの存在を検証してから `open_in_windows` 関数を呼び出します。引数がない場合は `.` が指定されたものとしてカレントディレクトリを開きます。
Rubyの特異メソッドについて

## 環境
Ubuntu 20.4
Ruby 2.6

## はじめに
Rubyには特異メソッドといったものがあります。特異メソッドとは、クラスの内部ではない場所に独立したメソッドを書き、あたかも、そのクラスの内部に実在しているかのように扱うメソッドのことです。また、拡張的な使い方として、superメソッドを使うことで、クラスの内部に実在するメソッドに対し、機能を追加することもできます。

自身の経験上、特異メソッドを使わざるを得ない状況に陥ったことは、一度もありません。殆ど、個人でしか開発を行った経験がないため、自分で作ったクラスにメソッドを追加したい場合は、実際に、クラスに追加すれば済むためだけの話だからです。

勉強のためだけの目的でむりやり特異メソッドを使って、メソッドを追加してもいいのだが、後々の可読性、メンテナンス性のことを考えると、あまりしたくはありません。他人が見たとき、「ん？、この人は、何がやりたいのだろう？」となってしまう可能性が非常に高いです。

恐らくではあるが、特異メソッドを使うケースとして、他人が作成したクラスに対し、「このクラスにメソッドを追加したい！」といった衝動に駆られるが、安易にカスタマイズができない事情がある場合は、特異メソッドを使って追加することになるかと思います。

そもそもメソッドは、クラスを作った人のルールに従って、ルール通りの使い方をするのではなく、自由に使っていいんだよというメッセージが、特異メソッドにはあるのかも知れません。自由である反面、やたら多用すると、それはそれで辟易しそうな気がするので、他人には使って欲しくない機能ではあります。あくまでも個人的な感想です。

## 動作確認
特異メソッドの動きについて動作確認をしてみました。

Testクラスにtest1メソッドがあります。test2メソッドは含まれていません。しかし、Testクラスをインスタンス化して作ったts変数に、test2メソッドを含めることができます。test2メソッドが独立して動いているのはなく、ts変数のメソッドとして動作しているのです。これが特異メソッドです。
```test.rb
class Test
    def test1
        puts "OK1"
    end
end

ts = Test.new
ts.test1

def ts.test2
    puts "OK2"
end

ts.test2
```

動作結果です。
```
OK1
OK2
```

ts.test2の代わりに、 Test.new.test2としてみました。こういう書き方もできるだろうかと思って書いてみたが、この書き方はできません。エラーになります。
```test.rb
def Test.new.test2
    puts "OK2"
end
```

## superの使い方
Testクラスの中にあるメソッドと同じ名前のメソッドを、特異メソッドとして記述することもできます。そうすれば、既存のメソッドが上書きされます。
```test.rb
class Test
    def test1
        puts "OK1"
    end
end

ts = Test.new
ts.test1

def ts.test1
    puts "OK2"
end

ts.test1
```

動作結果です。
```
OK1
OK2
```

特異メソッド内にsuperを１行追加すると、superの個所で、Testクラスのtest1メソッドが呼び出されます。
```test.rb
class Test
    def test1
        puts "OK1"
    end
end

ts = Test.new
ts.test1

def ts.test1
    super
    puts "OK2"
end

ts.test1
```

動作結果です。
```
OK1
OK1
OK2
```

superの位置を変えると、Testクラスのtestメソッドが呼び出されるタイミングも変わります。Testクラスのtest1メソッドが実行されて、その後に、特異メソッドであるtest1メソッドが実行されるといった流れとなります。

```test.rb
class Test
    def test1
        puts "OK1"
    end
end

ts = Test.new
ts.test1

def ts.test1
    puts "OK2"
    super
end

ts.test1
```

動作結果です。
```
OK1
OK2
OK1
```
PostgreSQLでデータベースを作ってテーブルにデータを入れて取得してみた

# 概要
今日はデータベースの勉強ということで、PostgreSQLで遊んでみました。
インストールして、データベースを作って、テーブルを作って、データを入れて、取得するところまでやってみました。
以下のページを参考にしました。
https://www.javadrive.jp/postgresql/

# 環境構築
以下のコマンドを実行しました。
```
$ sudo apt install postresql
```

# postgresでログイン
以下のコマンドを実行しました。
```
$ sudo su postgres -c 'psql --username=postgres'
```
これでpostgresとしてログインできるので、ユーザーを作りました。user2という名前です。create userを実行しました。
```
postgres=# CREATE USER user2 WITH PASSWORD '********';
CREATE ROLE
```
続いてデータベースを作りました。create databaseを実行しました。
```
postgres=# CREATE DATABASE mydb;
CREATE DATABASE
```
下準備はできました。

# user2でログイン
別端末から以下のコマンドを実行しました。さきほど作ったmydbにuser2でアクセスしています。
```
$ psql -U user2 -h localhost -d mydb
```
テーブルmybookを作成しました。create tableを実行しました。
```
mydb=> create table mybook (
  id integer, 
  name varchar(10)
);
CREATE TABLE
```
データを投入しました。insert文を実行しました。
```
mydb=> insert into mybook values (11, 'hoge');
INSERT 0 1
```
データが入ったことを確認しました。select文を実行しました。
```
mydb=> select id, name from mybook;
 id | name 
----+------
 11 | hoge
(1 row)
```

何かの役に立てばと。
AIのための数学講座を受講した

AIのための数学講座を受講した

https://www.udemy.com/course/math-for-ai/

## 動機・感想
前回読んだ推薦入門での推薦アルゴリズムを実践するための基礎数学力が足りてないなと思ったため。
本買ってきて手計算で頑張るのは挫折しそうだったので、UdemyでPython使いながら学べるコースを探した。
5時間ほどのコースなので、各分野への説明はかなり省略されておりほとんど公式の羅列に近かったが、わからない部分や証明に関してChatGPT-4に聞いたり、練習問題を出してもらったりしながら進めることで終えることができた。
動画　+ Jupyter Notebok(Python) + ChatGPT + Latexによってかなり学習のハードルが下がっていると感じた。
一方で推薦アルゴリズムのための数学ではないので、ある程度行列や確率、微分の基礎をおさえられたが、追加で落下傘式に学習する必要がありそう。

以下は線形変換でベクトルに行列をかける、というのがよくわからなかったのでChatGPTに聞いたときの例:

線形変換について
________

Human: 線形変換よく分からなかったので教えて
ChatGPT: 線形変換とは、ベクトル空間において一つの空間から別の空間への変換を表す概念です。線形変換は、以下の二つの性質を満たします。加法の保存: T(u + v) = T(u) + T(v) 、任意のベクトル u, v に対して成り立つ。スカラー倍の保存: T(cv) = cT(v) 、任意のスカラー c とベクトル v に対して成り立つ。ここで、T は線形変換を表す関数、u と v はベクトル、c はスカラーです。線形変換の一般的な例としては、ベクトルのスケーリング（拡大・縮小）、回転、鏡映などが挙げられます。線形変換は、行列を使って表現することができます。線形変換 T が与えられたとき、T を適用することは、行列 A をベクトル x に掛けることと同じです。すなわち、T(x) = Ax です。この行列 A を、線形変換の表現行列と呼びます。線形変換は、幾何学、物理学、画像処理、機械学習などの分野で広く応用されています。例えば、画像の回転やリサイズ、座標系の変換、線形方程式の解法など、多くの問題が線形変換を用いて解決されます。

Human: 行列Aをベクトルxにかける、ってどういうこと？
ChatGPT: 行列Aをベクトルxにかけるというのは、行列とベクトルの積を計算することを意味します。これは、行列Aの各行とベクトルxの各要素を掛け算し、それらの和を新しいベクトルの各要素とする操作です。具体的には以下の手順で計算されます。行列Aの行数とベクトルxの要素数が一致していることを確認します。行列Aがm行n列で、ベクトルxがn要素であることが必要です。一致していない場合、積を計算することはできません。積の結果となる新しいベクトルを作成します。このベクトルは、行列Aの行数（m）と同じ要素数を持ちます。行列Aの各行とベクトルxの各要素を掛け算し、それらの和を新しいベクトルの対応する要素に設定します。具体的には、新しいベクトルの第i要素は、行列Aの第i行とベクトルxの要素ごとの積の総和になります。例として、以下の行列Aとベクトルxを考えます。codeA = | 2  3 |    x = | 4 |
    | 1  2 |        | 5 |
行列Aとベクトルxの積は次のように計算されます。| 2*4 + 3*5 |   | 23 |
| 1*4 + 2*5 | = | 14 |
結果として得られるベクトルは、| 23 | と | 14 | です。この操作は、線形変換で言うところの T(x) = Ax を計算していることに相当します。

Human: 行列をベクトルに変換するのが線形変換ってこと？
ChatGPT: いいえ、線形変換とは、行列をベクトルに変換することではありません。線形変換は、あるベクトル空間から別のベクトル空間への変換を表す概念であり、その変換を行列とベクトルの積を使って表現することができます。線形変換は、あるベクトルxを別のベクトルyに変換する関数Tを指します。この関数Tは、加法の保存とスカラー倍の保存という2つの性質を満たします。線形変換Tを行列Aを使って表現することができます。このとき、線形変換Tは、ベクトルxに行列Aを掛ける操作と等価になります。すなわち、T(x) = Ax です。線形変換は、ベクトルを別のベクトルに変換することを意味しますが、行列そのものをベクトルに変換するわけではありません。線形変換は、ベクトルの拡大・縮小、回転、鏡映など、幾何学的な変換を表すことができます。また、線形変換は、幾何学、物理学、画像処理、機械学習などの分野で広く応用されています。

Human: ベクトルをベクトルに変換するってこと？
ChatGPT: はい、その通りです。線形変換は、あるベクトルを別のベクトルに変換する概念です。線形変換は、関数Tとして表現され、以下の二つの性質を満たします。加法の保存: T(u + v) = T(u) + T(v) 、任意のベクトル u,
Human: ベクトルを別のベクトルに変換するときになぜ行列が出てくるの？
ChatGPT: ベクトルを別のベクトルに変換するときに行列が出てくる理由は、行列が線形変換を簡潔に表現し、計算しやすい形式を提供するからです。行列は線形変換の性質を保持し、ベクトル空間の基底に沿った変換を効率的に表現できます。行列を使って線形変換を表現する場合、行列の各列は、変換後の空間における元の空間の基底ベクトルの座標を表します。つまり、行列によって線形変換がどのように働くかが明確になります。行列とベクトルの積を計算することで、ベクトルを別のベクトルに変換できます。この計算は、行列の各行とベクトルの要素を掛け合わせて合計することで行われ、新しいベクトルが生成されます。この操作は、線形変換における加法の保存とスカラー倍の保存の性質を維持します。行列を用いることで、線形変換の計算が効率的に行えるだけでなく、線形代数の概念や手法を線形変換に適用できるようになります。これにより、幅広い問題を解決できるようになります。例えば、連立方程式の解法、固有値と固有ベクトルの計算、行列の分解などが線形変換を扱う際に役立ちます。
話題のAIをまとめてみた

# [ChatGPT](https://chat.openai.com/)
ChatGPTは、OpenAIが開発した大規模言語モデルの1つで、GPT-3.5アーキテクチャに基づいています。ChatGPTは、自然言語の生成、理解、および対話に特化して訓練されたAIです。ChatGPTは、テキストベースの対話システムとして使用され、人工知能による自然な対話を実現することができます。

# [ChatPDF](https://www.chatpdf.com/)
ChatPDFでは、PDFファイル内のテキストを読み取り、それに基づいてユーザーが質問をすることができます。例えば、技術書のPDFファイルをアップロードした場合、ChatPDFを使用してその技術書の内容に関する質問をすることができます。

追加したほうがいいAIサイトがあればコメント送ってください。
[Flutter] 5分以内でアプリのアイコンの実装をしよう

　  
　   
<b>この記事を開いてから、5分以内にアプリのアイコンを実装してみましょう。</b>
この記事の趣旨としては簡単に、手早くアイコンを実装するやり方を記載しているので、詳細な設定は調べてみてください。
　
　

# １、画像を探す
ここは探そうとしたり、作ったりすると無限に時間がかかるので、時間は含めないようにします。僕は商標OKな画像を探して、Figmaで編集をしています。だいたい、20分〜30分ぐらいで完成しきります。



# ２、アイコンをファイルの中に入れよう

```
assets
 - images
   - icon
     - icon.png
```

# ３、pubspec.yamlに追加しよう

```yaml:pubspec.yaml
dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0
  #追加する
  flutter_launcher_icons: ^0.11.0

#追加する
flutter_icons:
  android: true
  ios: true
  remove_alpha_ios: true
  image_path: "assets/icon/icon.png"
  min_sdk_android: 21
  adaptive_icon_background: '#FFF422'
  adaptive_icon_foreground: "assets/icon/icon.png"

```

４、コマンドで生成する

```terminal
flutter pub run flutter_launcher_icons
```


### これで終わり!!!

　




以上です。僕の場合はアプリを47個出しているので、提出周りやアイコン作成はRTAみたいな感じで素早くやることが多いです。ぜひ試してください。アイコンのズレなどは公式のPackageを探して修正するともっと良くなります！
cocoapodのライブラリの中にjsonなどのResourceを含める

ライブラリの中にjsonファイルを含める方法がわからず苦労したのでメモ。

# podspec編集
podspecに含めるリソースの定義を追加します。これをせずにXcodeで直接ファイルを追加してもExampleアプリのpod installで消えてしまうので注意。
今回の例では `Resources/*.json` をbundleに含めます。

```:mylib.podspec
   s.resource_bundles = {
     'mylib' => ['mylib/Resources/*.json']
   }
```

podspecの編集が終わったら、Exampleアプリで`pod install`します。

# リソースの使い方
mylibライブラリ内で追加したリソースを参照するには以下のようにします。
この例では `hoge.json` のURLを取得しています。

```swift
let myBundle = Bundle(for: Self.self)
guard let resourceBundleURL = myBundle.url(forResource: "mylib", withExtension: "bundle") else {
    fatalError("mylib.bundle not found!")
}

// Create a bundle object for the bundle found at that URL.
guard let resourceBundle = Bundle(url: resourceBundleURL)
else { fatalError("Cannot access mylib.bundle!") }

guard let url = resourceBundle.url(forResource: "hoge", withExtension: "json") else {
    fatalError("Cannot access mylib.bundle!")
    
}
print(url)
```


# 参考
https://stackoverflow.com/questions/50625036/use-resource-bundles-in-cocoapods
【SQLAlchemy】SQLAlchemy のモデルの型ヒント ( Type Annotation ) を理解する

# TL;DR
```py
from sqlalchemy import DateTime, Column, func
from sqlalchemy.orm import Mapped, declarative_base

Base = declarative_base()


class ModelName1(Base):
    created_at: Mapped[datetime.datetime] = Column(
        DateTime,
        default=func.now(),
        nullable=False
    )
```

のように、`Mapped[<マップされる型>]` とすればよい。

# きっかけ
本記事では、SQLAlchemy を使用したモデルに与える、正しい型ヒントを紹介する。

SQLAlchemy を利用しての開発中に、SQLAlchemy の型ヒントがうまく与えられていないことがわかった。

試しに、`column_name: Column = Column()` とするとマイグレーション時に以下のような例外が送出される。

```
sqlalchemy.exc.ArgumentError: Type annotation for "ModelName.uid" can't be
correctly interpreted for Annotated Declarative Table form.
ORM annotations should normally make use of the ``Mapped[]`` generic type,
or other ORM-compatible generic type, as a container for the actual type,
which indicates the intent that the attribute is mapped.
Class variables that are not intended to be mapped by the ORM should use ClassVar[].
To allow Annotated Declarative to disregard legacy annotations which don't
use Mapped[] to pass, set "__allow_unmapped__ = True" on the class or a
superclass this class. (Background on this error at: https://sqlalche.me/e/20/zlpr)
```

これを翻訳すると、以下のようになる。

```
sqlalchemy.exc.ArgumentError: "ModelName.uid"の型ヒントは、 Annotated Declarative Table 形式に対して正しく解釈できません。
通常、ORMアノテーションは、実際の型のコンテナとしてMapped[]ジェネリック型、
または他のORM互換のジェネリック型を使用する必要があり、属性がマッピングされることを示します。
ORMによってマッピングされることを意図していないクラス変数は、ClassVar[]を使用してください。
Annotated DeclarativeがMapped[]を使用しないレガシーアノテーションを無視するようにするには、
クラスまたはそのクラスのスーパークラスに"allow_unmapped = True"を設定してください。 (このエラーの背景: https://sqlalche.me/e/20/zlpr)
```

要するに、ORM にマッピングされる Column は、`Mapped[str]` のような形で `Mapped[<実際にマップされる型>]` のようにすればよい。

# Solution
## Column の場合
```py
from datetime import datetime

from sqlalchemy import String, Column, func
from sqlalchemy.orm import Mapped, declarative_base

Base = declarative_base()


class ModelName1(Base):
    __tablename__: str = "model_name"

    created_at: Mapped[datetime.datetime] = Column(
        DateTime,
        default=func.now(),
        nullable=False
    )

    updated_at: Mapped[datetime.datetime] = Column(
        DateTime,
        default=func.now(),
        nullable=False
    )

    data: Mapped[str] = Column(
        String,
        nullable=False
    )
```

## `relationship` の場合
```py
from sqlalchemy.orm import Mapped, relationship, declarative_base

Base = declarative_base()


class ModelName1(Base):
    model_name_2: Mapped["ModelName2"] = relationship(
        "ModelName2",
        back_populates="reply"
    )


class ModelName2(Base):
    model_name_1: Mapped["ModelName1"] = relationship(
        "ModelName1",
        back_populates="model_name_2",
        uselist=False
    )
```

`Mapped[]` に与える引数は、`str` 型の値でも、実際の Model でも構わない。
しかしながら、大抵のモデルは相互依存になるだろううから、`str` 型が無難だろう。

# References
- [Mypy / Pep-484 Support for ORM Mappings — SQLAlchemy 1.4 Documentation](https://docs.sqlalchemy.org/en/14/orm/extensions/mypy.html)
【JavaScript】二次元配列について

# はじめに
この記事はJS初級者が中級者を目指して学習した内容のメモであることをご承知おき下さい
## 二次元配列とは
配列の要素がさらに配列であるようなデータ構造のことを指す。
行と列を持つグリッドや表の形式でデータを格納するときに便利。
## サンプルコード
```js
// 定義方法
const twoDimensionalArray = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

// 各要素へのアクセス方法
console.log(twoDimensionalArray[0][0]); // 1
console.log(twoDimensionalArray[1][1]); // 5
console.log(twoDimensionalArray[2][2]); // 9
```
## 二次元配列をループで処理する方法
```js
const twoDimensionalArray = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

for (let i = 0; i < twoDimensionalArray.length; i++) {
  for (let j = 0; j < twoDimensionalArray[i].length; j++) {
    console.log(`行: ${i}, 列: ${j}, 値: ${twoDimensionalArray[i][j]}`);
  }
}
```
上記は以下のように表示される
```
行: 0, 列: 0, 値: 1
行: 0, 列: 1, 値: 2
行: 0, 列: 2, 値: 3
行: 1, 列: 0, 値: 4
行: 1, 列: 1, 値: 5
行: 1, 列: 2, 値: 6
行: 2, 列: 0, 値: 7
行: 2, 列: 1, 値: 8
行: 2, 列: 2, 値: 9
```
AndroidStudio Flamingo でリソースファイルの表示形式を変更する方法

# はじめに

以下の記事を参考に設定を変更しようとしたところ、AndroidStudioのバージョンのせいか同じ名前の項目が見当たらなかったので簡単にまとめました。

https://dev.classmethod.jp/articles/android-studio-4-layout-editor-default-mode/

# 動作環境

`Android Studio Flamingo | 2022.2.1`

# 設定方法

1. メニューからPreference選択
2. Editor > DesignToolsを表示
3. Default Editor Modeから該当するファイルの表示形式を変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2706424/b4fcfa4e-ad38-6c46-d1a8-f816adec3bfa.png)
ubuntuにGoCVのインストールで試行錯誤した話

# Ubuntu 22.04 に GoCV(OpenCV)をインストールするときのあれこれ
golangでopencvを使いたくなったがその際のインストール関係で色々エラーが起きたので記録。
## 環境
Ubuntu 22.04LTS
go version go1.20.3 linux/amd64


## goとopencvについて
opencvは画像、動画処理のソフトで公式ではgolangをサポートしていません。pythonでよく使われています。
しかしgolangにはGoCVというgolangでopencvを使えるようにしたラッパーがあるのでopencvとあわせてインストールすればgolangでもopencvを使えるようになります。ただしubuntuのせいなのか色々エラーが起こりまくったので記録します。

## opencvのインストール

シェルスクリプトからのインストールが[いくつか](https://zenn.dev/wattak777/articles/9face959ffb497)の記事で紹介されているんですがうまく行きませんでした。
ということで次の記事を参考にソースからビルドしていきます。一応やっていることはシェルスクリプトの実行とほとんど変わらないはず。
https://toolatescrap.hatenablog.com/entry/2022/11/29/003848

必要なパッケージをインストール。
`sudo apt install -y cmake g++ wget unzip`


opencvの[サイト](https://opencv.org/releases/)からsourceをダウンロードして解凍。

適当にビルド用のディレクトリを作成、移動。
`mkdir build`
`cd build`

cmake用の設定
`cmake ../opencv-4.6.0`

cmakeでビルド
`cmake --build ./`
数十分はかかります。

インストール
`sudo make install`

## GoCVのインストール
基本的には[公式](https://gocv.io)にしたがって行う。
パッケージのインストール

`go install gocv.io/x/gocv@latest`

公式とか多くの記事ではgo get が使われていますがgoのバージョンアップに伴いgo installに変更になりました。それに伴って@latestをつけるようにしましょう。go installでは@のあとでバージョンの指定が必須です。latestにすると最新のものになります。とりあえずバージョン調べるのも面倒なので@latestで。

パッケージに移動。
`cd $GOPATH/src/gocv.io/x/gocv`
これでうまく行けばいいんですがgoのバージョンによって位置が違うので
`sudo find -name gocv`
とかで探しましょう。私の場合は
`cd go/pkg/mod/gocv.io/x/gocv@v0.32.1`
でした。

ここで
`make install`
するとおそらくエラーが出ます。原因はよくわからなかったのですが[これ](https://www.youtube.com/watch?v=3jrmaAUFkg4)を参照してMakefileの"libdc1394-22-dev"を"libdc1394-dev"に置換します。ubuntuとの対応の問題ですかね。置換したらmake installでインストールされるはず。

`gocv version:[] `
`opencv lib version:[]`
とでれば成功。
AWS Glueのブックマーク機能を有効にした場合のエラー時の冪等性について

## はじめに
皆さんこんにちは。
データ加工ジョブを作成するときに気を付けないといけないのは、**冪等性**ですよね。
AWS Glueでジョブを作成するときも冪等性は非常に重要です。
Glueの[ブックマーク機能](https://docs.aws.amazon.com/ja_jp/glue/latest/dg/monitor-continuations.html)（更新されたファイルのみを自動で判別してそのファイルだけ処理してくれる機能）を有効化した場合に、エラーが発生しても冪等性が担保されるのか？ということについて確認してみたので、記事にしてみます。

ここでいう **"エラーが発生しても冪等性が担保されている"** とは、**エラーが起きてジョブが失敗してしまっても、ジョブを再実行すれば最終的に正しい出力になる**ことを言います。これが担保されていれば、エラーが起きても何も考えずにとりあえず再実行すればOKなので運用が楽になりますね（ジョブの実装自体にバグがあったりする場合は別です）。

## 想定する状況
以下のような状況を考えます。
- inputファイルのjsonをS3に格納する
    - 4つのjsonファイル
- Glueジョブを実行する
    - Glueジョブのブックマーク機能は有効化されている
- 2つのファイルが出力されるが、途中でジョブがエラーとなる
    - ジョブが成功していたら、4つファイルが出力されるはずだった
- ジョブを再実行する
- ジョブが成功する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/cec96785-c28c-f6db-5be0-9c364a9dcbac.png)

さて、この図の？？？はどうなっているでしょうか。

## 考えられる選択肢
以下の3つのパターンを考えてみました。さて、どれになるでしょうか？？

### パターン①
エラー時に出力された2つのファイルはそのままで、再度最初からジョブが実行されて4つのファイルが新規作成されるパターンです。途中まで実行されたことがなかったことになって、もう一度ジョブをやり直しているイメージですね。
このパターンだった場合は、元々のファイル2つが残ってしまっているので、**冪等性が担保されていない**ことになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/1449e476-edc2-9a3d-2832-8a74792ecf5b.png)

### パターン②
エラー時に出力された2つのファイルはそのままで、残りの2ファイルだけ新規に作成されるパターンです。どこまで実行したかが記憶されていて、その途中から実行されたイメージですね。
このパターンの場合は、最終的な4ファイルが出来ているため、**冪等性が担保されている**と言えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/ad43fa19-a310-43f9-07de-f7ab254d964e.png)

### パターン③
エラー時に出力された2つのファイルが上書きされて、残り2つのファイルは新規に作成されるパターンです。①のように最初から実行していますが、中途半端に出力した2ファイルは上書きするイメージです。
このパターンの場合は、②と同じく**冪等性が担保されています**。
②との違いは、元々の2ファイルがノータッチか上書きされるかどうかの違いです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/2ccc2084-06a4-3fe6-cce2-c9ec237c7c9a.png)

## 正解の挙動
正解は･･･
**パターン③です！！**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/741a3195-64b6-bd92-bc17-dd1fbb19f9c6.png)

確かに、中途半端に出力した2つのファイルの中身も中途半端に出力されている可能性もあるから、上書きしたほうが確実ですよね。
ということで、Glueのブックマーク機能はエラーが起きても再度実行すればOKで、冪等性が担保されていると言えます。

ちなみに、ジョブが成功した後に、inputデータを何もいじらずもう一度実行すると、ジョブは成功しますがoutputファイルには何の変化もありませんでした。つまり、Glueのブックマーク機能はエラー時だけでなく成功した場合でも冪等性が担保されていました。ブックマーク機能、良き！

## 注意事項
今回はS3をインプットにしたので、S3のオブジェクトのタイムスタンプが更新されたものを勝手に差分データとして読み込んでくれました。ただ、これがS3ではないJDBCデータソースなどの場合は、タイムスタンプなどは見ずにブックマークキーとなるカラムで対象を判別するので気を付けてください。
また、今回の冪等性の挙動も変わる可能性があります。

## （参考）今回のエラー時の挙動をどのように検証したか
最初は、S3のoutputフォルダにファイルが数個できた瞬間にジョブを手動でstopする方法を試しました。
ですが、これだとstopしても結局全てファイルが出力してしまったため、うまくいきませんでした。

そのため、以下の方法で検証しました。
- 出力する際に、あるカラムでパーティションを作成するようにしておく
    - そのパーティションのvalueが、例えば1/2/3/4の4種類だとする
- その際、output/key=4 だけをバケットポリシーでGlueのロールから書き込めないようにしておく
    - 一応、この下に追加したバケポリの例※を記載しておきます
- こうすれば、key=1~3は書き込めるので途中までファイルが出力されるが、key=4は書き込めないため途中で権限エラーとなる

※ バケポリの例
```json
        {
            "Sid": "Example",
            "Effect": "Deny",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:role/Glue_role_XXX"
            },
            "Action": "s3:",
            "Resource": [
                "arn:aws:s3:::sample-bucket/output/key=4/*",
                "arn:aws:s3:::sample-bucket/output/key=4"
            ]
        }
```
GMailからOffice365メールにアクセスする方法

## Office365のメールをGMailに取り込む

:::note info
この構成は、Outlook365から行う必要があります。
:::

1. [設定] アイコン (メニュー バーの右上にある歯車) をクリックします。
1. 下部にある [Show all Outlook settings] をクリックします。
1. 「Mail」サブメニューをクリックし、「Forwarding」をクリックします。
1. メールの送信先のGMailアドレスを入力してください。

![Screenshot 2023-04-26 at 16.07.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82835/ef2013af-2601-7ca9-eed1-0af756ba97c2.png)

## GMailからOffice365メールを送信する

:::note info
この構成は、GMailから行う必要があります。
:::

1. 「設定」アイコン（右上隅の歯車）をクリックします。
1. 「設定」サブメニューを選択します.
1. [Accounts and Import] タブに移動します。
1. 「Send mail as」セクションから[Add another email address]をクリックします。

![Screenshot 2023-04-26 at 14.43.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82835/b6577f34-01d6-14b2-8f60-ae1fcecb2167.png)

5\. Office365メールアドレスを入力します。
6\. 次に、「Next step »」をクリックして、対応するSMTPサーバーをセットアップします。

![Screenshot 2023-04-26 at 14.43.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82835/a5f58755-d9f3-cfa7-00df-c53c4a10f796.png)

7\. SMTPサーバー: ```smtp.office365.com```を入力します。
8\. ポート: 「587」を選択
9\. ユーザー名: Office365のメールアドレスを入力します。
10\. パスワード: このメールアドレスに対応するパスワードを入力してください。
11\. 「Secured connection using TLS」を選択します。
![Screenshot 2023-04-26 at 14.44.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82835/0f5c76bf-54ad-7073-b7be-d51eeb70a21a.png)

## Conclusion
これで、GMailとOutlookの両方からOffice365アドレスにアクセスできるようになりました。
![Screenshot 2023-04-26 at 15.34.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82835/5725a187-fd73-0425-b16e-5d94a67ba341.png)

[参考](https://blog.pagesd.info/2020/02/25/access-office-365-mail-from-gmail/)
Svelte で ChatGPT 風の入力ボックスを作成した

# はじめに

最近、各企業で専用の ChatGPT アプリを作成している話を聞くようになりました。
需要があるかもしれないので、[Svelte] で入力ボックスだけを作成してみました。

# 2023年5月2日追記

以下の投稿でチャット画面全体を作成してみたので、こちらも参考にしていただければと思います。

https://qiita.com/fsd-tetsu/items/55959a5db1365c5b36af

# 参考にさせていただいたサイト

https://web-dev.tech/front-end/javascript/textarea-auto-height/

https://kakechimaru.com/scrollbar_custom/

# 実装

```html:App.svelte
<script>
	const maxHeight = 240;
	let text;
	let element;
	const handleInput = () => {
		// auto にすることで自動的にリサイズさせる
		element.style.height = "auto";
		// リサイズ後の高さを取得する
		let height = element.scrollHeight;
		if (maxHeight < height) {
			height = maxHeight;
		}
		element.style.height = `${height}px`;
	}
</script>
<div class="wrapper">
	<div class="frame">
		<textarea bind:value={text} bind:this={element} placeholder="Send a message." on:input={handleInput}></textarea>
	</div>
</div>

<style>
	:global(body) {
		padding: 0;
	}
	.wrapper {
		position: absolute;
		bottom:0px;
		width: 100%;
		display: flex;
		justify-content: center;
		padding: 10px;
		box-sizing: border-box;
	}
	.frame {
		width: 80%;
		max-width: 600px;
		padding: 10px;
		border: solid 1px rgba(0,0,0,0.2);
		border-radius: 10px;
		box-shadow: 0px 0px 30px -5px rgba(0,0,0,0.2);
	}
	textarea {
		resize: none;
		width: 100%;
		min-height: 48px;
		max-height: 240px;
		font-size: 16px;
		padding: 0;
		margin: 0;
		line-height:24px;
		border: none;
		white-space: pre-wrap;
		word-wrap: break-word;
		overflow-wrap: break-word;
		overflow-y: scroll;
	}
	textarea:focus {
		outline: none;
	}
	/* スクロールバーのスタイル */
	textarea::-webkit-scrollbar{
		width: 5px;
	}
	textarea::-webkit-scrollbar-track{
		background-color: none;
	}
	textarea::-webkit-scrollbar-thumb{
		background-color: rgba(0,0,0,0.3);
		border-radius: 5px;
	}
</style>
```

# 動作確認

[REPL] で動作確認してみてください。こんな感じで表示されるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2773745/af44e078-b990-eb76-4517-54750b3258df.png)

複数行のテキストを入力すると、高さが自動的に変わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2773745/78470ef7-f539-3277-fabe-c00b63d0edce.png)

高さが限界に達するとスクロールバーが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2773745/e5534e92-a8f0-d427-5c66-df1987da8889.png)

# まとめ

[Svelte] を使って ChatGPT 風な入力ボックスを作成できました。`bind:` のおかげでシンプルに実装できたと思います。むしろスタイルシートの方が難しかったかもしれませんね。

[Svelte] で実装する楽しさを再確認できましたー。:smiley:

[Svelte]:https://svelte.dev/
[REPL]:https://svelte.dev/repl/
Laravel(PHP)デバッグ使い分け（備忘録）

Laravelのデバッグ方法は色々あることは知っていましたが、それぞれどのような使い分けがあるのかと思っていました。備忘録的に書き残しておきます。

## var_dump()
良い点
- データの情報が詳しく確認できる(型の情報や配列のlengthなど)
- 複数この関数を用意すれば、変数を複数一度に見ることができる

悪い点
- 個人的に見にくい

※補足
このようにすることで見やすく表示させることが可能
```
echo "<pre>";
var_dump($array);
echo "</pre>";
```
## print_r()
良い点
- 見やすい

悪い点
- 情報が多いと見にくい

## dd()
良い点
- かなり見やすい

悪い点
- 変数がひとつしか見れない
- 実行がdd()の行で停止する

## 個人的な感想
３つともそれぞれ使ってみましたが、var_dump()やprint_r()を使った際に私が開発している環境ではページのサイドバーでデバッグした結果が見にくくなってしまっているという現象が起こりました〜

var_dump()はデータを詳しく見ることができるので使う場面はあるかもしれませんね〜
print_r()はLaravelを使っているぶんには必要ないのかも？

変数が一つしか見れないというデメリットがあるもののdd()は変数に何が入っているのかみたい時には一番わかりやすいと感じました。（今までずっとdd()を使っていたからかもしれません💦）



※追記
dd()の良さを保ちつつ、実行を止めずに複数の変数の中身を一度に見ることが可能な関数がLaravelにはあることを恥ずかしながら最近知りました！
`dump($array)`　この関数です！
これからはこっちを使っていこうと思っています！！
ぼっち演算子

# ユーザーが存在しない
```
current_user = nil
```
# ぼっち演算子なし
```
name = current_user.name
#=> undefined method `name' for nil:NilClass (NoMethodError)
```
# ぼっち演算子あり
```
name = current_user&.name
#=> nil
```

# まとめ
ぼっち演算子を使うと、エラーではなく、nilを返してくれる。
当然ながら、メソッドが存在しないとエラーになります。

簡単なように見えますが、落とし穴もあるみたいなので、注意して使いましょう。

https://techracho.bpsinc.jp/hachi8833/2017_11_21/48340
Hexabase TypeScript SDKを使ってデータ同士を紐付ける

[Hexabase（ヘキサベース）](https://www.hexabase.com/)は企業においても安心して利用できるBaaS（Backend as a Service）を提供しています。多くのBaaSがそうであるように、主にフロントエンド開発者に利用してもらいたいと考えています。そこで現在、TypeScript SDKの開発が進められています。

この記事ではHexabase TypeScript SDKのインストールと、データストアから取得したアイテム同士を関連付ける方法を紹介します。

## インストール

インストールはnpmやyarnを使って行います。

```
# npmの場合
npm install @hexabase/hexabase-js

# yarnの場合
yarn add @hexabase/hexabase-js

```

## インポート

インポートすると、 `HexabaseClient` というオブジェクトが取得できます。

```js
import { HexabaseClient } from "@hexabase/hexabase-js";

```

## 初期化

HexabaseClientを初期化します。

```js
const client = new HexabaseClient();

```

### 認証

Hexabaseでは業務利用を想定しているため、利用する際に認証情報が必須になります。最初はメールアドレスとパスワードで認証し、その後はトークンを使ってGraphQLにアクセスします。 `client` を使って処理します。

初回の認証は次のようになります。emailとパスワード、またはトークンが必須です。

```js
await client.login({email, password, token});
```

後はこの `client` に対して処理を行います。

## 現在のワークスペースを取得する

ログインした時点でHexabaseClientのcurrentWorkspaceが現在のワークスペースオブジェクトになっています。

```js
client.currentWorkspace
```

ワークスペースを切り替える場合には、 `setWorkspace` メソッドを使います。

```js
client.setWorkspace(newWorkspaceId);
```

## データストアを取得する

データストアの取得は以下のように行います。ワークスペースから該当するプロジェクトを取得し、さらにプロジェクトから該当するデータストアを取得します。

```js
const workspace = client.currentWorkspace!;
const projects = workspace.project(projectId);
const datastore = project.datastore(datastoreId);
```

## アイテムを取得する

データストアからアイテムを取得します。検索条件も設定できますが、今回は単純に取得しています。

```jsx
const items = datastore.items();
const item = items[0];
```

## アイテム同士を紐付ける際の準備

アイテム同士を紐付ける際には、まず管理画面で関連付けされたデータベースの設定が必要です。データストアの設定にて、関連付けるテーブルを指定してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/13c55b81-008c-be88-6540-d6cad0502c30.png)


また、 **関連付けられるテーブルにはユニークなフィールドが必要です** 。こちらもフィールド作成の際に指定してください。

アイテム同士を紐付ける

データの紐付け方には2種類あります。

- フィールドの紐付けるDB参照
- レコードに紐付けるデータリンク

DB参照はフィールドの設定でデータベース参照を使って定義します。データリンクの場合は、管理画面での関連付けられたデータベースの設定だけで大丈夫です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/e9ea4326-b4c8-7544-b8f2-515ae8b932a6.png)


### フィールドの紐付けるDB参照

実際のコードです。 `Linkeditem` というフィールドデータベース参照として定義しています。

```jsx
await item1
  .set('name', 'item1')
  .set('price', 100)
  .set('Linkeditem', item2)
  .save();
```

### データリンク

実際のコードです。 `link` を使います。データリンクは複数定義できます。

```jsx
await item1
  .set('name', 'item1')
  .set('price', 100)
  .link(item2)
  .link(item3)
  .save();
```

逆に削除する場合には `unlink` を使います。

```jsx
await item1
  .unlink(item2)
  .save();
```

組み合わせも可能です。

```jsx
await item1
  .set('name', 'item1')
  .set('price', 100)
  .link(item2)
  .link(item3)
  .unlink(item4)
  .save();
```

## まとめ

データリンクやデータベース参照はいわばリレーショナルデータベースとして利用できます。複雑なリレーションも実現できますので、ぜひ活用してください。

Hexabase TypeScript SDKを使えば、VueやReactなどと連携したWebアプリを素早く開発できるようになります。2023年04月現在絶賛開発を進めていますので、ぜひ試していただいてフィードバックいただければ嬉しいです！

[hexabase/hexabase-js](https://github.com/hexabase/hexabase-js)
JMeterでAzure SignalR Serviceとの接続を確立する方法

## 注意点
* pingと称して、JMeter側からたまに特定の文字列をSignalRで送信しないと通信が切断される。
* pingと称して、頻繁にSignalRからテキストフレーム通信が送信されてくるので、WebSocket Text Frame Filterでフレームを破棄する設定をいれておかないと、意図しない通信に反応してしまう。
* Azure SignalR Service特有なのかは分からないが、通信を確立するまでにプロトコルが存在する。
次の稿でそのプロトコルを記載する。

### プロトコル
1. [Webscoket Samplers by Peter Doornbosch](https://bitbucket.org/pjtr/jmeter-websocket-samplers/overview)プラグインをインストールする
2. Azure FunctionsでNegotiate関数を作っている場合、Http SamplerでPOST呼び出しする
HTTP Header Mangerで以下を指定する。（この部分はまだ設定過不足の余地あり）
　x-signalr-user-agent: JMeter
　x-ms-signalr-userid: 通信を共有したいユーザーID名
ポストプロセッサーのJSON ExtractorでレスポンスのurlとaccessTokenを取得する
3. urlに対して、Http SamplerでPOST呼び出しする
HTTP Header Managerで以下のペアを登録する。
　authorization: 1で取得したaccessToken
　x-ms-signalr-userid: 1で指定したx-ms-signalr-useridと同じユーザーID
　x-signalr-user-agent: JMeter
JSON ExtractorでconnectionIdを取得する
4. プラグインのWebSocket Open Connectionサンプラーでurlのドメインに対してwssで呼び出しを行う
HTTP Header Managerで以下のペアを登録する
　Connection:Upgrade
　Upgrade:websocket
　Accept-Encoding:gzip,default,br
　User-Angent:JMeter
5. プラグインのWebSocket Single Write SamplerでText Frameで「{"protocol":"json","version":1}」という書き込みを行う
6. プラグインのWebSocket Single Read SamplerでSignalRからの通信を待つ
備忘録 Windowsに、Redmineをインストール

# 1.ImageMagickのインストール
# 1.1 ImageMagickをダウンロードする。
[ImageMagick](https://imagemagick.org/script/download.php#windows "ImageMagick7.1.1-3-Q16-HDRI-x64-dll.exe")

:::note info
 *dll.exe　をダウンロードする
:::

# 1.2 インストール時のオプション
 「Install development header and libraries for C and C++」にチェックを入れる。

# 1.3 環境変数 Path に　ImageMagickのパスが追加されていることを確認する。

# 2.Rubyのインストール
## 2.1.下記のダウンロードして実行する。
 [Ruby+Devkit 3.2.2-1 (x64)](https://github.com/oneclick/rubyinstaller2/releases/download/RubyInstaller-3.2.2-1/rubyinstaller-devkit-3.2.2-1-x64.exe "Ruby+Devkit 3.2.2-1 (x64)")

## 2.2. インストール完了後、「Run 'ridk install'・・・」にチェックを付けたままFinish

## 2.3.コマンドウィンドウが起動するので、ENTERを入力し、完了したら、ENTERを入力し終了。

## 2.4.cmd（コマンドプロンプト）を「管理者で実行」する。

## 2.5.webrickをインストールする。
```
gem install webrick
```

## 2.6.rmagickをインストールする。
```
gem install rmagick
```
　　
# 3.MariaDBのインストール
## 3.1. MarianDBをダウンロードする。
[MarianDB](https://mariadb.org/download/?t=mariadb&p=mariadb&r=11.1.0&os=windows&cpu=x86_64&pkg=msi&m=yamagata-university "MarianDB")

## 3.2. MarianDBのインストール
:::note info
デフォルト文字コード　UTF8 をチェックする。
:::

# 3.3 Redmine のデータベースの作成
```
CREATE DATABASE redmine CHARACTER SET utf8mb4;
CREATE USER 'redmine'@’localhost’ IDENTIFIED BY 'PASSWORD';
GRANT ALL PRIVILEGES ON redmine.* TO 'redmine'@’localhost’;
exit
```

# 4 Redmineインストール
## 4.1 Redmineのダウンロード
[Redmine 5.0.5](https://www.redmine.org/releases/redmine-5.0.5.zip "Redmine 5.0.5")
## 4.2 Redmineを任意のフォルダに解凍する。
:::note info
D:\に展開し、D:\Redmine で参照できるようにする。
:::
## 4.3 database.yml の変更
d:\redmine\config\database.yml.exampleをD:\redmine\config\database.ymlにコピーして、5行目付近のデータベースの情報を環境に合わせて書き換えて保存する。
```
production:
adapter: mysql2
database: redmine
host: localhost
username: redmine
password: "PASSWORD"
# Use "utf8" instead of "utfmb4" for MySQL prior to 5.7.7
encoding: utf8mb4
```

## 4.4 configuration.yml の変更
email_deliveryを変更する。
[メールの設定例](http://guide.redmine.jp/Email_Configuration/)

GMAILを使用する場合は、2段階認証に設定し、使用する。

```
default:
  email_delivery:

･･･

production:
  email_delivery:
```

## 4.5 Gemfileの変更
3行目を下記のように書き換える。
```
ruby '>= 2.5.0', '< 3.2.3'
```

## 4.6 WebブラウザからのアクセスURLに/redmineを付ける場合の設定
D:\redmine\config\environment.rb の末尾に、下記を追記
```
Redmine::Utils::relative_url_root = "/redmine"
```

## 4.7 コマンドプロンプトを管理者権限で起動する。
カレントディレクトリを変更する。
```
D:

cd D:\redmine
```

## 4.8 bundler のインストール
```
gem install bundler
```
```
bundle install --without development test
```
```
bundle add webrick rmagick
```

## 4.9 Redmineをセットアップする。
```
set RAILS_ENV=production
bundle exec rake generate_secret_token
bundle exec rake db:migrate
bundle exec rake redmine:load_default_data
```

## 4.10 Redmineの自動起動
### 4.10.1 Thin Serviceをインストールする
```
gem install thin_service
```
### 4.10.2 コマンドプロンプトの文字コードをUTF8に変更する
```
chcp 65001
```
### 4.10.3 WindowsサービスにThin Serviceを登録する
```
thin_service install -N "Redmine Thin Service" -e production -p 3000 -c "d:\redmine" --prefix "/redmine"
```
:::note info
ポートは、3000 です。
:::

### 4.10.4 Thin Serviceを自動起動
Windowsサービスには手動起動設定として登録されていたので、OS起動時に自動起動するように設定変更する。


# 5.Redmineにアクセスする
ブラウザでhttp://localhost:3000/にアクセスする。

:::note info
初期のIDとパスワードは共にadmin。
:::
保守・2次開発のフォルダ/ファイル構成

共通
　管理
　　課題管理
　　総務管理
　　ナレッジ管理
　　海外A拠点
　　海外B拠点
　最新成果物・参考資料
　※参考資料って分かりづらいな。
　会議
2次開発
　管理
　　発注管理
　　見積管理
　　全体進捗管理
　　テスト環境管理
　　ライブラリ管理
　WF開発
　　作業中案件
　アジャイル開発
　　any
　移行
　　xxx
保守
　管理
　　AMデマンドリスト
　定型保守
　非定型保守

※できればサービス管理フォルダって消したいよね。。。

〇フォルダ/ファイル運用ルール
・既存のフォルダ/ファイルを参照しそれに従うこと。
・名前順で並び替えた場合に分かりやすくなるようなるべくすること。(ex.100_管理, 200_AE)
・古いファイルは、_oldに格納すること。(_archive, _bkとかNG)
・テンプレートフォルダは、_templateとすること。
・作業中のファイルは、_workフォルダを作成し格納すること。
　格納ファイルはファイル名_作業者名とすること。
　作業後は親フォルダ (通常のフォルダ) に配置する想定。作業後は_workのファイルは削除すること。
・作業中でないフォルダ (通常のフォルダ) には複数バージョンのファイルを配置しないこと。
・\_oldには、ファイル名_yyyymmdd (退避日) で配置すること。
・英数字は半角で統一する (但し、案件名等、正式な名称が全角の場合はそれに従うこと。)
・日付はyyyymmdd形式とする。(ex.20220101)
・繋ぎ記号は_ (アンダーバー) で統一すること。
Power BIを利用して社内情報を見える化（まとめ）

今年の初めからPower BIを使った記事を何本か書いてきましたが、今回が最終回です。
社内で業務の見える化第1弾が完了しましたので、使ったツールやスキルなどをまとめて載せておきます。

# 準備するもの
 - Power BI Desktop (Windowsアプリ）
 - Power BI サービス (Webアプリ) ※Proライセンス以上が必要

流れとしては、Power BI Desktopを使って、Teamsで共有されているEXCELファイルを取得⇒レポート作成⇒レポート発行、Power BIサービスからTeamsにレポートを共有するといったオーソドックスな流れです。

処理フローはこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885406/5a0a1346-7fb0-3f53-aee8-a416111c28db.png)

# 作業の流れ
1. Teams上のExcelをPower BI Desktopで取得する

以前投稿したとおり、Excelが配置されているパスさえ取得できれば読み込むことができます。
もちろんPower BIサービスからでも読み込めます。

https://qiita.com/fsd-kozue/items/50a661bdb125e8b4bf5b

２．レポート作成する
レポートの作成方法についても以前の記事をご参照いただければと思います。

https://qiita.com/fsd-kozue/items/16a4abd481c5232946b8

３．レポートを発行する
レポートを作成し終わったら発行ボタンを押下します。(赤丸のところ)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885406/f93d212d-a298-f1e2-40ae-00d0f6b511e0.png)

そうすると「Power BIへ発行」というポップアップ画面が表示されますので、ここでPower BIサービス上のワークスペースを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885406/f7814b8f-c4f5-e9ed-65b6-6e38cee93574.png)

上の画像で選択されている「マイワークスペース」であれば、Power BIサービスの無料ライセンスで発行でき、それ以外のワークスペースを利用したい場合はProライセンス以上が必要となります。
今回は、「スキルの見える化」というワークスペースに発行しました。
すると、データセットとレポートの2本がWeb上に表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885406/93c624ef-add3-63fd-b9fc-0407808b7aee.png)


４．レポートを共有する
「Teamsにレポートを共有する」章をご参照ください。

https://qiita.com/fsd-kozue/items/7cc98cc44a5e3585b40b

ここまでがレポート共有のフローになります。
次は運用についてのお話しになります。

# レポートを最新化する方法
せっかく作ったレポートを作りっぱなしにするのではなく、常に最新の状態に保っておきたい。
特にExcelファイルで入力したデータは日々更新されることが多いので、Power BI サービスを使ってスケジューリングします。
手順を簡単に説明します。

1. 先ほどワークスペースにあげたデータセットの設定画面を開く
1. スケジュールされている更新を「オン」にセット
更新の頻度とかタイムゾーンは適宜調整してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885406/da7f6d98-673d-757d-1d96-d5a1a4e6d319.png)


# Power BI Desktopで作成したレポートを他のメンバと一緒に運用する
最近あげた記事をご参照ください。

https://qiita.com/fsd-kozue/items/90426ee3e9147b9d0e58


以上がPower BI DesktopとPower BIサービスを使って社内情報をビジュアル化する流れとなります。
これからPower BIを使ってみようという方や社内の見える化を検討される方のお役にたてると幸いです。
B2C Commerce のその他 Salesforce 製品との接続 - まとめ

※ これから記載する事項は、私が所属する会社とは一切関係のない事柄です。



この記事では「B2C Commerce のその他 Salesforce 製品との接続」シリーズの記事のリンクをまとめています。
※ 今シリーズでは下記の画像に基づいて B2C Commerce からみた他の製品への接続について説明していきましたが、**あくまで B2C Commerce からみた接続** なので、実際にはその他の製品同士の接続を考慮しながらアーキテクティングしていってください。

![Cross Cloud (18) (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2110894/2ec251aa-bca9-6632-b070-75c1f1ca438f.jpeg)



#### 下記に関連する記事へのリンクを記載します

* [B2C Commerce のその他 Salesforce 製品との接続 - B2C-CRM-SYNC](https://qiita.com/syunyama/items/cc2640192320f8259908)
* [B2C Commerce のその他 Salesforce 製品との接続 - Salesforce Order Management 前編](https://qiita.com/syunyama/items/802fa03e96e387828179)
* [B2C Commerce のその他 Salesforce 製品との接続 - Salesforce Order Management 後編](https://qiita.com/syunyama/items/3b03acf2d1cbd3a27731)
* [B2C Commerce のその他 Salesforce 製品との接続 - Loyalty Management for commerce](https://qiita.com/syunyama/items/1399a622bb9b5be28a99)
* [B2C Commerce のその他 Salesforce 製品との接続 - Commerce Cloud Tableau Connector](https://qiita.com/syunyama/items/7818535efeeb79e2764d)
* [B2C Commerce Alerts for Slackを設定してみる](https://qiita.com/syunyama/items/84211211eabc8d21e708)
* [B2C Commerce のその他 Salesforce 製品との接続 - Commerce Cloud CDP Connector](https://qiita.com/syunyama/items/88b564afb9c8b07af931)
* [B2C Commerce のその他 Salesforce 製品との接続 - Marketing Cloud Connector](https://qiita.com/syunyama/items/38d7d45cac8205b4384e)
* [B2C Commerce のその他 Salesforce 製品との接続 - HTTP, FTP, SOAP](https://qiita.com/syunyama/items/6d86a288e69721f60058)
* [MuleSoft で B2C Commerce を利用してみる（事前準備編）](https://qiita.com/syunyama/items/cd21be5fadceb23db6c5)
* [MuleSoft で B2C Commerce を利用してみる（B2C Commerce 利用編）](https://qiita.com/syunyama/items/98df36764a1e6583fbe4)
* [B2C Commerce のその他 Salesforce 製品との接続 - Commerce API, WebDAV](https://qiita.com/syunyama/items/6258b0e8b0f88057f1b1)
【TypeScript】定数、型、ラベルを定義して取り出す方法（as Const + keyof typeof）


# const定義
まずは定数を定義する。以下のようにconstを使って定義する。


``` ts
export const FRUIT_LIST = {
  APPLE: 'apple',
  ORANGE: 'orange',
} as const;
```
# Type定義
次に、定数をもとに型を定義する方法。```keyof typeof```を使って以下のように定義する。

``` ts
export type FruitType = typeof FRUIT_LIST[keyof typeof FRUIT_LIST];
// FruitType  = 'apple' | 'orange'
````

# ラベル定義
Recordを使って、先ほど定義した型をキーとして、対応する文字列を格納。
日本語ラベルを定義できる

```ts
export const FRUIT_LABELS: Record<FruitType, string> = {
  [FRUIT_LIST.APPLE]: 'りんご',
  [FRUIT_LIST.ORANGE]: 'みかん',
};
```
# 取り出し方
最後に、上記で定義したラベルを取り出す方法をば。
以下のようにしてJSX側では取り出すことが可能


```JSX
 {FRUIT_LABELS[FRUIT_LIST.apple]} // りんご
```
エンジニアの本棚というアプリを作ってみた(React + Firebase)

# 作った経緯
社内でアプリを作るイベントがあり、Reactの学習をしたかったのでReactだけで作れるアプリというのを元に考えました。
アプリネタは社内のエンジニアがおすすめする書籍はなんだろうなとふと思ったのがきっかけです。

# 使用技術
- React18
- TypeScript
- Firebase Authentication(認証)
- Firebase Cloud Firestore(DB)

# アプリの紹介
GoogleBooksAPIで書籍を検索し、自分の本棚に登録していくというアプリです。
他人の本棚は常に覗けるようにしておき、次に読む本の参考にしたりできます。
積読している書籍については輪読会しようぜみたいと社内で声かけたりできたらいいなとか妄想してます。
[![Image from Gyazo](https://i.gyazo.com/f1b39b08ad0a63cfbc1d0d57416b8fe8.png)](https://gyazo.com/f1b39b08ad0a63cfbc1d0d57416b8fe8)

# 苦労したこと
#### 登録書籍のユニーク制約
書籍にユニーク制約をつけたいけどどうするんだ？と悩みました。
書籍にはISBNコード（国際標準図書番号）というユニークな番号があり、それをFirestoreのドキュメントIDに設定し、Firestoreの[setDoc](https://firebase.google.com/docs/firestore/manage-data/add-data?hl=ja#:~:text=%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88%E3%81%8C%E5%AD%98%E5%9C%A8%E3%81%97%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88%E3%81%AF%E6%96%B0%E3%81%9F%E3%81%AB%E4%BD%9C%E6%88%90%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88%E3%81%8C%E5%AD%98%E5%9C%A8%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88%E3%80%81%E6%97%A2%E5%AD%98%E3%81%AE%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88%E3%81%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E7%B5%B1%E5%90%88%E3%81%99%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E6%8C%87%E5%AE%9A%E3%81%97%E3%81%AA%E3%81%84%E9%99%90%E3%82%8A%EF%BC%88%E4%B8%8B%E8%A8%98%E3%82%92%E5%8F%82%E7%85%A7%EF%BC%89%E3%80%81%E6%96%B0%E3%81%97%E3%81%8F%E6%8F%90%E4%BE%9B%E3%81%95%E3%82%8C%E3%81%9F%E3%83%87%E3%83%BC%E3%82%BF%E3%81%A7%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%E3%81%8C%E4%B8%8A%E6%9B%B8%E3%81%8D%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82)メソッドを使用することで解決しました！

#### リクエスト制限
実装中に数回無限レンダリングを発生させてしまった時に、リクエスト上限になってしまいFirestoreが停止しました。
最初は原因がわからず急に動かなくなって焦りました...

#### ログイン
ログインユーザーを取得するまで待機させるのに詰まりました。
[現在ログインしているユーザーを取得する](https://firebase.google.com/docs/auth/web/manage-users?hl=ja#:~:text=%E3%82%82%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82-,%E7%8F%BE%E5%9C%A8%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B,-%E7%8F%BE%E5%9C%A8%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%97)
こちら参考に解決しました。

# 最後に
- Firebaseは初めましてでしたが、今回のイベントがきっかけで触れることができたので感謝が大きいです！
- 期限までに完成まで持って行けなかったのは悔しいですが、イベントとは別に機能追加してリリースまで持っていきたい...

この記事は、株式会社mofmofの「水曜日の個人開発」にサポートされています。

https://indie-dev.mof-mof.co.jp/
Azure Load Testingの使用について

https://learn.microsoft.com/ja-jp/azure/load-testing/

## Azure Load Testingについて
* Azure上で動く、負荷テストを実施するためのツール。
* URLが分かるならどのサイトに対しても負荷をかけることは出来る。
* JMeterスクリプト・プラグインが動く。カスタムで作成したプラグインも動くらしい（動作未確認）

## 使用した上での注意点
* 仮想ネットワーク接続は、仮想ネットワークとこのツールのリソースが同一サブスクリプション・同一リージョンで使用可能。
* このツールのリソースは現時点で東日本リージョンにはデプロイできない。
* JMeterでログをダウンロード可能なログファイルに出力するためには、ログレベルをwarn以上にする必要がある。
railsチュートリアルまとめ1 ゼロからデプロイまで

# 個人的リマインド用
参考
[Ruby on Rails チュートリアル プロダクト開発の０→１を学ぼう](https://railstutorial.jp/)
[railsのアセットパイプラインについて解説する](https://qiita.com/uma002/items/9a94ebc93c5f937502cd)


## 1 ゼロからデプロイまで
### cloud9の環境構築、RubyやRailsの導入
[cloud9でのrails環境構築と入門的内容](https://qiita.com/TeihenEngineer/items/c539ed1c3fd5fee6ed4c)
↑以前、記事にてまとめました。

Railsアプリケーションでは、どんなアプリでも始める時は**rails new**
このコマンドを実行するだけで、指定のディレクトリにRailsアプリケーションのスケルトンを簡単に作成できる。
今回はCloud9だが、利用しない場合はRailsプロジェクトで使うためのenvironmentディレクトリを作成しておく。
```
cd #ホームに移動
mkdir environment #ディレクトリ作成
cd environment
```
その後にrails new
```
rails _7.0.4_ new hello_app --skip-bundle
(--skip-bundleを書くことでbandleインストールが一緒に行われない。
先ほどインストールしたバージョンのbandleコマンドと互換性が保たれる)
```
**頻出ワード:アセットパイプラインとは**
作業がしやすいように画像、javascript、css、htmlファイルを分解つしてコーディングして、最終的に1つのファイルにまとめる仕組みのこと。詳しくは他の方の記事から。
[railsのアセットパイプラインについて解説する](https://qiita.com/uma002/items/9a94ebc93c5f937502cd)

Gemファイルに色々書き込んで、bundleインストールを実行。このGemファイルについてはこれから要勉強。

### Gemのバージョンについて
```
gem "sprockets-rails"
自動的に最新バージョンをインストール

gem "capybara", ">= 3.26"
最新バージョンのインストールを指定

gem "puma", "~> 5.0"
5.0以上6.0以下(いわゆるマイナーアップデート)のバージョンを適用
```
いろいろバージョンを指定したらbundleインストール。
```
cd hello_app/ 作業ディレクトリに移動
bundle _2.3.14_(ここは指定のバージョン) install
```
### rails server
開発マシンでのみブラウズできるローカルwebサーバーを起動するためのスクリプト。
rails s(server)で実行できるが、その前に一つ注意点。
```
config/encironment/development.rb

上記のファイルの末尾に以下のテキストを追加
Rails.appkication.configure do
・
・
・
#cloud9への接続を許可
 config.hosts.clear
end
```
クラウドでないOSでrails sの結果を表示するには、ブラウザのアドレスバーに
```
http://localhost:3000
```
を貼り付ける。

### MVCモデル
入門的な内容は以下を参照
[cloud9でのrails環境構築と入門的内容](https://qiita.com/TeihenEngineer/items/c539ed1c3fd5fee6ed4c)

### Hello, world!を表示するまで
使うcontrollerを調べる。現在はApplicationしかない。
```
ls app/controllers/*_controller.rb
```
続いてcontrollerに書き込み
```
app/controllers/application_controller.rb

class ApplicationController < ActionController::Base

  def hello
    render html: "hello, world!"
  end
end
```
次に「デフォルトのページの代わりに、このアクションを使うように指示する。そのためには、railsの**ルーター**を編集する。
**ルーター**とはコントローラとブラウザの間に配置され、ブラウザからのリクエストをコントローラに振り分ける(ルーティング)役割を持つ。
```
config/routes.rb

Rails.application.routes.draw do
  root "application#hello"
end

初期画面でapplicationコントローラのhelloアクションを実行しろっていう意味
```
### git
gitのセットアップに関しては以前まとめています
[Cloud9とGithubの連携(備忘録)](https://qiita.com/TeihenEngineer/items/a8dc7952986b1d7e6c2c)