OmniAICreator/Qiita-1.07M huggingface dataset:
vimの使い方

# vimの使い方
vimはいくつかのモードから成り立っています。
今回はインサートモード（入力）で入力して保存するところまでを書きます。
実際、他のモードはあまり使わないです。

## ノーマルモード

vimで起動した最初の状態が、ノーマルモード。
このままじゃ入力できない。
入力モードに切り替える必要があります。

## インサートモード

インサートモードという入力できるモードにする必要があります。
ノーマルモードの状態で`i`を入力することで、カーソルの位置から入力することができるようになります。
`i`と`o`のコマンドだけ覚えていれば十分です。

```
i       カーソルの位置から入力
o       カーソルの次の行に新しく行を追加して挿入モードに移行
```

インサートモード中は最下部に「**挿入**」とか「**INSERT**」と表示されていることを確認します。（各環境によって表示が違います）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/8e2c6825-df40-28a4-6f27-f82be9b2837c.png)
**入力し終わりインサートモードを抜けるにはESCキーを押します。**
するとノーマルモードに戻ります。

## 保存、閉じる

ノーマルモード時に`:(コロン)`キーを押します。
すると最下部にカーソルが移動されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/975eab06-704a-0a48-3e4b-e6ea2c73de0d.png)
`wq`と入力しEnterキーを押すと保存して閉じるになります。

```
:wq       保存して閉じる
:q        保存せずに閉じる
```
sympy: Symbol( ), symbols( ), var( )使い分け

# 混乱
sympyの使い方を確認しようと検索して出てくるwebページを見ると、変数シンボルの定義に、`Symbol( )`を使っているもの、`symbols( )`を使っているもの、`var( )` を使っているものなどがあり、どれを使うのが適当なのかよく分からない。
よく理解していないものだから、`Symbol( )`で複数のシンボルを作ろうとして、エラーになる。

なので、公式ドキュメントを読んで確認したので、その結果を下にまとめる。

# `Symbol( )`
`Symbol( )`は、Symbol ClassのオブジェクトのConstractor。
なので作れるシンボルオブジェクトは1度の呼び出しで1つ。

``` 
# 例
x = Symbol('x')
```

# `symbols( )`
`symbols()`は引数で与えられた文字列を解釈して、指定された名前を持つSymbolオブジェクトを返す。
返り値を変数で受け取らないと、そのオブジェクトは消えてしまう。

```
# 例
x, y = symbols('x, y') # 区切りはスペースでも可
```

## 便利なシンボルの生成方法
`symbols( )`は、引数で与える文字列によって複数のシンボルを生成する便利な使用方法がある。

以下の例では、返り値を受け取っている変数名は、生成されているシンボルの名前を示す。

```
x0, x1, x2 = symbols('x:3')
x50, x51 = symbols('x5(:2)')
a, b, c = symbols('a:d')
[a, b] = symbols(['a', 'b'])
```

#`var( )`
`var( )`は、引数で与えられたものと同じ引数で`symbols( )`を呼び出し、作成されるシンボルオブジェクトを同じ名前の変数として、global name spaceに格納する。
なので、`var( )`の返り値は変数で受ける必要がない。

## `var( )`使用上の注意
生成されるオブジェクトがglobal name spaceに格納されるゆえ、関数内で`var( )`を使うと、変数名の衝突などの問題を起こすゆえ不適当。関数内では`symbols( )`を使う方が良い。
(逆に言えば、トップレベルでは`var( )`を積極的に使うと良い。)
Lambda Layersで快適に開発する方法

みなさん、Lambda Layers使ってますか？
共通で利用するロジックをライブラリにできる、ということで登場時は大変盛り上がりました。
（それまでは関数ごとにライブラリ部分にシンボリックリンク貼って利用してた）

ただ開発を重ねるにつれて、「これ、色々不便じゃ、、、？」と思うことが湧き上がってきました。

# 根本原因：ローカルで/optを参照するの辛い

Layersのデプロイ先は/optになるので、ローカルでもそれに対応する方策を色々と取る必要があります。

### docker使って/optにLayersをマウントする

可能です。可能ですが、テストやビルド時にわざわざdockerに入るのめんどくさい、、
加えて、IDEにdockerを認識させるのが環境によりますが、面倒くさかったり、有料じゃないとできなかったりします。
IDEが「/optなんてないよ」と認識してくれない状態での開発は無理ゲー

### シンボリックリンクを使う

こちらも可能です。可能ですが、プロジェクトが複数に跨がってくるとその管理がまた面倒になってきます。
ローカルのグローバル領域荒らしたくないんじゃ、、、cloneしたら即開発したいんじゃ、、、

# 解決策
関数のソースからLayersのソースを呼び出す、という構成を取る以上、上記の/opt参照問題は避けられません。

色んなプロジェクトで利用してると環境構築やり直したりとかもちょいちょい出てきて、「もうIDE参照めんどいよ！」と、ある程度はローカルでそのまま開発できるよう、できる限り関数からLayersを参照しないように、、ロジックはLayersに寄せるように、、、としてたら、あることに気づきました。

***全部Layersに書けば良くね？***

「共通で利用するロジックをライブラリにできる」という触れ込みによる先入観で開発していましたが、極限まで参照を削っていったらこうなりました。


```typescript:BaseFunction.ts
// @ts-ignore
import {invokeLayerFunction} from '/opt/lambda_handlers/LayerRooter';

export async function handler(event: any) {
    return await invokeLayerFunction(event);
}
```

このソースは一度書いたらもう、二度と触れずに存在を忘れられます。
Typescriptならjsファイルごとコミットしても良いくらい。

で、この呼び出し先であるLayers側のコードはこんな感じです。

```typescript:LayerRooter.ts
const AWS_LAMBDA_FUNCTION_NAME = process.env.AWS_LAMBDA_FUNCTION_NAME;
const SOME_FUNCTION_NAME = 'hoge';

export async function invokeLayerFunction(event: any) {
    switch (FUNCTION_SUFFIX) {
        case SOME_FUNCTION_NAME:
            // call some metho
        default:
            break;
    }
}
```

この方式は、全ての関数のコードを`BaseFunction.ts`にし、関数名によって呼び出し先ロジックを変えるという方式です。
パフォーマンス的には`SomeFunctionA.ts`や`SomeFunctionB.ts`がLayerのメソッドを一つだけ呼び出す、という方がわずかに優れていますが、そうすると関数の追加のたびに/optを参照したコードを扱う必要があり、それすら面倒になったのでこの方式を採用しています。

他にも「全て一つの関数とし、引数のheader等で呼び出し先ロジックを変える」という方法もありますが、これは常時起動するコンテナ数という観点でパフォーマンスは良いものの、変なコードを仕込んでした待った場合のダメージが全体に及ぶ点や、CloudWatchのログ解析が大変、という問題もあるので関数は分けて運用しています。

マイクロサービスなのにモノリシックっぽくない？という気もしなくもないですが、Layer内のコードをちゃんと書けば問題ないかと考えています。

お役に立てましたら幸いです。
良い開発ライフを！
GitHub Actionsの実行履歴をまとめて削除する / How to delete workflow run histories at once

# TL;DR

```bash
owner="Organization名 または User名"
repo="リポジトリ名"
file_name="ファイル名"

gh api "repos/${owner}/${repo}/actions/workflows/${file_name}/runs?per_page=100" \
| jq -r '.workflow_runs[].id' \
| xargs -P4 -I{} gh api repos/${owner}/${repo}/actions/runs/{} -X DELETE
```

# やりたいこと

▼ 左側のWorkflow一覧から不要なWorkflowを削除したい。

![Workflow一覧](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502255/bbedb0a6-1b9b-f129-fdf6-c0c9147dc9f0.png)

▼ ちなみに1回のrunはweb上で消すこともできる。しかし大量にある場合はまとめて削除したい。
![手動で削除する場合](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502255/348387cb-dfad-2c1f-567a-99dc72668695.png)

# 方法

GitHub CLIとjqでいい感じにする。

https://github.com/cli/cli

https://github.com/stedolan/jq

▼ Homebrewでインストール

```bash
brew install gh jq
```

### #1 取得

```bash
gh api "repos/${owner}/${repo}/actions/workflows/${file_name}/runs?per_page=100"
```

