OmniAICreator/Qiita-1.07M huggingface dataset:
WebRTCを初めて使用する際に調査したことをまとめてみた

# はじめに
WebRTCとは「Web Real-Time-Communication」の略で、Webブラウザを通して映像や音声データの高速リアルタイム通信を可能にした規格です。
ZOOMみたいなビデオチャットアプリを作れたりします。
WebRTC自体は一つのプロトコルというよりも、様々な技術要素を組み合わせて成り立つ集合体のようなものです。
本記事では、WebRTCを構成する技術要素と通信を確立するまでの流れを記載します。

# API
WebRTCは3つのAPIが提供されている。

1. getUserMedia : ブラウザからカメラ・マイクへアクセスするためのAPI

2. RTCPeerConnection : 映像・音声を送り合うためのAPI

3. RTCDataChannel : 任意のファイルを送り合うためのAPI

# プロトコル
WebRTCは様々な技術要素が組み合わされて成り立っている。
プロトコルスタックはこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165658/5762272e-6bff-0a58-2790-c5984f96c3f0.png)



### Audio/Video(RTCPeerConnection)
映像・音声の符号化情報をパケット化するRTPを暗号化した、SRTP（Secure Real-time Transport Protocol）を使用している。
共有鍵を交換するためにDTLSの機能の一部を使用している。

### DataChannel
ストリーミング向けの転送プロトコル、SCTP（Streaming Control Transmission Protocol）を使用している。
DTLS（Datagram Transport Layer Security）により暗号化されている。

### STUN、TURN、ICE
通信セッションを確立する際にNAT/Firewallを越えてネゴシエーションするための一連の標準プロトコル。
#### STUN（Session Traversal Utilities for NAT）
自身に割り当てられたパブリックIPを知るためのプロトコル。
STUNサーバーはパブリックにアクセス可能で、Googleもパブリックなstunサーバ「stun.l.google.com:19302」を提供している。
#### TURN（Traversal Using Relays around NAT）
ポート範囲の制限・固定やTCPでの通信、パケットの暗号化を実現するプロトコル。
NAT/Firewallで通信が制限される場合、TURNサーバを経由してストリーミング情報を送信する。
#### ICE（Interactive Connectivity Establishment）
STUNとTURNを組み合わせ、通信先へ到達する経路情報を取得するためのプロトコル。
通信経路の候補となるIP/Portの組み合わせをICE Candidateと呼び、通信先と交換する。
すべてのICE Candidateが揃ってからSDP（後述）とまとめて交換する方式を「Vanilla ICE」、先にSDPだけを交換してからICE Candidateを順次交換する方式を「Trickle ICE」と呼ぶ。

### その他
#### SDP（Session Description Protocol）
解像度、フォーマット、コーデック、暗号化などのストリーミングメディアの情報などを記述するための規格。
通信を始める側から送るSDPをoffer、通信に応答する側から送るSDPをanswerと言う。

# 通信の確立
WebRTCの通信を確立するには、接続先とSDP、ICE Candidateを交換しなければなりません。
この交換をシグナリングと言い、シグナリングサーバを介して行います。
が、シグナリングに関してはWebRTCで定義がないので、実装者に一任されています。
## 通信確立までのフロー
### Vanilla ICEの場合
ICE Candidateが全てで揃うまで待ち、リストをSDPに詰めて送信します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165658/646ff318-617b-fa69-f17e-07c274f703fb.png)

### Trickle ICEの場合
SDPを送信後、準備できたICE Candidateを個別に送信します。
初期接続確立までの遅延を最小限にすることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165658/42f16214-5291-c828-06f3-6081356611c6.png)

## 参考
WebRTC
https://www.slideshare.net/nttwestcon/20140805-technical-description-of-webrtc-second-edition-public-edition-main-presentation-38236711

STUN、TURN、ICE
http://www.wata-lab.meijo-u.ac.jp/file/seminar/2017/2017-Semi1-Yuma_Kamoshita.pdf
【CI/CD】Tavern で API 自動テスト！

# はじめに
Tavern という API テストツールがあります。
API の Request や Response を yaml で記述することが出来ます。
@os1ma さんの記事で知りました。
このツールで API 自動テストのパイプラインを構築した話を書きます。

