OmniAICreator/Qiita-1.07M huggingface dataset:
BizRobo! BrowserTracer（ブラウザトレーサー）機能について

## はじめに
ビズロボでは、Web操作を行うことができることが、一つの強みですが、
Webブラウザエンジンによって表示がうまくされなかったり、
CSVの出力の際などに、少し出力方法について工夫が必要だったりと、
通信内容について確認したい場面があるかと思います。

<br>
今回は、ビズロボで通信内容の確認ができる
BrowserTracer（ブラウザトレーサー）機能についてです。

<br>

## ブラウザトレーサーとは
<br>

### まずブラウザとは 
WEBサイトを閲覧するために使うソフトのこと。Chrome、Internet Explorer(IE)、Microsoft Edge、Google Chrome、Safari、などが有名ですね。

HTMLやCSSなどを解釈して、見た目を整形した上で表示する機能がありますが、
ざっくり画面表示の役割を持っていると思っていただければと思います。

<br><br>
### トレーサー
トレースがなぞったり、過程を調べるというニュアンスですので、
トレースを行う主体といったところでしょうか。


そのためブラウザトレーサーは、
ブラウザが実行した通信の内容を確認できるといったイメージですね。

<br><br>
## 使い方

上部のTools（ツール）から
Open Browser Tracer（ブラウザトレーサを開く）をクリックします。

![tracer1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291018/3d9df490-faf3-156e-7d87-28281da076b3.png)

<br><br>
すると下記のようなシンプルな画面が開きます。

![tracer2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291018/24a3e5b5-1db5-1886-2603-7a0de8d9e4e8.png)

<br><br>
トレースの開始および停止は、
左上の赤丸のボタンをクリックすることで切り替えられます。

ちなみに開始すると下記のような形
（少しわかりにくいですが、ボタンが押されています）

この状態でブラウザを読み込んだり画面遷移をすることで、
通信内容の取得ができるようになりました！

![tracer3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291018/b89b99e7-62d8-4dc6-f0c9-3bd29ba78534.png)

<br><br>
ステップを通過させると、
画面が表示されたことがわかります。
（今回は、MY BizRobo!のログイン画面を読んでいます）

![tracer4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291018/f6305183-fc3b-baa2-7dc8-7ac9a72d74b2.png)

<br><br>
それでは、ブラウザトレーサーを確認してみます。
![tracer5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291018/e2598bb5-f8ea-fdde-6fe8-34103021cce9.png)


通信内容が取れていることがわかります。

<br><br>

より詳細なリクエストやレスポンスは各行を選択すると確認できるようになります。

![tracer6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291018/c528e394-7609-1ce2-2a35-860c363901a7.png)


<br><br>

![tracer7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3291018/f03c3839-776b-4b68-9c20-0f91e75979c0.png)
<br><br>

## 注意点

