OmniAICreator/Qiita-1.07M huggingface dataset:
TextFormFieldをたくさん並べるfileをすっきりさせる

# TextFormFieldをたくさん使うアプリをつくっているので　

　違うのはHintTextとonChangedのところだけなのに、設定でやたらfileが長くなるのを避けたい。
　ということで、設定を独立させてみました。　
　サイズや色を一括で変えられます。もしそれにもバリエションがほしければ、変数を増やすか、classを分けたらいいと思います。でも、変数をあまり増やすと、すっきり感は減ってしまいますね。

```dart
import 'package:flutter/material.dart';

class Format extends StatelessWidget {
  final String hintText;
  final ValueChanged<String> onChanged;

  const Format({
    required this.hintText,
    required this.onChanged,
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      textAlign: TextAlign.center,
      decoration: InputDecoration(
        contentPadding: const EdgeInsets.all(5.0),
        hintText: hintText,
        hintStyle: const TextStyle(
            fontSize: 14,
            color: Colors.green),
        fillColor: Colors.lightGreen[100],
        filled: true,
        focusedBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(20),
          borderSide: const BorderSide(
            color: Colors.lightGreen,
            width: 2.0,
          ),
        ),
        enabledBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(16),
          borderSide: const BorderSide(
            color: Colors.lightGreen,
            width: 1.0,
          ),
        ),
      ),
      onChanged: onChanged,
    );
  }
}
```

## 使うときはたったこれだけ　

```dart
child: Format(
         hintText: "Your Hint Text",
         onChanged: (text) {変数名 = text;
                            },
                  )
```

ああ、すっきりした。
プロジェクト計画はどこまで詳細に立てるべきか？ 旅行になぞらえると？

何か月、場合によっては何年とかかるプロジェクトを、どのくらい先までを詳細に計画するかは、プロジェクト計画を立てるうえでのよくある悩みどころの一つでしょう。

# たとえ話

そこでたとえ話として、旅行の計画について考えてみます。

人生をするうえで旅行を大切に思う人は多いでしょう。
もし「死ぬまでにできるだけ多く旅行したい」という要求があったとします。

人生のQCDに対応する概念を次のように置きます：
- Q: 元気
- C: お金
- D: 時間

次に、典型的な人生をざっくり３つのフェーズに分けます：
- 若年：学生、ないし、仕事でも若手と呼ばれる
- 中年：仕事は中堅ないしベテラン、子育て真っ盛り
- 老年：仕事は引退し、子育ても終わっている

（この分け方がどれほど多くの人々を代表しているかは、ここでは置いておきます。）

すると、人生のQCDに対する典型的な制約事項は、次のように分析できます：

|     |元気         |お金          |     時間   |
|:---:|:------------:|:-----------:|:----------:|
|**若年** |ありあまる  | あまりない   | ありあまる |
|**中年** |ある    |ある            | あまりない |
|**老年** |あまりない|ありあまる     | ありあまる |


上記制約のもとでは、中年であれば旅行の計画は次のように立てられます：
- お金もあるし、体も動くので、中年は旅行に適している。
- ただし、いかに時間を工面するかが課題。
- どこに行くかは自由だが、体力が必要な目的地は、早めがいい
- 老年になるまでに行きたい目的地の数は決めておいた方がいい

# 結論

このたとえ話から、結論を次の通り導けます：
プロジェクト計画をどこまで詳細に計画すべきかは、 **プロジェクト制約(QCD)を明らかにすることで見えてくる**
【差が出る】駆け出しエンジニアも抑えておきたいデザインの4原則

# はじめに
「エンジニアに**デザインの知識なんて必要なの？**」
そう感じる方もいるかと思いますが、原則ゆえに汎用性が高く、活かせる場面は多いです。

## どんな時に活かせるか？
   * ドキュメント作成（ex. README, 構成図）
   * SlackやChatworkといったコミュニケーションツールでのメッセージ（**相手が読みやすい文章**を書ける）
   * フロントエンドの実装時に、デザイナーの人がどんな事を考えてデザインしたのかを考えられる

## デザインの4原則
では、さっそく。
1. **近接**
1. **整列**
1. **反復**
1. **コントラスト**

この4つになります。


こちらは、「ノンデザイナーズ・デザインブック」という本で紹介されている原則になります。
<img width="100" alt="ノンデザイナーズ・デザインブック" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186503/ffd2abca-7a77-9485-f906-b658b839d52f.png">

| *原則* | *説明* |
|:-----------:|:------------|
| **近接**| 関連するものをグループにする|
|**整列**|全体の配置を整える|
|**反復**|繰り返す|
|**コントラスト**|メリハリを出す|




## 原則を適用するとどうなるか？
誰が見ても意図が伝わりやすくなり、情報を認識しやすくなります。