- 参考  
[tavern](https://github.com/taverntesting/tavern)  
[REST API 自動テストツールまとめ](https://qiita.com/os1ma/items/9eadcfb91fa26af762be)

# API テスト
僕たちのチームでは、Postman を使うことが多いです。
テストコードを見やすく、実装するため、Tavern を使うことを決めました。

# 実装
1. `tavern` を入れた Container を build する。
2. `tavern` のテンプレートを実装する。  
```
tavern-ci --stdout test.yaml --log-to-file test.log
```
3. runner を用意する。
4. GitLab から runner を起動する。

gitlab-ci の log は、こちら。

```yaml:log
============================= test session starts ==============================
platform linux -- Python 3.9.0, pytest-6.1.1, py-1.9.0, pluggy-0.13.1
rootdir: /builds/tests
plugins: tavern-1.6.0
collected 1 item
test.tavern.yaml F                                             [100%]
=================================== FAILURES ===================================
...

============
TESTS0020 0.033
TESTS0025 0.634
TESTS0030 0.0910001
TESTS0085 0.0579998
TESTS0090 600.011
TESTS0095 86.047
TESTS0105 112.684
TESTS0110 0.0489998
TESTS0115 0.0439999
TESTS0120 11.638
TESTS0125 0.346
TESTS0141 0.0600002
TESTS0190 0.0309999
TESTS0210 0.511
TESTS0220 6.805
============
Job succeeded
```

# まとめ
これが今回構築した自動テストのパイプラインです。

以上。

皆さんの参考になれば幸いです。
dockerのmount volumeのpermissionをfixuidでなんとかする

fixuidというコマンドを使う方法を知ったので共有します。

# 問題

docker/docker-composeでhostからvolumeをマウントして、そこへファイルを吐き出すと、rootで吐き出されてしまう。
あるいは、コンテナ内で作ったユーザーに対応するユーザーがhost側にいない
あるいは、host側のユーザーのUID/GIDを指定してdocker runしても、今度は当該ユーザーがコンテナ内にいない。

# 問題の根源

docker buildした時とdocker runする時で同じシステムとは限らない
なので、userのid、groupのidが異なってしまう。

# 対処

概ねこのような感じです

```make_env.sh
#!/bin/sh

# 適切な.envを作成できればこれを使わなくてもよい
touch .env
echo "UID=$(id -u $USER)" >> .env
echo "GID=$(id -g $USER)" >> .env
echo "UNAME=$USER" >> .env
```

```Dockerfile
...
RUN useradd hoge # ユーザー名は各自かっこいいのつけて
RUN USER=hoge && \
    GROUP=hoge && \
    curl -SsL https://github.com/boxboat/fixuid/releases/download/v0.5/fixuid-0.5-linux-amd64.tar.gz | tar -C /usr/local/bin -xzf - && \
    chmod 4755 /usr/local/bin/fixuid && \
    mkdir -p /etc/fixuid && \
    printf "user: $USER\ngroup: $GROUP\n" > /etc/fixuid/config.yml
# ここまでrootユーザー
# ここからhogeユーザー
USER hoge:hoge

ENTRYPOINT[ "fixuid" ]
# 他にもENTRYPOINTを使っている何かが有ればunshift的につければいい
# ENTRYPOINT[ "fixuid", "docker-php-entrypoint" ] 等
```

```docker-compose.yml
hoge:
  image: php:latest
  user: "${UID}:${GID}" # <= .envから読みこまれる
  volumes:
    - ....
```

# 使い方

```
# 各自、使う人が初回に叩いて.envを生成する
./make_env.sh

# あとは普通に使える
docker-compose up -d
```

# 原理

- Dockerfileのベストプラクティスに則ってbuild時にuserを作っておく。この時点では、UID/GIDはランタイムと一致する保証はない。
- LinuxのユーザーのUID/GIDは書き換えることが出来る。fixuidはそれを実施した上で、渡したコマンドを実行してくれる
    - 4xxxパーミッションが付いた実行ファイルは、その実行ファイルのownerの権限で動作する。fixuidはコレを利用してsudoなしでuid変更を実現する
    - 他にも$HOMEの書き換えなどやってくれる様子
- docker run時に、host側ユーザーのuid/gidを外部から与えることで、ファイルシステムに記録されるuid/gidをhost-guestで一致させる
    - 与える手段としては.envを使う。docker-composeは.envを読んでくれる
    - uid/gidはidコマンドで取得
- uid/gidが一致しているので、hostからもguestからもちゃんと読める！

# 参考:

- https://github.com/boxboat/fixuid
- https://boxboat.com/2017/07/25/fixuid-change-docker-container-uid-gid/
- https://qiita.com/yohm/items/047b2e68d008ebb0f001#%E3%81%86%E3%81%BE%E3%81%8F%E3%81%84%E3%81%8F%E6%96%B9%E6%B3%951--entrypoint%E3%81%A7useradd%E3%81%A7%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%92%E4%BD%9C%E3%82%8B
- https://qiita.com/cheekykorkind/items/ba912b62d1f59ea1b41e#setdotenvsh
- https://qiita.com/cheekykorkind/items/ba912b62d1f59ea1b41e#envsetdotenvsh%E3%81%8B%E3%82%89%E4%BD%9C%E3%82%89%E3%82%8C%E3%81%BE%E3%81%97%E3%81%9F
- https://qiita.com/hikaruna/items/e04371fd49da0338ad81
- https://qiita.com/cognitom/items/6d8af8a71552ec9c6212#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E6%A8%A9%E9%99%90--fixuid-
動的にリソースIDを取得する2つの方法

静的に定義されたリソース ID をプログラム上から取得する方法です。


# getIdentifier を使う

Resources クラスで定義されている `getIdentifier` を使います。

[Resources  \|  Android Developers](https://developer.android.com/reference/android/content/res/Resources#getIdentifier(java.lang.String,%20java.lang.String,%20java.lang.String))

たとえば、`strings.xml` 内で、`prefix_01` `prefix_02` ... `prefix_10` のように文字列が連番で定義されているとします。これをプログラム上から動的に得るには、

```kotlin
for (i in 1..10) {
    val id = resources.getIdentifier("prefix_${i.toString().padStart(2, '0')}", "string", packageName)
}
```

とします。

# リフレクションを使う

リソースファイル内で定義されたリソース ID が連番になっていないなど、何らかの理由で上記の方法が使えない or 使いにくい場合は、リフレクションを使います。

たとえば、`strings.xml` 内で `prefix_` から始まる文字列のリソース ID を全て取得したい場合は、次のようにします。

```kotlin
for (field in R.string::class.java.declaredFields) {
    if (Modifier.isStatic(field.modifiers) && !Modifier.isPrivate(field.modifiers) && field.type == Int::class.javaPrimitiveType) {
        try {
            if (field.name.startsWith("prefix_")) {
                val id = field.getInt(null)
                // do something
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}
```

異なるパッケージ内の `R` を参照する場合は、パッケージネームを直接指定する必要があります。

```kotlin
com.example.R.string::class.java.declaredFields
```

# 参考
[文字列からリソースIDを取得する \- Qiita](https://qiita.com/t-kashima/items/9462af782fb5f1a2a7da)
[android \- How to easily iterate over all strings within the "strings\.xml" resource file? \- Stack Overflow](https://stackoverflow.com/questions/10633456/how-to-easily-iterate-over-all-strings-within-the-strings-xml-resource-file/17607449#17607449)
CentOS8にはunarのバイナリがないのでbashで代替を作った

# why

メジャーな圧縮ファイルの解凍用にunarコマンドが便利 - Qiita https://qiita.com/twittarsan/items/550b18c222ceb75d0181

centos7のepelにはあったんだけどcentos8からは無くなっている。
のでラッパー的な代替を作った

# source
https://github.com/tknr/unar_centos8

## requires

gzip
p7zip
tar
unrar
unzip
## install

```

./install.sh

```

## usage

example:

```

unar foo.zip
unar bar.rar
unar .

```
eof


## 補足
epelにあった
https://centos.pkgs.org/8/epel-x86_64/unar-1.10.7-1.el8.x86_64.rpm.html
IBM i Services Directory : QSYS2.SYSTEM_VALUE_INFO ビュー

## 概要

■ビュー名：QSYS2.SYSTEM_VALUE_INFO
■カテゴリ：実行管理サービス
■サポート：IBM i 7.2以降

DSPSYSVALコマンドに類似した機能をSQLから実行できます。
WHERE句でシステム値名称その他条件を指定し検索できます。

## 使用例

■すべてのシステム値を取得する。

```
SELECT * FROM QSYS2.SYSTEM_VALUE_INFO
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/53ff1d39-399f-3ba5-c3a6-dcf4f7c9ecb9.png)


■disclaimer
・当ドキュメントは個人の見解を基に記述しています。所属する団体・企業の公式なドキュメントではありません。
・当ドキュメント内のサンプルなど個人の見解に基づく記述について、IBM S/Wサポート(SMWA等）へのご質問等はしないでください。当記事への質問としていただけますと幸いです。
セルラー通信モジュールの買い方

# MEMO

セルラー通信モジュールってどれ買えばいいのか正直わからないけど、
とりあえず調べた内容をまとめて公開しておく。

## セルラー通信モジュールのメーカー

1. u-blox
2. SIMCom
3. Sierra Wireless
4. Meiglink
5. Fibocom
6. スマホ作ってるメーカー(HUAWEI、ZTEなど)

日本在住であれば、1が一番手に入りやすい。
MouserやDigi-Keyの通販サイトでテスト用のブレイクアウトボードが売っている。
SARA-U201のブレイクアウトボードとしてCLICK-3Gは、マイクロテクニカ社が[マニュアル](http://www.microtechnica.tv/support/manual/CLICK-3G_man.pdf)を出しているので、
マイクロテクニカ社から入手した方がテストで困ったときに質問しやすいかも。

次に2が手に入りやすい。
SIMComは、キャセイ・トライテック社やマクニカ社が取り扱っている。
キャセイ・トライテック社はSIMComの代理店なので、そこから買えば技術的な相談がしやすいかも。

その他のメーカーは海外通販で取り寄せるしかない。
Aliexpressが一番取り寄せやすい。
ただ、届くまでに2~3週間はかかるので計画的に買おう。

## おすすめのメーカー

### u-blox

- 通販で取り扱っているところがある
- 日本語文献が少しある
- u-bloxの公式サイトに質問掲示板がある(英語)、優しい外国人が教えてくれるし、トラブルシュートの知見が貯まってる

### SIMCom

- 日本に代理店がある
- 日本語文献が少しある
- 安い:2000~3000円
- 販売元に質問できるし優しく答えてくれる(Aliexpressで買った場合)

初めてセルラー通信モジュールをテストするならu-bloxかSIMComがおすすめ。
前述でもあるように、その2つのメーカーは技術的な相談がしやすい。

## 型式の選び方

これも正直わからん。

注意点

- 生産終了している型式が通販に流れているときがある
- 海外通販で買う場合、日本の電波周波数を拾えるか見る

### SIMComの場合

型式は以下のように示される。

```
SIM[Series number][Area symbol]
Series number: シリーズの数字
Area symbol: 電波周波数が対応している地域を示す大文字のアルファベット
```

`SIM7500A`であれば7500シリーズのAの地域に対応する型式であることがわかる。
日本であれば`[Area symbol]`は`JC`、`G`が対応していることが多い。
使いたいSIMのキャリアの電波周波数が対応しているか仕様書を見るようにしよう。

## 接続用インターフェース

セルラー通信モジュールのブレイクアウトボードのインターフェースは、主に3つある。

- TTL
- mini pci
- m.2

どれもPCへUSB接続するために専用のUSBアダプタ/コンバーターが必要である。
TTLはUSB接続に変換するのに1つ1つQIコネクタ(ピン)をどこに差し込むか考えなくてはいけないので、
抜き差しだけで済むmini pciまたはm.2がおすすめ。
m.2はあまり普及してないので、mini pciが多い。
iOSアプリ「ここどこくん」をリリースしました

この度、iOSアプリ「ここどこくん」
https://apps.apple.com/us/app/%E3%81%93%E3%81%93%E3%81%A9%E3%81%93%E3%81%8F%E3%82%93-%E7%8F%BE%E5%9C%A8%E5%9C%B0%E4%BD%8F%E6%89%80%E5%8F%96%E5%BE%97%E3%82%A2%E3%83%97%E3%83%AA/id1547381423

を公開しました!!

当アプリでは、下記の技術を使用しております。

■使用技術
1,CoreLocationを使用した現在位置取得
2,逆ジオコーディングによる住所算出
3,MapKitによる現在位置のマップ表示

■利用シーン
緊急時で住所を今知りたい
仕事で現住所を知りたい
地図上でどこにいるかを知りたい

■対応端末・OS
iPhone･iPad
AppleWatchに対応しております。
対応OS
iOS14.0～
Watch OS 7.0～

このアプリのレビューを是非いただけましたら大変うれしいです!
CSVを使ったユーザー括登録スクリプト【Powershell】

アカウント登録を手作業でやるのが面倒なので、いろいろ参考にしつつ作りました。


```CSV:UserAcountInfomation.csv
SurName,GivenName,DisplayName,UserName,Domain,Profile,OU,Group1,Group2,Group3,Group4,Group5
スクリプト確認ユーザ,01,スクリプト確認ユーザ01,ScriptUser01,JahsDev2.local,,TestOU,DNSAdmins,Protected Users,TestGroup1,TestGroup2,TestGroup3
スクリプト確認ユーザ,02,スクリプト確認ユーザ02,ScriptUser02,JahsDev2.local,,TestOU,DNSAdmins,Protected Users,TestGroup1,TestGroup2,TestGroup3
スクリプト確認ユーザ,03,スクリプト確認ユーザ03,ScriptUser03,JahsDev2.local,,TestOU,DNSAdmins,Protected Users,TestGroup1,TestGroup2,TestGroup3
```


```Powershell:test

Import-Module ActiveDirectory
$CSV_FilePath = ".\UserAcountInfomation.csv"

Test-Path $CSV_FilePath
switch ($?){
    True{
    #真判定処理
        $Password = "Password!2#"
         Import-Csv $CSV_FilePath | %{
            $AddADUsers = @{
                Name = $_.UserName                                                         #ユーザアカウント名
                Surname = $_.SurName                                                       #姓
                GivenName = $_.GivenName                                                   #名
                DisplayName = $_.DisplayName                                               #表示名
#                msDS-PhoneticLastName = $_.FirstName                                       #姓(カナ)
#                msDS-PhoneticFirstName = $_.LustName                                       #名(カナ)
#                msDS-PhoneticDisplayName = ($_.FirstName + ' ' + $_.LustName)              #フルネーム(カナ)
                UserPrincipalName = $_.UserName + '@' + $_.Domain                          #ユーザプリシンパル名
                AccountPassword = (ConvertTo-SecureString -AsPlainText $Password -Force)   #パスワード
                ChangePasswordAtLogon = $True                                              #次回ログオン時にパスワード変更する
                Enabled = $True                                                            #ユーザ有効化　 
            }
            New-ADUser @AddADUsers  # アカウント追加
        }
        Import-Csv $CSV_FilePath | ForEach-Object{
            Add-ADGroupMember -Identity $_.Group1 -Members $_.UserName
            Add-ADGroupMember -Identity $_.Group2 -Members $_.UserName
            Add-ADGroupMember -Identity $_.Group3 -Members $_.UserName
            Add-ADGroupMember -Identity $_.Group4 -Members $_.UserName
            Add-ADGroupMember -Identity $_.Group5 -Members $_.UserName
        }
    }
    False{
    #偽判定処理
        Write-Host(" Error:CSVファイルが存在しません。 ")
        pause
    }
    Default{
    #判定外処理
    Write-Host(" 例外処理 ")
        pause
    }
}

```

※CSV上にOUの項目がありますが、一括で移動したいなーという理由で作ったは良いものの
　ドメインの情報を「 . 」毎に分割したり、OUは変数的に入れたりなど考えたら面倒になって
　実装してないです。
※最初からグループは5つまで設定可能です。
※カナはあってもなくてもいいのでコメントアウトにしてます。

【参考資料】
https://syachiku.net/ad-powershell-add-csv/
https://qiita.com/mindwood/items/6c4324604bec234f050c
【ネットワーク用語】IPヘッダーとは

__[IP](https://qiita.com/sasami_dc2/items/0a6446ff2e11bd47fc94)__はIPパケットの先頭部に記載されていて、送信元、宛先のIPアドレスなど通信制御用の情報が記載されている。
IPヘッダーに記載されている内容は以下の表に基づいた20バイト以上で記載される。

|フィールド名|ビット長|内容|
|:--|:--:|:--|
|バージョン|4|IPプロトコルのバージョン|
|ヘッダー長(IHL)|4|IPヘッダーの長さ|
|サービスのタイプ(ToS)|8|パケット送信時の優先度|
|全長|16|IPメッセージの全長|
|ID情報(Identification)|16|個々のパケット識別番号|
|フラグ|3|有効なのは2ビット分で、フラグメンテーションの可否を表すものとフラグメントしたものかどうかを表すもの2ビット。|
|フラグメント・オフセット|13|IPメッセージの先頭から何番目に位置するかを表す。|
|生存期限(TTL)|8|永久ループが発生した際に抜け出せるように生存期限を指定する。|
|プロトコル番号|8|プロトコル番号が記載される。([こちらを参照](https://qiita.com/sasami_dc2/items/bf25866bfe0cc4e94590))|
|ヘッダー・チェックサム|16|誤り検査用(現在は使用されていない)|
|送信元IPアドレス|32|発信元のIPアドレス|
|宛先IPアドレス|32|送信先のIPアドレス|
|オプション|可変長|上記以外のヘッダー・フィールドを記載するオプション追加が可能|
form_withで検索機能を実装する

#はじめに
Railsのform_withを使って検索したい情報をコントローラーへ送信して、
indexページに一覧表示する機能の実装方法を書いていきます。

#実現したいこと

今回はPostテーブルから自分が検索したワードを本文に含んだ投稿を
Postコントローラーのindex.html.erbに一覧表示していきたいと思います。

[実行環境]
Ruby 2.7.2
Rails 6.0.3.4

#検索条件の送信

```erb:search.html.erb

<%= form_with url: posts_path, method: :get, local: true do |f| %>
  <%= f.label :post_key, '検索' %>
  <%= f.text_field :post_key %>
  <%= f.submit, '検索する' %>
<% end %>
```

今回はindexページで検索結果一覧を表示するので、urlはindexに対応しているpathを入力します。
表示したいページがindexとは異なる場合には表示したいページに対応したurlを入力してください。

methodをgetに指定することでindexに繋がるルーティングを通りindexアクションに
検索したい値を送信することができます。
これを指定しておかないとmethodがpostで送信されてしまいエラーがでます。

:post_keyに検索したい値が格納されるので、
コントローラーに記述するワードと共通していれば:post_keyでなくても任意のワードを指定できます。

#検索結果一覧表示のコントローラー

```ruby:posts_controller.rb
def index
  if params[:posts_key]
    @posts = Post.where(params[:posts_key])
  else
    @posts = Post.all
  end
end
```

入力フォームから送信されてきた:posts_keyがここにたどり着きます。
elseの動作は、なにも入力せず検索ボタンを押した場合すべての投稿が表示されるようになっています。


#indexページで検索結果を一覧表示

```erb:index.html.erb

<p>"検索結果: <%= @posts.count %>件</p>
<ul class="posts">
  <%= @posts.each do |post| %>
    <li class="post">
      <%= post.content %>
    </li>
  <% end %>
</ul>
```

今回はページネーションを使わずに実装したので、
eachメソッドを使って繰り返し処理を実行して検索結果一覧を表示していきます。

countメソッドを使って検索結果の件数を表示しています。

#終わりに
以上の手順で検索機能が実装できるかと思います！
もし不備やわからないところがあれば気軽にコメントして
いただけるとありがたいです！
最後まで読んでいただきありがとうございました！
リモートホストへのGet-Eventlogが遅いのが自業自得だった

# 何の話か
リモート先のWindowsイベントログを取得したく`Get-EventLog -ComputerName HOSTNAME`とするとげろげろ遅い。遅かった理由は自分の勘違い。勘違いしていた書き方を直して早くした。

# Get-EventLog
Windowsイベントログを取得するコマンドレット。
例えばチェックディスクの結果ログ(ソース名`Wininit`)であれば、以下で取得できる。

```powershell:chkdsk結果ログを取得する
#chkdsk結果ログの情報取得
Get-EventLog -LogName Application -Source "Wininit"

#内容を表示したい場合
(Get-EventLog -LogName Application -Source "Wininit").Message
```

`-EntryType`(Warning、Infomationなど)、`-After``-Before`(日付時刻指定)、`-username`(ユーザー名指定)、`-Newest n`(新しいものからn件)など表示を絞り込めるパラメータがある。


# リモートホストに使うと遅い

Get-EventLogをローカル環境で実行した場合と、リモートホストに対して使用(`-ComputerName HOSTNAME`)した場合で、実行時間に大きな開きがある。

```powershell:Get-EventLog実行時間
#ローカル環境で
Measure-Command{
  Get-EventLog -LogName Application -Source "Wininit"
} | Select-Object TotalSeconds

#TotalSeconds
#------------
#3.7275934

#リモートホストに対して
Measure-Command{
  Get-EventLog -LogName Application -Source "Wininit" -ComputerName HOSTNAME
} | Select-Object TotalSeconds

#TotalSeconds
#------------
#128.8473589
```

これは指定したイベントログの内容を全部読んでパラメータ指定したものに該当するのを抽出しているせいらしい。リモートホストから貰ってたら時間がかかって当然。

そこで、`-Newest 100`と読み込む個数を指定すれば早くなるかな？と思い実行した。
しかし、これが全然早くならない。あれー？

```powershell:Get-EventLogが早く…ならない
Measure-Command{
  Get-EventLog -LogName Application -Source "Wininit" -ComputerName HOSTNAME -Newest 100
} | Select-Object TotalSeconds

#TotalSeconds
#------------
#124.5613644
```

#-Newest 100の意味

`Get-EventLog -LogName Application -Source "Wininit" -ComputerName HOSTNAME -Newest 100`と指定した場合の動作は、

誤：HOSTNAMEの　イベントログApplicationから　新しいログから順に100個読み込んで　ソース名Wininitのものを探せ。
正：HOSTNAMEの　イベントログApplicationから　ソース名Wininitのものを　新しいログから順に100個見つかるまで探せ。(100個なければ最後まで読むことになる)

…なのであった。
よく読んでみれば自分で書いた通りに動いているだけなんである。


#改良案

先にログを100個だけ読んで、それからパイプで渡してフィルタかけてやればいい。

```powershell:改良案
Measure-Command{
  Get-EventLog -LogName Application -Newest 100 -ComputerName HOSTNAME |
  Where-Object{$_.Source -eq "Wininit"}
} | Select-Object TotalSeconds

#TotalSeconds
#------------
#1.4705983
```

おお早い。

なお、これだと直近100個以内にお目当てのログがないと何も出てこない。
チェックディスクの結果ログなら終わった後すぐ読みに行くので、まず100個か200個以内くらいにあるから、まあ構わないか。
協働ロボットがいかにして製造業の労働問題に立ち向かうのか 

全米製造業者協会が昨年初めに発行した見通し調査では、多くの企業幹部が、製造現場における熟練の労働者を見つけるのが難しいと感じていることが明らかになりました。製造技術者協会（SME）による別の調査からも（さまざまな製造業者へのインタビューを実施）その結果が確認されています。SMEは、製造業者の約89％が、業務遂行に十分な熟練労働者を見つけることができていない、という事実を目の当たりにしました。

この状況がすぐに変わることはないでしょう。デロイトによると、今後10年間で製造業によって460万人以上の雇用機会が創出されるものの、その半分近くが「空白」になるとされています。このような不足は、すべての業界で見られています。製造業者は、業界におけるスキル不足に対処するために、人的に可能なことは何でも挑戦しています。

一部の企業経営者は、残業の実施、臨時スタッフの採用、退職時期の延長といった対策に目を向けています。会社を運営し続けるためにとられるそのような抜本的な措置は、ビジネスを傷つける可能性があります。一部の企業は、その仕事に適した労働力を確保できないために、新規事業を断念せざるを得ませんでした。多くの企業は、労働力の制約に対処しなければ、この10年で事業に終止符を打つことになるかもしれません。

![1600px_COLOURBOX35554517.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/857503/9c74b89e-df2f-859b-0a35-076e2f79f17c.jpeg)


<h2>解決策とは？</h2>
製造業における熟練の労働者不足に対処するために、多くの企業が自動化に目を向けています。ただし、一部の中小製造会社では、これに関連する技術スキルが不足しているため、製造プロセスに自動化を実装できていません。
![How-Well-Is-Your-Cobot-REALLY-Performing.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/857503/2c7e10f3-6162-76e1-6d3d-e24eeac15f6e.jpeg)

このような課題のほとんどは、ロボット産業で急速に成長を続けるセグメントである協働ロボットを使用することで対処できます。多くの企業が、協働ロボットを採用しています。協働ロボットは、柔軟性があり、統合が容易で、低コストで、設置に必要な面積が小さく、人間の傍で安全に作業にあたることができます。これらの特徴により、小規模メーカーと大規模メーカーの両方にとって魅力的です。

協働ロボットの使用は、メーカーによる変化を続ける消費者需要への適応も助けます。現代の消費者は高度に作り込まれた革新的な製品を求めています。これこそが、協働ロボットの提供できる価値です。多くの製造業者が協働ロボットを好んで採用しています。これにより、よりコンパクトな生産ラインで、複数の代替モデルを構築することができます。
コボットによる製造の近代化

<center>![Compliance-for-Robotic---collaborative-robots.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/857503/43c06b26-3a87-d6e0-5332-c7618c6bb0e0.jpeg)</center>


産業用ロボットは19770年代に導入されました。主に生産性と速度を向上させるために設計されています。初期のロボットは購入と設置に費用がかかりました。また、生産現場で広いスペースを占めることになる安全システムの設置も必須でした。また、プログラムを作成して運用を続けるには、高度な訓練を受けた技術者やエンジニアが必要でした。

協働ロボットは、従来のロボットとほぼ同様の結果を生み出します。人間にとって退屈で、汚い、危険な、そして反復的な仕事を引き継ぐことができます。産業用ロボットの導入により、高品質の製品が生産され、スクラップが削減され、歩留まりが向上しました。協働ロボットは、その一部として、従来のロボットよりも多くの新しい旨みをメーカーにもたらします。

協働ロボットは、人工知能と機械学習という特徴を備え、人間と一緒に安全に作業することができます。軽量で設置面積が小さいため、生産現場のあらゆる場所に使用できます。コボットには、マシンテンディング、組み立て、ピックアンドプレース、パッケージングなどのさまざまな作業をこなすアームが搭載されています。



<h2>コボット製造現場の新展開</h2>
ロボット産業は、製造環境を変える革新を絶えず生み出しています。エンドオブアームツーリング（EoAT）デバイスの導入により、<a href="https://www.universal-robots.com/ja/">ロボットアーム</a>にさらなる価値が付加されました。このツールは、ロボットによるマシンテンディングの精度を高めます。ロボットで使用されるこのようなツールのほとんどは、安全で、ユーザーフレンドリーで、取り扱いが簡単です。

チェンジャーなどのEoATデバイスの導入により、技術者は生産現場でグリッパーを交換することができます。これにより、1台のロボットを使用して生産現場でさまざまなタスクを実行できるため、柔軟性が向上します。また、ロボットをある作業から別の作業に切り替えるのに必要な時間、コスト、および労力も削減されます。

この10年間、多くの企業は、あらゆるテクノロジーを活用してビジネス変革の方法を模索し続けています。機械と人間の協働により、コスト削減、品質の向上、生産の合理化という面での見事なバランスが実現します。
Git Hubは何のために使うか？基本コマンドについて

#はじめに
git hubは開発現場でも、アプリの個人開発するうえでも必須スキルですし習得できれば、とても便利です。

gitが裏側で何をしているのか、実際にコマンドを入力したときに何が起こっているのか、git hubについて何ができるのかを基本的なことから、勉強しながら少しずつアウトプットできたらと思います !

## gitは何のために使うか？
・ファイルのバージョンを管理するためです。ファイルのバージョンを管理しないと、最新のファイルが出したい場合ほかのファイルに混ざってどこに保存したかわからなくなったりします。一人のときはそのくらいで収まるかもしれませんが複数人になったときにはもっと悲惨なことになりますw。

##例えば
決算資料のExcelを共有サーバーにおいて複数人で編集しているのを想像してみてください。決算資料のExcelがあって、Aさんが先に編集しました。で、あとからBさんがAさんが編集したのに気がつかず上書きしてしまいました。
こういうことが起こるわけです！
誰がいつ何を変更したのかがわかれば、便利に効率よく仕事できますよね！

ファイルのバージョンを管理すれば最新の状態がわかったり、『いつ、誰が何を変更したか』も、わかります。さらに毎回のバージョンが記録されているので、何かあったとき以前の状態にも戻せるようになります！
だから、複数人の編集がとっても楽になります！さらに誰かが編集したものを気づかずに編集しようとすると、警告を出すようにもなってるんですね！！
こういうことがgitでバージョンを管理するとできるようになるんです！

#ターミナルで頻繁に使うコマンド

Gitはターミナルで作業するので、その時に絶対に覚えておいてほしいコマンドだけまとめました。

###cdコマンド

ディレクトリを移動します。

###lsコマンド

ディレクトリの内容を表示します。 ls -a コマンドで、隠しファイルを含めたディレクトリ全内容を表示します。

###mkdirコマンド

ディレクトリを新規作成します。

###rmコマンド

ファイルを削除します。

###cpコマンド

ファイルをコピーします。

###mvコマンド

ファイルの移動とファイル名の変更を行います。

###catコマンド

ファイルの中身を表示します。


##GitHub単語
###リポジトリ
ファイルやディレクトリの変更履歴を管理するもの
リモートリポジトリ　　サーバーにあるイメージ
ローカルリポジトリ 　自分のPCにあるイメージ

基本的には、以下の流れでgithubを使っていく!!
ローカルでファイルを修正をする。
ローカルリポジトリに追加。修正内容のコメントを入れる。
リモートリポジトリに追加する。

###branch　merge
branchは変更履歴（リポジトリ）を分岐させる時に使用する！
どういうときにやるのか？
１つのファイルに対して異なる変更が必要な時（バグの修正、新規機能の追加など）
各自修正したbranchを１つのmasterにまとめ直すのがmerge


流れ
メインのbranchから、自分用のbranchを作成し作業を行う。
作業が終わり次第、メインのbranchにmerge

###基本コマンドと作業
git checkout -b hoge1
自分用のブランチ作成と移動
-bをつけることで、作成と移動ができる

git add test.html
まず、ローカルリポジトリにファイルを追加
※複数追加ある場合はこのタイミングで追加

git commit -m "テスト用アップ"
リポジトリに対して変更の内容を記述

git push origi hoge1
ローカルリポジトリをリモートリポジトリ（branch）にあげる。

実際には、この後masterファイルにmergeする

#おわりに
次回からは、もっと深ぼれたらと思います！
Linuxでのsambaのマウント。起動時にマウントするまで。

## sambaをマウントしたい。どうせなので起動時にマウントしたい。

環境は Raspberry Pi 4 の Raspberry Pi OS 10.7
sambaサーバーを勉強に立てたので、それをマウントするまでに調べたことのまとめ。
mountコマンドでのマウント → fstab に記述しての起動時の自動マウントの順にやりました。


###mountコマンドの基本
マウントコマンドの基本は

```bash
$ mount -t <ファイルシステムのタイプ> <デバイス> <マウントポイント>
```


###オプション- t で指定すべきタイプ
オプション -t で指定するのはファイルシステムのタイプ。
ファイルシステムとはなんぞやというのはここでは置いておいて、
今回 samba のマウントで指定べきタイプは ```-t cifs``` になる。

ファイルシステムに `cifs` を指定するためには `cifs-utils` がインストールされていなければならないので、一応確認しておきましょう。


```bash
$ apt list cifs-utils
一覧表示... 完了
cifs-utils/stable,now 2:6.8-2 armhf [インストール済み]
```
大抵は`smbclient`と一緒にインストールされてるはず。

###オプション -o で指定すべきもの
mountコマンドには `-r` `-w` などのオプションもあるが使わない。
その他の細かいオプションはすべて ```-o <オプション>,<オプション>,<オプション>``` のように `-o` の後にコンマ区切りで併記していく。

####mount.cifs のオプション
```-t cifs``` を指定すると mount.cifs が呼び出されるので、そちらのオプションを見なければならない。
ファイルシステムによって動きが違うから使えるオプションも変わるのだなと私は理解しました。

mount.cifs について
http://www.samba.gr.jp/project/translation/3.5/htmldocs/manpages-3/mount.cifs.8.html

というわけで -o の後に書くべきものは、
```-o user=<ユーザー名>,password=<パスワード>```
がまず最低限必要になります。


+ 他に書くべき候補
 + `rw` （読み取り書き込みできるようにするもの。私はうまくいかず↓を使った）
 + `file_mode=664` （マウントしたファイルのパーミッションの指定）
 + `dir_mode=775` （マウントしたディレクトリのパーミッションの指定）
 + `uid=<ユーザー名>` （マウントするもののオーナーを任意のユーザーにする）
 + `gid=<グループ名>` （マウントするもののグループを任意のグループにする）


ここまでを整理として、ここまででできた部分を繋げるとこう。
```mount -t cifs -o user=<ユーザー名>,password=<パスワード>,file_mode=664,dir_mode=775```


###マウントの実行

マウントするためにはマウントする場所にディレクトリが必要なので /mnt の下に作成する。
```# mkdir -m 777 /mnt/<マウントポイント>```

ようやくマウントができる。

```
# mount -t cifs  -o user=<ユーザー名>,password=<パスワード>,file_mode=664,dir_mode=775  //<ホストアドレス>/<ディレクトリ>  /mnt/<マウントポイント>
```

確認
```$ df -Th```


アンマウント
```$ unmount /mnt/<マウントポイント> ```



##/etc/fstab へ記述して起動時にマウントする

/etc/fstab はマウントするデバイスとファイルシステムを記述するファイルで起動時に読まれる。


###fstabの基本
記述は、

```
 <デバイス>  <マウントポイント>  <ファイルシステムのタイプ>  <オプション>  <dump>   <fsck>
```

`<dump>` には `0~1`
`<fsck>` には `0~2`
が入る。
その役割はここでは置いておいて、sambaのマウントを考えるなら両方 `0` を入れる。

あとは mountコマンド でマウントした時の記述と同じ。
ファイルシステムは `cifs`
オプションは `-o` の後にコンマ区切りで記述したものです。

###リモートファイルシステムはsystemdに自動マウントさせる

起動時にリモートファイルシステムをマウントさせるなら、systemdによる自動マウントさせましょう。

`_netdev,x-systemd.automount`
のふたつのオプションを記述するだけで、マウントをネットワークがオンラインになるまで待ち、またそのあとsystemdがうまいことマウントしてくれます。

このあたりのテクニックについては ArchWiki の fstab の頁にわかりやすく書いてありそれを読みました。
https://wiki.archlinux.jp/index.php/Fstab


###/etc/fstab にパスワードを書きたくない
`/etc/fstab` はおそらく多くの人のアクセスできるようすべきファイルで、そんなところにパスワードを書きたくはありません。

そんな時は `credentials=<path>` オプションを使い、ユーザーとパスワード情報を記述したファイルを別に用意してそれを読ませましょう。

今回は`/etc`に`smb-credentials`というディレクトリを作りその中に`.password1`というファイルを作ることにします。
パーミッションを適切に管理しましょう。

`.password1` に記述すべき書式は以下の通り。

```
username=<ユーザ名>
password=<パスワード>
```

###fstab への記述

`/etc/fstab` に記述します。

```
//<ホストアドレス>/<ディレクトリ>   /mnt/<マウントポイント>   cifs  _netdev,x-systemd.automount,credentials=/etc/smb-credentials/.password1,file_mode=664,dir_mode=775  0  0
```

`reboot` してマウントできれば成功。
シェル 速度計測

## 速度計測
```
start_time=`date +%s`
echo -n '開始時刻 ' > speedcheck.log
date "+%Y/%m/%d %H:%M:%S" >> speedcheck.log

echo  'start 計測対象one ' >> speedcheck.log
### 計測したい処理・コマンド ###
sleep 2
### 計測したい処理・コマンド ###
end_time=`date +%s` 
run_time=$((end_time - start_time))
echo $run_time >> speedcheck.log
echo  'end 計測対象one ' >> speedcheck.log

echo  'start 計測対象second ' >> speedcheck.log
### 計測したい処理・コマンド ###
sleep 3
### 計測したい処理・コマンド ###
end_time=`date +%s` 
run_time=$((end_time - start_time))
echo $run_time >> speedcheck.log
echo  'end 計測対象second ' >> speedcheck.log

echo -n '終了時刻 ' >> speedcheck.log
date "+%Y/%m/%d %H:%M:%S" >> speedcheck.log
```

## 出力結果
```
開始時刻 2021/01/08 14:17:28
start 計測対象one 
3
end 計測対象one 
start 計測対象second 
6
end 計測対象second 
終了時刻 2021/01/08 14:17:34
```
Macの「Automator」でファイル名を一括変更(リネーム・名前変更)する

# はじめに
「Automator」とは、Macに標準搭載されているアプリケーション。作業を自動化してくれる。
Automator 一括リネーム 等で検索すると類似の記事はあるが、数年前のものが多かったため投稿。

# Automatorの設定
1. Automatorを起動し、新規を選択。
![スクリーンショット 2021-01-08 13.50.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011610/18db0f46-1150-2fb0-673f-b643f2ef6897.png)
2. アプリケーションを選択。![スクリーンショット 2021-01-08 13.53.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011610/c5004cc5-96db-af41-aedb-fbfad1bd46e0.png)
3. 変数から「Finder項目の名前を変更」を選択し、右にドラッグ。![スクリーンショット 2021-01-08 13.54.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011610/cb1b15ba-ec97-5813-51ea-26dd2b622ec8.png)
4. アラートが出たら、追加しないを選択します。
![スクリーンショット 2021-01-08 13.56.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011610/a6344319-2914-f76f-263a-a9cd246ea5f9.png)

5. 連番付きの名前を選択し、各項目を設定
![スクリーンショット 2021-01-08 13.59.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011610/81c30f80-d17a-a0ec-aff5-2f538b669215.png)
6. 連番の後ろに数字を追加したい場合は、名前のあとにテキストを追加します。![スクリーンショット 2021-01-08 14.01.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011610/c3a643e5-2feb-0ad6-4b1f-68db8c97ba21.png)
7. 全ての設定ができたら、⌘+Sでデスクトップ等に保存します。
![スクリーンショット 2021-01-08 14.02.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011610/16494444-533f-1a07-2a8c-963e1328aae9.png)

# ファイル名の一括変更の実行
1.変更したいファイルを選択し、設定したアプリのアイコン上にドラックします。
 ![スクリーンショット 2021-01-08 14.05.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011610/04965d84-f74b-0a2f-cd20-32ad4d7c423a.png)
2.これでドラッグしたファイルの名前が一括で変更されます。
「CISOハンドブック―業務執行のための情報セキュリティ実践ガイド」（技術評論社）

2021年1月20日、「CISOハンドブック―業務執行のための情報セキュリティ実践ガイド」（著作 JNSA CISO支援ワーキンググループ）が出版される運びとなりました。

企業のセキュリティを扱う数多くの良書がありますが、本書は、「CISOが経営陣の一員として成すべきこと」に焦点をあて、実践のためのガイドを提供しているという点でユニークです。加えて、経営陣がCISOを活用するための理解を促し、「経営陣がCISOと共に成すべきこと」を示す試みであるともいえます。

| CISOハンドブック| ―業務執行のための情報セキュリティ実践ガイド  |
| ---- | ---- |
|  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529969/2c5c36b7-7b2d-459e-b45f-f31c74d1fa6e.png)| CISOハンドブック<br>―業務執行のための情報セキュリティ実践ガイド<br>著作： JNSA CISO支援ワーキンググループ<br><br>出版社 : 技術評論社 (2021/1/20)<br>発売日 : 2021/1/20<br>単行本（ソフトカバー） : 400ページ<br>ISBN-10 : 4297118351<br>ISBN-13 : 978-4297118358
|

# 概要
本書で述べる「成すべきこと」は、単にセキュリティ実践を学んでいる人なら誰もが理解していることの集約ではありません。実際、わたしたちにとっても、手強いテーマでした。前作を現マイクロソフトの河野さんと書き始めたときは、3か月程度で形にできると踏んだのですが、専門分野の常識として理解しているつもりでも、あやふやなことや、体系立てられていないことが多岐に及びました。

その後、JNSA CISO支援ワーキンググループを立ち上げ、さらに多くの知見を得ることで、2018年5月に「CISOハンドブック Ver1.0β」として公表することが出来ましたが、結果的に公表まで2年半の期間が必要でした。この間、ご期待いただいている方々からのお問い合わせに「もうすぐできる」と言い続けていたことから、「蕎麦屋の出前プロジェクト」と呼ばれたりもしていました。

今回の刷新版の製作にあたっては、技術評論社から出版の機会を頂き、JNSA CISO支援ワーキンググループに新たなメンバーも加わったことで、拍車がかかりました。コロナ禍の影響などで計画よりも時間がかかりましたが、1年少々でVer 1.0βで盛り込まれたことを再整理し、かつ書き切れていなかった点にも踏み込むことが出来ました。すなわち、基本的なセキュリティ対策に加え、技術系の人間が苦手な経営という意味でのマネジメント、セキュリティ対策の経緯を知るためのインシデント推移も取り上げています。結果として、目次だけで266行、内容は400ページとなり、そこそこ重たい本となりました。

完成した書籍を見ると、改めて不十分な点やアップデートをしていきたい点も見えてきます。しかし、読者の皆様がご自身の現場で「CISOが経営陣の一員として成すべきこと」を議論し、早期に実践を進めていくための道筋を示すことには貢献できると考えています。また、セキュリティについて比較的経験の浅いCISOや、CISOを支える担当者が、ご自身の業務を推進するための絵地図としても使って頂きたいと思います。

JNSA CISO支援ワーキンググループは、これからも活動を継続していく予定です。本書の至らない点についても、ワーキンググループとして取り組み、さらに良いものにつなげていきたいと考えています。また、多くの方にワーキンググループにご参加いただき、議論を深める機会を広めていきたいと思います。

# 謝辞
最後になりますが、多くの専門家の皆様の知見とアドバイス、また様々な経験と機会を頂きました。執筆陣の力だけでは、ここまでの形にすることは出来なかったと思います。
ご協力を頂いた皆様に改めてお礼を申しあげます。

JNSA CISO支援ワーキンググループ
「CISOハンドブック」 執筆者一同
テストコードの効率化

## はじめに
オリジナルアプリ制作にあたり、FactoryBotとFakerを用いてテストを行ったので、忘れないように載せておこうと思います。
**FactoryBot:** あらかじめ各クラスのインスタンスに定める値を設定しておくGem
**Faker:** メールアドレス、人名、パスワードなど、ランダムな値を生成するGem
**前提として、テストファイルuser_spec.rbがすでに生成してあるとする。**

## 1.gemの導入と段取り
1. FactoryBotとFakerのGemをGemfileのgroup :development, :test do内に記述し、bundle installする。

```ruby:Gemfile
group :development, :test do
# 中略
  gem 'factory_bot_rails'
  gem 'faker'
end
```
<br>
2. specディレクトリ内にFactoryBot用のディレクトリ（①）を作成し、さらにその中にFactoryBot用のファイル（②）を作成する
　（例）　spec / factories(①) / users.rb(②)


## 2.FactoryBot用ファイル（②）内に記述
1 で作成したファイル内に**FactoryBot**と**Faker**を用いてコードを記述する
Fakerの公式GitHub　https://github.com/faker-ruby/faker

```ruby:FactoryBot用ファイル（②）
FactoryBot.define do
  factory :user do
    name        {Faker::Name.name}
    email       {Faker::Internet.free_email}
    password    {Faker::Internet.password(min_length: 8)}
    birthday    { '2000-01-01' }
　  # 中略
  end
end
```

## 3.テストコードの記述
FactoryBot.build(:user)と記述し、Userのインスタンスを生成する。
また、**before**を用いて、それぞれのテストコードを実行する前にインスタンスを生成。

```ruby:user_spec.rb
require 'rails_helper'
RSpec.describe User, type: :model do
  before do
    @user = FactoryBot.build(:user)
  end

  describe 'ユーザー新規登録' do
    it "nicknameが空だと登録できない" do
      @user.name = ""
      @user.valid?
      expect(@user.errors.full_messages).to include "Name can't be blank"
    end
    it "emailが空では登録できない" do
      @user.email = ""
      @user.valid?
      expect(@user.errors.full_messages).to include "Email can't be blank"
    end
    # 中略
  end
end
```

## 最後に
一度学習した内容でしたが、うろ覚えだったので、復習できてよかったと思います！
twigファイルで変数にHTMLタグを入れる方法

```twig:.twig
{{ link }}
```
```php:.php
 //省略
 $this->view->var['link'] = '<a href="">リンク</a>';
````

こんな感じでtwigファイルにlinkと記述した変数にHTMLタグを入れて<a href="">リンク</a>を出現させたかったのだが、実際にはHTMLタグがそのままテキストとして表示された。

#解決法
```twig:.twig
{{ link|raw }}
```

これでエスケープされずにすみました。
[  JavaScript入門 ] falsyな値とtruthyな値とはなんなのか？またどのような時に使用するのか。

# falsyな値とは:point_up:
　***falsyな値というのはBooleanで真偽値に変換した場合にfalseになる値のこと。***

どゆこと、、、？

まずは、Booleanってなに？
***Booleanは真偽値に変換するもの***:raised_hand:

例えば、

```
let a = 0;
console.log(Boolean(a));


結果としてコンソールにはfalseと表示される
```
どういう事かというと、今回の場合、0というのは、Booleanによって真偽値に変換した時falseと等価になることがわかる。

##falsyな値

|falsyな値 |
|---|
|false |
|null  |
|0  |
|undefined  |
|0n |
|NaN  |

< 空文字列 "" も falsy ですね。

JavaScript の仕様には含まれませんが、ブラウザ環境だと歴史的な理由により document.all も falsy だったりします。
(オブジェクトであるにもかかわらず何かに変換しようとすると undefined としてふるまう) >

***@nagtkk さんにご指摘頂きました。***
***有り難うございます！***


***これらがfalsyな値としてあげられる***:raised_hand:

##truthyな値
***truthyな値は、falsyな値以外と覚えておく***


##どのような時活用するのか

プログラムを書いている際に、変数に値が入っているかどうか確認したい時がある:frowning2:　(値がnull、undefined以外か確認する）
***そんな時活用！！***

```
let a = parseInt("");
console.log(Boolean(a));

if(a) {
    console.log('hello');
} 
```
このようにif文の中にいれることによってaの値がfalsyな値かどうか確認することができる。この段階ではaという値はfalsyな値であることから、***if文の中の記述は実行されない。***

```
let a = parseInt("");
console.log(Boolean(a));

if(!a) {
    console.log('hello');
} 
```
このようにすることで、逆にfalsyな値であった時実行する。そのようなことも可能。

***しかし、今回、値がnull、undefined以外か確認するということをしたい為、他のfalsyな値である0のときだけを確認したい場合、違った記述が必要となる。***:frowning2:
必要最低限のgitコマンド一覧

##投稿の趣旨
gitの勉強をしている際に、覚えるべきgitコマンドがかなり多く頭がパンパンになってしまったため備忘録として記載する。


###カレントディレクトリの移動する。

カレントディレクトリ　「.」
ホームディレクトリ　　「~」
ルートディレクトリ　　「/」

```
$ cd ~      //ホームディレクトリの場合
```
###カレントディレクトリのパスを確認する。

```
$ pwd
```

###新しいディレクトリを作成する。

```
$ mkdir ディレクトリ名
```

###ローカルリポジトリを作成する。

```
$ git init
```

###ステージングエリアに変更を登録する。

```
$ git add ファイル名
```

###コミットする。
-m：コミット時にコメントを追記するオプション
-am：ワークツリーから一気にコミットしてコメントを追記するオプション

```
$ git commit -m"コメント"　
```

```
$ git commit -am"コメント"　
```

###ワークツリーの変更を取り消す。
不要なファイル修正をしてしまった際に、コミットした時のファイルに戻す。
但し、このコマンドで取り消せないケースがあり、それは以下の2点。
その場合はコマンドではなく自身でファイルを削除する必要がある。
・ファイルを新規作成したとき。（コミット自体していないため）
・ファイル名を変更したとき。（ファイル名を変更すると追跡できないため）

```
$ git checkout -- ファイル名
```

###ワークツリーに特定のバージョンを反映する。
ブランチを作成して、作業するバージョンの切替えに使用する。

```
$ git checkout ファイル名
```

###ステージングエリアへの登録を取り消す。
間違ってステージングエリアに登録してしまったときに使用する。
ステージングエリアというステータスのみ取り消すため、ワークツリーでの
変更は取り消されない。

```
$ git reset HEAD ファイル名
```

###ファイル、ディレクトリを削除する。
Git管理下にある不要になったファイルもしくはディレクトリを削除する。
削除した場合もコミットが必要になるので忘れないこと。

```
$ git rm ファイル名
```

```
$ git rm -r ディレクトリ名
```

###コミットの履歴を確認する。

```
$ git log
```
###リポジトリをフォークする。
複数人で作業するとき等、複製元のリモートリポジトリをフォーク（複製）して、自分のリモートリポジトリに取得する。さらに、下のクローン作業でローカルリポジトリに取得し作業を開始する。
フォークする方法は、複製元のリモートリポジトリをGitHubで検索し、Forkボタンをクリックするのみ。

###リモートリポジトリをクローンする
GitHubのClone or downloadのSSHを選択し、記載されているURLをコピーし、以下のコマンドを入力する。

```
$ git clone URLをコピペ
```

###ファイルの差分を確認する。
ワークツリーとステージングエリアの差分を確認。

```
$ git diff
```

ステージングエリアとGitディレクトリの差分を確認。

```
$ git diff --cached
```

###Gitで管理しないファイルの取り扱い
ローカルリポジトリに「.gitignore」ファイルを作成し、管理しないファイル名を中に記載する。当ファイルを保管する場所は「.git」ディレクトリと同じレベルの階層が望ましい。.gitignoreの効果がある範囲は、.gitignoreを配置したディレクトリ配下のパスであるため。
管理したくないファイルを一度ステージングエリアへ登録し、git stutasで確認すれば反映されているかどうかを判断できる。

####管理すべきではないファイル
・自動生成される一次ファイル（ログファイル、パッケージファイル、バックアップファイル）
・OSのファイル管理に伴うもの（WindowsのThumbs.db、macOSの.DS_Store）
・パスワードが書かれたファイル             ...etc

###ブランチする。
元データであるmasterブランチに対し、編集用のファイルを作成（分岐点の形成）する。
ブランチを作成して編集するときは、どのブランチを操作しているのか認識して実施すること。
git checkoutコマンドで操作するブランチを切り替えることができる。

```
$ git branch 作成するブランチ名
```

また、ブランチの一覧を表示したい場合は以下のコマンドで表示できる。
選択しているブランチは、*の印が付いている。
（git statusコマンドでも、on branchの項目に記載されている）

```
$ git branch
```

###ブランチをプッシュする
ローカルリポジトリで作成したブランチを、リモートリポジトリへ反映させること。
流れとしては、そのデータをチェックして頂いた（レビュー）後、マージ（ブランチの結合）する。

```
$ git push origin プッシュするブランチ名
```

リモートリポジトリに元データが存在しない場合（新規作成）、以下のコマンドでGitHubへプッシュし、ローカルリポジトリへ反映する。

```
$ git remote add origin https://から始まるリモートリポジトリのURL
$ git push origin master
```
###リモートリポジトリからローカルリポジトリへ反映する。
マージされた最新データを、ローカルリポジトリへ反映する。（プル）
※masterブランチにcheckoutしてから実施すること。

```
$ git pull origin master
```
ワークツリーへの反映はせず、内容を確認したいだけの時（ローカルリポジトリに入れたいだけの時）は以下のコマンドを使用する。（フェッチ）
その後、ワークツリーに反映したい場合はプルする。

```
$ git fetch origin
```
【AT Command】google.comへpingを打つ (SIMCom: SIM7000G)

# Memo

SIM7000GからAT Commandを使ってgoogle.comへpingを打つ方法。
個人的な備忘録なので、わかりにくいことや指摘があれば是非コメントお願いいたします。
それに合わせて更新します。

## 環境

- OS: windows10
- ターミナル: Tera Term

## ハードウェア

- インターフェースモジュール: mini pcie usbアダプタ
- セルラー通信モジュール: SIMCom SIM7000G
- SIM: soracom plan-D

## ログ

```
AT+CSTT="soracom.io","sora","sora"
OK

AT+CGDCONT=1,"IP","soracom.io"
OK

AT+CIICR
OK

AT+CIFSR
10.224.194.152

AT+CIPPING="www.google.com"
+CIPPING: 1,"172.217.26.36",73,117
+CIPPING: 2,"172.217.26.36",77,117
+CIPPING: 3,"172.217.26.36",80,117
+CIPPING: 4,"172.217.26.36",78,117
```

## AT Command

使用したSIMComのAT拡張コマンド(AT+)の解説。
`AT`のあとに`+`がついているCommandは各社の独自のCommandである(だから拡張コマンド)。
Commandの使い方は基本的に、`ATCommand=?`のようにCommandに`=?`をつければ見れる。

### AT+CSTT

>Start Task and Set APN, USER NAME, PASSWORD

と記述されているので、APNの設定。
APNの設定でユーザー名やパスワードを設定しなくてもいけるらしい。([FXFROG](https://www.fxfrog.com/2019/04/10/post-7976/))
一度設定したらOKっぽい。
再度指定しようとするとERRORする。

### AT+CGDCONT

>Define PDP Context

PDPコンテキストの定義なんだろうけど、
APNを指定するようなイメージでいいのかな?
一定時間経過するとIPアドレスが開放されるので通信できなくなる。
そのため、再度`AT+CGDCONT`を打つ必要がある。

### AT+CIICR

無線通信の有効化。
これでAPNのアクティベートか?
うーん、`AT+CGACT`となにが違うんだろう。
このコマンドは一度打てばOKっぽい。
再度打つとERRORする。

### AT+CIFSR

ローカルIPアドレスの確認。

### AT+CIPPING

Pingの要求。
任意の回数を指定できる。
`AT+CIPPING="URL",回数`

※セルラー通信モジュールのメーカーごとにPingを要求するコマンドが違うので注意。

## 参考文献

1. [FXFROG](https://www.fxfrog.com/2019/04/10/post-7976/)
2. [さくらのIoTブログ](https://sakura.io/blog/category/tech/)
3. [SIM7000シリーズのAT Commandマニュアル](https://simcom.ee/documents/SIM7000x/SIM7000%20Series_AT%20Command%20Manual_V1.04.pdf)
初期設定ターミナルがすごく見づらいので、改行して見やすくしてみました

## 初期設定のターミナルが見づらすぎる問題

VSCodeやMacのターミナルを使っていると、一度に処理行が多すぎて
今回の処理分がどこからなのかがわからなくなること、ありますよね。

これは簡単に変更できるみたいですが、かなり詰まってしまったので、
プログラミング初学者で同じ問題を抱えた人のためにこの記事を書きたいと思います。

この記事で対応している環境
`MacOS Catalina以上`
`Shell zsh`

↓目標
![スクリーンショット 2021-01-08 13.42.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699910/d60cceaf-b5db-0293-60dc-706411ddf589.png)



## わかる人向け

`~/.zshrc`に以下を追記してください。

```shell:.zshrc
PROMPT='%F{green}%n@%m%f　:　%F{cyan}%~%f
$ '
```

## Shellとは

> シェルは入力装置などによる利用者の操作を受け付けて、対応する動作をOSカーネルや他のソフトウェアに指示したり、それらからの出力を画面に表示するなどして利用者に伝える。簡易なプログラムなどを記述して与えることで操作を自動化することができるようになっていることが多い。

> [シェルとは - IT用語辞典 e-Words](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwi997DXj4ruAhXGMd4KHYN4BU8QFjAFegQIBhAC&url=http%3A%2F%2Fe-words.jp%2Fw%2F%25E3%2582%25B7%25E3%2582%25A7%25E3%2583%25AB.html&usg=AOvVaw0e69gVvVcqtuPu128RO6dr)


つまり、ユーザーとPCを繋げてくれるもののことです。

Shellにはいくつかの種類があり、Macの標準では
`MojaveまでがBash `、`Catalinaからがzsh` になります。
（ここ大事です）

これらは、ターミナル起動時のタイトルに書いてあるので確認しておいてください。

これからは標準Shellがzshの人向けに説明していきます。

## .zprofile と .zshrc

Shellには設定ファイルが2つあります。
bashでは`.bash_profile`と`.bashrc`になります。

### .zprofile

こちらはユーザーログイン時に一度だけ読み込まれます。

空ファイルのままで大丈夫です。

### .zshrc


こちらはインタラクティブモードで読み込まれます。
つまり、ターミナルなどを起動した時に読み込まれます。

こちらに追記していきます。

## 結論

`~/.zshrc`に以下を追記してください。

```shell:.zshrc
PROMPT='%F{green}%n@%m%f　:　%F{cyan}%~%f
$ '
```

## 参照

[【macOS】10.15 Catalinaのzshプロファイルに対応する](https://www.yokoweb.net/2019/10/12/macos-catalina-zsh-profile/)
[zshの設定ファイルの読み込み順序と使い方Tipsまとめ](https://qiita.com/muran001/items/7b104d33f5ea3f75353f)
vimにpluginを入れて育成を始める。

## プラグインマネージャーを選ぶ

vimのプラグインを管理する
プラグインマネージャーをインストールする

[参考サイト](https://qiita.com/kumamo-n/items/ddbb4fbe073873d90bba)

今回シンプルなvim-plugを採用

```
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
```

`vim .vimrc`に以下を追記

```
call plug#begin()
#インストールしたいプラグインのgithubのリポジトリを指定
call plug#end()
```

## プラグインを入れてみる

例えばvim内でgitが使える[tpope/vim-fugitive](https://github.com/tpope/vim-fugitive)を入れてみる。

`vim .vimrc`のリトポジ指定場所に以下を追記

```
set number

call plug#begin()

#追記内容
Plug 'tpope/vim-fugitive'

call plug#end()
```

vimを開き`:PlugInstall`でプラグインをインストールする。

vim内で`:Gstatus`と入力し実際に使ってみる！
> vim内に`git status`と同じ内容が表示されるはず、

## その他設定

vimに行番号などを表示するには.vimrcに以下を追記する

```
set number
```

## .vimrc最終的にどうなったか

```
set number

call plug#begin()
Plug 'tpope/vim-fugitive'
call plug#end()
```

# まとめ
このようにvimにpluginや行番号などの設定を変えて自分好みに
vimを育成もとい、カスタマイズをし**扱いやすいようにしましょう！**

## 動機
vimにプラグイン入れようかなと思った事とQiitaを始めてみたので投稿してみました。
初投稿で不備が多々あると思います(・。・)

### 動作環境
> ubuntu 20.04
LaTeXのbibTeXで参考文献をアルファベット順で出力する


# はじめに

$\LaTeX$では，bibTeXを使うことで，`bib_name.bib`ファイルをもとに自動で参考文献を出力することができます．

これは，以下のようにすることで，参考文献を出力できます．

```latex
\bibliography{bib_name}
\bibliographystyle{junsrt}
```

これは，参考文献情報を`bib_name.bib`から取得し，
`junsrt.bst`(bibtex style file)で，参考文献をソートしています．

`bib_name.bib`は使いたい好きなファイル名に変えてください． 
例えば，`ganariya.bib`などにすれば，`\bibliography{ganariya}`として参考文献情報を読み込みます．


# アルファベット順にする

アルファベット順にするには`jplain`を使うと良いです．
これ以外にも，学会指定のスタイルファイルやデフォルトスタイルなど，他のアルファベット順のスタイルファイルがあると思います．
それらから一つ選んで使うと良いです．

```latex
\bibliography{bib_name}
\bibliographystyle{jplain}
```

# 追記 2021/07

`K. ganariya` のように名前を省略表記で出力したい場合は，`jabbrv`を`junsrt`の代わりに指定するとよいです．
ロリポップ！からケチケチバックアップする話

## ０．初めに

私は、非エンジニアのドシロウトです。しかも貧乏（汗）です。

元々、無料レンタルサーバーのXFREEで、とあるPHP製のオンラインメモの保管ツールで個人的なメモを保存し、テスト利用していました。

[無料レンタルサーバー【XFREE(エックスフリー)】](https://www.xfree.ne.jp/)

自分専用のオンラインメモツールは、意外と便利だったので、本格的に使って行こうと考えました。

XFREEの無料版は容量が1GB、SSL非対応で少しレスポンスも遅いときがあり、 格安のレンタルサーバーを探しました。

探した結果、結局、有名なロリポップ！レンタルサーバーで一番安いエコノミープランを試すことにしました。

[ご利用料金 - レンタルサーバーならロリポップ！](https://lolipop.jp/pricing/)

エコノミーでも初期費用が1500円かかりますが、月額は100円で格安です。

エコノミープランは、容量20GB、SSL対応、PHPも使えますが、バックアップをするオプションを入れると月300円追加で必要です。

[バックアップ / 機能一覧 / サービス - レンタルサーバーならロリポップ！](https://lolipop.jp/service/specs/backup/#option)

貧乏な私は、Google Apps Script（GAS）を使って、なんとかバックアップできないか、試すことにしました。

## １．試したこと

試したことをまとめると以下です。

* ダウンロード用PHPツール

    ロリポップ！にあるメモ保存ディレクトリを丸ごとZIPにしてダウンロードするPHPツールの設置

* 起動/保存用GASツール

    PHPツールをHTTPベースで起動し、ダウンロードしたZIPを、Google Driveに1世代保存するGASツールの作成、トリガー設定



## ２．ダウンロード用PHPツール

以下の記事の「PHPでzipコマンドを使ってディレクトリを丸ごと圧縮する」のPHPプログラムを丸パクリしています。

[PHPでディレクトリを丸ごとZIP圧縮する方法の速度比較](https://blog.ver001.com/php-zip-archive/)

ZIPを一時保存するディレクトリを新たにロリポップ！に作ったのと以下のPHPプログラムを設置しただけです。

注）getZipのパラメタは、フルパスでの指定が必要ですが、ロリポップ！の管理画面の「ユーザー設定＞アカウント情報」で分かります。

```php:down.php
<?php
ini_set('display_errors', "On");
//$dir 取得したいフォルダパス
//$zipFileSavePath 一時、zipを保存しておくフォルダパス
function getZip($dir,$zipFileSavePath){

 // zipファイル名
    $fileName = "zipFile".time();
// 圧縮対象フォルダ
    $compressDir = $dir;

// コマンド
// cd：ディレクトリの移動
// zip:zipファイルの作成
    $command =  "cd ". $compressDir .";".
        "zip -r ". $zipFileSavePath . $fileName .".zip .";

// Linuxコマンドの実行
    exec($command);

// 圧縮したファイルをダウンロードさせる。
    header('Pragma: public');
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=".$fileName.".zip");
    readfile($zipFileSavePath.$fileName.".zip");

//    消す
    unlink($zipFileSavePath.$fileName.".zip");
}

getZip('/home/users/1/aaaa.jp-bbbbb/web/（保存ディレクトリ）','/home/users/1/aaaa.jp-bbbbb/web/（ZIP一時ディレクトリ）');

?>　
```


## ３．起動/保存用GASツール

以下の記事を参考にGASを作成しました。

[GASを使ってGoogle Drive内にあるファイルのダウンロードURLからコンテンツを取得したい - Qiita](https://qiita.com/tanaike/items/9fd1294647e2181c7765)

gasのプログラムが以下でこれを1日1回実行するようにトリガー設定しています。

```javascript:zipdown.gs
function myFunction() {

    // バックアップファイル名 ※lolipop-down.zipを使ってます
    var svrfilenamearray = [ "lolipop-down.zip",
                             "lolipop-downtest.zip" ];

    // ドライブのファイル名取得        
    var filesdel = DriveApp.getFiles();


    // ファイルがあるだけ繰り返す
    while (filesdel.hasNext()) {
      var filed = filesdel.next();
      // バックアップファイル名かチェック
      for(var i = 0; i < svrfilenamearray.length; i++) {
        if (filed.getName() == svrfilenamearray[i]) { 
          // 古いバックアップファイル削除処理
          filed.setTrashed(true);
          Logger.log(filed.getName()+" バックアップファイル削除終了");
        };
      };
    };
 

  // ロリポップ！のダウンロード用PHPツールのURLを発行して受信
  var blob = UrlFetchApp.fetch('https://（ロリポップ！のサイト）/down.php', {muteHttpExceptions: true}).getBlob();
  // Google Driveに保存
  DriveApp.createFile(blob.setName('lolipop-down.zip'));
}
```

## ４．終わりに

貧乏でなければ、普通にバックアップオプションを使った方が良いと思います。

牛丼一杯の値段ですので…

以　上
Laravel5/6/7でGoutteを使用する時はバージョン指定しないとエラーになるよ。

タイトル通りです。

Laravel5/6/7系にてGoutteを使用したい場合はインストール時にバージョン指定してあげないとエラーが出ます。

```
composer require weidner/goutte "1.6"
```

たぶんこれで、エラーなくインストールできるはず。

ちなみに、バージョン違いのエラーが出た時は使用したいライブラリの`README.md`を見れば、大抵どっかに書かかれています。

今回の場合は[こちら](https://github.com/dweidner/laravel-goutte)の最後に書かれていました！

感謝感謝(*´ω｀*)ﾉ
【JS】真偽値を確認する方法。ビックリマーク２つ（!!）の意味。

個人メモです。

変数や処理の冒頭にビックリマークを２つ`!!`つけると、真偽値の状態を確認できる。

```js:
x = 100
console.log(!!x)
//true

arr = [1,2,3]
console.log(!!arr)
//true
```

変数に`!`(反転の意)一つをつけると、値が存在すればfalse、存在しなければtrueを返す。

さらにこの戻り値にビックリマークをつけて`!!`とすれば、実際の状態にあった真偽値が返る。

**▼注意点**
0や空の配列はfalseで返る。

```js:
x = 0
console.log(!!x)
//false

arr = []
console.log(!!arr)
//false
```

<br>
if文の条件式で変数を指定した場合に、tureかfalseどっちになっているかを確認するのに便利。


##Boolean()
`!!値`は`Boolean(値)`と同じ。
可読性の観点では`Boolean`の方がわかりやすい。

```js:
x = 100
console.log( Boolean(x) )
//true

arr = [1,2,3]
console.log( Boolean(arr) )
//true
```
Eloquentのwithで指定カラムのみの取得と条件指定を同時にできなかったというお話

私が所属している会社の業務でデータの抽出処理を実装するということになったのですが、その抽出条件が多数のテーブルとそのカラムに跨っているという物でした。
その実装方法を色々試している中、「なぜこれができないんだ」と困った話について書いていきたいと思います。

LaravelのEloquentでは、Modelクラス内でリレーションを設定することで、`with`メソッドを用いて関連するモデルの情報を同時に取得するということができます。

```App\SomeData.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class SomeTable extends Model
{
    public function otherData()
    {
        return $this->hasOne('App\OtherData', 'otherdata_id');// hasManyも同様の記述
    }
}
```

```php
App\SomeTable::with(['otherData']);
// SomeTableのデータと共に、対応するOtherDataのデータも同時に取得できる
```

この時、`OtherData`の内一部のカラムの情報のみが欲しいという場合、そのカラムを記述することで取得するデータを絞ることができます。

```php
App\SomeTable::with(['otherData:otherdata_id,another_column']);
// 対応するOtherDataのデータの内、主キーとanother_columnのみが取得される
```

また、`OtherData`の内特定条件を満たすもののみを取得するということもできます。

```php
App\SomeTable::with([
    'otherData' => function($query) {
        $query->where('another_column', '<', 10);
    }
]);
// 対応するOtherDataのデータの内、another_columnが10未満のもののみが取得される
```

今回実装したい抽出処理では多数のテーブルに必要な情報が跨っているものの、その内実際に利用するカラムは僅かです。そのため、PHP側での処理が重くならないように次のようなコードを書いてみました。

```php
App\SomeTable::with([
    'otherData:otherdata_id,another_column' => function($query) {
        $query->where('another_column', '<', 10)
    }
]);
// 期待した通りには動かない
```

改めて考えてみたところ、カラム指定を行わない`with`で取得するオブジェクトはModelクラスを継承しているものになっていたのですが、カラム指定をすると単なるCollectionクラスのオブジェクトになっていました。なので、カラム指定をした場合Modelに対する`where`ではなく、Collectionに対する`where`として動作してしまい、期待した動作にはならなかったのではないかと考えています。

今回の抽出処理の実装については、ひとまず愚直にテーブルを`join`することで実装することにしました。何かいい方法があるとなればコメント等宜しくお願い致します。
VmwareFusionでのLinuxMint20仮想化メモ

VmwareFusion(バージョン12.1)によるLinuxMint20(Mate 64bit)仮想化による個人的備忘録です．

- VmwareFusionでの設定
    - ファイルから新規 → ディスクまたはイメージからインストール
        - LinuxMint20のisoを選択
    - OS： Linux → その他のLinux 5.x 以降のカーネル(64ビット)を選択
    - ブートファームウェアの指定：UEFIを選択（UEFIセキュアブートにチェックを付けない）
    - 設定のカスタマイズをクリック → 仮想マシンファイルを指定して保存
        - プロセッサとメモリを設定（お好みで）
        - ハードディスクを設定（容量が少ない場合，LinuxMintをインストールできない）
    - 設定を終え次第，設定ウィンドウを閉じて，仮想マシンを実行して，Mintのインストール作業へ

- LinuxMintのインストール
    - GRUB: Start Linux Mint 20 MATE 64-bit を選択
    - デスクトップのInstall Linux Mintをダブルクリックして，インストール設定へ
        - 言語設定: 日本語
        - キーボードレイアウト: 日本語 → 日本語
        - マルチメディア・コーデック: お好みで
        - ディスクを削除してLinux Mintをインストールを選択し，
        - ディスクに変更を書き込みますか？を続けるを選択
        - タイムゾーン: Tokyo
        - ユーザ名，パスワードをお好みで記入してインストール
        - 今すぐ再起動をするをクリック
        - Please remove the installation medium, then press Enter: Enterキーを押して再起動する 

- LinuxMint20の個人的な設定
    -  ログインする
    -  ようこそ画面を起動時に出さないようにする
    -  端末を開いて，フォルダの英語化を行う
        -  ```$ LANG=C xdg-user-dirs-gtk-update```
            -  Don't ask me this againをチェックし，Update Namesをクリックする
    -  パッケージ一覧を更新をする
        -  ```$ sudo apt update```
    -  パッケージを更新をする
        -  ```$ sudo apt upgrade```
    -  必要としないパッケージを削除をする
        -  ```$ sudo apt autoremove```
    -  以下のコマンドは実は必要はないです（すでにインストールされているため）
        -  ```$ sudo apt install open-vm-tools open-vm-tools-desktop```
    -  フォントRicty Diminishedをインストール
        -  ```$ sudo apt install fonts-ricty-diminished```
    -  端末のフォントをRicty Diminishedにする
        -  端末 → プロファイルの設定 → "固体幅のフォント"を使用する のチェックを外してフォントを設定する
    - アップデートマネージャでローカルミラーに切り替えても良いかもしれないです
IBM i Services Directory : SYSTOOLS.DELETE_OLD_SPOOLED_FILES プロシージャー

■サービス名：SYSTOOLS.DELETE_OLD_SPOOLED_FILES
■カテゴリ：スプール・サービス
■サポート：IBM i 7.3 SF99703 Level 18以降
■参照URL（IBM i 7.5）：https://www.ibm.com/docs/ja/i/7.5?topic=services-delete-old-spooled-files-procedure


読んで字のごとく、古いスプールファイルを検索して削除するプロシージャーサンプル。
スプールの存在日数、OUTQ、ライブラリー、ユーザーで対象をフィルターできます。

＜使用例＞
■OUTQ QPRINTについて50日以上前のスプールのリストを表示する。
・PREVIEW YESを指定すると検索のみで削除しない
・OUTQ名を指定しないと全OUTQが対象となる

```
CALL SYSTOOLS.DELETE_OLD_SPOOLED_FILES(DELETE_OLDER_THAN => CURRENT DATE - 50 DAYS,
     P_OUTPUT_QUEUE_NAME => 'QPRINT', 
     PREVIEW => 'YES');
```

実行すると、該当するスプールをリスト表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/9deb3871-5ec3-6d01-712d-6edb96cbf9d2.png)


■PREVIEWを'NO'に変更すると合致するスプールを削除する。

```
CALL SYSTOOLS.DELETE_OLD_SPOOLED_FILES(DELETE_OLDER_THAN => CURRENT DATE - 50 DAYS, 
     P_OUTPUT_QUEUE_NAME => 'QPRINT', 
     PREVIEW => 'NO');
```

実行すると、ステートメントは正常実行された、というメッセージが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/8712713f-bcda-8402-2ca3-96563b718007.png)


■パラメーター  （）内は属性（モード, タイプ, 長さ, CCSID, ロケーター, デフォルト値）

```
DELETE_OLDER_THAN (INPUT, TIMESTAMP, 6, , , (CURRENT_TIMESTAMP - 3 MONTHS))
P_OUTPUT_QUEUE_LIBRARY_NAME (INPUT, VARCHAR, 10, , ,'*ALL')
P_OUTPUT_QUEUE_NAME (INPUT, VARCHAR, 10, , ,'*ALL' ) 
P_USER_NAME (INPUT, VARCHAR, 10, , ,'*ALL' ) 
PREVIEW (INPUT, VARCHAR, 3, , ,'NO' ) 
```


■参考URL : https://www.ibm.com/support/pages/systoolsdeleteoldspooledfiles

■disclaimer
・当ドキュメントは個人の見解を基に記述しています。所属する団体・企業の公式なドキュメントではありません。
・当ドキュメント内のサンプルなど個人の見解に基づく記述について、IBM S/Wサポート(SMWA等）へのご質問等はしないでください。当記事への質問としていただけますと幸いです。