動作に影響が出てしまうため、
ポイントは絞って使用し、使用しない場合はすぐに無効にしましょう。
この内容については、[Kofax RPA のヘルプ](https://docshield.tungstenautomation.com/RPA/ja_JA/10.4.0_rp4hrvtqrq/help/kap_help/reference/c_browsertracer.html)で以下のように説明されています。

>記録中、特に JavaScript 記録を利用した記録中は大量のデータが収集されるため、動作が通常よりずっと遅くなることがあります。目的のトラフィックのトレースが完了したら、必ず [記録] ボタンを無効にしてください。



## おわりに
今回はブラウザトレーサー機能についてでした。

BizRoboでは、
通信内容を考慮しての開発も必要になるシーンがあるため、
ぜひ今後も活用していきたいと思います。

最後まで見ていただきありがとうございました。


以上
An AI assistant built into Chrome's integrated AI

Google has integrated Gemini Nano into the Chrome Developer Edition, allowing offline use of built-in AI models for simple tasks. This functionality ensures seamless operation even without an internet connection. On-device AI not only guarantees data security but also provides fast response times, accessible through window.ai.

🌟 https://chromeai.org has made several optimizations for Chrome's built-in AI:

Interact with Chrome's built-in AI through a conversational interface
Support for local caching of historical generation records
Real-time conversation mode with AI response times between 200-300 milliseconds, depending on device performance
Purely offline usage, storing no data
Clear and convenient guidance
Plugin version available for direct use in the sidebar

网站地址：https://chromeai.org
GitHub 地址：https://github.com/debugtheworldbot/chromegemini![344241398-6fc32de3-1e2d-4d2c-b259-5c6ca2454654.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3843432/955abd5e-1c8b-0725-7484-0480b93014b3.png)
![uploading...0]()
【Laravel】抽象メソッドとは

## 抽象メソッドとは
抽象クラスの中で定義されるメソッド。
抽象クラスは、他のクラスに継承されることを前提としている。
子クラスは必ず抽象メソッドを実装しなければならないため、特定のメソッドが常に存在することを保証できる。

`abstract`は「このメソッドは抽象メソッドである」という意味。

具体的なロジックはこの抽象メソッドを実装するサブクラスに委ねられる。 
```php
abstract class Animal {
    //抽象メソッドを定義
    abstract public function makeSound();
}

class Dog extends Animal {
    public function makeSound() {
        return 'Bark';
    }
}
```

## 使う場面
- 共通のインターフェースを強制し、子クラスが必ず特定のメソッドを実装する必要がある
- 共通の基本機能を持ち、それを派生クラスで具体的に実装する必要がある
文字列の分割を最初に出てきた分割文字のみで分割

_で分割したいけどスプリットで分割すると後の-まで分割されちゃうよ。。って人のために
```vb
Function SplitFirstUnderscore(ByVal text As String) As Variant
    Dim splitPos As Integer
    splitPos = InStr(text, "_")  ' 最初のアンダースコアの位置を見つける

    If splitPos > 0 Then
        ' アンダースコアが見つかった場合、文字列を分割する
        SplitFirstUnderscore = Array(Left(text, splitPos - 1), Mid(text, splitPos + 1))
    Else
        ' アンダースコアがない場合、元の文字列をそのまま返す
        SplitFirstUnderscore = Array(text, "")
    End If
End Function
```
sh: react-scripts: command not foundの解決方法

reactのプロジェクト始めようとしたら早速エラーで詰まったので備忘。

# 今回の構築環境
```
node -v
v20.14.0

npm --version
10.7.0

react": "^18.3.1",
"react-dom": "^18.3.1",
```

# エラーの経緯
reactプロジェクトを始める
```
npx create-react-app project-name
cd project-name
npm start
```

npm startしたら以下のエラー出る。
```
npm start

> react-app@0.1.0 start
> react-scripts start

sh: react-scripts: command not found
```

# 解決した方法
package.jsonのコマンド部分を書き換える。
```package.json 変更前
"scripts": {
    "start": "react-scripts start",
}
```

```package.json 変更後
"scripts": {
    "start": "NODE_ENV=production node_modules/react-scripts/bin/react-scripts.js start",
}
```

参考サイト

https://note.com/suke3300_blog/n/ne19d5883d3ab

https://stackoverflow.com/questions/40546231/sh-react-scripts-command-not-found-after-running-npm-start
(Tailscale) リモート接続について（職場⇔自宅）

# リモート接続がしたい！
　リモート接続用のアプリケーションなんて星の数ほどあるじゃないかと思ったそこのあなた。使えないんです。大学のセキュリティ×Linux機の掛け合わせによるガチガチセキュリティではね！！！！
 　流石に名前を書くのはやめますが、大体のアプリケーションがだめでした。工夫したことといえば
<ul>
<li> シングルログインになるように、職場（便宜上職場と書いてますが研究室です。今のところは院生なので）のマシンからはログアウトしておく</li>
<li> グラフィックのドライバを変えた</li>
<li>　実に様々なリモート接続クライアント＆サーバを試した</li>
<li>　ファイアウォールの設定をゴニョゴニョした（今はもとのストリクトな設定に戻してます）</li>
</ul>

などなど……。まあ上げればキリがないのだが。そして最終的に行き着いた先が　<b>Tailscale</b>　であったというわけ。ありがたやありがたや。最近はVPNの脆弱性が指摘されていたり、何かとセキュリティ関連のインシデントが多かったので、セキュアなリモート接続が構築できるアプリケーションには頭が上がらないのである。

と、まあ前置きは長くなったが、以下に使い方の説明を残しておく。

# まずはOpen-SSH server をインストールしよう
　いきなりあれなのだが、RSA暗号のキーペアを作成するのに使用する。というかどうやらtailscale自体がSSHのwrapperのようだ。VPNの脆弱性といえば、アカウント情報（IDとパスワード）さえ突破できれば侵入できるというのがWell Knownなわけだが、Tailscaleはキーペアでの認証ができるのでそのへんが安心だったりする。
　余談だが、apt-get update の後に apt-get upgrade するのをセットにしている。特に開発しているわけではないので、aptitude upgrade あたりまでで大体ことがすむので、特別な理由でもなければ普段からセキュリティーの強化はするに越したことはない。
 
　SSHのインストールおよび設定は以下のサイトを参考にさせてもらった。

https://zenn.dev/uchidaryo/books/ubuntu-2204-server-book/viewer/openssh

## ssh-client & ssh-server のインストール

```
sudo apt-get update
sudo apt-get upgrade

# おそらくclient の方はデフォルトで入っているはず
sudo apt-get install openssh-server (接続される側のマシン)
sudo apt-get install openssh-client (接続する側のマシン)

# 状態の確認
systemctl status sshd.service

# もしactive(running) と表示されていなかったら
sudo systemctl start sshd.service
sudo systemctl enable sshd.service
```
### サーバ（接続される側）の設定
```
# もとの設定ファイルのバックアップをとる
sudo cp -p sshd_config sshd_config.orig
sudo chmod a-w sshd_config.orig

#　接続される側の設定ファイル編集
sudo vim sshd_config
```
　パスワード認証だとセキュリティ激甘になってしまうのでキー認証にしてしまうのがおすすめ。サーバに直接アクセスできない環境の場合、初回のみパスワード認証にしておき、ペアキーを作成・サーバ側にコピーしてキー認証に変更すると良いと思います。
```
# 新しい設定でエラーが出ないか確認
sudo sshd -t -f sshd_config

# 終わったら設定の変更を反映させる
sudo systemctl restart sshd.service
```
### 公開鍵認証の導入
　ここは簡単なのでさくっと行ってしまいましょう。
```
# クライアント（接続する側のマシンでの作業）
# -t ed25519 はアルゴリズムの指定、-C "コメント"　でコメントを残すことができる。
ssh-keygen -t ed25519 -C ""

# サーバに公開鍵をコピー
ssh-copy-id user_name@ip_address_or_domain_name
```
これでサーバにSSH接続できるようになったはずです。試しに
```
ssh user_name@ip_address_or_domain_name
```
でSSHできることを確認してください。そして
```
sudo vim /etc/ssh/ssdh_config

# /etc/ssh/sshd_config (/Passwod などとすればvimでファイル内の文字列を検索できる)
PasswordAuthentication no
```
としてしまえばOKです。

# Tailscale のインストール
　これは最近はやっているだけあって各所にインストール方法が記載されているので慣れたもので、

https://tailscale.com/download

からOSを選んでソースコードをダウンロードします。ダウンロードしたディレクトリに移動し、
```
sudo apt-get install ./tailscale*.deb
```
などとしてインストールしてください。
インストールできたら
```
sudo tailscale login
### ここでログイン用のurlが出てくるので移動し、指示に従ってログインしてください ###

# 無事ログインできた場合　Success!　の文字が表示されます。

# tailscale を起動
sudo tailscale up

# tailscale をsystemd　に登録
sudo systemctl start tailscaled
sudo systemctl enable tailscaled

# tailscale でのipアドレスを表示
tailscale ip -4
[ipv4 address]
```
これで終わりです。クライアント・サーバどちらも同じ手順でtailscaleをインストールしておきます。
```
tailscale status | grep [登録名　一部でもOK]
```
などとすれば、自分のアカウントで登録されたマシンの状態が見られます。
接続できる状態になっていれば一番右側にactive；relay "tok", などと表示されます。ちなみにrelay "tok"は”東京のリレーサーバを中継している”の意です。

筆者は通常のSSH同様パスフレーズ認証かと思っていてしばらく詰みました（普段はイーサネット内なので完全に油断していた）。もし片方をwifiなどでつないでいる場合は<b>USBなどで鍵をダイレクトにコピー</b>することになるかと思います。
最速でRailsアプリケーションをDockerコンテナ上で動かす

## 経緯
- [仕組みと使い方がわかる Docker&Kubernetesのきほんのきほん | 小笠原種高 |本 | 通販 | Amazon](https://www.amazon.co.jp/%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%A8%E4%BD%BF%E3%81%84%E6%96%B9%E3%81%8C%E3%82%8F%E3%81%8B%E3%82%8B-Docker-Kubernetes%E3%81%AE%E3%81%8D%E3%81%BB%E3%82%93%E3%81%AE%E3%81%8D%E3%81%BB%E3%82%93-%E5%B0%8F%E7%AC%A0%E5%8E%9F%E7%A8%AE%E9%AB%98/dp/4839972745)を読んだのでアウトプットとして勉強中のRailsアプリの環境をDockerコンテナ上で作ってみようと思いました。
- 今から書く内容は、Dockerコンテナ上で動くRailsアプリケーションを配布（Github)できるようになるまでの流れを最速でやってみようと言うものです。（最速というか、最短の方が近いかもです）
- というのも、Githubで公開してるrailsのコードを実際に実行したいとなった時、開発環境でつまづくと本末転倒になってしまうのでは、だったらdocker使って親切に開発環境まで配布できたら親切なのでは？と思ったのがきっかけです。
:::note warn
ですが、、、いまだ勉強中で、Docker習いたてのほやほやなので温かい目で見ていただけたら嬉しいです😀
:::

- では、本題に入っていきます。
## 早速作ってみよう

### Railsアプリケーションの作成
- フォルダ作成
```bash
mkdir sampleapp_on_docker
cd sampleapp_on_docker
```

- プロジェクト作成
```bash
rails new sampleappondocker
cd sampleappondocker
```

- CRUD画面作成
```bash
rails generate scaffold article title:string content:string
```

- マイグレーション
```bash
rails db:migrate
```
- サーバー起動
```bash
rails s
```
- [localhost:3000](localhost:3000)にアクセスして動作確認

### Dockerfile docker-compose.ymlの作成

- Dockerfile
```dockerfile
FROM ruby:3.2.2

RUN mkdir /sampleapp
WORKDIR /sampleapp
COPY Gemfile /sampleapp/Gemfile
COPY Gemfile.lock /sampleapp/Gemfile.lock

RUN gem update --system
RUN bundle update --bundler

RUN bundle install

CMD ["rails", "server", "-b", "0.0.0.0"]
```
:::note warn
すでにDockerfile(production用)があるので、それの名前は他の名前(Dockerfile.prod)に変更しておきます）
:::

- docker-compose.yml
```yaml
version: '3'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/sampleapp
      - ./db:/sampleapp/db
    environment:
      - RAILS_ENV=development
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails db:migrate && bundle exec rails s -p 3000 -b '0.0.0.0'"
```

- コンテナ起動
```bash
docker-compose up
```
- [localhost:3000](localhost:3000)にアクセスして動作確認
- コンテナ停止
```bash
docker-compose down
```
:::note warn
Dockerfileとdocker-compose.ymlファイルはsampleappondocker配下においてください。
:::

- ここまでできたら、Githubに保存して完了となります。
- これで、Rails環境がないマシンでも、Githubからクローンして`docker-compose up`すれば、[localhost:3000](localhost:3000)で確認できます。（そのはず。。。）

## 最後に
実際のGithubURLを貼っておきますのでぜひお試しください。↓
[yasaigaoisi/sampleapp_on_docker](https://github.com/yasaigaoisi/sampleapp_on_docker)
今後やってみたいこととしては、今回は、物理マシンにもRails環境がある前提で実装していたので、Dockerコンテナ内で完結できるようにしたいです。（多分、バインドマウントとかちゃんと理解できてないので、ローカル上でプロジェクト作成とかやってました。そこが、Dockerコンテナ上でできれば、上手くいく。。。はず。。。なんかできそうな気がしてきましたね😃）
[解決済み]AWS EC2でデプロイしたWEBサイトがタイムアウトする！

**[解決しました](#解決20240723)**

# 目的
正常にデプロイを完了させて正常にWEBサイトを開きたい！

# 問題
デプロイしたWEBサイトにパブリック IPv4 DNSで開こうとするとタイムアウトしてしまう。

# 状況
昨日の時点では一応繋がりはしたがLaravelのエラーが発生し、
`SQLSTATE[HY000]: General error: 8 attempt to write a readonly database`
と言われていた。

今日はそのエラーを解決すべく、もう一度エラーを確認しようとインスタンスを起動したところタイムアウトしてしまった次第。

[こちらの記事](https://qiita.com/me-654393/items/504acfbb766eddbf1046)を参考にさせていただきデプロイ作業を進めてきていたので、もう一度心当たりのある箇所を読み返していた。
そこで`curl -s http://localhost | grep title`で動作確認を行ったところ、昨日まで`<title>Welcome to nginx!</title>`が出ていたところを今度は大量の文字列と`SQLSTATE[HY000]: General error: 8 attempt to write a readonly database`の文字。
穏やかじゃない…。やはりお前か…。

調べるとSQLが読み込み専用モードになっているので書き込みモードにすると解決するというので、見様見真似でMySQLのモードを確認してみた。
だが返ってきたのは「読み込みモードOFF」

行き詰まってしまったので再びPerplexityにエラー内容をぶつけてみた。

**「あなたが遭遇したエラーは、SQLiteデータベースに関連するもので、『読み取り専用データベースに書き込もうとした』という内容です。」**

SQLite！？
俺はMySQLで進めてきたんだぞ！？

見えてきた！！そうか、思えば今開発中にのプロジェクトは`.env`に関して何も構っていない。
見に行ってみるとやはりそうだ。
`DB_CONNECTION=sqlite`となっているではないか。
`.env`、`.env.example`の上記の項目を`mysql`に書き換え、正しいのかよくわからない方法でGitHubにPush！
さらによくわからない方法でAWSにPull！

そして再度動作確認をすると………
**`<title>DigitalKennel</title>`**
うおおおおおおおおおおおお俺が名付けたプロジェクト名だあああああああああああああ！！！！！！！！！！！

これはWEBサイトにも問題なく繋がるはず、いそげええええええええええええええええ！！！！！！！！

<br>
<br>
<br>

![SCR-20240722-piyw.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798584/d2d3268b-c523-fd36-daf4-77ae56859b46.png)

<br>
<br>

おわり

# 解決(2024/07/23)
結論から言うと決定的な原因はわかりませんでした。

おそらくですが、URLに`https://`で接続しようとして失敗していたのではないかと思います。
とはいえ以前も`http://`で接続しなおして失敗していたのですが、セキュリティグループでHTTPを許可した上で`https://`ではなく`http://`で接続したのは23日が初だったのかもしれません。
灯台元暗しですね…。
PythonとHTMLで簡単な掲示板を作ろう：Flaskで始めるWebアプリ開発入門

# はじめに
PythonとHTMLを使って簡単な掲示板アプリケーションを作成してみましょう。このチュートリアルでは、Pythonの軽量WebフレームワークであるFlaskを使って、基本的な掲示板を構築します。掲示板のフロントエンドにはHTMLを使用します。

# ディレクトリ構造
まず、以下のようなディレクトリ構造を作成します。

```
message_board/
│
├── app.py
└── templates/
    └── index.html
```

# 必要なライブラリのインストール
Flaskをインストールしていない場合は、以下のコマンドでインストールします。
```sh
pip install flask
```

# Flaskアプリケーションの作成
app.pyファイルを作成し、以下のコードを記述します。


```python:app.py
from flask import Flask, render_template, request, redirect, url_for

app = Flask(__name__)

# メッセージを保存するリスト
messages = []

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        # フォームからメッセージを取得
        message = request.form.get('message')
        if message:
            messages.append(message)
        return redirect(url_for('index'))
    
    return render_template('index.html', messages=messages)

if __name__ == '__main__':
    app.run(debug=True)
```
## コードの説明
### 1.Flaskのインポートとアプリケーションの作成:

```python
from flask import Flask, render_template, request, redirect, url_for

app = Flask(__name__)
```
Flaskモジュールをインポートし、Flaskアプリケーションのインスタンスを作成します。

### 2.メッセージの保存:
```python
messages = []
```
投稿されたメッセージを保存するためのリストを定義します。

### 3.ルートの設定:
```python
@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        # フォームからメッセージを取得
        message = request.form.get('message')
        if message:
            messages.append(message)
        return redirect(url_for('index'))
    
    return render_template('index.html', messages=messages)
```
* /ルートを定義し、GETおよびPOSTリクエストを処理します。
* POSTリクエストが送信された場合、フォームからメッセージを取得し、messagesリストに追加します。
* メッセージを追加した後、リダイレクトしてページを更新します。
* GETリクエストの場合、メッセージを含むテンプレートをレンダリングします。

### 4.アプリケーションの実行:
```python
if __name__ == '__main__':
    app.run(debug=True)
```
スクリプトが直接実行された場合、Flask開発サーバーを起動します。

# HTMLテンプレートの作成
次に、templatesフォルダにindex.htmlファイルを作成し、以下のコードを記述します。

```html:templates/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>掲示板</title>
</head>
<body>
    <h1>簡単な掲示板</h1>
    <form method="POST" action="/">
        <textarea name="message" rows="4" cols="50" placeholder="メッセージを入力してください"></textarea><br>
        <button type="submit">投稿</button>
    </form>
    <h2>投稿一覧</h2>
    <ul>
        {% for message in messages %}
            <li>{{ message }}</li>
        {% endfor %}
    </ul>
</body>
</html>
```

### アプリケーションの実行
上記のファイルを作成したら、ターミナルでアプリケーションを実行します。

```sh
python app.py
```
次に、ブラウザで http://127.0.0.1:5000/ にアクセスすると、掲示板が表示されます。メッセージを入力して投稿すると、ページがリロードされてメッセージがリストに追加されます。

## 画面表示結果
![スクリーンショット 2024-07-22 17.25.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75802/8af11148-cf3a-690d-868a-069f9427f30a.png)


# 終わりに
このチュートリアルでは、PythonのFlaskフレームワークとHTMLを使って簡単な掲示板を作成しました。次のステップとして、データベースを導入してメッセージを永続化する方法や、ユーザー認証機能を追加してみるのも良いでしょう。ぜひ、挑戦してみてください！
お菓子の詰め合わせ (paizaランク A 相当)　Python解説

# 自己紹介
僕のX：
https://x.com/e4h99rhQ7I24670
この記事でおかしなところがあれば教えてください。

# 問題　お菓子の詰め合わせ (paizaランク A 相当）
https://paiza.jp/works/mondai/a_rank_skillcheck_archive/school_hiking

# 感想
ビット計算、論理演算等知っていると楽だと思います。^^
知らないとかなり難しく感じるかもしれません
AtcoderだとB問題、diff200程度かなー

# 解説
この問題の肝はNの制約が厳しすぎるところです。(N <= 20)
この条件であれば、2^Nまで計算できます。
よって、とりあえず2^Nの計算オーダーの解法を考えればいいです。
一つのお菓子に対して買うか買わないかの二択である点から、全探索が2^Nのオーダーで計算できます。

## 実装で用いている計算方法
左シフト
----------
```python
1 << A
```
2^A乗の値を返す

論理積
----------
```python
A & B
```
A,Bどちらも１なら１を返す。それ以外は０を返す。


以下実装
--

```Python
N, X = map(int, input().split())
A = [int(input()) for _ in range(N)]

ans_money = 1 << 60
ans_num = 0

for i in range(1 << N):
    num = 0
    money = X
    for j in range(N):
        if i & (1 << j) == (1 << j):
            num += 1
            money -= A[j]
    if money < 0:
        continue
    if ans_num < num:
        ans_num = num
        ans_money = money
    elif ans_num == num:
        ans_money = min(ans_money, money)

print(ans_money)
```
【Rails】resourcesによるルーティング

# はじめに
Rails初学者の学習内容の備忘録です。
間違いや補足等あればご指摘いただけると幸いです。

今回はresourcesについて学習したのでまとめます。

# resourcesとは？
Railsのルーティングでよく使われるメソッドで、一般的なCRUD(Create,Read,Update,Delete)操作に対応するルートを自動生成します。

**resourcesを使わない場合**
 ```routes.rb
  get "posts", to: "posts#index"
  get "posts/new", to: "posts#new"
  get "posts/:id", to: "posts#show"
  post "posts", to: "posts#create"
  get "posts/:id/edit", to: "posts#edit"
  patch "posts/:id", to: "posts#update"
  delete "posts/:id", to: "posts#destroy"
  ```
resourcesを使わない場合は、上記のように書く必要がありますが

  **resourcesを使った場合**
```routes.rb
  resources :post
```
resourcesを使うと7つのアクションを1行で書くことができます。
よく使う基本的なやつは１行で書いちゃおうぜということですね。

# resourcesの使い方
使い方はroutes.rbの中で
```routes.rb
  resources :コントローラ名
```
とするだけです。また、

```routes.rb
  resources :コントローラ名, :コントローラ名
```
として複数のコントローラのルーティングを定義することも可能です。

**onlyとexcept**
特定のアクションのみを定義したい場合
```routes.rb
  resources :post, only: {:index, :show}
```
とすれば、indexアクションとshowアクションのみ定義されます。
逆に、特定のアクションを含めたくない場合は、
```routes.rb
  resources :post, except: {:index, :show}
```
とすれば、index、show以外のアクションが定義されます。

# まとめ
resourcesを使うことで、RESTfulなコードを効率的に設定でき、可読性も上がる。

**参考サイト**
[Pikawaka 【Rails】 resourcesメソッドを使ってルーティングを定義しよう！](https://pikawaka.com/rails/resources)
Promise配列処理の備忘録

# JavaScriptで複数Promise処理の備忘録
前提条件（Promise配列）
```JavaScript
const promises = [ promise0, promise1, promise2 ... ];
```

## `Promise.all( promises )`
* `promises`配列ですべての`Promise`が`resolve`
`then`に処理が移譲される。
コールバック関数の引数はもとの`promises`と同じ順番の各`Promise`で`resolve`された値の配列。
* `promises`配列で`reject`を検出
`catch`に処理が移譲される。
コールバック関数の引数は`reject`を検出した`Promise`のエラー。

## `Promise.allSettled( promises )`
常に`then`に処理が移譲される。
コールバック関数の引数はもとの`promises`配列と同じ順番の各`Promise`結果の配列。
* `resolve`が返される要素の場合の処理結果
{ status: "fulfilled", value: （`resolve`された値） }
* `reject`が返される要素の場合の処理結果
{ status: "rejected", error: （`reject`されたエラー） }

## `Promise.any( promises )`
* `promises`配列で`resolve`した結果がある場合
`then`に処理が移譲される。
コールバック関数の引数は最初に`resolve`された値。
* `promises`配列ですべて`reject`された場合
`catch`に処理が移譲される。
コールバック関数の引数はもとの`promises`と同じ順番の各`Promise`結果（`reject`されたエラー）の配列をerrors属性に持つ`AggregateError`オブジェクト。

## `Promise.race( promises )`
最初に解決した処理により分岐する。
* `resolve`された場合
`then`に処理が移譲される。
コールバック関数の引数は最初に`resolve`された`Promise`の値。
* `reject`された場合
`catch`に処理が移譲される。
コールバック関数の引数は最初に`reject`された`Promise`のエラー。
「平文でパスワード」の愚挙

先日、実際に遭遇した事例で閉口したことがありました。
（どちらのなんのシステムのことかは詮索しないでください。）

わたしはとあるCSVファイルを自動でとあるサーバへSCPで送る、というスクリプトを書こうとしておりました。
が、通信相手が冗長しており、いま1号機と2号機のどちらがアクティブなのかを確認するルーチンを組まねばなりません。
ただ、サーバ側では定期的に自分がアクティブなのか否かを確認するスクリプトがすでに動いているとのことでした。

依頼されたのがサービスイン直前で時間がなく、ほかのタスクも抱えていましたので極力手間をかけたくない、またテストのためにフェイルオーバーをしてもらうことはすでに難しいフェイズに入っていました。
そのため、こちらからCSVを送るのではなく、サーバ側に依頼してアクティブと判断されたサーバからCSVを取りに来てほしいとお願いした処、先方も余計な手間をかけたくないとのことで断られました。

で、その際に言われたことが、
「なんでSCPなんか使うんですか？FTPで良いじゃないですか。」
それに対して、いくら閉じたネットワークといえどもパスワードを平文で送るわけには行かない。PJにもセキュリティ監査があるはずですが、いまだにそんなものが許容されうるのか、と質問したところ、
「パスワード？　そんなのスクリプト内に平文で書けばいいじゃないですか。みんなそうやってますよ。」
とのお返事がありました。
確かにプログラムは動いてナンボではありますが、「平文でパスワード」などという暴挙の提案にいたたまれず、
「わたしは過去20年そんな方法で実装したことがないので、ちょっとやり方勉強してきますね。」と返しておきました。

社内にはプログラムを書くお仕事の方もたくさんいらっしゃいますし、インフラ事業部といえども簡単なスクリプトを書いて実装することは日常ありうるかと思いますが、あらゆる通信は可能な限り暗号化されるべきだと考えています。
たとえばいまどきhttpで公開されたサイトを誰が信用するでしょうか。
たしかに当該ネットワークはクローズドな環境ではありましたが、あまりの出来事にわたしの口もクローズしてしまいました。

余談ですが、本件はPJのもっとも上位のマネージャにこっそり報告しておきました。
こちらのマネージャさんはわたしの10年来のお知り合いで何度も一緒に苦労したことがある方ですので「適切に対処します」とのお言葉をいただきました。
じゃんけんの手の出し方 (paizaランク A 相当)　Python解説

# 自己紹介
僕のX：
https://x.com/e4h99rhQ7I24670
この記事でおかしなところがあれば教えてください。

# 問題　URL
https://paiza.jp/works/mondai/a_rank_skillcheck_sample/janken

# 感想
Aランク問題相当にしては難しかった。(´;ω;｀)
（ただ僕の考察が下手なだけという説もある）
Atcoderでdiff200くらい

# 解説
N, Mの制約がそれほど大きくないので、へんな工夫をせずに考察をする。
ここで、なにも考えずに全探索をするとO(3^N)となりTLEする、
ここでの注目ポイントとしてはじゃんけんで出す種類ごとの数が決まれば、後は最大で勝てる順番に並び替えるのは簡単であるであること。

つまり、相手が出してきたものの順番は一切考えなくてよい。

ここで、自らがパーを出す回数をi回とすると、
チョキを出す回数は（M-5i)/2回になる。
グーを出す回数はN-i-(M-5i)/2回。

ただし、小数点以下が存在するときは、考えない。（continueする）

あとは最大で勝てる回数をそれぞれmin()をとってカウントするだけ。

# 実装
自分が出す種類ではなく、相手が出したものの種類数でカウントしている。
例えば相手がグーなら指を５本消費など。
```Python
N, M = map(int, input().split())
S = input()
ans = 0
G = 0
C = 0
P = 0

for i in range(N):
    if S[i] == 'G':
        G += 1
    elif S[i] == 'C':
        C += 1
    else:
        P += 1

for i in range(M//5+1):
    num_G = i
    num_P = (M-5*i)//2
    num_C = N-num_G-num_P
    if 5*num_G+2*num_P != M or num_G+num_P > G+P+C:
        continue
    ans = max(ans, min(num_P, P)+min(num_G, G)+min(num_C, C))
print(ans)
```
AWS Cloud Questをやってみた

# AWS Cloud Questをやってみた
https://aws.amazon.com/jp/training/digital/aws-cloud-quest/

- AWS Skill Builderのアカウントを作成
- 認証後、Cloud Questを開始
https://explore.skillbuilder.aws/learn/course/17553/play/92082/cloud-quest-cloud-practitioner-wopureisuru


# よくわからないまま開始
- 初めの困っている人に話しかけてみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546030/a3b138fa-8e46-1634-b61d-d686b6620536.png)
- 最後まで会話をすすめると、学習目標が表示されていき、「開始」ボタンが登場したので、「開始」してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546030/36f1348d-5fb1-6d33-adcc-0d6530328193.png)
- 学習が開始されたので、矢印で読み進めます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546030/2aeb8d34-3d28-f870-29ab-a8c6b2eba623.png)
- 計画が表示されました。特にやることがなくて、右下のボタンから「3実践」にすすんでみた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546030/a057b2b7-6620-f1c9-0fab-5600278b260e.png)
- 動画が再生されたあとに、下記の画面がでるのでステップに従ってみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546030/02e792c6-37b7-0b22-737a-28cf67a8e900.png)
- ラボを開始すると、新しいタブでコンソールホームが開く。（数分かかったりする）どうやらこのAWSの管理画面でアカウントを変えてはいけないようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546030/45a7e6c0-ed24-8f87-4fee-de966f114d88.png)
- ラボを開始すると、カウントダウンが始まっていて、ちょっと焦る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546030/688e965f-8ba1-0426-a05e-5b7d13f38e4d.png)
しかし、言語こそ違うが、全く画面は同じなので手順に従ってすすめると静的サイトがホストされた様子。そのまま、[4DIY]に進むと、先ほどと同様動画が再生されたあとに、実践。
- ここまで来て、今までやってきた方法を繰り返すのね！ということに気づいた。
- 順調に先ほどの手順にならってこなした後、検証フォームにバケット名を入力し、「検証」をしてみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546030/d9d2d8cc-6e2a-f682-059d-734b649333d4.png)
- しばらく、「検証中」とでたあと（数秒）、お疲れ様でしたと表示されたので「終了」する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546030/58a78699-6115-6589-c96f-7fe3a4479e2b.png)
- 最初の画面にもどったので、「！」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546030/ffaa8b5b-7bd4-65c0-8f10-7e6f9235305e.png)
- なんか選べってでてきた～
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546030/f3793ce0-0777-88ce-3463-ff5dd9f9032e.png)
- その後、花火が上がってレベルアップしましたｗ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546030/9a65bae4-93e3-09a9-6b81-722f83e525cf.png)

