OmniAICreator/Qiita-1.07M huggingface dataset:
SwiftでTDD写経 第11章 不要になったら消す

2つのサブクラスDollarとFrancにはもうコンストラクタしか残っていない。
コンストラクタだけのサブクラスを残しておく理由はないので、サブクラスを消してしまいたい。

サブクラスのあらゆる参照を消し去ることが目的。
まずは親クラスのFrancを返していたメソッドから変更し、同様にDollarもMoneyにする。

変更前
```playground.swift

    static func dollar(_ amount:Int) -> Dollar{
        return Dollar(amount,"USD")
    }


    static func franc(_ amount:Int) -> Franc{
        return Franc(amount,"CHF")
    }
  
``` 
変更後

```playground.swift
    static func dollar(_ amount:Int) -> Dollar{
        return Money(amount,"USD")
    }


    static func franc(_ amount:Int) -> Franc{
        return Money(amount,"CHF")
    }

```

次にクラスの等価性のテストに関しては他のテストで十分テストされているので、もう消せるのではないか？

```playground.swift
   func testEquality(){
        assert(Money.dollar(5) == Money.dollar(5))
        assert(Money.dollar(6) == Money.dollar(6))
        assert(Money.franc(5) == Money.franc(5))
        assert(Money.franc(6) == Money.franc(6))
        assert(Money.franc(6) != Money.franc(3))
        assert(Money.franc(6) == Money.dollar(6))
    }
```

うん、、、いらないね、、、過剰テストなので消す。


```playground.swift
   func testEquality(){
        assert(Money.dollar(5) == Money.dollar(5))
        assert(Money.dollar(6) == Money.dollar(6))
        assert(Money.franc(6) == Money.dollar(6))
    }
```

前章で書いたテスト、testDifferentClassEquaﾕﾕtyは複数のクラスがある状況でしか意味をなさない。
ましてやサブクラス消すのでこのテストは消すぞ。

次にtestFrancMultiplicationはFrancに依存してる。こいつも消すぞ。
あらゆるものをけした結果以下のようになるぞ。（雑

```playground.swift
var moneytest = MoneyTest()

moneytest.testMultiplication()
moneytest.testEquality()
moneytest.testCurrency()

class MoneyTest{
    init(){}
    
    func testMultiplication(){
        var five:Money = Money.dollar(5)
        assert(Money.dollar(10) == five.times(2))
        assert(Money.dollar(15) == five.times(3))
    }
    
    func testEquality(){
        assert(Money.dollar(5) == Money.dollar(5))
        assert(Money.dollar(6) == Money.dollar(6))
        assert(Money.franc(6) != Money.dollar(6))
    }
    
    func testCurrency(){
        assert("USD" == Money.dollar(1).currency())
        assert("CHF" == Money.franc(1).currency())
    }

}

///親クラス
class Money :Equatable{
    var _amount:Int
    var _currency:String
    init(_ amount:Int,_ currency:String){
        self._amount = amount
        self._currency = currency
    }
    
    static func == (lhs: Money, rhs: Money) -> Bool {
        print(lhs.currency())
        print(rhs.currency())
        return lhs._amount == rhs._amount &&
        lhs.currency() == rhs.currency()
    }
    
    func currency() -> String{
        return _currency
    }
    
    func toString() -> String{
        return _amount.description + " " + _currency
    }
    
    func times(_ multiplire:Int)  -> Money{
        return Money(_amount * multiplire, _currency)
    }
    
    static func dollar(_ amount:Int) -> Money{
        return Money(amount,"USD")
    }
    
    static func franc(_ amount:Int) -> Money{
        return Money(amount,"CHF")
    }
}



```
【Python】Anaconda環境で、急に環境が削除出来なくなった場合

## 環境
 * CentOS・・・CentOS Linux release 7.8.2003 (Core)
 * Anaconda・・・conda 23.1.0


## 起きたこと
環境構築で作り直したくなったのでいつも通り以下のコマンドで環境を削除を試みたが、エラーも何も出ず、環境が表示されない。こんなこと今までなかった。

```
conda remove -n 環境名 --all
```

ググってみたら、削除出来ない系の記事が1つだけヒットした。
https://qiita.com/noa_28/items/1f1f75cc0cb7831b725b

記事通り環境のbinフォルダで以下を実行した後に環境削除コマンドをやったが変わらず。

```
rm -rf *.app
```

## 解決した方法
 * ①Anacondaのフォルダの環境一覧のあるディレクトリに移動してから、
削除対象のフォルダを強制削除した。
 * ②ここで環境一覧確認コマンドの「conda info -e」を実行したら、「さっき削除した環境が見つからない」といったエラーが出てしまう。これだけでなく、condaコマンド自体一時的使えなくなる。(condaコマンドのどの操作してもエラーになる)
このエラーが出ること自体は先ほどの記事と同じだが、ルートディレクトリなど他のディレクトリに移動したら変わるものではなかった。僕の場合はanacondaのコマンドではなく環境フォルダを強引に削除したので、整合性が取れない状態になったのだと思う。
 * ③ここで、新たに全く同じ名前で環境を作る。すると、先ほどのエラーは出なくなった。これで作り直し成功(もしNo such file or directoryみたいに出たら、一度ターミナルを閉じて新しいターミナルを開いてから再実行したら環境作成処理が走る)
SwiftでTDD写経 第9章 歩幅の調整



通貨(Currency)の概念を導入する。

①MoneyクラスにCurrencyの抽象Method入れる。
②やっぱ親クラスにプロパティ入れよ。
③コンストラクタでCurrencyの値入れよ。
④timesMethodは自分のコンストラクタ呼び出すんじゃなくてファクトリメソッド使おう！

```playground.swift
import UIKit

var moneytest = MoneyTest()

moneytest.TestMultiplication()
moneytest.TestEquality()
moneytest.TestFrancMultiplication()

class MoneyTest{
    init(){}

    func TestMultiplication(){
        var five:Money = Money.dollar(5)
        assert(Money.dollar(10) == five.times(2))
        assert(Money.dollar(15) == five.times(3))
    }

    func TestEquality(){
        assert(Money.dollar(5) == Money.dollar(5))
        assert(Money.dollar(6) == Money.dollar(6))
        assert(Money.franc(5) == Money.franc(5))
        assert(Money.franc(6) == Money.franc(6))
        assert(Money.franc(6) != Money.franc(3))
        assert(Money.franc(6) != Money.dollar(6))
    }
    
    func TestFrancMultiplication(){
        var five = Money.franc(5)
        assert(Money.franc(10) == five.times(2))
        assert(Money.franc(15) == five.times(3))
    }
}
///親クラス
class Money :Equatable{
    var amount:Int
    var currency:String

    init(_ amount:Int,_ currency:String){
        self.amount = amount
        self.currency = currency
    }
    
    static func == (lhs: Money, rhs: Money) -> Bool {
        return lhs.amount == rhs.amount && type(of: lhs) == type(of: rhs)
    }

    func currency()-> String{
            return currency
        }
    
    func times(_ multiplire:Int)  -> Money{
        return Money(amount , currency)
    }
    
    static func dollar(_ amount:Int) -> Dollar{
        return Dollar(amount,"USD")
    }
    
    static func franc(_ amount:Int) -> Franc{
        return Franc(amount,"CHF")
    }
    
}

///Dollar子クラス
class Dollar:Money {
    override init(_ amount:Int,_ currency:String){
        super.init(_ :amount , _ :currency)
        self.amount = amount
        self.currency = currency
    }
    override func times(_ multiplire:Int)  -> Dollar{
        return Money.dollar(amount * multiplire)
    }
}


///Franc子クラス
class Franc:Money {
    override init(_ amount:Int, _ currency:String){
        super.init(_ :amount , _ :currency)
        self.amount = amount
        self.currency = currency
    }
    override func times(_ multiplire:Int)  -> Franc{
        return Money.franc(amount * multiplire)
    }
}

```