公式リンク: [List workflow runs](https://docs.github.com/en/rest/reference/actions#list-workflow-runs)

**冒頭に貼ったスクショの画面ではURLが次のようになっている。末尾がファイル名(拡張子はyaml or yml)**

`https://github.com/${owner}/${repo}/actions/workflows/${file_name}`

### #2 jqでフィルター

```bash
| jq -r '.workflow_runs[].id'
```

全件なら上記。例えばブランチで絞りたい場合、以下のようにする。

```bash
| jq -r '.workflow_runs[] | select(.head_branch = "master") | "\(.id)"'
```

### #3 削除

```bash
| xargs -P4 -I{} gh api repos/${owner}/${repo}/actions/runs/{} -X DELETE
```

公式リンク: [Delete a workflow run](https://docs.github.com/en/rest/reference/actions#delete-a-workflow-run)

-P4は4並列。APIの叩き過ぎで怒られた場合は減らしてください。

### まとめ（再掲）

```bash
owner="Organization名 または User名"
repo="リポジトリ名"
file_name="ファイル名"

gh api "repos/${owner}/${repo}/actions/workflows/${file_name}/runs?per_page=100" \
| jq -r '.workflow_runs[].id' \
| xargs -P4 -I{} gh api repos/{owner}/{repo}/actions/runs/{} -X DELETE
```
DartでSleepを使っちゃいけない場合。Future.delayedとの話

Flutter歴一週間にみたない赤ん坊です。バブー。はいはい。

timeout処理を実装するためにFutureのtimeoutメソッドを使用したのですが、これがsleepだとうまく動きませんでした。試行錯誤の末、ようやくawait Future.delayedを使わなければいけない事がわかったので、シェアさせていただきます。

以下のコードは、うさぎとかめが競争するプログラムです。うさぎはsleepで寝てもらい、かめはawait Future.delayedで休んでもらいます。


```dart:test.dart
import 'dart:async';
import 'dart:io';

//計測用
class Timer {
  static int started = 0; //開始時間

  //リセット
  static void reset() {
    started = getNow();
  }

  //現在エポックミリ秒を取得
  static int getNow() {
    return DateTime.now().millisecondsSinceEpoch;
  }

  //経過ミリ秒を取得
  static int getPassedTime() {
    return ((getNow() - started) / 1000).round();
  }

  //結果をプリント
  static void printWithTime(String str) {
    print(Timer.getPassedTime().toString() + "秒: $str");
  }
}

//待ち処理
Future run(String runner, int duration) async {
  Duration _dur = Duration(seconds: duration);

  if (runner == "かめ") {
    Timer.printWithTime("$runner delay開始");
    await Future.delayed(_dur); //awaitのdelay使用。正常にタイムアウト処理される

  } else {
    Timer.printWithTime("$runner sleep開始");
    sleep(_dur); //sleep使用。タイムアウト処理されない
  }
  Timer.printWithTime("$runner完走");
}

//タイムアウト関数
FutureOr onTimeout(String runner) {
  Timer.printWithTime("$runnerタイムアウト");
}

//メイン
main() {
  const int waitTime = 10; //待ち時間
  const int timeoutTime = 3; //タイムアウト時間

  const Duration timeoutDur = Duration(seconds: timeoutTime);
  ["うさぎ", "かめ"].forEach((runner) async {
    Timer.reset();
    await run(runner, waitTime)
        .timeout(timeoutDur, onTimeout: () => onTimeout(runner));
  });
}

```


それぞれのFutureにtimeoutを設定した結果は、次のようになりました。

0秒: うさぎ sleep開始
10秒: うさぎ完走
0秒: かめ delay開始
3秒: かめタイムアウト
10秒: かめ完走

この結果から分かるに、うさぎはタイムアウトを無視して完全にsleepした後、完走（処理を終了）しています。対してかめはawait Future.delayedをしつつ、律儀にタイムアウトを経てから、完走（処理を終了）しているのが分かります。

続いて、かめ二匹に走ってもらうと、次のようになります。

0秒: かめ delay開始
0秒: かめ delay開始
3秒: かめタイムアウト
3秒: かめタイムアウト
10秒: かめ完走
10秒: かめ完走

先ほどはうさぎのsleepに邪魔されて次のかめがスタート出来ませんでしたが、今回はかめがスタートした後すぐに次のかめもスタートしています。このように、sleepのうさぎは他の非同期処理も抑制していたことが分かります。

Futureのtimeoutを使うときは、sleepではなくawait Future.delayedを使おうというお話でした。
【Vue.js】Vue.jsについて

#はじめに
こんにちは。
JavaScriptのフレームワーク`Vue.js`についてアウトプットしていきます！

##Vue.jsとは
>Vue.jsは、ユーザーインターフェイスを構築するためのJavaScriptフレームワークです。開発で必要な機能がセットになったツールと思ってもらえればわかりやすいと思います。
様々な機能が用意されているため、操作を覚えると扱いやすく少ない記述で実装が可能です。

> 参照：https://coosy.co.jp/blog/vuejs-benefit/

<br>

##フレームワークとは
フレームワークは全体の流れがもともと実装されている「型」のようなもので、その中で実装したい部分のコードを記述して開発していく。`Vue`や`React`、`Angular`などがある。


<br>

##Vue.jsを使用するメリット

JavaScriptのライブラリに`jQuery`というものがありますが、`Vue.js`との違いとして、

* `Vue.js`の方が、簡潔にコードを記述できる
* SPA（シングルページアプリケーション）開発ができる
* シンプルに設計されているため、拡張性が高い

などが挙げられます。

<br>

###Vue.jsのコード

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Hello World</title>
</head>

<body>
  <div id="app">
    {{ message }}
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="main.js"></script>
</body>
</html>
```
```javascript:main.js
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello World'
  }
})
```
`Vue.js`の基本的な構文になります。
bodyタグ内で、HTMLでVueとJSファイルを読み込みと、divタグにID`app`を指定。
`{{ message }}`に`'Hello World'`が置換されて出力される。

<br>

#最後に
ここまでVue.jsについてまとめました。
これからVueについての理解を深めるためにアウトプットしていきます！
誤った認識があればご指定いただけると嬉しいです^ ^
Excelのリボンの表示が大きいとき


#初めに
会社で使用しているExcelのリボンがなんか大っきい気がして
場所も取るので、スッキリしたバージョンにしたいなと思って調べたら
方法が見つかったのでメモ代わりに

##リボンがでがい

EXCELのリボンがこんな感じで場所と撮って嫌だ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61019/878b83ca-6382-9424-f225-5f62ea547d1a.png)

この表示の方がスッキリする、よし変更だ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61019/9c6e4e0a-12a9-4cba-5148-e377f81f4a46.png)



##対処方法
まずは上の「▼」っぽいやつをクリックして
「タッチ/マウスモードの切り替え」にチェックを入れる


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61019/3d685449-a8c5-87e6-d722-1a3aa64934cc.png)

これを入れると隣のアイコンがでてきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61019/fee9df36-15ec-f7e2-fe04-360c321efdfa.png)

これをクリックして
タッチ→マウスに切り替えてる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61019/ab4da8b6-1be7-7ce4-ecb3-4c3b5301876e.png)

切り替えると「マウス」がグレーになる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61019/034f5f6d-f1b2-25fa-4c34-85127dd31bb6.png)

そしてリボンもスッキリ！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61019/ece1e541-d748-3654-c51c-dc61f8bd34a6.png)
Creating network "terraform2_app_net" with driver "bridge" ERROR: Pool overlaps with other one on this address space  の対処法

#問題

docker-compose run 〜を実行したら表題のエラーが発生しました。

```
Creating network "~" with driver "bridge"
ERROR: Pool overlaps with other one on this address space
```

訳すとプールがこのアドレス空間で他のプールと重複していますということ。
同じものを作ろうとしてしまっていたということでしょうか。

#原因

docker-compose.yml にて同じネットワーク名称で作成をしていたためでした。

#解決策

使用されていない残っていたネットワーク設定を削除します。

```
docker system prune
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all dangling images
  - all dangling build cache

Are you sure you want to continue? [y/N] y
```

全て消してしまえばOKです。
これでdocker-compose run が実行できました。
KubernetesのYamlファイルのValidation方法

標準の kubectl にて、以下の方法でおこなえます

```
# Client-side validation
# クライアントで完結できる、Yamlの形式チェックなどがおこなわれます
$ kubectl apply -f xxxx.yml --dry-run=client