- とりあえず、続けてみます。
Ansibleのインストール

ansibleのモジュールを活用するため構築。

### 環境
仮想化：VMware workstation-pro15
ホスト：Windows10
ゲスト：ubuntu22.04.3TLS

### Ansibleのインストール手順

   ``` sh:パッケージリストの更新
   sudo apt update
   ```

   ``` sh:ソフトウェアプロパティの共通ツールのインストール
   sudo apt install software-properties-common
   ```
   
   ``` sh:AnsibleのPPAをシステムに追加
   sudo add-apt-repository --yes --update ppa:ansible/ansible
   ```
Ansibleの公式PPA（Personal Package Archive）をシステムに追加。これにより、Ansibleの最新版をインストールできる。
   ``` sh:Ansibleインストール
   sudo apt install ansible
   ```

   ``` sh:バージョン確認
   ansible --version
   ```

※Ansibleがインストールされているマシンから管理機器へSSHでアクセスできる必要がある。

### Python 3のpipをインストールする

Ubuntu 18.04以降では、Python 3がデフォルトのPythonバージョンのためPython 3用の`pip`をインストールする。
``` sh:pipインストール
sudo apt update
sudo apt install python3-pip
```

このコマンドは、システムのパッケージリストを更新した後、`python3-pip`パッケージをインストールします。