振り返り
・大きめの設計変更にのめり込みそうになったので、その前に手前にある小さな変更に着手した。
・差異を呼び出し側(FactoryMethod側）に移動することによって、2つのサブクラスのコンストラクタを近づけていった。
・リファクタリングの途中で少し寄り道して、timesメソッドの中でFactoryMethodを使うように変更した。
･Francに行ったリファクタリングをDollarにも同様に、今度は大きい歩幅で一気に適用した。
・完全に同じ内容になった2つのコンストラクタを親クラスに引き上げた。
[Excel] エクセルで営業日のみを数える方法 Workday()

# はじめに
エクセルを使用する上で日数を数えることは非常に多い。
しかし納期が祝日設定だったり、会社の休みだったりすると依頼先からの苦情を聞くことになる。
ここでは納期設定を簡単に且つ完璧に行うためのエクセルの基本的な関数`WORKDAY()`を紹介する


# 従来の方法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/b560eba8-26b8-8d08-e7a0-c1680ff6fce9.png)
一番よく使っている方法はこのように、基準日から+1などをした結果であると思う。実際に私の部署でもこれが一般的で、納期設定が土日になり苦情が来るような状況であった。これを解決するために見つけた関数が`WORKDAY()`であった。

# Workday()使用方法
`WORKDAY(開始日、日数、[祭日])`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/d2bf4f11-8565-38de-a605-94d418032413.png)

このように土日を数えず、営業日後の結果が平日になることを確認することができた。

## 祝日or休み設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/2caef1e4-8e09-64c4-b419-cf24cb4af739.png)

この関数において、祝日は基本的は考慮せず、自分から設定してあげる必要がある。人によっては祝日も自動で計算して欲しいこともあると思うが、自分は世間と異なる祝日（トヨタカレンダー）であるため、会社にあわせた休みを設定する必要がある。
実際に`WORKDAY`を導入したことはよかったが、会社の長期休みの期間中も営業日として数えてしまい、納期が短すぎるという苦情を受けたことがある。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/6a94daeb-dec7-2203-c1f8-657a9830e5a1.png)
このように工数を１日/人として依頼書を出す時、会社の長期休みなどを予めて設定しておくと、うっかり休み中の納期設定をしてしまうなどのミスを予防することができる。


# 終わりに
納期の日付は依頼を受ける側からすればとても敏感な部分なのでミスをしてはいけない部分ではあるが、週に数百枚の書類を書いていると納期の確認が難しくなる。`WORKDAY()`関数を活用することで最低限のミスは予防しましょう。

# 参考
https://www.becoolusers.com/excel/workday.html#:~:text=WORKDAY%E9%96%A2%E6%95%B0%E3%81%A7%E3%81%AF%E3%80%81%E5%9C%9F%E6%9B%9C%E3%83%BB%E6%97%A5%E6%9B%9C,%E6%AC%84%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%BE%E3%81%99%E3%80%82&text=%E3%80%8C%E7%A5%9D%E6%97%A5%E3%80%81%E7%8B%AC%E8%87%AA%E3%81%AE%E4%BC%91%E6%A5%AD%E6%97%A5,%E3%81%AE%E3%80%81%E6%97%A5%E4%BB%98%E3%81%AE%E9%83%A8%E5%88%86%E3%81%AE%E3%81%BF%E3%80%82
５分で紹介「キタミ式イラストIT塾応用情報技術者」

# はじめに
この記事は 
**「キタミ式イラストIT塾応用情報技術者」** を**５分**で**この本の魅力や大まかな内容**を理解することを目的とした記事です。

この記事で少しでも興味を持ってこの本を読むきっかけになれば幸いです。

<img width="300" alt="名称未設定のアートワーク (2).jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2921163/cae00e79-c829-8a33-e858-46ff87461910.jpeg">

# 目次
**・概要
・個人的な感想
・引用**

# 概要
この本は**全855ページ、19Chapter**で構成されています。

内容は**応用情報技術者試験の出題範囲の内容**となっていて、
出題範囲の内容が網羅されています。

各Chapterの最初には**導入マンガ**があり、
その次に**Chapterの内容**の解説、
**過去問と解説**という順で書かれています。

全ページが**カラー**で書かれていて、
図やグラフが多用されていて**視覚的に理解できるように工夫**されています。

図以外にもいくつかの**キャラクター**が登場して、
読者が理解しやすいようにキャラクターの**コメント**が書かれています。

その他に重要な言葉には**太文字**になっていたり、
**色**がついていてわかりやすくなっています。

# 個人的な感想

この本を読んで、
この本は**応用情報技術者試験に合格したい人の
最初の一冊としておすすめできる本**だと思いました。

理由は以下の通りです。
・**わかりやすい工夫が多いため初学者に優しい
・出題範囲が網羅されている
・視覚的に理解できる**

さらに試験の過去問題集など
**演習問題と一緒に使うと**より効率的な学習につながると思います。

# 引用
>キタミ式イラストIT塾応用情報技術者
著 きたみりゅうじ
2020/12/12

https://store.shopping.yahoo.co.jp/bookfan/bk-4297131889.html?sc_i=shp_pc_search_itemlist_shsrg_title
【Mac】rbenv を導入して Ruby のインストールとバージョン管理を簡単にする

## 概要
以下についての簡単な備忘録

- Ruby をインストールする
  - ただし、バージョンの切り替えを簡単に行えるようにバージョン管理ツールを利用する
- Ruby の言語バージョン管理には「rbenv」を採用する
  - rvm は使用しない
- 「rbenv」単体だけでは Ruby のインストールはできないため「ruby-build」もあわせて導入する