# Server-side validation
# 適用可能性も含めたサーバサイドでのチェックがおこなわれます
$ kubectl apply -f xxxx.yml --dry-run=server
```

従来あった `--dry-run` は deprecated のようなので注意！

https://stackoverflow.com/questions/64279343/kubectl-dry-run-is-deprecated-and-can-be-replaced-with-dry-run-client
OSコマンド・インジェクションの脅威と対策(安全なウェブサイトの作り方)

#はじめに
本記事は[安全なウェブサイトの作り方](https://www.ipa.go.jp/security/vuln/websecurity.html)(IPA)の第一章「ウェブアプリケーションのセキュリティ実装」に解説を加えた記事です。
長いので分割して投稿しています。
画像はすべて上記サイトから引用してます。


#目次
1.[概要](#概要)
2.[脅威](#脅威)
3.[根本的解決](#根本的解決)
4.[保険的対策](#保険的対策)


#概要
>ウェブアプリケーションによっては、外部からの攻撃により、ウェブサーバのOSコマンドを不正に実行されてしまう問題を持つものがあります。このような問題を「OSコマンド・インジェクションの脆弱性」と呼び、問題を悪用した攻撃手法を、「OSコマンド・インジェクション攻撃」と呼びます。
引用：[1]

![53D9D6DE-436C-436C-8F7F-04CAA78AC34F.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686089/57d9505e-f687-ad0f-2f1e-8dd5aae43fe8.png)



#脅威

- サーバ内ファイルの閲覧、改ざん、削除 
　　　重要情報の漏えい、設定ファイルの改ざん等

- 不正なシステム操作 
　　　意図しないOS のシャットダウン、ユーザアカウントの追加、変更等

- 不正なプログラムのダウンロード、実行
　　　ウイルス、ワーム、ボット等への感染、バックドアの設置等

- 他のシステムへの攻撃の踏み台 
     サービス不能攻撃、システム攻略のための調査、迷惑メールの送信等

#対象
外部プログラムを呼び出し可能な関数(perlのopen関数等)を使用しているウェブアプリケーション


#根本的解決
###(1)シェルを利用できる関数などの利用を避ける。
webアプリケーションに利用されている言語の中には、シェルを起動できる機能を持つものがあります。
代表的なもので、perlのopen関数(引数のファイルパスに「|」(パイプ)を使うことでOSコマンドを実行できる)などがあります。これらの関数をそもそも使わないことで、不正な利用をされた時の被害を抑えられます。
前述の例ではopen関数の代わりにsysopen関数を使うことでシェルの起動を防げます。

#保険的対策
###(1)シェルを利用できる関数の引数に対してチェックを行う。
前述のopen関数を使わなければいけない場合、引数に対してチェックを行うことが重要です。
例えば数値を引数として取る場合は、入力が数字のみからなる文字列であることをチェックする必要があります。

#リンク
1.[SQLインジェクション](https://qiita.com/reacon4234/items/ac5738e22a3eacfae623)
2.OSコマンド・インジェクション←本記事
3.パス名パラメータの未チェック/ディレクトリ・トラバーサル
4.セッション管理の不備
5.XSS(クロスサイトスクリプティング)
6.CSRF(クロスサイト・リクエスト・フォージェリ)
7.HTTPヘッダ・インジェクション
8.メールヘッダ・インジェクション
9.クリックジャッキング
10.バッファオーバーフロー
11.アクセス制御や認可制御の欠落



#参考文献
[1]IPA『[安全なウェブサイトの作り方 - 1.2 OSコマンド・インジェクション](https://www.ipa.go.jp/security/vuln/websecurity-HTML-1_2.html)』
プリザンターをVisual Studioでデバッグする

## 概要
この記事では、オープンソースのローコード開発プラットフォーム「[Pleasanter](https://pleasanter.org)」をVisual Studioでデバッグする際の手順を記載しています。

## 事前準備
下記の手順に従いWindowsにプリザンターをインストールして起動するのを確認します。
https://pleasanter.org/manual/getting-started-pleasanter-windows
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/54629299-e410-2f17-f7e2-fc86b221021b.png)

## Visual Studio Community 2019のインストール
下記よりVisual Studio Community 2019をダウンロードしてインストールします。
https://visualstudio.microsoft.com/ja/vs/community/

## ソースコードのクローン
Visual Studioを起動しリポジトリのクローンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/42d5a33a-5d51-6e62-aa96-188e45461ed8.png)

リポジトリの場所に下記のURLを入力しクローンボタンをクリックします。
https://github.com/Implem/Implem.Pleasanter
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/8caa77f1-6647-81cc-7871-d209ccb3b32a.png)

ソリューションファイルをダブルクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/a9b53653-064d-cbed-5fc2-fb10b1e2bfeb.png)

下図のようにプロジェクトファイルの一覧が表示されればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/0bbc431c-0d1e-7989-7c06-d02dcc8bdcf0.png)

## データベース接続の設定
事前準備でインストールしたRds.jsonをコピーしてクローンしたディレクトリのRds.jsonを上書きコピーします。コピー元のファイルは標準では下記のフォルダに存在します。
C:\web\pleasanter\Implem.Pleasanter\App_Data\Parameters\Rds.json

下図のようにVisual Studio上で下記変わっていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/ac2f5361-1f3d-25eb-cefe-6a57fb99c00e.png)

## スタートアッププロジェクトの設定
ソリューションエクスプローラーで「Implem.Pleasanter.NetCore」を右クリックして「スタートアッププロジェクトに設定」をクリックします。下図のように「Implem.Pleasanter.NetCore」が太字になればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/0b662074-9b9e-f1d2-9fe4-a84d0b3b40ac.png)

## デバッグ実行
デバッグ実行ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/7c6c573f-a5c1-ae56-984c-37a363806927.png)

下図のようにデバッグモードでプリザンターが起動します。事前準備でインストールしたプリザンターのデータベースに接続しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/8b99f247-5c9d-0756-c8fe-8d623844c63e.png)

下記のようにItemsController.csを開いてIndexメソッドにブレークポイントを設置し、デバッグモードで起動したブラウザでログイン操作を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/615ac7f9-f240-d1ba-c291-637d4967b471.png)

下図のようにブレークポイントで停止し、変数の中身などが確認できるようになりました。エラーが発生した際の原因調査や、独自機能のカスタマイズなど様々な用途に活用できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/7de4bb91-971f-389a-6cd7-4add1f3a612f.png)
【Python】10進数を2進数に変えるプログラムを作ってみた！

　Pythonを学び始めたので、とりあえずできそうなプログラムを手当たり次第作っています。今回は10進数を2進数に変えるプログラムを原始的に作ってみました。

```python
def base_number(num):
    remainders = []
    while True:
        remainder = num % 2
        remainders.append(str(remainder))
        num //= 2
        if num == 0:
            remainders.reverse()
            binary = "".join(remainders)
            print("2進数は" + binary + "です")
            break

num = int(input("数字を入力してください："))
base_number(num)
```

出力結果は以下のようになります。

```
数字を入力してください：160
2進数は10100000です
```


　もっと簡単に2進数を出せる数学の公式があれば、より簡潔なコードが書けると思いますし、Pythonにも2進数を簡単に出しやすいメソッドがあるかもしれませんが、アルゴリズムを考える勉強のため、まずは自分なりに考えてみました。
　結果的に「reverse」や「join」といったメソッドを使ってしまったため、これを使わない方法も考えてみたいと思います。
　またこの2進数の値をInteger型にしようとすると、「00000101」のような場合は「101」になってしまいますし、String型で仕方ないのかなと思っています。

　ご意見いただけると勉強になります。

<br>
【Ruby on Rails】font-awesome-sassを導入してアイコンを重ねて表示する方法


#対象者

* RailsアプリにFont Awesome導入予定の方
* Font Awesomeを重ねて表示したい方

#目的

*　アイコンを重ねて表示する！

イメージは下記の通り

![スクリーンショット 2021-09-10 7.35.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1681213/6012ab5c-5ffa-548e-857a-d477a681d4da.png)

#####使用環境

Rails　5.2.5

**注意**：Rails６をご使用中の方は導入方法が異なります。詳しくは[こちら](https://pikawaka.com/rails/font_awesome_sass)を御覧ください



#実際の手順と実例
###1.FontAwesomeを設定する

Gemfile

```
gem 'font-awesome-sass'
```

導入後は**bundle install**を実行する

続いてapplication.cssをapplication.scssに書き換えて下記のコードを追記します。
順番を入れ替えないように注意！

```application.scss
@import 'font-awesome-sprockets';
@import 'font-awesome';
```

###2.アイコンを重ねる表記方法

```html
<div class="col-md-4">
  <span class="fa-stack fa-4x"> 
   <i class="fas fa-circle fa-stack-2x "></i>
   <i class="fas fas fa-search fa-stack-1x fa-inverse"></i>
  </span>
</div>
```

###3.解説

1. 複数のアイコンを重ねるには**fa-stack**で重ねる２つの要素の親要素として指定します。
1. 続いてiタグで囲まれたアイコンを最背面から順に記述します。
1. fa-stack-2x、fa-stack-1xと指定することで、背面のアイコンの大きさが重ねるアイコンの大きさの２倍になります。

これで実装完了です！

#参照

* [Stacked Icons （FontAwesome　公式）](https://fontawesome.com/v5.15/how-to-use/on-the-web/styling/stacking-icons)
* [【Rails】 font-awesome-sassの使い方を徹底解説！](https://pikawaka.com/rails/font_awesome_sass)
基礎から学ぶReact/React Hooks学習メモ 5-1 useState

# React Hooksを基礎から理解する 5-1 useState

参考
- [基礎から学ぶReact/React Hooks](https://www.amazon.co.jp/dp/B09CP8T4TX)

## useState

- インポートする
    - ``import React, { useState} from 'react'``
- useStateの基本構文
    - ``const [状態変数, 状態を変更するための変数] = useState(状態の初期値)``

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88686/67cc7927-6bdc-f129-6cc4-521048334c91.png)

```js:Counter.js
import "./styles.css";

export const Counter = ({
  count,
  countIncrement,
  countDecrement,
  countReset,
  initialCount
}) => {
  return (
    <div>
      <p>
        現在のカウント数：{count}
        <br />
        countの初期値：{initialCount}
      </p>
      <button onClick={countIncrement}>Increment</button>
      <button onClick={countDecrement}>Decrement</button>
      <button onClick={countReset}>Reset</button>
    </div>
  );
};
```

```js:Hello.js
import "./styles.css";