### インストールの確認

``` sh:バージョン確認
pip3 --version
```
### CiscoのNexusやCatalyst、JuniperのMX、EX、QFX、Linuxサーバー、NetboxなどをAnsibleで管理する場合のモジュールをインストール

- **Cisco Nexus向け**: `cisco.nxos`
- **Cisco Catalyst向け**: `cisco.ios`
- **Juniper向け**: `junipernetworks.junos`
- **Linuxサーバ向け**: `ansible.builtin`内のモジュールでほとんどの作業が可能。
- **Netbox向け**: `netbox.netbox`

これらはAnsible Galaxyを通じてインストールする。

``` sh:モジュールをインストール
ansible-galaxy collection install cisco.nxos
ansible-galaxy collection install cisco.ios
ansible-galaxy collection install junipernetworks.junos
ansible-galaxy collection install netbox.netbox
```

### 事前にインストールしておくと良いライブラリ

- **Pythonライブラリ**: AnsibleはPythonで書かれており、特定のモジュールやプラグインには追加のPythonライブラリが必要。ここでは`netmiko`、`ncclient`、`paramiko`、`requests`をインストール。

``` sh:ライブラリをインストール
pip3 install netmiko ncclient paramiko requests
```



### ライブラリのインストール先へのパスを通す

1. ユーザのホームディレクトリの`.bashrc`ファイルを編集し、ファイルの最後に以下の行を追加

