OmniAICreator/Qiita-1.07M huggingface dataset:
Python pillow が OSError: image file is truncated となってしまうとき

JPEGファイル特有の問題のようです。


# 出現したエラー

>OSError: image file is truncated

これについては検索すると山ほど以下のTipsが出てくるのですが、これでLoadはできても、次のconvert() 処理で同じエラーになってしまい、解決できないときには。

```python
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
```

# OpenCVで読み込んで、変換してやるといい

RGB画像であればこれで。

```python
from PIL import ImageFile
import cv2

fn = "hoge.jpg"

	try:
		im = Image.open(fn)
		im = im.convert("RGB")
	except OSError:
		cvimg = cv2.imread(fn)
		cvimg = cv2.cvtColor(cvimg, cv2.COLOR_BGR2RGB)
		im =  Image.fromarray(cvimg)

  #これで im が得られた
```

truncated になるのはJPEGのみなので、全部でcv2を通すのはオーバーヘッドになってしまうので。


# おしまい
docomoのSPモードメールのspammerに困らされた人の話

過去にやっていた仕事の経験を活かし（というわけではありませんが）、キャリアメール宛に送り付けられるスパムメールのヘッダを調べて送信元(経験上、awsとgcpが大半）にabuse report、というのをやっています。
が、対応できないのが１つ。docomoのSPモードメールです。正規の方法で送信されたメールヘッダを見られる人は一度見てください。eFromがなく、FromアドレスのIPが全部固定。つまり…spammerのおもちゃです。
不定期に大量に送りつけられてはweb画面で対処…が1週間続くこともありましたが、今回は酷かった。数日前から数えて50通近くきており(岩田とか斉藤とかのアレです）、さすがにうんざり。

FromアドレスのIPは一律なので、当然使えません。どのマシンが送りつけてるかhintになりそうなものがないかヘッダを見てもさっぱり
(ヘッダのSPF情報も多分本物)じゃ本文の(spammer好みの)ドメインでwhois…引いたらdomain reuse業社orz
ということでdig(確か)で引いたら大当たり！今回はawsが収容先と判明し、awsのabuse reportに件のspammerのメールのsrcをプレゼントしました。
今の所、awsから「うちの顧客でしたので処理してます」というメールが来たのでほっとしてます。
マシンの親アカウント(という言い方で良かったんだっけ？)ごと /dev/null されてもらいたいですね。

ちなみにspam mailのFromのIPからwhoisを引いた際に散見するところを列挙すると
・awsやgcp,sakura：序の口
・IDCFや国内の中小ホスティング会社：報告窓口代わりに代表問い合わせフォームを使わざるを得ないこともあり面倒。
・「かの国」系列と東南アジア：後者の場合、ダミー企業がIP取得した？のかと思うくらい。

最後に…
・スパムメールの参照はweb上でsrcだけ見ましょう(重要)。プライベートで使用してるスマホやタブレットのメールアプリでは絶対受信しないように
てかISP各社も同じようにしてほしい。
・何がしこまれてるかわからないので、セキュリティソフトを最新化したPCかmacでやりましょう。会社からの支給品ではやらないように(違う意味で問題になるので）。
・ヘッダ情報は https://mha.azurewebsites.net に貼り付けてから見るのが簡単。
20240408 日記 cder.nvimの変更、気になってるエントリ

### cder.nvimの変更
cder.nvimはWindowsだと動かないのでプラグイン本体に手を加える必要があった
ついでにデフォルトのoptsもWindows用にあれこれしようと思う

#### の前に、Neo-treeの使い勝手改善
初めて知ったんだけどNeo-treeはfile、buffer、gitの3つのモードがある、それぞれ、ファイルシステム（デフォルト）、バッファで開いてるものだけ、gitで変更のある分だけ、という感じ

詳細は [Recipes · nvim-neo-tree/neo-tree.nvim Wiki](https://github.com/nvim-neo-tree/neo-tree.nvim/wiki/Recipes)
本当はトグルで同じキーを押すとfile -> buffer -> git -> file...と順番になってほしいが、現在のモードをとる方法がわからないので、Recipesにあるのをそのまま使う
```lua:init.lua
require('neo-tree').setup({
  window = {
    mappings = {
      ['e'] = function() vim.api.nvim_exec('Neotree focus filesystem left', true) end,
      ['b'] = function() vim.api.nvim_exec('Neotree focus buffers left', true) end,
      ['g'] = function() vim.api.nvim_exec('Neotree focus git_status left', true) end,
    },
  },
})
```
これやると便利

#### Windows用修正を入れた

ここに入ってます
[tontoroRR/cder.nvim at support_windows](https://github.com/tontoroRR/cder.nvim/tree/support_windows)

使うときは以下のようにしとくとよいです
 `eza`、`bat`、`fd`、`exa`、`fdfind`使ってるのでそこらへんは適当に
```lua:Lazy使う場合
  {
    'tontoroRR/cder.nvim',
    branch = 'support_windows',
    event = 'VeryLazy', -- lz
    config = function ()
      m = {
        {'<Leader>tc',  ':Telescope cder<CR>'}, -- km
      }
      map_keys(m, vim.keymap.set)
      local fd_param = '--type directory --type symlink --exclude .git'
      if vim.loop.os_uname().sysname == 'Windows_NT' then
        require('telescope').setup({
          extensions = {
            cder = {
              command_executer = { 'cmd.exe', '/c' },
              previewer_command = 'eza -a -F --icons --color -1', -- uutils ls -a',
              pager_commnd = 'bat --plain --paging=always --pager="less -RS"',
              dir_command = { 'fd.exe', '--type=d', '--type=l', '.', },
            }
          },
        })
      else
        require('telescope').setup({
          extensions = {
            cder = {
              dir_command = { 'fdfind', '--type=d', '--type=l', '--exclude=.git', '.', },
              previewer_command = 'exa -a --icons --color=auto -F -1',
            },
          },
        })
      end
      require('telescope').load_extension 'cder'
    end
  },
```
#### いろいろ気になるところがある

* Windows用のデフォルトを入れたい
    * 今は`init.lua`側で設定しているけど
* フォルダアイコン、ちょっと変
* なぜかフィルタがうまく動かない
* 存在しないフォルダ名を入力してEnterするとエラー
* cderで移動した場合、zoxideとの連携がうまくいかない

いずれ本家にプルリクだそう、

### 気になってるエントリ

* [iTerm2とstarshipでterminalとshellをお洒落にしました！ #Terminal - Qiita](https://qiita.com/macololidoll/items/1c369217c6203dd479bd)
starshipの使い方学びたい
* [【Vim】Vimの基礎を学ぼう！【vimtutor】【実践Vim】 #初心者 - Qiita](https://qiita.com/kagami_t/items/67f2183e8d1120ca9eff)
いちどVimを大まかに網羅する感じで学びなおしたい、よく使うのしか知らないので
pyenv-virtualenvでanaconda/miniondaライクな環境を作ろう！！！

# 0.目的
anaconda/minicondaが商用利用では有料になり扱いにくくなったため、pyenv-virtualenvでpython環境を構築できる様にする。

# 1.pyenv-virtualenvとは
pythonのバージョン管理をするpyenvとモジュール管理するvirtualenvをあわせたパッケージ

# 2. インストール可能なpythonのバージョン一覧
```
$ pyenv install -l
```
anacondaやminicondaも含まれているがビジネス目的では現在有料なので利用時には注意

# 3.pyenvのインストール
```
$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bashrc
$ exec "$SHELL"
```

# 4.pyenvによるpythonインストール
```
$ pyenv install 3.8.6 # python仮想環境インストール
$ pyenv global 3.8.6 # アクティベート　
$ pyenv rehash # 反映？
```

# 5.pyenv-virtualenvのインストール
```
$ git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv
```

# 6.pyenv-virtualenvの環境設定
```
$ echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
$ echo export PYENV_VIRTUALENV_DISABLE_PROMPT=1 >> ~/.bashrc
$ source ~/.bashrc
```
これでpyenv-virtualenvのインストールは完了

# 7.virtualenvの仮想環境構築
3.8.6の下に仮想環境を作る
``` 
$ pyenv virtualenv 3.8.6 test
```

# 8.環境の変更
```
$ pyenv global 3.8.6/envs/test #作った環境の中の環境に移動したい場合
$ pyenv global system # localに戻りたい場合
$ pyenv global 3.8.6 # 作った環境に移動したい場合
```
上記のうち、1行目と3行目はフォルダ構造的には親子の関係にあるが環境は別物
vscodeではこの段階でinterpreterの変更リストに仮想環境の名前が登場
pip instgallし放題


# 9.使っている環境の確認
```
$ pyenv versions

>出力
  system
* 3.8.6 (set by /home/initial/.pyenv/version)
  3.8.6/envs/test
  test --> /home/initial/.pyenv/versions/3.8.6/envs/test
```
選択されているものの先頭に*がついている


# 10.環境の削除
$ pyenv uninstall 3.8.6/envs/test

# 11.まとめ
pyenv-virtualenvでpythonの仮想環境を構築する方法を学んだ。
devise導入における基本コマンド

# devise 導入 基本手順
## deviseとは?
deviseとはユーザー認証機能導入を手助けするgemです。
## ユーザー管理機能の実装
### deviseのinstall
#### gemファイルへの追記  
**Gemfile**
```
# 中略
gem 'devise'
```
#### bundleによる反映
**コマンド**
```
bundle install
```
### deviseの設定ファイルの作成
```
rails g devise:install
```
### userモデルの作成
モデルやマイグレーションファイルの自動生成、ルーティングへの追記を行う[^1]  

[^1]:**user**はあくまでモデル名の一例。masterでもなんでも良い。
```
rails g devise user
```
### usersテーブルの作成
マイグレーションの実行
```
rails db:migrate
```
再起動して反映
```
rails s
```

### viewの作成
```
rails g devise:views
```

### controllerの作成[^2]
[^2]:私はまだ使ったことはない。googleアカウントでのログイン機能実装で使う予定。

```
rails g devise:controllers users
```
タッチタイピングのコツ

# はじめに
タッチタイピングを覚えることはとても重要です。議事録を取るときや、何かを参考にしながらメモを取るときなどに視線を変えず文字を打つことができるのはとても作業効率を高めます。その上で今回はタッチタイピングを習得するためのコツについて記述します。

# タッチタイピングの基本
以下画像のように内側から順に人差し指、中指、薬指、小指でタイピングします。
![key配列.dio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693671/5144a0d2-13ae-6132-b444-bf65e7a7acd2.png)
【画像の出展】
https://dynabook.com/assistpc/tab/faq/pcdata/720212.htm

これが基本形なのでこれは暗記しましょう。タッチタイピングでは「F」, 「J」に両人差し指を置き、他の指を横一列に並べた形をホームポジションと言います。ホームポジションの形から上下に指を動かすことでキーボードを見なくてもタイピングできるようになります。

# 練習サイト
以下サイトで私は練習しました。（練習中）
速さよりも正確性を重視して練習するといいと思います。（知らんけど）

寿司打
https://sushida.net/
e-typing
https://www.e-typing.ne.jp/member/
React公式ページで学んでみた⑨（備忘録）

# はじめに
初めまして！
エンジニアになって数年、今まで本を読むだけでしたが、もっとプライベートで楽しみながら成長したい！自分が学んだ足跡を残していきたい！と思い記事を書きました！
最終的には自在に開発できるようになりたいと思っています。:triumph:
いろいろな記事を参考にさせてもらっています。:bow_tone2:
その中でもこれってどういう意味？とかつまづいたところを念入りに書いていこうかと思います。:fist:

# 今回の目的
前回の続きです。今回は「state の管理」。被る部分もあると思いますが、後で振りかえって深掘りするきっかけになるのが理想です。細かく書くと大変なのであっさりめ。

https://qiita.com/mr_noppo/items/7baed5891572c308736d

# 使用したものや事前準備
・Macbook Pro
・Visual Studio Code

# 主に参考にさせていただいた記事
https://ja.react.dev/learn/managing-state

# state管理
Reactのバグの一般的な原因は、冗長な、あるいは重複したstateである。

・覚えたいこと
ーstateを適切に構造化する方法
ーstate更新ロジックをメンテナンスしやすい状態に保つ方法
ー離れたコンポーネント間でstateを共有する方法

# stateを使って入力に反応
Reactはユーザー入力に応じてstateの変更をトリガにUIを変更する。
（例）
・フォーム内に文字を入力すると、ボタンが押せるようになる。
・ボタンを押すと、フォームとボタンが非活性になり、Loadアニメーションになる。
・APIのレスポンスが正常に返ってきた時、結果が表示される。
・APIのリクエストに失敗した時、エラーメッセージが表示される。

```react
    const [status, setStatus] = useState('typing');

    // レンダリングされた時にstateのstatusがsuccessならリターン
    if (status === 'success') {
        return <h1>That's right!</h1>
    }
    async function handleSubmit(e) {
        e.preventDefault();
        setStatus('submitting');
        try {
          await submitForm(answer);
          setStatus('success');
        } catch (err) {
          setStatus('typing');
          setError(err);
        }
    }
    function submitForm(answer) {
      // 失敗でエラーをスローする
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          let shouldError = answer.toLowerCase() !== 'lima'
          if (shouldError) {
            reject(new Error('Good guess but a wrong answer. Try again!'));
          } else {
            resolve();
          }
        }, 1500);
      });
    }
```

# UIを宣言的に考えるために
## コンポーネントのさまざまな視覚状態を特定する
さまざまな視覚状態とは、ユーザーが見るUIの状態である。
モックアップを作る時は各状態を基準に用意すると良い。
活用できるのは「storybook」で振る舞いの確認が可能。

例：入力フォームとSubmitボタンを持つFormコンポーネント
・無効状態のSubmitボタン
・有効状態のSubmitボタン
・フォーム入力不可かつLoading状態
・入力フォームとSubmitボタンが非表示になり、テキストメッセージが表示される
・エラーメッセージが表示される

## 状態変更を引き起こすトリガの決定
トリガには、人間からとコンピュータの入力の２種類がある。変化に応じて対応できるようにstateを設定する。
・人間からの入力：ボタンクリック、入力、リンク遷移など
・コンピュータからの入力：レスポンスの到着、タイムアウトなど

Statusの変化とトリガのフロー図を描くと可視化されわかりやすくなる。

## stateは可能な限り少なくする
stateは「動くパーツ」であり、増えれば複雑性が増すため。
stateはリファクタリングの対象とし複雑性を抑える

stateは、同時に発生しない状態同士で管理する考えを持つ。
例えば、エラーメッセージを表示しているときにサクセスメッセージを出すことはない場合、同じstateで制御することを考える。
また、より複雑な場合、state単体で制御しきれないこともある。
あるstateが変更された時テキストのみ表示になる場合、それ以外のコンポーネントの制御のために用意されたstateは意味をなさない。
それぞれのstateの本来あるべき状態を制御するために、useReducerを用いることも考える。


# 終わりに
視覚状態に応じたモックアップを想定し、入力に対してstateを用意し、用意したstateで状態を制御する。制御した結果が見れるようstorybookも使えるようにしていきたい。
また、stateの制御のためにuseReducerの使用も考えられるようになりたいと思いました。

# 次
https://qiita.com/mr_noppo/items/ff72d4fe67ec202e67b9
Hello World

## はじめに
初カキコ...ども...
ということで初投稿です。

最初に何を書くべきか、と悩んだ中でベタですが自己紹介書こうかなあと。これから投稿活動を行っていく上で、私がどんな人間かを知っていただけると幸いです。
前置きは程々に、お手すきの方はお付き合いください。

## 筆者の経歴
主な筆者の情報
### 学生時代
高校卒業後、私大文系の商学部に進学。
私文ゆえに遊びまくり...というわけでもなく、そこそこ真面目に勉強し、そこそこちゃんと遊びとバランスの取れた学生生活を送っていた。
会計には強い関心を持っていたのでそちらの勉強は比較的楽しんで行っていたものの、プログラミングに触れることはナシ。
強いて述べるならデータ入力のアルバイトで一応IT企業に所属していた程度だった。
キーボード叩ければ誰でもできる系だが、Web系の会社だったのでSEOとかCSSとか単語レベルの勉強にはなっていたかなあと思う。
家にいて暇な時間はソシャゲやFPS(APEXドハマリ時代)をプレイしていたので、気づけばゲームはそばにいたモノであったしそれが今につながっているかもしれない。
### 社会人1年目
就活では金融機関やメーカー経理などの選択肢があったが、それまで経験のなかった領域であるIT分野を選択。常に新しいことを勉強して知識のアップデートをしていたかったのと、単純に楽しそうだったからという気持ちで進んでいくことに。
入社後の部署選択でも **「楽しそう」** という熱を信じ、会社のエンタメ部門へと進んだ。
テスト業務の受託を行う会社であるため、QAにおける基礎業務を学んでいく1年であった。
デバッグ業務や項目設計・見積り作成などを広く学ぶことができ、着実な経験の1年になったと思う。ただ、**自分はデバッグをやるために今の会社に来たのか？本当にQAとしてキャリアを積みたいのか**と言いようのない違和感を抱くように。。。
真面目に他業界への転身なんかも視野に入れるようになった。
そんな中、所属会社にQAエンジニアとしての求人募集が届く。
これはチャンスじゃあないかと直感で感じ取り、ゴリ押しの結果2年目はQAエンジニアをやらせてもらうことに。
とりあえず、、ということで仕事に使う**Airtest**を自身のPCでいろいろと触ってみる。
### 社会人2年目
間違いなく社会人人生における転機となった1年。
テスト自動化を目的とするQAエンジニアとしての活動を開始する。
なんとかQAエンジニアという対外的な地位を頂いたものの悲しいかなプログラミングのプの字も知らないエンジニア。
**Pythonってなんぞ？？Gitってなんぞ？？** というところから始まり、とんでもないインプットの毎日。言語のチュートリアル本をはじめとする技術本を読み漁る。
わからないことがわからない状況ではあったが、頭を回し続けて手を動かし続けるべきという考えのもと、 **自動テストの制作を開始** 。実行環境などは先輩エンジニア方が整えてくださっていたのでプログラマーのような業務を行っていました。
なんやかんやとやっていけたのは先にも挙げたゲームテストフレームワーク**Airtest**と**Poco**のすごいところで、自分のように知識のない人間でも読み書きできるようになっていた。
2ヶ月ほどプログラミングを経験し、ここで悪癖が顔を覗かせ、 **調子に乗る。**
なんとなくプログラミングができるようになり、 **エンジニアとして成長してきた** と勘違いしてしまい、もっと色々やってみたい！と言い出す。ほんまに？
そんなワガママにも答えてくださって、Railsを用いた簡単な **デバッグ用APIの作成** にも着手し始める。もちろん最初から一人でできるわけもなく、サーバーエンジニアの先輩にお願いしながらモブワークで作成（質問攻め）を行う。おかげさまで今はほぼ一人立ちできている。感謝しかない。
ということでシナリオ作成、必要に応じてAPIの作成、自動テスト周りの進捗管理や実装の取り組みなどなど包括的に行うようになっていったのであった。
来年からは、、、どうなるのだろうか？私事で絶賛転職活動中なので社会人3年目は今もどうなるのだろうといったところである。その辺も記事にしていきたい。
### 習得技術
- 全体
    - Python,Ruby on Railsの読み書き
    - Github CopilotやChatGPTをはじめとするAIとの対話
- フロントエンド
    - ゲームの本当に基礎的な画面の作り方
- バックエンド
    - APIの作成
    - DBの理解、クエリを少し
- 自動テスト
    - 全体的な軽い進捗管理
    - 自動テストのコーディング
    - 運用におけるあれこれ
## まとめ
いかがだったでしょうか。
文字書くのは好きなほうだと思うのですが、長文はなかなか難しい。
読みやすい感じにまとまっていたら幸いかなあと思います。
今後書きたい内容としては

- ゲームの自動テストにおける技術。AirtestやPocoについて
- 0からエンジニアになる勉強方法
- 自主制作のゲームについて
- 転職活動周り

などなど書いていけたらなあと思います。
割と3日坊主気質なので決意表明として残しておきます（笑）
最後にはなりますが、読了いただきありがとうございました！
感想頂けるとモチベになります！
今後よろしくお願いします！
英語のYouTubeで勉強やキャッチアップしたい…！日英同時字幕クローム拡張機能「eJOY」の出番です

# はじめに
プログラミング学習中の[@kat_log](https://twitter.com/kat__log "Twitter")と申します。

英語のYouTubeも情報収集手段の1️つとして選択肢に入ると世界が広がりますよね…！
それを手助けしてくれるクローム拡張機能をご紹介です！

![image.png](https://soco-st.com/wp-content/themes/socost/upload/11813_color.svg)

# 結論
グーグルクロームの拡張機能**eJOY**を入れましょう！！🔥

# インストール
こちらをインストールです！

https://chromewebstore.google.com/detail/ejoy-ai-dictionary/amfojhdiedpdnlijjbhjnhokbnohfdfb?utm_source=hompage

# 早速使おう！
YouTubeで英語動画を開きます

https://www.youtube.com/watch?v=ZXsQAXx_ao0

字幕をオンにします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/7d4e99a4-b1e7-2d34-c0a3-63d36d83309c.png)

eJoyの設定アイコン（しずく「💧」のアイコンです！）をクリックして設定画面を開きましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/713af52f-ac0e-3ce7-f595-6db50d381ed6.png)

Original subtitles、Translation subtitlesをオンにします！
（その下の、Machin translationもオンにしておくと、機械翻訳ではありますが、日本語訳が２パターン見れるのでこちらもオンにするのおすすめです！）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/c0430ecb-7a13-5159-d3cd-d57286941f64.png)

Original subtitlesを英語、もしくは無ければ英語（自動生成）にします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/ab142eeb-25f8-4529-2012-2a355652d300.png)


Translation subtitlesを日本語にします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/a0cdca19-191b-ef59-019e-ac6ff145a17e.png)

これにて日英同時字幕で見れます！😆

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/a09ef010-9df8-2516-7da3-4cd93494e903.png)

# おまけ　カスタマイズ
文字サイズを調整すると見やすくなっておすすめです！

Full settingsを開きます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/43c6d70b-2ad1-8653-3533-da00b7bd4b2e.png)


Original subtitlesタブでは、Original subtitlesの文字サイズが変更できます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/eabd8ea8-4ee4-a65e-8edc-25ed09d5a1f2.png)

もちろんTranslation subtitlesやMachin translationもカスタマイズできます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/62271ba3-7ce7-01c3-5674-55fe58247735.png)