export const Hello = ({ name, handleChangeName, initialName }) => {
  return (
    <div>
      <p>
        Hello, <b>{name} !!</b>
        <br />
        nameの初期値： <b>{initialName}</b>
      </p>
      <input type="text" onChange={handleChangeName} />
    </div>
  );
};
```


```js:App.js
import React, { useState } from "react";

// 名前付きインポート
import { Hello } from "./Hello";
import { Counter } from "./Counter";

const INITIAL_COUNT = 0;
const INITIAL_NAME = "JavaScript";

export default function App() {
  // useState初期化
  const [count, setCount] = useState(INITIAL_COUNT);
  const [name, setName] = useState(INITIAL_NAME);

  // countボタンのイベントハンドラ　setCount((c) => c+1) で引数に現在の値が入ってくる
  const countIncrement = () => setCount((prevCount) => prevCount + 1);
  const countDecrement = () => setCount((prevCount) => prevCount - 1);
  const countReset = () => setCount(INITIAL_COUNT);

  // テキストボックスのイベントハンドラ
  const handleChangeName = (e) => {
    setName(e.target.value);
  };

  return (
    <>
      <Counter
        count={count}
        countIncrement={countIncrement}
        countDecrement={countDecrement}
        countReset={countReset}
        initialCount={INITIAL_COUNT}
      />
      <Hello
        name={name}
        handleChangeName={handleChangeName}
        initialName={INITIAL_NAME}
      />
    </>
  );
}
```
記事ですべてのバージョンの合計数を取得する


累積カウントを使うみたいです。(でもよく分からん。レポートではできなかったように思う。)

[Article Views](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Cg1Cb)

+ [ナレッジ記事の閲覧に関するレポート](https://community.servicenow.com/community?id=community_blog&sys_id=ba4e66addbd0dbc01dcaf3231f9619b4)

誰がナレッジ記事を開いたかに関する指標を収集するために、次の 2 つのレポートを実行します。  

+ 部門ごとにグループ化された特定のナレッジ記事をユーザーが表示するリスト レポート
+ 毎月の部門ビューの傾向レポート

次のことができるように、部門ごとにデータをグループ化することにしました。

+ これらの測定基準を部門マネージャーと共有して、直属の部下の誰がトレーニング コンテンツを表示しているか、または表示していないかを把握します。
+ どの部門が最も頻繁に記事を開いているかを調べます (その理由について、経験に基づいた推測を行います)。

**List Report**
このリスト レポートは、X か月間で次のことを示しています。

+ 記事を開いたユーザーとその日付。
+ ユーザーを部署名でグループ化します。ユーザーが記事にアクセスするたびに新しいレコードが作成されることに注意してください。したがって、ユーザーが記事を数回開くと、そのユーザーに対して複数のレコードが作成されます。
+ 総ナレッジ ビュー。

最終レポートは次のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c914324a-ff5c-9e08-3b19-849303d7f8ab.png)


1. レポート > 新規作成
2. 名前: レポートの内容を説明するわかりやすい名前を選択します
3. タイプ:リスト
4. 表: kb_use
5. グループ化:部署
6. 表示対象: レポートを表示できるグループまたはユーザーを指定できます
7. [フィルター条件を追加] ボタンをクリックします。
8. 次のフィルターを追加します。
+ 記事| です| < KB番号>
+ オプションのフィルター: User.Department | ではない| <あなたのチーム名>
このフィルターを使用して、外れ値のレコードを削除することにしました。たとえば、私のチームは通常、学習目的ではなく、コンテンツの正確性のために記事をレビューするため、部門を削除します。
+ オプションのフィルター:作成済み| に| <日付オプションを選択>
このフィルターを使用して、記事がいつ表示されたかのパラメーターを絞り込みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9ab9252e-c4ce-9f0f-223d-a271f2489492.png)


**Trend report**
このトレンド レポートは、X か月間で次のことを示しています。

+ 記事が毎月何回閲覧されているか。
+ 毎月、どの部門からのビューが何パーセントであるか。
+ 記事を閲覧した各部門のユーザー数。
最終レポートは次のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/29139cb8-ffd3-8f64-e9e0-a393b48597fb.png)


1. レポート > 新規作成            
2. 名前: レポートの内容を説明するわかりやすい名前を選択します
3. タイプ:トレンド チャート
4. 表: kb_use
5. グループ化:部署
6. 表示対象: レポートを表示できるグループまたはユーザーを指定できます
7. トレンド フィールド: 1か月ごとに作成
8. 集計:カウント
9. [フィルター条件を追加] ボタンをクリックします。
10. 次のフィルターを追加します。

+ 記事| です| < KB番号>
+ オプションのフィルター: User.Department | ではない| <あなたのチーム名>
このフィルターを使用して、外れ値のレコードを削除することにしました。たとえば、私のチームは通常、学習目的ではなく、コンテンツの正確性のために記事をレビューするため、部門を削除します。
+ オプションのフィルター:作成済み| に| <日付オプションを選択>
このフィルターを使用して、記事がいつ表示されたかのパラメーターを絞り込みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8eba067f-d1c9-9e8c-79c2-b735e03138ab.png)


# ナレッジ記事の閲覧数を測定する方法
これらは素晴らしいレポートです。私は、SaaS のレポートおよび視覚化ツールである Explore Analytics を使用して、これらのレポートをさらに一歩進めることにしました。

リスト ビューでは、複数レベルのピボット機能を利用して、部門別だけでなく、読者が読んでいる記事の種類別に読者を分類しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/1712f984-f385-cc57-a7f9-415af2aca3a7.png)
tqdmのインポートミス

# はじめに

for文などで重めの処理や、Pytorchでの学習などの進捗管理のために使うことも多いtqdm。

importするときによくミスるのでメモ。

Pytorchでの学習を回す時を例に挙げます。

# 環境
python 3.9.5
macOS 12.0 beta

# ダメな例
```python
import tqdm

for inputs, labels in tqdm(train_dataloader):
# ---以下学習処理----
```

これだと`'module' object is not callable`とエラーが出る。モジュールは関数として呼べないよって意味。

# 良い例
```python:①
from tqdm import tqdm

for inputs, labels in tqdm(train_dataloader):
# ---以下学習処理----
```

```python:②
import tqdm