```sh:パスを通す
export PATH="$HOME/.local/bin:$PATH"
```

``` sh:変更の有効化
source ~/.bashrc
```
★勉強メモ


・SFとESBの認証　OAuthのJWTフロー
・ファイル言及、←→ESB、新システムマーク、デプロイ（MultiOrgだと二重でテストや反映が必要）　
・同期非同期の選択理由
　　→画面に結果を待つ必要性
　　→疎結合、対向が障害時にSFの入力がとまってしまう。　→仮に対向障害時はESBでリトライ、だめならアラートあげて保守対応


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/fd11ea4b-35a5-b526-23dd-2e61e709cde5.png)

右クリックで画面動かす、左スクロールは拡大・縮小


★インテグレーションパターン
リモートプロセスの呼び出し
　同期　　リクエスト&レスポンス
　非同期　ファイア&フォーゲット


https://qiita.com/nori83/items/a99c9cf48ba35ab653aa

https://qiita.com/nori83/items/095055bcaa812605960f

https://qiita.com/nori83/items/40921b1df17143f70d0b

https://qiita.com/nori83/items/921d3f1d56b84b4afe6c

https://qiita.com/nori83/items/05bf5be31c56244926ff

https://qiita.com/nori83/items/78948787a1729062d2db

https://qiita.com/nori83/items/bc32c9a4621087ad40fa

https://qiita.com/nori83/items/be3e22119339f16f6431

https://qiita.com/nori83/items/0ac04913a23dc77ee85f

https://qiita.com/nori83/items/e54c9451c12ab87e4817

★代理認証の特徴
・SAMLが使えない場合に代理認証を利用。社内の認証サーバを使いたいとか、SAMLより古い規格を使いたい（SAMLが対応していない）場合など。
・認証のWebサービスはSOAPである必要あり。
・TLSを使うこと。
・RESTは使えない。
・統合IDも使わない。（統合ID使うのはSAML）
・SFDCサポートに依頼して有効化してもらわないと代理認証は使えない。
https://wa3.i-3-i.info/word11616.html

★更新トークン
・これで新しいトークンを要求する。
・アクセストークンは有効期限があるため、期限切れたら更新トークン使って再取得が必要。

★FSLのモバイルで出来ること
・色味やロゴ変更、地理情報などの精度設定
・プッシュ通知
・デイビュー（その日の作業を見る）
・フロー
・ナレッジ
・Chatter
・オフライン
・バーコードスキャナー
・サービスレポート（作業指示から出力可能）

★ディスパッチャーが出来ること
・スケジュール管理／最適化
・ガントチャートで稼働をTrack
・ロケーションに応じて分割
・Chatter


 その他コメント
・APIの同時接続数（20秒以上）：25本
・APIコールのタイムアウト：10分
・APIコール数は、買える！＼(＾o＾)／:high_brightness:

Moblie Publiser for Community
◆ ノンプログラミングでモバイルアプリ構築可能。
　⇒Communityなどはコミュニティビルダーでサイトを作り、ポイント＆クリックでカスタムモバイルアプリ化が可能。
　　【手順】SFに問いあわせ⇒ビルダーで構築⇒ストアにプロジェクト登録（配信用のアイコン画像や説明等）⇒管理パッケージをインストール（プッシュ通知など実行する仕組みなど包含）⇒ベータ版でテスト⇒OKならSubmit⇒審査OKなら掲載
◆ 毎回のログインが不要で、Push通知、位置情報、FaceId／TouchIdなどモバイルデバイスのメリット活用が可能。
◆ 要ライセンス?　⇒　調べたがHitしない。追加コスト必要なはずだが。

◆ SF社にてStoreへの配信手続きを実施してくれる。
◆ Payground環境で試行可能。（ただPaygroundだとアイコンなどのブランディングなどは試せない。）
◆ コミュニティビルダーでの追加／変更／削除は、モバイル側に適応可能。
※MobliePubliser for Communityは実態はハイブリッドモバイル
◆ LWC対応。1組織5個。有料アプリ／アプリ内課金は不可。Push通知に上限あり。
　 Push通知はChatter関連やカスタムの通知、縦表示のみサポート

  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/a029b949-ceef-43cf-a4c2-808261d7028a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/f7515946-93a3-ae44-dd91-5931a8cc3bcd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/6adb2220-042e-b4ae-67b4-19cc4af8cb93.png)


SalesforceConnect
ポイント①：1時間あたりのCallOutは2万回（緩和はサポートに要相談）
ポイント②：1時間あたりの新規に取得できる行は10万（レポートなどを使わない選択をすればこの制限は撤廃可能だが、ポイント①の制限はいずれにせよ撤廃されない。）
ActiveDirectoryからBitlocker回復キーを一覧取得する方法

Crowdstrikeがやらかしてくれたので、膨大な数のコンピューターオブジェクトからBitlocker回復キーを一覧取得する必要が出てきました。
少し遅れましたが、「Bitlocker回復キー」を一括取得するPowershellを記載します。


```
Get-ADObject -Filter "objectclass -eq 'msFVe-RecoveryInformation' -and msFVE-RecoveryPassword -like '*'" -Properties * |
Select-Object CanonicalName,msFVE-RecoveryPassword
```
または
```
Get-ADObject -Filter {objectclass -eq 'msFVe-RecoveryInformation' -and msFVE-RecoveryPassword -like '*'} -Properties * |
Select-Object CanonicalName,msFVE-RecoveryPassword
```
※なぜか msFVE-RecoveryPassword をシングルクォーテーションで括るとエラーになります。