# 終わりに
動画に英語字幕が用意されていても、されていなくても、YouTubeの字幕自動生成の英語を、日本語訳してくれるので、YouTube上の全ての英語動画が、一応英語字幕＋日本語字幕で見れるという状態になります…！🙌🙌
自動生成＋機械翻訳のため違和感がある場合もあるのですが、意外と「なんとなく分かる」レベルで見れること多いです😂

お読みいただきありがとうございました！
どなたかの参考になれば嬉しいです！
便利なツールで情報収集の幅広げちゃいましょう〜！

# 参考

https://www.youtube.com/watch?v=ZXsQAXx_ao0
Linux勉強４日目：Apacheの設定ファイルを編集する。

少し期間が空いてしまった。子育て世代の宿命ですね。。。


前回はApacheのインストールと初期ページが開けることの確認までをしていた。
ので、今回はApacheの設定ファイルを編集する。

なんで編集する必要があるの？

 TelnetとかでApacheから情報を取得すると、以下の情報が見れる。

 ```bash
 [root@localhost conf.d]# telnet 127.0.0.1 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
OPTIONS / HTTP/1.1
host: localhost

HTTP/1.1 200 OK
Date: Mon, 01 Apr 2024 17:05:56 GMT
Server: Apache/2.4.57 (Rocky Linux)
Allow: OPTIONS,HEAD,GET,POST,TRACE
Content-Length: 0
Content-Type: httpd/unix-directory

Connection closed by foreign host.
```  