for inputs, labels in tqdm.tqdm(train_dataloader):
# ---以下学習処理----
```

これでうまくいった。

# まとめ
モジュールと関数の違いをちゃんと理解する。

でもモジュール名と関数名が一緒なのややこしい...。
スカンクワークとは、本来やるべき業務以外の自主的活動

## スカンクワークとは

> https://en.wikipedia.org/wiki/Skunkworks_project (翻訳)
> スカンクワークスプロジェクト（''skunkworks project''）とは、通常、少人数でゆるやかに構成されたグループによって開発されるもので、主に革新のためにプロジェクトを研究・開発するものである。この言葉は一般的に技術プロジェクトを指し、ロッキード・マーチンの先進開発プログラム（旧ロッキード先進開発プロジェクト）の公式な別名であるスカンクワークスが起源となっている。

> **スカンクワークスプロジェクトは、高度な自主性を持って官僚主義にとらわれずに運営されていることが多く、高度なプロジェクトや秘密のプロジェクトに取り組むことを使命としている。これらのプロジェクトは、開発が成功した場合には、通常のプロセスに従って後から製品が設計されるという理解のもと、秘密裏に行われることが多い。**


### 日本語解説

https://www.weblio.jp/content/%E3%82%B9%E3%82%AB%E3%83%B3%E3%82%AF%E3%83%AF%E3%83%BC%E3%82%AF

> ・スカンクワークとは、社員が本来やるべき業務以外の**自主的活動**をいう。
> ・社員に業務外の自主的活動を自由に行なわせることで、**新規事業の芽を見出したり、イノベーションが生まれたりすることを狙いとしている。**

## 例えば15%カルチャー

https://www.3mcompany.jp/3M/ja_JP/careers-jp/working-at-3m/diversity-and-inclusion/3MerCareer-FShield/


## 例えば20%ルール

[Google Japan Blog: 20%ルールの話](https://japan.googleblog.com/2007/07/20.html)

> Google には、20% の時間は自分の好きなことを自由にやっていてもよい、という「20%ルール」があります。 Google News や AdSense などの製品はこの 20%ルールが元となって生まれています。

### 但し...

[The '20% Time' Perk at Google Is No More - The Atlantic](https://www.theatlantic.com/technology/archive/2013/08/20-time-perk-google-no-more/312063/)
[Googleが今も実践する｢20%ルール｣で、未来の自分に投資するメリット | ライフハッカー［日本版］](https://www.lifehacker.jp/2020/11/223428google-says-it-still-uses-20-percent-rule-you-should-totally-copy-it.html)

> エンジニアの中には、これを｢120%ルール｣と称する人もいました。つまり、執務時間の一部を自由な発想の時間に置き換えるのではなくて、通常業務に加えてさらに20%多く時間を使うという意味です。


## まとめ

「スカンクワーク」そのものは業務時間内にやるとか、やらないとか、そういった決まりはない。 **= 「スカンクワーク」を業務時間内にやることを認めてくれている、推奨してくれている会社はすばらしい。**

ということを理解し、金曜日は「スカンクワーク」ができる日だと良いなあなどと思いながらまとめた。冒頭の通り「これらのプロジェクトは、開発が成功した場合には、通常のプロセスに従って後から製品が設計される」べきらしいので、会社にこの仕事を認めさせるまで頑張るという意思を持てという意味でも、「スカンクワーク」という言葉を大事にしたい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/7b914095-9ea3-24f9-8066-5131aa2d088a.png)
[Google Japan Blog: 20%ルールの話](https://japan.googleblog.com/2007/07/20.html) ではこんな社内ツールの小さな改善もこの「20%」のところからうまれたらしい。

以上参考になればさいわいです。
Github Issuesをキレイに外部公開するサービス「2go」作ってみた

# はじめに
今回初めて個人開発で作ったサービスを公開します。今までも何回かトライしていたのですが、なかなか公開までに至らないうちに、なにか問題にぶちあたったり、時間がかかりすぎて情熱が冷めてしまったりしていたので、今回はまずはスモールスタートで公開して改善していくことを心がけました。大体今回の公開まで、開発を始めてから1ヶ月程度になります。毎日朝4時半に起きて、子どもたちが起きる7時過ぎまでを開発時間として取り組んできました。
![2go.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997184/29cebc30-4af5-8856-afaa-6d9a4705ca3d.png)
# どんな人向け？
自分で作っているサービスの開発ロードマップをユーザーに公開するために、都度ブログを書いたりするのも大変ですよね。もし、自分のサービスのソースコードをGithubで管理していたとして、Github Issuesを見せるとしてもGithubに馴染みのない人にとっては読みにくいですし、外に出すサービスであればあるほど、Githubのレポジトリは非公開になっていると思います。これをなんとかできないかなと思いました。
![lp_issues.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997184/e3d792bd-935d-13c4-3f90-15c521f5059c.png)

# どんなサービス？
まずはこちらを見てください。
https://2go.plus/nice2h/2go/roadmap
このようにGithubのレポジトリ内のIssueをMilestone区切りにして、Githubに馴染みのない人にも見やすいロードマップサイトを公開するサービスです。もちろん、非公開のレポジトリを公開設定にすることなく、ロードマップだけを外部公開することができます。
![lp_roadmap_pc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997184/fa971979-fe2f-549b-4803-87de654b4aca.png)
Githubアカウントでログインすると、以下の設定画面になります。レポジトリを選択して、どのMilestoneを共有するかをチェックして保存します。すると、自動的にロードマップサイトのURLが生成されるので、こちらにアクセスすれば常に最新のロードマップを見ることができます。このURLをシェアすれば、多くの人にあなたのサービスのロードマップを簡単にキレイに公開できるわけです。
![lp_github_setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997184/a1b9be9c-3053-c8a7-2d30-6ddd5afa8a95.png)

Milestoneを今まで使っていな方は、Milestoneを作成して、Issueを割り当てればロードマップを整理することができます。また、Labelを活用している方もいらっしゃると思いますので、Milestoneの中のLabelでIssueをフィルタすることもできます。これらを駆使することで、Bugは見せずにenhancementだけ表示するなどのことも可能です。
今後の予定としては、今はMilestone基点で表示しているところを、Labelベースで表示できるようにもしたいと思っています。その他は、まさに上記のURLを参考にしていただければ、いつも最新です。
# どんな技術を使ってる?
企業での開発経験はないので、全て自己流です。書籍やWebサイトを中心に勉強して開発しながら学んできました。念の為、利用している技術は以下のとおりです。
- Laravel : APIとBlade（SSRはやってみたことあり）
- Vue3 : フロントエンド（今回初挑戦）
- Tailwindcss : デザイン（Bootstrapからの脱却）
- Docker : これらの開発環境と、本番でもDocker利用（いずれ分割予定）
- Cloud : Conoha VPS(インフラに時間を掛けたくなかった)
# 気になっていること（随時追加予定）
- 開発環境はLaravel sailを使いましたが、本番は自前でdocker-compose.ymlを使いました。このあたりのコンテナの構成をどのようにしているか気になりました（本番でもsail使う？）
- 本番環境にコードをpullしてからnpm run prodしてbuildが終わるまでにラグがあり、この間は使えない機能が出てしまったりするが、このあたりをみなさんはどのように工夫しているか？
- DBについては、どこまでレコードを暗号化するか。検索機能などとのトレードオフになると思われるが。。
# 今後は？
現在alphaフェーズですが、alphaとしてもう1段階リリースの予定があります。多くの人に使っていただき、Feedbackをいただきながら改善して、開発経験を増していきたいと思います。また、今回の個人開発は最初から海外も同様の問題を抱えていると思ったので、最初から英語圏も視野に入っており、今の所すべてのUIは英語にしています。以下の英語Twitterアカウントも作成して、情報発信していこうと思っています。

https://twitter.com/2go_plus

もちろん、日本語のTwitterは私の今まで通りのアカウントを利用していく予定です。

https://twitter.com/jnakajima1982
ぜひGithubアカウントでログインして試していただき、ご感想・ご指摘をいただければと思います！
拡張子の「.iso」とは？

#拡張子の「.iso」とは？
- ISOイメージ（ISOイメージファイル、イメージファイルとも言う）を表す拡張子のこと

#ISOイメージとは？
- CDやDVDの全ての中身を１つのファイルの形にしたもの

- 名前の由来は国際標準化機構（ISO）が 定義したことからきている

- ネット上でOSを配布する際に使われていたりする(※)

※ISOイメージ形式のOSをUSBメモリ（またはCD/DVD）に入れて、起動ドライブ（ブートUSB、ライブUSBとも言う）を作成して使用する
Next.jsでページ内リンクを実装する

## react-scrollのインストール
>https://www.npmjs.com/package/react-scroll


```shell
npm install --save-dev react-scroll
```



```jsx
[使用例]
//test.tsx
import {Link as Scroll} from "react-scroll"

export default function Layout():JSX.Element {
    return (
        <div>
            <header>
                <nav>
                   <Scroll to="skills" smooth={true}
                                            duration={600} offset={-30}>skills</Scroll>
                </nav>
           </header>
            <main>
               <div id="about">ここにコンテンツを書く</div>
               <div id="skills">ここにコンテンツを書く</div>
               <div id="values">ここにコンテンツを書く</div>
               <div id="future">ここにコンテンツを書く</div>
            </main>
        </div>
)}
```
### option解説
- to="遷移先のid名"
- smoothをつけるとスムーズに移動するようになる。
- durationは移動時間
- offsetで到着位置をずらせる




```jsx
//[応用例]
───────
```js
[応用例]
↑↑↑↑↑↑↑ 編集リクエストの内容

export default function Layout() {
{/* map関数で取り出してタグを生成する。 */}
    const navItem = ["about", 'skills', 'values', 'future']
    return (
        <div>
            <header>
                <nav>
{/* map関数で取り出してタグを生成する。 */}
                    <div className="space-x-6 md:space-x-8">
                        {navItem.map((item, index) => {
                            return (<Scroll to={`${item}`} className=" uppercase" smooth={true}
                                            duration={600} key={index} offset={-30}>{item}</Scroll>)
                        })}
                    </div>
                </nav>
           </header>
            <main>
               <div id="about">ここにコンテンツを書く</div>
               <div id="skills">ここにコンテンツを書く</div>
               <div id="values">ここにコンテンツを書く</div>
               <div id="future">ここにコンテンツを書く</div>
            </main>
        </div>
)}
```
変数名、関数名の付け方まとめ

##はじめに
※あくまで参考程度にとどめてください。会社独自のルールで変数をつけている場合があるのでその場合はそちらに従うようにしてください。

サンプルコードはjava Script, htmlで書いてます。

##命名規則の種類

javascriptやPHPにおいて関数や変数、HTMLなどでもclass名など、命名規則を用いる場面は多々あります。この際に**命名規則がなく、バラバラになっていると可読性が悪くなることで改修コストが増えたり、バグの原因になる可能性も出てきます。**

そういったことを防ぐためによく使われるのが以下の命名規則になります。主に単語間の記法が異なるのり、それぞれ呼び方も覚えておいてください。


#【キャメルケース】
単語の先頭を大文字にする命名規則です。全ての単語の先頭を大文字にするのがアッパーキャメルケースもしくはパスカルケースと呼ばれています。

先頭の単語だけ小文字にするのがローワーキャメルケースと呼ばれます。

両方とも主にPHPやJSなどの関数でよく使われています。


```js
const CamelCase = "CamelCase　これはアッパーキャメルケース";
const camelCase = "camelCase　これはローワーキャメルケース";
```