### 前提
macOS を利用しているので、Homebrew でインストールする前提です。
事前に Homebrew をインストールしておいてください（[方法はこちら](https://qiita.com/to3izo/items/3171220733d0e2d18bfb)）。
Windows の方は、都度、読み替えてください。

## 手順

現在の Ruby バージョンを事前確認
```zsh
# バージョン確認
ruby -v

# 結果：既に入っていれば、バージョンが表示される
ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.x86_64-darwin22]
```

### rbenv インストール

「rbenv」本体は切り替え機能しかなく、Ruby をインストールすることはできないため、Ruby をインストール可能な「ruby-build」も一緒に導入します。
```zsh
brew install rbenv ruby-build
```

確認
```zsh
# バージョン確認コマンドで結果が返ってくれば OK
rbenv -v
```

### 設定ファイルに追記
※ `.zshrc` がまだない場合は、ホームディレクトリ直下に作成してください（`.zshrc` がわからない方向けの記事は[こちら](https://qiita.com/to3izo/items/b6a735793d55d65c5b10)）。

これをやらないと、rbenv で Ruby をインストール・設定してもバージョンが反映されないので注意。
以下のコマンドで設定ファイルに追記する。

```zsh
# 以下の２つを実行して、設定ファイルに追記
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.zshrc 
echo 'eval "$(rbenv init - zsh)"' >> ~/.zshrc
```

設定ファイルを反映させる
```zsh
source ~/.zshrc
```

確認（`/Users/ユーザ名/.rbenv/bin` と `RBENV_SHELL` が追加されている）
```zsh
# 環境変数 確認コマンド
printenv

# 結果表示
：
HOME=/Users/ユーザ名
PATH=/Users/ユーザ名/.rbenv/shims:/Users/ユーザ名/.rbenv/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin
RBENV_SHELL=zsh
：
```

### Ruby をインストール

```zsh
# インストールできるバージョンを一覧表示
rbenv install --list

# 一覧の中から、バージョンを指定してインストール（例：v3.1.3）
rbenv install 3.1.3
```

確認
```zsh
# インストールしたバージョンを一覧表示
rbenv versions

# 結果（使用中のバージョンに * 印がつく）
* system # 元々入っているものは "system" と表示される
  3.1.3
```

### Ruby のバージョンを切り替える

バージョンを選択
```zsh
# 一覧の中から設定してバージョンを切り替える
rbenv global 3.1.3
```

確認
```zsh
# バージョン確認
ruby -v

# 結果
ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e) [x86_64-darwin22]
```

無事、インストールとバージョン切り替え完了！

## おまけ
rbenv をインストールして、Ruby を設定しても `ruby -v` で反映されず切り替わらない場合がありますが、多くの場合はシェルの設定ファイルへの追記と反映ができていない可能性があります。
.zshrc（または、.bash_profile）への設定部分は忘れずに行いましょう。

`which` コマンドで Ruby がどこを参照しているのか確認するのが良いかもしれません。

```zsh
# Ruby コマンドがどこを参照しているか確認
which ruby

# 結果①：元々入っている ruby など、別の場所を参照している場合（rbenv で切り替わらない）
/usr/bin/ruby
# 結果②：正しく参照されている場合（rbenv で切り替えることができる状態）
/Users/ユーザ名/.rbenv/shims/ruby
```

また、各プロジェクト内で `.ruby-version` などでローカルバージョンを指定している場合は、global よりローカルを優先します。意図していない場合はご注意ください。
Salesforce で443以外のportで外部にリクエストを送信したい時


Salesforce では、送信ポートを以下のいずれかに制限しています。
80: このポートは、HTTP 接続のみを受け付けます。
443: このポートは HTTPS 接続のみを受け付けます。
1024 ～ 65535 :これらのポートは、HTTP または HTTPS 接続を受け付けます。

443以外のポートを使う場合、リモートホスト登録の際指定のポートも含める必要があります。
ポートの記載がないとapexで以下のエラーがスローされます。

common.apex.runtime.impl.ExecutionException: Unauthorized endpoint

以下のようにポート設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259482/d9e98dab-4375-b8e4-4ce7-7140d33b636f.png)
Polarsでjsonlファイルを読み書きする

最近[`Polars`](https://gihyo.jp/article/2023/02/monthly-python-2302)というRust製の高速データフレームライブラリが流行っているようです。今回は[Pandasでのjsonlの読み込み方](https://qiita.com/meshidenn/items/3ff72396fe85044bc74f)に倣って、Polarsでjsonlファイルを扱ってみます。

## JSON Linesとは
`JSON Lines`とは、改行区切りで1行1JSONオブジェクトという形式で定義されたファイルで、拡張子は`.jsonl`を使います（参考：[JSON Lines](https://jsonlines.org/), [atatus JSONL](https://www.atatus.com/glossary/jsonl/)）。以下にjsonlファイル例を示します。

```json: sample.jsonl
 {"id": "0000000", "name": "hoge", "content": "toto"}
 {"id": "0000001", "name": "piyo", "content": "titi"}
 {"id": "0000002", "name": "fuga", "content": "tutu"}
```

Pandasでは、以下にようにしてjsonlファイルを読み書きします[^1]。
```python
import pandas as pd
df = pd.read_json('sample.jsonl', orient='records', lines=True) # 読み
df.to_json('hoge.jsonl', orient='records', force_ascii=False, lines=True) # 書き
```
しかし、Polarsの[read_jsonメソッドのドキュメント](https://pola-rs.github.io/polars/py-polars/html/reference/api/polars.read_json.html)には、これらのキーワード引数は存在しません。

## Polarsでの読み書き方法
結論からいくと、以下のようになります。
```python
import polars as pl
df = pl.read_ndjson('sample.jsonl') # 読み(先行評価)
df.write_ndjson('hoge.jsonl')       # 書き
df = pl.scan_ndjson('sample.jsonl') # 読み(遅延評価)
```

[read_ndjsonメソッド](https://pola-rs.github.io/polars/py-polars/html/reference/api/polars.read_ndjson.html)で改行区切りJSONファイルを読み込むことができます。
それはいいのですが、この`NDJSON`というのがよくわからなかったので以下にまとめます。

### NDJSONとは
`NDJSON`とは、`newline delimited JSON`の略です。[JSONLからフォークされたもの](https://zenn.dev/katoaki/articles/aef091a3580f5e)らしいですが、JSONLと同じと思って問題ないのだと思います。

## まとめ
JSONLかNDJSONかどっちかにすることはできなかったのだろうか。

[^1]: `orient`は入力ファイルの形式を指定でき、`lines`は1行ずつ出力するか決めるオプションです（参考：[qtatsuの速報 pythonでJSON Linesを作る方法](https://qtatsu.hatenablog.com/entry/2021/03/27/143233), [note.nkmk.me pandas.DataFrameをJSON文字列・ファイルに変換・保存（to_json）
](https://note.nkmk.me/python-pandas-to-json/)）。
bashについて（備忘録）

## bash(Bourne Again Shelln)とは
- シェルの種類の一つ
- Unix系のシステムで用いられるシェルのこと
- Macや Windowsにも幅広く普及しているシェル


## シェル(Shell)とは
- ユーザーとコンピュータの橋渡しをするプログラム

## bashrcとは
- bashを起動したときに読み込まれる設定ファイル
- シェルに必要な設定を書く場所
- 具体的にはよく使うコマンドの短縮形を登録するエイリアスなどを設定できる


## bash_profileとは
- ログインシェルがbashの状態でログインしたときに読み込まれる設定ファイル
- 実行される順番としてはbash_profile、bashrcとなる
- 環境変数[^1]を書く場所
[^1]:　環境変数
その変数を定義したシェル上、およびそのシェルで実行されるプログラムすべてで有効な変数のこと

## ※追記
ログインした際にファイルが実行される順番はこちら
1 /etc/profile
2 ~/.bash_profile
3 ~/.bash_login
4 ~/.profile
5 ~/.bashrc

今まで、なんとなくbash_profileを使っていましたが、新しいパソコンを購入し、homebrewを入れた際にPATHが~/.profileに入力されたので大丈夫かなと思って調べました〜
toBe(),toEqual(),toStrictEqual()でオブジェクトや配列を比較する時の違いを知る

GPT-4さんとの会話を楽しんでします。
最近は`jestのテストについて勉強中`なので、その質問のやりとりがメインとなっています。

今回は、`toBe(),toEqual(),toStrictEqual()`についてAIのユイに聞きながら学習を進めていました。
それぞれでオブジェクトを比較する時、どのような違いがあるのか見ていきましょう。

## toBe(),toEqual(),toStrictEqual を使い分ける
まずそれぞれの役割を理解します。

### toBEを使うケース
 - プリミティブ値を評価する
 - 同じオブジェクトの参照を持つ変数かを評価する

### toEqualを使うケース
 - オブジェクトのプロパティの値を評価する

### toStrictEqualを使うケース
 - クラスや、配列内の未定義(undefined)なプロパティを含む、厳密なオブジェクトの評価する


## toBe()を使ってみる

toBeの場合基本的にプリミティブ型のテストとして使いますが、オブジェクトのテストとしても使えます。
ただし、toBeは`参照も見ている`ので使用するときは注意が必要です

```jsx
    const obj1 = { a: 1, b: 2 };
    const obj2 = { a: 1, b: 2 };
    const obj3 = obj1;
    expect(obj1).toBe(obj3); // 参照が同じためtrue
    expect(obj1).toBe(obj2); // 参照が違うためコケる。

    const arr1 = [1, 2];
    const arr2 = [1, 2];
    const arr3 = arr1;
    expect(arr1).toBe(arr3); // 参照が同じためtrue
    expect(arr1).toBe(arr2); // 参照が違うためコケる。
```

## toEqual()を使ってみる
単純に値が同じかどうかを調べたい場合、`toEqual()` を使用するのがシンプルです。

```jsx
    const obja = { a: 1, b: 2 };
    const objb = { b: 2, a: 1 };
    expect(obja).toEqual(objb); // 参照が違っても値が同じなのでtrue
    
    const arra = [4, 5];
    const arrb = [4, 5];
    const arrc = [5, 4];
    expect(arra).toEqual(arrb); // 参照が違っても値が同じなのでtrue
    expect(arra)
.toEqual(arrc); // 順序が違うのでコケます
```

## toStrictEqual()を使ってみる

オブジェクトや配列の値だけでなく、プロトタイプも含めた厳密な比較を行います。
まずは`toEqual()`と同等の比較を行ってみます。

```jsx
    const obja = { a: 1, b: 2 };
    const objb = { b: 2, a: 1 };
    expect(obja).toStrictEqual(objb); //成功する

    // 未定義とundefinedを区別しないので成功します
    expect([, undefined, 1]).toEqual([, , 1]); 
```

オブジェクトの値の比較について`toEqual()`と同様の結果が得られることがわかりました。
続いて、オブジェクトのプロトタイプが違う時を見てみます。

```jsx
    function Obja() {
      this.a = 1;
    }
    function Objb() {
      this.a = 1;
    }
    expect(Obja).toEqual(Objb); // プロトタイプが違うのでコケます

    const Objc = () => {
      this.a = 1;
    };
    const Objd = () => {
      this.a = 1;
    };
    expect(Objc).toEqual(Objd); // プロトタイプが違うのでコケます

    // 未定義とundefinedを厳密に区別します。
    expect([, undefined, 1]).not.toStrictEqual([, , 1]); 
});

```

:::note info
Q - プロトタイプってなんだろう？
A - オブジェクトが他のオブジェクトから継承する仕組み(継承親の値を探しにいく)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129861/addd75c9-c419-6348-172e-fec78cf4fd44.png" width="600">
(ググるよりいいな)
:::



## まとめ

`toBe(),toEqual(),toStrictEqual()`でオブジェクトや配列を比較する時の違いを見ていきました。
`toBe(),toEqual()` はよく使いそうですが、`toStrictEqual()`はそれほど出番がないように感じます。
ただ、どのようなマッチャーが存在しおり、それぞれどう違うのかを学んでおくことは大切です。
適切なマッチャーを即座に選択できるようこれからも学習を進めます。
AWSわからない単語

## VPC(Virtual Private Cloud)とは
- AWS アカウント専用の仮想ネットワーク
## サブネットとは
- ネットワーク内のさらに分割された小さなネットワークのこと。
- VPC の IP アドレスの範囲
- サブネットはVPC内に複数設置することができる。
- 1つのAZ[^1]（アベイラビリティゾーン）を指定して配置される. 複数のAZに一つのサブネットを作ることはできない。
[^1]:　AZ（アベイラビリティゾーン）とは
1つのAWSリージョン内でそれぞれ切り離され、冗長的な電力源、ネットワーク、そして接続機能を備えている1つ以上のデータセンターのこと。
- バブリックサブネットとプライベートサブネットに分かれる
### パブリックサブネット
- インターネット側から、中のリソースにアクセス可能
- サブネットの中からインターネット側にもアクセス可能

### プライベートサブネット
- インターネット側から、中のリソースにアクセスできない 
- サブネットの中からはインターネット側にアクセス可能
- Internet Gateway[^2]へのルートがない
- インターネットに接続するためにはパブリックサブネット内にNAT Gateway[^3]が必要

[^2]:　Internet Gatewayとは
内部のネットワークから外部のインターネットに接続するためのゲートウェイ機能の総称
[^3]:　NAT Gatewayとは
プライベートサブネットからインターネットにアクセスするためのゲートウェイ

## セキュリティグループとは
- VPC（AWSネットワーク）上で通信制御をするファイアウォール機能。
- サーバやロードバランサー毎に立ちはだかる壁のような役割でIPや通信プロトコル単位、VPC内同士での通信であれば通信元セキュリティグループのIDを指定して制御できる。
ChatGPTがプログラミング学習のパートナーになるか

## 目的
最近ChatGPTの有料プランに加入して色々試しているときに、ふと「誰かに書いたプログラムのレビューをして欲しい。ChatGPTを使ったらプログラミングの学習のパートナーになるのでは...?」と思い立ちました。自分も学習始めの頃は「エラーの内容が英語で書かれているし、何を指摘しているかよくわからない！もういや！」となっていましたが、ChatGPTならもう少し人間に寄り添ってくれるかもしれません。少し実験してみました。


## 実験
ChatGPTに、以下のような形で少々雑なリクエストを出してみました。人間にこんなお願いをしたら「んな初歩的なこと俺に頼むな」「は？そんなもんググったら一発だろ」「本読め」と罵詈雑言を浴びせかけられること間違いなしでしょう。この誰かに頼みごとをするというハードルがグッと下がるのが、AIの良いところですね。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290256/110f2ef4-1756-0ff8-b40a-181b73a85e18.png)

そうすると入門用の例題を7つほどつらつらと紹介してくれました。確かに初心者にはちょうどいい難易度かもしれません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290256/88f90447-c242-ee1e-7d3a-bf9aa255c3ab.png)

と、いうことで1番目の問題「1から10までの整数を順番に出力するプログラムを書いてください。」に対して、下記のようなクソコードを投げてみました。さて、どうなるか...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290256/4ea3404c-22c2-ab21-c22e-d2ab3b716fda.png)

以下がChatGPTの回答です。うーんさすが...正解ということを判定するのはもちろんのこと、もっとスマートな解答例まで教えてくれる...優しい...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290256/9b1c471b-44b7-bc02-21c1-01ed4055c865.png)

## わざと間違った出力をするプログラムを渡してみる

では、以下のような「エラーではないけど、所望の答えと異なるプログラム」を与えてみましょう。このプログラムでは1〜10だけでなく11も出力されてしまうので、回答的には間違いになります。是非指摘して欲しいところですが...

```
i=1
while(1):
    print(i)
    if(i>10):
        break
    i=i+1
```

どきどき...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290256/a088dfc6-7546-5fcd-6777-2b4b6535155c.png)

うーんこれはダメでした。きちんと誤答であることを指摘してくれません。しかし、しれっと正解のコードを出して訂正してくるあたり、相手を傷つけない優しい性格なのかもしれません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290256/6ce49f41-0bd2-ffc3-c8ee-814dbb6e6e82.png)

いちおうこのことをChatGPTに指摘してみました。ちゃんと自らの非を認めているようだ。これは、なかなかプライドの高くなってしまった人間にはできることではないですね。AIならではの素直さ・謙虚さが伺えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290256/b32686dd-5343-39ff-df6f-ac2429f0ec8e.png)