`Server: Apache/2.4.57 (Rocky Linux)`
`Allow: OPTIONS,HEAD,GET,POST,TRACE`
→　Apacheのバージョンがわかり、かつTRACEメソッドが有効なので、そのバージョン特有のセキュリティ脆弱性を悪用されるかもしれない。
これらの情報を隠蔽する

ディレクトリ表示の無効
→　ファイルリストをが外部から隠すことで外部から内部構造が知られてしまうのを防ぐ

クリックジャッキング無効
→　

```bash
[root@localhost conf]# vi httpd.conf
```
で設定ファイルを編集する。
`Options Indexes FollowSymLinks`から、Indexesを消す。

内部ディレクトリ構造を外部から隠すことができた。


あとは、設定ファイルの末尾に次の内容を追記する。
            
```apache
ServerTokens ProductOnly
ServerSignature off
TraceEnable off
Header append X-FRAME-OPTIONS "SAMEORIGIN"
```

上二行でバージョン情報の削除
下二行でクロスサイトスクリプティング、クリックジャッキングの対策                                     
が有効になった。

```bash
[root@localhost conf]# telnet 127.0.0.1 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
OPTIONS / HTTP/1.1
host: localhost

HTTP/1.1 200 OK
Date: Mon, 01 Apr 2024 17:19:45 GMT
Server: Apache
Allow: HEAD,GET,POST,OPTIONS
X-FRAME-OPTIONS: SAMEORIGIN
Content-Length: 0
Content-Type: httpd/unix-directory
```

数日間空いてしまったので、今回はここまでで・・・
サイズが気になるお年頃？

# はじめに
Linuxに限らずストレージの使用状況が気になるときがありますよね。あとどのくらい空き容量があるのか、どのくらい使用しているのか、確認するときのコマンドがいくつかあります。

# ``df``コマンド(Disk Free)
``df``コマンドはディスクの使用量や空き容量を確認できます。ただ、オプションなしで``df``と実行するとブロックサイズで表示されるのでいまいち分かりにくい。そこで``-h``オプションを付けて``df -h``で実行するとバイト単位で表示されるので分かりやすくなります。

# ``du``コマンド(Disk Usage)
``du``コマンドはディレクトリの使用量を確認できます。オプションなしで``du``と実行するとカレントディレクトリ(今自分がいるディレクトリ)の使用量を表示します。``du ディレクトリ名``で実行すれば指定したディレクトリの使用量を確認できます。こちらも``-h``オプションを付けることで読みやすい表示にできます。

# ``lsblk``コマンド(List Block)
``lsblk``コマンドは利用できるブロックデバイス(HDDやSSDなど)をツリー上に一覧表示できます。

# ``fdisk``コマンド(Fixed Disk)
``fdisk``コマンドは``-l``オプションを付けて``fdisk -l``で実行するとカーネルが認識しているパーティション情報を確認することができます。

# さいごに
AWSのLinuxインスタンスでEBSのサイズ拡張するときにもパーティションの確認などが必要です。オンプレでもクラウドでもLinuxのスキルは必要とされます。Linux技術の習得はより価値あるエンジニアになる一つの選択肢です。40歳超えて知識0からでもLinuCレベル3コンプリートして活躍できるのだから。そう、約半世紀ずっーーーーーと引きこもりで地球から一歩も出ていない石ころでも。

LinuCとは

https://linuc.org/about/01.html
世界一流エンジニアの思考法を読んで、個人的なまとめ(更新中)

###

以下の本を読んで、気になったフレーズと、なぜ気になったか、そこから何を学んだのかを
自分用にアウトプットとしてまとめていきます。

読んだ本はこちら↓

**世界一流エンジニアの思考法 by 牛尾 剛さん**

https://www.amazon.co.jp/%E4%B8%96%E7%95%8C%E4%B8%80%E6%B5%81%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%AE%E6%80%9D%E8%80%83%E6%B3%95-%E7%89%9B%E5%B0%BE-%E5%89%9B/dp/4163917683

***

### いきなり手を動かさない。まずは、事実（データ）を一つ見つける→いくつかの仮説を立てる→その仮説を証明するための行動をとる。


例えば、何かしら不具合やコンパイルエラーなどが発生した時、以下のようなアプローチを取ることがある。

1. エラー発生！
1. 色々適当に怪しいところをぽちぽちいじる
1. あ、なんか治った！とりあえずよかった！
1. 終わり。。。。

このアプローチは最悪で、よくないところが二点ある。