#【スネークケース】
単語の間をアンダーバーで繋ぐ命名規則です。
主にDBなどで使用されることが多く、HTMLのclassとかにも使われています。

```html
<h1 class="snake_case">snake_case</h1>
```

#【ケバブケース】
単語の間をハイフンで繋ぐ命名規則です。
HTMLのclassや、ファイル名などでよく見かけます。

```html
<h1 class="kebab-case">kebab-case</h1>
```

##どれをどこで使うべきか？

命名規則によってパフォーマンスが上がるなどといったことはそんなにありませんが、可読性をアップしたり、ルールを統一することで複数人での開発をスムーズにすることが目的でこれをすることによって関数名を見るだけで何となくやってることがわかったりします。

ちなみにグーグルのがいどらいんでは単語の間をハイフンで繋ぐケバブケースが推奨されているようです。HTMLのclass名においてはWordPressなどのフレームワークでもケバブケースが採用されているのが確認できます。

また、プログラミングの関数などではキャメルケースが多く、フレームワークなどでよく見かけます。DBのテーブル名などにはアンダーバーを使ったスネークケースが使われていることが多いです。

なので、以下のように使い分けるといいかと思います。

**キャメルケース　→　プログラミングでの関数や変数**
**スネークケース　→　DBなどで扱う値**
**ケバブケース　→　HTMLのclass名**

もちろん、最初に記述した通り、会社やチームごとに決められている命名規則が違ったりするので必ずしも、正解というのはあませんので、開発チーム内の命名規則を見極める必要があります。

##変数名は使用されている状況に合わせて具体性を決める

適切な変数名は使用される状況によって変わります。

例えばユーザーIDを処理するときに、プログラムないで扱うIDが他になければ

```js
const id  = req.body.id;
```

で十分ですが、他にもIDがある場合は、

```js
const userId = req.body.user_id
```

としないと、どのIDなのかわからなくなります。

