OmniAICreator/Qiita-1.07M huggingface dataset:
CSSだけでJavaScriptっぽい動きを実装してみた

自社アドベントカレンダー実施中です:calendar:よろしければこちらもご覧ください :calendar:

https://qiita.com/advent-calendar/2022/ari-group

****
# はじめに
自分は普段、業務システムのバックエンド担当で、HTML,CSSはシンプルなものしか実装したことがありません。今までCSSをがっつりと書いたことがなく、CSSではレイアウトの調整、JavaScriptで動きを付けるものだと思って過ごしてきました。

ある日、CSSだけでJavaScriptで書いたように動いているボタンを見て、どうやって書いてあるのか気になったので、コードを調べ、書いてみました。
**WEBページを作ったことがある方には基本事項ばかりの、ゆるい記事です。**

:::note info
自分の備忘録、そして実務には向かない内容ですのでご了承ください。
:::


## CSSで書いてみたもの
早速ですが、こちらが動作のデモです。
デフォルトではボタンを押せませんが、「同意する」にチェックを入れると遷移できるようになります。JavaScriptは書いていません。
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="gOKoJEy" data-user="harusaku" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/harusaku/pen/gOKoJEy">
  チェック＆クリック</a> by 春 (<a href="https://codepen.io/harusaku">@harusaku</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


作成時、こちらを参考にさせていただきました:writing_hand:

https://codepen.io/ash_creator/pen/JjZReNm

本家様は、同意するチェックやリンクにも制御が付いて、
レイアウトもきちんと指定されています。美しいです。

## 疑似クラス、ＣＳＳアニメーション
今回調べて、初めて書きました。便利なクラスがあるんですね～。

https://qiita.com/soarflat/items/4a302e0cafa21477707f

https://developer.mozilla.org/ja/docs/Web/CSS/Pseudo-classes

## さらにググって解読
参考元の、お手本CSSをググりながら作成。書いた内容は、以下のとおりです。

<font color="green">1. リンク要素の手前に、「次のページへ」という要素を表示する
⇒「次のページへ」要素が邪魔して、リンクは押せなくなる</font>
 
```css:test.css
.next::before{
    content : '次のページへ' ;
    position : absolute ;
    width : 100% ;
    height : 100% ;
 /* 色、文字位置なども指定する(略) */
}
.next{
    position : relative ;
 /* 色、文字位置なども指定する(略) */
}
```

<font color="green">2.「同意する」にチェックがあれば、リンクを最前面に出す
⇒リンクがクリックできるようになる</font>

```css:test.css
#check:checked ~ .next{
    z-index : 2 ;
}
```

<font color="green">3. 「次のページへ」の押せないボタンにアニメーションを付ける（ゆっくり消す）</font>

```css:test.css
#check:checked ~ .next::before{
    animation: animation 1s;
    animation-play-state: running;
    animation-fill-mode: forwards;
}
@keyframes animation {
 /* アニメーションの設定を書く(略) */
}
```

です。やっていることはシンプル。
あとは各要素の位置を調整すれば完成で、冒頭のデモの動きになります。



## おわりに
練習のために、コピペせずに組み立てながら書いたため、これだけのコードに思いのほか時間がかかってしまいました。自分のようなCSS初心者は、少し難しいことをやろうとすると、書きたいものが全然違うところに表示されたりして、思い通りのレイアウトが中々完成しません。


今回書いたものは、（JavaScriptや、JQueryを使えば一瞬で書けるし）全く実用的ではありませんが、動きを想像しながら実際に書いてみることでCSSの知識が深まり、良い練習になりました。基本の動作を組み合わせてやりたいことを実現するというのは、開発と同じだなのだと思いました。

あと、codepenなどに公開されている、色々な方のカラフルな動くサンプルは、見ているだけで楽しかったです。メモ帳一つあれば表示確認ができるので、機会があればいろいろ動かしてみようかなと思いました。

##### （余談）達人になると、CSSだけでマリオが作れる。
今回調べている途中で知りました。画像も無し、HTMLとCSSだけだそうです。Aボタンでジャンプができ、実際にプレイできて驚きました。

https://ash-creator.com/hentai_css/mario/

最後まで読んでいただきありがとうございました。
「つながり」でかんがえる多様性

「多様性」という言葉をいまはじめて聞いた人はいないでしょう。

一方で筆者は「**多様性とは何か？**」ということに答えられないでいました。辞書的な意味は知っていますが、仕事においてどのように活かすべきかはよくわかっていませんでした。

そんななか、**『マネジメント3.0』** という書籍にあった多様性に関する記述にとても感銘を受けたので、メモがてら残しておこうと思います。

## 「多様性」はあればいいものじゃない

まず「多様性」とググったときに出てくる最初のページの説明を引用します。

> 多様性（ダイバーシティ／diversity）とは「ある集団の中に異なる特徴・特性を持つ人がともに存在すること」です。[^1]

これはとてもわかりやすい説明です。

しかしこの説明を誤って解釈してしまうことも多々あります。それは「多様性があればあるだけ素晴らしい」という解釈です。

多様性はポジティブなものだとは思いますが、**コンテクストによっては「なんぼあっても良い」というものでもありません**。『マネジメント3.0』では、これを次のように説明しています。

> しかしながら、これは常に多様性がより大きいほど、より大きな創造性をもたらすということではない。警察官、オランダ人、バレーのダンサー、よちよち歩きの子供を集めても、あなたが望むようなイノベーションのレベルをあなたにもたらすことはないだろう。すべての多様な観点がより大きなパターンにおいてつながり続けるためには、ある程度の安定性と十分な共通点がなければならないのである。ルーウィンとレジーナは、これを **インクルーシブな多様性(inclusive diversity)** と呼ぶ[^2]

これはユーモアのある、わかりやすい指摘です。[^3] 仕事において、われわれが大きくすべきなのはインクルーシブな多様性でしょう。

## 仕事においては重要なのは「新しいつながり」

ここまで理解したとして、**実際の行動や日々の思考になにか反映できることはあるでしょうか**。筆者はとくにこれを悩んでいました。

『マネジメント3.0』がスゴいと思ったのはここです。たとえば著者は次のように書いており、納得・共感しました。

> あなたが新たな人間を雇う際に見るべき重要なことは、**その人がどのようにその組織の人たちとつながるか**ということである。[...]というのは、つながりにおける多様性が、あなたのチームの能力とパフォーマンスに最も大きな影響を持つからである。むろん、多様性にはつながりだけではなく、他のものもいっぱいある。それでもつながりの影響は性の影響よりも確かに大きい。[^4]

筆者なりに言い換えると「**個人のタグではなく、その人が加わることによる関係性の変化に意識を向けよう**」と言えるでしょうか。

## 「ちがい」でなく「つながり」

振り返ると、チームや組織の多様性のことを考えるとき、真っ先に性別や年齢など個人ごとの「ちがい」を見てしまいがちな面がありました。

しかしこれよりも重要なものとして「つながり」がある、というのが著者の主張です。

この主張にはとても納得します。多様性が大きくなってよかった瞬間というのは、ただ属性のちがう人が加わったこと自体ではなく、その人がいることによって（ポジティブな）新しいコミュニケーションや新しい観点が生まれたときだったからです。

たとえばいま私のいるチームは男女が半々のチームですが、これが多様性そのものでポジティブな結果を生み出しているとはまったく感じません。

そうではなく、それぞれのメンバーがいることで、観点の見落としがなくなったり、雑談が弾んだり、チャレンジングになったり。その人がいることで新しいものが生まれていくとき、はじめて「さまざまな人が存在してよかった」と感じます。[^5]

## 最後に

「多様性はよいもの」ぐらいの認識だったときと比べると、ここで紹介した考え方は納得のいくものであり、ビジネスにおける多様性を一歩深く理解、実践できるような気になりました。

「相手のちがいを受け入れる」ことを目的にするのではなく「相手が加わることによる相乗効果を考えてみる」ことで、多様性を広げたり、自身のもつ多様性にも気がつけたりしそうです。

このあたりに関心のある方がいれば、ぜひコメントいただければ嬉しいです。

[^1]: [SDGsで求められる多様性とは？企業が取り組むダイバーシティの実現](https://www.hrpro.co.jp/miraii/post-909/#:~:text=%E5%A4%9A%E6%A7%98%E6%80%A7%EF%BC%88%E3%83%80%E3%82%A4%E3%83%90%E3%83%BC%E3%82%B7%E3%83%86%E3%82%A3%EF%BC%8Fdiversity%EF%BC%89,%E3%81%A7%E7%94%A8%E3%81%84%E3%82%89%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82)

[^2]: Jurgen Appelo、『マネジメント3.0 適応力の高いチームを育むための6つの視点』、p72。

[^3]: ただし「ある程度の安定性と十分な共通点」というのが難しいことは変わりありません。この水準がおかしいと多様性を受け入れられないからです。たとえば安定性や共通点にジェンダーや人種を入れてしまうのはアンチパターンでしょう。一方でナレッジやスキルセット、ビジョンや個人の志向などはあらかじめ規定しておいたほうがよいのだろうと感じました。

[^4]: 同、p100。

[^5]: すでに述べていますが、これは仕事においての話題です。
Raspberry Pi版Almalinuxをgptのディスクでブートする


# １. 始めに
CentOSの後継として使用可能なAlmalinuxをRaspberry pi4のサーバでも使い始めました。サーバではgptのHDDからブートする方法を取りたかったのですが、公開されているRaspberry piのイメージはmbrのため2TBより大きいHDDは使えません。調べたところ、mbrのイメージをインストール後、gptに切り替えて使用する方法があったので、メモとしてのこします。

# ２．準備

- Raspberry Pi 4
- 2TBより大きいUSB HDD
- SDカード(作業用Raspberry pi OS用)
- AlmalinuxのRaspberry Pi向けイメージ
- usb_boot.zip

# ３．手順

## 3-1. Raspberry Pi OSの準備
Raspberry Pi Imagerなどを使用して、準備した作業用SDカードにインストールしてください。

https://www.raspberrypi.com/software/


## 3-2. usb_boot.zipのダウンロード

以下のURLからusb_boot.zipをダウンロードして、Raspberry Pi OS上で解凍してください。

https://forums.raspberrypi.com/viewtopic.php?t=196778


## 3-3. Almalinuxイメージのインストール

Almalinux のaarch64のブートイメージをダウンロードします。下記のgitのREADME.md内にイメージのダウンロードリンクがあります。

https://github.com/AlmaLinux/raspberry-pi/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575990/d7b0d5bb-2776-73fd-43d0-ffb028ef62c8.png)

ダウンロードしたら、USB HDDにddをします。PC上での作業はbalenaEtcherが便利です。

https://www.balena.io/etcher/

一度Raspberry PiにUSB接続で立ち上げ、SDカードなしで立ち上がることを確認します。

## 3-4. mbr　→　gpt変換作業

SDカードをRaspberry Piに装備して、Raspberry Pi OSで立ち上げます。起動したら、上記ディスクを接続します。（以降、仮に/dev/hdaとします。）接続するとオートマウントするので、アンマウントします。

```
$ sudo su
# umount /media/pi/*
```

mbrからgptに変換します。Raspberry Pi OSでのみ、このコマンドが実行できます。他のOSではエラーとなります。

```
# mbr2gpt /dev/sda
```

## 3-5. ディスクの調整
次にパーティション拡張をします。この例では、rootに約128GB割り当て、残りを別パーティションとしています。128GiBはディスク最初からのサイズとなります。partedのresizepartを使用します。ディスクの最初にはブートパーティションとスワップが定義されているため、少し小さい値のパーティションとなります。指定方法は、20GiB,1.5TiBとか設定できます。すべてrootfsに定義するのであれば、ディスクいっぱいの値を定義してください。

```
# parted /dev/hdb
(parted) resizepart 3 128GiB
```
残りを別パーティションにするには、続けてpartedでmkpartコマンドで定義します。

```
(parted) mkpart work ext4 128GiB 100%
```
終了します
```
(parted) quit
```

次にPARTUUIDが変更になってしまうので、cmdline.txtを変更します。
blkidを実行して/dev/sda3のPARTUUIDを取得します。
```
# blkid
```
/dev/sda3の項目内のPARTUUID="XXXX" をコピーします。
次に/dev/sda1をマウントします。
```
# mount /dev/sda1 /mnt
```
cmdline.txtを編集します。
```
# vi /mnt/cmdline.txt
```
上記のPARTUUIDのコピーをペーストして、コマンドライン内のPARTUUID=XXXXと入れ替えます。
編集が終了したらシャットダウンします。
```
# shutdown -h now
```
SDカードを外してUSBディスクのみにしてブートすると立ち上がるはずです。ダメな場合はPARTUUIDのミスであることがほとんどのため、見直してください。
LPIC Lv1-101　ランレベルについてまとめてみた

# はじめに
LPIC Lv1-101　ランレベルについてまとめてみた

# 最終更新日
2022年11月29日

# 環境の情報
OS
Ubuntu20.04

# 注意
最新の状態を確認して下さい。

# 公式さま
Linux Professional Institute
https://www.lpi.org


# 参考さま
https://mondai.ping-t.com


# SysVinit
UNIX系OSで使われてきた起動するまでの仕組み。


# wall
コマンド。
案内を通知できる。
Linuxは複数人で同時に使うことが出来る。
そのため、システム停止作業は色んなのユーザーに影響してしまう。
そのため、ログイン中の全ユーザーにメッセージを送れる。



# ACPI
Advanced Configuration and Power Interface
規格。
コンピュータの電源管理や構成に関する。
OS上でシャットダウンや再起動などを行う際の命令は、ACPIイベントとして通知されます。




# acpidデーモン
ACPIイベントを監視し、イベントに対応する処理を実行します。




# /etc/inittab
ファイル。
デフォルトのランレベルの設定を行うことができる。
「SysVinit」を採用しているシステムにて。



# /etc/inittab
ファイル。
「ctrl+alt+del」キーを押下した際の動作を設定する。
SysVinitを採用したシステムにて。
PHP の Docker に Postfix を入れてホストにリレーする


# PHP の Docker でメールを送信したい

Docker上で PHP アプリケーションの開発をしていて、PHP からメールを送信する必要が出てきました。
そのままだと、Docker の PHP  にはメールを送信する仕組みが含まれていませんので、同じ Docker 内に Postfix を入れて、ホストにリレーすることにしました。
ベースの Docker イメージは php:8.1-apache です。

併せて Vim やネットワーク系のコマンド(ping, curl など)、メール送信確認のための mail コマンドもインストールしておきます。

```Docker:Dockerfile
FROM php:8.1-apache

# package install
RUN apt-get update && \
    apt-get -y upgrade && \
    apt-get install -y \
        vim \
        iproute2 \
        iputils-ping \
        curl \
        mailutils \
    && docker-php-ext-install pdo pdo_mysql && apt-get clean
```

# Postfix のインストールと設定

Postfix のインストールには少し工夫が必要です。
そのままだと、インストール中に質問が入って止まってしまうので、
`DEBIAN_FRONTEND=noninteractive` を指定して、インストール中に処理が止まらないようにします。

そして、 postfix の設定ファイルに、メールのリレー先を設定します。
今回はいったんホストマシンに送りつけて、ホストマシンからさらに外部のメールサーバーにリレーすることにしたので、 Docker からのリレー先はホストマシン (host.docker.internal) としました。
/etc/postfix/main.cf の relayhost の設定を書き換えます。

```Docker:Dockerfile つづき
RUN DEBIAN_FRONTEND=noninteractive apt install postfix -y && \
    sed -i -E 's/^(#| )*relayhost( )*=.*$/relayhost = host.docker.internal/g' /etc/postfix/main.cf
```

# PHP の設定

PHP の設定については、sendmail_path を適宜設定します。
一応デフォルトは "sendmail -t -i" なのでやらなくていいかもですが、念のため。

```Docker:Dockerfile つづき
# php.ini
RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" && \
    sed -i -E 's/^(;| )*sendmail_path( )*=.*$/sendmail_path = \"sendmail -t -i\"/g' /usr/local/etc/php/php.ini
```

# CMD は一つだけ

Dockerfile の CMD 命令は一つだけしか指定できないので、 Apache と Postfix を両方起動するために、シェルスクリプトを書いてそこに両方のコマンドを記述し、そのスクリプトを CMD に指定します。

```shell:startup.sh
#!/bin/sh

/etc/init.d/postfix start
/usr/local/bin/apache2-foreground
```

```Docker:Dockerfile つづき
COPY startup.sh /

CMD sh /startup.sh/etc/postfix/main.cf
```

この Dockerfile を元にコンテナを作成すると、 Apache+PHP で Postfix が動くようになりました。
メールテンプレートが使用されている箇所を探す


+ [メールテンプレートが使用されている箇所を調べたい](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000JfJN7)

テンプレート自体はSOQLで検索できるけど、使われている場所は分からないですね。

```
select Subject from EmailTemplate
```

[EmailTemplateオブジェクト](https://developer.salesforce.com/docs/atlas.ja-jp.object_reference.meta/object_reference/sforce_api_objects_emailtemplate.htm)

アイデアにあがっていますね。
[Search Email Templates](https://ideas.salesforce.com/s/idea/a0B8W00000GddunUAB/search-email-templates)


以下で有償のツールが紹介されています。

これら考えるとSOQLでなくて　メタデータを検索すればできるのかもしれません。
https://developer.salesforce.com/forums/?id=9062I000000DKuwQAG

[Satrang Metadata Search](https://appexchange.salesforce.com/appxListingDetail?listingId=a0N30000009wgF7EAI)


試してはないですが、何やらURL hackがあるようです。
[How to determine where an email template is being used?](https://salesforce.stackexchange.com/questions/10827/how-to-determine-where-an-email-template-is-being-used)


URL hack the "show dependencies" button available for example on Apex classes.
Apex クラスなどで使用できる [依存関係を表示] ボタンを URL ハックします。

 https://instance.salesforce.com/packaging/dependencyPage.apexp?id=... - you can paste class id, page id, email template id... Good for initial reconnaissance. Probably you can achieve similar results while building a fake changeset and clicking show/add dependencies. It's not a 100% solution though.
 https://instance.salesforce.com/packaging/dependencyPage.apexp?id=... - クラス ID、ページ ID、メール テンプレート ID を貼り付けることができます... 最初の偵察に適しています。おそらく、偽の変更セットを構築し、依存関係の表示/追加をクリックすると、同様の結果を得ることができます。ただし、100% の解決策ではありません。

また、無償らしいツールも紹介されていました。

[happysoup.io](https://salesforce.stackexchange.com/questions/10827/how-to-determine-where-an-email-template-is-being-used)

もうひとつ方法が紹介されていました。

[Salesforce: find email template associated to which email alerts](https://www.simplysfdc.com/2014/01/salesforce-find-email-template.html)
[TIPS]: Node.jsでglobパターンを、RegExpに変換するBetterな法方

[自分ブログより](https://blog.hedrall.work/posts/20221120-glob)

# 結論

以下のコードで`glob`の文字列を`RegExp`の文字列に変換することができました。

```typescript
const minimatch = require('minimatch').Minimatch;
const globToRegExp = glob => {
  const regexp = new minimatch(glob).makeRe();
  if (!regexp) throw new Error(`globに変換できません。glob: "${glob}"`);
  return regexp.toString().slice(1, -1); // 前後に `/` がついてしまうので、sliceする
};
```

# 解説

`glob`を`RegExp`に変換する際にちょうど良いライブラリを見つけるのに時間がかかったので、本記事を書きました。

まず `glob to regexp` などで検索すると [glob-to-regexp](https://github.com/fitzgen/glob-to-regexp) のようなパッケージが出てきます。NPMでは相当なダウンロード数がありそうですが、レポはpublicアーカイブになっており、このまま利用するのも少し気が引ける状況でした。

そこで、`Node.js`で`glob`を使ってファイルを読み込む際の定番ライブラリ [glob](https://github.com/isaacs/node-glob) を見てみたところ、内部的に [minimatch](https://github.com/isaacs/minimatch) というパッケージを利用してパターンマッチさせているとの記述があります。

では、`minimatch`の方をみてみると、NPMのno内部で`glob`パターンマッチに利用されており、`glob`文字列をJSの`RegExp`オブジェクトに変換できるという旨記載がありました。確かにNPMのレポジトリをみると、[package.json](https://github.com/npm/cli/blob/dc8e6bdd1d9e3416846c4f0624705cb42a7fb067/package.json#L90) に記載されています。

以上から、`Node.js`を利用する以上、NPMと同じロジックで`glob`を扱うのが自然と考え`minimatch`を利用することにしました。

`minimatch`の中には `makeRe()` という関数があり、これで `RegExp` オブジェクトを吐き出せるようです。

ちなみに、RegExpオブジェクトには`toString()`メソッドが利用できますが、`/./.toString() => '/./'`のように、前後に `/` がつくので、`.slice(1, -1)`でとってあげるようにしないと、`RegExp` <=> `string`間の相互変換は冪等な操作にならないようです。

以上、小ネタでしたが参考になれば幸いです。
2022年にあったモデルビューの更新

# はじめに
　Power BI Desktopにある3つのビューのうち、3番目のビュー「**モデルビュー**」大事です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/7fe8f0cc-2fae-3807-1a46-91a715280a96.png)
事あるごとに、今年は「モデルは？ モデルどうなっていますか？」と言い続けてきました。
おそらく来年も言い続けると思います。
そのモデルビューの中で、2022年に2つ機能追加がありました。

## [プロパティ]ペインでのリレーションシップ編集の追加

リレーションシップの編集方法が1つ追加になりました。

これまでのダイアログでの編集との比較は図を参照ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/bafb9ff8-74c2-fb60-9883-6369e4a90b72.png)

関連のLearnのDocsはこちらです。

https://learn.microsoft.com/ja-jp/power-bi/transform-model/desktop-create-and-manage-relationships#edit-a-relationship?WT.mc_id=DP-MVP-5004418 

関連の公式ブログはこちらです。

https://powerbi.microsoft.com/ja-jp/blog/power-bi-october-2022-feature-summary/#post-21148-_Toc116053186

こちらは2022/12/1現在、プレビュー機能です。

[ファイル]/[オプションと設定]/[オプション]から[プレビュー機能]の下の方にあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/8592d827-2597-c6f2-1fb4-fae065150e62.png)

※表記はバージョンによって異なる可能性があります。

### （関連）リレーションシップの管理

モデルの中全体のリレーションシップ管理はこちらで確認できますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/9d1784ee-3252-bd2c-3b05-009b4a738dc4.png)

## モデルビューの中でDAXの編集ができるようになった

レポートビュー、データビューと同様にDAXの編集ができるようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/0e312c86-cc1b-db6b-a7c6-2a9266627bac.png)

地味にうれしいアップデートですね。

# おわりに
　モデルビューで行う、モデリング、リレーションシップをいい感じで作ること、超大事です。
学習は以下のMS Learnのトレーニングがオススメです。

https://learn.microsoft.com/ja-jp/training/modules/create-power-bi-model-relationships/?WT.mc_id=DP-MVP-5004418
【Homebrew】よく使う brew コマンド一覧

## コマンド一覧

|brew コマンド|概要|
|:---|:---|
|-v|Homebrew のバージョン確認コマンド|
|update|Homebrew自体の更新を主としたアップデート（時間かかる）|
|upgrade|インストール済みパッケージの更新も含めたアップグレード（時間かかる）|
|outdated|更新のある formula （＝最新でないパッケージ）を一覧表示する|
|cask outdated|`outdated` の Cask 版|
|cleanup|使用していない＆古いバージョンのパッケージやキャッシュを削除してくれる|

# 詳細説明
コマンド実行時のコンソール表示の内容・意味などを説明

## update

Homebrew自体の更新を主としたアップデート（けっこう時間がかかります）

```bash
# 実行
brew update

# 結果（新しく導入可能な関連パッケージ表示）
Updated 1 tap (homebrew/core).
==> New Formulae
bindgen   corrosion   kustomizer ...

# 結果（アップデートできるパッケージを表示）
==> Outdated Formulae
ca-certificates   gdk-pixbuf   highway ...

You have 13 outdated formulae installed.
You can upgrade them with brew upgrade
or list them with brew outdated.
```

## brew outdated

更新のある formula （＝最新でないパッケージ）を一覧表示する

```bash
# 実行
brew outdated

# 結果（左が現在のバージョン/右が導入される予定の最新バージョン）
ca-certificates (2022-04-26) < 2022-10-11
fontconfig (2.14.0) < 2.14.1
gdk-pixbuf (2.42.9) < 2.42.10
graphviz (6.0.2) < 7.0.2
highway (1.0.1) < 1.0.2
imath (3.1.5) < 3.1.6
libpng (1.6.38) < 1.6.39
librsvg (2.54.5) < 2.55.1
libx11 (1.8.1) < 1.8.2
libxext (1.3.4) < 1.3.5
node-build (4.9.82) < 4.9.99
openssl@1.1 (1.1.1o) < 1.1.1s
pango (1.50.11) < 1.50.12
```

## brew cleanup

Homebrew 2.0 からは、30日ごとに自動で brew cleanup が実行される、また、install コマンドなどを実行することによっても、brew cleanup が実行されるので、無理に実行する必要はない

```bash
# 実行
brew cleanup

# 結果（削除せずにスキップしたパッケージ）
Warning: Skipping fontconfig: most recent version 2.14.1 not installed
# 結果（削除したパッケージ）
Removing: /Users/tommy/Library/Caches/Homebrew/fontconfig--2.14.0... (625.3KB)
```
Google UXデザイン：ユーザビリティ・スタティ時のメモの取り方

# はじめに

わたしが[Google UX Design Certificateで得られた素晴らしい体験][google]を、特に重要だと思われるポイントを小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ Google UX Design Certificateを受講してみてください。

[google]: https://qiita.com/mapami/items/7a0d0a3d4661c50f8bec

https://www.coursera.org/professional-certificates/google-ux-design

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/66d514dc-1996-9cf3-5acb-014309ebb027.png" width="800">

<details><summary>これまでの振り返り</summary>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/d326d1e3-3b70-ffc3-eabf-1ac6a7fcaec7.jpeg" width="500">

</details>

[plan]: https://qiita.com/masami-atwvn/items/aafed71e2ccc67898b0f

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/18c3a009-f64f-1275-ab54-38caefbfec4f.png" width="800">

今回は、ユーザビリティ・スタディでメモを取る必要がある理由と、誰がメモを取るのか、効果的なメモの取り方について探ります。

# メモを取る理由

まず、メモを取ることにより、ユーザビリティ・スタディ中に考えたことをすべて記録することができます。

たとえば、各参加者のボディランゲージや話し方について気づいたことを示すことができます。
- 参加者は微笑んでいますか? 
- イライラしているように見えますか？

ボディランゲージや声のトーンに基づいて参加者がどのように感じているかを推測するときは、[バイアスについて学んだ][bias]ばかりのことを心に留めておいてください。モデレートされた研究でこのバイアスを回避する1つの方法は、参加者が感情を示したと思われる時点で、どのように感じたかを尋ねることです。

[bias]: https://qiita.com/masami-atwvn/items/10c384d48e7e3de09b32

# 誰がメモを取る？

チームにUXリサーチャーがいる場合、彼らがリサーチを実施し、メモを取る可能性が高いでしょう。たとえ専任のリサーチャーがいたとしても、プロジェクトに関わる他のチームメンバーが参加し、メモを取ることは有用です。なぜなら、各チームメンバーは、自分の仕事に影響を与える問題に気づく可能性が高いからです。

例えば、UXライターは、参加者がアプリのボタンを間違えて押してしまったことに気づくかもしれません。一方、UXデザイナーは、ユーザーがボタンを探すのにどれだけ時間がかかったかに気づくかもしれません。

***<font color="MediumVioletRed">Googleでは、徹底的にメモを取ります。</font>*** 実際、リモートでも対面でも、多くのチームメンバーが研究を観察します。リサーチが終わると、全員が自分のメモと経験を集約します。そして、これらのメモから重要な洞察を抽出し、次のステージのデザインに反映させます。

# メモの取り方

正しい方法というのはなく、人それぞれ好きなメモの取り方があると思います。ここでは、スプレットシートでのメモの取り方について、ご紹介します。

次の５つのカテゴリを準備しておくと便利です。
1. タスク
1. クリックパス
1. 観察
1. 引用
1. タスクの完了


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/cdcb8742-935c-326d-87af-3c2315b9cd75.png" width="800">

#### タスク
調査中に参加者が完了するように誘導される各プロンプトをリストアップすることができます。この情報は、調査が始まる前に必ず記入しておいてください。また、調査の前に、各参加者のメモ書き用のスプレッドシートを作成する必要があります

#### クリックパス
参加者がタスクを完了するために取る経路です。ユーザーのクリックパスに関する情報を記録することは、ユーザーフローに関する新しい洞察を開発するのに役立ちます。特に、最初の数回のクリックは、製品のナビゲーションがどれほど直感的であるかを理解するのに役立つので、注意してください。

これで、メモを取る準備が整いました。

#### 観察
行動、意見、態度、およびエラー、問題、または混乱した領域を書き留めることができます。

観察欄は、潜在的なユーザーの行動や意見を間接的に理解するためのものです。プロンプトのタスクをこなしているときの参加者の声のトーンや態度も理解することができます。

#### 引用
肯定的なものも否定的なものも含めて、重要な引用が含ます。

#### タスクの完了
- 簡単に完了した場合: 1
- 完了したが困難だった場合: 2
- 完了しなかった場合: 3

というように、番号を振ります。

# さいごに

デザインに多様な声を反映させることは、本当に重要なことなのです。

デザインの目的は何かと考えたとき、それはまさに問題を解決し、ビジネスを前進させることです。もし、ある層だけをターゲットにしていたり、その製品を使う可能性のあるすべての人の問題を理解していなければ、ビジネスは繁栄し、成功することはできないのです。
npmとかyarnとかって結局なんなん？

npmとかyarnとかnpxとかpnpmとかいろんなものが出てきたので知識のアップデートも兼ねて共有します。

:::note info
【こんな方にオススメ！】
・これまでなんとなくnpmやyarnのコマンドを実行していた人
・これから使いたいけど、どれを使っていいのか迷子な人
:::

記事を読んで理解度を上げてもらえたら大変嬉しいです。

## npmとは？
- `Node Package Manager`の略で、Node.jsのモジュールを管理するツール
- Nodeをインストールすると自動で付いてくる
- `package-lock.json`によってinstallされたnode_modulesが記録されている

### バージョン確認
```javascript
npm -v
```

### 初期化（package.jsonが生成される）
```javascript
npm init
```

### package.jsonに記載されたパッケージを一括でインストール
```javascript
// package.jsonに記載されている内容を元にnode_modulesをインストールする
npm install

// package-lock.jsonの内容を元にnode_modulesをインストールする
npm ci
```
package.jsonを直接編集した時には実行が必要です。
**見覚えのないエラーが出た場合はいったんinstallし直す**ことをオススメします！

https://docs.npmjs.com/

## yarnってなに？
- npmと互換性があり、npmの時に利用していた`package.json`がそのまま利用できる。
- npmよりも動作が早い
- `yarn.lock`によってinstallされたnode_modulesが記録されている

### バージョン確認
```javascript
yarn -v
```

### 初期化（package.jsonが生成される）
```javascript
yarn init
```

### package.jsonに記載されたパッケージを一括でインストール
```JavaScript
yarn
```

yarnの動作が早いのはインストールしたパッケージをキャッシュしているから。
キャッシュされているnpmのリストは`yarn cache list`で表示されます。
キャッシュをクリアする時は` yarn cache clean`で実施できます。

https://yarnpkg.com/

## npxってなに？
`node package executer`でnpmがパッケージを管理するツールに対して**パッケージを実行するツール**がnpxです。
npmバージョン5.2.0より同梱されているコマンドです。

npxコマンドを利用することで開発環境内パッケージを実行することが可能です！

```javascript
npx module_name
```

実行したパッケージがインストールされていなければインストールを勧められます。（v5.2.0以降）

:::note warn
v5.2.0以前はインストールされていないパッケージを実行した場合、終了したら自動で削除されます。
:::

## pnpmってなに？
`performant npm`の略で`pnpm`だそうです。

**最大の特徴は、速さ・容量の節約・厳格さです。**
速さは、他のツールに比べて最大2倍速とされています。

:::note warn
npmとyarnでは対応していてもpnpmには標準対応していない場合があるので注意が必要です…
:::

npmはインストールしていなくても依存しているパッケージだった場合アクセスできるのに対して、pnpmはアクセスすることができずエラーになります。

npmでパッケージをインストールせずにimportして利用していた場合、依存パッケージのバージョンアップや依存関係が亡くなった場合にエラーが発生するのを防ぎます。

https://pnpm.io/ja/

## 【まとめ】結局何がいいの？
結局pnpmがいいのでは？と感じる方も多いと思います。
早いし、容量は節約できて、パッケージのインストール関連のエラーも少なさそう。

ただ、個人的にはすぐに乗り換えなくてもいいと考えています。
npmやyarnもpnpmが採用しているnode_modulesの構造を採用しようとしている。
（yarnは既にしている）

現在パッケージ管理や速度が大きな課題になっていないのであれば、一度それぞれのツールの動向を探ってからでも遅くないと考えています。

昨年の記事になりますので少し古いですが参考にしてください。

https://pnpm.io/ja/blog/2021/12/29/yearly-update
マネジメントtips：プレッシャーと生産性

仕事でプレッシャーは付き物です。納期あれば、納期のプレッシャーがあるでしょうし、成果物があると成果物としての品質のプレッシャーがあるでしょう。

もちろん、エンジニアという職種の人達には、プレッシャーの中で仕事をしている事が多いと思います。

# プレッシャーと生産性
トム・デマルコの著書『デッドライン』によると、プレッシャーを掛ける事によって、生産性が向上しない。
*結構古い本ですが、読みやすくて良い本です。
理由は、「思考は速くならない」からだと記されている。
```
プロジェクトには、様々なプレッシャーが存在する。
そして、人間は、プレッシャーを与えられるとそれに対応して、生産性があがると思われている。
しかし、人間は、プレッシャーを与えられても、思考が早くなる事は無い。
頭の回転は、速くならないので決して、生産性があがる事は無い。
```
という物です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/4d540e24-c13f-f11b-f962-7dc8d5be8060.png)

確かに、その通りだと思います。加えて、高プレッシャーは思考が遅くなります。ハードルが高すぎると諦めて思考停止したり、目標を見失ったりするためです。ムチでしばいて、24時間、365日働かしても生産性は向上しません。むしろ、残業時間が少ない方がTotalの生産性は高い。総労働時間とプロジェクトの成果物は、単純比例しません。
# やる気と生産性
どうすれば、生産性は向上するのか、それは、「やる気」である。
プロジェクトメンバーの内面の「やる気」があがれば、生産性は、向上する。それには、適切な労働時間、適切な環境、適切な賃金、適切なコミュニケーション、適切なチャンス等が必要となる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/728d1ccd-129c-2f57-d473-93180b5452e2.png)

そして、これらは、人によって適切な労働時間違うし、適切な環境も違う。もちろん、人によっては、適切なプレッシャーが必要な人間もいる。
最終的には、生産性をあげるためには、個別の人にフォーカスをあてて、個別に程度なプレッシャーを与えるマネージメントが必要である。
# お願い
今後も続けていきますので、フォロー、イイね、シェアお願いします。
下記、説明会もご参加下さい。
[エンジニア年収アップ講習(転職サポート付き！)　無料説開会　12月6日　19時開催](https://cto-can-be.hp.peraichi.com/)
エンティティの状態遷移関数

[Next.js + サーバーサイドTypeScript + 関数フレーバーでクリーンなアプリを作ったので実装意図とか書く Advent Calendar 2022](https://qiita.com/advent-calendar/2022/shwld)
の**9日目**。[株式会社mofmof](https://www.mof-mof.co.jp/)に生息している[shwld](https://twitter.com/shwld)です。

前日は[TaskEither型](https://qiita.com/shwld/items/d519f740150a97687acc)について書きました。

# エンティティの状態遷移関数
モデルのプロジェクト構造は以下のようになっています。

> models
 ┣━ account
 ┃   ┣━ mutations
 ┃   ┃   ┣━ build-account.test.ts
 ┃   ┃   ┣━ **build-account.ts** ← 状態遷移メソッド「新規作成」
 ┃   ┃   ┣━ edit-account.test.ts
 ┃   ┃   ┣━ **edit-account.ts** ← 状態遷移メソッド「更新」
 ┃   ┃   ┗━ index.ts
 ┃   ┣━ account-entity.ts
 ┃   ┣━ account-interfaces.ts
 ┃   ┣━ account-policies.ts
 ┃   ┣━ account-validator.ts
 ┃   ┗━ index.ts
 ┣━ story
  ...

[https://github.com/shwld/uzumaki/tree/main/domain/core/src/models](https://github.com/shwld/uzumaki/tree/main/domain/core/src/models)

上記のmutationsフォルダ内について解説していきます。

こちらのフォルダには、エンティティの状態を変異させるメソッドが入っています。
一つの状態変更イベントを1ファイルとして格納しています。

ファイルの中身は以下のようになっています

```typescript:/models/account/mutations/build-account.ts
// 入力データの型
export interface Account_BuildInput {
  id: ID;
  name: string;
  createdById: string;
}

// 出力データの型
export interface Account_BuiltAttributes
  __state: 'Built';
  id: ID;
  name: string;
  createdById: string;
}

/**
 * Validation
 */
export const validationSchema = z // バリデーションはzodを利用
  .object({
    ...AccountValidator.validators,
    createdById: genericValidator.id,
  })
  .strict();

/**
 * Mutation
 */
export const build = (
  input: Account_BuildInput
): Result<InvalidAttributesError, Account_BuiltAttributes> => {
  return pipe(
    {
      ...input,
      createdAt: new Date(),
      updatedAt: new Date(),
    },
    validateWith(validationSchema),
    map(v => ({
      ...v,
      __state: 'Built',
    }))
  );
};
```
[GitHubで /models/account/mutations/build-account.tsを みる](https://github.com/shwld/uzumaki/blob/main/domain/core/src/models/account/mutations/build-account.ts)

> [TypeScriptによるGraphQLバックエンド開発 ──TypeScriptの型システムとデータフローに着目した宣言的プログラミング](https://techplay.jp/column/1631)

では、バリデーション後なども型を用意していましたが、自分はそれはしませんでした。
理由としては、特にそこの処理を分離して使う利用シーンが思い浮かばなかったというところです。

基本的にはmutationとセットでバリデーションも実行しており、バリデーション結果に応じて状態を遷移させる処理となります。

mutationそれぞれに対応した型を用意することで、イベントからイベントへの遷移をどうやって行うのかを型で説明できるようになるとともに、どの型は永続化できるのかも型で判断できるようになります（リポジトリに永続化処理があるかどうかをみる）

また、mutationsをフォルダ内に一つ一つファイルで作ることによって、コマンドとクエリが分離され、クエリを安心して使えるようになりました。
# 次回予告
次回は[エンティティのバリデーション](https://qiita.com/shwld/items/270e6d5baf61021a2059)について書きます。
携帯隔日記

パソコンを持ち歩かず記録する努力。　

# 1.入力が遅い。

# 2.切り貼りが下手。　

# 3.発想が貧困。　

何かいいとこないか、　

# 4.制約が多い時の発想の歪みを確認。　

# 5.英語の作文が捗らない。　

# 6.参考文献の編集が非効率。　

なんとかならんか。　

やり方を探る。
Either型を使ってエラーを扱う

[Next.js + サーバーサイドTypeScript + 関数フレーバーでクリーンなアプリを作ったので実装意図とか書く Advent Calendar 2022](https://qiita.com/advent-calendar/2022/shwld)
の**7日目**。[株式会社mofmof](https://www.mof-mof.co.jp/)に生息している[shwld](https://twitter.com/shwld)です。

前日は[関数の合成](https://qiita.com/shwld/items/2dd1ce65388a7c5b4904)について書きました。

# Either型
一般的なアプリケーションは、処理の途中でこれ以上処理を進められなくなることがあります。
不正な入力データであったり、外部のシステムやデータベース、その他無数の要因で同じ処理でもエラーになってしまったり、エラーの原因は様々。

昨日書いた関数合成の中でそういったエラーが起きたらどうしよう。

```ts
pipe(
  input,
  validation,
  build,
  save,
  sendMail,
)
```

こんな風に、入力をバリデーションして、データを整形してDBに保存して、メール送信するみたいな処理を書いたとき、
バリデーションが失敗したらそれ以降は実行してもらいたくない。

こういうときにはEitherを利用すると良い。

https://gcanti.github.io/fp-ts/modules/Either.ts.html

Eitherは正常な結果と、そうでない結果の型を表現できる。
慣習として `left` が正しくないデータ、 `right` が正しいデータとしてどちらかの場合であることを表現できる。

- これを使うことでvalidationの結果、不正なデータだった場合にはleftを返すようにする
- buildやsaveはrightだけを受け取って処理する、leftだったら何もせずに次に送る

というように失敗データを無視して後続処理に受け渡すことができる

また、fp-tsには、新たに生まれた例外パターンを leftにunionとして加える、[Either#chainW](https://gcanti.github.io/fp-ts/modules/Either.ts.html#chainw) がある。

例
```
validation() // 失敗ならleftで`InvalidError`を返す
build() // Either rightのときだけ処理する
save() // Either rightのときだけ処理する。失敗なら`DBError`または`InvalidError`をleftで返す
mail() // Either rightのときだけ処理する。失敗なら`MailSendError`または`DBError`または`InvalidError`をleftで返す
handleError() // Either leftのときだけ処理する。`MailSendError`または`DBError`または`InvalidError`を受け取る
```

これを使えば、順番に実行していく中で発生するエラーのパターンをすべてunionとしてleftで保持しつつ最後にエラー処理をするということが可能で、良い（語彙力）
最後にエラー処理する際に、エラーを [ts-pattern](https://github.com/gvergnaud/ts-pattern) などを使ってもれなく処理すれば、どのエラーを処理漏れているかを型でチェックできたりと旨味が大きい。

デメリットとしては、入力にEitherを取ることが増えてちょっとめんどくさいなとか感じることだろうか。
# 次回予告
明日は[TaskEither](https://qiita.com/shwld/items/d519f740150a97687acc)について書きます
podman で docker-compose を実行する

Moodle の bitnami.moodle:latest を起動できた時のメモ。
OSは、Fedora37 です。

```
$ sudo dnf install python3-pip
$ sudo pip3 install -U pip
$ sudo pip3 install docker-compose
$ sudo dnf install podman-plugins
$ sudo systemctl enable podman.socket
$ sudo export DOCKER_HOST=unix:/run/podman/podman.sock
```
以下を参考に、bitnami.moodle:latest イメージを起動する準備をする。
https://github.com/bitnami/containers/tree/main/bitnami/moodle

```
$ curl -sSL https://raw.githubusercontent.com/bitnami/containers/main/bitnami/moodle/docker-compose.yml > docker-compose.yml
```

一度立ち上げてみる。

```
$ docker-compose up -d
```

以下の設定が必要であることが判明したので、設定を追加。

```
# vim /etc/sysctl.conf
net.ipv4.ip_unprivileged_port_start=443
net.ipv4.ip_unprivileged_port_start=80
```

もう一度立ち上げてみる。
```
$ docker-compose up -d
Creating network "moodlebitnami_default" with the default driver
Creating moodlebitnami_mariadb_1 ... done
Creating moodlebitnami_moodle_1  ... done
```

確認
```
$ docker container ls
CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS          PORTS                                                                            NAMES
b95063d365b3   bitnami/moodle:4       "/opt/bitnami/script…"   31 seconds ago   Up 30 seconds   0.0.0.0:80->8080/tcp, :::80->8080/tcp, 0.0.0.0:443->8443/tcp, :::443->8443/tcp   moodlebitnami_moodle_1
78b2fbc93046   bitnami/mariadb:10.6   "/opt/bitnami/script…"   32 seconds ago   Up 30 seconds   3306/tcp                                                                         moodlebitnami_mariadb_1
```

https://localhost
Moodle にログイン
user/bitnami
関数の合成

[Next.js + サーバーサイドTypeScript + 関数フレーバーでクリーンなアプリを作ったので実装意図とか書く Advent Calendar 2022](https://qiita.com/advent-calendar/2022/shwld)
の**6日目**。[株式会社mofmof](https://www.mof-mof.co.jp/)に生息している[shwld](https://twitter.com/shwld)です。

前日は[型で状態を表現する](https://qiita.com/shwld/items/ed12f28b220fb600d344)について書きました。

# 関数の合成
クラスを使わずにドメインモデルを書くことに決めたのですが、そうなると関数型の流儀みたいなものを使いたくなります。
とはいえ、あまり関数型の流儀に自分自身が慣れていないのと、理解しきれていないので、少しづつ取り入れることにしました。

関数を組み合わせて処理を書く際に普通に書くとこうなります。

```typescript
function sum(a, b) {
  return a + b
}

function addTax(kane) {
  return kane * 1.1
}

addTax(sum(10, 20))
```

2つとかならいいのですが、たくさんの関数を使おうとすると

```ts
e(d(c(b(a()))))
```
つらそう！！！


ここは、よくあるメソッドチェーンみたいに書きたいものです。

```ts
price.add(20).addTax()
```

みたいに！
なので、pipeを使いました。

```ts
const sum = (a) => (b) => a + b;
pipe(10, sum(20), addTax);
```

だいぶ近い。良いでしょう。

ということで、これを実現するために [fp-ts](https://gcanti.github.io/fp-ts/)の `pipe` というのを使っています。
# 次回予告
明日は[Either型を使ってエラーを扱う](https://qiita.com/shwld/items/f5f192ace0702d9156e2)について書きます
型で状態を表現する

[Next.js + サーバーサイドTypeScript + 関数フレーバーでクリーンなアプリを作ったので実装意図とか書く Advent Calendar 2022](https://qiita.com/advent-calendar/2022/shwld)
の**5日目**。[株式会社mofmof](https://www.mof-mof.co.jp/)に生息している[shwld](https://twitter.com/shwld)です。

前日は[プロジェクトのアーキテクチャ](https://qiita.com/shwld/items/318d9f6034e02cfcb23d)について書きました。
# 型で状態を表現する
TypeScriptを利用するにあたり、最初はクラスベースでドメインモデルを書いており、ドメインモデルを表現する際に状態をプロパティとして表現していました。

例えば `isDeleted` のようなプロパティで削除状態を表現したりしていました。

```typescript
class Story {
  readonly isDeleted
  ...
}
```

プロパティで状態を表現し、リポジトリ層で状態を永続化するという流れで考えていたのですが、そうなるとリポジトリ層で状態を見て分岐するという処理が多数出来上がりました。
このあたり、リポジトリパターンを用いた開発に不慣れというのもあるのですが、モヤモヤとしていました。

ちょうど今年は、Haskellに入門してみたり、DDDを関数型で実装する[Domain Modeling Made Functional](https://pragprog.com/titles/swdddf/domain-modeling-made-functional/) を見てみたり（読みきれてないですが...）

このあたりを導入してみたいなと思っていたタイミングで、[TypeScriptによるGraphQLバックエンド開発 ──TypeScriptの型システムとデータフローに着目した宣言的プログラミング](https://techplay.jp/column/1631)の考え方を見たので、自分もこの流れに乗ってみました。

上記記事にもありますが、イベントによる状態の遷移一つ一つを一つの方として捉えることで、イベントがとても局所的なアクションになり、責任が単一に近づきます。

例えば、

```typescript
export interface Account_BuiltAttributes {
  id: ID;
  createdAt: Date;
  updatedAt: Date;
  name: string;
  createdById: string | null;
  __state: 'Built'
}
```

のような型で新規作成を表現しました。
これとは別に、編集のイベントの結果は `__state` を別のものになるように設定し、型で区別できるようにしています。

```typescript
export interface Account_DraftAttributes {
  ...
  __state: 'Draft'
}
```

こうすることで、永続化の際には、`Account_DraftAttributes` のように、あるイベントを通った状態のデータのみを入力にすることで、その状態を永続化するリポジトリの処理も単一責任にしつつ、利用シーンを明確にすることができました。

参照した記事と違うのは、バリデーション済かどうかを型として表現していないところですが、それに関しては後日の記事で書こうと思います。
# 次回予告
明日は[関数の合成](https://qiita.com/shwld/items/2dd1ce65388a7c5b4904)について書きます
プロジェクトのアーキテクチャ

[Next.js + サーバーサイドTypeScript + 関数フレーバーでクリーンなアプリを作ったので実装意図とか書く Advent Calendar 2022](https://qiita.com/advent-calendar/2022/shwld)
の**4日目**。[株式会社mofmof](https://www.mof-mof.co.jp/)に生息している[shwld](https://twitter.com/shwld)です。

前日は[設計方針](https://qiita.com/shwld/items/c0da9efa1a03a6053a9e)について書きました。

----
プロジェクトのアーキテクチャについて書きます。

[クリーンアーキテクチャ](https://qiita.com/nrslib/items/a5f902c4defc83bd46b8)のように、逆方向へは依存しないようにしています。

矢印の方向に依存する
`apps, infrastructures` → `use-cases` → `core domain, interfaces`

```:ディレクトリ構造
┣━┳ apps
┃ ┣━━ web: フロントエンド (Next.js)
┃ ┗━━ worker: バックグラウンドワーカー
┣━┳ domain
┃ ┗━━ core: ドメインロジック
┃ ┗━━ interfaces: リポジトリや外部依存のインタフェース定義
┣━┳ infrastructures: 外部システムへの依存を持つ部品
┃ ┣━━ repository: データ永続化処理 (prisma)
┃ ┣━━ worker: バックグラウンド処理 (graphile-worker)
┃ ┣━━ pubsub: リアルタイム処理 (pg-pubsub)
┃ ┗━━ mailer: メール送信処理 (mailgun)
┣━┳ packages
┃ ┗━━ 共通で利用するパッケージ
┗━┳ use-cases
  ┗━━ graphql-resolvers: GraphQLクエリの解析と実行
```
# 次回予告
明日は[型で状態を表現する](https://qiita.com/shwld/items/ed12f28b220fb600d344)について書きます。
Javascript環境で学習用プロダクト開発時の実装方針

[Next.js + サーバーサイドTypeScript + 関数フレーバーでクリーンなアプリを作ったので実装意図とか書く Advent Calendar 2022](https://qiita.com/advent-calendar/2022/shwld)
の**3日目**。[株式会社mofmof](https://www.mof-mof.co.jp/)に生息している[shwld](https://twitter.com/shwld)です。

前日は[shwld is 誰。このアドベントカレンダーの技術レベルの前提]()について紹介しました。
# 実装方針

設計する上で優先度高めに設定しているのは以下です。
ただし、満たすものを作るというよりは願望です。

- 新規プロジェクト開発時に初速が出ること
- 中規模くらいまではスケールできること
- 依存パッケージを増やさないこと

前日に書きましたが、作るものは[PivotalTracker](https://www.pivotaltracker.com/)です。
これを作るうえで、どこまで作るかを判断するポイントは以下です。

- よくある処理の実装方法を知るために一つ以上実装する
  - 認証
  - ファイルアップロード（未実装ですが...）
  - 非同期処理
  - バックグラウンド処理
  - リアルタイム処理
  - メール送信
  - バッチ処理
  - ロギング（未対応ですが...）
- MVPになっている
  - 最低限プロジェクト運用を回せる機能が揃っている

## 依存パッケージを増やさないこと
普段はRailsを書いていることが多いのですが、メジャーバージョンアップなどの対応は依存が多いほど大変です。
とはいえRailsはもはや枯れていて、大変なのはバージョンアップのタイミングくらいですが、JavaScript、Node.jsなどはそうではなく、ライブラリや周辺環境は目まぐるしく変わります。

そうなるとパッケージのバージョンアップの機会も自ずと多くなります。
この環境において依存パッケージを増やすのはリスクが大きいです。
- 小さなパッケージは使わず極力自分で書くなどし、制御可能な状態を保つこと。
- 依存はなるべく安定したものを選択する。
これらを意識することが重要だと思います。

まだこのプロジェクトもNext.jsを13にアップデートできておらず、そこだけでも大変なのに、他の依存が増えたらアップデートだけで手が回らなくなります...

# 次回予告
明日は[プロジェクトのアーキテクチャ](https://qiita.com/shwld/items/318d9f6034e02cfcb23d)について書きます。
shwld is 誰。このアドベントカレンダーの技術レベルの前提

[Next.js + サーバーサイドTypeScript + 関数フレーバーでクリーンなアプリを作ったので実装意図とか書く Advent Calendar 2022](https://qiita.com/advent-calendar/2022/shwld)
の**2日目**。[株式会社mofmof](https://www.mof-mof.co.jp/)に生息している[shwld](https://twitter.com/shwld)です。

前日は[作ったもの](https://qiita.com/shwld/items/14bbe56ff2881b031c26)について書きました。

# shwld is 誰。このアドベントカレンダーの技術レベルの前提

主に[株式会社mofmof](https://www.mof-mof.co.jp/)という会社でエンジニアや、エンジニア組織の改善活動などをやっています。
## 技術的興味
- 仕事ではGraphQL RubyとReactをよく使っています
- 個人開発では最近はNextJSを使うことが多いです
- バックエンドの言語選定をそろそろ改善しようと色々みているなかで、今回TypeScriptを試しています
## 記事を書く上で、各要素のレベル感
TypeScriptはまあまあ長く仕事で使っています。
GraphQLも結構長く使っています。
どちらも3~4年以上?くらい

ですが、関数型に関しては、仕事で書いたことはなく、趣味でも今回が初めてのビギナーです。
今年、Haskellに入門したりいくつか本などを読んだくらいのレベル。

TypeScriptは仕事で使っていると書きましたがフロントエンドのみで、バックエンドで書いたことはNext.jsやfirebase functionのレベルでしかありません。
そんな人物が書くので試行錯誤もたくさんあり、マサカリ募集です。
## 意気込み
設計に関する記事は具体的なものが少ないので、今回、ソースをすべて公開して設計意図を綴るというのをやってみました。
自分が設計周り学んででほしいなと思ったコンテンツです（記事の質は別として）

あと23記事出す予定なので、よかったらみてください。

## 連絡先
| SNS | URL |
|----|----|
Twitter | https://twitter.com/shwld
GitHub | https://github.com/shwld
Zenn | https://zenn.dev/shwld
## 次回予告
明日は[実装方針](https://qiita.com/shwld/items/c0da9efa1a03a6053a9e)について書きます。
Next.js + サーバーサイドTypeScript + 関数フレーバーでクリーンなアプリを作った

[Next.js + サーバーサイドTypeScript + 関数フレーバーでクリーンなアプリを作ったので実装意図とか書く Advent Calendar 2022](https://qiita.com/advent-calendar/2022/shwld)
の**1日目**。[株式会社mofmof](https://www.mof-mof.co.jp/)に生息している[shwld](https://twitter.com/shwld)です。

特典目当てに１人アドベントカレンダーに挑戦してみます。
アウトプットのきっかけをくれてありがとうございます。

アドベントカレンダーのタイトルどおりですが、

「**Next.js + サーバーサイドTypeScript + 関数フレーバーでクリーンなアプリを作ったので実装意図とか**」

を書いていきます

# 初日は作ったものを紹介します
[Pivotal Tracker](https://www.pivotaltracker.com/)のクローンを作りました。

UZUMAKI - Scrum Story Tracker

https://uzumaki.shwld.app/

PivotalTrackerはスクラムプロジェクトの管理ツールとして最も好きなツールです。
このツールのストーリー管理機能を見様見真似で実装しました。

ソースはオープンソースで公開しています。

https://github.com/shwld/uzumaki
# なぜ作ったのか

「**技術の検証を思い切りやるため**」

今年はDDDを学んだりアーキテクチャを学んだり、今までできていなかったところを学ぶ年になりました。
自分は、学んだことが本当に有益なのか、実際に個人開発で使ってみて試すというサイクルを回しています。

その一環としてのPivotalTrackerのクローンを作成しました。

今までは技術の検証とプロダクトの両方を回していましたが、今回は**作るものに迷わない**というのと、**ある程度ボリュームのあるプロダクト**という条件で選びました。

**作るものに迷わない** は開発に集中するためです。そもそもですが、プロダクトの検証や収益化などは個人でやるモチベーションが上がらないというのも大きいです...
**ある程度ボリュームのあるプロダクト** は自分がある程度の規模である程度実装を進めないと良いか悪いかを実感できないために、設けている条件です。

こういうケースではこういうツラミがある。や、こういうケースではDXが優れている。など多くのケースを体感したいと思ってやっています。

# 次回予告

明日は[shwld is 誰。このアドベントカレンダーの技術レベルの前提](https://qiita.com/shwld/items/3b626f178f924a3916d8)について書きます。
Jupyter Lab/Notebook：localhostで起動できなくなった場合

# 状況
Edgeを更新（私の場合、バージョン 107.0.1418.56 ）するとjupyter lab/notebookが突然起動しなくなり、下図のエラーが表示された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335742/753e9596-f0b9-1378-5287-afdf07c5f8d5.png)

# 環境
OS: Windows10 Enterprose(20H2)
conda: 22.9.0
Edge: 107.0.1418.56 

# 対処法 
Anaconda Promptを見る限り、ローカルホストでサーバーは起動してるみたい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335742/e22cd3e7-465c-4da7-fe50-987c5eb46715.png)

試しに、「http://127.0.0.1:8888/…」 で始まるアドレスをEdgeのアドレスバーに入れて起動すると、jupyter labが起動した。なるほど、"localhost"が問題か…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335742/fa28a502-723c-1402-7bbd-1d525403f55b.png)

こちらのサイトに解決策があったので、試してみた。
https://blog.masahiko.info/entry/2020/03/10/000025

「edge://net-internals/#hsts」#2と入力してEnterを押すと、HTTS/PKP#1に遷移。
下図のように、Delete domain security policiesに「localhost」と入力し、Delete
を押下した後、念のためEdgeを再起動。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335742/341dd407-4fed-d86b-1d31-9e3190d2704d.png)

その後、Anaconda Promptから「jupyter lab」で起動すると、いつも通り「localhost:8888」で始まるアドレスで起動するようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335742/3eead1c8-a28e-faa8-9d3f-7e960e23c612.png)

#1 HTTS/PKPの詳細はこちら　https://laboradian.com/disable-hsts-for-domain/
#2 私はEdgeを使っているので、「edge://net-internals/#hsts」と入力したが、ブログ中にあるように、「chrome://net-internals/#hsts」と入力しても良いみたい（chromium edgeですからねー）。

# おまけ
Pipeline Pilotのhtml系の表示コンポーネントでも同じエラーが出ていて困っていたが、今回の対策で解決しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335742/d8517c37-c4b2-2fb1-59d4-229e35dff518.png)
2022/11/29主にITとかセキュリティの記事

米政府、ソフトウェアサプライチェーン保護のガイダンスを公開
https://www.security-next.com/141738

政府、病院サイバー対策で新組織　日医などと支援強化(11/27)
https://www.47news.jp/8622334.html

カルダノ基盤のステーブルコインdUSD、開発停止へ(11/26)
https://coinpost.jp/?p=411079

米首都に中国製ドローンが進入　中枢へのスパイ活動懸念(11/27)
https://www.47news.jp/world/8621465.html

アフリカ諸国の中央銀行、CBDC導入に大きな有用性見出す＝BIS報告書(11/27)
https://jp.cointelegraph.com/news/bis-report-finds-uneven-progress-differing-motivations-in-african-cbdc-adoption

楽天カードが期限切れ!?　それフィッシング詐欺の可能性が！(11/27)
https://news.nicovideo.jp/watch/nw11750973

NVIDIAのGPUが医療機器に浸透、ソフト定義化のニーズ捉える(11/28)
https://xtech.nikkei.com/atcl/nxt/column/18/00001/07389/

ビデオ会議中に眼鏡から情報漏洩
パソコンの画面がレンズに反射　閲覧しているサイトを最大94％で識別(11/28)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/041800012/111700193/

ネットワーク監視
ネットワークの稼働状況を確認する作業(11/28)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/091900032/111700051/
【iOS Safari】WEBページ&ローカルサーバ　実機検証を行う方法

WEBページの実機検証を行う方法について、忘れがちなため備忘録として。

## WEBページを検証する方法
iPhoneのWEBインスペクタという機能を利用して、WEBページの検証を行います。

:::note info
Webブラウザなどの開発者向け機能の一つで、表示中のWebページを構成するファイルや、HTMLやCSS、JavaScriptなどのソースコード、各要素のスタイルや属性などの詳細を表示するツールをWebインスペクタあるいは単にインスペクタという。
:::

### iPhoneの設定

① iPhoneの設定を開きsafariの設定へ
② safari設定画面下部の詳細を選択
③ WEBインスペクタの設定タブをオンにする

iPhoneの設定はたったこれだけです。
閲覧したいサイトをiPhoneのsafariで開き、PCとiPhoneをケーブルで接続します。

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2663349/ccc1b84e-62c1-b80a-c682-64e0f9dcf4df.jpeg">


### PCの設定

① PCとiPhoneを接続したら、PCのsafariを開く
② safariメニューの開発を選択
③ 接続しているiPhoneを選択し、iPhoneのsafariで開いているWEBサイトを選択


<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2663349/cc2f7dbb-3caf-0d69-4a95-a73566cd197a.png">


### 検証

これで閲覧したいWEbサイトのSPのコードをPCのsafariで検証することができます。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2663349/3c893a70-f414-b848-b8fd-7ddb43b75f0d.png">
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2663349/f0ba5341-b8a7-3519-94e6-ce2d1421d03f.png">


## ローカルサーバを実機検証する方法
iPhoneからローカルホストにアクセスし、検証する方法です。
ローカルホストで制作したページを開いている前提で進めていきます。

### PCの設定

① 【システム環境設定】を開き、ネットワークを選択
② IPアドレスを確認します

<img width="450" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2663349/0a9244b1-a869-5d02-5c16-1ea1ba5c6d1c.png">


### iPhoneの設定

① iPhone設定を開き、Wi-Fiを選択
② 接続しているWi-Fiの【！】マークを選択
③ 画面下部のプロキシを構成を選択
④ 【手動】→【サーバ(PCのIPアドレスを入力)】→【ポート (ローカルホストのポート番号入力)】
⑤ 入力が完了したら保存をする

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2663349/80e93525-c29b-b8f0-69c0-5d4cf24ef49c.jpeg">

---- あとは【WEBページを検証する方法】と同じく下記を設定

⑥ iPhoneの設定を開きsafariの設定へ
⑦ safari設定画面下部の詳細を選択
⑧ WEBインスペクタの設定タブをオンにする

### iPhoneからローカルホストに接続
【PCのIPアドレス】:【ローカルホストのポート番号】 (例) 123.123.0.12:8000
をsafariのブラウザで開くとローカルホストにiPhoneから接続できます。

### PCの設定

① PCとiPhoneを接続したら、PCのsafariを開く
② safariメニューの開発を選択
③ 接続しているiPhoneを選択し、iPhoneのsafariで開いているIPを選択



### 検証
これでローカルサーバの実機検証が行えます。
検証が終わりましたら、設定を元に戻しておくことを忘れないようにしてください。

以上　iPhone safariでの実機検証でした。
harborでDockerImageのキャッシュを持たせるようにする設定


## harbor
- コンテナイメージをSlefHostedできるソフトウェア
- DockerHubのPullLimitへの対策やインターネット接続ができない完全プライベートネットワークなど、コンテナレジストリを冗長化することができる


## コンテナイメージのキャッシュ
以下のようなイメージでPullする。

クライアント → Harbor → インターネット上で公開されているパブリックリポジトリ

一度、Harborに問い合わせ、自身にキャッシュがなければ、インターネット上に問い合わせしに行くというもの。
キャッシュが効いているHTTPプロキシサーバのイメージ。


## 設定方法
リファレンスの通りに設定すればOK。

ProjectでProxy Cacheを有効にして作成する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/6de6707a-0134-d19d-cdc0-8b1a881be5e0.png)

その前に、DockerHubをレジストリとして登録してあげる必要がある。（リファレンスにのってる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/1538c6b9-f38d-374f-2265-3962614fccf9.png)


## 動作確認

```
docker pull harbor.vamdemic.local/proxy_cache_project/goharbor/harbor-core:dev
```

Harbor上にキャッシュされるのが分かる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/65d81bac-f795-5f0f-dc52-30686583d0d4.png)



## 参考
https://goharbor.io/docs/2.1.0/administration/configure-proxy-cache/
https://blog.cybozu.io/entry/2021/01/26/090000
ローカルネットワーク上のAUTOMATIC1111に別マシンからアクセスする

## はじめに
こんにちは、最近StableDiffusionでイラストを出すのにはまっているねぎまぐろです。

私はよくノートパソコンからGPUを積んでいるマシンにリモートアクセスして使うので、今回のWebUIもGPUマシンで起動しておいてノートパソコンから遊ぶつもりでした。が、同じローカルネットワーク内にも関わらず、表示されたポートにアクセスしても接続が許可されない旨のメッセージが表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401575/d7ca205d-b4b0-5e6e-cfe8-8300a19c5ae0.png)


どうやらlocalhost以外のアクセスが弾かれるようです。このあたりの根本的な解決策が分からなかったので、~~とりあえず応急処置的に対応してみました。~~

**webui側で用意されている方法で妥当なものを教えていただいたので2番目に追記しました。**

### 解決法1: `--share` オプションを使う
これは簡単で、WebUIが標準で用意してくれている機能のようです。

`$ ./webui.sh --share`

これを使うと、インターネット経由でアクセス可能なリンクが発行されます。
欠点としては、ローカルにアクセスするのにインターネットを経由するので、画像の読み込みなどがやや遅くなります。

## 解決法: `--listen --port <port>`オプションをつける
コメント欄で教えていただきましたが、起動オプションに`--listen`をつけるとローカルネットワーク内からアクセス可能になるようです。同時に、`--port <port>`をつけると特定のポートで待受されるようになります。

`$ ./webui.sh --listen --port 5555`

この方法であればインターネットを経由しないので画像の読み込みも高速に行われます

#### 参考
- [Command Line Arguments and Settings · AUTOMATIC1111/stable-diffusion-webui Wiki](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Command-Line-Arguments-and-Settings#command-line-arguments)
- [Stable Diffusion Web UI(AUTOMATIC1111版)を導入したのとWaifu DiffusionやTrinArtのモデルを使ってみたのと【AI画像生成】](https://kirarico.net/memo/2121/#toc8)

### ~~解決法2: redirでポートフォワードする~~
~~localhostでしかアクセスできないポートの原理は分かりませんが、redirを使って7860を適当なポートにフォワードしてやるとアクセスできることが分かりました。~~

~~`$ ./webui.sh & redir --cport=7860 --lport=5555`~~

~~これならばインターネットを経由しないので画像の読み込みも高速に行われます。~~

## おわりに
~~もし根本的な解決を知っている方がいらっしゃったら教えていただけると幸いです。~~

@ko3n さん教えていただいてありがとうございました！

みなさん良いAIお絵描きライフを！
Google Play Developer API を使うための設定方法(1)

Google Play Developer APIにアクセスするためにはGooglePlayConsoleの
【すべてのアプリ】の状態で左のメニューから【設定】→【APIアクセス】と進み
![1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984652/410922ed-d31c-df47-6617-8a8fa08836b8.jpeg)
Google Play Android Developer APIをオンにしてすぐ下の【APIの詳細を表示】を選択
![2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984652/118e218f-4d77-acd8-6236-9107c7b5629c.jpeg)
【認証情報】から上の【＋認証情報を作成】を選択し、『APIキー』と『OAuthクライアントID』を作成します。
『APIキー』の方はボタンを押すだけで、『OAuthクライアントID』は色々と入力が必要です。
![3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984652/2253e594-aadc-52f3-bba1-bbbfb8bcb5b8.jpeg)
![4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984652/12c41da4-e953-997f-c149-4044ec08a94f.jpeg)
SHA-1証明書のフィンガープリントの項目は、各アプリのダッシュボード内の【設定】→【アプリの完全性】→【アプリの署名】へと進みそこのSHA-1証明書のフィンガープリントをコピペでOKです。
![6.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984652/5679d07f-5a5d-fc9a-43c2-ee273183a46e.jpeg)
その後【作成】を選択してOAuthクライアントIDを作ります。
クライアントIDを作成したらその時の表示画面からJSONをダウンロードしておきます。（あとからでもダウンロードできます）
![7.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984652/e4be0617-881b-e8f7-1498-6fd7889c8c94.jpeg)
続けて【OAuth同意画面】へと進み公開ステータスはテスト、ユーザーの種類は外部
テストユーザーに自分のGoogleアカウントを設定します。
その後【アプリを編集】を選択し『アプリ名』『ユーザーサポートメール』
『承認済みドメイン』『ディベロッパーの連絡先情報』を入力します。

『承認済みドメイン』には自分のホームページのドメインを承認してから使用しました。承認のためにはDSN設定が必要で、自分がレンタルしているXserverの場合だと
![8.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984652/b5996b74-d229-442b-0d3e-c03fc5334cb9.jpeg)
![9.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984652/74b8d957-933e-1a8d-325c-33da08a79e9b.jpeg)
上の画像の赤丸の所にGoogleから発行されたDSNレコードをコピペします。
これでドメインが承認されるので、それを『承認済みドメイン』に使用します。

アプリを出すならホームページ位もってるよなぁ？
というGoogle様の意図だと思います。

【保存して次へ】を選択します。スコープはよくわからないのと
特に顧客の個人情報を吸い上げる必要がないので何もせずに【保存して次へ】
テストユーザーには自分のGoogleアカウントを入れて【保存して次へ】
これでOAuthの設定は一旦完了です。

今回の記事はここまでです。お疲れ様でした。
apt updateがうまくいかない

# 環境
Ubuntu server 22.04.1 LTS
# apt update が動かない
 ubuntu server を入れていつも通り apt update をしたらパッケージの情報を取ってくる時点でエラーを出していた。
`Ign:http://` みたいなログが延々出てくる。

固定 IP の設定を間違えたのかと思ったが正常だった。

# 原因と解決法
## 原因
名前解決が出来ておらずサーバーまで到達していなかったため。
## 解決法
`/etc/systemd/resolved.conf` の
```
[Resolve]
#DNS=
```
を
```
[Resolve]
DNS=8.8.8.8
```
にする。
天下の Google 様のパブリックDNSを指定した。
変更した設定を反映させるために
```
sudo systemctl restart systemd-resolved
```
で名前解決だけ再起動。
解決!

# tips
どうしても Google にお世話になりたくない！けど長いアドレスは覚えられない！という人へ。
- 1.1.1.1 (Cloudflare)
- 9.9.9.9 (IBMなど)

をどうぞ。(括弧内は運営会社)

# 最後に
Ign の3文字を見たらとりあえず名前解決を疑ってみるのも手。
Ruby Singleton Class

## メソッドの定義場所
メソッドがどこに定義されているのかは```owner```メソッドを使うことによって確認できます。
```ruby
class User < ApplicationRecord
    def self.from_class
        return "from class"
    end

    def from_instance
        return "from instance"
    end
end
```
上記のようなクラスを想定します。
```ruby
pry(main)> User.instance_method(:from_instance).owner
# => User(...)
pry(main)> User.method(:from_class).owner
# => #<Class:User(...)>
pry(main)> User.singleton_class
# => #<Class:User(...)>
```
インスタンスメソッドはUserクラスに定義されている一方で、クラスメソッドはsingleton_classに定義されています。

```ruby
pry(main)> user = User.last
pry(main)> user.class
# => User(...)
pry(main)> User.class
# => Class
```
```userインスタンス```の所属先は```Userクラス```、```Userクラス```の所属先は```Classクラス```(UserクラスはClassクラスのインスタンス)であるのに、なぜクラスメソッドはsingleton_classに定義されているのでしょうか。

## singleton_classとは

https://medium.com/@leo_hetsch/demystifying-singleton-classes-in-ruby-caf3fa4c9d91

↑ こちらの記事を読んでいただければ僕の記事は読まなくても大丈夫です。

`singleton` = `特異`

特異メソッド(singleton_method)はクラスメソッドのような、特定のオブジェクトのみが持つメソッドです。
同様に考えると、特異クラス(singleton_class)は、特定のオブジェクトのみが持つクラスです。

インスタンスメソッドが呼び出された場合、そのインスタンスの所属先のクラス内でメソッドを探索します。
この理論でいくと、クラスメソッドが呼び出された場合は、所属先であるClassクラス内でメソッドを探索するはずです。

しかし、Classクラスがあらゆるクラスの所属先であることを考えると、全てのクラスメソッドがClassクラスに定義されていることになります。
これでは全てのクラスから、全てのクラスメソッドが呼び出せるようなカオスな状態になってしまい、機能的によろしくないです。

ここで登場するのが**Singleton Class**です。

https://docs.ruby-lang.org/ja/latest/method/Object/i/singleton_class.html

Singleton Classはそのオブジェクトに特有の隠されたクラスです。

これによってインスタンスがメソッド呼び出しの際に所属先のクラスを探索するように、クラスメソッドの場合はsingleton_classを探索するという、同じような設計を保つことができています。

#### singleton_classの継承関係
クラスを継承した場合、スーパークラスに定義されているインスタンスメソッドはサブクラスでも呼び出すことができますが、これはクラスメソッドも同様です。

AdminUserクラスをUserクラスが継承する場合を考えます。
```.rb
class AdminUser < User
end
```
```ruby
pry(main)> AdminUser.superclass
# => User(...)
pry(main)> User.singleton_class
# => #<Class:User(...)
pry(main)> AdminUser.singleton_class.superclass
# => #<Class:User(...)
```
このように、Userクラス、AdminUserクラス間だけでなく、Userクラスのsingleton_class、AdminUserクラスのsingleton_classの間にも継承関係があることがわかります。

## 参考にしたサイト

https://maximomussini.com/posts/understanding-the-singleton-class
VPNゲートウェイとサイト間接続・ポイント対サイト接続・仮想ネットワーク間接続について

●VPNゲートウェイ
Azure上に作成可能な仮想ネットワークゲートウェイの一種。
パブリックインターネット経由で異なるネットワーク間を接続し、暗号化されたトラフィックを送受信するために使用される。

VPNゲートウェイをしようすることで以下の3つの接続を構成できる

●サイト間接続
オンプレみうｓネットワークとAzureの仮想ネットワークを接続するための構成。
３つの接続構成のうち最も代表的、VPNプロトコルいんはIPsec/IKE(IKEv1またはIKEv2)を使用。

●ポイント対サイト接続
個々のクライアントコンピュータをAzureの仮想ネットわーｌ区に接続するための構成。インターネット経由で最大10000まで任意で実行されるWindowsa,Mac,Linuxコンピューターを仮想ネットワークに接続する。OpenVPNプロトコル、SSTP,IKEv2の核プロトコルが使用できる。

●仮想ネットワーク間接続(VNet間接続)
Azure上の仮想ネットワーク同士をVPNで接続するための構成。他の接続構成とは異なり、仮想ネットワーク間接続のトラフィックは、インターネットではなくAzureのバックボーンネットワークを経由して送信される。


●サイト間VPN接続の実装手順
１、仮想ネットワークおよびゲートウェイサブネットの作成
２、VPNゲートウェイの作成
３、ローカルネットワークゲートウェイの作成
４、接続の作成と確認

※ゲートウェイを配置するための専用サブネットのことをゲートウェイサブネットとよ日、「GatewaySubnet」という「名前をつける必要がある。
また、通常のサブネットの作成時と同じ様にアドレス範囲も設定するが、このサブネットにはゲートウェイしか配置しないため、アドレスプレフィックス長として/27か/28を使用することが推奨されている。