Get-ADComputerだと取れないのは盲点でした。(objectclass 指定して情報抜くことなんてほぼやる機会がない・・・）
あと、複数キーがある場合はCanonicalNameに[ホスト名+取得時刻]となり複数行として記載されます。
基本的には時間が一番新しいものを使うかと思います。
LLMとRAGをサクッと体験できるハンズオンや記事まとめ【技術選定準備や好奇心を満たしたい方へ】

勉強しながら随時更新していきます。

## AWSを用いた生成AI構築(CFnデプロイ込みで1時間)
AWS公式の生成AI体験ワークショップ。
ぽちぽちしてCloudFormationをdeployしてたらchat botなどが丸っと構築されている。

ひとまず生成AIを実際に体験したい人にはおすすめ。CFnテンプレートの他にCDKによるワークショップも用意されている。

https://catalog.workshops.aws/generative-ai-use-cases-jp/ja-JP

　
生成AI体験ワークショップを進める上での詰まりポイントは下記に簡潔にまとめています。

https://qiita.com/tnktnk/items/b69edbd0e70443323a51

## LLM(chatGPT)のAPIを叩く(10分)

https://qiita.com/tnktnk/items/f70ab00ffd6056629708


## チャンク分解
https://zenn.dev/yuta_enginner/articles/9f4c34b36193c0

pip installしたものたち

```
pip install langchain
pip install langchain_community
pip install langchain_openai
pip install chromadb
```

詳細は上記記事を読んでほしいのですが、私はこんな感じのコード書いて動作確認しました。

``` sample.py
import os
from openai import OpenAI
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings

client = OpenAI(
    api_key=os.environ.get("OPENAI_API_KEY"),
)

# ------ado_wikiをコピーしてここに貼り付け------

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000, chunk_overlap=200
)

all_splits = text_splitter.create_documents([ado_wiki])

# for i,doc in enumerate(all_splits):
#     print(f'--------------------------{i}--------------')
#     print(doc.page_content[:500])
#     print('・・・')
#     print(doc.page_content[500:])

vectorstore = Chroma.from_documents(
    documents=all_splits,
    embedding=OpenAIEmbeddings(model='text-embedding-3-small')
)

print(vectorstore.similarity_search_with_score('ユニバーサル・スタジオ・ジャパンのイベント楽曲は?'))

```
Podman環境を作ろう

# 1. はじめに　DockerではなくPodmanを利用する理由

コンテナ技術といえば多くの人がDockerを思い浮かべるでしょう。しかし、ここではPodmanを使用します。以下に、DockerではなくPodmanを利用する利点を説明します。

## 1-1. デーモンレスアーキテクチャ

Dockerはデーモン（長時間動作するバックグラウンドプロセス）を使用してコンテナを管理しますが、Podmanはデーモンを使用しません。これにより、次の利点があります：
- **セキュリティの向上**：デーモンが不要なため、システムの脆弱性を減少させ、攻撃面を縮小します。
- **シンプルなプロセス管理**：各コンテナは独立したプロセスとして実行されるため、システムの標準ツールで簡単に管理できます。

## 1-2. ルートレスコンテナ

Podmanはルートレス（非特権）モードでコンテナを実行できます。これにより、管理者権限を持たないユーザーでもコンテナを操作でき、安全性が向上します。特に以下の点でメリットがあります：
- **セキュリティの強化**：管理者権限を必要としないため、特権昇格攻撃のリスクを低減できます。
- **マルチユーザー環境に最適**：複数のユーザーが同一システムでコンテナを実行する場合に、各ユーザーの権限を分離して安全に運用できます。

## 1-3. Docker互換性

PodmanはDocker CLIと高い互換性があります。ほとんどのDockerコマンドをPodmanでそのまま使用できます。これにより、Dockerからの移行がスムーズに行えます。また、以下の点も利点です：
- **学習コストの低減**：既にDockerに慣れているユーザーは、ほぼそのままの知識でPodmanを利用できます。
- **既存ツールの活用**：Docker用に作成されたスクリプトやツールを大幅な変更なしで利用できます。

## 1-4. Kubernetesとの親和性

PodmanはKubernetesとの統合がスムーズです。Podmanで作成したコンテナやポッドは、そのままKubernetesに移行できます。これにより、開発から本番環境へのデプロイが一貫して行えます。

## 1-5. Docker Desktopのライセンス問題

2021年8月以降、Docker Desktopのライセンスは変更され、以下のような制約が追加されました：
- **商用利用の制限**：企業や大規模な組織がDocker Desktopを商用目的で利用する場合、有料のサブスクリプションが必要です。
- **規模による制限**：非商用利用であっても、従業員数が250人以上、または年間収益が1000万ドル以上の組織は、有料のサブスクリプションが必要です。

このライセンス変更により、多くの組織で以下のような課題が生じています：
- **コストの増加**：大規模な組織ではライセンス費用が大きな負担となる可能性があります。
- **ライセンス管理の複雑化**：利用者数や収益に応じてライセンスを管理する必要があり、運用が複雑化します。

一方で、Podmanはオープンソースであり、商用利用に関する制限がありません。これにより、以下の利点があります：
- **コストの削減**：ライセンス費用を気にせずに利用できるため、コストを削減できます。
- **自由な利用**：商用、非商用を問わず自由に利用できるため、開発から本番環境まで一貫して利用できます。


# 2.環境の概要

|No.|ソフトウェア分類|ソフトウェア|用途|備考|
|--|--|--|--|--|
|1|OS|Windows 11|主要なデスクトップオペレーティングシステム|僕が使っているOSだから|
|2|仮想化ソフトウェア|WSL (Windows Subsystem for Linux)|Windows上でLinux環境を提供する仮想化ソリューション|軽量で高性能な仮想化が可能|
|3|コンテナソフトウェア|Podman|デーモンレスで動作するコンテナエンジン|Docker互換性が高く、セキュリティが強化されている|
|4|コンテナ簡易オーケストレーター|Podman Compose|複数のコンテナの管理とオーケストレーションを簡易に行うツール|Podman単体では管理が難しい複数コンテナの連携を簡素化|


# 3.環境構築

すでに導入済みのWindowsにPodmanをインストールする手順を示す。

# 3.1 WSLインストール

以下の手順はPowerShellを管理者として開き実行します。

1. WSL2をデフォルトバージョンとして設定します。

```sh
wsl --set-default-version 2
```

2. 以下のコマンドを実行してWSLを有効にします。
```sh
wsl --install -d Ubuntu-24.04
```
## Ubuntuの初期セットアップ

1. Ubuntuを初めて起動する(通常インストール時)と、以下のようなプロンプトが表示されるので、指示に従ってユーザー名とパスワードを設定します。

```sh
Enter new UNIX username: <your-username>
New password: <your-password>
Retype new password: <your-password>
```

2. システムを最新の状態に更新します。
```sh
sudo apt-get update
sudo apt-get upgrade -y
```

# 3.2 Podmanインストール

1. WSL上のUbuntuで以下のコマンドを実行し、Podmanをインストールします。

```sh
sudo apt-get -y install podman
```

2. Podmanが正しくインストールされているか確認します。

```sh
podman --version
```

# 3.3 Podmancompose インストール

1. 以下のコマンドを実行してPodman Composeをインストールします。

```sh 
sudo apt-get install podman-compose -y
```


2. Podman Composeが正しくインストールされているか確認します。
```sh
podman-compose --version
```

以下のようにVersionが示されれば完了です。お疲れさまでした。

```
podman-compose version 1.2.0
podman version 4.9.3
```
railsでテーブルを関連付けした際のwhereでのカラムの指定の仕方について

- includes
- preload
- eager_load

などで関連テーブルを読み込んだ際に、whereメソッドから関連テーブルのカラムを参照したい場合はreferencesキーワードを使って関連テーブル名を宣言する必要がある
```rb
 User.includes(:posts).where("posts.name = 'foo'")
　　# Doesn't JOIN the posts table, resulting in an error.  
 User.includes(:posts).where("posts.name = 'foo'").references(:posts)  
 # Query now knows the string references posts, so adds a JOIN
```

`joins`メソッドを使う際は不要だと思うが、`incluedes`などの関連付けをeager loadingするメソッドを採用した際にはreferencesメソッドの出番になる感じだと思う
https://api.rubyonrails.org/v7.1/classes/ActiveRecord/QueryMethods.html#method-i-references

joinsメソッドを使った際はこんな感じでwhereを指定できる
```rb
time_range = (Time.now.midnight - 1.day)..Time.now.midnight
Customer.joins(:orders).where('orders.created_at' => time_range).distinct
```
https://railsguides.jp/active_record_querying.html#%E7%B5%90%E5%90%88%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%A7%E6%9D%A1%E4%BB%B6%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B
【Excel Addin】Execute multiple writebacks with one button

# Introduction #
I would write a topic regarding how we can execute multiple Sharperlight writeback defined on an Excel worksheet with one button.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/1fcfb6c5-58c9-2864-793e-b535b028c7e1.png)


# Common method #
We basically prepared a table with data and defined a Sharperlight writeback with it to load data to the table in the connected database. There may be some cases we define multiple Sharperlight writeback, and we may want to have only one button to kick them in all.  

The below image shows that there are two tables, each with a Sharperlight writeback defined.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/6c7a64e2-73f2-dfd8-0790-a0e150c03f82.png)
There are two execution buttons defined, and we have to push those one by one.

# Tasks Template #
Let's start considering to make changes so that we can use only one button to execute the two Sharperlight writeback next to next.