##関数名は機能を明確にする。
「[うまくメソッド名を付けるための参考情報](https://qiita.com/KeithYokoma/items/2193cf79ba76563e3db6)」はかなり参考になるので見てみてください。

変数よりは入力する回数がかなり少なくなり、エディタで補完してくれるので多少長くても大丈夫です、なるべくわかりやすく簡潔に関数名をつけましょう。

```js
//アカウント作成
const createAccount = () => {
 // 処理
}

//アカウント更新
const updateAccount = () => {
 // 処理
}

//アカウント削除
const deleteAccount = () => {
 // 処理
}
```
VCに誰かが入った時に通知してくれるbotを作る【Discord/Java】

## はじめに
身内用に誰かがDiscordのVCに入ったときに通知してくれるbotを作ったので覚え書き。

## 環境
- Java
- Gradle
- Javacord

## Javacordの導入
[Javacord](https://github.com/Javacord/Javacord)はDiscord botをJavaで開発するためのライブラリです。
以下のようにgradleファイルに記述します。

```gradle:gradle.build
repositories { mavenCentral() }
dependencies { implementation 'org.javacord:javacord:バージョン' }
```

## Discord botアカウントの設定
https://qiita.com/1ntegrale9/items/cb285053f2fa5d0cccdf

こちらとかを参考にしつつbotを作成する。

## ログインする

```java
        DiscordApi api = new DiscordApiBuilder()
                .setToken("ここにbotトークンを入れる")
                .login().join();
```

botトークンに関しては直接記述したり、環境変数に入れて`System.getenv().get("TOKEN")`とかで取得すると良いと思います。

## VCに誰かが入ったときを検知する

```java
        api.addServerVoiceChannelMemberJoinListener(event -> {});
```

`addServerVoiceChannelMemberJoinListener`はサーバー上の誰かがVCに接続したときに呼ばれます。
ラムダ式を用いて`event`にイベント情報を格納します。

## メッセージを送る

```java
            String user = event.getUser().getName();
            String channel = event.getChannel().getName();

            if (event.isMove()) return;

            new MessageBuilder()
                    .append(user, MessageDecoration.UNDERLINE)
                    .append(" が ")
                    .append(channel, MessageDecoration.BOLD)
                    .append(" に入ったよん")
                    .send(api.getTextChannelsByName("通知先のチャンネル名").iterator().next());
```
`user`にVCに接続した人の名前、`channel`に接続したチャンネル名を格納します。
ユーザが移動する度にメッセージが送られるとうるさいので`isMove()`の際は処理を終了します。
`MessageBuilder`を生成してメッセージを作り、送信します。
`MessageDecoration`をパラメータに指定すると文字を太字にしたり下線を引いたりできます。
`append`で文字列の結合、`send`で指定先のテキストチャンネルにメッセージを送信します。
`getTextChannelsByName()`を用いて名前でチャンネル名を検索し、検索結果のコレクションの先頭のチャンネルを取得します。

メッセージのところは自分の好きなように編集すると良いと思います。

## 動かす
プログラムを実行してDiscordサーバーで動かします！
![5df9710685a931d75128ed4b012d1f75.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237947/bd8380e1-5ad0-8769-56a7-59161fe7bb90.png)
botが通知メッセージを送ってくれます。

## おわりに
このbotを導入したら作業VCに人が集まりやすくなりました。
VCに入った時に通知があれば気づきやすいですからね。

[最終的なコード](https://github.com/AInine9/WhoJoinedBot)を貼っておきます。

## 参考文献
https://qiita.com/1ntegrale9/items/9d570ef8175cf178468f

https://qiita.com/1ntegrale9/items/cb285053f2fa5d0cccdf

https://javacord.org/wiki/

https://docs.javacord.org/api/v/3.3.2/overview-summary.html
【TypeScript】jestでioredis-mockを正しくインポートする


# はじめに

[`ioredis`](https://github.com/luin/ioredis)はNode.jsにおける主要なRedisクライアントパッケージの一つです。
単体テスト等で、Redisサーバーに実際にアクセスすることなく実行するために`ioredis`をモック化したい場合には、[`ioredis-mock`](https://github.com/stipsan/ioredis-mock)を使うことができます。

TypeScriptでは単体テストフレームワークとして[`jest`](https://jestjs.io/ja/docs/getting-started)を使用することが多いと思いますが、`jest`で`ioredis-mock`を使用する際には、そのインポート方法を誤ると実行時にエラーが発生してしまします。

私はこれに引っかかってしまったので、本記事では、TypeScript+`jest`を使用している環境において、`ioredis`の型情報を利用できる形で`ioredis-mock`をインポートする際の、正しい方法と誤った方法、そのエラー内容についてまとめています。

# 検証環境

- Node.js: 14.17.0
- TypeScript: 4.3.5
- ioredis: 4.27.7
- ioredis-mock: 5.6.0
- jest: 27.0.6

# 正しい方法

`ioredis-mock`公式リポジトリのREADME[^3]に記載されている方法です。
ちゃんとREADMEを読んで素直にこの方法に従わなかった自分を恨みます。

```ts
import Redis from 'ioredis';
jest.mock('ioredis', () => require('ioredis-mock/jest'));
```

# 誤った方法1

公式のGitHubにある型定義の利用についてのIssueに書かれている方法[^4]です。
`jest`で使うと後述する特定の状況でエラーが発生します。

```ts
import Redis from 'ioredis';
const RedisMock: typeof Redis = require('ioredis-mock');
jest.mock('ioredis');
```

エラーの内容は以下の通りです。

```log
TypeError: Cannot read property 'map' of undefined
```

このエラーは特定のコマンド実行時に発生します。全て調べたわけではないですが、`hset`等のHash系のコマンドで発生することが多いです。
例えば、hsetコマンドを利用した以下のコードで発生します。

```ts
const redis = new RedisMock();
await redis.hset('aa', 'bb', 7);
```

# 誤った方法2

GitHubのIssueに書かれている方法[^4]と公式リポジトリのREADME[^3]に記載されている方法を組み合わせてしまったものです。
実行時に上記コードにあるインポート部分でエラーになります。

```ts
import Redis from 'ioredis';
const RedisMock: typeof Redis = require('ioredis-mock');
jest.mock('ioredis', () => require('ioredis-mock/jest'));
```

エラーの内容は以下の通りです。

```log
TypeError: Cannot read property '_transformer' of undefined
```

[^3]: [ioredis-mockのjestでのセットアップ（公式リポジトリ）](https://github.com/stipsan/ioredis-mock#configuring-jest)
[^4]: [Are typings available?](https://github.com/stipsan/ioredis-mock/issues/661#issuecomment-733941657)
ディクショナリ型のメソッドまとめ　(Python ver.)

### このページについて
ディクショナリ型のメソッドをまとめたページです
必要に応じて、順次更新
###■ dict.get()
###**指定したキーに対応する値を取り出す**

```python:get_example.py
animals = {'1':'dog','2':'cat','3':'rabbit'}
print(animals['2'])
#cat
```

###■ dict.items()
###**→キーと値を取り出す**

```python:items_example.py
score = {'English':70, 'Math':65, 'Japanese':85}
for key, value in score.items():
    print(key, value)

#English 70
#Math 65
#Japanese 85
```

###■ dict.keys()
###**→キーの一覧を返す**

```python:keys_example.py
score = {'English':70, 'Math':65, 'Japanese':85}
print(score.keys())
#dict_keys(['English', 'Math', 'Japanese'])

for k in score.keys():
    print(k)
# English
# Math
# Japanese
```

###■ dict.pop()
###**→指定したキーと値を削除する**

```python:pop_example.py
fruits = {'apple':15, 'banana':5, 'orange':10}
fruits.pop('banana')
#5
print(fruits)
#{'apple': 15, 'orange': 10}
```

###■ dict.setdefault()
###**→値を取り出す**

```python:setdefault_example.py
fruits = {'apple':15, 'banana':5, 'orange':10}
fruits.setdefault('grape':20)
print(fruits)
#{'apple':15, 'banana':5, 'orange':10, 'grape':20}
```

###■ dict.values()
###**→辞書の値の一覧を返す**

```python:values_exmaple.py
score = {'English':70, 'Math':65, 'Japanese':85}
print(score.values())
#dict_values([70, 65, 85])

for k in score.values():
    print(k)
#70
#65
#85
```
クラス名を取得するExtension

タイポ対策のためにクラス名を取得したいと思ったときに、いろいろ方法があったので残しておきます。

# 実装

```swift
import Foundation

extension NSObject {
        
    // from class
    class var className: String {
        return String(describing: self)
    }
    
    // from instance
    var className: String {
        return String(describing: type(of: self))
    }
    
}
```
上のやつがクラスから呼ばれるやつで、下のやつがインスタンスから呼ばれるやつです。
``NSObject``というのはよく理解していないのですが、ほとんどのクラスの継承元となっているクラスで、強いて言うならルートクラスみたいなやつです。

# 挙動

```swift
print(UIView.className)
// "UIView"が出力される

let myLabel = UILabel()
print(myLabel.className)
// "UILabel"が出力される
```

# 応用例

```swift
    static let identifier = HistoryDateCell.className
```
cellのidentifierを登録するとき等に便利です！

<br>
<br>
<br>

他にも、インスタンス名とかファイル名とか取得する方法ってあるんですかね
Rails Ransackを使った検索機能

#ransackとは
ransackとは***検索機能を実装するためのツール***です。


#ransack導入

```Gemfile

gem 'ransack'

```
その後

```
$ bundle install
```
で導入できます。

#routes.rbに追加

```routes.rb

Rails.application.routes.draw do
     
      #省略
　　　　　　　　　　collection do
　　　　　　　　　　　get 'search'
    end
  end
end

```
　get 'search'をルーティングに追加します。
コントローラーのアクション以外を使う時はcollection doを使うみたいです。

#コントローラーにsearchアクションを追加
検索機能を取得するためにはprivate以下にメソッドを追記し、before_actionで
呼び出します。


```users_controller.rb

class UsersController < ApplicationController
     
     #省略
  before_action :set_q, only: [:index, :search]

  def index
    @users = User.all
  end


#省略


　　　def search
    @results = @q.result
  end



　　　　def set_q
    @q = User.ransack(params[:q])
  end


　　　　　　　　private

    def set_q
    @q = User.ransack(params[:q])
  end


    #省略

end

```

*下の文は下の資料から引用します。

⚫︎***params[:q]***  この後に作成するビューファイルから送られてくるパラメーター
⚫︎***ransackメソッド*** 送られてきたパラメーターを元にテーブルからデータを検索するメソッド
⚫︎***resultメソッド*** ransackメソッドで取得したデータを ActiveRecord_Relationの
オブジェクトに変換するメソッド



#キーワード検索方法

```index.html.erb

<%= search_form_for @q do |f| %>
  <%= f.label :name, "Keyword" %>
  <%= f.search_field :name_cont %>
  <%= f.label :job_eq, '仕事' %>
  <%= f.search_field :job_eq %>

  <%= f.submit "検索" %>
<% end %>

```
<%= search_form_for @q do |f| %>〜<% end %>の間のコードが検索フォームです。

#いろいろな検索機能の種類

上のキーワード検索以外にも
***数値の対象検索***、***複数の選択検索***などもあるみたいです。
他の検索機能は下の資料が詳しいのいで確認してください。

#よく使うメソッド
下のメソッドがよく使うみたいです。

***[検索したいカラム名]_eq***             ***完全に一致するとき***
***[検索したいカラム名]_not_eq***	      ***完全に一致しないとき***
***[検索したいカラム名]_matches***	      ***一部が一致するとき***
***[検索したいカラム名]_does_not_match***	***一部が一致しないとき***

他にもたくさんあるので下の資料から調べてみてください。




⚫︎参考資料
https://pikawaka.com/rails/ransack
https://qiita.com/nojinoji/items/e1b174220da8c81a1756
Postman: フォルダ内のリクエストをアルファベット順ソートする

現時点、Postman自体にはその機能が無く、GitHub issueに要望が上がっている。
[こちらのコメント](https://github.com/postmanlabs/postman-app-support/issues/5222#issuecomment-845157470)にあるように、Collectionをエクスポートしてnpmモジュールを使ってソート、インポートで希望通りにソートできた。

```console
$ npx @matthewlein/postman-collection-sorter ./path/to/your/API.postman_collection.json
Sorting collection file:  ./path/to/your/API.postman_collection.json
Sorting Successful!
Sorted collection saved to: ./path/to/your/API.postman_collection.sorted.json
```
個人的なheroku関係のブックマークリスト

- herokuコマンドがターミナルを起動させる度に使えなくなる

https://song-of-life.hatenablog.com/entry/2019/09/23/122554

- cloud9からherokuへのdeploy方法
(画像の扱いはかなりのお金がかかります)

https://note.com/ya_jp/n/na1660348a358

- S3 + Laravel + herokuで画像アップロードまとめ【忙しい人のため用】

https://qiita.com/nakasan773/items/9436e9b1c60831120aba

- Herokuにデプロイしたら500 Server Errorが出た

https://qiita.com/mumucochimu/items/f233d6f6347747dde7f2

- LaravelをHerokuにデプロイするまでに最低限やる事。

https://mrkmyki.com/laravel%E3%82%92heroku%E3%81%AB%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%99%E3%82%8B%E3%80%82
競プロ典型90問　002 - Encyclopedia of Parentheses

#問題
[競プロ典型90問　002 Encyclopedia of Parentheses](https://atcoder.jp/contests/typical90/tasks/typical90_b)

#解法


以下の2つを主に考えてコードを書きました。

- 再起関数を使い長さNになるまで文字を追加していく。
- 正しいカッコ列の条件を外れた場合、文字を追加しない。

####正しいカッコ列の条件

まず、正しいカッコ列の条件を考えたところ、以下の2つになりました。

1. カッコ列を左から見て行った時に`")"`の数が`"("`を超えないこと。
1. カッコ列の`"("`の数と`")"`の数が等しいこと。

ここで長さNのカッコ列を全探索して、全てにおいて上記の判定をしても良いのですが、大変そうだなぁと思ったのでもう少し考えてみました。

2の条件から以下の2つがわかります。

1. Nが奇数の場合正しいカッコ列は存在しないこと。
1. カッコ列を左から見て行った時に`"("`の数が`N//2`を超えないこと。

ということで、空の文字列から1文字ずつ追加してカッコ列を作る際に、以下の2つを条件判定しながら追加していけば正しいカッコ列が作れるのではないかと思いました。

- `"("`を追加する際は`"("`の数が`N//2`を超えないこと。
- `")"`を追加する際は`")"`の数が`"("`の数を超えないこと。

####再起関数

上の条件がわかったところで再起関数を使えばあとは簡単にコードが書けるのではないかと思いました。

再起関数とは、「ある関数の中で自分自身を呼び出す関数」のことです。

<details><summary>例</summary><div>
例えば1からNまでを掛け算した結果を求めたい場合を考えます。
これは、1からN-1までをかけた結果にNを掛ければよいですね。
そして、1からN-1までを掛け算した結果を求めたい場合には1からN-2までを掛け算した結果にN-1をかければ良いです。
というふうにこれを1までやっていくのが再起関数の考え方です。

~~~python3
N = int(input())

def saiki(i):
    if i == 1:
        return 1
    else:
        return saiki(i-1)*i

print(saiki(N))
~~~
</div></details>

#ソース

今回カッコ列の1つ目は必ず`"("`であるため、呼び出す際に引数に`"("`を渡しています。
また、最後は必ず`")"`であるため、作っている文字列の長さがN-1になった時点で最後に`")"`を追加して出力しています。

~~~python3
N = int(input())

if N%2 == 1:
    print()
    exit()

def addChar(str,numL,numR):
    if numL+numR == N-1:
        print(str+")")
        return
    else:
        if numL < N/2:
            addChar(str+"(",numL+1,numR)
        if numL - numR >0:
            addChar(str+")",numL,numR+1)

addChar("(",1,0)
~~~

#最後に

公式の解法を見るとbit全探索で解けると書いてあり、全然違う方針でした。
bit全探索自体は調べてみてかなり有効な方法だと思ったのでまた勉強して、この問題もその通り書いてみようかなと思います。

今回は問題自体の難易度がそこまで高くなかったこともあり、プログラム自体は割とすんなりかけたと思います。(最初少し迷走して不安でしたが)
それだけに今回は記事を書いている時間の方がかなり長くなってしまいました。

もう少し記事の方もすんなり書けるようになればと思っているのですが、こっちはプログラミングと違って考え方が分かればすんなり書けるようになると言ったものでもなくて難しいですね。「ここの記述はいらない」や逆に「ここをもう少し詳しく書いた方が良い」などあれば参考にさせていただきますのでコメントお願いします。

以上、拙い記事ではありますが何かの参考になれば幸いです。
最後まで読んでいただきありがとうございました。
laravelでgmailを使ってのメール送信ができない(laravel Expected response code 250 but got code "530")

下記の記事を参考にgmailのサービスを使ってlaravelからパスワードリセットのメール等を送れるように試みました。

環境
IDE AWS cloud9
laravel6

設定は完了したものの所々でエラーに捕まったのでシェアします

https://qiita.com/hiro5963/items/df062ab19e8ceba4573f

#エラー
## 前提のcache等のクリア

 .envファイルを書き換えたら必ずcacheをクリアしましょう。クリアしないとenvファイルの内容が反映されません。

```
php artisan cache:clear
```

下記の記事を保存しておきましょう
https://qiita.com/Ping/items/10ada8d069e13d729701




## config/mail.phpの確認

  envファイルの内容はconfigファイルを経由して反映されます。
envファイルの内容によって変わります

例

```php:.env
MAIL_DRIVER=smtp
```

の場合には

```php:config/mail.php
'driver' => env('MAIL_DRIVER', 'smtp'),
```



```php:.env
MAIL_MAILER=mailgun
```

の場合には

```php:config/mail.php
'driver' => env('MAIL_MAILER', 'mailgun'),
```




## laravel Expected response code 250 but got code "530"のエラーが出た

下記の記事を参考にしました

https://stackoverflow.com/questions/42574375/laravel-expected-response-code-250-but-got-code-530

自分は

```
MAIL_ENCRYPTION=null
```

から

```
MAIL_ENCRYPTION=tls
```

に変えたら動きました

##メール認証メールのリンクをクリックすると403エラー

https://qiita.com/Takagi-Yuya/items/47e80036bf15bbd0e50c

##E-Mail Verificationを実装中にTarget class [App\Listeners\LogVerifiedUser] does not exist.
https://qiita.com/naohirofujita001/items/1e5825df28190edac619

#感想

このエラーを解消するだけで丸2日かかりました。
少しでも役に立っていただければと思います。
リスト型に利用できるメソッド (Python ver.)

##このページについて
・リストに使えるPythonのメソッドをまとめたページ
・必要であれば順次更新

##■ list.append(x)
###**→リストの末尾に要素を追加する**

```python:append_examle.py
fruits = ['apple','orange']
fruits.append('banana')
print(fruits)
#['apple','orange','banana']
```

####リストを追加した時の挙動
```python:append_example2.py
fruits = ['apple','orange']
fruits.append(['banana','kiwi'])
print(fruits)
#['apple','orange',['banana','kiwi']]
```

##■ list.count(x)
###**→リストでのxの出現回数を返す**

```python:count_example.py
number = [2, 0, 1, 1, 8, 1, 9, 3, 6, 7, 5, 1]
x = number.count(1)
print(x)
# 4
```

##■ list.extend(x)
###**→全ての要素を対象のリストの末尾に追加**

```python:extend_example.py
number = [1, 3, 5]
number.extend([7,9,11])
print(number)
#[1,3,5,7,9,11]
```

##■ list.index(x[, start[,end]])
###**→リストの要素を検索する**

```python:index_example.py
country = ['Japan', 'America', 'Australia', 'Korea']
country.index('Japan')
# 0
```

```python:index_example2.py
number = [0,1,2,4,1,1,0,2]
number.index(0, 2, 7)
# 6
```

##■ list.insert(i,x)
###**→指定した位置(i)に要素(x)を挿入する**

```python:insert_example.py
color = ['Blue','Green','Red']
color.insert(2,'Yellow')
print(color)
#['Blue', 'Green', 'Yellow', 'Red']
```

##■ list.pop(i)
###**→リストの中の指定された位置(i)にある要素をリストから削除する**

```python:pop_example.py
sushi = ['maguro', 'ika', 'sa-mon', 'ikura']
x = sushi.pop(0)
print(x)
#['ika','sa-mon','ikura']
```

##■ list.remove(x)
###**→リストの中からxと同じ要素を取り除く**

```python:remove_example.py
animals = ['dog', 'cat', 'rabbit']
animals.remove('dog')
print(animals)
#['cat', 'rabbit']
```

####複数削除はしてくれないみたい
```python:remove_example2.py
animals = ['dog', 'cat', 'rabbit', 'dog']
animals.remove('dog')
print(animals)
#['cat', 'rabbit', 'dog']
```

##■ list.reverse()
###**→リストの並び順を反転する**

```python:reverse_example.py
alphabet = ['a','b','c','d','e']
alphabet.reverse()
print(alphabet)
# ['e','d','c','b','a']
```
Rails初心者 「rails s -b 0.0.0.0」でサーバー立ち上げ時にエラーが起きた時の対処方法【自分用備忘録】

## この記事の対象
Railsをインストールし、アプリを作成して、ローカルサーバーを立ち上げ用としたら以下のエラーが返ってきた

```
Error: No such file or directory @ realpath_rec - /Users/アプリの保存場所/アプリ名/config/webpacker.yml (RuntimeError)
```

# RailsのバージョンによってはRailsの他にインストールが必要なパッケージがある
Rails6からという記事を見たが、、、以下の2つをインストールしなければサーバーが立ちあがらない

1. webpacker
1. yarn


## webpackerのインストール
```
rails webpacker:install
```

### もし「Yarn」がインストールされていなければ以下のエラーが出ます
```
Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/
Exiting!

```

## yarnのインストール [Homebrewを使用]

```
brew install yarn
```
→完了！！　[webpackerのインストールに戻る](## webpackerのインストール)


![スクリーンショット 2021-09-09 23.16.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1977965/65e59142-b06e-4d67-39fb-833d52ba1801.png)

## 「rails s -b 0.0.0.0」を起動
いかがでしょうか。

![スクリーンショット 2021-09-10 0.06.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1977965/bdda3521-8c05-a175-8370-8a8d50e04e27.png)
【Rails】DB上は文字列だけどモデルでは配列として扱いたい

# 環境情報

- Rails 5.2.6

# やりたいこと

ActiveRecord側ではintegerの配列で扱いたいが、DBにはカンマ区切りの文字列として保存したい  

# やりかた

fooというテーブルのfoo_idsをintegerの配列として利用したい

## テーブル作成

```ruby
create_table :foos do |t|
  t.string :foo_ids
end
```

## Coderクラス作成

activemodelのattributeの仕組み上、頻繁にdump,loadが呼び出されるので、バリデーションなども行う場合は要注意

```ruby
class IntegerArray
  def self.dump(object)
    return "" if object.blank?
    object.join(",")
  end

  def self.load(string)
    return [] if string.blank?
    string.split(",").map(&:to_i)
  end
end
```

## モデル作成

```ruby
class Foo < ApplicationRecord
  serialize :foo_ids, IntegerArray
end
```

## 確認

```shell
[10] pry(main)> foo = Foo.new                                                                                                                                                                          
[12] pry(main)> foo.foo_ids = [1, 2]                                                                                                                                                                      
=> [1, 2]
[15] pry(main)> foo.save!                                                                                                                                                                                 
   (3.2ms)  BEGIN
  Foo Create (2.7ms)  INSERT INTO `foos` (`foo_ids`) VALUES ('1,2')
   (7.3ms)  COMMIT
=> true
[16] pry(main)> Foo.first   
  Foo Load (2.8ms)  SELECT  `foos`.* FROM `foos` ORDER BY `foos`.`id` ASC LIMIT 1
=> #<Foo:0x00007fbfb7be5ae0 id: 3, foo_ids: [1, 33]>                                           
```

# serializeつかっていいの？

基本的に避けたほうが良いのは同意できるが、パフォーマンスなどの都合でどうしても正規化できない状況もあるのでトレードオフを考慮して使うべきだと思いました。（storeはまだ使い所がわかりません）  
また、具体的にどの処理が重いのか検証した記事が少なく、調べてみたいと思います。to be continued...

https://qiita.com/jnchito/items/68e91e9bf46f960a79e4

https://techracho.bpsinc.jp/baba/2013_08_12/12693

# 他の方法

1. 独自のActiveRecord::Type::Serializedを定義して、serialize毎再実装する（大変だが少しだけ最適化できる）
1. モデル側にintegerの配列として扱えるメソッド群を用意する（うまくmodule化すれば一番安定？）
1. composed_ofでValueObjectのように扱う