OmniAICreator/Qiita-1.07M huggingface dataset:
【Java】Javaで出来ること

# 目的
Javaで出来ることを把握する。

# 目次

1. [Javaの特徴](#javaの特徴)
1. [アプリの開発](#アプリの開発)
1. [Webサイトの作成](#webサイトの作成)
1. [Webサービス](#webサービス)
1. [システムの開発](#システムの開発)
1. [組み込みシステムの開発](#組み込みシステムの開発)

# Javaの特徴

まず、Javaの特徴ですが、以下のような特徴があります!

・実行速度が速い
・ライブラリが充実している
・プラットフォームに依存しない

Javaは環境に左右されない言語で、`JVM`（Java Virtual Machine：Java仮想マシン）が入っていればWindowsでもLinuxでもMac上でも動きます。

# アプリの開発

まずJavaで出来ることの1つにアプリの開発があります。
特にJavaで開発されるAndroidアプリはとても多く、Androidスマートフォンアプリのどんな分野も開発できるため、標準開発システムと言えます。

また、パソコンのアプリにもJavaで開発されたものがあります。

# Webサイトの作成

続いてJavaで出来ることとして、Webサイトの作成があります。
Javaの役割としては、サーバー側のプログラム処理に利用されます。
他の言語である「Ruby」「PHP」「Python」でも処理することは可能ですが、Javaの方が処理速度が速いといった特徴もある為、Webサイトの作成ではJavaが使用されていることが多いです。
ECサイトや旅行予約サイト、掲示板、SNSといったなんでも作ることができ、有名なところだと、楽天の裏側にJavaが使われています。

# Webサービス

Javaはインターネットと相性が良く、私たちの想像できるWebサービスは大体Javaを使えば作れます。
有名なところだと、TwitterがJavaを利用しており、Twitterに限らずチケットの予約サイトなどのWebサービスでJavaが使用されています。

# システムの開発

システム開発するうえで、Javaはとても安定性に優れた言語で、セキュリティ性も高いシステムになっています。
Javaによって、みずほ銀行や三菱UFJ銀行などの銀行システムが開発されており、その他クレジットカードシステムのほか、金融機関のシステム開発にも用いられています。

# 組み込みシステムの開発

Javaは元々は家電などに組み込まれ、動作するため、ハードウエアに依存しないプログラムとして開発されました。
ハードウェアに依存しないJavaを使用したシステムに出来ることとして、家電だけでなく携帯電話やブルーレイディスクプレーヤーなどを稼働させるためのシステムを構築させることができます。

# 最後に

こう振り返ると、かなり多くの範囲をカバーしていると感じました。Javaを習得することで、様々な業務に活かすことができそうです。
では。
MySQLで大文字小文字区別せず重複しないようにデータを保存する

## やりたかったこと

case insensitiveの (最後に`_ci`がつく) Collation(照合順序)を選択し、UNIQUE制約を貼ったときに、本当に重複しないかを試してみました。

## Character setとCollationについて

他の記事で詳しく説明されているので今回は割愛します。

https://qiita.com/tfunato/items/e48ad0a37b8244a788f6

https://qiita.com/kazu56/items/6af85ffcf8d3954455ad

utf8mb4_general_ciなど、最後が`_ci`となっているものは、大文字小文字を区別しないため、'example' = 'EXAMPLE'と判定されます。

## 実験

DockerでMySQLを立ち上げ、複数の照合順序のテーブルを作り、重複しないかデータを投入してみます。

### MySQL 5.7のDocker準備

各種ファイルを作っておきます。

```yml:docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: test
      MYSQL_USER: user1
      MYSQL_PASSWORD: password
    ports:
      - 3306:3306
    volumes:
      - ./db/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./db/init:/docker-entrypoint-initdb.d
      - ./db/data:/var/lib/mysql
```

デフォルトのCharacter SetとCollationを定義。

```conf:./db/my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci

[client]
default-character-set=utf8mb4
```

collationの異なる3つのテーブルを作成します。

```sql:./db/init/init.sql
DROP TABLE IF EXISTS `utf8mb4_bin`;
CREATE TABLE `utf8mb4_bin` (
  `id` INT(11) AUTO_INCREMENT,
  `email` VARCHAR(255),
  PRIMARY KEY (`Id`),
  UNIQUE `idx_email` (`email`)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

DROP TAble IF EXISTS `utf8mb4_general_ci`;
CREATE TABLE `utf8mb4_general_ci` (
  `id` INT(11) AUTO_INCREMENT,
  `email` VARCHAR(255),
  PRIMARY KEY (`Id`),
  UNIQUE `idx_email` (`email`)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

DROP TABLE IF EXISTS `utf8mb4_unicode_ci`;
CREATE TABLE `utf8mb4_unicode_ci` (
  `id` INT(11) AUTO_INCREMENT,
  `email` VARCHAR(255),
  PRIMARY KEY (`Id`),
  UNIQUE `idx_email` (`email`)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```

`docker-compose up`をするとMySQLが立ち上がります。

### データを投入してみる

MySQLが立ち上がったら接続し、それぞれのテーブルにメールアドレスを入れていきます。

```sql
INSERT INTO utf8mb4_bin (email) VALUES ('sample@example.com');
INSERT INTO utf8mb4_general_ci (email) VALUES ('sample@example.com');
INSERT INTO utf8mb4_unicode_ci (email) VALUES ('sample@example.com');
```

次に重複判定されるかテストしてみると、utf8mb4_binのテーブル以外は重複判定されました。

```sql
INSERT INTO utf8mb4_bin (email) VALUES ('SAMPLE@example.com');

INSERT INTO utf8mb4_general_ci (email) VALUES ('SAMPLE@example.com');
  -- Duplicate entry 'SAMPLE@example.com' for key 'idx_email'

INSERT INTO utf8mb4_unicode_ci (email) VALUES ('SAMPLE@example.com');
  -- Duplicate entry 'SAMPLE@example.com' for key 'idx_email'
```

insertではなく、updateのタイミングでも重複判定されました。

```sql
INSERT INTO utf8mb4_general_ci (email) VALUES ('hoge@example.com');
UPDATE utf8mb4_general_ci SET email = 'SAMPLE@example.com' WHERE email = 'hoge@example.com';
  -- Duplicate entry 'SAMPLE@example.com' for key 'idx_email'
```

最後にalter tableでも重複判定してくれました。

```sql
ALTER TABLE utf8mb4_bin MODIFY email VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
  -- Duplicate entry 'SAMPLE@example.com' for key 'idx_email'
```

## おわりに

collationはあまり意識せずデフォルト値のままだと大文字小文字区別してくれないので、逆に区別したいときは注意が必要です。
普段あまり意識せずに使ってきていたので、色々実験してみて理解が深まりました。
Linux ubuntu20.04 インストール 忘備録

##インストーラの言語の選択
|選択|
|----|----|----|
|今回は「English」|


##Keyboard configuration キーボードレイアウト
|項目|選択|
|----|----|----|
|Layout|japanese||
|Variant|japanese||

##Network connections  ネットワークインターフェイス
###ネットワークインターフェイス
> ネットワーク機能を利用するために必要な通信装置や、オペレーティングシステム（OS）上での装置の利用設定、装置の機能

* 利用するPCに搭載された優先LANポートや無線LANポートが一覧で表示される。
* NAME(=ネットワークポート名)接続したPCの環境によって変化する
* 未接続の場合は「not connected」,接続状態の際はDHCPV4欄にIPアドレスが表示される。
* Wifi接続する場合は「wl*」のネットワークポート>「EditWiFi」>「choose*network」でネットワークを選択し、パスワードを入力して接続する。

###DHCPとは
> DHCPとは「Dynamic Host Configuration Protocol」の略で、 IPv4ネットワークにおいて
(中略)
各種設定に必要な情報を入手して、<b>自動的に設定<b>を行えるようになります。 
https://www.nic.ad.jp/ja/basics/terms/dhcp.html

##Configure proxy /Proxyサーバー設定
|項目|選択|
|----|----|----|
|Proxy address|今回は変更なし(=空欄のまま)||

##Configure Ubuntu archive mirror /updateやinstallを行う際のサイトを指定
> ソフトのupdateやinstallを行う際にダウンロードするサイトを指定します。基本的には近いサイトが自動で選択されますので変更する必要はありません。「Done」を選択してEnterキーを押下します。
https://server-network-note.net/2021/01/ubuntu-20-04-lts-server-install/

|項目|選択|
|----|----|----|
|Mirror address|今回は変更なし(=デフォルトのまま)||

##Guided storage configuration 
|項目|選択|
|----|----|----|
|Use an entire disk|今回はこちらを選択||
|Set up this disk as an LMV group|今回はこちらを選択||
|Encrpt the LVM group with LUKS|非選択||

###Use an entire disk
|項目|説明|
|----|----|----|
|entire |全体||

###md126  imsm RAID 0
|項目|説明|
|----|----|----|
|md|Mdadm：md (multiple device) administers or manages||
|126|||
|imsm|Intel Intel Matrix Storage Manager は、RAIDシステム（以下、ディスクアレイ）を管理するユーティリティ||
|RAID 0|複数のHDD,SSHにデータを分散して書き込む方式。<br>RAIDは、RAID0～RAID6まである。|

###partition 1 existing,already formatted as ntfs not mounted
|項目|説明|
|----|----|----|
|partition|HDDやSSDその他メモリスティックなどにもうけることが出来る「しきり」<br>https://eng-entrance.com/linux-partition||
|ntfs |「NT File System」の略<br>https://wa3.i-3-i.info/word13131.html|

###Set up this disk as an LVM group
|項目|説明||
|----|----|----|
|LVM|LVM（logical volume manager）とは、複数のハードディスクやパーティションにまたがった記憶領域をひとつのボリュームグループにまとめ、単一の論理ボリューム（LV）として扱うことのできるディスク管理機能<br>主にLinuxをはじめとしたUNIX系のOSで利用できる機能の1つ。<br>https://www.idcf.jp/words/lvm.html|

###Encrpt the LVM group with LUKS
|項目|説明|
|----|----|----|
|Encrpt |暗号化||
|LUKS|（Linux Unified Key Setup. ラックス）とは、Linuxに実装するためにClemens Fruhwirthにより作られたディスク暗号化の仕様。<br>https://ja.wikipedia.org/wiki/LUKS||

##Strage configuration
>ストレージの設定の確認画面になります。設定を確認したら「Done」を選択してEnterキーを押下して下さい。
https://server-network-note.net/2021/01/ubuntu-20-04-lts-server-install/

|英文|日本語訳|選択|
|----|----|----|
|<b>Confirm destractive action.</b><br>Selecting continue below will begin the disks selected to be formatted.<br>You will not be able to return to this or a previous screen once the installation has started.<br>Are you sure you want to continue?|破壊的なアクションを確認します。以下で続行を選択すると、フォーマット対象として選択されたディスクが開始されます。インストールが開始されると、この画面または前の画面に戻ることはできません。続行してもよろしいですか？|Continue|

参考

https://www.yokoweb.net/2020/05/04/ubuntu-20_04-lts-server-install/

https://ubuntu.com/server/docs/install/storage
Vue3へ移行に合わせてこう動く

# 以下環境が整い次第、マルっと移行したいところ
- Vue3
- TypeScript
- Vite (ヴィータ)
- Nuxt3
- Vuetify3

---

# タイミング
- 後述するが、Vuetify3が最後(2021/3Q)にリリースされそう
    - そのタイミングに合わせてマルっと。

---

# Vue3
- 元Google社員の[ Evan You ]が作ったjavascript framework
    - https://v3.ja.vuejs.org/
- Vueのメジャーバージョンアップ
- compositionAPIが標準装備される
    - script書くエリアがかなり整頓されるイメージ
    - [composition api is なに？](https://v3.ja.vuejs.org/guide/composition-api-introduction.html#setup-%E3%82%B3%E3%83%B3%E3%83%9B%E3%82%9A%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%82%AA%E3%83%95%E3%82%9A%E3%82%B7%E3%83%A7%E3%83%B3)

---

# TypeScript
- MicroSoftが開発したJavaScript進化版
    - https://www.typescriptlang.org/
- Googleの社内標準言語として採用されてる
- TypeScriptはあらかじめ型を定義する静的型付けでバグなくす

---

# Vite (ヴィータ)
- compileの爆速化
    - https://zenn.dev/konnyaku256/scraps/6e8f78642cde2c
- ちなみに作者はVue作者の [ Evan You ]
- compileまじで早いです

---

# Nuxt3
- 2021/2Qにベータ版
    - https://nishimura.club/nuxtjs-v3-roadmap-and-information-organization
- VueFrameworkで大人気のやつ
- ある程度規約があるので、コードが共通認識されやすい

---

# Vuetify3
- 2021/3Qにリリース目標らしい
    - https://vuetifyjs.com/ja/introduction/roadmap/#v3-0-titan
- compositionAPI対応されたcomponent
- 従来通り、楽に綺麗なデザインできる
自称「通販プラットフォーマー」が教えるEC通販サイトオンボーディング①

この記事は何回かにわたって投稿します。
自称「通販プラットフォーマー」を自負する筆者が、これまでやってきた経験からECで通販やるなら
どんなことを知らないといけないのか、を説明していきます。

（この記事は5分で読めます。）

##こんな人に読んでほしい
* 通販サイトを作ってくれ！といわれた
* 通販サイトは使っていても、作ったことはない…
* バックグラウンドも通販分野に携わったことがない

ECを作る分野は経験があっても、モノをアツカウことには未経験という方向けのセクションです。

## 自称通販プラットフォーマーの経歴
* DMMのエンドユーザー向け通販事業部に4年所属　→　内部のシステム構造を嫌というほど知る
* DMMの法人向け通販事業に2年所属　→　はじめて0から通販システムを設計、リリース

過去のバックグラウンドもあって、要件からリリースまでは **1年** でローンチしました。
（これは知ってる人ならなかなかえぐいスピード感です。）

それ以外にも日常的に、

* 商品の入庫出庫データの管理
* 物流側との保守管理
* 新規倉庫とのつなぎこみ
* ECサイトの改善企画

などをやっております。そんな経歴を含めて、通販プラットフォームってほんと奥深いという気づきから、似たようなエンジニアの方に向けて、ノウハウを共有したく、記事を書き始めています。


## 何はともあれ、通販システムってなんだ
まずは、一般的な通販システムはどういう構成でつながっているかを俯瞰的に説明です。
通常のエンドユーザー⇔買い物ができるサイト　から踏み込んで何を作らないといけないか？の全体像です。

はい、こんな感じ。
![Piita用全体像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1706758/f87f33e1-5079-d60a-f962-3b38662c8323.png)

エンドユーザーが見る世界から、**通販では階層に3ステークホルダーが関わっていること** が基本構造です！
そのため、EC側はエンドユーザーとの接点以外に、

* 仕入れ会社とのシステム連携
* 物流倉庫とのシステム連携
* 配送業者とのシステム連携

を配慮する必要があります。
C2Cの場合には、仕入れ会社と物流倉庫が「enduser」になるという感じ。概念は同じです。


## めっちゃ時間がかかる工程はどこ？
はっきりいって、EndUserとECサイトは割と簡単です。
一番時間がかかるのは、**受注在庫管理を行うシステム（図だと上部の右側）**　です。
ここのセクションは工期の半分を使うといっても過言ではないです。

## プラットフォーマーとして意識したいこと
EndUserがよりサービスを使いやすくするのは当たり前の世界。
でも、通販プラットフォームはそれ以上に、**各ステークホルダーとの連携をいかに早く・ランニングコストをかけずに運用**できるようにしておくか、を最初の設計から考えておくことをおススメします。

図でいうと、★のところを最初の段階から自動化しておくこと。です。

![Piita用全体像 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1706758/4b646d84-9e1d-6eee-3aa4-efd83df2e9f8.png)

##自動化とかあったりまえじゃん…
はい、そのとおりです。

でも、なぜここが時間がかかるかというと、とにかく仕入れ会社や物流倉庫のクライアント側は割と老舗的なシステムを使っていることが多い！という状況です。
（APIに対応している、とかもわりと稀）
この**連携先とのデータ連携I/Fの仕様の読み解きがかなり難儀**　というのが私の経験則になります。

当然、仕入れ業者が複数、倉庫が複数になればそれだけの読み解きと実装コストが上乗せされていくことになります。

そして、重要なことは自動化できるのはデータのみ。
実際には**各ステークホルダーごとにオペレーション**があること。
これを理解しないと、システムだけできても全く機能されないものを世に放ってしまうことになります。

## もやもやさせといて今回はここまで！
（つらいところだけを伝えて、もやもやさせてしまいましたが）
今回は、まず通販プラットフォームの全体像とどの工程が大変なシーンか、という点のみお届けしました。

次回からは、**「倉庫オペレーション」**にどんなものがあるのか？
業界用語がなかなか難しいので簡単に解説したいと思います。
Active Storageとdeviseでログインしてない場合は、画像を見れなくする

Active Storageを使っていて、ログインしていなくても、画像のURLにアクセスすると画像が表示されてしまっていたので、下記のようにソースを加えることで対処しました。

ActiveStorage::BaseControllerにdeviseログインの認証メソッドを追加

```ruby:app/models/concerns/active_storage_base_controller_extension.rb
module ActiveStorageBaseControllerExtension
  extend ActiveSupport::Concern

  included do
    before_action :authenticate_user!
  end
end
```

追加したモジュールを読み込ませる。

```ruby:config/initializers/to_prepare.rb
Rails.configuration.to_prepare do
  ActiveStorage::BaseController.include ActiveStorageBaseControllerExtension
end
```
[Next.js] 最速でNext.jsを動かす

# 注意
現在はNext13がリリースされており、構造が12までと異なります。
詳しくは公式ドキュメントを参照お願いします。

# 最速でNext.jsを動かす
基本は[Nextチュートリアル公式](https://nextjs.org/learn/basics/create-nextjs-app/setup)を圧縮して書いています。
　
[Node公式サイト](https://nodejs.org/ja/)からNode.jsを端末にインストールする
Node.js 10.13 or 最新バージョン

```
$ npx create-next-app
? What is your project named? › next-app

$ cd next-app
$ npm run dev
```
※プロジェクト名は任意の名称に
サーバーを立ち上げたら http://localhost:3000/ にアクセス

## 編集してみよう
`pages/index.js`開いて`<h1>`内を`Hello Next.js!`と編集
保存するとリアルタイムにタイトルが変更される
ここまででNext.jsのアプリが動かせる

# ページルーティング
## まずリンクをつける方法
モジュールを利用したいコンポーネントファイルに読み込み

```js
import Link from 'next/link';
```

```js
<Link href="/posts/first-post">
    <a>Link</a>
</Link>
```
ここで開発ツールで見ると<br>
`<a href="/posts/first-post">Link</a>`で書き出されている

#### Linkの中にaタグを入れる理由
- `<Link href="">`: クライアントサイドで遷移させるため
- `<a>`: SEO対策 aタグだとBotに理解してもらうため(hrefは不要)

[Next.js ではなぜ Link の中にaを入れる？なぜhrefをLinkに付ける？？](https://zenn.dev/luvmini511/articles/b5e9f02cadd160)

## ページ追加
`/pages/posts/first-post.js`追加

```js
import Link from 'next/link';

const FirstPost = () => {
  return (
    <>
        <h1>First Post</h1>
        <h2>
            <Link href="/">
            <a>Back to home</a>
            </Link>
        </h2>
    </>
  );
}

export default FirstPost;
```

#### React.Fragmentタグについて

```js
return (
    <> {/* <React.Fragment>...</React.Fragment> */}
        React.Fragmentの省略形
        return内では必ず1個のタグでラップしなければならずdivでくくると
        構造上余計セレクタが含まれてしまうため
        HTMLには反映されないタグが用意されている
    </>
);
```
TypeScript NodeJS websocket client

# install
```console
npm i websocket @types/websocket
```

# usage
## 共通化
```typescript
const websocket = <T>(url: string, onmessage: (t: T) => void, onerror?: (e: any) => void, onclose?: () => void) => {
    const webClient = require("websocket").client
    const client: client = new webClient()
    client.on('connect', (con: connection) => {
        console.log(`connected ${con.connected}`)
        con.on('error', (e: any) => console.error(e))
        con.on('close', () => console.log("websockets closed."))
        con.on('message', (message: Message) => {
            if (message.type === "utf8") {
                const t = JSON.parse(message.utf8Data) as T
                onmessage(t)
            }
        })
        if (onerror) {
            con.on('error', onerror)
        }
        if (onclose) {
            con.on('close', onclose)
        }
    })
    client.connect(url)
}
```

## 利用例
この例では、仮想通貨取引所binanceへbtcusdt, xrpusdtの約定データをサブスクライブしている。

```typescript
interface AggTrade {
    e: string
    E: number
    a: number
    s: string
    p: string
    q: string
    f: number
    l: number
    T: number
    m: boolean
}

function test(){
    websocket<AggTrade>("wss://fstream.binance.com/ws/" + "btcusdt@aggTrade", t => console.log(`Pare:${t.s}`))
    websocket<AggTrade>("wss://fstream.binance.com/ws/" + "xrpusdt@aggTrade", t => console.log(`Pare:${t.s}`))
    return
}
test()
```

## 実行結果
```console
Pare:BTCUSDT
Pare:BTCUSDT
Pare:BTCUSDT
Pare:XRPUSDT
Pare:BTCUSDT
Pare:BTCUSDT
Pare:BTCUSDT
Pare:BTCUSDT
Pare:BTCUSDT
Pare:XRPUSDT
Pare:XRPUSDT
Pare:XRPUSDT
Pare:BTCUSDT

```

# Document
https://github.com/theturtle32/WebSocket-Node
remix-run / react-router の5.3 releaseに伴う変更点


# remix-run/react-routerのversion5.3(from version 5.2)におけるコードの変更点

[remix-run/react-router](https://github.com/remix-run/react-router/releases/tag/v5.3.0)をversion5.2 から version5.3 での変更する箇所。ネクストversionでの対応した方がいい箇所のまとめ。

## Breaking Change

none...(まぁ、Minor Changeやし)

## Suggest Change

1. activeClassName, activeClassNameをBC予定になるので、5.3に変更するタイミングであげておきませう。
1. [Element.ariaCurrent](https://developer.mozilla.org/en-US/docs/Web/API/Element/ariaCurrent)でfalse対応ができるようになりました。


## 1. activeClassName, activeClassNameをBC予定になるので、5.3に変更するタイミングであげておきませう。

`className` props が定義された関係でそっちを利用するように徐々に移行しましょう。
6.Xのリリースタイミングでremoveされるので対応を実施。([file](https://github.com/remix-run/react-router/blob/7a891467987b164b64f39eaf72415b609ed2d4a7/packages/react-router-dom/modules/NavLink.js#L29))

```nav-ink-changed.jsx
// Good
function Comp() {
  return (
    <NavLink
      to="/"
      className={isActive =>
        `px-3 py-2 ${isActive ? 'text-gray-200' : 'text-gray-800'}`
      }
    >
      Home
    </NavLink>
  );
}

// Not Good activeStyle will duplicate
<NavLink
  to="/faq"
  activeStyle={{
    fontWeight: "bold",
    color: "red"
  }}
>
  FAQs
</NavLink>

// Not Good activeClassName will duplicate
<NavLink to="/faq" activeClassName="selected">
  FAQs
</NavLink>


```

## 2. [Element.ariaCurrent](https://developer.mozilla.org/en-US/docs/Web/API/Element/ariaCurrent)でfalse対応ができるようになりました。

```nav-ink-changed.jsx
<NavLink aria-current="false"></NavLink>
```

他の変更箇所については、Projectのコード変更外のため明記をさけます。(ざっくりと)

- travis.ymlの脱却 -> github actionsへ
- babel関係のファイルのアップデート
- .github/XXXのファイルの命名規則
- useContextを利用したSample Codeに変更
- ReadMe群のアップデート(ちょっと読みやくなった)
- publish script の変更
- Sample Codeでの命名規則の変更(key, contextという変数名ではなくpathname, XXXContextに変更)
【個人開発】あるあるネタを言いたかったのであるあるネタを共有・投票できるアプリを作りました。

## はじめに

「これあるあるだわ〜しかも結構面白いからみんなに共有したいなー」

って思ったことありませんか？

ありますよね？

あると思います。

ということで今回、あるあるネタを共有・投票できるアプリをリリースしました！

アプリURL：[~~https://aruaruneta.work/~~](https://aruaruneta.work/)
※現在停止しています。

## サービス概要
日常で起きたあるあるネタを投稿し、一人何回でも投票できるアプリケーションです。

[![Image from Gyazo](https://i.gyazo.com/17cfdfa2ca3405a036e5f2a2466ef689.png)](https://gyazo.com/17cfdfa2ca3405a036e5f2a2466ef689)

一人で何回でも投票できるため、自分の投稿を意図的に上の方に持ってくることも可能です。  
複数回投票できることで承認欲求も満たせるかと思います。

[![Image from Gyazo](https://i.gyazo.com/e0ac9b09ea3097870d0e02ac53f3c2ab.gif)](https://gyazo.com/e0ac9b09ea3097870d0e02ac53f3c2ab)

Twitter共有もできるので、ぜひオススメのあるあるネタをたくさん共有してみてください！

[![Image from Gyazo](https://i.gyazo.com/7470970d58a8790fd81d8b47c9129973.gif)](https://gyazo.com/7470970d58a8790fd81d8b47c9129973)

## 使用技術
### バックエンド
- Ruby 2.7.2
- Rails 6.0.4.1
- RSpec 5.0.2
- RuboCop 1.20.0
- JWT 2.2.3

### フロントエンド
- Vue 2.6.14
- VueRouter 3.5.2
- Vuex 3.6.2
- Vuetify 2.5.8
- VeeValidate 3.4.12
- axios 0.21.1
- ESLint 0.4.3

### インフラ
- Nginx
- Puma
- AWS
  - VPC
  - EC2
     - Amazon Linux 2
  - Route53
  - RDS
     - MySQL 
  - ALB
  - ACM
- Capistrano 

## インフラ構成図

[![Image from Gyazo](https://i.gyazo.com/ec88a52791e2d24582cba78371ccf436.png)](https://gyazo.com/ec88a52791e2d24582cba78371ccf436)

## 最後に
Vue.jsを使ってアプリを作ったのは初めてだったので、いろいろとわからないこともありましたが楽しく作れました。

やはり初学者にとって日本語のドキュメントがあるのは助かりますね笑

最後まで読んでいただきありがとうございました！

前回作ったアプリについての記事も見てくれたら嬉しいです↓

[【個人開発】家の中にときどき出る不快な虫を検索するサービス「むしめがね」をリリースしました。](https://qiita.com/kimorisan/items/84997591c7c2c897da18)
WordPressでpluginがactiveか調べる方法

#方法は二種類ある
1. [wp-adminからplugin.phpをrequireする。](#wp-adminからplugin.phpをrequireする。)
2. [get_optionを使用する。](#get_optionを使用する。)

class_existsで判断する方法もあるけど正確性に欠けると思うので排除

##wp-adminからplugin.phpをrequireする。
よく紹介されている方法、「Wordpressでpluginがactiveか調べる方法」とかで調べると大体出てくる。

    require_once ABSPATH . '/wp-admin/includes/plugin.php';
    $result = is_plugin_active('wordpress-importer/wordpress-importer.php');
    //$resultにtrueかfalseが入るからif文で条件分けする。

wp-adminからファイルをrequireすることに気持ち悪さと抵抗を感じてる…

##get_option( 'active_plugins' )を使用する
「Wordpressでpluginがactiveか調べる方法」とかで調べると出てこない？あるかもしれないけど見逃してるだけかも

    //配列で現在activeなpluginの配列が返ってくる。
    $plugins = get_option( 'active_plugins' );

    //in_arrayとかでpluginがあるか判定
    if(in_array('wordpress-importer/wordpress-importer.php', $plugins)){
    　echo 'WordPress インポートツールは有効です';
    }else{
      echo 'WordPress インポートツールは有効ではありません';
    }
get_optionの引数リストがあったので色々できそう
[options一覧](https://codex.wordpress.org/Option_Reference)

###まとめ
2の方がきれいな感じがする
忘れないようにメモ
vue-chartjsで export 'default' xxx was not found in 'chart.js' エラーが出るとき

[vue-chartjs公式](https://vue-chartjs.org/ja/guide/)を参考に導入してみたら、以下のエラーが出てしまった。

```
export 'default' xxx was not found in 'chart.js'
```

## 原因
chart.jsの最新バージョン（3.x系）にvue-chartjsが対応していなかった。

以下のように素直にインストールするとchart.jsは3.x系がインストールされるので、ダウングレードする必要がある。

```
yarn add vue-chartjs chart.js
```

## 対応
2.x系の最終版はv2.9.4らしいので、そちらを導入

```
yarn remove chart.js 
yarn add chart.js@2.9.4
```

エラー解消し、無事チャートが描画された

## 参考
https://github.com/chartjs/Chart.js/releases/tag/v2.9.4

https://stackoverflow.com/questions/66940954/why-does-nuxt-give-me-this-error-with-vue-chartjs
2FA設定したAppleアカウントのアプリダウンロード情報をAppAnnieに自動連携する設定

## 何が課題だったのか？

自社でiOS/Android向けのアプリをリリースしており、ストアのダウンロード情報をAppAnnieに連携してKPI情報として使っている。

最近定期的にAppAnnie→AppStoreConnectの認証をしなくてはならず非常に面倒になった。２FA(two factor authentication)を有効にしたAppleアカウントで使える新しい認証方法がAppAnnieより発表されたので、そちらを使おうとしたらだいぶハマったので、備忘録。

## フロー

- [こちら](https://appleid.apple.com/)より、App用パスワードを生成しておく。名前は `AppAnnie` 等わかりやすいものにしておく。
- [こちら](https://help.apple.com/itc/contentreporterguide/?lang=en#/apd2f1f1cfa3) を参考に、Reporter.jar をダウンロードする
- 生成したApp用パスワードと Reporter.jar を使ってアクセストークンを発行

```
$ java -jar Reporter.jar p=Reporter.properties Sales.generateToken

Please enter your username:
Please enter your password:
If you generate a new access token, your existing token will be deleted. You will need to save your new access token within your properties file. Do you still want to continue? (y/n): y
Your new access token has been generated.
AccessToken: (非表示)
Expiration Date: (非表示)
```

- AppAnnieのアカウント一覧より、接続に問題があるAppleアカウントの「Update Credentials」をクリック
- 生成したアクセストークンを入力
- 表示されたAppAnnieのメールアドレス(例: `***@appannie.com`)をAppStoreConnectに招待する。なお、Financeの権限を必ずつける（[こちら](https://helpcenter.appannie.com/community/s/article/How-can-I-update-Apple-App-Store-connections-when-2FA-is-enabled)を参考)


以上で、招待を送ってしばらくするとコネクションが復旧されるとのこと。現在様子見。

アクセストークンを生成するところで、AppStoreConnectからはどうやってもアクセストークンが発行できず(最高権限のAdminアカウントで見ても表示されず)、Javaのツールを使うことで解決できることに気づくまでハマりました。
【雑談／小ネタ】多言語対応では、数字に気を付けよう


# 数字と多言語対応

データベースやローカルファイルを扱うとき、状況によっては**多言語対応**が要求されます。

全世界向けと名打って、最初から複数のチームで製品開発しようというときには、恐らく勝手に意識することが多いと思うんですけど、

あまり規模の大きくないチームで、海外の特定の国の顧客と交渉していて、
かつ開発チームに日本人が多くて英語くらいしか日常的に使えないよ～という状況だとして、

**じゃあ今回のプロジェクト(アプリも英語で統一して)上手くいったし、別の顧客にも声かけて販売を検討してみようかな**

という軽いノリで商談して開発していたりすると、つい**「数字の記法間違えてる！！！！」**ということに気づかず、謎の不具合調査に1~2日かけてしまうことも普通にあります(*なお、私の個人的な経験の例です*)。

文字表記のブレやエンコードくらいなら、まあ何とか気づくのは早いんですが、数字の場合は意外と気づかないような気がします。

# 割と有名な例(CSVファイル)

日本国内だけでなく、米国、英国、豪州などの英語圏、中国、韓国、インドなどのアジア圏に向けての場合、数字を使ったCSVファイル(カンマ区切り)はこう書くことが多いと思うんです。

```csvs
100.0, 200.0, 50.1, 19.88
```

ところが、特にフランス語圏、ドイツ語圏、スペイン語圏に行くと数字の表現は**「ピリオド」**ではなく**「カンマ」**です。

EUが多い・・・と思いきや、南米や中東もヨーロッパの言語に影響を受けていることもあって、こうした国でも注意が必要です。

https://coliss.com/articles/build-websites/operation/writing/53.html

こうした言語圏でのCSVフォーマットは次のようになります。

```csvs
100,0; 200,0; 50,1; 19,88
```

**しかし例えばスイスでは、ドイツ語とフランス語が主要言語にもかかわらず、小数点は「.」(ピリオド)で表現されるみたいです。**
従って、国の文化によってこの辺りのルールをきちんと考えてやる必要があります。

さらに、経理関係の話をするときにも注意が必要で、

**フランス語圏では、数字を333 333,11といった感じで表現されますし、
ドイツ語圏では、数字を333.333,11といった感じで表現します。**

こうした影響は、例えばWindowsを使っていれば、
Windows OSのカルチャー設定の部分と直接関係してくる部分なので注意が必要です。

従って、**「英語は共通語だからどこでも通じるだろう」**と、
うっかり英語圏のルールで開発をしていると思わぬ見落としがある場合もあります。
（プログラミングは、英語を基準に行なわれるのが標準だと思うので、見落としがちです）

# まとめ

多言語対応を行なう場合、工数があまり割けないと「とりあえず英語で」とやりがちですが、
その場合には、国固有のカルチャールールに気を付けましょう。

その中でも、特に「数字」に関しては結構見落としやすいので、テストコードなども含めて注意深く検討すると良いです。
場合によっては、言語によって「保存されるデータの内容」が変わる可能性があるので、言語依存性をサポートしないフォーマットに対しては特に意識を払う必要があります。
mayaがエラー・ワーニングを吐く時の対処 6 ~どこから来たのかdataStructure~

モデルを2つ以上importした際に出てくるワーニング

    // Warning: file: D:/hoge.ma line 257023: Structure 'mapManager_stoneFloor' is already defined. Using the original rather than creating a copy. // 

なんぞこれ？しかもいっぱい出てくるから鬱陶しい。

調べてみる
-

https://knowledge.autodesk.com/ja/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2020/JPN/Maya-Basics/files/GUID-688D724C-F0D9-4649-BDD4-86E2447CFA05-htm.html

https://help.autodesk.com/cloudhelp/2019/JPN/Maya-Tech-Docs/CommandsPython/dataStructure.html

なるほどよくわからん。

とりあえず
　- ノード以外で持てるデータ構造
　- 一度定義すると、データ構造は編集できない

というものであり、
その為データをimportした際
既にシーン内に同名のdataStructureが存在すると
定義済みのdataStructureを再定義しようとすることになるので
先述のようなワーニングが出るという流れかしら。

unknownプラグインほど拡散はしにくいが、
ベースモデルなど使いまわす物に混入していると拡散しやすい。

そもそも、どこからきた？
-
自セクションでは使用しないが、何かしら必須な物かもしれない。
問い合わせてみたところ
**心当たりがない**
との事。

可能性として考えられるのは・・・
 - なにかのプラグインを使用した副産物
 - 別のソフトウェアとデータを行き来した際にくっついてきた

なんだけれども、ソフトをまたぐ調査は一旦断念。
**※この件についてご存じの方が居たらぜひ教えて頂きたい。**

除去
-

存在するかどうかの確認

    import maya.cmds as cmds
    dataStructure_list = cmds.dataStructure(query=True)
    if len(dataStructure_list) != 0:
        print("exists dataStructure!!!")

コマンドでの除去

    import maya.cmds as cmds
    cmds.dataStructure( removeAll=True )

除去した上で、諸々データ上問題が無い事を確認。


どこから入ってきたのか・・・
想像の域は出ないけれどもここ数年で見かけるようになったので、
マーベラスデザイナー/サブスタンスデザイナー・ペインター
あたりのような気もするけれども、調べる元気は今のところ出ないので保留中
**※重ねて、この件についてご存じの方が居たらぜひ教えて頂きたい。**
1分で、分かるよ。貴方が！jqコマンドを！

> 仕事で良くできているシェルシステムをいじる機会がありますが、シェルでJSON形式を操作する必要がありました。シェルは条件分を作成するさえややこしくて、シェル主力ではない場合はかなり生産性が低くなります。それでjqコマンドみたいなutilコマンドは大変助かります。今回はjqコマンドを触った感触と例を紹介していきたいと思います。

#環境
※ macでbashが使いたい方は、「[1分で、macのシェル種類を切り替え](https://qiita.com/modagi/items/4a0dac254cce41e9b1ab)」へ

- シェルはbash 
- macOS Big Sur 11.3.1


#実施
### 1. jqコマンドが使える状態か確認

```bash
jq --version
``` 
なかったら、インストールしましょう

### 2. jqコマンドUtilをインストール
Macなので今回はbrewでインストールします。

```bash
brew install jq
``` 

linuxでしたらこうやって

```
apt-get install jq # Debian or Ubuntu
```

windowsならchocolatetyやバイナリーのようですね。

[公式HPはこちら](https://stedolan.github.io/jq/download/)　

### 3. jqを使ってみる

基本形は下記になります。'.'のarg項目は「identify filter」と呼ばれます。

``` bash
jq '.'
{"open": "tone"}

> {
>  "open": "tone"
> }

```
このようにJSONの形式になります。
jqの役割はjsonのデータをINPUTにして
json形式がOUTPUTとなります。つまり、jsonパーサーなんです。

### 4. jqをパイプラインで使ってみる
パイプライン(　|　)をつけて使うとより効果的になります。
つまり、filterと飛ばれた　'.'にjsonの「key」をつけて「value」だけを取得できます。

```bash
echo '{"foo": "bar", "hoge": "piyo"}' | jq '.foo'

> "bar"
```

### 5. JSONファイルからパーシング
読み込むjsonファイルパスは第２引数として指定できます。
これでファイルからのパーシングもOKです。

```bash
echo '{"foo": "bar"}' > foobar.json
jq '.' foobar.json

> {
>   "foo": "bar"
> }
```


#結論
シェルプログラミングは強力ですが、どうしても生産性が低くなる傾向があります。
その時に、迷わずにjqコマンドようなUtilを使った方が一般的には断然にいいと思います。
他にもいいUtilがありましたら習いたいと思います。

#レファレンス
https://stedolan.github.io/jq/manual/
【Python】ccxtライブラリでFTXから板情報を取得してLineに通知してみた

#はじめに
今回はPythonのccxtという複数の仮想通貨取引所のAPI操作が集約されたライブラリを用いて、海外仮想通貨取引所のFTXから板情報を取得して、自分のLineに通知する方法を紹介します。

#環境
Python3.9

#手順
1.Pythonのインストール
Pythonのインストール方法は省きます。検索頂ければ直ぐに見つかるかと思います。

2.ccxtライブラリのインストール
特に他のライブラリのインストールと変わりないですが、過去に記事を書いたので以下でご確認頂ければと思います。

https://qiita.com/hirockio2206/items/a3d9fe32fed8d1c9b83e

#プログラム

```ccxd.py
import ccxt#←CCXTライブラリを呼び出します。変更不要です。

def ftx(): #←CCXTを呼び出します。変更不要です。
   
   ftx = ccxt.ftx({
       })
   return ftx

value = ftx().fetchOrderBook('BTC/USD')　#←板情報の入手です。今回は'BTC/USD'を確認します。
#'BTC/USD'の値を変えれば他の仮想通貨の板情報を確認できます。

value['asks'][0][0]#←板情報(asks)の一番上の値を取得するコマンドです。変更不要です。

asks =int(value['asks'][0][0])#←取得した値をint型に変換しています。これをしないとlineに通知できません。変更不要です。
asks_comma= "{:,}".format(asks)#←値にカンマを入れています。この方が見やすいと思いまして。変更不要です。

#↓Lineに通知する箇所です。line_notify_tokenだけご自身で発行をお願いします。それ以外は変更不要です。
import requests
from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_EVEN
addmessage="\r\n""　現在値:"

line_notify_token = '****************************************'
line_notify_api = 'https://notify-api.line.me/api/notify'
message = addmessage + asks_comma

payload = {'message':"\r\n"+ message}
headers = {'Authorization': 'Bearer ' + line_notify_token}  # 発行したトークン
line_notify = requests.post(line_notify_api, data=payload, headers=headers)
```

#最後に
いかがでしたでしょうか。
これを定期的に通知させることで投資判断をすることも可能かと思います。

私はLineの通知機能をOFFにして、1時間毎にスマホに通知をしています。
今回はask値を通知させましたが、他にもbid値や先物値なども取得できます。
それを計算させた結果をスマホに通知することも可能です。

ご参考になれば幸いです。
サンプル

hoge

```function:関数

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class LogWindowExample {
    private JFrame frame;
    private JTextArea logArea;
    private JButton logButton;

    public LogWindowExample() {
        // フレームの設定
        frame = new JFrame("ログウィンドウ");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);

        // テキストエリアの設定
        logArea = new JTextArea();
        logArea.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(logArea);
        frame.add(scrollPane, BorderLayout.CENTER);

        // ボタンの設定
        logButton = new JButton("ログを追加");
        logButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                addLog("これはログメッセージです");
            }
        });
        frame.add(logButton, BorderLayout.SOUTH);

        // フレームを表示
        frame.setVisible(true);
    }

    // ログをテキストエリアに追加するメソッド
    private void addLog(String message) {
        logArea.append(message + "\n");
    }

    public static void main(String[] args) {
        // EDT (Event Dispatch Thread)でGUIを初期化
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new LogWindowExample();
            }
        });
    }
}


```

```vba:CheckJyoken.vb
Option Explicit

Private chekString01

Private chekString02

Private chekString03

Function getChekString01() As String
    getChekString01 = chekString01
End Function

Sub setChekString01(value As String)
    chekString01 = value
End Sub

Function getChekString02() As String
    getChekString02 = chekString02
End Function

Sub setChekString02(value As String)
    chekString02 = value
End Sub

Function getChekString03() As String
    getChekString03 = chekString03
End Function

Sub setChekString03(value As String)
    chekString03 = value
End Sub
```
チラ裏。if,elseの問題

問題
「ポイント付与サービスを考えます。
購入金額が999円以下の場合、3%のポイント
購入金額が1000円以上の場合、5%のポイント
このように付与されるポイントを出力するメソッドを作りましょう。

ただし誕生日の場合はポイントが5倍になります。
誕生日の場合はtrue, 誕生日でない場合はfalseで表します。
また、小数点以下をすべてのポイント計算が終わったあとに切り捨てましょう。

呼び出し方：
calculate_points(amount, is_birthday)」

step1
購入金額が999円以下なのかまたは1000円以上なのかを判断したいので、条件分岐後ポイント計算をした後に結果を変数pointに代入します。

```ruby:qiita.rb
  if amount <= 999
    point = amount * 0.03
  else
    point = amount * 0.05
  end
```
step2
誕生日の場合は、直前で定義した変数pointに5をかける処理を行います。

```ruby:qiita.rb
  if is_birthday
    point = point * 5
  end
```
step3
小数点以下を切り捨てたポイント数を出力させたいので、ポイント数の記述部分に'.floorメソッド'を使用。

```ruby:qiita.rb
puts "ポイントは#{point.floor}点です"
```
最後に指定された呼び出し方に添って記述し、完了。

```ruby:qiita.rb
def calculate_points(amount, is_birthday)
  if amount <= 999
    point = amount * 0.03
  else
    point = amount * 0.05
  end
  if is_birthday
    point = point * 5
  end
  puts "ポイントは#{point.floor}点です"
end
```

備忘録を兼ねているので、私の恥ずかしい初回回答も掲載。
反省しているので触れないでください、、、

```ruby:qiita.rb
〜悪い例〜
def calculate_points(a,b)
  if b && a <= 999
    puts "ポイントは#{a * 0.03 * 5.floor}点です"
  elsif b && a >= 1000
    puts "ポイントは#{a * 0.05 * 5.floor}点です"
  elsif a <= 999
    puts "ポイントは#{a * 0.03.floor}点です"
  else
    puts "ポイントは#{a * 0.05.floor}点です"
  end
end
〜悪い例〜
```

以上
AWS SAA合格体験記

# この記事は
AWS歴3年、インフラエンジニア歴5年の駆け出しエンジニアがAWS SAAを受験した体験記を残すものです。

# 書いていること、書かないこと
## 書いていること
- 勉強に費やした期間や、使った教材の話
- 自宅受験ノウハウ(ここがメインかもしれません)

## 書かないこと
- 具体的な問題や出題分野の話
- 勉強のコツの話

# 勉強に費やした期間や、使った教材の話
## 勉強に費やした期間
2021年7月に受験を決め、受験は9/8なので2ヶ月ほど「勉強できる」期間がありました。
もともと、業務でAWSも使っていましたし、ここ３年ほどはサーバレスアーキテクチャをベースに一部EC2の設計から運用まで実務経験があったので勉強はお盆休みでいいかぁ、くらいでした。

そして、お盆休みは夏休みの高揚感に負け、全く勉強できず・・・・・・

時は過ぎ、9月に入り、脳内で「SAA、9/10だったよなー」と思ったのが9/7のことです。
そして、受験当日の9/8の朝に環境チェックのためにAWS認定アカウントのページに行ってみると、え、今日なの！？
となった、なんともお恥ずかしい気付き方でした。

なので、正直なところ無対策です(試験直前の3時間くらい)。
今回の受験は３年の実務経験による知識で臨んだというイメージです。

## 使った教材
実は、2018年に一度SAAを受験して650点くらいで不合格でした。
その時に、Udemyの以下の講座を購入していました。

- [これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（SAA-C02試験対応版）](https://www.udemy.com/course/aws-associate/)
- [【SAA-C02版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）](https://www.udemy.com/course/aws-knan/)

本腰を入れて勉強、というわけではないのですが、ほんとにたまに、気づいた時に問題集を解いてはいました。

# 自宅受験ノウハウ
COVIC-19の影響もあるのかないのか、AWS認定資格も自宅受験ができるようになりました。
ピアソンVUEでの受験については[こちら](https://www.pearsonvue.co.jp/Clients/Amazon-Web-Services/Online-Proctored.aspx)

試験の申し込みなどは苦労したことはなかったんですが、当日がとてもきつかった・・・
ふりかえって考えてみると、当たり前な話なのですが事前の環境整備がとても重要です。

## 電気機器は全て手の届かないところに移動させる
机の上にあるあらゆる電気機器は全て手の届かないところに移動させないといけません。
僕の場合、これらが指摘されました。

- PCと接続しているUSBスピーカ
- 外付けDVDドライブ
- 3in1充電器(スマホとAppleWatchとAirPodsを充電できるアレ)
    - ついでに充電してたAppleWatch

## 文字が見えるものは手の届かないところに移動させる
文字のあるもの、それが見えるものが手の届く範囲にある場合、移動させましょう。
もしくは、上から布をかけて見えない状態にしましょう

- デスク横の本棚にある本たち
- カレンダー
- [コースター](https://shop.tv-tokyo.co.jp/shop/g/gDBS003509/)
    - 確かにこれは文字でしかない……

## モニタには布をかけましょう
複数モニタ使っている方は多いと思いますが、外付けしているモニタに関して、上から布をかけて完全にモニタ面を覆うように指示されました。
これが一番焦ったんですが、大きめのモニタを使っている人はおうちにそれを隠せるだけの布があるのかが重要ですね。

# 受験した感想
ほぼ無対策で臨んだ分、やっぱり問題に対する耐性が低かったのでかなり難しく感じました。
ただ、よく読んで文章を理解してみると経験したことであったり自分で実際に考えたことのあるようなことばかりだったので解きやすかったです。
そういう意味では、2018年に受験して不合格だった時に比べ、より実務的な問題が増えているように思えます。
日本語が分かりにくい、という意見もあったりしますがずいぶん改善されているような気がしました。

問題集やBlackbeltなどで知識をつけて試験に臨むことも非常に重要と思いますし、そこをしっかりやっていればもっと楽勝で合格できたのだと思いますが、実際に手を動かして使ってみることが非常に重要なのではないかなと思いました。

次は、DVAに挑戦予定です。
今度はちゃんと勉強するぞ！ということで、とりあえずバウチャーを使って模擬試験を受験しました。
弱いところがわかったので、ここを中心に勉強していこうと思います。

なんだか、資格が体系的に整理されているので一つ合格すると次はこれやってみよう、とモチベーションが上がるのがとても良いですね！！

SAA自体の受験にはあまり役立つ情報は書けなかった気がしますが、自宅受験ノウハウ、ぜひ皆さんの受験に役立ててください。
心の平穏につながります。
Flask+スクレイピングで記事一覧画面を作ろう②

<h2>概要</h2>
こちらは前回[Flask+スクレイピングで記事一覧画面を作ろう①](https://qiita.com/Yuthon/items/398025d2858ce2e47483)の続きです。
今回は、Flaskの準備を行い、HelloWorldを表示させます。
<h2>Flaskの環境を作ろう</h2>
Macの方はターミナル、Windowsの方はパワーシェル、もしくはコマンドプロンプトで以下のコードを打って仮想環境を作ります。

1. Anacondaでの仮想環境を作りたい方

```terminal
# 仮想環境を作ります
$ conda create --name flaskenv

# 作れたら、仮想環境を適用します
$ conda activate flaskenv

# Flask, wtforms, requests, BeautifulSoupをインストールします
(flaskenv)$ pip install flask wtforms requests beautifulsoup4
```
2.virtualenvでの仮想環境を作りたい方

```terminal
# ↓まだvirtualenvをインストールしていない方
$ pip install virtualenv

# 仮想環境を作ります
$ virtualenv flaskenv

# 仮想環境を適用します
$ source flaskenv/bin/activate

# Flask, wtforms, requests, BeautifulSoupをインストールします
(flaskenv)$ pip install flask wtforms requests beautifulsoup4
```
pyenvを使用した仮想環境も構築できますが、少し複雑になるので以下の記事を参考にすると良いかもしれません。
[pyenvとpyenv-virtualenvの自分流使い方 - Qiita](https://qiita.com/ksato9700/items/5d9eba10fe6b8e064178)

<h2>HelloWorldを表示しよう</h2>
環境の準備ができたので、任意のフォルダにapp.pyを作ってHelloWorldを表示してみましょう。(今回はFlaskScrapingというフォルダを使用します)

```python:FlaskScraping/app.py
# モジュールのインポート
from flask import Flask

# Flaskアプリのインスタンスを作成
app = Flask(__name__)

# ルーティングの設定
@app.route('/')
def index():
    return '<h1>Hello World!</h1>'

# このコードによって、Flaskがweb上で走ります
if __name__ == '__main__':
    # debug=Trueとすることで、保存するだけで変更が適用されます
    # エラーも見やすくなります
    app.run(debug=True)
```
このPythonファイルを実行しましょう。

```terminal
(flaskenv)FlaskScraping$ python app.py
```
これで、コンソールに http://127.0.0.1:5000/ というURLが表示されるので、これにアクセスしましょう。
Hello World!と表示されていたら成功です！

以上でFlaskの準備もできたので、次回から本格的にアプリを構築していきましょう！
ありがとうございました🙇‍♂️
[Flask+スクレイピングで記事一覧画面を作ろう③](https://qiita.com/Yuthon/items/aba29f0daecf125bc3ad)
【メモ】Seismic Unix でサンプル数の大きなファイルを扱う

# 課題
### 背景
サブボトムプロファイラなどで取得したデータは、他のソフトウェアでも扱えるように"seg"形式に変換することが多い（"sgy"や"segy"でも同じ事になると思われる）。通常の反射法のデータと比べてトレースあたりのサンプル数 ```ns``` が多かったり、サンプリング ```dt``` がとても小さな値だったりする。

加えて、簡便なオペレーションに伴い沢山の測線を取得する事が多いので、ある程度自動的な処理にかけたい場面も多い。

### トレース数の制限
SUのデフォルトのソースコードでは、どうやらトレースあたりのサンプル数が16bitの```65535```に制限されているようで、それより長いファイルを投入すると ```SU_NFLTS``` の値を超えたというエラーが発生することがある。特に描画系のコマンドで気づく事が多い。

## ソースコードの書き換え（対症療法）

```segy.h``` の29行目あたり ```SU_NFLTS``` の値を少し大きくしてコンパイルすると、 ```SU_NFLTS``` に関するエラーが出なくなる。

```segy.h
<< #define SU_NFLTS	65535   /*   Arbitrary limit on data array size	*/
>> /*	#define SU_NFLTS	65535      Arbitrary limit on data array size */
>> #define SU_NFLTS	131070   /*   Arbitrary limit on data array size */
```

オリジナルファイル：

https://github.com/JohnWStockwellJr/SeisUnix/blob/master/include/segy.h

## 追記
2011年頃、このGoogleGroupsで既に同様の議論がされている。

[GoogleGroups　[Seisunix] Reading long SEGY traces](https://groups.google.com/g/osdeve_mirror_geophysics_seisunix/c/tm6j8DFxk_w/m/UMpKC1WCNjwJ)

 ```segy.h``` を書き換えるのは注意が必要で、どこかで型の不整合が起きるなどの問題を起こす可能性がある旨が書かれていた。そもそも上記のように ```SU_NFLTS``` だけを書き換えても、 ```ns``` フィールドは ```short型``` で定義されているので（313-315行目）、16bitを超える数値をぶち込むとどうなるか分からないですね。それで ```int型``` なんかに書き換えようものなら、ソースコード全体に影響が出てしまうのでこわい。

```segy.h
	unsigned short ns;	/* number of samples in this trace 
			   byte# 115-116
			*/
```


規格通りのSEG-Yヘッダでは ```ns``` フィールドは16bitの ```short型``` であるべきなので、正攻法はSEGYファイルの方を修正すべきとの議論もある。しかし、、、

現行の [SEG-Y Rev.2.0](https://wiki.seg.org/wiki/SEG-Y) ではトレースあたりのサンプル数を

```math
 2^{32} -1 個
```

測線あたりのトレース数は

```math
 2^{64} -1 個
```

まで増やしたとの事なので、「気分としては」無限に増やして良いことになる。Seismic Unix 全体のアップデートを一人でやるのは大変なので、コミュニティで何とか新しい規格に対応して欲しいなぁとぼんやり思う。
【備忘録】Gitの初期設定


# はじめに
備忘録としての初期設定(mac)について執筆します。

具体的には、Github上に登録したユーザー名とメールアドレスの設定、エディター（今回はAtom）の設定について記載します。

# Gitとは
バージョン管理システムの１つ。
バージョン管理システムとは、データ保存だけでなく、誰がいつどこを編集したのかを履歴を把握できるシステムのことである。これを使うことで、最新のデータがどこにあるのか確認でき、データの復元が容易にできる。

Gitの他のバージョン管理システムはMercurial、Subversion等がある。

# 環境
OS:macOS Big Sur 11.5.2

# Gitのバージョン確認
macにはデフォルトでGitがインストールされている。
ターミナルで下記のコードを入力してバージョンの確認をする。
※2021年9月9日現在のバージョンは　2.30.1

```ターミナル
git version

git version 2.30.1 (Apple Git-130)
```
## Gitがインストールされていない場合、下記のURLから下記URLからインストールする。

https://git-scm.com

# githubの登録
下記URLを参考に登録をする。

https://qiita.com/ayatokura/items/9eabb7ae20752e6dc79d

# Atomのインストール
下記URLからインストールする。

https://atom.io

# ターミナルでの設定
GitbHubに登録したユーザー名とパスワードの設定、エディダーの設定（今回はAtom）をターミナルでせってしていく。

※登録した名前を「name」、登録したメールアドレスを「mail」とする。

ターミナルに下記の内容を入力していく。

```
git config --global user.name "name"
git config --global user.email "mail"
git config --global core.editor "atom --wait"  
```


# 入力内容の確認方法
ターミナル上で下記のコードを入力して設定内容を確認する。

ユーザー名の確認

```
git config user.name

name
```

メールアドレスの確認

```
git config user.email

mail
```

エディターの確認

```
git config core.editor  

atom --wait
```

## 一度に全ての入力内容の確認をする方法
一度に設定内容を確認するためには下記のコードをターミナルで入力する。

```
git config --list

credential.helper=osxkeychain
user.email=[メールアドレス]
user.name=[名前]
core.editor=atom --wait
```

# 設定したフォルダの確認
今回設定した内容はgitconfigファイルに保存されている。
確認するためには、下記コマンドを入力する。
Cat:ファイルの中身を表示するコマンド

```
cat ~/.gitconfig   

[user]
	email = mail
	name = name
[core]
	editor = atom --wait
```

# 参考

https://qiita.com/ayatokura/items/9eabb7ae20752e6dc79d


https://www.udemy.com/course/unscared_git/
MoshiをKotlinで使う

Kotlinで、[Moshi](https://github.com/square/moshi)を使う場合の方法を記載します。

```gradle:app/build.gradle.kts
    implementation("com.squareup.moshi:moshi-kotlin:1.12.0")
    kapt(com.squareup.moshi:moshi-kotlin-codegen:1.12.0)
```

### Adapterの登録を行います。

DaggerなどのDIで、Module化すると楽になります。

```kotlin
val moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()
```

* Hiltを利用した場合

```kotlin
@Module
@InstallIn(SingletonComponent::class)
class JsonModule {

    @Provides
    @Singleton
    fun provideMoshi(): Moshi {
        return Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()
    }
}
```

### Json定義

JavaのMoshiの場合、定義出来る型が決まっていました。
それ以外を使用する場合、自前でアダプターを用意する必要があります。

* Primitives (int, float, char...) and their boxed counterparts (Integer, Float, Character...).
* Arrays, Collections, Lists, Sets, and Maps
* Strings
* Enums

Kotlinの場合、Kotlinの型が使用できるため、Anyクラスなど使用することが可能です。

```kotlin
@JsonClass(generateAdapter = true)
data class Request(
    val name: String,
    val parameters: Any?
)
```

### 文字列からJSON

```kotlin
val text = "..."
val moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()
val adapter = moshi.adapter(Request::class.java)
val request = adapter.toJson(text)
```

### JSONから文字列

```kotlin
val request = Request("name", 1)
val moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()
val adapter = moshi.adapter(Request::class.java)
val str = adapter.fromJson(request)
```

### List型の場合

```kotlin
val moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()
val type = Types.newParameterizedType(List::class.java, String::class.java)
val adapter = moshi.adapter(type)
```

moshi-kotlin-codegenは、簡単に使用できますので、是非お試しください。
Railsのインストールでつまづいたこと（原因はONEDRIVE）

もう腹が立って仕方がない

結局は個人のデスクトップフォルダが、知らない間にOnedriveにリンクされていて、
権限の関係でインストールが出来なかったからである。

それにしても、腹が立つ・・・

以下の環境はどちらも駄目だった。

* WSL/Ubuntu
* MYSYS2/MinGW


# デスクトップフォルダ

ずいぶん前は
C:\Users\motoc\デスクトップ\rails


最近、こうなっている
C:\Users\motoc\OneDrive\デスクトップ\rails


知らない間に、こんなクソ仕様にしやがって・・・

しばいたろか！


#フォルダ

C:\Users\motoc\OneDrive\デスクトップ\rails

```
motoc@DESKTOP-5GGB0DP MINGW64 ~
$ cmd.exe /c "chcp 65001"
Active code page: 65001

motoc@DESKTOP-5GGB0DP MINGW64 ~
$ cmd.exe /c "mklink /j rails C:\Users\motoc\OneDrive\デスクトップ\rails"
Junction created for rails <<===>> C:\Users\motoc\OneDrive\デスクトップ\rails

```

#エラー内容

```
$ bin/rails s
C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/bootsnap-1.8.1/lib/bootsnap/compile_cache/iseq.rb:30:in `fetch': No such file or directory - bs_fetch:open_current_file:open (Errno::ENOENT)
        from C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/bootsnap-1.8.1/lib/bootsnap/compile_cache/iseq.rb:30:in `fetch'
...　省略

```


#解決方法

下記のフォルダに変更

C:\Users\motoc\rails

```
motoc@DESKTOP-5GGB0DP MINGW64 ~
$ cmd.exe /c "mklink /j rails C:\Users\motoc\rails"
Junction created for rails <<===>> C:\Users\motoc\rails
```

無事に動いた

```
motoc@DESKTOP-5GGB0DP MINGW64 ~/rails/railsample
$ bin/rails s
=> Booting Puma
=> Rails 5.2.6 application starting in development
=> Run `rails server -h` for more startup options
*** SIGUSR2 not implemented, signal based restart unavailable!
*** SIGUSR1 not implemented, signal based restart unavailable!
*** SIGHUP not implemented, signal based logs reopening unavailable!
Puma starting in single mode...
* Version 3.12.6 (ruby 2.6.8-p205), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop
Started GET "/" for ::1 at 2021-09-09 10:41:43 +0900
Processing by Rails::WelcomeController#index as HTML
  Rendering C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/railties-5.2.6/lib/rails/templates/rails/welcome/index.html.erb
  Rendered C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/railties-5.2.6/lib/rails/templates/rails/welcome/index.html.erb (7.3ms)
Completed 200 OK in 32ms (Views: 25.0ms | ActiveRecord: 0.0ms)

```
突然 Clean Architecture って言われても

<div style="text-align: right;">
2021.1
</div>

##前振り

コロナなご時世なので、ずっと、リモートワークなのに、急に呼び出されんたですよね。
進捗会議の日程だったので深く考えず、出かけてみたら…

次期開発に先だって、現状の作りである、Clean Architectureについて現状に沿って説明してほしいとか！
いゃ、突然ですか？

実装が、この図のどこに相当するか説明してってて言われても…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503965/60026a7a-6603-779e-e072-3db71edb343d.png)

無理です

で、こっちで
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503965/0f936ae0-91f1-ff49-9407-43c886d0917c.png)
Javaによるwebアプリの標準的なインプリメントなので、そんなには乖離がないんですね。

でも、みんなどうしてるんだろうと、ブログを徘徊してみました

##現状の実装

DIの登録はStartupにべた書きです

なんちゃってSingle Pageで、WebとAPIを分けています
現場の決定なので、Entity Frameworkです
Dapper 使ったことないからダメなんだそうです
でも、誰かが生のado.net
使っています
でも、Entity Frameworkはrepository層でラップしてあるので
とはいえ、DbContextはDIしているので、見えちゃうんですがw

ていうか、もともとあるクラス名が意味のない機能IDなので…

クラス間の受け渡しのデーターがPOCOじゃなくってinterfaceだったりしたのは書き直したのですが
まあ、どのフォルダーに何を置くのかという、レベルの理解でしかない？ので。

あとは、どのクラスに何を追加していくのか？
いゃ、まとめるのではなく、分けるのだというと
要は、utilとかcommonがないというのが…
あと、定数クラスは作らないというのが、理由から説明しないと駄目で。

Deep changeを目指してのトライアルなのだけと、今までの、汎用コンピューター的な、仕事の進め方と違いすぎるから、きっと、作業が進むにつれて劣化してい行くのでしょう
Windows PCにおけるポートを指定した疎通確認方法

#背景
Windows PCにおける疎通確認方法として、コマンドプロンプトにおけるpingコマンドが有名ですが、これはポートを指定できません。
ポートを指定した疎通確認を実施したかったため調査しました。
Windows PCであれば、ソフトのインストール等を実施する必要はありません。

#クライアント側(送信側)での疎通確認方法
PowerShellにおいて、以下のコマンドで疎通確認ができます。(コマンドプロンプトは×)
※IPアドレスとポート番号(192.168.0.1と5432の部分)は適宜修正してください。

```powershell:powershell.exe
> Test-NetConnection -ComputerName 192.168.0.1 -Port 5432
ComputerName           : 192.168.0.1
RemoteAddress          : 192.168.0.1
RemotePort             : 5432
InterfaceAlias         : イーサネット
SourceAddress          : 192.168.0.10
PingSucceeded          : True  #ping疎通可否確認
PingReplyDetails (RTT) : 1 ms
TcpTestSucceeded       : True  #サーバ側のポート開放有無確認
```

#サーバ側(受信側)でのポート開放有無確認方法
コマンドプロンプトにおいて、以下のコマンドでアプリケーションがポートを開放しているか確認できます。
※ポート番号(5432の部分)は適宜修正してください。

```powershell:cmd.exe
> netstat -nao | find ":5432"
プロトコル   ローカル アドレス        外部アドレス             状態            PID
TCP         0.0.0.0:5432           0.0.0.0:0              LISTENING       XXXX
```

XXXXにはPID(プロセスID)が表示されますので、該当ポートを開放しているアプリケーションを特定できます。
特定方法は、
　　タスクマネージャー → 詳細
から確認できる同一のPIDのアプリケーションです。
![スクリーンショット 2021-09-09 095359 - コピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989967/75dcabda-da03-1669-1d0a-5f7cfccce51b.png)
59日後にITパスポートを受けるFラン私大文系既卒(42日目)

# グリッドコンピューティング
* グリッドコンピューティングとは?
 * インターネットを使って複数のコンピュータを繋ぐことで、スーパーコンピュータ並みの高速処理を実現するシステム

# NAS(Network Attachment Storage)
* NASとは?
 * ネットワークに接続して使用するファイルサーバ専用機

# TCO(Total Cost of Ownership)
* TCOとは?
 * 初期コストと運用コストを合わせた費用

# フェールソフト
* フェールソフトとは?
 * たとえ性能が落ちたとしても、システム全体は動作させる設計
 * フォールトトレランとは機能を縮小しない、フェールソフトは機能を縮小してでも稼働率を上げるという違いがある

# マルチスレッド
* マルチスレッドとは?
 * タスクを複数のスレッドに分けて処理すること

# ターボブースト
* ターボブーストとは?
 * いつもより早く、プロセッサコアを動かすこと

# BIOS(Basic Input Output System)
* BIOSとは?
 * ハードウェアを制御するプログラム
 * PC起動時に最初に立ち上がる

# LSI(Large Scale Integration)
* LSIとは?
 * 大規模集積回路
 * ほぼICと同義

# ポートリプリケータ(replicate)
* ポートリプリケータとは?
 * 色々な規格のポートがついている機器

# IrDA(Infrared Data Association)(Infrared :赤外線)
* IrDAとは?
 * 赤外線の標準化を策定する団体

# LPWA(Low Power Wide Area)
* LPWAとは?
 * 少ない電力で遠距離通信を実現する通信方式
 * IoTの構成要素

# MDM
* MDMとは?
 * 企業で使われるモバイル端末を一元的に管理するためのサービスやソフトウェアのこと

# MVNO(Mobile Virtual Network Operator)
* MVNOとは?
 * 仮想移動体通信業社
 * 通信会社から通信回線を借り受け、格安SIMを提供する業者

# ブレードサーバ
* ブレードサーバとは?
 * 物理的に薄いサーバを複数入った、サーバの集合体のこと

# ユビキタスコンピューティング(ubiquitous :偏在的に)
* ユビキタスコンピューティングとは?
 * コンピュータの所在を意識することなく、いつでも、どこでも、誰でもコンピュータを使える情報環境を表す概念


# スループット
* スループットとは?
 * コンピュータやネットワークが単位時間あたりに処理できるデータ量のこと

# ピアツーピアシステム
* ピアツーピアシステムとは?
 * コンピュータ同士が対等の立場でデータのやり取りをするシステムのこと
Laravel date型カラムの取り扱いに注意

## エラーの詳細
例えば`User`モデルに`date`型の`birthday`というカラムがあるとする。

この`birthday`を

```php
{{ $user->birthday->format('Y/m/d') }}
{{ $user->birthday->format('Y年m月d日') }}
```

上記のようにフォーマットを変更して表示する場合、`User`モデルに

```php
protected $dates = [
  'birthday'
];
```

とすると**`birthday`は`Carbon`インスタンスとなるため、フォーマットを変更できる。**


しかし、フォーマットを変更して表示している場合`birthday`が`null`だと下記のようなエラーになる。

```
Call to a member function format() on null
(nullなのにメンバー関数format（）を呼び出しています)
```

エラーを回避するために下記のようなNull合体演算子を書いてみたが、それでも`null`の場合、同じエラーになる。


```php
{{ $user->birthday->format('Y/m/d') ?? '登録なし' }}
```

これはの`birthday`のフォーマットを変更した上で`null`判定しようとしているのだが、フォーマットを変更するタイミングで`birthday`が`null`のため、やはり同じエラーが起こる。

## 解決策

`birthday`のフォーマットを変更する前に条件分岐をすればいい。

```php
// if文の場合
@if($user->birthday)
  {{ $user->birthday->format('Y/m/d') }}
@else
  登録なし
@endif

// 三項演算子の場合
{{ $user->birthday ? $user->birthday->format('Y/m/d') : '登録なし' }}
```

上記のようにすることで、`birthday`が`null`でもエラーは起きなくなる。


ということでlaravelの`date`型カラムの取り扱いには要注意です。

(自戒の念を込めて。)
bootの設定を変更してLinuxのISOイメージDVDを起動

##はじめに
PCからWindowsを削除し、ubuntu20.04のISOイメージDVDからLinuxをインストールしていきます。
本記事は、主にboot設定に関しての記述をメインにします。

##ブート(boot)とは								
「PCを立ち上げる」という意味。
BIOSメニューの一種。

##BIOS(バイオス)とは
Basic Input Output System
パソコンの土台部分であるマザーボードに搭載	
OSが起動する前のタイミングで、キーボードやマウス、パソコンの頭脳部分であるCPUなどの管理や制御を担う

<b>BIOS画面サンプル</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637823/3cd608a6-801a-9a0a-ffc2-aed0527117da.png)

								
								
##BIOSのメニュー画面		
* <b>Main(System Info、CMOS)</b><br>
日時設定やメモリ情報など基本情報の表示や設定の初期化。
* <b>Advanced(Tools、Integrated)</b><br>
システムの詳細設定や接続に関するものの設定が行えます。（CPU、メモリー、IDE、スーパーIO、トラステッド・コンピューティング、USBなど）<br>
* <b>Security</b><br>
ユーザーおよびスーバーバイザのパスワードを設定<br>
スーバーバイザ：PC管理者や、OSの意<br>
* <b>Boot</b><br>
起動デバイスに関する優先順位を設定
* <b>Exit</b><br>
BIOS画面を終了する

##BIOS画面に入る方法
|メーカー|操作|
|----|----|----|
|VAIO(SONY)|電源ボタン押下後、F2連打||

##BootMode Legacy UEFI
LegacyよりUEFIの方が新しい。

##LinuxのISOイメージDVDを起動
* Boot Priority<br>
DVDから起動する場合は「External Device」の優先順位を一番上に上げる。
* Exit に移動し、変更を保存して終了する。
* DVDが立ち上がりインストール画面に遷移する。
Macのpythonをアップデートした備忘録

**概要**
主な手順は以下を参考にした。
https://qiita.com/Ajyarimochi/items/ff40e57d082dd171e761
ただし、インストールするpythonのバージョンによっては上手く入らなかった、grobalしてもpyenvで見ると変わってなかった等があった。なんで？

**手順**
pythonのバージョン確認

```
$ python -V
```
Homebrewはインストールされているのでpyenvをインストールした

```
$ brew install pyenv
```
pyenvのバージョン確認

```
$ pyenv -V
```
pyenvの設定を行う

```
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
```
インストールできるもののリスト出す

```
$ pyenv install --list
```
3.8.0をインストールしようとしたができなかった

```
$ pyenv install 3.8.0
```
3.10.0rc1をインストールしたらできた

```
$ pyenv install 3.10.0rc1
```
pyenvバージョン確認する

```
$ pyenv versions
```
そうするとsystemの下に3.10.0rc1が並んで表示され、systemの方の頭に*がついている状態になるのでglobalする

```
$ pyenv global 3.10.0rc1
```
systemではなく3.10.0.rc1の方に*がつく状態になる
もう一度pyenvするとPython 2.7.16と表示されてしまった
以下を参考にしてこれを足した
https://www.webworxinc.jp/2020/08/22/version/

```
$ export PATH="$HOME/.pyenv/shims:$PATH"
```
再度グローバル化する

```
pyenv global 3.10.0rc1
```
バージョン確認してみる

```
pyenv -V
```
Python 3.10.0rc1と表示されたので、pythonのアップデートは終わり
pumaをdevelopment環境でもバックグラウンドで実行する

puma 5.0.0からデーモン化機能が削除されてしまったので、production環境ではsystemdで動かす事になった。
development環境ではrails sなどで実行すればいいのだが、ターミナルを専有されるのが嫌なのでdevelopment環境でもrails sではなくバックグラウンドで実行するための自分用のメモ。
バックグラウンドで実行したいだけなら単純に&をつけて実行すればいいだけなので簡単。

### 結論

さっそくだが、こんなシェルスクリプトをプロジェクト直下のbin/ディレクトリに配置して実行権限を付与する(chmod +x)。

そしてこう使う。
```
bin/pumactl.sh start
bin/pumactl.sh stop
```

* bin/pumactl.sh

```bash
#!/bin/bash

current_dir=`(cd $(dirname $0); pwd)`
rails_root=`(cd "$current_dir/../"; pwd)`
log_file="$rails_root/log/puma.log"
pid_dir="${rails_root}/tmp/pids"
pid_file="${pid_dir}/puma.pid"

start() {
  echo "starting puma"

  mkdir -p $pid_dir
  cd $rails_root
  bundle exec pumactl start >> $log_file  2>&1 &
}

stop() {
  echo "stopping puma"
  cd $rails_root

  if [ -f $pid_file ]; then
    bundle exec pumactl stop
  else
    echo "pid file not found: $pid_file"
  fi
}

restart() {
  echo "restarting puma"
  stop
  start
}

# See how we were called.
case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart)
    restart
    ;;
  *)
    echo $"Usage: $prog {start|stop|restart}"
esac
```