1. 治るんだったらまだいいが、、、`2`の手順の部分で、治るかどうかは割と運頼みなところもあり、目立てが悪かったらとんでもない時間かかる可能性がある。
1. 直せたところで、なんで治ったのか、何が原因だったのかを理解できていないので、何も自分の知識となっておらず、将来的な生産性が上がらない。



不具合などが発生したときには、以下のことを意識してアプローチする。

- いきなり手を動かすのではなく、なぜ不具合が起きているかを考え調査の方針を立てる。その上で手を動かす。
    - `思考のない試行錯誤は悪`

***

### 理解が十分でないまま手を動かして努力しても、空回りになるだけで身につかず、あやふやの試行錯誤は取り組んだことも忘れやすく頭に残らない。「何かを早くできるように急ぐ努力」がかえって本質的な理解を遠ざけてしまうのだ。

問題が発生した際にアプローチとして、問題解決を急ぐばかり、成長に糧にならない方法を取りがち。
例えば、

- GPTに直接投げて、帰ってきた答えをそのままコピペ
- ググって出てきたコードを直接はる。

上記の方法でも解決自体はできるかもしれないが、自分の成長としては何も残らず、次同じような原因の問題が発生したら同じことを繰り返す可能性が高い。(実際、自分はかなりこれやってしまっていた....)

よっぽどの非常事態でない限り、問題が発生した際の解決のアプローチとして、単純に問題が解決できたという結果だけを
追い求めるのではなく、それに伴う自分の成長も意識して問題解決に取り組む。

その際、**理解に時間がかかってしまっても、焦らない。**
どんなに頭がいい人でも、理解に時間をかけている。
(頭のいい人が問題解決が早いのは、以前時間をかけてしっかりと基礎を理解をしているから)

***

### メンタルモデルを作ることのススメ

そもそも、**メンタルモデル**とは？
↓
人々が世界を理解し、予測し、解釈し、新しい状況に適用するための、自己の心の中のイメージや理論のこと

メンタルモデルを前もって自分の中で作っておくことで、さまざまな事象に対して理解が早まる、、、らしい。
ここに関して、理解が浅いので、本書で紹介されている以下の本を読んでさらに理解を深めるのと、自分に合ったメンタルモデルを探していきたい。

[超一流が実践する思考法を世界中から集めて一冊にまとめてみた](https://www.amazon.co.jp/%E8%B6%85%E4%B8%80%E6%B5%81%E3%81%8C%E5%AE%9F%E8%B7%B5%E3%81%99%E3%82%8B%E6%80%9D%E8%80%83%E6%B3%95%E3%82%92%E4%B8%96%E7%95%8C%E4%B8%AD%E3%81%8B%E3%82%89%E9%9B%86%E3%82%81%E3%81%A6%E4%B8%80%E5%86%8A%E3%81%AB%E3%81%BE%E3%81%A8%E3%82%81%E3%81%A6%E3%81%BF%E3%81%9F%E3%80%82-%E3%82%AC%E3%83%96%E3%83%AA%E3%82%A8%E3%83%AB%E3%83%BB%E3%83%AF%E3%82%A4%E3%83%B3%E3%83%90%E3%83%BC%E3%82%B0/dp/4815604428)

*** 

### 一つのことで２時間以上ブロックされたなら、質問するなり相談するなりして寝かせておいて、他の仕事をやっておく方が断然生産性が高い(p.47)。

自分一人で解決しようと躍起になるのは、よくやりがちだが、これは自分自身にとっても、チームにとってもよくない。
エキスパートに早い段階で質問をすることで、修正の方向性も正すこともできるし、最終的なアウトプットも大抵よくなる。
自分一人で決めた方向性ではなくなるので、修正後の認識齟齬、出戻りも少なくなりチームとしても良い。

### 続く....順次更新中
[エンジニア面接で答えられますか？]  TCPの3ウェイ・ハンドシェイクについて

# 背景
こんにちは、エンジニアの[gccj](https://twitter.com/milegao)です。
4月になると何か新しいことをしたくなりますよね。
僕は定期的に記事を書くことにチャレンジしてみたいと決めました。
一方、毎週ネタを考えるのが難しいので「エンジニア面接で答えられますか？」シリーズなら考えなくても良いし、
他の方にも役立つと信じで、記念すべき第一回「TCPはなぜ3ウェイ・ハンドシェイクする必要がある？」を書きました！
お役に立つと思ったらぜひシェアよろしくお願いします。


それでは「TCPはなぜ3ウェイ・ハンドシェイクする必要がある？」を回答してみます！

# ジュニアの回答例
1. TCPは双方向通信のプロトコルです
2. 双方向通信だから、送信側と受信側との間に接続（connection）しないといけない
3. 送信側と受信側の接続とその確認のため3ウェイ・ハンドシェイクする必要がある


# シニアの回答例
### 1.  TCPは信頼性が高く、バイトストリーム指向、コネクション指向のプロトコルです

**信頼性が高いとは**：ネット状況が悪い状態においても、データを確実に送受信するのを保証すること。

**バイトストリーム指向とは**：バイトベースで、パケットと呼ばれる小さなチャンクに分割して送信。そして、ストリームというのは厳密な順序を保つことを意味する。

**コネクション指向とは**：データ転送する前に、コネクションを確立しないと行けないこと。

### 2. コネクション指向だから、コネクションを確立するために3ウェイ・ハンドシェイク

詳細：
```
SYN: クライアントがサーバーに対して接続要求（SYNパケット）を送信します。この段階でクライアントは自分の初期シーケンス番号をサーバーに伝えます。
SYN-ACK: サーバーは接続要求を受け取り、クライアントに対して接続受け入れの返信（SYN-ACKパケット）を送信します。このパケットには、サーバーの初期シーケンス番号と、クライアントのシーケンス番号への確認応答が含まれます。
ACK: クライアントはサーバーからのSYN-ACKパケットを受け取り、最後の確認応答（ACKパケット）をサーバーに送信します。これで、双方向の通信の準備が整い、データの転送が開始できます。
```

### なぜ2ウェイや4ウェイでもない？
##### 信頼性のためにシーケンス番号の維持が必要
シーケンス番号を利用して、パケットを標記することで、送った、受け取ったパケットを判別する。3ウェイ・ハンドシェイクはお互いのシーケンス番号の初期値を送受信両方を知らせと確認するため必要なプロセスです。


##### 不安定なネット環境でも安定なデータ転送を実現するために信頼性のあるコネクションの実現が必要
3ウェイ・ハンドシェイクはこの信頼性のあるコネクションを実現するのに最小値です。
もちろん4,5回もできるのですが、リソースの無駄になるため必要性がないです。

##### 無効の接続や遅延による混乱を防ぐため必要
ネットワークの品質が低下している状況下では、送信側が初期接続要求（ハンドシェイクリクエスト）を複数回送信する可能性があります。
この状況で、もし通信プロトコルが2ウェイ・ハンドシェイクだけを採用している場合、受信側は単に接続要求に対して承認（Yes）または拒否（No）の応答を返すだけになります。
このシンプルな応答メカニズムでは、受信側は送られてきたハンドシェイクリクエストが実際に新しい通信セッションを開始するためのものなのか、それともネットワークの遅延によって送信された無効な（重複な）ものなのかを区別することができません。

# 最後
以上、ジュニアエンジニアとシニアエンジニアそれぞれの回答を答えてみました。
もし記事の回答よりもっと面白い回答があればぜひコメントで共有いただきたいです！
Terraformの基礎勉強（１）Cloud9環境の構築

## 目的
Terraformの基礎（ついでにAWS開発環境）をハンズオンで学ぶ。出会ったエラー等も忘れず記録する。

## Cloud9の環境構築
#### 1. Cloud9とは
AWSの統合開発環境。コードを管理してリリースしたりできる。

https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/welcome.html

#### 2. 環境作成
AWS管理コンソールからCloud9を検索して、Cloud9の画面へ遷移。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2153287/7c3c65ae-d587-5c67-fc94-4c87ac99ff5a.png)

[環境を作成]を押下し、環境名とその他情報を入力。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2153287/477fbe4f-d42b-da4e-a3b2-de5551dcee4e.png)

[作成]を押下して環境が作成されていることを確認。
Cloud9 IDEの[開く]を押下して立ち上がればOK.

#### 3. asdfインストール
Terraformのバージョンを管理するツール。下記コマンドを入力してインストール。
```
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
```

```~/.bashrc```の最後尾列に下記を追記。
```
. "$HOME/.asdf/asdf.sh"
. "$HOME/.asdf/completions/asdf.bash"
```

今入っているCloud9環境を```exit```で抜けて、もう一個新しいTerminalを作成して、asdfのバージョンを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2153287/c52047e1-74aa-9294-693a-56f1bd146fad.png)

#### 4. asdfでTerraformをインストール
下記コマンドを実行。
```
asdf plugin add terraform
```
下記コマンドでインストール可能なTerrarformバージョンを確認できる。
```
asdf list all terraform
```

適当なディレクトリを作成後、下記ファイルを作成しコマンドを実行すると、tool-versionsに記載したバージョンがインストールされる。
```text:tool-versions
terraform 1.3.7
```
```
asdf install
```

## 参照
- asdf
┗Official Download
┗3. Install asdf
https://asdf-vm.com/guide/getting-started.html
Golangにおけるスライスの範囲指定：a[low : high]

`a[low : high]`: スライスの範囲を示します。startからendまでの要素を含みますが、end自体は含みません。つまり、start以上 end未満の要素が含まれます。

- 範囲指定の際、startの値は含まれ、endの値は含まれないことに注意
- 範囲指定は元のスライスの一部を参照するだけであり、元のデータを変更するわけではありません


例えば、以下のようなスライスがあるとします。この場合、a[1:4]は、インデックス1（含む）からインデックス4（含まず）までの要素を抽出します。つまり、[1, 2, 3]が返されます。