### 具体例（webサイト）
弊社の[ホームページ](https://www.nuco.co.jp/)で、**デザインの4原則**がどのように適用されているか見てみます。

<img width="600" alt="top" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186503/a265e550-2bea-394f-72a5-b8107cc126d1.png">

| *原則* | *適用箇所の例* |
|:-----------:|:------------|
|**近接**|「システム開発」内で丸アイコン・タイトル・説明が近くにあり、かたまりを作っている。（枠はないが、間隔をあけることで実現）|
|**整列**|近接によって作られた1つのまとまりを、等間隔配置している。（画像認識, 音声解析, 自然言語処理）|
|**反復**|近接によって作られた1つのまとまりを3回繰り返している。ホームページ全体では、SERVICE, ABOUT, CONTACTが同じ構成で反復している|
|**コントラスト**|3色（白、黒、黄色）の色分け。文字の太さ。|

### 具体例（文章）
AとBの文章はどちらが読みやすいでしょうか？
#### A
仕様
ファイル名を引数で受け取り、特定の文字列が含まれていたらどういう種類のファイルかを出力してください。
‘txt’が入っていたら‘text’, ‘py’が入っていたら‘python’, ‘jpg’ か jpeg’が入っていたら‘image’

#### B
仕様
ファイル名を引数で受け取り、特定の文字列が含まれていたらどういう種類のファイルかを出力してください。
下記、特定の文字列とファイル種類の組み合わせです。
・txt      → text
・py       → python
・jpg, jpeg → image



## まとめ
改めて、後で読み返す可能性が高い文章などは、きれいに書いておいた方が良いな、と思った次第であります。
4原則は、カフェのメニューなど、日常生活の中でも適用されています。

「もしかして原則の〇〇では？」と考えてみると色々発見があるので、良かったらやってみて下さい。

## 最後に
弊社は未経験からエンジニアになった方が活躍している会社です。
未経験者の新卒・中途採用も実施していますので、ご興味ある方は[こちら](https://www.recruit.nuco.co.jp/)より。
とある検体のOEP(2)

後進のために 検体 と OEP (Original Entry Point) へ確実にたどり着くことが出来るロードマップを公開します。
このような記事は世にあまりなく画期的ではと自画自賛です。
マルウェア解析訓練において試行錯誤の手助けになればと思っております。

OEPを発見するコツ
・ループに入ったら出口にブレークポイント（以下BP）を仕掛けてF9
・F8で走りすぎたら，その場所にBPをしかけて次からはF7
・アクセス違反でOllyDbgが停止した場合の対処は，
　序盤は，走りすぎと判断して再スタート
　後半は，`shift+F9` で先に進ませる

# 検体

一昔前に流行したランサムウェア TeslaCrypt です。
SHA-1
8c5ce36e359c786a187cca8f73485ab5be57880c

https://www.virustotal.com/gui/file/f547a805cd0b963ab061b03d66e82cf63f11e27f1dd2528977c7d73fe7c1e572/details

# 使用したデバッガ
32ビットのWindows7環境だったので OllyDbg を使用

# 解析失敗の条件
F8で走りすぎて最後まで行くと，デスクトップに配置したテキストファイルの拡張子がvvvに変わる。
アクセス違反でOllyDbgが停止するのは，解析失敗ではない。

# 解析成功の条件
メモリ空間に `vssa` の文字が配置される。
※ vssadmin.exe delete shadows の一部

# 解析開始

### `再スタート`
004173B3 で止まってる

F8 で進める
`00417343` でF8すると `0012310D` アクセス違反まで走って止まるので，再スタート

### `00417343` にBP 止まったら F7 
`0040AD60` に入ってくる

フォントが茶色で表示される
FLD
FSTP
の山を越え，

ループの先にBPを仕掛けながら進める

00415DBCにBPを仕掛け，
今までBPとしていた00415DB7,00413EC4,00414017,00415D37などのBPを解除し進める

`00415EA3` でF8すると `0012310D` アクセス違反まで走って止まるので，再スタート

### `00415EA3` にBP 止まったら F7
`xxxx0048` に入ってくる　※xxxxは動かす度に変わるアドレス

ループの先にBPを仕掛けながら進める

`xxxx042A`　CALL EDX でF8すると `0012310D` アクセス違反まで走って止まるので，再スタート

### `xxxx042A` にBP 止まったら F7 
`00122837` に入ってくる

ループの先にBPを仕掛けながら進める

00122A3D のあたりから，
LoadLibraryA
GetProcAddress
が繰り返される。
IATの再構築をやっている。たぶん。

ループの先にBPを仕掛けながら進める

00123123にBPを仕掛け，
今までBPとしていた00123095,001230FF,00123116,0012310DなどのBPを解除し進める

ループの先にBPを仕掛けながら進める

00123252にBPを仕掛け，
今までBPとしていた0012322C,001231F0,0012200などのBPを解除し F9 で進めると

ここでアクセス違反が40回くらい連続で発生するので `Shift+F9`　を連打する

`00123A2A`　CALL EAX でF8すると デスクトップに配置したテキストファイルの拡張子がvvvになるので，再スタート

### `00123A2A` にBP 止まったら F7 
`yyyy0000` に入ってくる ※yyyyは動かす度に変わるアドレス
F8 で進める
`yyyy03B2` でF8すると デスクトップに配置したテキストファイルの拡張子がvvvになるので，再スタート

### `yyyy03B2` にBP 止まったら F7 
`yyyy0763` に入ってくる
F8 で進める
`yyyy078B` JMP EDX でF8すると デスクトップに配置したテキストファイルの拡張子がvvvになるので，再スタート

### `yyyy078B` にBP 止まったら F7 
`004257C9` に入ってくる

こいつがOEPだと思う。
リソースカレンダーレコードを作成する

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめN～Z](https://qiita.com/Keiji_otsubo/items/92f92bb9f668ca9688be)


元の質問 : [フローで行動レコードを作成し、リソースカレンダーに振り分けたいです。](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000JdUHhSAN)

フローでの作り方をとのことでしたが、まずはどのオブジェクトのどのフィールドに値を入れて作成したらいいかが分からないですね。
ということで調べてみたのですが、共有カレンダーはあってもリソースカレンダーは情報がなかったです。

ということで実際に画面からレコードを作成してそのレコードの値を確認してみようと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8d084f11-9aaa-7130-fe5b-634bb8a8e225.png)


結果としては　行動オブジェクトを作ったあとに、EventRelationオブジェクトに作った行動のIdとリソースカレンダーのIdとステータスフィールドにAcceptedを指定してレコードを作ればOKみたいです。

[EventRelation オブジェクト](https://developer.salesforce.com/docs/atlas.ja-jp.238.0.object_reference.meta/object_reference/sforce_api_objects_eventattendee.htm?_ga=2.134022219.490628629.1663288617-1204562978.1663288617)

また、行動idとカレンダーIdでチェックしているようでこの２つの組み合わせが同じものを追加しようとすると重複エラーになりました。ダブルブッキングもチェックできると思います。（リソースのカレンダーなので当然の機能ですね）

私の場合は以下のApexコードで追加することができました。
フローでも２つのIdを取得できれば可能だと思います。

```
EventRelation er = new EventRelation();
er.EventId ='00UO000000IkiXJMAZ'; 
er.RelationId = '023O0000007LzjPIAS';
er.Status ='Accepted';
insert er;
```

実際に画面を操作してレコードを調べる方法がやっぱり早いですね。
OpenCVで画像内の「最頻色」を取得する


画像内の「最も多くの面積を占める色」を取得したく、考案したのがRGB全ての最頻値を取るというやり方でした。

BGRを3byte分の文字列に結合してstatistics.mode()で最頻値を取得してRGBそれぞれに分解し直してます。

一見同じ色に見えても、webカメラからの画像ソースだったりするとRGB値全てがキレイに揃わないことも多いですが、
**inRange()に渡す色の範囲の基準値としては使えそう。**
そのへんの事情を考慮すると本当はこういうのはクラスタリングで取得するのが最適なんですかね？🤔
もっとうまい実装法を知りたいです。


```python
import cv2
import numpy as np
import statistics

def 画像の最頻色を取得(img):
    color_arr = np.vstack(img) # pix数 * 3（原色） の形状の行列
    color_code = ['{:02x}{:02x}{:02x}'.format(*color) for color in color_arr]

    mode = statistics.mode(color_code)
    b = int(mode[0:2], 16)
    g = int(mode[2:4], 16)
    r = int(mode[4:6], 16)
    color_mode = (r, g, b)
    return color_mode

img = cv2.imread(r'img.jpg')
print( 画像の最頻色を取得(img) )

```
Sample App of Flutter3 x MySQL8 with mysql_client 5

# 全件表示ページも付けてみた　

　[元の記事はこちら](https://qiita.com/dongri727/items/412b97eed4943006a0a0)


　SQL文はいたってシンプル　
```
    var result = await conn.execute("SELECT * FROM timeline ORDER BY year ASC");
```

## 全件表示からupdate pageにidを持って飛べるようにした。

つまり、そのid番号を使って編集作業ができるということだけれど、今は番号はwidget titleとしてappBarに表示されてるだけなので、それを見てTextFormFieldに自分で入れなきゃならない。ここが自動ではいると、もっと便利。　
　ちなみに、同じ機能をselect pageにも付けた。　

```
                  return Card(
                      child: ListTile(
                        leading: Text(data['selectedYear']?? ""),
                        title: Text(data['selectedName']?? ""),
                        subtitle: Text(data['selectedCountry']?? ""),
                        trailing: TextButton(
                          child: const Text("update"),
                          onPressed: () {
                            Navigator.push(
                              context,
                              MaterialPageRoute(builder: (context) => UpdatePage(title: data['selectedId']?? "")),
                            );
                        },
                        ),
                      )
                  );
```

## 各ページのボタンをテキスト表示にした。 
```
      floatingActionButton: FloatingActionButton.extended(
        onPressed: _readAll,
        tooltip: 'ReadAll',
        label: const Text("read all"),
      ),
```

## TextFormFieldのデザインを少し変えた　
 文字の位置を中央に寄せて、色を変えています。


```
    return TextFormField(
      textAlign: TextAlign.center,
      decoration: InputDecoration(
        contentPadding: const EdgeInsets.all(5.0),
        hintText: hintText,
        hintStyle: const TextStyle(
            fontSize: 14,
            color: Colors.green),
        fillColor: Colors.lightGreen[100],
        filled: true,
        focusedBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(20),
          borderSide: const BorderSide(
            color: Colors.lightGreen,
            width: 2.0,
          ),
        ),
        enabledBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(16),
          borderSide: const BorderSide(
            color: Colors.lightGreen,
            width: 1.0,
          ),
        ),
      ),
      onChanged: onChanged,
    );
```

## そしてビデオを撮った。　

　海外の人が検索してもヒットするように、英語のみでタイトルと解説を付けた。ビデオ自体には音声はなくて、音楽は同じフラッター大学のcoboさんのオリジナルを使わせていただいた。ので、ビデオの中身より、音楽がおしゃれ。　

https://youtu.be/HVeZe1v9qmg

##　あとはこのQiitaの記事をシンプルにまとめて英語化する予定。
call of overloaded 'begin(int, int, int)' 　対処


# 忘備録
## 久しぶりに、RoverCを使おうと思ったらエラーが発生


~~~
error: call of overloaded 'begin(int, int, int)' is ambiguous
   Wire.begin(0, 26, 10000);
~~~

## 対処例
~~~
  int sda=0;
  int scl=26;
  uint32_t frequency=10000 ;
  Wire.begin(sda, scl,frequency);
~~~

## 以上
※転載済み　スプリント0実施物　

| 優先度 | タスク名 | 詳細 | ステータス |
|:-:|:-:|:-:|:-:|
|  # マストリスト | イベントのスケジュールの決定（どのイベントを何曜日に何時間やるか）  |  スプリントの期間（1週間など） スプリントプランニング（1ヶ月8時間、1週間2時間、PO参加1時間、タスク切りで1時間など） リファインメント（1週間2時間など） レトロスペクティブ（1週間30分、内部30分）、有名どころでいうとKPT |  完了 |
|   | ワーキングアグリーメントもしくはチームルールの記載場所の決定  |   |  未完了 |
|   |  ざっくりとマイルストーンまでのプロダクトゴールのPBI作る |  POがビジネス目線で作成 開発チームが着手可能かどうかの判断をするときの最大サイズの決定 最大サイズの単位も決める（時間なのかポイントなのか） |   |
|   | アーキテクチャ構成図（場所の確定はmust。記載の粒度は段々あげていく前提）  |   |   |
|   |  gitブランチルールの決定 | 自動デプロイのCICDツール選定、モノレポなどを考慮しつつが望ましい  |   |
|   |  スクラムガイド2020の確認（SMのみ）https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf |  ※完全な理解は難しいと思うので流し読みで2-3回が適当 |   |
|   |  インフラパラメータ記載場所（awsなどでCDKを用いてい実装するならこれは不要） |   |   |
|   |  PBIの一旦の記載フォーマット決定 | 少なくとも　完了条件（DOD）　は記載する  |   |
|   | PBIの完了までのステータスフローの決定  |  開発メンバーの実装終わりステータスはデプロイ待ちステータスとし、POがレビューして良い状態はPOレビュー、それが終わると完了とする？など |   |
|   | プロダクトゴールの決定  |  プロジェクトの期間と、それまでに何を成し遂げたいか、達成する肝となる指標は何か 例：デザインとページのレスポンススピードでは、ページのレスポンススピードを優先するなど |   |
|   |  スプリントレビューでSM（もしくはdev）が提示する資料のフォーマットの決定 | このスプリントで何を開発したのか（インクリメント） 何に何時間かかったのか　など、チームの成長のために有効な指標、バグの原因分析などを入れるプロジェクトもある  |   |

| 優先度 | タスク名 | 詳細 | ステータス |
|:-:|:-:|:-:|:-:|
|  # 優先度高リスト |  自動テストをやるかの決定と、やる場合どのようにやるかの決定、もしくは記載場所だけでも決定 |   |   |
|   |  受け入れの品質基準（コードカバレッジなど）を設定するかの決定と、設定する場合どうするか、もしくは記載場所だけでも決定 |   |   |
|   |  コードレビューをするかの決定、する場合のルール（誰が、どういう観点で見るのか。レビュアーを固定した方がいいのか。何人が見るべきか。）の決定 |   | 
|   |  ざっくりと非機能要件のPBI切り（pbiを切るという最低限の記載でもよい） |脆弱性試験 負荷試験　などなど |   |
|   |  プログラミングの観点でのアーキテクチャ構成の記載場所の確定（デザインパターンなど） |   |   |
|   |  今後一定期間における使用環境バリエーションの確認、その相談を行うというpbiもしくはタスクの作成 |  開発環境、stg環境、prod環境は使用するタイミングがあるか、必要かなど） |   |
| # 優先度中  |  ローカル環境構築など、作業手順wikiの作成、少なくとも記載場所だけでも決定 |   |   |
| # 優先度中  |  エクストリームプログラミングの読了（SMの）（スクラムとは厳密にいうと全く異なるものだが、より具体的なプラクティスが記載され、情報量も多く、スクラムを理解する上で有用。スクラムガイドだけでは記載や単語の意味が漠然としたところの疑問解決に役立てるように使用するのが良い） |   |   |
| # 優先度中  | 品質指標の見える化をするかどうかと、見えるようにする場合はどうするかを決める、少なくとも記載場所だけでも決定  | コードカバレッジやコード重複など  |   |


備考	

	上記全てをスプリント0中に実施する必要があるというわけではない、
	可能な限り検討して進め、残項目はスプリント1後などに少しづつも可能。
	マストリスト（1-2週間以内に決めたいもの）
	↓
	優先度高リスト（スクラム開始後、1ヶ月以内に少なくとも相談まではしたいもの）
	↓
	優先度中リスト（スクラム開始後、1-3ヶ月以内に少なくとも相談まではしたいもの）
	の順に記載
DBバージョンアップした時なにをやったか

はじめてのDBバージョンアップをする機会があったので、やったことをまとめておきます。

# 前提
* MySQL5.6->8.0へのバージョンアップ
* 対象はPHPで書かれた業務システム

# 流れ
全体の流れは以下。
1. バージョンアップ前後の環境で単体テスト実行、エラーの有無確認
2. エラーがあれば修正
3. 動作確認・パフォーマンステスト

## バージョンアップ前後の環境で単体テスト実行
全クラスで単体テストを書いていてJenkinsで実行できる状態だったので、Jenkinsで実行するDBをバージョンアップ前・後で用意。
1. バージョンアップ前後のDB環境のコンテナをDockerで作成
2. DB環境作ったサーバをJenkinsの管理ノードに追加
3. Jenkinsプロジェクト設定でそれぞれ作ったコンテナのラベル式を設定

で、指定したバージョンのDBで実行できたので便利でした。
※ノードの追加参考：[【Jenkins運用基本】Jenkinsの管理ノードに外部サーバを追加する手順 - そういうのがいいブログ](https://souiunogaii.hatenablog.com/entry/Jenkins-add-Node#%E6%89%8B%E9%A0%86Jenkins%E7%AE%A1%E7%90%86%E7%94%BB%E9%9D%A2%E3%81%A7%E7%AE%A1%E7%90%86%E3%83%8E%E3%83%BC%E3%83%89%E3%81%AB%E5%A4%96%E9%83%A8%E3%82%B5%E3%83%BC%E3%83%90%E3%82%92%E8%BF%BD%E5%8A%A0)

単体テストですべての処理が網羅されていることが前提ですが、
これで「バージョンアップ後にエラーにならないこと」の担保ができるのでテストの工数がぐっと減りました。CIは偉大ですね。

> 単体テストですべての処理が網羅されていること

これは単体テストのカバレッジが100%になっていれば網羅されているだろうという前提で進めました。
カバレッジは単に「その行を処理として通っているか」だけを見るので厳密に言うと違うのですが、まぁその辺は現実的なスケジュールを加味して、カバレッジである程度担保できるでしょうみたいな感じですね。
日頃からの単体テストの整備は大事です。

## エラー修正
これは単体テストとDockerとJenkinsのおかげでサクサクできました。
1. エラー修正をpush
2. Jenkinsでテスト実行
3. 新旧DB環境の結果確認
4. エラーあれば修正

を繰り返して修正していけばOK。
修正する度に手動で検証する…という手間が省けるのが素晴らしいですね。
また、Dockerでコンテナ作成しているので新旧環境の違いはDBバージョンだけ（のはず）なので、エラーの原因特定がしやすかったです。

## 動作確認・パフォーマンステスト
ここに一番時間をかけました。というかJenkinsのおかげでここに時間をかけられました。
本来は性能が上がるはずなので速くなりそうなものですが、
* DBに新機能が追加された
* DB側のバグが修正された
* 上述したエラー修正でクエリを変更した

などにより今まで速かったものが遅くなった…なんてこともあるのでパフォーマンステストは重要。

また、動作確認については基本的にJenkinsで単体テスト回してエラー無しであれば（=DB操作メソッドの入出力が変わっていなければ）OKという方針でしたが、

> 単体テストですべての処理が網羅されていること

これが確実に担保されているわけではないので、やはり動作確認は念のためしておきたい…という話に。
とはいえスケジュールも限られているので、パフォーマンステストで全機能各1回は実行するしその時エラーにならないことを確認しようということになりました。

パフォーマンステストの方は各画面・バッチで同じ処理を実行して実行時間を計測、新旧DBで比較し遅くなっていないかを確認することにしました。

観点としては以下。
* 対象選定
    * 業務上重要度の高い機能：3回実行、平均実行時間を比較
    * 業務上重要度の低い機能：1回実行、大きな遅延が無ければOK
* 画面処理
大体3秒以上の遅延が無ければOK。（業務システムなので業務に支障が出ない程度であればOK）
* バッチ処理
件数が増えれば増えるほど遅延がかさむので、個別に処理件数と遅延時間を確認する。
```
例：1秒程度の遅延は問題なし、10秒以上の遅延は問題ありとする場合
1000件処理する可能性があるバッチ
a. 10件のデータ処理で0.1秒遅延している場合、 100件で1秒遅延、1000件で10秒遅延する
   →問題あり
b. 10件のデータ処理で0.01秒遅延している場合、 100件で0.1秒遅延、1000件で1秒遅延する
   →問題なし
MAX処理件数100件のバッチ
c. 10件のデータ処理で0.1秒遅延している場合、 100件で1秒遅延する
   →問題なし
```

実行時間の計測は
* バッチ処理
開始時間と終了時間をテーブルで管理しているので、そこの差分で測る。
* 画面処理
Webサーバに吐き出しているログに画面処理の実行時間が出るので、それをtailコマンドで監視して確認。
`tail -f [ファイル名] | grep "検索文字列"`
[tailコマンドについて詳しくまとめました 【Linuxコマンド集】](https://eng-entrance.com/linux-command-tail)

という感じで、個人的にはtailコマンドで監視しながら作業するのがいかにも映画に出てくるプログラマー！って感じで楽しかったですねw

# まとめ
今回特に大変だったのは、更新系処理のテストデータの用意でした。
特にバッチに処理させるテストデータは少なくとも10件くらいは必要だったので、作るのに結構手間がかかりました。
今回は見送ったのですが、画面から作れるデータは[Selenium](https://www.selenium.dev/ja/)を使う？みたいな話も出てました。流れましたが…
後になって思うと、やっぱりこれ使った方が良かったかも…。
[10分で理解する Selenium - Qiita](https://qiita.com/Chanmoro/items/9a3c86bb465c1cce738a)
次の機会に生かします。
【Rails】Parameter Objectパターン

## 環境
Rails 6.0.1
Ruby 2.6.3
PostgreSQL 11.16

## Parameter Objectパターン

Laravelだったらフロントから投げられたパラメータはRequest層でバリデーションをかけたりするが、
RailsはドキュメントにRequest層に当たるものが載っていない。
そういうときにParameter Objectパターンを使って実装するのもひとつの手法らしい。


```app/models/parameters/profile_parameter.rb
module Parameters
    class ProfileParameter
      attr_reader :name,
                  :email,
                  :avatar,
                  :birthday,
                  :gender,
                  :phone_number,
                  :living_address,
                  :house_name,
                  :room_number

      def initialize(opts = {})
        update(opts)
      end

      def update(opts)
        @name = attrs[:name] if attrs.key?(:name)
        @email = attrs[:email] if attrs.key?(:email)
        @avatar = attrs[:avatar] if attrs.key?(:avatar)
        @birthday = attrs[:birthday] if attrs.key?(:birthday)
        @gender = attrs[:gender] if attrs.key?(:gender)
        @phone_number = attrs[:phone_number] if attrs.key?(:phone_number)
        @living_address = attrs[:living_address] if attrs.key?(:living_address)
        @house_name = attrs[:house_name] if attrs.key?(:house_name)
        @room_number = attrs[:room_number] if attrs.key?(:room_number)
        validate!(opts)
        self
      end

      def attributes
        {
            name: name,
            email: email,
            avatar: avatar,
            birthday: birthday,
            gender: gender,
            phone_number: phone_number,
            living_address: living_address,
            house_name: house_name,
            room_number: room_number
        }.compact
      end

      private

      def validate!
        raise_bad_request if name.blank?
        raise_bad_request if email.blank?
        raise_bad_request if birthday.blank?
        raise_bad_request if phone_number.blank?
      end

      def raise_bad_request
        raise ActionController::BadRequest, '必須項目が入力されていません'
      end
    end
  end
end
```

Parameterオブジェクトをnewしてすでにバリデーションされた```profile_params.attributes```をupdateに渡せる。

```app/controllers/profiles_controller.rb
def update
  profile_params = Parameters::ProfileParameter.new(params)
  current_user.update(profile_params.attributes)
  ...
end
```

## 気をつけること
今回は必須パラメータが存在するかのバリデーションしか行っていないが、
フロントから渡された値の形式が正しいか（正しいメールアドレスの形式か）など、型が正しいかなどのフォーマットに関するバリデーションに留めた方が良い。
そうしないとパラメータオブジェクトの責務を超えてしまう。

データの整合性などの検証はモデル層でした方が良い。

## 参考

https://techracho.bpsinc.jp/hachi8833/2018_03_20/53807
Salesforce認定アドミニストレーター試験の公式練習問題を解説してみた-その025

こんにちは。本橋孝昭です。

Salesforce認定アドミニストレーター試験の公式練習問題があるのはご存じでしょうか。
Trailheadにフラッシュカードとして何度も解ける練習問題がございます。

今回はTrailhead
アドミニストレーター認定の準備: アプリケーションと活動
サービスアプリケーションとサポートアプリケーションの準備

にある練習問題1問目をご紹介します。

https://trailhead.salesforce.com/ja/content/learn/modules/administrator-certification-prep-applications-activities-and-mobile/prep-for-service-and-support-applications?trail_id=administrator-certification-prep


今回の内容は動画絵も説明しています

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

<iframe width="560" height="315" src="https://www.youtube.com/embed/afdeRD125KU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>



問題はこちらです

![エスカレーション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/ed2fecb9-0b54-6364-eea1-4fbafebb133f.png)

正解はCです

今回の場合は
・４時間後
というとことろがポイントですね

今回の中でBとCとDは自動化ルールですが、Cは特定の時間に更新させることができます

Bについて間違っている理由を説明します
Bは自動的に特定の条件でメールを送る自動化です

今回のようにサポートマネージャーに連絡する自動化ではないので間違いですね

Dについて
割り当てルールは特定の一致条件に対して所有者を割り当てるルールです
レコード作成時などに割り当て可能ですが今回のように４時間以上たった状態で更新することはできないので間違いです

なおAについて
ケースキューとは特定のチームへレコードを割り当てることが可能です
今回はケースマネージャーという個人に割り当てるので間違いですね

なお、今回正解のエスカレーションルールはケースオブジェクトのみ使える機能です。

もしも他の問題でケースオブジェクトではない問題の場合、エスカレーションルールが正解ということは無いと思ってください
Python,Ruby,PHP,Java,JavaScript,Perlの文字列連結の比較 | プログラミング言語比較


<a href="https://qiita.com/yuki_kimoto/items/f9c2454e7f9130ddb003">Qiita > プログラミング言語の比較</a>

プログラミング言語Python,Ruby,PHP,Java,JavaScript,Perlの文字列連結の比較

# Python

https://qiita.com/masa2223/items/cf3c4cc104e90d3c40d3

# Ruby

https://qiita.com/Kta-M/items/c7c2fb0b61b11d3a2c48

# PHP

https://qiita.com/horikeso/items/01463f5e17985428055c

# Java

https://qiita.com/supercell1023koeda/items/a548f2bdd811168e7c44

# JavaScript

https://qiita.com/saka212/items/11ce1f1d6316c1fbf15b

# Perl

https://perlzemi.com/blog/20161003147558.html

https://perlzemi.com/blog/20080221120361.html

https://perlzemi.com/blog/20081007122338.html
【Ruby】◯番目から最後までの文字列を取得する

## 環境
Rails 6.0.1
Ruby 2.6.3
PostgreSQL 11.16

## String[]

```[]```の中に```Range```オブジェクトを指定できる。
```str[f..-1]```は「f文字目から文字列の最後まで」を表す慣用句

```ruby
message = 'こんにちは、山田さん'

message[2 .. -1] 
=> "にちは、山田さん"
```

ハッシュタグ検索を実装したいときに使えそう
```ruby
keywords = '#今日のコーデ'

if keywords.start_with?('#')
  search_keywords = keywords[1..-1]
end
# 検索の処理が続く
```

### 追記①
コメントで教えていただきましたが、
Ruby 2.6 以降なら「終端の無い Range リテラル」が使えるため下記のように書ける。
（Ruby 2.6 系は公式サポートが終了しているので注意）
```ruby
keywords = '#今日のコーデ'

if keywords.start_with?('#')
  search_keywords = keywords[1..]
end
# 検索の処理が続く
```
https://docs.ruby-lang.org/ja/latest/doc/news=2f2_6_0.html


### 追記②

コメントで教えていただきましたが、```delete_prefix```を使ったほうが処理がわかりやすくて良さそう。

```ruby
keywords = '#今日のコーデ'

if keywords.start_with?('#')
  search_keywords = keywords.delete_prefix('#')
end
# 検索の処理が続く
```
https://docs.ruby-lang.org/ja/latest/method/String/i/delete_prefix.html


## 参考

https://docs.ruby-lang.org/ja/latest/method/String/i/=5b=5d.html
Apache 2.4 で特定のユーザーエージェントのみアクセスを許可する

アプリ内のWebViewで表示するサイトに、容易にアプリ外からアクセスできないようにするために対策が必要だったので下記のような設定を行った


```
  DirectoryIndex index.html

  <Directory /usr/local/www/myapp.jp/unknown>
    AllowOverride None
    Require all granted
  </Directory>
  Alias /.unknown.html /usr/local/www/myapp.jp/unknown/unknown.html

  <Directory /usr/local/www/myapp.jp/htdocs>
    AllowOverride All
    SetEnvIf User-Agent MyappUserAgent myapp
    Require env myapp
    FallbackResource /index.html
    ErrorDocument 403 /.unknown.html
  </Directory>
```

なお、この対策は簡易的ものでセキュリティ対策ではない
[Rails,Ruby]文字列の置換(gsub,sub)

# はじめに
正規表現について学んでいたら、文字を置換する`gsub`メソッドが出てきたので練習も兼ねて遊んでみました。

# gsub
文字列内に指定した文字が複数含まれている場合、その全てを置換します。

使用例の前に突然ですが穴埋め問題です。（同じ数字には同じ単語が入ります）
皆さんは高校野球・山下智茂監督のこの名言をご存知ですか？
```
心が変われば(1)が変わる
(1)が変われば(2)が変わる
(2)が変われば(3)が変わる
(3)が変われば運命が変わる
```
答えは1から順に`行動`、`習慣`、`人格`です。

では答えを数字の部分に置換しましょう。
```ruby
q = "心が変われば(1)が変わる\n
(1)が変われば(2)が変わる\n
(2)が変われば(3)が変わる\n
(3)が変われば運命が変わる"

a = q.gsub(/1/,'行動').gsub(/2/,'習慣').gsub(/3/,'人格')

puts a
```
すると以下のように出力されます。
```
心が変われば(行動)が変わる
(行動)が変われば(習慣)が変わる
(習慣)が変われば(人格)が変わる
(人格)が変われば運命が変わる
```
では、`gsub`の使い方です。
```ruby
文字列.gsub(/置き換えたい文字列/,'置換後の文字列')
```
第1引数に置き換えたい文字列を`/`で挟み指定します。
第2引数に置換後の文字列を指定します。

第2引数を`''`とすれば空文字に置換できます。
[例]たぬき暗号
```ruby
cipher = 'こたれはもたじたれたつたちかたんのれたんたしゅうたです。'
plain_text = cipher.gsub(/た/,'')
puts plain_text

# 出力結果
# これはもじれつちかんのれんしゅうです。
```

# sub
ここで`gsub`に似た`sub`について確認します。
文字列を置換できることや、引数の指定の方法は`gsub`と変わりませんが、`sub`では最初にマッチした１つだけしか置換されません。
[例]
```
q = 'いっぱい'
puts "A「#{q}の「い」を「お」に変えて言ってみて～」"
puts "B「#{q.sub(/い/,'お')}？」"
puts "A「ブー！！正解は#{q.gsub(/い/,'お')}でした〜」"
```
出力結果は各自で確認してください。小学生の頃を思い出しますね笑

# 最後に
真面目に名言から始めたのに締まらないですが以上が`sub`メソッドと`gsub`メソッドの使い方です。
数行で終わる話を最後までお読み頂きありがとうございました。
商談の価格表の選択

元の質問 : [商談の種別ごとに表示する価格表を変更したい](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000JyAfSSAV)


この価格表の選択画面ですが、基本的には一度価格表をセットしてしまえば次からは表示されないと思います。
オブジェクトのフィールドを調べていくと
Pricebook2Idというフィールドがあって説明は以下のとおりです。

関連する Pricebook2 オブジェクトの ID。Pricebook2Id 項目は、この商談に適用される Pricebook2 を示します。Pricebook2Id 項目は、商品機能を有効化している組織にのみ定義されます。いずれか一方の項目 (Pricebook2Id または PricebookId) に値を指定できます。両方指定することはできません。このため、両方の項目が nillable を宣言しています。

そのためこのフィールドに既に選んだ価格表のIdが入っていれば次からは表示されないようです。
ということは、この標準の価格表選択画面を使わずに別に用意してあげたらいいと思います。
私ならAuraコンポーネントでクイックアクションから呼び出せるようなカスタムコンポーネントを作ってユーザの所属(ロール？）から国内、海外を判断して選択できる価格表だけを表示できるようにします。（申し訳ない、普段から何でもコーディングしているので...フローは分かりません）

同じようなことはスクリーンフローでもできそうですが、詳しい説明は私には無理です。

英語ですが、参考になりそうなブログがあります。
[Automatically Assign Pricebook Based on Opportunity Record Type](https://automationchampion.com/2022/02/10/automatically-assign-pricebook-based-on-opportunity-record-type-2/)
Goで簡易な集合型を実装してみよう

# はじめに

Goには、集合型が存在しない。Goで集合型っぽいことを実装するには様々な方法があるが、空のstructをvalueとして持つmap型を定義する方法が使い勝手が良い。今回はこれを利用してSet型の定義を行い、簡易なメソッドを実装してみよう。

# 実装

```golang
type Set map[interface{}]struct{} // Set型の定義

func NewSet() *Set { // 新しい集合を作成
	return &Set{}
}

func (s Set) Add(key interface{}) { // 集合に値を追加
	s[key] = struct{}{}
}

func (s Set) Delete(key interface{}) { // 集合から値を削除
	_, ok := s[key] // 値の存在判定
	if ok {
		delete(s, key)
	}
}
```

※今回は簡易的な実装のためmapのkey(interface{})の型判定は実装していない

# How to use

```golang
func main() {
    s := NewSet() // 集合を作成
    s.Add("a") // 値の追加
    s.Add("b") // 値の追加
    s.Add("c") // 値の追加
    fmt.Println("Before:", len(*s), s) // map型のためlen()関数が利用可
    s.Delete("b") // 値の削除
    fmt.Println("After :")
    for k, _ := range s { // 値を取り出すときはmapと同じように
        fmt.Println(k.(string)) 
    }
}
```

出力
```terminal
Before: 3 &map[a:{} b:{} c:{}]
After :
a
c
```

# 参考資料

[GoでSet型を実現する場合の選択肢](https://kitakitabauer.hatenablog.com/entry/2017/04/04/204701)
[Combine] 複数のAnyCancellableをまとめてstoreする

https://qiita.com/417_72ki/items/5943700dbe5d3663512a

をCombineでもやりたいよねって話。

ただし、Combineの場合 Swift Foundation の `Set` が使われており `DisposeBag.insert(_:)` に相当するfuncが存在しないので自前で用意する必要があります。

`Set` は struct なので `mutating` を付けるのがミソ。

```swift
public extension Set where Element == AnyCancellable {
    mutating func insert(_ cancellables: [AnyCancellable]) {
        cancellables.forEach {
            $0.store(in: &self)
        }
    }

    mutating func insert(_ cancellables: AnyCancellable...) {
        insert(cancellables)
    }
}
```

これで

```swift
hoge.sink { ~ }
    .store(in: &cancellables)
fuga.sink { ~ }
    .store(in: &cancellables)
```

が

```swift
cancellables.insert(
    hoge.sink { ~ },
    fuga.sink { ~ }
)
```

と書けるようになりました🎉

折角なのでresultBuilderも作っちゃいましょう。

```swift
public extension Set where Element == AnyCancellable {
    /// Convenience function allows a list of cancellables to be gathered for cancel.
    mutating func insert(@AnyCancellableBuilder _ builder: () -> [AnyCancellable]) {
        insert(builder())
    }
    
    @resultBuilder
    struct AnyCancellableBuilder {
        static func buildBlock(_ cancellables: AnyCancellable...) -> [AnyCancellable] {
            cancellables
        }
    }
}
```

これでRxSwift時代と同じように書けるぞい💪('ω'💪)

```swift
cancellables.insert {
    hoge.sink { ~ }
    fuga.sink { ~ }
}
```
mb_strlen()の文字列の長さは文字エンコーディングによって可変するという話


## 概要
**strlen()** は文字列の長さをバイト数で返し、
**mb_strlen()** は文字列の長さを取得するとよく書かれるが
そもそも文字コードはどうなっているのか？

## 答え
PHPの公式を見てみる

https://www.php.net/manual/ja/function.mb-strlen.php

説明には`文字列の長さを得る`とだけ書かれているが
パラメータにはしっかりと`$encoding`が書かれている
```php
mb_strlen(string $string, ?string $encoding = null): int
```

- **encoding**
encoding パラメータには文字エンコーディングを指定します。省略した場合、
もしくは **null** の場合は、 <font color="Red">内部文字エンコーディング</font>を使用します。

#### 内部文字エンコーディングとは？
PHP.iniで文字のエンコーディングを設定できるみたいです。

https://www.php.net/manual/ja/mbstring.configuration.php#ini.mbstring.internal-encoding
> mbstring.internal_encoding string
警告
この非推奨の機能は、きっと 将来 削除 されるでしょう。
内部文字エンコーディングのデフォルト値を定義します。
この値は空のままにしておいて、代わりに default_charset を設定すべきです。

`mbstring.internal_encoding` は空にしてdefault_charset を設定すべきと。
そして`default_charset`では

https://www.php.net/manual/ja/ini.core.php#ini.default-charset

> default_charset string
"UTF-8" がデフォルトの値です。 htmlentities() や html_entity_decode() そして htmlspecialchars() で encoding パラメータを省略した場合は、このデフォルト値を利用します。 

なるほど
元々、`UTF-8`が設定されているから
エンコーディングの引数を入れなくても正常に文字数を取得できていたんですね！

## 結論
php.iniで変更されるリスクがあるなら
引数には`UTF-8`を入れておきたいところですね。

```php:例
mb_strlen('一意専心', 'UTF-8')
// 出力結果: int(4)

mb_strlen('一意専心', 'SJIS')
// 出力結果: int(7)
```
Raspberry Piでrsyslogを使ってsshguardの不正アクセスブロックをLINEに通知する

/etc/rsyslog.d/に適当なconfを作成

```line-notification.conf
module(load="omprog")
if ($msg contains "Blocking") then {
    action(
        type="omprog"
        template="RSYSLOG_TraditionalFileFormat"
        binary="***.sh"
    )
}
```
sshguardが不正アクセスIPをブロックしたときにrsyslogに以下が通知される。
```/var/log/auth.log
*** ** **:**:** raspberrypi sshguard[***]: Blocking "***" for *** secs (* attacks in * secs, after * abuses over * secs.)
```
したがって、line-notification.confに"Blocking"がmsgに含まれるとshellが走るように設定する。
LINEに通知するshellスクリプトを適当に作成。
```***.sh
#!/bin/bash

while read line; do
        msg1=$(echo ${line} | sed -e "s/\"//g")
        curl -v https://api.line.me/v2/bot/message/push \
        -H 'Content-Type: application/json' \
        -H 'Authorization: Bearer {***}' \
        -d @- <<EOS
{"to": "***","messages":[{"type":"text","text":"${msg1}"}]}
EOS

done
```
sedで/var/log/auth.logにあるIPアドレス部分が””で囲われているのを置換してやらないとjson書式が崩れるので、何かしらの置換が必要。
LINEに渡すデータ部分（-d以下）はシングル・ダブルクォーテーションの扱いが難しいので@でヒアドキュメントをパイプでつなげた。

結構雑な部分が多いけど出力できた。
「null」と「undefined」の違いをゲームで楽しく学ぼう！

## はじめに
プログラミングを学習する上で必ず理解が必要となる`null`。
**何もない状態**ということではありますが、いまいちイメージが付きにくいかと思います。

また、`JavaScript`（以下、`js`）では値の1つとして`undefined`があります。**未定義であることを示す値**とされていますがこちらもイメージが付きにくく最初は悩ます存在ですよね…。

オブジェクティブグループでは、社員一人一人の技術力向上を目指し毎月Excel講習、フロントエンド講習といった様々な講習会を行っています。

フロントエンド講習会では受講者の希望や理解度に合わせて講習を行っています。
ロジックコースの初心者向けクラスでは`HTML`・`CSS`・`js`を使って基礎的な「プログラミング」で必要な内容や考え方を学習していきます。過去に`null`と`undefined`についての講義があり、その際に盛り上がったゲームについてを記事とさせていただきます。

## null or undefined ？

:::note warn
- null：定義付けはされているけど、答えがありません
- undefined：定義付け自体がそもそもされていない
:::

講義を聞いていて、「わかるような……わからないような……？」という受講者に対して、講師からはトイレットペーパーへ例えたお話もありました。

:::note info
- null：トイレットペーパーの芯も紙もない状態
- undefined：そもそもホルダー自体がない状態
※講師の方から一部適切な説明ではなくイメージを掴んでもらう為の説明とのことです。
:::

やはり実生活に例えると想像がしやすく、理解がしやすいですね！　という流れから、他にも例えられないか……そうだ、せっかくなのでゲームをしよう！となりました。

その名も……

<font color = red>**null or undefined  ゲーム！**</font>

名称はそのまま、ルールはシンプルです。
質問者は回答者を指名し、質問は自分で考えますが内容は何でもOK！

回答者が「true（はい）」「false（いいえ）」「null（質問の意味が分かりません） 」「undefined（質問自体の意味が分かりません）」と4点から答えることのできる質問を考えます。
　
条件分岐の講習も踏まえて「true」「false」も回答として含むことにしました。回答者は自身の感覚で答えてOKとします。そして、回答者は回答後に質問者となり、また別の回答者を指名します。

## 実際の問題・回答紹介
では、実際にどのような問題や回答が出たか。質問者、回答者は講師、受講生問わず行いました。
- **「お米は黄色いですか？」**
一見falseですが、「お米」という言い方だと玄米や外国のお米も含まれるのでtrue。
- **「トラベリング（※1）って知っていますか？」**
回答者はバスケットボール知識がなくfalseと回答。質問者としてはtrueが返ってくる想定での質問でした。
<font color = "#a9a9a9">※1：バスケットボールの「３歩以上歩いてはならない」というルール </font>
- **「あｗｓｚｄｘｆｃｙｇｖｈｊｋｍ；ｄ」**
undefined！！！意味が分かりません！！
- **「日本の大統領は誰ですか？」**
null！日本に大統領は存在しません。
- **「スイカは果物ですか？」**
スイカは野菜という知識の有無でtrueかfalseか変わりますね。
- **「ダンスパーティーは綺麗ですか？」**
⇒質問者の意図ではダンスパーティー＝紫陽花の品種です。一
般的に思い浮かべる「舞踏会」を連想すると質問の意味が分からずnullとなりますね。
しかし紫陽花の品種を知っていればtrueとなります。
- **「ウィーーーースっ！」**
挨拶というのはわかるけど…
質問ではなく意味がわからないですね（笑）undefined！
- **「トマトは緑色ですか？」**
こちらも熟しているかどうか、旬の時期かどうかでも変わります。
- **「N’Djamena！！（ンジャメナ）」**
こちらも意味が…わかりません…　undefined！
（ちなみにチャドの首都だそうです。しりとりで無敵になれますね。）


などなど質問を考えることや回答がどうなるかで大盛り上がりでした！
「null or undefined ゲーム」ですが、元々の知識があるかないかでも回答が大きく変わることが実感できるので、機械学習の重要さがわかります。

質問者でも、回答者でも条件分岐や定義の有無を考えるのでエンジニアとしての思考力が自然と上がります。何よりも`null`・`undefined`に対して親しみが湧きますね（笑）

## おわりに
実際にゲームをしていたのは30分ほどですが、受講生間でのコミュニケーションも自然と生まれ和気あいあいとした雰囲気で講習会を行うことができました。

この記事を読んで頂いた方は是非「**null or undefined ゲーム**」をしてみてはいかがでしょうか？
自然とエンジニアとしてのスキルアップにも繋がるかも…？

フロントエンド講習会は毎月第二土曜日に業務として行っているため、振替休日もしっかりと取得することができます。
オブジェクティブグループではこうした取り組みを行い、今後も社員全員のスキルアップを目指していきます！

参考：[null](https://e-words.jp/w/Null.html)/ [undefined](https://www.sejuku.net/blog/28461)
AndroidTV(GoogleTV)で不明なアプリをインストールする

自分用メモです。

# 前提
AndroidTVにapkファイルをダウンロードしても
「このユーザーは不明なアプリをインストールできません」
と言われてインストール出来ない状況です。

# 環境
* デバイス：Chromecast with Google TV(初代)
* モデル：Chromecast
* AndroidTVのOSバージョン：10
* AndroidTVのOSビルド:QTS1.220504.008.8726984

# 手順
まずホーム画面から「設定」→「システム」→「デバイス情報」→「AndroidTVのOSビルド」にフォーカスを合わせて決定ボタンを連打する。
これで開発者モードが有効になりました。

次にホーム画面から「設定」→「アプリ」→「セキュリティと制限」→「不明なアプリのインストール」からダウンローダーやファイラーなどに権限を付与します。
開発者モードが有効でない場合はこの画面でアプリにフォーカス出来ずに権限が付与出来ませんので最初から手順をやり直しましょう。

# あとがき
野良apkを入れさせたくないのは解るけど手順複雑すぎでしょ。
ファミレスなどでタブレットがあるとメンテナンスモードに移行させたがる人でないとたどり着けないよ。
WordPressテーマ AFFINGER6 アップグレードができない時の解決策

Affinger6のアップグレードができない原因のNo1は「親テーマ見つからない」のはフォルダ名が原因です。

Affinger系を全部消して、ファイル名を「affinger」にしてから、再インストールするとできました。


https://money-jump.com/value-affinger6/
【Flutter】import するパッケージが多くなった時の対処法

##  初めに
コーディングをしていく中で、一つのファイルでインポートするパッケージやページの数が増えてきてしまいました。
初期に書いたコードの中では、以下のように大量の import 文が並んでいるものもありました。
![スクリーンショット 2022-09-12 16.46.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609901/72fa0578-f6bc-63e0-e65e-95bea5fc3c52.png)
流石にここまで import 文が並ぶことは無いかもしれませんが、大きなプロジェクトになると大量のページやパッケージを import する機会はあると思うので、今回はその対処法を共有したいと思います。

## 記事の対象者
+ ファイル内の大量の import を無くしたい方
+ 大規模なアプリを開発中の方
+ コードを綺麗に保ちたい方

## 実装
大量の import 文を無くすためには `export` を使います。
まずは新たに 「 importer.dart 」 というファイルを作成します。

次に作成したファイルに import 文を全てコピペします。
```dart: importer.dart
import 'package:widget_example/widget_tools/icon_example.dart';
import 'package:widget_example/widget_tools/intro_slider_example.dart';
import 'package:widget_example/widget_tools/list_example/leading_icon_list_example.dart';
import 'package:widget_example/widget_tools/list_example/simple_number_list_example.dart';
import 'package:widget_example/widget_tools/list_wheel_scroll_view_example.dart';
import 'package:widget_example/widget_tools/percent_indicator_example.dart';
import 'package:widget_example/widget_tools/radio_button_example.dart';
import 'package:widget_example/widget_tools/scaffold_example.dart';
import 'package:widget_example/widget_tools/snack_bar_example.dart';
import 'package:widget_example/widget_tools/switch_list_tile_example.dart';
import 'package:widget_example/widget_tools/tab_bar_example.dart';
import 'package:widget_example/widget_tools/tutorial_coach_mark_example.dart';
import 'package:widget_example/widget_tools/url_launcher_example.dart';
```
<br>

次に全ての import 文を export 文へ変更します。
```dart: importer.dart
export 'package:widget_example/widget_tools/icon_example.dart';
export 'package:widget_example/widget_tools/intro_slider_example.dart';
export 'package:widget_example/widget_tools/list_example/leading_icon_list_example.dart';
export 'package:widget_example/widget_tools/list_example/simple_number_list_example.dart';
export 'package:widget_example/widget_tools/list_wheel_scroll_view_example.dart';
export 'package:widget_example/widget_tools/percent_indicator_example.dart';
export 'package:widget_example/widget_tools/radio_button_example.dart';
export 'package:widget_example/widget_tools/scaffold_example.dart';
export 'package:widget_example/widget_tools/snack_bar_example.dart';
export 'package:widget_example/widget_tools/switch_list_tile_example.dart';
export 'package:widget_example/widget_tools/tab_bar_example.dart';
export 'package:widget_example/widget_tools/tutorial_coach_mark_example.dart';
export 'package:widget_example/widget_tools/url_launcher_example.dart';
```
<br>

最後に export したパッケージを使いたいページで 「 importer.dart 」 をインポートします。
```dart: main.dart
import 'importer.dart';
```
これで、「 importer.dart 」で export した全てのパッケージを import 先の「 main.dart 」で利用できるようになりました。

元のコードでは import 文が 13行ありましたが、 export で一つのファイルにまとめておくことで import 文を 1行に省略することができるようになりました。

以上です。

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

今回は短い記事でしたが、参考にしていただければ幸いです。
誤っている箇所があればご指摘いただければ幸いです。

### 参考にしたサイト
https://zenn.dev/littleforest/articles/a4fc5bc7c944d42f66d2
【Abaqus】使い方講座　小ネタ1　メッシュと結合


# はじめに
【Abaqus】使い方講座のうち、「小ネタ」では本編と違い、ちょっとしたテクニックだったり、気が付いたことを書いていきたいと思います。

他の回は以下のサイトにまとめています。
https://qiita.com/yuki_2020/items/d613eedb149cbbd16ce8#%E4%BD%BF%E3%81%84%E6%96%B9%E8%AC%9B%E5%BA%A7%E9%80%A3%E8%BC%89


# 今回の内容

今回は、メッシュの切り方によって特にパートとパート間の結合部が変な感じになってしまったこと書いていこうと思います。
数学的な裏付けや、リファレンスだったりはなく、「多分こうだろうな」ということを書いていきます。



Abaqusを使用していて、いろいろなパーツを`結合`を使ってサーフェスとサーフェスをくっつけていたのですが、解析結果を見たらくっついてなかったんです。
原因は結合する上下面でメッシュの切り方が違ったからでした。

![image (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/6224ff12-3459-3fda-7e05-03485aef1b75.jpeg)

# 前提
今回は、↓のような上と下のパートからなっており、接触面同士を「相互作用」の結合し、1面を完全固定し、反対側のエッジを引っ張り上げるような解析をしています。

![image (8).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/5dfa911e-9821-8713-773a-9aae36692f62.jpeg)



# 失敗例：節点がずれている


このように上面とした面で節点の位置が異なるようにメッシュを切ってしまうと、
![image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/48540a78-5f3d-5440-a0b9-a8e9762e250e.jpeg)


このように真ん中に穴が開いてしまいます。
![image (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/6224ff12-3459-3fda-7e05-03485aef1b75.jpeg)

![image (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/61f4605d-4240-e5b9-138d-c7f3db594229.jpeg)


おそらく結合では、できるなら節点同士を共有、できないなら節点が相手のサーフェス上に乗るように内部で処理をしているのでしょう。

# 成功例:節点が一致している


対して、このように節点の位置が上下で同じようにメッシュを切ると、
![image (3).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/37043b6d-de63-1b72-448a-5374ff039cf8.jpeg)


このように共通面で同じような変形をしてくれます。
![image (4).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/e17056d8-94ae-b9a4-e2e9-9f502ef48c90.jpeg)
![image (5).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/391d7710-ffcd-5a15-7b57-18fd40b98bf1.jpeg)


おそらく要素として適合要素を使用しているため要素間のノードは連続になるのでしょう。適合要素について詳しく知りたい方はこちらhttps://qiita.com/yuki_2020/items/9dcfd88c8909300cc9a1#%E7%AF%80%E7%82%B9%E3%81%AE%E6%80%A7%E8%B3%AA



# 対策法

各パートごとに同じ位置になるようにメッシュを切るのは面倒です。
そのようなときには、アセンブリを作成するときに、インスタンスタイプとして`インディペンデント（インスタンスにメッシュ）`を選択しましょう。
そうすると、アセンブリ状態でいつものようにメッシュを切ることができます。

![image (6).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/558ae11e-62c5-2f22-7e8b-5aabcb345119.jpeg)

`ディペンデント（パートにメッシュ）`にすると、パートごとにメッシュを切ってしまい、今回のようなずれが起きてしまいます。

圧子と試験片別々にメッシュを切りたいけど、試験片は様々なパートからなっているんだ、というときも安心してください。
一緒に切りたいパートだけ`インディペンデント（インスタンスにメッシュ）`にし、それとは別に`ディペンデント（パートにメッシュ）`のパートをアセンブリに組み込むことはできます。

![image (9).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/9777fc9f-1cdf-b2ef-b88a-13e014e86b16.jpeg)

ただし、別のパートである必要はあります。



# さいごに

メッシュの切り方について説明しました。
こんなミス普通ないでしょ、と思う方もいるかもしれませんが、メッシュが細かくなっていろいろなパートを組み合わせていると忘れてしまうものです。
また、この経験を通して初めて`ディペンデント（パートにメッシュ）`と`インディペンデント（インスタンスにメッシュ）`の使い分けがわかりました。

リファレンスを読んではいないので、もし、間違っているところなどありましたらご指摘ください。
２つの App Service に同じカスタムドメイン名を割り当てる際の注意点 ：「異なるスケールユニット」なら割り当てられる

# 前置き

App Serivce は有料プランでカスタムドメイン名を設定することが出来ますが、  
複数の App Service に同じカスタムドメイン名を設定することが出来るか調査してみました。

# 結果

:::note
それぞれの App Service が「異なるスケールユニット」に存在する場合、同じカスタムドメインを割り当てることが出来る 
:::

それぞれの App Service が同じスケールユニットに存在する場合、
「カスタムドメインの追加」の「検証」で「次のアプリではホスト名が既に使われています…」のエラーとなり、カスタムドメインを追加できません。

![スクリーンショット 2022-09-16 101840.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23789/bcf8b3d4-e46c-c65f-9bc8-86d44234d394.png)

# 参考

https://github.com/MicrosoftDocs/azure-docs/issues/40427#issuecomment-543246709

## 引用 + 日本語訳

> 同じスケール ユニット内の 2 つのアプリが同じカスタム ドメイン名を持つことはできないという制限が報告されています。アプリのスケール ユニットをチェックして、それらが異なることを確認します。スケール ユニットは、FTP URL のドメイン名を調べることで見つけることができます ( <scale-unit>.ftp.azurewebsites.windows.net)。アプリのスケール ユニットは、App Service プランの作成時に Azure によってランダムに決定され、変更することはできません。Azure は、2 つのプランが同じリソース グループとリージョンの組み合わせで作成された場合にのみ、それらが同じスケール ユニット内にあることを確認します。

## この記事を書いたきっかけ

担当している案件で「ドメイン名は現行のまま、宛先を 旧 App Service から新 App Serivce に切り替える」という作業を行った際、  
同じカスタムドメイン名は複数の App Service に割り当てられないと思いこんでしまっていたため（検証では同じスケールユニットの App Service で試したため）、 以下の手順で実施しました。

1. DNSプロパイダーの CNAME レコードを新 App Serivce の割当 URL に変更する
1. 旧 App Service のカスタムドメインを削除
1. 新 App Service にカスタムドメインを割り当て

結果、DNSのキャッシュが更新されるまで旧環境の App Service へのアクセスが発生しダウンタイムが生じてしまいました。
同じカスタムドメイン名が割り当てられるとわかっていたら、以下の手順とすればダウンタイムは発生しなかったと思われます。

1. 新 App Service にカスタムドメインを割り当て
1. DNSプロパイダーの CNAME レコードを新 App Service の割当 URL に変更する
1. DNSが伝播したら旧 App Service のカスタムドメインを削除（あるいは App Serivce を停止）
【PHP基礎】foreachで注文票を作ってみましょう！

# foreachで配列の中身を取り出すとの復習
まずは以下のコードを通して、foreachの基礎を復習します。
もし、もうforeachのことは理解だったら、「配列とforeachを通して、注文票を作ってみましょう！」との部分へ飛んでください。

## コード

```php
1  <?php
2  
3  // 1.　配列を作る
4  $prices = [
5    'コーラ'  => 100, 
6    'ビックマック'  => 490,
7    'ポテナゲ大'  => 500,
8    'サイドサラダ'  => 290,
9  ];
10
11 // 2.　foreachで、配列のキーと値を一つずつ取り出す
12 foreach ($prices as $key => $price) {
13   echo $key.' - '.$price.'円'.PHP_EOL;
14 }
```

## コードを実行した結果
```
コーラ - 100円
ビックマック - 490円
ポテナゲ大 - 500円
サイドサラダ - 290円
```

## コードの説明
* __pricesという配列を作ります__
配列の中で、4つキーとその値を定義しました。
それぞれのキーは'コーラ'、'ビックマック'、'ポテナゲ大'、'サイドサラダ'です。
キーの後ろはその値です。
例えば、5行目でのコード、「'コーラ'  => 100,」との意味は、「コーラ」というキーの値は100です。

* __foreachを通して、配列のキーと値を一つずつ取り出す__
```php
11 foreach ($prices as $key => $price) {}
```
このコードの意味は、procesからキーを一つずつ取り出してkeyに代入することと、procesから値を一つ取り出してpriceに代入することです。
そうすると、keyの中は、「コーラ」と「ビックマック」、「ポテナゲ大」、「サイドサラダ」との文字列があります。また、priceの中は100、490、500、290との値があります。

* __echoを通して、キーと値を出力します__
```php
13   echo $key.' - '.$price.'円'.PHP_EOL;
```
* 注意点
    * 変数と文字列を繋ぐ時は「.」でつなぎます。
    * PHP_EOLとは、改行との意味です。

## 配列とforeachを通して、注文票を作ってみましょう！
```php
<?php

// 配列を作る
$prices = [
    'コーラ'  => 100, 
    'ビックマック'  => 490,
    'ポテナゲ大'  => 500,
    'サイドサラダ'  => 290,
];

// 合計金額ための変数。最初の値は0にする。
$total = 0;

// 注文票を出力する
echo '--------注文票--------'.PHP_EOL;

// 配列のkey(キー)とvalue(値)を一つずつ呼ぶ出す
foreach ($prices as $key => $price) {
  // 注文内容と金額を出力する
  echo $key.' - '.$price.'円'.PHP_EOL;
  // 合計金額を計算する
  $total += $price;
}

// 合計金額を出力する
echo '合計 '.$total.'円'.PHP_EOL;
echo '----------------------';
```

結果
```
--------注文票--------
コーラ - 100円
ビックマック - 490円
ポテナゲ大 - 500円
サイドサラダ - 290円
合計 1380円
----------------------
```
このように注文票ができました！
Installer Projectsを導入

# Visual Studio 2022に Installer Projectsを導入

### 1.「メニューバー」→「拡張機能」→「拡張機能の管理」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526209/46b24eca-da75-7ed9-82bc-711d00ca8a98.png)

### 2.右上の検索ボックスにて、installerを入力し、一覧に表示されるので、「ダウンロード」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526209/7178e834-4705-2fb1-e35a-d059d6c5b94a.png)

### 3.インストールがスケジューリングされたら、Visual Studioを終了する。
開いているファイルがあると、開始されないようです。
（ずっと待ってしまいました。）
Visual Studioを終了しても、開始されます。
今回、Visual Studioを終了しました。
VSIX Installerが走り、Modify棟進めていくと、インストールが完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526209/deff4cb6-1b1d-3522-1b29-09d71c728843.png)

### 新しいプロジェクトに追加されました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526209/fa80bc25-9a33-0bce-4081-be8bcd8c19a7.png)
TypeScript - オブジェクトの型からプロパティの型を抽出する方法

はいさい！ちゅらデータぬオースティンやいびーん！んな、がんじゅーやみ？

# 概要

TypeScriptでオブジェクトの型（type）から、そのオブジェクトのプロパティの型を抽出する方法を紹介します。

また、オブジェクトの型からではなく、推測（Infer）された型からプロパティの型を抽出する方法も紹介します。

最後に、JSDocsで同様なことをどのようにできるか、書いておきます。

# 問題の例

Reactでメモのリストを表示するアプリを作っています。

メモの型は以下の通り。`id`がややこしい！

```typescript:@types/index.ts
export type Memo = {
    id: string | number | symbol;
    body: string;
};
```

そこで、コメントを削除するロジックを追加します。

```tsx:Comments.tsx
import { useState } from "react";
import type { Memo } from "@types/index";

const memos: React.FC = () => {
  const [memos, setMemos] = useState<Memo[]>([]);

  const deleteMemo = (id　 /** ここの型をどうする？ */ ) =>
    setMemos(prev => prev.filter(memo => memo.id !== id));

  return (
    <ul>
      {memos.map(memo => (
        <li key={String(memo.id)} onClick={deleteMemo.bind(null, memo.id)}>
          {memo.body}
        </li>
      ))}
    </ul>
  );
};

export default memos;
``` 

しかし、この`deleteMemo`の関数の引数の方をどうしましょうか？

もちろん、以下のような書き方ができます。

```typescript
const deleteMemo = (id: string | number | symbol) =>
    setMemos(prev => prev.filter(memo => memo.id !== id));
```

しかし、このような書き方は冗長だし、`Memo`の`id`の方が後々のリファクタリングで変わったら、修正する箇所が増えます。

# 解決法

以下のようにすれば、`Memo`の`id`プロパティの型を抽出することができます。

```typescript
const deleteMemo = (id: Memo["id"]) =>
    setMemos(prev => prev.filter(memo => memo.id !== id));
```

意外と簡単！

こうすると、大元の`Memo`型が変わっても、TypeScriptがエラーが吐かないのでありがたいです。


## 型なしのオブジェクトから抽出する方法

以下のように推測された型からも方を抽出することができます。

```typescript
const comment = { id: 1, body: "Hello", title: "First" };

type CommentId = (typeof comment)['id']; // number
```

また、以下のように、配列からも抽出できます。

```typescript
const comments = [
    { id: 1, body: "Hello", title: "First" },
    { id: 2, body: "World", title: "Second" },
    { id: 3, body: "Wide", title: "Third" },
];

type CommentId = (typeof comments)[0]['id']; // number
```

## JSDocsの構文

上記の型抽出はJSDocsでも可能です。

### Reactの例

```jsx:Memos.jsx
//@ts-check
/** @typedef {{id: string | number | symbol; body: string;}} Memo */

import React, { useState } from "react";

/** @type {React.FC} */
const memos = () => {
  const [memos, setMemos] = useState(/** @type {Memo[]} */ ([]));

  /** @param {Memo["id"]} id */
  const deleteMemo = id =>
    setMemos(prev => prev.filter(memo => memo.id !== id));

  return (
    <ul>
      {memos.map(memo => (
        <li key={String(memo.id)} onClick={deleteMemo.bind(null, memo.id)}>
          {memo.body}
        </li>
      ))}
    </ul>
  );
};

export default memos;
```

### Commentsの例

```javascript
const comments = [
    { id: 1, body: "Hello", title: "First" },
    { id: 2, body: "World", title: "Second" },
    { id: 3, body: "Wide", title: "Third" },
];

/** @typedef {(typeof comments)[0]['id']} CommentId */
```

# まとめ

以上、TypeScriptでオブジェクトのプロパティの型を抽出する方法を紹介してきました。

TypeScriptの公式ドキュメントにこの方法を探してもなかなか見つからなかったので、<q>もしかして</q>と思ってやってみたら、できたので共有したくなりました。

また、配列として定義したタイプも同様に`[0]`と指定すると、開梱してその中の型を抽出することもついでに発見したので、ますます面白くなりました。

今後も、ぜひ、TypeScriptのこういった便利な機能を見つけていきたいと思います！
NextJS+ThreeJS+electronでメタバース

## なぜこんな面倒なことをするのか？

通常ゲーム開発をする場合Unityを使いますが、私はJSの勉強のためにあえてUnityもUnrealEngineも使わずにメタバースの開発をやってみます。

## とりあえずhello world

```js
import React from 'react'
import {ChakrProvider} from '@chakra-ui/react'

export default function Home () {
    retrun (
        <React.Fragment>
            <ChakrProvider>
                <div>Hello</div>
            </ChakrProvider>
        </React.Fragment>
    )
}

```

次回はこれに3DデータのJSファイルを紐づけていきます。
Rubyで配列や文字列を部分的に反転

以前に next_permutation のアルゴリズムを[勉強していた](/HMMNRST/items/26786552a2660735d34f)際、**配列の一部分だけを逆順に並べ替える操作**が（メソッド一発では）できないことが気になった。 C++ の [`std::reverse`](https://cpprefjp.github.io/reference/algorithm/reverse.html) であれば、列の始端と終端を指定するので部分的にもできそう。

---

メソッドが無いなら作っておけばいいか、ということで作ってみた。

実装に使うメソッドは範囲指定可能な `#[]` と `#[]=` のみなので、配列だけでなく文字列にも適用できる。複数のクラスを拡張するならモジュール化しておくと良さそう。

```ruby
# Array と String に共通のメソッドを使って実装
module SequenceExtension
	# 破壊的メソッド
	# ※ #[] が列を返さないような引数は考慮していない
	def reverse_in_range!(*args)
		self[*args] = self[*args].reverse!
		self
	end

	# おまけ：非破壊的メソッド
	def reverse_in_range(*args)
		self.dup.reverse_in_range!(*args)
	end
end

# include なり refinement なりで追加
Array.include(SequenceExtension)
using Module.new { refine(String) { import_methods SequenceExtension } }

ary = [0, 1, 2, 3, 4]
p ary.reverse_in_range(1, 3) #=> [0, 3, 2, 1, 4]
ary.reverse_in_range!(2..-1); p ary #=> [0, 1, 4, 3, 2]

str = "abcd-xyz"
str.reverse_in_range!(/\w+/); p str #=> "dcba-xyz"
```
ActiveRecordでの条件付きのリレーションについて

# 概要
ActiveRecordでは「has_many, has_one, belongs_to」をモデルに定義することでテーブル間同士の関連性を表すことができます。
この関連性ですが、単純なテーブル同士の関係だけではなく、条件を定義することで任意の関連性を表現出来るので、そのことについてまとめます。

# 基本
開発チームとチームメンバーをDBで管理する場合を考えてみます。
開発チームには複数のチームメンバーがいるので、開発チームとチームメンバーの関係は1対nになります。
名前を`teams`, `members`とします。
![名称未設定2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264889/da52d669-a155-4c27-8ee0-04a3be6f7c0f.png)


モデルで定義すると以下のようになります。
```ruby
class Team < ApplicationRecord
  has_many :members
end

class Member < ApplicationRecord
  belongs_to :team
end
```

# 条件付きの関連性
突然ですが、開発チームはグローバルな多国籍チームでした。チームメンバーの国籍を`nationality`というカラムで新しく定義することにします。
この例において、以下のように日本国籍のチームメンバー、アメリカ国籍のチームメンバーなどを開発チームのモデルに関連性として定義することができます。モデルのスコープに近いでしょうか。
```ruby
class Team < ApplicationRecord
  has_many :members
  has_many :japanese_members, -> { merge(Members.where(nationality: 'japanese')) }, class_name: 'Member', inverse_of: :team, 
end
```

# 応用
またまた突然ですが、開発メンバーの中には複数のチームに所属するメンバーがいることが分かりました。
そのため開発チームとチームメンバーの関連性は多対多です。`team_members`という中間テーブルを定義してこれを表現することにします。
![名称未設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264889/7565160a-5f50-1c47-a707-3f9a103e1ae7.png)


モデル定義は以下のようになります。
```ruby
class Team < ApplicationRecord
  has_many :team_members
  has_many :members, through: team_members
end

class TeamMember < ApplicationRecord
  belongs_to :team
  belongs_to :member
end

class Member < ApplicationRecord
  has_many :team_members
  has_many :teams, through: team_members
end
```

この場合で、先ほどの日本国籍のチームメンバーをモデルに関連性として定義すると以下のようになります。
```ruby
class Team < ApplicationRecord
  has_many :team_members
  has_many :members, through: team_members
  has_many :japanese_members, -> { merge(Members.where(nationality: 'japanese')) }, through: team_members, source: 'team'
end
```

# おまけ
チームにはリーダーが1人だけいることとします。
リーダーかどうかは`is_leader`というbool型のカラムで定義することにします。
teamにhas_oneでリーダーのメンバーを定義しようとすると以下のようになります。

```ruby
class Team < ApplicationRecord
  has_many :team_members
  has_many :members, through: team_members
  has_one :lead_team_member, -> { merge(TeamMembers.joins(:team).merge(Members.where(is_leader: true))) }, class_name: 'TeamMember', inverse_of: :team
  has_one :lead_member, source: 'member', through: lead_team_member
end
```
has_manyで定義した中間テーブルを通して(throughして)、直接has_oneを定義することはできないので、まずteam_membersに対してhas_oneを定義します。
次に上記で定義したhas_oneの関連を通して(throughして)、最終的にmemberテーブルに対してhas_oneの関連性を持たせることができます。

mergeやwhereがネストしたりして可読性が落ちるので（かつテストも書きづらくなるので）、一つ一つスコープで定義するとよりわかりやすく簡潔に書けるかと思います。