Select Cell N2, and choose **Other** => **Run Tasks Template** from the Sharperlight ribbon.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/f4695919-62f9-3bcd-ac37-a0b95a980589.png)
A table and a button would be populated like this.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/cf3a6197-5278-80ed-3f48-d98e64b845a6.png)
Add another row to the table.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/c9254926-b3d3-d4b7-5f25-444784fbc163.png)

## Set values to the tasks template ##
#### Filename ####
It can be blank as we use the current active file.
#### Worksheet ####
Type in the current worksheet name to the column.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/213c1dac-0c4f-1284-51db-acfc467c5f7e.png)
#### Writeback ####
Find the name of Sharperlight writeback saved from the writeback dialog, and type in the writeback name into the writeback column.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/9abe9ce2-c0ce-2238-1691-1d65d7603b5c.png)
#### Recalculate ####
Accepts a TRUE/FALSE boolean value or a blank cell, the recalculation will occur before the writeback.
This time I leave it blank.
#### Save Workbook ####
Accepts a TRUE / FALSE boolean value or a blank cell, the save will be actioned after the recalculation and/ or writeback.
This time I leave it blank.

## Run the tasks ##
We set the value for the template so far like this, and it's time to run the template now.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/59185a60-a2e6-37a5-2989-0bc51f8ebde5.png)

Click **Run Tasks** button, the tasks would be executed from the top and we shoud see this.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/94a72009-48b1-27a8-837f-16332d427609.png)

# Conclusion #
This is a simple option, but you may be find it is useful.
The writeback can be the other sheets, even in the other workbooks.
Please try doing it to find the way which makes your work better.
Azure と AWS の CDN サービスの主要な違いを個人的に比較

AWS の CDN サービスといえば CloudFront ですね。

これに近い機能を持つ Azure の CDN サービスは Front Door(Standard/Premium)である理解です。

両者の違いを個人的な観点で比較してみます。

## 1 つのリソースで複数のドメインを管理する方法

Azure Front Door は Amazon CloudFront と比較して、より階層的な構造を持ちます。この違いは、それぞれのサービスの特徴と利点を反映しています。

### Azure Front Door(Standard/Premium)

1 つの Front Door リソース(プロファイル)に複数のエンポイントを追加できます。
また、それぞれのエンドポイントに対して複数のカスタムドメインを追加できます。

## Amazon CloudFront

1 つの CloudFront 配信（ディストリビューション）に対して複数のドメイン名（CNAMEs）を関連付けることができます。
したがって、1 つの CloudFront リソースで複数のドメインをサポートすることが可能です。

## WAF 部分に固定費がかかる

### Azure Front Door(Standard/Premium)

Azure は 1 つの Front Door を構築すると、Standard の場合 `$35/月` 、 Plemium の場合 `$330/月` の固定費がかかります。

https://azure.microsoft.com/ja-jp/pricing/details/frontdoor/#pricing

Premium の料金は WAF の料金も込みなので、料金面を考慮すると 1 つの Front Door にできるだけ多くのドメインを含めたくなりますが、そうすると IaC の管理が煩雑になっていきますので悩ましいです。

WAF が不要な場合の選択肢：

1. [Azure CDN](https://azure.microsoft.com/ja-jp/pricing/details/cdn/): 純粋な CDN サービスで、基本的に従量課金制です
1. Azure Front Door Standard: WAF なしで利用可能ですが、固定費は発生します

Front Door を使用する場合、CDN だけでなく WAF に対する固定料金も支払うことになります。

### Amazon CloudFront

AWS の場合、CDN(= CloudFront)と WAF は別々で用意されます。

CloudFront の場合、料金は基本的に従量課金です。

https://aws.amazon.com/jp/cloudfront/pricing/

WAF の料金は選択するリソースタイプによって変動し、「Web ACL」や「ルール」を選択すると固定費がかかります。

https://aws.amazon.com/jp/waf/pricing/

AWS のアプローチでは、必要な機能に対してより細かく料金を支払うことができます。

## セキュアにオブジェクトストレージと接続する手段

急に具体的な話ですが、オブジェクトストレージに対してインターネットからのアクセスを拒否し、CDN のみからアクセスさせる構成を提供する手段が全く異なるので整理します。

### Azure Front Door(Standard/Premium)

オブジェクトストレージ = Azure Blob Storage と捉えると、Standard の Azure Front Door に解決策がありません。

Azure Front Door Standard の場合は Azure Blob Storage のパブリックエンドポイントを介する構成のみ可能です。

Azure Front Door Premium の場合は Private Link を構成することで対応可能です。

https://learn.microsoft.com/ja-jp/azure/frontdoor/private-link

ただし、Private Link が構成可能なリージョンに制限があるため注意が必要です。

### Amazon CloudFront

オブジェクトストレージ = Amazon S3 と捉えると、オリジンアクセスコントロール (OAC)を使用することで対応可能です。

https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html

OAC を使用する際は、S3 バケットポリシーの適切な設定も必要です。
Vim 9.1 patchダイジェスト (更新停止のお知らせ)

### お知らせ
[2017/03](https://qiita.com/h_east/items/23cd0d10932505072e6b) から [2024/06]() までの7年4か月の間、Vim patchダイジェストをお送りしてきましたが、必要性が薄れてきたので更新を停止します。

Vim 9.1 リリース以降の機能追加/仕様変更は、Vimのhelpに随時追記されており、Vimから以下のコマンドで参照することができます。

```vimscript
:h version-9.2
```

日本語訳は、vim-jpの[help - Vim日本語ドキュメント](https://vim-jp.org/vimdoc-ja/)で参照できます。
- [version-9.2](https://vim-jp.org/vimdoc-ja/version9.html#version-9.2)

以上、ありがとうございました。
選択したユーザのリンク設定を自動化してみますが... お決まりの... できません


脱PPAPを狙って、Power Automateで選択したユーザのリンク設定を自動化してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/6daea0ff-4c45-993c-f2fd-5aca947095b3.png)

さくっと、ここまで書いてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/f44b15d8-43d5-05bd-cd59-9246aae7ef63.png)

Power Automateの名前が変ですが...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/90e44a01-fbe9-8797-d1ad-ece27ce43174.png)

特定のユーザでなく、全員になってしまいまいましたね。　メールアドレスではない？


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9f76b013-5c7b-ef95-78b8-a765469e5ea3.png)

エラーは出てないけど...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/20e7680b-b3af-8bec-6c66-7c835e3ab62e.png)

できないようなことが回答されている...