```go
package main

import "fmt"

func main() {
	a := []int{0, 1, 2, 3, 4, 5}

	var s []int = a[1:4]
	fmt.Println(s) // [1 2 3]
}
```

https://go.dev/play/p/G5l0I5tf4Sy
MacのOptionキーの隠された(?)チカラ

# はじめに
ふとした記事で目にした、`option`キーに備わる力。
色々調べていくと「こんな機能があったのか！」と驚くことがたくさんあったので、今回の記事にて共有したいと思います。

あんまりいっぱい紹介してもアレなので、私が実用的だと思った3つを紹介します。
知っているのしかなかったらすみません🙏

## 本題

では最初にFinderでのoptionキーでできることを紹介します。

<img width="300px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/17220d1d-bd06-80b5-ce08-9521d63e05b7.png">

これ、パスのコピーはどこからするんだ😡となったこと、ありませんか?
この時、`option`キーを押すと...

<img width="300px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/117e9ebf-0ba5-343b-35e0-b50f2a4014c0.png">

コピーの部分が、パス名をコピーに変わっています。
ここからできたのか...

こんな感じで基本は、メニュー画面でoptionを押すことにより隠れて?いたメニューが出てきます。

二つ目に、右上リンゴマークを押した時でてくるメニュー。

これが、
![スクリーンショット 2024-04-07 19.44.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/bd135676-b875-4c52-702f-499bbb827deb.png)
こうなります。
![スクリーンショット 2024-04-07 19.45.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/9aa33df1-d144-e7e9-b52b-689cdfa7fdba.png)

開いてみると「このMacについて」よりもかなり細かいシステム情報を見ることができます。

三つ目にChrome(と他のアプリ全て?)です。

これが、
![スクリーンショット 2024-04-07 19.48.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/630a09ed-b160-015a-704c-ef1bdd8f61bb.png)

こうなります。
![スクリーンショット 2024-04-07 19.48.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/4596aa88-1107-80be-5615-3cb80fe4ba98.png)

終了が「終了 (ほかのウインドウは保持)」となってますね！地味に便利かもしれません。

### 終わりに
他にもググればたくさんあるので、いいなと思ったらぜひ調べてみてください！
また、おすすめの使い方があればコメントに書いていってください🙇🏻‍♂️
ラグランジュ双対問題の強双対性について

# はじめに

ラグランジュ双対問題の強双対性についてわかった気になったのでまとめました。

# ラグランジュ双対問題の強双対性について

https://qiita.com/momo10/items/b296eda7146b15f68310

https://qiita.com/momo10/items/dc23a2a9b6459c9395a8
GitでCloneしたらearly EOF