## エラーを含むプログラムを渡してみる
次に「エラーが出て実行不可能なプログラム」として、以下のようなプログラムを渡してみましょう。このプログラムでは5行目で"="で比較をしているのでSyntaxErrorが発生しますが、さてこれは指摘してくれるでしょうか。


```
i=1
while(1):
    print(i)
    if(i=10): # =で比較しているのでSyntaxErrorになる
        break
    i=i+1
```

おぉ...ちゃんとエラーを指摘してくれました！しかもエラーの発生箇所と、その解決方法まで教えてくれるとはなんとお優しい...


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290256/bdec40bf-70db-6714-80a8-4bce0203ce98.png)


## ChatGPTへのお願いの仕方を変えてみる
もしかしたら冒頭のお願いで「もしエラーがあったら指摘して欲しいな」しかいっていないので、エラーしか指摘してくれないのかも。

というわけでこういうお願いを追加。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290256/17c898b4-067d-29ae-9989-932298c0bd30.png)

するとエラーだけじゃなくてプログラムの出力結果が所望のものでは無いことも指摘してくれうようになりました！お願いの仕方で教師としての精度が変わるのかもしれません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290256/c9ffeff8-efe3-fd0b-4c92-9c55e6563e37.png)


## まとめ
今回はプログラミングの学習パートナーとして、ChatGPTが使えるかどうかを実験してみました。結果としてまだ少し粗さはあるものの、こちらのお願いの仕方次第で、かなりの精度でプログラミング学習をサポートしてくれるパートナーになりうると思います。なんといっても、こちらがプログラムをかけるまで、じっと何も言わずに見守ってくれるのが嬉しいです。書籍やオンライン教材などはどうしても学習が単調になりがちですが、ChatGPTを使うことでレビューやディスカッションを行えるようになり、プログラミング学習がより捗るかもしれません。
何より、プログラミング学習初心者がぶつかる「エラーの内容が英語で書かれているし、何を指摘しているかよくわからない！もういや！」という、大きな障壁が取り除かれるかもしれません。
【Linux】使用しているシェルを確認する方法


## はじめに

以下の方法では現ユーザーのログインシェルが出力されます。  

```terminal
$ bash
$ echo $SHELL
/bin/bash
$ zsh
$ echo $SHELL  
/bin/bash
```

使用するシェルを`zsh`に変更しても`$SHELL`にはログインシェルである`bash`のフルパスが出力されます。 

https://linux.die.net/man/1/bash#:~:text=is%20%27%27%2B%20%27%27.-,SHELL,-The%20full%20pathname

> SHELL
>
> The full pathname to the shell is kept in this environment variable. If it is not set when the shell starts, bash assigns to it the full pathname of the current user's login shell.

`bash`から`zsh`へ変更した際に`zsh`であることを確認する方法について記載します。  

## 確認方法

### `echo $0`

ターミナルでコマンドを実行する際には次のように`echo $0`を実行することで確認できます。  

```terminal
$ bash
$ echo $0
bash
$ zsh
$ echo $0
zsh
```

ただしシェルスクリプトの中で使用すると期待しない結果になります。  

```sample.sh
echo $0

```

```terminal
$ bash sample.sh
sample.sh
```

シェルではなく実行時のコマンド名が出力されます。  

### `readlink "/proc/$$/exe"`

シェルスクリプトでも現在使用しているシェルを確認するためには次のコマンドを実行します。  

```terminal
$ bash
$ readlink "/proc/$$/exe"
/bin/bash
$ zsh
$ readlink "/proc/$$/exe"
/bin/zsh
```

```sample.sh
readlink "/proc/$$/exe"
```

```terminal
$ bash sample.sh
/bin/bash
$ zsh sample.sh
/bin/zsh
```

シェル名のみ取得する場合には次のように実行します。  

```terminal
$ basename "$(readlink "/proc/$$/exe")"
zsh
```
php基本構文『コロン構文』