+ [Create share link of onedrive folder to specific person](https://powerusers.microsoft.com/t5/Using-Flows/Create-share-link-of-onedrive-folder-to-specific-person/td-p/477355)
+ [Create a sharing link for a file or folder - Link scope](https://powerusers.microsoft.com/t5/General-Power-Automate/Create-a-sharing-link-for-a-file-or-folder-Link-scope/td-p/391757)


specific personを使ってみても、はやりできないです。

# 何かある？



Hi I got this to work using LinkKind 6 and Role 7 to send a link with view and block download - Linkkind 7 chucks up a badgateway error.

Is there a way to do this so in the Enter Email box a user can specify multiple emails and a link generated for each users email entered 

理解できません。

[Create sharing link for a file or folder in SharePoint for specific people](https://ideas.powerautomate.com/d365community/idea/85c4cb3a-b169-4c71-acd9-c8ae48947f28)

scopeに 7をセットしてみた

```Json
{
    "host": {
        "connectionReferenceName": "shared_onedriveforbusiness",
        "operationId": "CreateShareLinkByPathV2"
    },
    "parameters": {
        "path": "/ブック 1.xlsx",
        "type": "View",
        "scope": "7"
    }
}
```

エラーですね。

```Json
{
  "status": 400,
  "message": "[parameters] Cannot convert the literal '7' to the expected type 'Edm.String'.",
  "source": "api.connectorp.svc.ms"
}
```


Edm.Stringって？

以下をみると、テキストデータってなているけど...

https://learn.microsoft.com/ja-jp/rest/api/searchservice/supported-data-types

数字の７にしてみたけど同じエラーですね。

```Json
{
    "host": {
        "connectionReferenceName": "shared_onedriveforbusiness",
        "operationId": "CreateShareLinkByPathV2"
    },
    "parameters": {
        "path": "/ブック 1.xlsx",
        "type": "View",
        "scope": 7
    }
}
```
確実に操作を行ってもらうという気配り

示唆に富む出来事があったので注意喚起ついでに展開します。

postfixのmain.cfの編集方法をメールにてやり取りしていて、
質問者を通じて「このように編集しなさい」という内容を教えてもらいました。
メールは返信を行うとき設定により引用符がはいるのと、1行の文字数制限により強制改行が入ることがありますね。
実際の作業者には質問者からそのメールのコピーがそのまま渡りまして、肝心のmain.cf編集箇所が引用符と改行だらけで、大変読みにくいものとなってしまい、作業者は編集を誤ってしまいました。

作業者はmain.cfの編集に明るくないからこそ、質問者を通じてメールでやり取りしていたわけで、せっかく回答が得られてもそれが正しく反映されないと意味がありません。
質問者は手間を惜しんで回答者とのやり取りをそのまま転送して、回答を伝えるという仕事を完了したつもりになっていたのでしょう。

人に何かを伝えるときはその人に最大限わかりやすく送ってあげることが大切だということが学べる出来事でした。
シェルスクリプト 正規表現の有効性検証方法

## 概要

Goなどの高級言語で正規表現を使用する時には、正規表現が有効なものかどうか無意識にでも判別していると思います。

* [MustCompile](https://pkg.go.dev/regexp#MustCompile)
    * 正規表現が正しくない場合はプログラムを強制終了する
* [Compile](https://pkg.go.dev/regexp#Compile)
    * 正規表現が正しくない場合はエラーとなる

今回は、シェルスクリプトで正規表現が本当に正しい正規表現なのかチェックする方法について調べてみました。


## `grep`コマンドを使用する方法
`grep`コマンドを使って正規表現が適用可能かどうかを確認できます。`grep`は正規表現が無効であればエラーメッセージを出力します。

```sh
#!/bin/bash

regex="$1"

# テスト文字列
test_string="test"

# 正規表現をテストするための関数
function test_regex {
    echo "$test_string" | grep -E "$regex" > /dev/null 2>&1
    if [ $? -eq 0 ]; then
        echo "正しい正規表現です。"
    else
        echo "無効な正規表現です。"
    fi
}

# 正規表現をテスト
test_regex
```

### `awk`コマンドを使用する方法
`awk`も正規表現の有効性を確認するのに使えます。無効な正規表現の場合、エラーメッセージが表示されます。

```sh
#!/bin/bash

regex="$1"

# テスト文字列
test_string="test"

# 正規表現をテストするための関数
function test_regex {
    echo "$test_string" | awk -v regex="$regex" 'BEGIN { if (match("", regex)) exit 1 }'
    if [ $? -eq 0 ]; then
        echo "正しい正規表現です。"
    else
        echo "無効な正規表現です。"
    fi
}

# 正規表現をテスト
test_regex
```

## `perl`コマンドを使用する方法
`perl`も正規表現の有効性をチェックするために使用できます。

```sh
#!/bin/bash

regex="$1"

# 正規表現をテストするための関数
function test_regex {
    perl -e "qr/$regex/" 2> /dev/null
    if [ $? -eq 0 ]; then
        echo "正しい正規表現です。"
    else
        echo "無効な正規表現です。"
    fi
}

# 正規表現をテスト
test_regex
```

## `sed`コマンドを使用する方法
`sed`も正規表現の有効性を確認するために使えますが、`sed`の正規表現は若干の違いがあるため注意が必要です。

```sh
#!/bin/bash

regex="$1"

# テスト文字列
test_string="test"

# 正規表現をテストするための関数
function test_regex {
    echo "$test_string" | sed -E "s/$regex//" > /dev/null 2>&1
    if [ $? -eq 0 ]; then
        echo "正しい正規表現です。"
    else
        echo "無効な正規表現です。"
    fi
}

# 正規表現をテスト
test_regex
```
ACCESSでフォームを作ってVBA連動:ボタン押すとクエリ実行するサンプル

## 手順1: データベースの作成
Microsoft Accessを開き、新しい空白のデータベースを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/e570bee9-06ce-243d-f3f5-5a21d4afb753.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/e2123510-f09e-44fb-8623-55dc6d5146fc.png)

## 手順2: テーブルの作成
テーブルを作成し、必要なフィールドを追加します。例えば、SampleTableという名前のテーブルを作成し、以下のフィールドを追加します：
ID (オートナンバー型)
Name (短いテキスト)
Age (数値)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/e4aee0db-b185-7d56-6b9a-eb7aebb2236e.png)

## 手順3: クエリの作成
クエリデザイナーを開き、新しいクエリを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/1649e8db-6793-ce72-4e41-225db74d27e0.png)

クエリの内容を設定します。例えば、SampleTableのすべてのレコードを選択するクエリを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/1a46f9ca-0da9-9146-4ffd-82d2ce8fa63d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/9a720f97-34e3-decc-06e5-6b449ddf8fb9.png)

クエリに名前を付けて保存します。例: SelectAllQuery
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/1cad14ff-22dd-6d27-c9e0-965d0c8281b8.png)
↓ Ctrl +　S
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/cde36e62-de41-2d23-3bf6-ca5265d1dd3f.png)



## 手順4: フォームの作成
フォームデザイナーを開き、新しいフォームを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/f9575b59-480f-94f2-72b0-2f760ed8fed2.png)

フォームにボタンを追加します。ボタンに名前を付けます（例: btnRunQuery）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/f3627114-ed92-fd91-9397-e90d16e2016a.png)
↓テキスト編集
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/ec106fc0-76e2-45c3-cfa1-da2f5f970beb.png)
↓ボタンの名前を設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/d28c4337-48cb-a4f0-e560-436ff1904fb2.png)



## 手順5: VBAコードの追加
フォームのデザインビューでボタンを選択し、プロパティシートを表示します。
[イベント]タブを選択し、[クリック時]イベントに移動します。
[クリック時]イベントの右側にある「…」ボタンをクリックし、[コードビルダー]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/527ad16c-54bd-0dd7-0b49-f96c84c39adc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/a6bd510d-5cca-c7fb-08fd-35359014a470.png)

以下のVBAコードを入力します：
```
Private Sub btnRunQuery_Click()
    ' 特定のクエリを実行
    DoCmd.OpenQuery "SelectAllQuery"
    
    ' メッセージを表示
    MsgBox "クエリが正常に実行されました"
End Sub
```

Ctrl +　Sで保存

## 手順6: フォームの使用
### フォームを保存し、フォームビューで開きます。

Ctrl +　Sでフォームを保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/864bab3c-b72d-84d0-70d2-01aa750e4c07.png)
開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/03c8b026-bd2e-b048-a159-75510298ef4b.png)



btnRunQueryボタンをクリックして、クエリが実行されることを確認します。
クエリが正常に実行されると、メッセージボックスに「クエリが正常に実行されました」と表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058523/6fc6d1e4-3efe-c1ad-12f8-16e09ac27949.png)


これで、ボタンを押すと特定のクエリが実行され、終了時にメッセージが表示されるフォームが完成です。
GraphQL初心者必見！ゼロから学べる実践入門

GraphQLとは？
---
GraphQLは、Facebookによって開発されたクエリ言語であり、APIの実装方法です。
REST APIのようにエンドポイントごとにリクエストを送るのではなく、クライアントが必要なデータを一度のリクエストで取得できるのが特徴です。

GraphQLの利点
---
`柔軟なデータ取得`: クライアントは必要なデータを指定して取得できるため、過剰なデータ取得や不足がありません。
`単一のエンドポイント`: 全てのリクエストは単一のエンドポイントで処理されるため、APIの管理がシンプルになります。
`型安全`: スキーマを使ってAPIの型を明確に定義するため、データの整合性が保たれます。
`ドキュメンテーションの自動生成`: GraphQLサーバーは、スキーマに基づいたドキュメントを自動生成するため、APIの仕様が常に最新の状態に保たれます。

``` .基本的なクエリの例
type Query {
  user(id: ID!): User
}

type User {
  id: ID!
  name: String
  email: String
}
```

``` .ユーザーの名前とメールアドレスを取得する
query {
  user(id: "1") {
    name
    email
  }
}
```
GraphQLとRESTの比較
---
■GraphQLの利点
`データの取得の柔軟性`: クライアントが必要なデータだけを取得できるため、ネットワークの負荷が軽減されます。
`単一のエンドポイント`: すべてのリクエストが単一のエンドポイントで処理され、APIの管理が簡単になります。

■RESTの利点
`成熟したエコシステム`: RESTは長い間利用されてきたため、ツールやライブラリが豊富です。
`キャッシュの容易さ`: RESTではHTTPメソッドやステータスコードを利用してキャッシュが容易に行えます。

まとめ
---
GraphQLは、クライアントが必要なデータを指定して効率的に取得できる柔軟なクエリ言語およびAPI実装の方法です。
受付の管理用に作ってみましたが...


色々試してやっと思ったような動きをしましたが...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/f9a75d4a-e2e9-9cc2-8994-3c65accb91a3.png)


編集画面がよく下記のエラーで開かないんですよね。
ということで実用性が無いと判断されて今回は没です。

Failed to create or join session (API: NewInstance)xhr error. Status: 504, response:


まぁ、時間は全く無駄になったけど、今後はこの仕組みは使わないと決めることができました。それだけでもいいでしょう。

本当に使えん。