## 再現手順
Reactのデザインテンプレートである[AdminLTE](https://adminlte.io/)を
自分のGitにforkし、ローカルにcloneしようとしたところ以下のエラーが出た。

```
% git clone {リモートリポジトリURL}
Cloning into '{リポジトリ名}'...
remote: Enumerating objects: 2889, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (3/3), done.
Receiving objects:  47% (1360/2889), 9.61 MiB | 121.00 KiB/s


error: RPC failed; curl 92 HTTP/2 stream 5 was not closed cleanly: CANCEL (err 8)
error: 7152 bytes of body are still expected
fetch-pack: unexpected disconnect while reading sideband packet
fatal: early EOF
fatal: fetch-pack: invalid index-pack output
```

## エラーの原因
こちらはリポジトリが大きすぎる際、cloneしようとすると
「デカすぎてムリィ…」とリクエストの過負荷で怒られてしまうことが原因。

## 解決方法
今回は、1度でcloneするのではなく、何回かに分けてcloneするという方法を採用。

コマンドは「git clone --depth」と「git fetch --unshallow」を使う。

```
git clone --depth 1 {リポジトリ名}
Cloning into '{リポジトリ名}'...
remote: Enumerating objects: 1135, done.
remote: Counting objects: 100% (1135/1135), done.
remote: Compressing objects: 100% (874/874), done.
remote: Total 1135 (delta 252), reused 1040 (delta 223), pack-reused 0
Receiving objects: 100% (1135/1135), 8.77 MiB | 160.00 KiB/s, done.
Resolving deltas: 100% (252/252), done.
```
cloneに成功したら、そのリポジトリへ移動し、fetchする。
```
% cd {cloneしたリポジトリ} 
% git fetch --unshallow
remote: Enumerating objects: 1867, done.
remote: Counting objects: 100% (1867/1867), done.
remote: Compressing objects: 100% (873/873), done.
remote: Total 1754 (delta 905), reused 1663 (delta 814), pack-reused 0
Receiving objects: 100% (1754/1754), 6.93 MiB | 99.00 KiB/s, done.
Resolving deltas: 100% (905/905), completed with 64 local objects.
```
これで問題なくcloneに成功した。

## depthオプションについて
git clone で --depth オプションを使うと、
指定したコミット数で刈り取ることができる。

Git のドキュメントを読むと、
depthオプションを使ったcloneのことを
「シャロークローン (shallow clone)」と呼ぶらしい。

https://git-scm.com/docs/git-clone

## git fetch unshallowについて

git fetch unshallowとは、
そのリポジトリにフェッチされていない全ての履歴をフェッチすることができる。
つまり、shallow cloneしたリポジトリであっても、
git fetch --unshallowを実行することで過去の履歴も追うことが可能。

## なんでearlyという名前？
これは自分がちょっと疑問に思ったので軽めに調査。
どうやらHTTPレスポンスに「425エラー（Too Early Experimental）」があり、
この意味とマッチしてそう（語源はしっかりと調べられておらず…）

引用元：[425エラーとは](https://find-a.jp/seotimes/glossary/425error/)

:::note info
425エラー（Too Early Experimental）とは、HTTPステータスコードの一種で、通常はウェブブラウザからウェブサーバーへのリクエスト時に発生します。一般的に、ウェブブラウザがウェブサーバーに対して情報を要求した際、そのリクエストが早すぎると判断された場合にこのエラーが表示されます。
:::


## 補足
結構Gitでcloneする際には、shallow cloneは使われているみたいです。
歴史が深い現場だと活躍するようですね。
私はまだ小規模で歴史が浅い開発経験しかないので、
いつかはレガシーな現場の大リフォームも行ってみたいものです。

## 参考
https://qiita.com/cacahuatl/items/4d763e98f3934e3569ca
[Vitest]mockを使ってテストしてみよう

# はじめに
Vitest は、高速で柔軟なユニットテストフレームワークです。Vitest を使うことで、モックを活用したテストを簡単に書くことができます。本記事では、Vitest のモック機能を使ったテスト手法について解説します。

# mockとは
mock とは、実際の動作を模倣したダミーオブジェクトのことです。テストを行う際に、実際の動作を再現するのが難しい場合や時間がかかる場合、mock を使うことで効率的にテストを行うことができます。

# なぜmockを使うのか
mock を使うメリットは以下のようなことが考えられます。

- 外部依存関係のあるコードをテストしやすくなる
- 外部の API や DB 接続など、テスト環境で再現が難しい動作をモックできる
- 外部システムの影響を受けずにテストできる
- テストの実行時間が短縮できる
- これらのメリットを活かすことで、効率的かつ信頼性の高いテストを書くことができます。

# mockを使ってテストを書いてみる
Vitest では、vi.fn() を使ってモック関数を作成することができます。以下に具体的な例を示します。


``` mock.ts
export const mockTestFunc = (value1: number, value2: number): number => {
  return value1 + value2;
};
```

```mock.test.ts
import { mockTestFunc } from './mock';
import { expect, test, vi } from 'vitest';

test('mockTestFunc adds two numbers correctly', () => {
  const mockFn = vi.fn(mockTestFunc);

  const result1 = mockFn(2, 3);
  expect(result1).toBe(5);
  expect(mockFn).toHaveBeenCalledWith(2, 3);
  expect(mockFn).toHaveBeenCalledTimes(1);

  const result2 = mockFn(10, 20);
  expect(result2).toBe(30);
  expect(mockFn).toHaveBeenCalledWith(10, 20);
  expect(mockFn).toHaveBeenCalledTimes(2);
});

test('mockTestFunc returns undefined for non-number inputs', () => {
  const mockFn = vi.fn(mockTestFunc);

  const result1 = mockFn('a' as unknown as number, 3);
  expect(result1).toBeUndefined();
  expect(mockFn).toHaveBeenCalledWith('a' as unknown as number, 3);

  const result2 = mockFn(10, false as unknown as number);
  expect(result2).toBeUndefined();
  expect(mockFn).toHaveBeenCalledWith(10, false as unknown as number);
});
```
この例では、mockTestFunc 関数をモック化し、正常な入力と異常な入力に対してテストを行っています。モック関数の呼び出し回数やパラメータ、戻り値などをアサーションすることで、関数の動作を検証しています。

Vitest の vi.fn() を使うことで、簡単にモック関数を作成できます。また、toHaveBeenCalledWith や toHaveBeenCalledTimes などのアサーション関数を使うことで、モック関数の呼び出しの検証も行えます。

# 最後に
Vitest を使ったモックを活用したテストについて解説しました。モックの活用は、効率的かつ信頼性の高いテストを書くための重要なテクニックです。


# 参考
https://vitest.dev/guide/mocking.html

https://vitest.dev/api/mock

# 最後に
他にも色々な記事を書いているので、よければ読んでいってください、、、

https://qiita.com/hukuryo/items/5c1f04929caea8a409dc

https://qiita.com/hukuryo/items/3e4cc8b3588d39df84ea

https://qiita.com/hukuryo/items/b7eacc4c9cd844dda9b6
PostgreSQL 学習に役立つサイト

個人的にPostgreSQLの学習の役に立ったサイトまとめ  

# ベース

## Official
基本的にドキュメントに書いてあることを気力の限りハンズオンで試す。  
ボリュームが多いので、私の場合は2~3カ月掛かった。  

https://www.postgresql.org/docs/current/index.html



# 内部構造

## EDB Webinar
分かりやすい説明でお勧め

https://edbjapan.com/postgresql-technical-webinar-announcement/

## The Internals of PostgreSQL
難しいけど、雰囲気を掴むのに良い

https://www.interdb.jp/pg/

# 情報収集

## Planet PostgreSQL

https://planet.postgresql.org/

## pganalyze

https://pganalyze.com/blog

## CYBERTEC

https://www.cybertec-postgresql.com/en/tag/sql-help/


## Percona

https://www.percona.com/blog/

## BuruceのBlog
英語が分からなくても発表資料は一通りハンズオンで進められるのでお勧め

https://momjian.us/main/blogs/pgblog.html
MUI) Material Iconの画像位置を調整したかったときの話


## この記事の対象者

- Reactの
- Material UI の中で
- IconButton の上に
- Material Icons を乗せつつ
- Icon の位置を調整したい

そんな方にお送りします。

戻るとか、進むのボタンをArrowBackIosNew, ArrowForwadIos で表現したかった。

でも、丸い背景に乗せると、ちょっとズレて見えてしまう。

この錯覚を解消するために、Arrowの部分をずらしたかったのにずいぶん苦戦しちゃった…💦

という内容です。

<a id="anchor2"></a>
## 目次

1. この記事の対象者
2. 目次
3. TL;TL
4. コード概要
5. classの指定について（補足）
6. 学び



## TL;DL

結論

- Material Iconのpropsに `sx={{'&.MuiSvgIcon-root': {marginLeft: '2px'}}}` のような形で子要素のclassにスタイルを当てればOK

`&.MuiSvgIcon-root` …こんな書き方知らないよー＼(^o^)／


## コード概要

MUIのButtonにMaterial Iconを単純に乗せた場合のコードは下記の通り。

(Buttonのサイズは32px × 32pxの真円、中のIconは24pxとしました)

```tsx
import {Box, IconButton} from '@mui/material'

exprot default function HogeView() {
    return (
        <>
            <IconButton sx={{width: '32px', height: '32px'}}>
                <ArrowBackIosNew/>
            <IconButton/>
            <IconButton sx={{width: '32px', height: '32px'}}>
                <ArrowForwardIos/>
            <IconButton/>
        </>
    )
```

このままの表示だと、

ArrowBackIosNewの＜の形が、円の中心からやや右にズレた位置にあるように見える。

(実際はセンターに配置されているが、錯覚でズレて見えてしまう)

雑なイメージだと、

( <)

こんな感じ。

ので、少しだけ左に＜の位置をシフトさせたい。

その場合は、IconのSvgの要素に対して、marginをつけてあげればよいので、

```tsx
import {Box, IconButton} from '@mui/material'

exprot default function HogeView() {
    return (
        <>
            <IconButton sx={{width: '32px', height: '32px'}}>
                <ArrowBackIosNew sx={{'&.MuiSvgIcon-root': {marginRight: '2px'}}}/>
            <IconButton/>
            <IconButton sx={{width: '32px', height: '32px'}}>
                <ArrowForwardIos sx={{'&.MuiSvgIcon-root': {marginLeft: '2px'}}}/>
            <IconButton/>
        </>
    )
```

としてあげればよい。
※ArrowForwrdIosの場合は逆で、右にズラすのでmarginLeftを入れる。


## classの指定について

開発者ツールで要素を確認してみると、

Material Iconの要素の中に子要素としてIcon画像の要素が存在していることがわかる。

class名として色々と付与されているので、

今回はそのせんのものを選択して値を指定した。


## 学び

まだまだ開発者ツールとお友達になれていないので、

使い方をもっと触って覚えていきたい…というのと、

Arrowの位置ズレが、Iconの重心位置の関係でズレて見えるという事を踏まえて、

1px単位で調整の指定をするデザイナーさん、すげぇわ。
41歳 非エンジニアが本気でエンジニア転職に挑戦する

## 自己紹介
はじめまして。[@nyakako13](https://qiita.com/nyakako13 "Qiita ページ") です。
現在は非エンジニア（某通信会社所属）で、年齢は41歳です。

20代、30代でほんの少しだけエンジニア経験があります。
（VBやPHPを使っていました）

かなり昔の話なので、正直その頃の経験はあまり活かせません。

ここ1,2年でPython,Javaなどを独学で学び、いくつか簡単なWebアプリを作ってデプロイしました。（良かったらGithub見てみてください。）

資格も一応、基本情報とJava Silverを取得しました。


## なぜ本気で学ぶのか？
今、３歳の子供がいるのですが
子供が産まれてから今後の働き方を考えることが増えました。

今の仕事を楽しめていない自分の姿を子供にずっと見せ続けるのか・・・！？
そんな親の姿を見て、子供はどんな風に育つのだろうかと心配になりました。

また、若い頃はその時の事情で続けられなかったけれど
ITやプログラミングはもともと好きな分野でした。

エンジニアの仕事自体も好きで、
ずっといつかエンジニアに戻りたいという想いをもっていました。

物価も上がり続けるこんなご時世ですが
普通の会社員では昇給の見込みもかなり少ない・・・

エンジニアならがんばってスキルを上げて、価値提供していければ
収入も増やせる職業だし、もう一度挑戦したい！！

<br>

要は単純に子供にカッコつけたいだけなのかもしれません。笑

<br>

しかし、40代でのエンジニア転職は予想以上に大変でした。

- そもそも書類選考に通らない
- 面接に進んでも「スキル不足」でお祈りメールがきたり
「年齢とスキルが見合っていない」などと渋い顔をされる
- カジュアル面談ですら
 「エンジニアの素養、ポテンシャルが見えづらい」
 「スキルレベルが求めるレベルに届いていなかった」
　などの理由でお見送りになることも・・・

このままではいけない。。

20代,30代の若い方以上に企業が認めてくれるだけの、
何か、圧倒的なアピールポイントや実力が必要だと感じました。

## JISOUとの出会い
そんな中、Qiitaの技術記事や登壇など圧倒的なアウトプットで人生を変えられた[@Sicut_studyさん](https://qiita.com/Sicut_study "Jinさん Qiitaページ") の[JISOU](https://projisou.jp/ "JISOU") というサービスに出会い、参加することにしました。



## 決意
まずはQiita記事100本投稿します！！


## 将来なりたい姿
エンジニア転職を成功させて、
40代からエンジニアを目指す方の希望に少しでもなれたら嬉しいです！

## おわりに
未経験や浅経験、厳しいと言われている年代で転職活動されている方、　まけずにがんばりましょう！！
OpenAIのライバル:Cohereが最高にイケている件

## はじめに
Cohere(コーヒア)とは、生成AI関連のスタートアップ企業であり、オラクル、エヌビディア（NVIDIA）、セールスフォース・ベンチャーズ（Salesforce Ventures）、センチネルワン（SentinelOne）などが支援しています。

これまでにCommand-R+などのモデルを公開しています。

今回はCohereのイケている部分について紹介させていただきます。

## UIがイケている
こちらCohereのダッシュボードです。実際に使ってみるとわかるのですが、全ての画面がわかりやすいです。この画面だけでもやりたいことがすぐ見つけられますし、サイドバー、ヘッダーの選択肢も適切です。（筆者の感想ですが）


![ 2024-04-08 18.47.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/844efa7a-666b-a382-1f6d-3514a31aa70c.png)

PlayGroundはChatだけではなく、ClassifyとEmbedも選択できます。
さらにConnectorsでWeb検索を有無を選択できます。

このUIの偉いところは、一画面で情報が十分で、初めて使う筆者のようなユーザーにとってわかりやすく作られています。

![ 2024-04-08 18.53.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/30108544-e25e-7752-0d0f-da30735c519a.png)

Embedについても見てみます。
プログラムもAPIキー付きで簡単に見ることができ、個人的には調べる手間が一つ減るので、フレンドリーです。


![ 2024-04-08 19.03.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/93bdc3d8-a641-6415-144c-4fe48a3dc2b9.png)

ファインチューニングについても見てみます。

ファインチューニングの画面のUIの偉いところは、データを入力する画面に具体例&説明が記載されており、とてもわかりやすいです。
ドキュメントを熟読せずとも、簡単に使えるというのがフレンドリーです。（ちなみにドキュメントもわかりやすいです）

![ 2024-04-08 22.27.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/0fe82f55-9ec9-1ce1-d466-7d56b0b44394.png)


以上より、（筆者の主観ですが）UI/UXがとてつもなく良いです。


## ドキュメントが豊富でイケている
### ドキュメントの概観

こちらがCohereのドキュメントです。

https://docs.cohere.com/

![ 2024-04-08 22.05.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/f015cd74-6215-b47b-8ea9-a23ee0972f92.png)

サイドバーの情報の粒度が適切で調べたいことにすぐ辿り着けますし、量も少なすぎることは一切ないです。

### 教育資料が豊富(LLM University,LLMU)

以下のサイドバーを見てほしいのですが、コンテンツが豊富かつわかりやすいです。

https://docs.cohere.com/docs/llmu

![ 2024-04-08 22.08.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/9cc56b79-8b9a-88a6-4a0f-01384a4c0758.png)


さらに各パートで解説のnotebookまでついています。

以下ReRankingのノートブックなのですが、プログラムもしっかりしています。

なぜこれが無料なんだ。

https://colab.research.google.com/github/cohere-ai/notebooks/blob/main/notebooks/llmu/End_To_End_Wikipedia_Search.ipynb

### 具体例が豊富
教育資料のみならず、アプリケーションの具体例まで豊富です。

https://docs.cohere.com/page/application-examples


![ 2024-04-08 22.17.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/217b7753-a62a-2fe5-9eda-b97557a1e7f7.png)


`streamlit`でのアプリケーションコードが全文公開されているので、簡単にLLMを組み込んだアプリを作ることができます。

なぜこれが無料なんだ。（2回目）

## モデルがイケている
モデルに関しては他の人が色々な記事を書いているので、ここでは割愛します。自分も面白い内容があったら記事にします。

ここでは`CohereForAI/c4ai-command-r-plus`のリンクだけ置いておきます。

https://huggingface.co/CohereForAI/c4ai-command-r-plus

## トークナイザーがイケている (2024/04/11追加)
トークナイザーについて以下の記事を出しました。
端的にCohereのトークナイザーについて述べると語彙数が多い&必要なトークン数が既存モデルより少ないです。特に後者のトークン数が少ないという観点は、応答速度に直結します。

よければ読んでみてください。

https://qiita.com/sergicalsix/items/5ceb9a3a0d11affb4b9a

## さいごに
Cohereに惚れてしまいました。

このサイトを見るだけで、内部に優秀なフロントエンドエンジニアとデザイナー、AIエンジニアがいるだろうと予想されます。（当たり前かもしれませんが）

とりあえずCohereのペーパーは以下40ほどあるので、今月来月までに全部目を通して記事を出したいなと思います。

https://cohere.com/research/papers
Docker composeで--env-fileオプションとデフォルト環境変数を使ったコンテナ内環境変数の切り替え方法

# はじめに
　Docker composeの起動時オプション「--env-file」と「environment」のデフォルト環境変数を使って、コンテナ内の環境変数を切り替える方法を紹介する。  
　設定ファイル(xxx.env)を複数用意することで、コンテナ内の環境変数を変更することができるので、docker-compose起動時にコンテナの振る舞いを変更したいときに有用。

# 動作確認環境

* Ubuntu 22.04
* Docker compose v2.24.2

# 方法

## ポイント
* docker-compose.ymlファイルの```environment```セクションに、コンテナ内に指定したい環境変数を指定
  *  この時、デフォルト環境変数の値を設定しておく
* xxx.envファイルに、個別設定したい環境変数を記載
* ```environment```に指定するコンテナ内の環境変数と、xxx.envファイルに指定するdocker-composeファイル内の環境変数の名前は同じにしておく（別々でも良いが、わかりやすくするため）

環境変数の設定の流れは以下となる。
```mermaid
graph LR
    Env[--env-file xxx.env] --ファイル内環境変数の設定--> Compose
    Compose[docker-compose.yml] --environmentでコンテナ内環境変数を設定
                                  コンテナ内環境変数=ファイル内環境変数
                                  (ファイル内環境変数にデフォルト値を設定)--> Container[コンテナ]
```

## 具体例
### 構成

　以下のようなファイル構成とする。ここでは、切り替えたい個々の環境変数設定として、```a.env```と```b.env```を用意する。
```bash
.
├── docker-compose.yml
└── config
    ├── a.env
    └── b.env
```

### docker-compose.ymlの設定

　環境変数のデフォルト値の指定は、```${環境変数名:-デフォルト値}```と指定する。こうすることで、環境変数が設定されていない場合はデフォルト値が使われるようになる。

:::note warn
デフォルト値の前に-が入るので、数値を設定する場合は注意する。
:::

```docker-compose.yml
version: '3'
services:
  test:
    image: ubuntu:20.04
    environment:
      STRING_VALUE=${STRING_VALUE:-default}  # デフォルト値:default 
      BOOL_VALUE=${BOOL_VALUE:-false}  # デフォルト値:false
      INT_VALUE=${INT_VALUE:-1}   # デフォルト値:1
      DOUBLE_VALUE=${DOUBLE_VALUE:--1.5}   # デフォルト値:-1.5

```

### xxx.envファイルの設定

　個別設定したい環境変数をxxx.envファイルに記述する。docker-compose.ymlに記述したデフォルト値を利用したい場合は、xxx.envファイルには指定しない。

#### 設定A

```a.env
STRING_VALUE=a
BOOL_VALUE=true
INT_VALUE=2
DOUBLE_VALUE=0.1
```

#### 設定B

```b.env
STRING_VALUE=b
```

### 起動方法

#### 環境変数のデフォルト値を使いたい場合

```bash
docker compose up
```

コンテナ内の環境変数は以下のようになる（全てデフォルト値）。
```bash
STRING_VALUE=default
BOOL_VALUE=false
INT_VALUE=1
DOUBLE_VALUE=-1.5
```

#### 設定A (a.envを指定する場合)

```bash
docker compose --env-file ./config/a.env up
```

コンテナ内の環境変数は以下のようになる（全てa.envで設定した値）。
```bash
STRING_VALUE=a
BOOL_VALUE=true
INT_VALUE=2
DOUBLE_VALUE=0.1
```

#### 設定b (b.envを指定する場合)

```bash
docker compose --env-file ./config/b.env up
```

コンテナ内の環境変数は以下のようになる（STRING_VALUE以外デフォルト値）。
```bash
STRING_VALUE=b
BOOL_VALUE=false
INT_VALUE=1
DOUBLE_VALUE=-1.5
```

# まとめ

　Docker composeの起動オプション--env-fileとenvironment環境変数のデフォルト値を使って、コンテナ内の環境変数を切り替える方法を紹介した。envファイルを複数用意することで、コンテナ環境変数を変更してコンテナの挙動を変更させたい場合に有用。

# 参考

https://docs.docker.jp/compose/environment-variables.html

https://qiita.com/SolKul/items/989727aeeafcae28ecf7

https://qiita.com/suin/items/a51a5cba17ee568c8b01
Linuxでユーザを作る方法と初期設定ですること

# はじめに
自分用メモです
あまりわかっていないことがあります

# 環境

環境はWSL2 2204 を使ってます。
まぁローカルでも大丈夫なのではと思ってます。

# 作業

## ユーザー作成と初期設定
usernewはあなたの作りたいユーザー名に置き換えてください。
newgroupはあなたの作りたいグループです。
まずは、新しいユーザーの作成と初期設定から行います。以下の手順をroot権限で実行します。root権限がない場合は、コマンドの先頭に `sudo` を付けて実行してください。

### ユーザー作成

```shell
sudo adduser newuser
```

### パスワード作成
パスワードは見えません
```shell
passwd  newuser
```

### sudo権限の付与（任意）

```
sudo usermod -aG sudo newuser
```

### グループへの追加（任意）
```
sudo usermod -g $newgroup1 newuser
```

### サブグループへの追加（任意）

```
sudo usermod -a $newgroup2 newuser
```

### ユーザーのディレクトリ作成
```
sudo mkdir /home/newuser
```

### ディレクトリに権限を与える
newuserというグループとnewuserに所有権を与えています。
```
sudo chown -R newuser:newuser /home/newuser
```


所有者には読み取り、書き込み、実行の権限を与え、グループと他のユーザーには読み取りと実行の権限を与えます。
```
sudo chmod 755 /home/newuser
```
ユーザーに切り替えたいときは

```
su newuser
```
## シェルの設定



初期ではコマンドラインが
```
$
```
のみとなっており非常にわかりにくいです。

そこでユーザー名とパスをコマンドラインに表示します。
このときの色付けも行います。

### bashのとき

`~/.bash_profile`に

```
PS1='\[\033[1;32m\]\u\[\033[0m\]\[\033[1;32m\]@\h\[\033[1;37m\]:\[\033[0m\]\[\033[1;34m\]\w\[\033[0m\] $ ' 
```
を追加
`~/.bash_profile`はシェルにログインしたとき読み込まれるファイルです。


デフォルトシェルをbashに変更
(たぶん)シェルがshからbashに変わります。

```
chsh -s /bin/bash
```

### zshのとき


~/.zshrc

に
```zsh:.zshrc
PS1='%F{green}%n%f@%F{green}%m%f:%F{blue}%~%f%# '
```

と書き込んでユーザ名とパスを色づけしましょう。

デフォルトをzshにするには

```
chsh -s /bin/zsh
```

## WSLの場合（任意）

WSLデフォルトユーザーの変更


/etc/wsl.conf ファイルに以下の設定を追加します。

```
[user]
default=username
```

その後、PowerShellで以下のコマンドを実行し、WSLをシャットダウンします。


```
wsl --shutdown
```
再度WSLを起動すると設定が反映されるはずです。
AL2023にyarnをansibleを使ってインストールしたい

こちらを参考に手順を作りました

https://chore-update--yarnpkg.netlify.app/en/docs/install#linux-tab


手順をplaybookに変換しているだけですが、こちらでうまく動作いたしました。

```playbook.yaml
- name: yarn をインストールする手順
  block:

  - name: node をインストール
    ansible.builtin.shell:
      cmd: "curl --silent --location https://rpm.nodesource.com/setup_20.x | sudo bash -"
    become: yes

  - name: yarn のrpmパッケージをダウンロード
    ansible.builtin.get_url:
      url: https://dl.yarnpkg.com/rpm/yarn.repo
      dest: /etc/yum.repos.d/yarn.repo
      mode: '0755'
    become: yes
  
  - name: yarn をインストール
    ansible.builtin.dnf:
      name: yarn
      state: present
  become: yes
```

コマンド
`ansible-playbook playbook.yml --ask-become-pass`
Gradleリポジトリの検索条件を設定して、ビルドを効率化

Android Studioで新規プロジェクトを作成した場合に、setting.gradle.ktsのpluginManagementが以下のように作成されるようになっています。

```setting.gradle.kts
pluginManagement {
    repositories {
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        mavenCentral()
        gradlePluginPortal()
    }
}
```

Gradleでは複数のリポジトリが記述されている場合、先頭から順にリクエストし、エラーとなった場合は次のリポジトリにリクエストする、という検索が行われます。ネットワークリクエストを伴うためコストが大きく、リポジトリやライブラリの数が増えていくとどんどん効率が悪くなってしまいます。できれば不要なネットワークリクエストは行いたくないものです。

そこで、ライブラリを検索する条件を設定して、条件に合致しない場合はそもそもリクエストを行わないようにすることでビルドの効率を上げることができます。

# 条件設定方法

include条件とexclude条件を設定することができます。
include条件に該当したものの中からexclude条件に該当したものを除いたものが、そのリポジトリにあると見なされます。
デフォルトはすべてをincludeし、excludeなしの状態ですね。
フィルタリング条件は様々ありますが、通常はライブラリのGroupIDで条件振り分けをすることになるでしょう。
ここでは省略しますが、同一のGroupIDで複数のリポジトリにArtifactが配置されているもの、同一のライブラリで、バージョンによってリポジトリが異なる、という場合もあり得ることです。その場合も指定する手段は用意されています。

`includeGroup`/`excludeGroup`
GroupIDを直接指定します。

`includeGroupByRegex`/`excludeGroupByRegex`
GroupIDを正規表現で指定します。正規表現になれていないと間違った指定をしてしまいがちでもあります。

`includeGroupAndSubgroups`/`excludeGroupAndSubgroups`
前述の正規表現は少し使用の難易度が高いですが、ほとんど場合で正規表現を用いるのは、そのグループおよびそのサブグループ全体（`org.gradle`自体および`org.gradle.XXX`全体）を指定したい場合であるということで、Gradle 8.1から追加された指定方法です、まだ`@Incubating`がついていますが、特別不安定というわけではなさそうで、ほとんどの場合、これを使えば問題無く指定できると思います。

android開発ではgoogleのリポジトリは必須で使いますので、概ね以下のような指定になると思います。

```setting.gradle.kts
pluginManagement {
    repositories {
        google {
            content {
                includeGroupAndSubgroups("com.android")
                includeGroupAndSubgroups("com.google")
                includeGroupAndSubgroups("androidx")
            }
        }
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google {
            content {
                includeGroupAndSubgroups("com.android")
                includeGroupAndSubgroups("com.google")
                includeGroupAndSubgroups("androidx")
            }
        }
        mavenCentral()
    }
}
```

そのほか業務での開発なら社内でのみ利用するリポジトリなどがあると思いますので、それらに適切な条件を設定して無駄な検索が行われないようにすると良いでしょう。

以上です。
4/20 tecHub（IT交流会）を秋葉原で開催！

![20240420_tecHub1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670233/220f15b6-0fee-2bf8-5138-3ac86a54b888.jpeg)

新社会人になり、まだ仕事に慣れない人。
社内で異動があり、環境が変わった人。

新年度は、変化が多い月です。
今年度の目標を決めて、スタートした人も多いと思います。

今月もtecHubを開催しました。
tecHubは、キャリアを考えるきっかけになる場にもなっていますが、IT業界のキャリアについて興味深いトピックがあったので、紹介します。

**目次▼**
<INS>[今月のトピック](#今月のトピック)
[2024年4月のtecHubを開催しました！](#2024年4月のtecHubを開催しました！)
[今後について](#今後について)
[次回の開催](#次回の開催)</INS>

<h3>今月のトピック</h3>
ここ数年、賃金は上がらないのに、物価は高騰しています。
お金のことを考えて、より節約を工夫したり、副業やキャリアアップを考える人も増えています。

<b>新卒の初任給を引き上げ！25万円以上に</b>

新卒の初任給を引き上げている企業が、ニュースになりました。
数年前は初任給が20万円前後だったので、大きく引き上がっています。

会社で昇給するには、資格を取ったり、数少ない役職に就くなど。
会社独自のルールで決まっているため、今の会社で昇給を狙うと時間がかかるケースもあると思います。

そのため、勉強や副業でスキルアップしたり、転職やフリーランスへの転向をすることが、当たり前の時代になってきました。
会社以外の収入アップを考える人は、10年前よりも増えていると感じています。

<b>転職を選択肢に入れる時代</b>
社会人の5人に1人が転職を視野に入れており、新卒の社会人でも4人に1人が転職を考えています。

転職理由の上位は、
<b>・収入アップ
・職場の人間関係
・スキルアップやリスキリング</b>
など。

転職をキャリアアップの一つの手段と捉えて、長期で人生設計を考える時代です。
tecHubでは、そういう方に向けてリアルな情報交換の場を提供しています。

<h3>2024年4月のtecHubを開催しました！</h3>
4/20にtecHubを秋葉原で開催しました。
参加者は、75名となり、大盛況でした。

日付：4/20(土) 14:00〜16:30
場所：LIFORK秋葉原Ⅱ 1階ラウンジ
参加者：約75名
内容：IT交流会

<b>tecHubは毎月イベント開催しています！</b>

毎月60〜80名ほどの方が参加している人気のイベントです。

3ヶ月に1度：LT（ライトニングトーク）と懇親会の2部構成イベント
その他：オフラインのIT交流会イベント

今回のIT交流会は、ピザとドリンクを片手に、ITエンジニア同士の情報交換や他分野の話を聞いたり、キャリアの相談ができます。
普段の職場では聞けない話も聞けるので、会を重ねるごとに参加者が増えています。

![20240420_tecHub2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670233/ce389278-4fdc-efeb-6840-e36b2555e5e6.jpeg)

<b>IT交流会に参加した人の声</b>
今回も、幅広い分野のIT関係者が集まり、会社員、フリーランスエンジニア、法人化されている方など、様々な人が参加していました。

今月は、環境や立場によって求められる人間的・技術的なスキルの変化を体感し、課題解決に向けた活発な会話が交わされました。
幅広い分野と様々なキャリアを持つ人々がいることで、異なる立場からの視点や考え方を取り入れることができたようです。

参加者からは、
<b>「転職やフリーランス転向などのキャリアアップを考えるきっかけになった」
「学びの多い会だった」
「参加してよかった」</b>
などの声をいただいています。

さらにIT業界に興味のある他業界の方も参加しており、<b>「IT業界について色々と知ることができて良かった」との声もありました。</b>
イベント中はもちろんのこと、会場の扉が閉まる最後まで活気ある雰囲気で盛り上がりました。

<h3>今後について</h3>
来月は、LT付きの懇親会イベントを実施します。
今後もtecHubをよろしくお願いいたします。

<h3>次回の開催</h3>
次回の開催は、以下の日程を予定しております。

日時：5/18(土) 13:00～16:30　
場所：近日公開
内容：2部構成（LT＋懇親会）

詳細とお申込みは、以下のサイトをご確認ください。

https://tecworks.connpass.com/event/314509/

また、tecHubはコミュニティサイトも始めました。
会社員、フリーランス、法人の方向けに、オフラインコンテンツと人脈形成の機会を提供しています。

https://www.navi56.com/communities/tecHub
Hexabase TypeScript SDKの使い方（グループの使い方）

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

この記事ではHexabase TypeScript SDKのインストールと、グループの使い方を紹介します。

## インストール

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

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

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

## インポート

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

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

## 初期化

HexabaseClientを初期化します。

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

## 認証

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

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

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

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

## グループとは

グループはユーザーをまとめて管理する機能です。また、グループには子グループを作成でき、ツリー構造で管理できます。

なお、すべてのユーザーは1つ以上のグループに所属している必要があります。

## グループを取得する

グループはワークスペースの下で管理されます。

```jsx
// ワークスペースを設定
await client.setWorkspace('demo');
// グループを取得
const groups = await client.currentWorkspace.groups();
```

なお、通常は `groups[0]` にデフォルトグループ「ワークスペース」が入っています。

## グループを作成する

新しいグループを作成するには、 `group` に対して `save` メソッドを実行します。

```jsx
const group = await client.currentWorkspace.group();
group
	.set('name', 'test group')
	.set('display_id', 'test_group');
await group.save();
```

## グループを入れ子にする

グループを入れ子にする場合は、親グループの `group` メソッドを使います。

```jsx
const group2 = await group.group();
group2
	.set('name', 'test group 2')
	.set('display_id', 'test_group_2');
await group2.save();
```

## ユーザーを追加する

ユーザーを追加するには、 `add` メソッドを使います。

```jsx
await group.add({ email: 'user@example.com', userName: 'demo'});
```

## ユーザーを削除する

ユーザーを削除するには、 `remove` メソッドを使います。

```jsx
await group.remove({ id: 'USER_ID' });
```

## 所属しているユーザーを得る

所属しているユーザーを得るには、 `users` メソッドを使います。

```jsx
const users = await group.users();
```

## グループの削除

グループを削除するには、 `delete` メソッドを使います。

```jsx
await group.delete();
```

## まとめ

SDKを使うことで、データベース参照は簡単に操作できます。グループを使うことで、データへのアクセス制御が柔軟になります。

Hexabaseには他にもバイナリファイルのアップロードや認証などの機能があります。それらの機能も利用してください。

[Hexabase \| 新規事業向け開発・競争領域でのDX実現をサポート](https://www.hexabase.com/)