# HTML内に記述する時に使いやすい
```
<?php
    $products = ['デニム', 'Tシャツ', 'スカート',];
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./style.css">
</head>
<body>
    <!-- コロン「:」構文 
    PHP文法の中でHTMLを使いたい時 -->
    <?php foreach($products as $product): ?>
        <div>
            <h1>商品名</h1>
            <p><?php echo $product; ?></p>
        </div>
    <!-- endで終わる -->
    <?php endforeach; ?>
</body>
</html>
```
# 実際に表示すると
![スクリーンショット 2023-03-18 23.47.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/5fee5213-b2d8-1590-3884-7d794eb7a8b9.png)
CSSはこちら
![スクリーンショット 2023-03-18 23.48.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/05a1e54f-3d7a-848d-eb52-8efb762478a6.png)
FScalendarの日付ごとに区切り線を入れるやり方

## はじめに

今回はFScalendarを使ったカレンダーを日付ごとに線で区切る方法について書きます。
デフォルトでは以下のように区切りのないカレンダーが表示されます。
![1dbaf22f81f91e14428694b8eb24a3b2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2182598/8db9a6b7-b8e6-7723-cdc2-5f25314c96f3.png)


勝手に簡単にカスタマイズできそうだと思っていたのですが、公式マニュアル含め色々と調べてもなかなかピンポイントの情報を見つることができず苦労しました。備忘録を兼ねて、実装方法について書きたいと思います。


## この記事を読むにあたって
FScalendar自体の設定方法については割愛します。既にライブラリを導入しdelegate等の設定を済ませた上で参考にしていただけたらと思います。

## 実装方法
まず、今回はcalendarという変数名でFSCalendarのViewをリンクさせます。
```swift
@IBOutlet weak var calendar: FSCalendar!
```

cellForメソッドを使って枠線を実装します。
FSCalendarDataSourceプロトコルを適応させた状態で、cellForと入力すると補完で出てきます。

```swift
func calendar(_ calendar: FSCalendar, cellFor date: Date, at position: FSCalendarMonthPosition) -> FSCalendarCell {
        let cell = calendar.dequeueReusableCell(withIdentifier: "CELL", for: date, at: position)
        cell.layer.borderColor = UIColor.gray.cgColor
        cell.layer.borderWidth = 0.5
        return cell
    }
}
```
delegateを設定しているので、画面に表示される日付のセルの数だけこのcellFor関数が呼ばれているようです。この中で引数dateで渡ってきた日付のcellのborderColorとborderWidthを設定して返すようにしました。これで表示される全てのセルにこの処理が適応されカレンダーのセルに灰色で太さ0.5の枠線をつけることができます。

上記コードでwithIdentifierを"CELL"と任意の名前を設定しています。
viewdidroadに以下を入れてFSCalendarCellのIdentifierを先ほど任意で決めた名前"CELL"に設定します

```swift
override func viewDidLoad() {
        super.viewDidLoad()
        calendar.register(FSCalendarCell.self, forCellReuseIdentifier: "CELL")
    }
```

以下はコード全文


```swift
import UIKit
import FSCalendar

class ViewController: UIViewController ,FSCalendarDataSource{
    
    @IBOutlet weak var calendar: FSCalendar!
    override func viewDidLoad() {
        super.viewDidLoad()
        calendar.register(FSCalendarCell.self, forCellReuseIdentifier: "CELL")
    }
    
    func calendar(_ calendar: FSCalendar, cellFor date: Date, at position: FSCalendarMonthPosition) -> FSCalendarCell {
        let cell = calendar.dequeueReusableCell(withIdentifier: "CELL", for: date, at: position)
        cell.layer.borderColor = UIColor.gray.cgColor
        cell.layer.borderWidth = 0.5
        return cell
    }
}
```





これでシュミレータを起動すると、

![6d495b97aa87c8d89ecf1f0ca345b651.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2182598/0c9edfe4-f59a-cc22-f634-02d3c3afca9b.png)



枠線がつきました！

## 最後に

もっと良い方法があればコメントなどで教えていただけたら嬉しいです。
最後まで読んでいただきありがとうございます！
Library not loaded: /opt/homebrew/opt/icu4c/lib/libicui18n.69.dylibへの対応

# Library not loaded: /opt/homebrew/opt/icu4c/lib/libicui18n.69.dylibへの対応
## 背景

```
brew upgrade
```
brew upgradeしてしまったことで、icu4cが最新化version72に進んでしまった。
この結果、手元のposgresが表題のエラーになった。

## 解決方法
1. HomebrewのFormulaフォルダへ移動
```
cd $(brew --prefix)/Library/Taps/homebrew/homebrew-core/Formula
```

2. gitのログを確認、戻したいバージョンのコミット番号を確認
```
 git log --follow icu4c.rb
```

3. コードをチェックアウト
```
 git checkout XXX
```

4. 再インストール
```
brew reinstall ./icu4c.rb
```

5. gitのコードを戻す
```
git checkout master
```

## 参考URL
とても参考になりました。ほぼ記載いただいた通りです。
https://zenn.dev/ttskch/articles/8bd187c62436b8
[検証]Multi-stage buildsにしたらめっちゃDocker Imageのサイズが小さくなった話~Golang編~

# 自己紹介
初めまして。私は都内でwebエンジニアをしています。

今の会社にインターンとして経て、入社しました。

業務では、Nuxtjs, Golang, Kubernetesを用いて運用保守開発や

最近はPandasを用いてデータ分析など日々苦戦している若輩者です。

## 背景

DockerImageのMulti-stage buildsをするとサイズがどのくらい落ちるか気になったので、検証しました。

## 対象としている人

- Docker学習中の人
- Docker Imageを実装している人

# 実験結果

一目瞭然ですね。
まさかの約370MBの違いもありました。

Goのベースイメージを採用したDockerImage
[golang:1.19]()をベースイメージとして使っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2083780/1d9bebbb-bb78-5145-1a7b-150fa1899955.png)

Multi-stage buildsを採用したDockerImage
[scratch](https://hub.docker.com/_/scratch)をベースイメージとして使っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2083780/c0f9912f-5208-06f9-b60b-5ccae2d97e99.png)

## それぞれのDockerImage

Goのベースイメージを採用したDockerImage

```Dockerfile
FROM golang:1.19
WORKDIR /usr/src/app
COPY . ./
RUN go mod download && go mod verify
EXPOSE 8000
CMD ["go", "run", "./cmd/main.go"]
```

Multi-stage buildsを採用したDockerImage

```Dockerfile
# syntax=docker/dockerfile:1
FROM golang:1.19 as builder
WORKDIR /usr/src/app
COPY ./backend/go.mod ./backend/go.sum ./
RUN go mod download && go mod verify
COPY ./backend .
RUN CGO_ENABLED=0 go build -o binary ./cmd/main.go
FROM scratch
WORKDIR /usr/src/app
# scratch doesn't have timezone.
COPY --from=builder /usr/share/zoneinfo/Asia/Tokyo /usr/share/zoneinfo/Asia/Tokyo
COPY --from=builder /usr/src/app/binary /usr/src/app/binary
COPY ./backend/configs.yaml .
EXPOSE 8080
CMD ["./binary"]
```
SSL/TLS関連の主なディレクティブ

●SSL/TLS関連の主なディレクティブ
・ssl{on|off}　SSL/TLSの有効化・無効化　※バージョン1.15からはlistenディレクトリでsslを指定する
・ssl_certificate　ファイル名;　サーバ証明書のファイルを指定(中間CA証明書があるとき
・ssl_certicate_key　ファイル名;　サーバ秘密鍵のファイルを指定
・ssl_ciphers　暗号スイート;　使用可能な暗号スイートを指定
・ssl_protocols　プロトコル;　使用可能なSSLなプロトコルを指定


●Nginxの設定を再読み込みするコマンド

nginx -s reload
Use cases of wget

# download files from list

assumes list.txt contains following

```text
voice-record.mp3
agenda.docx
minutes.docx
```

after executes this command

```sh
wget -i list.txt --base="http://your.site/page/"
```

following files will be downloaded

```text
http://your.site/page/voice-record.mp3
http://your.site/page/agenda.docx
http://your.site/page/minutes.docx
```

# add headers of http request

```sh
wget --referer="https://www.bbc.co.uk/" --header="User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0" "https://www.bbc.co.uk/weather"
```

# check web server is ready to serve after restart  

```sh
wget -O/dev/null --timeout=5 --waitretry=15 --tries=27 --retry-connrefused --quiet "http://your.site/page"
```

Options
- -O/dev/null: saves downloaded content to /dev/null, i.e. doesn't keep
- timeout=5: 5 seconds connection timeout
- waitretry=15: waits up to 15 seconds in next try. By default, extra 1 second waiting time is added on next try, start from 1 second  
- tries=27: tries to connect 27 times 
- retry-connrefused: retries even though destination refuses to connect. Without apply this flag program terminates when destination refuses to connect  
- quiet: doesn't output anything to console

wget returns 0 when success, otherwise returns 4.
React.js ✖️Tailwind CSSで可読性を高めるアイデア

# 本記事について
この記事では、React.jsでスタイリングとしてTailwindCSSを使用する際にClassName内がごちゃついて可読性が下がってしまう事を回避するために自分がとっている方法について記述しています。
コードの内容についてはあくまで例なので気にせずに記述方法にだけフォーカスしていただけると幸いです。
まだまだ初学者のため、もっといい方法があればぜひコメント頂けると幸いです。

### 　Before
普通に書くとこんな感じ。
やっぱり見にくい気がします。
```
const ExamplePage = () => {
    return (
        <>
            <div className="h-2 w-2 pt-1 text-white bg-pink-200 bg-opacity-20 border-b md:hover:text-red">
                <p className="p-1 mt-1 font-semibold underline">これは例です</p>
            </div>
            <div className="mt-2 pb-2 rounded-sm shadow-sm">
                <p className="font-light">
                    この記事では
                    <span className="font-bold text-red-400 underline underline-offset-1">
                        個人的に可読性の高いと
                    </span>
                    思う記述方法について記載しています。
                    <br />
                    あくまで例なので、スタイリングの中身は適当ですので
                    ご注意ください。
                </p>
            </div>
        </>
    );
};

export default ExamplePage;
```

### After
Styled Componentのように関数コンポーネントの外に書き出します。
これにより、同一のスタイルを簡単に適用することができ、可読性が上がると同時に保守性も高まると感じています。
縦に長くなってしまうというデメリットはありますが、その部分に関しては別ファイルで定義したものをインポートすれば解決されると思います。

```
const ExamplePage = () => {
    return (
        <>
            <div className={styles.topContainer}>
                <p className={styles.title}>これは例です</p>
            </div>
            <div className={styles.bottomContainer}>
                <p className={styles.bottomContainer}>
                    この記事では
                    <span className={styles.emphasis}>
                        個人的に可読性の高いと
                    </span>
                    思う記述方法について記載しています。
                    <br />
                    あくまで例なので、スタイリングの中身は適当ですので
                    ご注意ください。
                </p>
            </div>
        </>
    );
};

export default ExamplePage;

const styles = {
    topContainer: `
    h-2 
    w-2 
    pt-1 
    text-white 
    bg-pink-200 
    bg-opacity-20 
    border-b 
    md:hover:text-red
    `,
    title: `
    mt-2 
    pb-2 
    rounded-sm 
    shadow-sm
    `,
    bottomContainer: `
    p-2
    mt-1
    bg-white
    rounded
    `,
    explanation: `
    font-light
    `,
    emphasis: `
    font-bold 
    text-red-400 
    underline 
    underline-offset-1
    `
};
```
フロントエンド（React + Apollo）からGraphQL経由でDevise認証（Rails + GraphQL Ruby）するときに参考にしたリンク

# 主な実現方法

- X. GraphQLエンドポイントでDevise認証も兼ねる
    - ドキュメントでいう[Mounting Operations In an Existing Schema](https://github.com/graphql-devise/graphql_devise#mounting-operations-in-an-existing-schema)
- Y. APIとしてのGraphQLとDevise用のエンドポイントを分ける
    - DeviseにはREST APIのController経由でアクセス
        - Devise用のGraphQLエンドポイントを建てる方法もあるが、X,Y双方の悪いところを引き継ぐためあまりおすすめはしない

どちらも、認証成功時の認証用トークンをフロントエンドに保持し、
GraphQLに投げるときにはリクエストヘッダに認証用トークンを詰めて、
サーバサイドでリクエストヘッダに正規の認証情報があれば通信を継続して、なければエラーにするというロジック

通信経路としては認証とAPIアクセスは分断可能であり、結局GraphQL側ではAPIを投げられたときの認証トークンを見ればいいだけなので、どちらでも実装可能だが、
細かいところでそれぞれ違いがある

- X. GraphQLエンドポイントでDevise認証も兼ねる
    - メリット
        - 通信を全て一本のGraphQLでまかなえるのでシンプル
    - デメリット
        - 一本化するに当たって専用のgem(graphql-devise)を使う必要があり、そんなに情報が転がっていない
            - 特にあるライブラリとあるライブラリを掛け合わせて使うとき、その掛け合わせでの情報は更に探しにくいので問題の切り分けがかなり難しくなる
- Y. APIとしてのGraphQLとDevise用のエンドポイントを分ける
    - メリット
        - ほぼ一般的なDeviseの利用法なので、情報がネットに溢れており、何かカスタマイズしたいときやエラーになったときに調べやすい
    - デメリット
        - 1つのアプリの接続先が2本になる
            - フロントエンドから通信する先が2本になる
            - Rails側でGraphQLモジュールとControllerモジュールどちらも触ることになりあっちゃこっちゃする
        - GraphQLでの認証エラーでのハンドリングを自身で行う必要がある


# 作成時に参考にしたサイト
本当であればリポジトリを見せたり、細かく説明するとかしたりしたいんですが、
個人アプリでリポジトリがプライベートなのと、説明が結構長くなってしまうので参考資料を載せるだけにしました。
時間あったらやります

- X. GraphQLエンドポイントでDevise認証も兼ねる
    - [graphql_deviseの公式ドキュメント](https://github.com/graphql-devise/graphql_devise)
    - [jwtを使ったGraphQL側との通信](https://zenn.dev/yjiro0403/scraps/2b9611af7e37a2)
- Y. APIとしてのGraphQLとDevise用のエンドポイントを分ける
    - https://qiita.com/shu1124/items/e8c37b73e015afc63074


ちなみに私は「X. GraphQLエンドポイントでDevise認証も兼ねる」側でやったんですが、詰まったところが多かったので、メモしておきます（時間できたら詳しく書きます）

- graphql-deviseで既存スキーマ上で認証を行ったとき
    - contextをController上でgql_devise_contextを使って作らないと、元々Controllerでガシガシ動くDeviseをうまく動かすことができない
    - 上記に絡めて、テストをしようとしたらcontextからResource(例:User)を見つけられない、controllerを見つけられないというエラーに振り回されるので、Mutation単体でテスト、`XXSchema.execute`でテストしようとすると痛い目に合うので、大げさでもgraphqlエンドポイントにポスト通信とかでテストするのが吉
- Apolloでレスポンスヘッダを見ようとすると、ログイン時のMutationのコールバックでいじれると思いきや、ApolloClientの通信全体のミドルウェアに挟む必要がある
    - https://zenn.dev/yosipy/articles/6bbd9c64b6ad74
- Next.jsを使用していたため、サーバサイドでもCookieをいじる必要があり、nookiesライブラリを使うと捗った
[脳死したい人向け]Github ActionでDockerImageのBuild＆Pushの自動化の実装、解説してみた

# 自己紹介
初めまして。私は都内でwebエンジニアをしています。

今の会社にインターンとして経て、入社しました。

業務では、Nuxtjs, Golang, Kubernetesを用いて運用保守開発や

最近はPandasを用いてデータ分析など日々苦戦している若輩者です。

## 背景

Github ActionによるDockerImageのBuildを実装した際に、document通りに実装した時のメモです。

## 対象としている人

- Github、DockerHubのアカウントがある人
- Github ActionによるDokcer ImageのBuild&Pushの実装をしたい人

## 結論

1.以下のファイルを導入したいGithubレポジトリの`.github/workflows`ディレクトリ配下に設置してください。
```yaml
name: ci
# mainブランチに変更があった場合に走ります。
on:
  push:
    branches:
      - "main"
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Login to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
      -
        name: Build and push
        uses: docker/build-push-action@v4
        with:
          context: .
　　　　　　　　　　　　　　　　　　　　# Dockerfileが存在するPathを指定する
          file: ./Dockerfile
          push: true
          tags: ${{ secrets.DOCKERHUB_USERNAME }}/${リポジトリ名}:latest
      -
        name: Build and push
        uses: docker/build-push-action@v4
        with:
          context: .
          # Intel系AppleSilicon系に対応するため
          platforms: linux/amd64,linux/arm64
          # Dockerfileが存在するPathを指定する
          file: ./Dockerfile
          push: true
          tags: ${{ secrets.DOCKERHUB_USERNAME ${リポジトリ名}:${{ github.sha }}
```
2.DockerHubにログインするための情報を把握する。
Github上でpushをするために、DockerのLoginを行う必要があるため以下の情報が必要です。
- Dockerhubのユーザー名
- DockerhubのAccess Token
[こちら](https://docs.docker.com/docker-hub/access-tokens/)からAccessTokenを取得してください。
3.SecretにDockerHubにログインする必要な設定をする。
対象レポジトリの`Settngs`/`Security`/`Actions`/`Secrets`に先ほど取得したDockerHubにログインするために必要な設定を行います。
|key|value|
|---|-----|
|DOCKERHUB_USERNAME|Dockerhubのユーザー名|
|DOCKERHUB_TOKEN|DockerhubのAccess Token|
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2083780/5b374432-c5a2-a9d2-a89f-abfb834ff311.png)
## 完成
以上で実装は完成です。
mainブランチのコードに変更があった場合、自動的にDockerImageがPushされます！
## 学んだ箇所
actions/checkout@v3の動作について
引用ですが、checkoutを追加するとpushされたコードをチェックアウト，プルリク時には，そのプルリクされたコードをチェックアウトするという動作になるそうです。
```yaml
    -
      name: Checkout
      uses: actions/checkout@v3
```
これがないと以下のエラーが発生します。
```zsh
buildx failed with: ERROR: failed to solve: failed to read dockerfile: open /tmp/buildkit-mount3050335498/Dockerfile: no such file or directory
```
## 参考
https://teratail-com.translate.goog/questions/06z9r8qi6eoq0x?_x_tr_sl=ja&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=sc
https://docs.docker.com/build/ci/github-actions/
[Rails] privateとprotectedの違い

## はじめに
railsアプリを作成する中で、`priate`と`protected`の違いが分からなかったため調べてみました。
とても噛み砕いた内容になるかと思いますので、ご了承ください。

## privateとprotected
### 共通点
クラス外からは呼び出す事ができない。
```ruby
class Food
  private
    def breakfast
      p "パン"
    end

  protected
    def lunch
      p "パスタ"
    end
end

food = Food.new
food.breakfast
#　　>> エラー
food.lunch
# >> エラー
```
同じクラスのインスタンスの中であれば呼び出せる。
```ruby
class Food

  def morning
    breakfast
  end
 
  def noon
    lunch
  end

  private
    def breakfast
      p "パン"
    end

  protected
    def lunch
      p "パスタ"
    end
end

food = Food.new
food.morning
#　>> "パン”
food.noon
# >> "パスタ"
```

### protected
protectは上記に加え、生成した別のインスタンスが同じクラスを持っていたら呼び出す事ができます。

```ruby
class Food

  def set_like_food(food)
    @food = food
  end

  def my_like_food(food2)
    p "私の好きな食べ物は、#{get_like_food}と、#{food2.get_like_food}です。"
  end

  private
    def get_like_food
      @food 
    end
end

food1 = Food.new
food1.set_like_food("パン")

food2 = Food.new
food2.set_like_food("パスタ")

food1.my_like_food(food2)
```
`def my_like_food(food)`の`#{get_like_food}`では呼び出し元の値である「"パン"」が入っており、上記で説明した、クラス内の他のインスタンスから呼び出せています。

しかし`#{food2.get_like_food}`の「food2」は、呼び出し元の「food1」とは異なるインスタンスです。
つまり、food1のメソッドをfood2が`#{food2.get_like_food}`のように使用しようとしています。

その場合、`get_like_food`メソッドがprivateメソッドだと呼び出せません。
逆にprotectedだと呼び出せます。

## 終わりに
自分で見返した時理解できるように、自分なりに噛み砕いて記述したため分かりずらい部分やずれた理解をしている部分があるかもしれません。
その際はコメントで教えてえただけると嬉しいです！

## 参考サイト
[【Ruby入門】private と protected の使い方まとめ【メソッドのアクセス制御】](https://26gram.com/private-protected-in-ruby)
自分用  C#+SDL2 libpng16-16.dll: 指定されたモジュールが見つかりません。

# エラー内容
SDL_image.IMG_Initで、```Failed loading libpng16-16.dll: 指定されたモジュールが見つかりません。```といったエラーが出る。

# 解決策
SDL_image.IMG_Initを実行する前にSetDllDirectroryでdllの検索場所をプログラムのあるパスにすれはよい
以下コード。
```cs
using System.Runtime.InteropServices;
using SDL2;

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetDllDirectory(string lpPathName);

void Init()
{
    // 初期化する前にSetDllDirectoryでdllの検索場所をプログラムのあるパスに設定する
    SetDllDirectory(AppContext.BaseDirectory);

    if (SDL_image.IMG_Init(SDL_image.IMG_InitFlags.IMG_INIT_PNG) == 0)
        Console.WriteLine(SDL_image.IMG_GetError());
    
    ...
}
```
macOSバージョンアップした後、rubyのインストールができなくなった

# はじめに

rubyの環境構築を試みたところ、エラーが出てしまった。
macOSのアップロードをした後、rubyがインストールできなくなってしまっていた。

※注意※
プログラミング学習中の初心者です。
記述に間違いがあれば、ご指摘いただけますと幸いです。

# 環境
macOS Ventura 13.2.1


# 試したこと

まずmacM1チップ用のコードを打ち込みました。
```
$ OPENSSL_CFLAGS=-Wno-error=implicit-function-declaration RUBY_CFLAGS=-DUSE_FFI_CLOSURE_ALLOC rbenv install 2.６.６
```
エラーが出てインストール出来ませんでした。
（エラーログ撮り損ねてしまいましたので、割愛します）

```
$ ruby -v
rbenv: version `2.6.6' is not installed (set by /Users/ユーザー名/workspace/136567_ExamPostApp_Sorcery/.ruby-version)
```

続いて下記のコードも試してみましたが、エラーとなりました。
```
$　RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.1)" rbenv install 2.6.6
To follow progress, use 'tail -f /var/folders/ww/blyvnpr94n99mgj80b_b3c6w0000gn/T/ruby-build.20230318172246.85478.log' or pass --verbose
Downloading ruby-2.6.6.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.6.tar.bz2
Installing ruby-2.6.6...

WARNING: ruby-2.6.6 is past its end of life and is now unsupported.
It no longer receives bug fixes or critical security updates.

ruby-build: using readline from homebrew

BUILD FAILED (macOS 13.2.1 using ruby-build 20230208.1)

Inspect or clean up the working tree at /var/folders/ww/blyvnpr94n99mgj80b_b3c6w0000gn/T/ruby-build.20230318172246.85478.nDK0jT
Results logged to /var/folders/ww/blyvnpr94n99mgj80b_b3c6w0000gn/T/ruby-build.20230318172246.85478.log

Last 10 log lines:
transform_mjit_header: SKIPPED to transform __sputc
transdb.h updated
Undefined symbols for architecture arm64:
  "__mh_execute_header", referenced from:
      _rb_dump_backtrace_with_lines in addr2line.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [libruby.2.6.dylib] Error 1
make: *** Waiting for unfinished jobs....
ln -sf ../../../.ext/include/-darwin22/rb_mjit_min_header-2.6.6.h include/ruby-2.6.0/-darwin22/rb_mjit_min_header-2.6.6.h
```

治らなかったため、rbenvを一度アンインストールするなどしましたが、
結局下記のコードを実行したところ、インストール成功しました。

```
$ RUBY_CFLAGS="-w" rbenv install 2.6.6 
To follow progress, use 'tail -f /var/folders/ww/blyvnpr94n99mgj80b_b3c6w0000gn/T/ruby-build.20230318183454.13481.log' or pass --verbose
Downloading openssl-1.1.1t.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/8dee9b24bdb1dcbf0c3d1e9b02fb8f6bf22165e807f45adeb7c9677536859d3b
Installing openssl-1.1.1t...
Installed openssl-1.1.1t to /Users/ユーザー名/.rbenv/versions/2.6.6

Downloading ruby-2.6.6.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.6.tar.bz2
Installing ruby-2.6.6...

WARNING: ruby-2.6.6 is past its end of life and is now unsupported.
It no longer receives bug fixes or critical security updates.

ruby-build: using readline from homebrew
Installed ruby-2.6.6 to /Users/ユーザー名/.rbenv/versions/2.6.6
```

# まとめ
ruby-buildがビルド時にhomebrewのバージョンを使おうとするため、エラーとなっていたことが判明しました
RUBY_CFLAGS="-w"（デフォルトのCFLAGS(C言語のコンパイラオプション)）とすることにより、
コンパイラからの警告メッセージを出力しないように設定でき、
例外が発生せず、インストールする事が可能になったようです。
```
$ RUBY_CFLAGS="-w" rbenv install 2.6.6 
```

# 参考ページ
https://qiita.com/kouta1206/items/3c56884df4d10f39ebde
MAMPでApacheが起動しないときの対処法


先日購入したWindows11のPCにMAMPを入れて起動しようとしたら、`Apache`も`SQL Server`も立ち上がらなかったので備忘録がてら書きます。

使用している、MAMPのバージョンは5.0.0です。

解決策は大きく3つ。
- MAMP\conf\apache\httpd.confを編集
- Nginxを使う
- Microsoft visual c++ 再頒布可能パッケージ インストール

## MAMP\conf\apache\httpd.confを編集
`LoadModule perl_module modules/mod_perl.so`をコメントアウト
私の環境では元々されていたため、これでは対処ができなかった。

## Nginxを使う
1. MAMPのボタンのPreferencesを押す
1. Serverに移動
![mamp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920450/9cbe1cf9-3179-928d-e4a1-95287a0f768e.png)
1. Nginxをチェック
![mamp-preferences.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920450/c0d426bb-70b2-7c1b-3607-1e953404fdf2.png)

## Microsoft visual c++ 再頒布可能パッケージ インストール
1. [再頒布可能パッケージの最新のサポートされているダウンロードをMicrosoft Visual C++する](https://learn.microsoft.com/ja-jp/cpp/windows/latest-supported-vc-redist?view=msvc-170)というタイトルのページに行く
1. x64を選択してダウンロード
![microsoft_VisualC++.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920450/f8c59aaa-bf41-a8b4-94e2-3f8cd0af05a6.png)
1. 終了したら再起動


今回は、私は3つ目の方法で対処しました。


### 参考文献
[MAMP ApacheもMySQLも点灯しません](https://teratail.com/questions/9004x2zep7q62i)
[MAMP エラー Apache が起動しない](https://www.webdesignleaves.com/pr/plugins/mamp_error_apache.html)
[WindowsでMAMPのApacheサーバが起動しない時の対処法](https://mio-code.com/2020/01/25/windows-mamp/)
ChatGPTでdiscord botを作ろうとしたけど失敗した話

こんにちはGSです。

今回も前回同様にChatGPTを使用してみました。この作品も同様にSIGNATE投稿作品になりますのでもしよろしければ、twitterの方でRTやいいねをいただけたらと思います。

https://twitter.com/ggtyun29/status/1637091500927635458?s=61&t=vVDItsCE8nrycVb4ey7Szg

今回はbot開発のテーマで書かせていただきます。

# 背景

現在いろいろな企業では社内ツールでChatGPTを導入することを検討しているところもあるかと思います。そこで今回はdiscordにbotを入れるまでの部分と実際にChatGPTapiがdiscordでうまく動くまでの二段階でフローを考えましたが前者の部分で失敗した話をまとめたいと思います。

またこれを制作したGSは開発はド級の初心者であるため、記事内に間違いがある場合は指摘をください

# 実践
![スクリーンショット 2023-03-18 21.14.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606656/b109e138-06fd-e44b-1035-ac8c39e927ac.png)
![スクリーンショット 2023-03-18 21.14.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606656/97b091a7-96ac-2548-ece2-cd0144cf39d1.png)
![スクリーンショット 2023-03-18 21.14.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606656/70075d47-ca11-ba59-5a53-43cf49cc6226.png)
![スクリーンショット 2023-03-18 21.14.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606656/7ff9ef21-c3e1-3495-7d51-12e9610d5270.png)
![スクリーンショット 2023-03-18 21.14.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606656/d496d68a-c455-3b0b-39f1-4098a5e3dd52.png)

# どこで失敗したか

先に原因について書きます。大きく分けて原因は二箇所あります
* ChatGPT側の学習が2021年9月までのため使用しているdiscordライブラリが古い
* 手順書の工程で特権ゲートウェイインテントに触れていなかったことです


具体的にどこで失敗したかに関しては、手順5の部分ですね。

次のプロンプトで

```
手順5にて

Traceback (most recent call last):
  File "/hogehoge/discord_bot_env/mybot.py", line 6, in <module>
    bot = commands.Bot(command_prefix='!')
TypeError: __init__() missing 1 required keyword-only argument: 'intents'

というエラーが出ました。
```

と返しました。すると、
![スクリーンショット 2023-03-18 21.33.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606656/2e1192b4-b44a-4fcd-3ccf-05bdd820c968.png)

次のこのコメントで、ログインには成功しましたが、コメントが返ってきませんでした。
ここがverの問題だと考えています。

次に公式のdiscord.pyのリファレンスを見に行きました。

https://discordpy.readthedocs.io/ja/latest/quickstart.html

これにpython fileの方を書き直した結果、特権ゲートウェイインテントについてのエラーが出ました。特権ゲートウェイインテントってなんだろうと思い調べたところ以下になります。上記の手順では2に該当する部分のチェック項目が漏れていたことがわかりました。

![スクリーンショット 2023-03-18 22.51.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606656/913b7b79-13ac-8822-3374-4f402fb3a8f5.png)

こちらの項目についていくつかonにして指示に従ったところ

![スクリーンショット 2023-03-18 22.53.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606656/528b2fdd-a6d2-0e11-9922-87cfa191795f.png)

成功しました。

# 感想

ChatGPTでは完全にクリアとはなりませんでしたが、ある程度の補完はできているかなと思っています。本当に必要最低限の手順は教えてくれたので、理解していない身としてはかなり危険だなと思いますが、役には立ったと感じています。
iPhone  MacBookAir  接続

病院のWi-Fiが22に切れる。

iPhone と　MacBookAirで接続しようとした
<この項は書きかけです。順次追記します。>

![995B8E8C-D0B5-440C-9BC8-F168BA586233.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/d45976b2-ebb4-0c4c-573c-b264f240205d.jpeg)

# MacBookAir M2 2022

# iPhone 8

# BUFFALO BKBU AJ106/WH2

# ロアス　UH194MBL

# Logicool


# 接続失敗
全部同意についだら、どれとどれも認識しなかった。
# 個別接続

ひとつづつ接続したら、それぞれ接続できた。　　

# 再起動

全部つないで再起動したら全部USB接続はつながった。　

原因は不明。
iPhone  MacBookAir はUSB接続。

# 未解決課題　

## iPhone  MacBookAir  blouetooth
。bluetoothは接続していてもネット共有がでていない。原因不明。
## iPhone  MacBookAir  Wi-Fi

無線接続はWi-Fiはときどきしかつながらない。原因不明。

＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴(document history)
ver. 0.01 初稿 　20230318


### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

####  Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
Pythonファイルの.exe化

## 始めに

Pythonで作成したプログラムをPython実行環境のない人でも扱えるよう.exeにビルドした。

ネット上に転がっている手順そのままではうまくいかなかったので、自分の環境で成功した手順のメモを残す。

## この文書内で実行する内容

- pipenvでPC内に仮想環境構築
- 仮想環境下でpythonのバージョン、仕様ライブラリを指定し、pyinstallerでビルド

### 仮想環境下でビルドするメリット

- pythonのver. を指定可能
- 必要最低限のライブラリのみインポートするため、容量が削減される

## 参考

[PyinstallerでPythonプログラムをexe化する手順書（Windows編）](https://qiita.com/nal_dal_dere/items/95e173068af399e61981)

## 作業環境

| 名称       | 詳細                            |
| ---------- | ------------------------------- |
| OS 名      | Microsoft Windows 10 Enterprise |
| バージョン | 10.0.19044 ビルド 19044         |
| Python     | Python 3.11.2                   |
| pip        | 23.0.1                          |
| pipenv     | 2023.2.18                       |

## 使用するツール

- python
- pip
- pipenv

(下記は仮想環境下で都度インストール)

- pipenv
- pyinstaller
- Pythonファイルに使用している標準ライブラリ以外のライブラリ

## 手順

### 仮想環境有効化まで

カレントディレクトリを設定、仮想環境下のpython ver. を指定し、仮想環境を有効化

```

cd [フォルダパス]

python -m pipenv --python 3.11.2

python -m pipenv shell

```

### 仮想環境下

仮想環境下で再度pipenvとpyinstaller、ライブラリをインストール、pyinstallerでビルド。

```

pip install pipenv

pip install pyinstaller

pipenv install [Pythonファイルに使用している標準ライブラリ以外のライブラリ]

pyinstaller --onefile [.exe化したいpyファイル名]

```

### 終了後

仮想環境の無効化、削除

```

exit

python -m pipenv --rm

```

## ポイント

- pipenvはpythonモジュールとして実行しないと認識しない。
- exe化の際、"--onefile"を記述するとファイル数が少なく済む。