OmniAICreator/Qiita-1.07M huggingface dataset:
(参照設定なし)VBA/VBSでCOMオブジェクトのメソッド・プロパティ一覧を確認する方法

#概要
　VBAやVBSでCOM連携のコードを書いていて、ふとメソッド・プロパティの一覧が見たくなることがあります。
　あれ、ウインドウ取得のWindowsメソッドってShell.applicationだっけ、Wscript.Shellだっけ、メンバー見れたら分かるのになとか、僕はよくあります。
　いや、VBAなら参照設定すればインテリセンス効くじゃんって話ですけど、結局最後は配布用にCreateObjectに書き換えるのに、いちいち参照設定するのは面倒だし、書き換え漏れをなくすためにも最初からCreateObjectで書いていくこと、ありませんか？
　ネット見たくても周りの目があって見れない、そんなときに使ってください。
#方法　
　VBAでもVBScriptでも、以下のコードを実行すればメソッド・プロパティが表示されます。

```vb:VBA/VBScript共通
Dim wShell
Set wShell = CreateObject("Wscript.Shell")
wShell.Run "PowerShell -NoProfile -NoExit -Command $com = New-Object -ComObject ●ComObject名●;$com|Get-Member"
```
####実行例/ExcelVBA
<img width="900" alt="2020-05-17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/c8b30db3-439f-15af-ba07-8fb5388cf566.png">
<img width="900" alt="2020-05-17 (3).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/5ebc4bf3-7b43-037e-2b32-8379eafefa81.png">

####実行例/VBScript
<img width="900" alt="2020-05-17 (4).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/be208ba4-29c6-65d9-dc2f-b0367f77f719.png">
<img width="900" alt="2020-05-17 (5).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/b10a7e20-b619-9ab3-eaf4-e4d38e9db358.png">

　PowerShellを使います。PowerShellでは、標準でCOMオブジェクトのインテリセンスも効きますし、メンバーも取得できます。
　もちろん、PowerShellから

```powershell:PowerShell
$com = New-Object -ComObject ●ComObject名●
$com|Get-Member
```
でもOKです。
#おまけ
　メソッド・プロパティの値の取得もできます。VBAならローカルウインドウでできますが。
　PowerShellはメソッドの後ろに()が必要なので気をつけてください。

```vb:VBA/VBScript共通
Dim wShell
Set wShell = CreateObject("Wscript.Shell")
wShell.Run "PowerShell -NoProfile -NoExit -Command $com = New-Object -ComObject ●CreateObjectの名前●;$com.●メソッド()又はプロパティ●|Select-Object *"
 
```
<img width="900" alt="2020-05-17 (7).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/cca73470-27c5-f812-2d24-d0bf80fc8077.png">

<img width="900" alt="2020-05-17 (6).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622636/180bbace-24c2-4db3-0810-d8329c677821.png">

 こちらもPowerShellで直接書いた方がシンプルです。

```powershell:PowerShell
$com = New-Object -ComObject ●CreateObjectの名前●
$com.●メソッド()又はプロパティ●|Select-Object *
```

　個人的に、閉鎖的な環境で開発しているためか、VBA/VBScriptで困るとPowerShellに頼ることがよくあります。
　次回はVBA/VBScriptでWebスクレイピングする際のPowerShell併用法について書こうと思います。
　PowerShell,いいですよ！

追記
Nortonでスクリプトの実行として弾かれることがあるようです。
その場合はNorton側でEXCEL等のスクリプト実行の設定を許可してください
FirefoxでAmazon検索をする時に中国系業者を検索対象から外す

## はじめに
日本のAmazonにも多数の中国系業者が出店しており、痛い目にあった人もいるでしょう。品質もそうですが、そういう業者は中国から発送するので、購入した後手元まで届くのに結構時間がかかってしまい、後悔することもあります。

これを回避するために、商品検索結果のURLに`&emi=AN1VRQENFRJN5`を加えるだけで、その手の業者の表示が消えることが[先人により示されました](https://n-styles.com/main/archives/2017/04/14-054444.php)。また、それをMACやChromeで簡単に使う方法を提案している記事([MACの場合](http://hitoriblog.com/?p=58709), [Chromeの場合](https://yuyubu.hatenablog.com/entry/2019/10/22/chrome-extension))があります。

この記事ではFirefoxを使って同様のことをする方法を述べます。

## この記事で分かること。
* FirefoxでAmazonの商品検索時、検索結果から中国系業者を除外する方法

## 使うツール
* Firefox Addon: [Redirector](https://addons.mozilla.org/ja/firefox/addon/redirector/?src=search)

## 設定の仕方
1. Firefox Addonの[Redirector](https://addons.mozilla.org/ja/firefox/addon/redirector/?src=search)をインストールする。
2. FirefoxのAddonアイコンが並ぶ領域に以下のアイコンが現れるので、このアイコンをクリックする。<br/>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519489/4a448f86-e1c0-dcbe-97ff-fcae2eaa5c31.png)
3. `Edit Redirects`ボタンをクリックする。
4. `Create new redirect`ボタンをクリックする。
5. 以下のように入力する。
    * Description: Avoid Chinese Seller in Amazon.
    * Example URL: https://www.amazon.co.jp/s?k=test
    * Include pattern: (https://www.amazon.co.jp/s.*)
    * Redirect to: $1&emi=AN1VRQENFRJN5
    * Pattern type: Regular Expression
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519489/9440abba-020d-732f-d3e7-74badea03c1a.png)
6. `Save`ボタンを押す。

これで、下記の例示(Example)のように、Amazon検索をした時にいつも`emi=AN1VRQENFRJN5`が付くようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519489/6a8f34b9-2f5e-9819-10ad-802554153228.png)

## Redirectを一時的にやめたい時
中国系業者を利用したい時もあります。その場合は次のようにします。
1. FirefoxのAddonアイコンが並ぶ領域にある`Redirector`をクリックする。
2. `Disable Redirector`をクリックする。
DisableからEnableにしたい場合も同様な操作となります。

以上です。
SPEEDTEST をコンソールから利用する

格安SIMでよく利用されている SPEEDTEST ですが、コンソール版がありました。

https://www.speedtest.net/apps/cli

```sh
$ speedtest-cli
Retrieving speedtest.net configuration...
Testing from *****, Incorporated (49.236.225.238)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by fdcservers.net (Tokyo) [5.17 km]: 6.515 ms
Testing download speed................................................................................
Download: 78.74 Mbit/s
Testing upload speed......................................................................................................
Upload: 84.69 Mbit/s
```

上記のように簡単にネットワークの速度を得ることが出来ます。

## OSS 版について

本家のソフトウェアはOSSではないので、有志によるOSS実装もいくつかある模様です。

* https://github.com/sivel/speedtest-cli
* https://github.com/nelsonjchen/speedtest-rs

Python 版が一番人気があり、 `pip install speedtest-cli` で簡単にインストールできます。このバージョンは TCP ベースではなく、レガシー版と同様の手法で HTTP ベースで計測しているので、本家とは少し値が異なります。

レガシー版の挙動については rust 版の README に簡単な説明があります。

## 接続先について

* https://www.speedtest.net/speedtest-servers-static.php

テスト用のサーバーサイドはスポンサーがホストしていて、上記のリストから、確認できます。IPアドスから、近い順に列挙されるようになっています。IPA、楽天モバイル、筑波大などがホスティングしているようです。

|URL|スポンサー|
|---+-------|
|http://speed.coe.ad.jp:8080/speedtest/hi|IPA CyberLab|
|http://ookla.mbspeed.net:8080/speedtest/hi|Rakuten Mobile , Inc|
|http://speed.open.ad.jp:8080/speedtest/hi|OPEN Project (via 20G SINET)|
|http://speedtest.softether.co.jp:8080/hi|SoftEther Corporation|

レガシー版のファイルも置いてあるので curl を使ってテストすることも出来ます。

```sh
$ curl http://speed.coe.ad.jp/003.100Mbytes.dat > /dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  100M  100  100M    0     0  9259k      0  0:00:11  0:00:11 --:--:-- 10.1M
```
jq コマンド sed もあるよ　Linux 

# 願望
記述形式をまとめたい

# jq

```js:例
// 表示結果から " , などの区切り記号を除外
jq -r

// 表示項目の途中に特定の構文記号（改行やタブなど）を追加
jq ' .[] | .ddd + "\n" + .dddd + "\t" '

// 条件式がtrueである物のみ対象とする
jq ' .[] | select(.text != "null") | .text'

// 要素の存在有無
jq ' .[] | select(has(\"text\")) | .text'
```
```js:複数の値を抜き出す
// カンマで区切れば複数指定可能
jq ".[].Id,.[].value"
// [ ] で囲んで [ , ]形式で表示
jq "[.[].Id,.[].value]"
// |@csv で1行にまとめて表示
jq "[.[].Id,.[].value]|@csv"

// |@tsv で1行にまとめて表示して、" と /t を外して綺麗に表示
jq "[.[].Id,.[].value]|@tsv" | sed -e 's/\"//g' | sed -e 's/\\t/,/g'
jq -r "[.[].Id,.[].value]|@tsv" | sed -e 's/\"//g' | sed -e 's/\\t/,/g'
```
# sed

```zsh:sed
# ダブルクォーテーション、タブ を除去
sed -e 's/\"//g' | sed -e 's/\\t/,/g'

# その他
| sed 's/|.*$//g' | sed 's/[<>]//g'"
```

# 参考
https://dev.classmethod.jp/articles/jq-manual-japanese-translation-roughly/

https://qiita.com/minamijoyo/items/95f8e60d2fe9509f0b7e

https://beatsync.net/main/log20130428.html

https://tech.mktime.com/entry/108

https://medium.com/veltra-engineering/jq-looks-like-programming-lang-7568367c321d

https://qiita.com/Chitama/items/53161b51d31692c785f4

https://orebibou.com/2016/05/jqコマンドで覚えておきたい使い方17個/

https://tech.mktime.com/entry/127

https://momijiame.tumblr.com/post/51299899637/jq-コマンドが強力すぎてヤバい件

https://www.mtioutput.com/entry/jq-some-catch
Dockerで環境構築したローカルサイトにSSL証明書エラーでアクセスできなかった時の対処法


DockerとPHP Laravelを使用し環境構築を行った際、
`$ docker-compose up -d` でコンテナを立ち上げたあと、
ローカルサイトにhttpsアクセスすると証明書エラーが出てアクセスができない…

SSLサーバ証明書発行したはずなんだけど…と思ってたら、
**自己証明書は、基本的にブラウザに信頼されないため、信頼する証明書として手動で追加する必要がある**
とのこと。知らんかった。

ということで、
**1. SSL証明書を発行する手順
2. macOSで信頼する証明書として追加する手順**
の備忘録。

#発生したエラー
参考までに、発生したエラー

```error
この接続ではプライバシーが保護されません
NET::ERR_CERT_INVALID
```
<img width="736" alt="スクリーンショット 2020-05-15 11.58.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569980/7b4fe4f2-3597-8a30-3dbf-aad8b081680f.png">


#1. SSL証明書を発行する

```r:
 #nginxコンテナに入る
$ docker-compose exec nginx sh
 #apkアップデートとOpenSSLのパッケージのインストール
$ apk add --update openssl
 #server.keyという名前で 2048bit の秘密鍵を作成
$ openssl genrsa 2048 > server.key
 #秘密鍵から署名要求(server.csr)を作成
$ openssl req -new -key server.key > server.csr
C=JP/ST=Tokyo/L=minato-ku/O=Example/OU=Web/CN=Exampledomain
 #署名要求を秘密鍵で署名してサーバ証明書(server.crt)を作成
$ openssl x509 -days 3650 -req -signkey ./server.key -in server.csr -out ./server.crt
```
基本的なSSL証明書の発行は以上でOK。

なんかChromeの仕様変更により、ドメイン名のチェックをCommon Name(通称CN)ではなく
Subject Alternative Names(通称SAN)を参照するようになったという記事を見つけたため、
もしSubject Alternative Namesを含んだ自己署名サーバ証明書を作成する場合は以下。

```r:
 #SANの設定値を定義するtxtファイルを用意（ファイル名は任意） 
$ touch san.txt
```
```ruby:san.txt
subjectAltName = DNS:Exampledomain, IP:127.0.0.1 
```
SANの定義ファイルを用意したら、秘密鍵・証明要求を作成するところまでは先述した手順と同じ。
**サーバ証明書を作成する際に`-extfile`オプションでSANの定義ファイルを読み込ませる。**

```ruby:
 #用意した定義ファイルを読み込ませてサーバ証明書を作成
$ openssl x509 -days 3650 -req -extfile san.txt -signkey server.key < server.csr > server.crt

 #作成したサーバ証明書の内容を確認する
$ openssl x509 -in server.crt -text -noout
Certificate:
　　　　　…
        Subject: C = JP, ST = Tokyo, L = minato-ku, O = Example, OU = Web, CN = Exampledomain
        Subject Public Key Info:
　　　　　…
        X509v3 extensions:
            X509v3 Subject Alternative Name: 
                DNS:Exampledomain, IP Address:127.0.0.1

```

サーバ証明書の内容を確認してCommon NameとSubject Alternative Namesが出力されていればOK。

#2. 作成したサーバ証明書を信頼する証明書として追加する手順[macOS]
1.で作成したサーバ証明書（server.crt）を 信頼する証明書として設定すれば、 HTTPS の通信ができるようになる。

下記の手順で設定します。詳しくは[こちらの記事](https://qiita.com/suin/items/be87a7a581f30b38c5f7)を参照。

- キーチェーンアクセス.appを開く
- 作成したserver.crtをダブルクリックで開く
- 証明書の詳細画面で「信頼」を開く
- 「この証明書を使用するとき」項目を**常に信頼**に変更



以上の手順を踏んでローカルサイトにアクセスすると、入れるようになった…！！！
手順的にはさほど難しくないけど、ど素人からすると解決まで長い道のりだった（ ;  ; ）


####参考サイト
- https://qiita.com/t-kuni/items/d3d72f429273cf0ee31e
- https://qiita.com/suin/items/be87a7a581f30b38c5f7
- [https://weblabo.oscasierra.net/openssl-gencert-1/](https://weblabo.oscasierra.net/openssl-gencert-1/)
- [https://jp.globalsign.com/support/faq/07.html](https://jp.globalsign.com/support/faq/07.html)
java(クラスとインスタンス)

##定数フィールドの宣言
```java
public class Matango {
	int hp;
	//int level = 10;　　　 //フィールド
	final int LEVEL = 10;　//定数フィールド
}
```
値を書き換えることができないようにする定数フィールド
`final`を付けて名前を`大文字`にする（LEVEL）

##thisは省略しない

```java
public class Hero {
	String name;   //名前の宣言
	int hp;        //HPの宣言
	
	public void sleep() {
		this.hp = 100;
		System.out.println(this.name + "は、眠って回復した");
	}
```

`this.`は省略しても動作する
ローカル変数や引数にも同じhpがあるとそちらが優先されてしまう可能性がある
フィールドを用いる時は`this.`をつけるようにする


##インスタンスの生成

```java
public class Main {
	public static void main(String[] args) {
		//１、勇者を生成
		Hero h = new Hero();
	}
}
```
クラス名(Hero) 変数名(h) = new　クラス名(Hero)();



##フィールドへの値の代入

```java
public class Main {
	public static void main(String[] args) {
		//１、勇者を生成
		Hero h = new Hero();
		//２、フィールドに初期値をセット
		h.name = "勇者";
		h.hp = 100;
		System.out.println("勇者" + h.name + "を生み出しました！");
	}
}
```

変数名.(h.) フィールド名(name) = 値("勇者");
gitのsubmoduleのメモ

## 作業中のgit親レポジトリに既存のgit子レポジトリを追加

```console
$ cd /path/to/parent_directory/
$ git submodule add git@github.com:me/child_directory.git ./child_directory

$ git add .
$ git commit -m '......'
```

## サブモジュールを含む親レポジトリをクローンしてくる

ToBeWritten...
YamahaRTX1200でタグVLAN


# VLANの種類
* ポートVLAN(プライベートVLAN)
* ポートベースVLAN(ポートVLAN)
* タグVLAN


# トランキングプロトコル
IEEE802.1Qのみ


# タグVLAN設定
```
// 仮想IF lan1/1 作成
vlan lan1/1 802.1q vid=101 name=VLAN101
// 仮想IF lan1/1にIP設定
ip lan1/1 address 192.168.70.1/24
// 保存
save
```

# 結果
VLANインターフェースを作成したら、そのNW宛のパケットはVLANIF宛に送られる

```
show ip route
192.168.70.0/24     192.168.70.1         LAN1/1  implicit  
```
Dockerにsshdをインストールしてsshログインする

# 目的
Dockerにsshdをインストールする方法に関する備忘録です

少し探したところ、公式サイトに書いていた、、
> [Dockerize an SSH service](https://docs.docker.com/engine/examples/running_ssh_service/)

# Dockerfileを作成して起動

Dockerfileを作成する

```dockerfile:Dockerfile
FROM ubuntu:16.04

RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:THEPASSWORDYOUCREATED' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd

ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile

EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
```

Dockerfileと同じディレクトリでdocker buildする

```
$ docker build -t eg_sshd .
...
Successfully built a25d2079f336
Successfully tagged eg_sshd:latest
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
eg_sshd             latest              a25d2079f336        2 minutes ago       205MB
```

buildに成功したのでdocker runする

```
$ docker run -d -P --name test_sshd eg_sshd
2c72816dcfccbe6ed82e15635d4a43d77180b564a95de32c553bfe8c5e49fb16
$ docker ps
CONTAINER ID        IMAGE                    COMMAND               CREATED             STATUS              PORTS                   NAMES
2c72816dcfcc        eg_sshd                  "/usr/sbin/sshd -D"   21 seconds ago      Up 20 seconds       0.0.0.0:32768->22/tcp   test_sshd
```

dockerコンテナの22番ポートがどこにマッピングされているか確認する（今回は32768のようだった）

```
$ docker port test_sshd 22
0.0.0.0:32768
```

IPアドレスか、localhostを指定してsshでログインする

```
$ ssh root@localhost -p 32768
root@localhost's password:(Dockerfileでchpasswdした値、例:"THEPASSWORDYOUCREATED")
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.9.125-linuxkit x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

root@2c72816dcfcc:~# 
```

sshでdockerコンテナ内にログインできました。

# 参考
[Dockerize an SSH service](https://docs.docker.com/engine/examples/running_ssh_service/)
[DockerでポータブルなLinux開発環境(GUI付き)を構築する](https://qiita.com/gitcell/items/8b1f154edc26def7ecce#とりあえずxが動くかテスト)
シンプルなDockerの起動と停止方法

# Dockerの起動と停止
Dockerの起動と停止方法について必要な情報だけをまとめたシンプルな内容を作成しました。

### 関連するコンテナをまとめて起動
```
$ docker-compose start
```

### 関連するコンテナをまとめて停止
```
$ docker-compose stop
```
この状態でPCをシャットダウンすることができます。

### ちなみに...
停止してすぐに再起動をしたい場合はリスタートがおすすめです！

```
$ docker-compose restart
```

# お勧めできない停止方法
下記のコマンドは安易に行わないようにしましょう。

```
$ docker-compose down
```
こちらのコマンド実行するとインストールしたはずのGemがなくなってしまうようなことがありますので注意が必要です。

#コンテナに入る方法
次にコンテナに入り通常コマンドでRailsの開発を行う方法の解説をしたいと思います。こちらは下記のリンクから参照してください。
[Dockerの開発環境でコンテナに入り通常のコマンドで実行する方法](https://qiita.com/chisaki0606/items/68e21d9a31f1eaaeac00)
初学者がアウトプットするAjaxの話

#Ajaxについてわかりやすくまとめてみた！
初学者ですがまとめてみました。
至らぬ点、間違っている点がございましたらご指摘くださいませ。

##Ajax通信の登場人物
・**クライアントくん**
サーバーくんとは仲良しだけどいつも要求ばかりしている、
サーバーくんと二人きりでお話しすると変な間が入ってちょっと気まずい。


・**サーバーくん**
クライアントくんと仲良し！けど二人きりだと変な間が入る
いつもクライアントくんの言うことばかり聞いてる。
XMLHttpRequestと言う道具を使ってJavascriptくんと文通している。

・**変な間**
クライアントくんがサーバーくんに要求をしてから要求の結果が返ってくるまでの間。
謎の力によってクライアントくんは動けなくなる。


・**JavaScriptくん**
クライアントくんともサーバーくんとも仲良し！！
3人でいると変な間が入らず、めちゃくちゃ会話が弾む。
実はクライアントくんの行動を監視している。


##Ajaxとは
Ajaxとは「Asynchronous JavaScript + XML」の略
Asynchronousとは、非同時性の、非同期の、と言う意味です。
XMLとは、XMLHttpRequestと言うAPIの略です。
要するに、「JavascriptとXMLファイルによってサーバーと非同期通信を行う」ということです。

##同期・非同期とは
そもそも同期・非同期って何だろう？

クライアントくんはサーバーくんにいつも要求ばかりしています。
**クライアントくん**)　ねぇねぇサーバーくん、美味しい焼肉屋を探したいから食べ○グのページを見せて！

**サーバーくん**) 　本当にクライアントくんは食いしん坊だなぁ、わかったよ、ちょっと待っててね！　

変な間・・・・・　クライアントくん(う、動けぬ、、、)

**サーバーくん**)　はい！これが食べ○グのページだよ！

**クライアントくん**)　わぁ〜、ありがとう！

クライアントくんがサーバーくんに要求（今回は食べ○グのページを見せて）を言ってから変な間があいて食べ○グのページが返ってきました。

クライアントがHTTPリクエストを送ってから、HTTPレスポンスがサーバーから返ってくる間待ち続ける通信方式を同期と言います。

逆に非同期は、HTTPリクエストを送ってからHTTPレスポンスがサーバーから返ってくる間、クライアントが待つことなく動き回れることを言います。

##XMLHttpRequestとは
クライアントくん（ウェブブラウザ）上で動くjavascriptくんが直接サーバーくんとのやりとりを行う際に使用するオブジェクトです。
データ形式はXML形式に限りません。(jsonでも可能です)
javascriptくんはサーバーくんとのやり取りで得たデータをクライアントくんに渡すことができます。

##結局Ajaxで何ができるの？


**クライアントくん**)　ねぇねぇサーバーくん、兵庫県にある焼肉屋さんの一覧を見せて！

**サーバーくん**) 　本当にクライアントくんは食いしん坊だなぁ、わかったよ、ちょっと待っててね！　

**JavaScriptくん** )　(シュバババババ)僕がサーバーくんと一覧情報のやり取りをしてるから、クライアントくんは好きに動いてていいよ！

**クライアントくん**)　Javascriptくんありがとう！　謎の力が発動せず自由に動けるよ〜（カーソルビュンビュン）

**サーバーくん**)　JavaScriptくんこれが一覧だよ！

**JavaScriptくん** ) 　ありがとうサーバーくん、json形式でくれたんだね！これを見やすく加工してクライアントくんに届けるぞー

**クライアントくん**)　わぁ〜、ありがとう！

**JavaScriptくん** )　クライアントくんの行動（クリックやスクロール）に合わせて必要な情報があれば取ってくるぞー


JavaScriptくんが必要な情報(今回は焼肉屋さんの一覧)を取得してくれたことで、クライアントくんが投げるHTTPリクエストが必要なくなり変な間が発生しませんでした。
また、HTTPリクエストは必要な情報以外(HTMLやCSS)もセットで持ってきてしまうため、
サーバーくんに負荷がかかってしまいます。

Ajaxを使うことで必要な情報を負荷をかけず、変な間も発生させずに持ってくることができました！
すごいAjax!


###終わりに
浅い知識のままアウトプットに及んだゆえ、至らぬ点が多々あったと思います。
気になる点があれば、ご遠慮なくお申し付けください。

スキルは可変、日々精進。
これからも頑張っていきます。
PythonでFizzBuzz問題を解いてみる

Python を勉強しようと思い、まずはFizzBuzz問題をやってみようと思います。
使用環境：Python 3.6.3


# FizzBuzz問題とは
Jeff Atwood さんが提唱したこんな問題。
> 1から100までの数をプリントするプログラムを書け。ただし3の倍数のときは数の代わりに｢Fizz｣と、5の倍数のときは｢Buzz｣とプリントし、3と5両方の倍数の場合には｢FizzBuzz｣とプリントすること。

マトリクスやベン図で書くとこんな感じ
<img width="863" alt="fizzbuzz_image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565211/0ab8bedf-f322-f1e5-2fb9-2ec58fcd054f.png">


# コードにしてみる
### for バージョン
```python:Python
for i in range(1, 101):
    if i % 3 == 0 and i % 5 == 0:
        print('FizzBuzz')
    elif i % 3 == 0:
        print('Fizz')
    elif i % 5 == 0:
        print('Buzz')
    else:
        print(i)
```

### while バージョン
```python:Python
i = 1
while i <= 100:
    if i % 3 == 0 and i % 5 == 0:
        print('FizzBuzz')
    elif i % 3 == 0:
        print('Fizz')
    elif i % 5 == 0:
        print('Buzz')
    else:
        print(i)
    i += 1

```

### 三項演算子で書いてみる
```python
for i in range(1,101):
    print('Fizz' if (i % 3 == 0 and i % 5 == 0) else 'Fizz' if (i % 3 == 0) else 'Buzz' if (i % 5 == 0) else i)
```
ポイントは、print文の中に演算式を入れ込んでいるところ（さすがに見にくいので、各条件式に()つけてます）。
でも、入れ子の三項演算子にしないといけないから見にくい。。。

##### 参考
```:三項演算子の構文
(条件がTrueのときの値) if (条件式) else (条件がFalseのときの値)
```


# やってみてわかったこと
* FizzBuzz問題は、条件判定や繰り返しの構文がわかってよいですね。
* 個人的には、Python の三項演算子の構文に慣れない。
【Flutter】NetworkImageでCERTIFICATE_VERIFY_FAILEDエラーの解決方法

# 何が起きたか
サーバーに上げた画像をNetworkImage()で取得しようとした時にエラーが出たので解決方法を示す。

# エラー内容
```example.dart
NetworkImage('画像を置いたサーバーのURL')
```

```
Handshake error in client (OS Error: CERTIFICATE_VERIFY_FAILED: ok(handshake.cc:355))
```

# 解決方法
main.dartでHttpClientをoverrideして、globalに設定すればいけた。

```main.dart
class MyHttpOverrides extends HttpOverrides{
  @override
  HttpClient createHttpClient(SecurityContext context){
    return super.createHttpClient(context)
      ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;
  }
}

void main() {
  HttpOverrides.global = new MyHttpOverrides();
  runApp(MyApp());
}
```
GASでSpreadSheet特定列の最終行を取得するには

## はじめに
Google Apps ScriptにおいてSpreadSheetの最終行列を取る事は簡単です。例えば以下のようなやり方があります。

##### 最終行は何行目か取得する
```javascript
const lastRow = SpreadsheetApp
    .getActiveSpreadsheet()
    .getSheetByName("sheet")
    .getLastRow();
```

ただ、これは「対象シート全体のうち一番下の行番号を取る」という挙動をする為、特定列の最終行Noを取るには向きません。

よって簡単に特定列だけで最終行を取る関数を用意しましたのでご紹介します。

##### 特定列の最終行を取得する関数
```javascript
function getSpecificLastRow(sheet,rowRange) {
    const values = sheet.getRange("H:H").getValues().reverse();
    let counter = 0;
    values.forEach((val, index) => {
        if (val[0].toString() !== "") {
            counter = values.length - index;
        }
   })
   return  counter;
}
```
上記関数を使う際には以下の通りにすれば利用できます。

```javascript
function main(){
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheet");
    const range = "A:A"; // A列の最終行を取りたいとき
    const lastRow = getSpecificLastRow(sheet,range);
    Logger.log(lastRow);
}
```

もし何かのお役に立てば幸いです。

[参照元](https://ymuichiro.blogspot.com/2020/05/gasspreadsheet.html)
ancestorsメソッドについて


書籍でancestorsメソッドについて、役立ちそうな情報が書かれていたのでまとめてみました。

```ruby:これまでの認識

class Mountains
end

class Nepal  < Mountains
  def everest_place
    "nepal"
  end
end

  p Nepal.ancestors
  p Nepal.class.superclass.superclass.superclass

```
```ruby:出力結果

[Nepal, Mountains, Object, Kernel, BasicObject]
BasicObject
```

継承関係を辿るときに、superclassだと一つ一つ辿っていかくちゃいけなくて、不便。
ancestorsメソッドを使えば今のクラスからBasicObjectまでを配列で取り出せて便利だなという程度の認識でした。（モジュールも含む）


```ruby:新たな認識

module World
 def everest_place
  "china"
 end
end

class Mountains
 def everest_place
  "india"
 end
end

class Nepal < Mountains
  include World
 def everest_place
   "nepal"
 end
end

p Nepal.ancesters

nepal = Nepal.new
puts nepal.everest_place
```
上記のように、
❶Nepalクラスは、Worldモジュールをインクルードしているので、Worldモジュールのeverest_placeメソッドを使える
❷Nepalクラスは、Mountainsメソッドを継承しているため、Moutainsクラスのeverest_placeメソッドも使える

**Nepalクラス内のeverest_placeメソッドも含めると、3つのeverest_placeメソッドがあったとします**
どのeverest_placeメソッドが呼び出されるかによって、もちろん出力結果も変わってきますね。

そんな時に活躍するのが、ancestorsメソッドです。
p Nepal.ancestorsの出力結果を見てみると、

```ruby:Nepal.ancestorsの出力結果
[Nepal, World, Mountains, Object, Kernel, BasicObject]
```
と表示されます。
**左から順に呼び出されるので、Nepalクラス内で定義したeverest_placeメソッドが取り出されることがわかります。**

実際に結果を見ていきます。

```ruby:出力結果
nepal
```


ちゃんと、Nepalクラス内で定義したeverest_placeメソッドの戻り値がかえってきました。
LaravelでTenancyを使用し、DBをユーザーごとに動的に切り替える方法

Laravelの利点にDBの扱いやすさがありますよね、これまでDB周りで詰まったことはほとんどありませんでしたが、DBを動的に変更する機能で詰まったので、備忘録として残しておきます。

### 使用環境
・MAC
・Laravel7.5
・Tenancy　　←本記事の主役

### 作りたかったもの
Laravelで※シングルサインオン（SSO）機能のAPI認証基盤の構築。
DBはユーザーが新規で登録されるごとに新規で構築され、ログイン中のユーザーごとに切り替える。
※Single Sign Onの略。1つのIDとパスワードを入力して、複数のWebサービスやアプリケーションにログインする仕組み。

### 詰まった箇所
・ユーザーが新規登録される毎にDBをプログラム内で(自動で)構築する
・DBが構築される毎に構築されたDBにテーブルを作成する(マイグレーションを実行する)
・ログイン中のユーザーごとにDBを切り替える

### 詰まった原因
LaravelでDBを扱うにはconfig/database.phpにDB情報を、前もって記入しておく必要があります。
(PDOでDBに直接接続するなど別方法もありますが、ここでは割愛させてください。)
しかし、今回作りたかった機能としてDBを動的に切り替える必要があるのですが、config/database.phpに前もって記入することができなかったからです。

### 解決策
####・Tenancyを使用し、マルチテナント環境を構築する。
https://reffect.co.jp/laravel/laravel-multi-tenant-stancl-tenancy
Tenancyの使用方法については👆に記載されています。

👇のコードでテナント（ユーザーごとの環境）・テナントごとのDBとテーブルの構築までします。

```php
//ユーザー登録機能内にテナント作成機能を追加(一部抜粋)
//リクエストされたユーザー名
$user_name = $request['user_name'];
//メインドメイン
$baseURL = 'qiita.com';
//ユーザー名でテナントを作成
$tenant = Tenant::new()->withDomains($user_name . '.' . $baseURL)->save();
//migrate実行(実行したいマイグレーションファイルは/database/migrations/tenantに格納しておく)
$exit = \Artisan::call('tenants:migrate', ['--force' => true,]);
```

これで以後は、「リクエストされたユーザー名.メインドメイン」のURLにアクセスすると、
そのユーザー用のページにアクセスすることができ、ユーザーに対応したDBに自動で切り替えられます。
（ここら辺の動きを詳しく知りたい方は👇をどうぞ）
https://tenancy.dev/


実際にはこんな感じでテナント用ページにアクセスし、API認証機能を実装しました。

```php
$tenant_name = 'foo.';
$baseURL = $tenant_name . 'qiita.com/';
$client = new \GuzzleHttp\Client(['base_uri' => 'http://'. $baseURL]);
       $response = $client->request(
            'POST',
            'changeProfile',
            [
                'headers' => [
                    'Accept' => 'application/json',
                    'Authorization' => 'Bearer '.$api_token
                ],
                'form_params' => [
                    'profile' => $profile,
                    'email' => $email,
                ],
            ]
        );
```
拝啓、CreateJSに携わっている皆様

#前文(はじめに)
拝啓
CreateJSに携わっている皆様、お元気ですか。
世の中からFlashは消えつつあり、[PixiJS](https://github.com/pixijs/pixi.js)によりEaselJSが消滅しつつあるように思えます。

#主文(言いたいこと)
では、言いたいことがあるのでお伝え致します。
##開発辞めちゃったの?
例として、SoundJSは最終リリース(Ver1.0.0)が2017/9/16で終わっています。
もっと言うと、この前のバージョン(Ver0.6.2)が2015/12/5で約2年もの間が空いております。
Ver1.0.0での内容に

```
Almost 2 years of bug fixes and improvements
```
と、書いてありますことから、2年間空いていることは承知の上だと思います。
しかし、現在(2020/5/16)でのissuesの数は82件あります。

Ver1.0.0には非推奨のメソッドを使っていたというものもあります。
[Internal preloading was using deprecated method name](https://github.com/CreateJS/SoundJS/commit/33b1303425da20770688455c46aab28c6dab4cdc)
これらはVer1.0.2では改善されています。

では何故、最新リリースをVer1.0.0にしているのか。CDNを1.0.0にしているのか。疑問でございます。
開発辞めちゃたの?という質問も来ています。
[Making createjs community driven? your thoughts please
](https://www.reddit.com/r/createjs/comments/gjfgr3/making_createjs_community_driven_your_thoughts/)

確かに、Slackがあるのでそこで質問をしたり、開発の手伝いをすれば良いのですが、中々ハードルの高いものでございます。
共に開発する意欲はわかるのですが、せめて数年前のissuesとかには目を通してもらえると幸いです。

##Reactで使いたい
ただいま、Ver2.0が開発中との噂を小耳にはさみました。なんでもES Modules対応するらしいじゃないですか。
記事にもなっているので期待大ですね。
[CreateJS 2.0が待望のES Modules対応。使い方とwebpackによるバンドル方法](https://qiita.com/tonkotsuboy_com/items/8cc5c77aa91b1a3ac321)

確かにブランチには2.0という文字が刻まれております。非常に楽しみです。
ところで、PreloadJSにはないのですが何故なのでしょうか。
もしかして、ES Modules対応しなくても使える使い方があるのでしょうか。
今後の開発がとても興味深いです。

##PixiJSとの共存
今日では、PixiJSというものがございます。
なんでもWebGLなので高速に描画することができます。パフォーマンスも高いことが特徴です。
しかし滑らかな線を描くとなるとCreateJS内のEaselJSの方がいいらしいですね。
[HTML5 CanvasとWebGLの使い分け](https://ics.media/entry/5140/)

##EaselJSの他との共存
他に描画系のものといえば、[konva](https://konvajs.org/)があげられます。
それらを戦わせてみました。
[createjs-easeljs-vs-konva-vs-pixi.js](https://www.npmtrends.com/createjs-easeljs-vs-konva-vs-pixi.js)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234613/2032ee7b-a4d7-35d0-5139-8b8b166dd0c4.png)
おっと、konvaが頭一つ出てる感じですね。
頑張って!!EaselJS!!不人気だけど!!

#末文(まとめ)
沢山の疑問や質問はありますが、いずれ他をしのぐライブラリになると思っております。
末筆ながら、CreateJSのさらなるご発展をお祈りしております。
敬具
Pythonひよっこが『言語処理100本ノック 2020』に挑戦【10-14】

Pythonひよっこのわたしが、『言語処理100本ノック 2020』の第2章の前半部分に挑戦してみました。 
一般の方が公開されている解答と比べながら、1問ずつ学んだことなどをまとめていきたいと思います。  

こちらの続きになります。
[Pythonひよっこが『言語処理100本ノック 2020』に挑戦【06-09】](https://qiita.com/tulip_rabbit/items/bfe190306eb9bf315316)

#第2章:UNIXコマンド
##10.行数のカウント
```python
#10.
f=open('popular-names.txt','r')
print(len(f.readlines()))
f.close()
```

```
wc -l popular-names.txt
```
→ターミナルでwcコマンドを使って確認しました。

wcコマンドを使ったことがなかったので、いろいろと調べながら進めました。
readlines()はファイルのすべての行を読み込んでリストに入れたものを返すので、 このリストの長さ=ファイルの行数 であることに早めに気づけたので本体はさくっとかけました。

##11.タブをスペースに変換
```python
#11.
f=open('popular-names.txt','r')
f_new=open('popular-names_11.txt','w')

text=f.read()

f_new.write(text.replace('\t',' '))

f.close()
f_new.close()
```
```
cat popular-names.txt | tr '\t' ' '
```
→trコマンドを使ってみました。

新しくできたファイル'popular-names_11.txt'はちゃんとスペースで区切られたテキストファイルになっていました！！
sedコマンドでは、'\t'が受理されなかったので trコマンドを使いました。

##12.1列目をcol1.txtに、2列目をcol2.txtに保存
```python
#12.
f=open('popular-names.txt_11','r')
f_new1=open('col1.txt','w')
f_new2=open('col2.txt','w')
text=f.readlines()

for i in range(2780):
    text_new=text[i].split(' ')
    f_new1.write(text_new[0]+"\n")
    f_new2.write(text_new[1]+"\n")

f.close()
f_new1.close()
f_new2.close()
```
→cutコマンドで "\t" が使えなかったので、11.で作成した、スペースで区切られた方のファイルを使いました。

```
cut -f 1 -d " " popular-names_11.txt   
cut -f ２ -d " " popular-names_11.txt
```
→ターミナルでcutコマンドを使って確認しました。

for文のrangeで10.で求めた行数を使ってしまったのですが、あまり良くないですよね...
ほかの方の解答でpandasを使ったものがありました。
pandasをちゃんと勉強したことがなかったので細かいところまで見れていませんが、いろいろと便利なものがあるみたいなので今後手を出していきたいです。

##13.col1.txtとcol2.txtをマージ
```python
#13.
f=open('popular-names_13.txt','w')
f_1=open('col1.txt','r')
f_2=open('col2.txt','r')

for i in range(2780):
    f.write(f_1.readline().replace("\n","\t")+f_2.readline())
    
f.close()
f_1.close()
f_2.close()
```

```
paste col1.txt col2.txt
```
→ターミナルでpasteコマンドを使って確認しました。

相変わらずfor文のrange()は要改善ですが、ノータイムで実装できました。
readline()でとってきた要素はどちらも \n が入っているので、col1.txtのものはタブと置き換える必要があります。(ここで最初つまずいてしまいました。)

##14.先頭からN行を出力
```python
#14.
def print_func(N):
    f=open('popular-names.txt','r')
    
    for _ in range(N):
        print(f.readline())
    f.close()
        
print_func(4)
```

```
head -n 4 popular-names.txt
```
→ターミナルでheadコマンドを使って確認しました。

jupyter notebookでのコマンドライン引数の使い方がわからなかったので、題意を満たす関数:print_funcを定義し、そこに引数として出力する行数:N を渡すことにしました。
きっと、問題と同じようなことを実装できたと思います...

#おわりに
UNIXコマンドが全然ピンと来ないので、どの問題も調べながら使っています。
むずかしい、というより、なかなか慣れないです...

ゼミの本読みが溜まってしまっているので、それが落ち着いたら続きに取り組もうと思います！
DockerとPython(とSQL)で簡単なRPGゲームを作る Ⅰ~Docker+python3環境構築~

# 概要
在宅ワークに飽きてきたのでゲームでも作ってみようと思います．
暇なときにちょっとずつ作っていきます．

# 環境構築
Python3が使用可能なDocker環境を作る.
Tkinterとか使ってGUIも作れるといいと思っている．

ディレクトリ構成

```Dir
Game
  |-Docker
  |   |-Dockerfile
  |   |-docker-compose.yml
  |   |-requirements.txt(pip用)
  |
  |-program
  |   |-(program)
  |-DB
     |-(player-data etc)

```

Dockerfile

```Dockerfile
FROM python:3.7.0-slim

WORKDIR /app
COPY /requirements.txt /app/

RUN apt-get update \
  && apt-get -y upgrade \
  && apt-get install -y python3-tk \
  && pip install --no-cache-dir -r requirements.txt \
  && rm -rf /tmp/* /var/tmp/* \
  && rm -rf /var/lib/apt/lists/* \
  rm -rf /var/lib/apt/lists/*

WORKDIR /work
```

ついでにcompose-upも作っておく(そのうちSQLにデータを保存したりしたい)

```docker-compose.yml
version: '3'
services:
    quest-env:
        image: "quest-image"
        volumes:
            - ./../program/:/work
        tty: true
```

# とりあえず動作確認
Hello world代わりに以下のプログラムを作成，実行

```Battle.py
def Encount(monster):
    print("やせいの{}があらわれた！".format(monster))

if __name__ == '__main__':
    Encount('スライム')
```

```出力
python3 Battle.py
やせいのスライムがあらわれた！
```

やったね！

# 基本となるキャラクタークラスを作る
敵味方関係なく基本となるキャラクターのクラスを作る．ここから継承とかしていけたら勉強になっていいな...
名前，攻撃力，HPを持っていて攻撃とダメージ計算ができるクラス．超単純．

```character.py
class character():
    def __init__(self, name, attack, HP):
        self.name = name
        self.atk = attack
        self.hp = HP
    
    def attack(self):
        return self.atk
    
    def damage(self, enemy_attack):
        damage = enemy_attack
        self.hp -= damage
        return damage

```
相手の攻撃力を一旦damageに移しているのは，後々たまにダメージ倍増とかを入れる準備．

さっきのBattle.pyに入れて動かしてみる.
とりあえずプレイヤーとモンスターのインスタンスを生成して戦わせる．

```Battle.py
import character

def Encount(monster):
    print("やせいの{}があらわれた！".format(monster.name))

def Attack(attacker, defender):
    print("{}のこうげき！{}に{}のダメージ".format(attacker.name, defender.name, defender.damage(attacker.atk)))
    return defender.hp

def Battle(player, monster):
    Encount(monster)
    turn = 0
    while(1):
        turn += 1
        print("--------------------")
        print("ターン:{} HP:{}".format(turn, player.hp))     
        if Attack(player, monster) <= 0:
            print("{}を倒した！".format(monster.name))
            break
        if Attack(monster, player) <= 0:
            print("{}は倒れた！".format(player.name))
            break

if __name__ == '__main__':
    player = character.character('たこやき', 2, 10)
    monster = character.character('スライム', 2, 10)
    Battle(player, monster)
```
一応攻撃を関数化して共通化してみた．あと先制攻撃を入れるために遭遇も分けてみた．

一応勝ち負けのパターンでテストしたけど勝ったパターン載せときます．

```出力
python3 Battle.py
やせいのスライムがあらわれた！
--------------------
ターン:1 HP:10
たこやきのこうげき！スライムに2のダメージ
スライムのこうげき！たこやきに2のダメージ
--------------------
ターン:2 HP:8
たこやきのこうげき！スライムに2のダメージ
スライムのこうげき！たこやきに2のダメージ
--------------------
ターン:3 HP:6
たこやきのこうげき！スライムに2のダメージ
スライムのこうげき！たこやきに2のダメージ
--------------------
ターン:4 HP:4
たこやきのこうげき！スライムに2のダメージ
スライムのこうげき！たこやきに2のダメージ
--------------------
ターン:5 HP:2
たこやきのこうげき！スライムに2のダメージ
スライムを倒した！
```
勝った！

今日はこれくらいにしておきます．
EC2のスナップショットを手軽に自動取得する方法

# はじめに

EC2のスナップショットを定期的に取得する簡単な方法がないかと探してみたところ、EC2ダッシュボード上にある「データライフサイクルマネージャー」という機能を使うと簡単に実現できることが分かりました。

今回はこのデータライフサイクルマネージャーを使った、スナップショットの作成手順（※GUIベース）を備忘録として記事にしてみました。

# 手順

## 1. EC2インスタンスのタグ付け

* まず最初に、スナップショットを取るEC2インスタンスを識別するためのタグを付与します。
* 今回はキー「Name」に対する値として、「nkojima-test」を設定しました。

![10_EBSスナップショット_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/1e6b1c22-c0c4-49d5-cacb-d4e90bc5b9d3.png)

## 2. データライフサイクルマネージャの設定

* EC2ダッシュボードの左側のメニューにある、「ライフサイクルマネージャー」をクリックします。
* データライフサイクルマネージャーの画面に入ったら、［スナップショットのライフサイクルポリシーを作成する］をクリックします。

![10_EBSスナップショット_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/9d64ca71-a1f7-6e11-0133-6ea13db14861.png)

* ライフサイクルポリシーの作成画面に入ったら、ポリシーの説明として何らかの文言を設定します。
 * 後で出てくる「スケジュール名」の補足にあたるような文言が良いのかもしれません。
* リソースタイプの選択については、今回は「インスタンス」を選択しました。
* ターゲットについては、先程にEC2インスタンスに設定したタグ（Name）を指定します。

![10_EBSスナップショット_021.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/af3077fe-04a3-4113-5df9-5c41d5766a61.png)

* 次にポリシースケジュールとして、スナップショットを取る時間などを設定します。
* スナップショットの開始時刻は[UTC（協定世界時）](https://ja.wikipedia.org/wiki/%E5%8D%94%E5%AE%9A%E4%B8%96%E7%95%8C%E6%99%82)のため、画面上で設定する時刻は「日本時間の9時間前」として設定する必要があります。
 * 日本時間で18時からスナップショットを取りたい時は、`9:00 UTC`と設定します。
* 今回は保持するタイプはカウント（世代）として、保持する数を1にしました。
 * この設定の場合、保持されるスナップショットは1世代だけで、スナップショットの自動作成が何回繰り返されてもスナップショットは1つだけとなります。

![10_EBSスナップショット_022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/10744afb-c7b8-c1c2-b4d1-8c2c39ae3b2b.png)

* タグ付け情報は、［ボリュームからタグをコピーする］という欄にチェックを入れました。
 * これにより、EC2インスタンスに設定されているタグがスナップショットにもコピーされます。

![10_EBSスナップショット_023.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/f4698933-45b9-4f5d-1ca1-9f896505b227.png)

* スナップショットの高速復元、クロスリージョンコピー、パラメーターについては設定をしませんでした。

![10_EBSスナップショット_024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/b2d15b00-defd-02fc-f60b-00316b32a4cf.png)

* IAMロールについては、デフォルト値の［デフォルトロール］を選択しました。
 * デフォルト値のままで、動作に特に問題はありませんでした。
* 最後に［ポリシーを有効にする］にチェックが入っていることを確認して、［ポリシーの作成］をクリックします。
 * スナップショットの自動作成を止めたい時は、ここで［ポリシーを無効にする］にチェックを入れます。

![10_EBSスナップショット_025.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/5a6e1f18-011f-482f-ac33-4fd023ee4d1c.png)

## 3. 作成されたポリシーの確認

* ポリシーの作成が完了したら、ライフサイクルマネージャー画面でポリシーの状態が［ENABLED］になっていることを確認します。
 * ポリシーが無効化されていると、ポリシーの状態が［DISABLED］となっているはずです。

![10_EBSスナップショット_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/a55081b4-62b7-9394-52a9-4e1ea075a18b.png)

## 4. 作成されたスナップショットの確認

* スナップショットの作成予定時刻を少し（※1時間程度）過ぎたら、EC2ダッシュボードからスナップショット画面へ入り、スナップショットが作成されていることを確認します。
* ポリシーの状態が［ENABLED］であるのにスナップショットが作成されていない場合は、スナップショットの取得開始時刻、取得間隔などを確認してください。

![10_EBSスナップショット_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/b372e04a-bec9-f17f-4bb6-0102aae9f7ce.png)
Railsでdotenv-railsを中途半端に入れたらちゃんとenv読み込んでくれなかった

## はじめに
ホームページを制作している途中で、問い合わせ機能を作りたくなった。
ActionMailerを使ってsmtpを使ってGmailに送信する時に起きたエラーを解消した話。

結論として、
・メールサーバの設定等はデフォルトのconfig/environments
・コード内で使用する環境変数はdotenv-rails
で使い分けることにしました(そもそもそういう使い方をすべきなのか...？)

## 環境
Ruby 2.7.0
Rails 5.1.6 


## やったこと

①[Rails5で確認画面経由のメッセージ送信フォームを実装する] を参考にActionMailerを導入
[Rails5で確認画面経由のメッセージ送信フォームを実装する]:https://remonote.jp/rails-confirm-form


②環境変数を追加するために以下を追加

```ruby:config/environments/development.rb
DEFAULT_EMAIL = '******@gmail.com'
DEFAULT_EMAIL_PASSWORD = '****************'
```


③ここで「ちゃんと環境変数を切り分けたいな」と思い[dotenv-railsを導入]してconfig/environmentsを削除
[dotenv-railsを導入]:https://qiita.com/ryosuketter/items/ceb592dc6b23a20e51b5


④そしたらこのエラー。
　`SMTP From address may not be blank: nil`
　メールサーバー設定の記述はしていたのでenvをちゃんと読み込めていないんだなと。

⑤あとは結論の通り。
　デフォルトはdevelop.rbで、追加の環境変数は.envで解決。
【gsudo】Windowsで簡単にsudoする

# Windowsでも`sudo`使いたいよね

個人的な結論：**gsudoがおすすめ！**

- [gsudo - a sudo for Windows](https://github.com/gerardog/gsudo)

何がいいかというと、**同じウィンドウ内で新しく管理者権限（スーパーユーザー）でシェル（PowerShell＆Cmd）を開ける**（新規ウィンドウが別に開かない）！

UNIX系のシェルみたい（BashとかZshとか）に同じウィンドウ/タブ上で権限を切り替えてコマンド操作できる！

名前の由来はGUIとsudo？

動画でどうぞ。

![gsudo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173746/8fcc0c02-aba2-9ae7-4ebb-f8ce0f4cd843.gif)

コマンドを入力した後、管理者権限に切り替えるためのユーザーアカウント制御画面で「はい」を選ぶと管理者権限でコマンドが実行されます。
（動画では確認画面はキャプチャされていませんが、実際は出ています）


## 事の経緯
最近、Windows上で開発するようになってPowerShellやCmdを使う機会が増えたのですが、LinuxとかMacみたいにターミナル上で管理者権限で操作するのがしんどいなと感じていました。

というのも、**管理者権限に切り替えようとすると新規ウィンドウがいちいち立ち上がる**から。

操作が終わったらウィンドウを閉じるか、最初から管理者権限でターミナルを起動すればいいんですが毎回やってると面倒くさく感じる。

特に最近はWindows Terminalで複数タブを開いて操作することが多いので、タブ内で操作を完結させたいという気持ちが強くなりました。(Windows Terminalはいいぞ)

自分でスクリプト書くのもだるいし、便利なパッケージないかなと調べたところgsudoを見つけました。管理者権限で操作するときにPowershellやCmdを新しく別ウィンドウで開きたくない人にはおすすめです。

ちなみに他にもWindows上でsudoする方法はいくつかありましたが、別ウィンドウで新しくシェルを開くタイプばかりでした。
（※全部試したわけではない）

- [Windowsでsudoしたい](https://qiita.com/AinoMegumi/items/fd56711fe1fd2a0e1bbf#comments)
- [PowerShellでsudo
](https://qiita.com/twinkfrag/items/3afb9032fd73eabe09be)
- [sudo コマンド書いた。](https://mattn.kaoriya.net/software/lang/go/20170614142801.html)
- [Sudo](https://github.com/janhebnes/chocolatey-packages/tree/master/Sudo)
- [Windows における su(sudo) 事情考察
](https://qiita.com/zetamatta/items/d41552c383605b24a8c2)

ちなみにパッケージではないですが、下記で紹介されているスクリプトを実行すれば管理者権限のシェルを起動できます（ただし、これも別ウィンドウで開く）

- [WindowsのPowerShellを管理者権限で起動する方法
](https://qiita.com/syui/items/7d42d7e691010ee212fb)

## インストール
インストールはパッケージマネージャー使ってもいいし、コマンドラインからも可能。


```powershell
# scoop
scoop install gsudo
```

```bat
:: chocolatey
choco install gsudo
:: 環境変数を更新
refreshenv
```

```powershell
# パッケージマネージャーなしの場合（非管理者権限で実行）
PowerShell -Command "Set-ExecutionPolicy RemoteSigned -scope Process; iwr -useb https://raw.githubusercontent.com/gerardog/gsudo/master/installgsudo.ps1 | iex"
```

## 使い方 

### 管理者権限の必要なコマンド
インストールが済んだら、PowerShellでもCmdでも使えるようになります。使いたいコマンドの先頭に`gsudo`をつけて実行するだけ。コマンド実行後は非管理者権限（一般ユーザー）に戻ります。（bashやzshで一般ユーザーでsudo使うのと同じ）

```powershell
# Chocolateyでgitをインストール
gsudo cinst git
```

### 管理者権限に切り替える
管理者権限（UNIX系でのroot）に切り替える場合は`gsudo`だけでOKです。`exit`でシェルを終了すれば前の一般ユーザーのシェルに戻ります。

```powershell
# bashでいう`sudo su`に相当
gsudo
# 管理者権限のシェルで操作できる
rm test.txt
# 一般ユーザーに戻る
exit
```

快適なWindowsターミナルライフに一歩近づいた:metal:
HTMLのインライン要素とブロック要素

HTMLのインライン要素とブロック要素について、

なんとなくの感覚でスタイルをあてていることが多いので、復習。

###インライン要素
- 横並びに表示され、縦幅・横幅を指定できない。
- cssでdisplay:block;をあてるとブロック要素の性質を与えれて縦並びにできる。
- display:inline-block;はインライン要素とブロック要素の両方の性質を併せ持ち、横並びで表示されるが、高さが指定できる。

###ブロック要素
- 縦並びに表示される。
- cssでdisplay:inline;をあてるとインライン要素の性質を与えれて横並びにできる。


インライン要素とブロック要素のざっくりとした見分け方は、
横に並べばインライン要素。
縦に並べばブロック要素。

また、スタイルがあたる優先度はタグ→クラス→id。
ただし、親要素、子要素なども含めると変わってくる。。。

インライン要素か、ブロック要素か、理解した上でコーディングするのが大事だと思った。

例えば、

「spanタグは縦並びにならないのか。」

と、

「spanタグはインライン要素だから縦並びにならないのか。」

では、文章にすると少しの違いだけどコーディングしていく上で、大きく変わってくると思う。

本当に基礎基本なことで今更なことですが、しっかりとこういったことも自分の理解を深めるために書き残していこうと思いました。
WebページにTwitterのタイムラインを表示させる

#概要
　Webアプリを作りたいと思い勉強し始めました。様々なWebアプリを参考にしていると目に入るのが「Twitterのタイムライン」でした。

　どうやってTwitterのタイムラインを埋め込むかを調査した備忘録を残します。最終的に次のようにできました。(今回はTwitterのAPIを使用せずに実装しています。APIを使用するほうが一般的？)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/e934c3f0-9bdb-b3ce-39e0-eb158862b5e8.png)

#開発環境
- Webブラウザ　：　Google Chrome
- Twitter

#作ってみる
##埋め込むURLを入力

[Twitter Publish](https://publish.twitter.com/#)にアクセス。

次のような画面が出るので、TwitterのアカウントURLを入力する。
私の場合は次のURLを入力します。

```
https://twitter.com/kmaepu
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/9710fe51-9114-a548-d089-1c4201719da8.png)

##ウィジットタイプの選択
画面を下にスクロールし、ウィジットのタイプを選びます。左側の「**Embedded Timeline**」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/45cbc88d-0fd7-ba1d-7445-056bbc834137.png)

参考にこのまま使用した場合のWeb画面は次のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/a5d670af-6792-81cf-0b57-978172234e1f.png)

ちなみに、
右側の「**Twitter Buttons**」を選択すると、次のようにフォローかメンションのボタンを埋め込むことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/fc39f854-5977-ac84-aaec-9833d9eb7ade.png)

##ウィジットのオプション設定
このまま進むと、画面いっぱいにタイムラインが表示されてしまうので整形します。ウィジット選択画面の下の「set customization options」を選択します。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/7d41c7f1-b85a-95f3-4dff-b5cdae9a3b5d.png)

タイムライン型ウィジットの場合、次のような設定画面が表示されます。
ウィジットの
 - 高さ(px)
 - 幅(px)
 - デザイン(白 or 黒)
 - 表示基本言語

を入力します。設定したら右下の「**Update**」ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/0b085634-b698-3b19-d7b5-26eae9389d6f.png)

##HTMLのコードをコピー
次のようにHTMKのコードが表れうので、右側の「**Copy Code**」をおすと。コードをコピーできます。あとは使用したいhtmkファイルにペーストするだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/1f6e28f3-ba57-f370-03ac-ed0af4799d71.png)

##完成！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/421e9e2a-098b-13ac-4894-584246f3865d.png)

#おわりに
ウィジットを埋め込むだけなので、コードを書かずに実現できて便利でした。余談ですが、趣味で水耕栽培や家庭菜園をしておりその様子をTwitterでつぶやいてます。
↓
<a href="https://twitter.com/kmaepu?ref_src=twsrc%5Etfw" class="twitter-follow-button" data-show-count="false">Follow @kmaepu</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Postmanにてレスポンスボディのjsonの構造をチェックする

> This section contains different examples of validating JSON responses using the Ajv schema validator. I do not recommend using the tv4 (Tiny Validator for JSON Schema v4).

https://postman-quick-reference-guide.readthedocs.io/en/latest/schema-validation.html

とあるのでこれに従いtestスクリプトを作成する。
そのためには想定するjsonの構造からチェック用のjsonスキーマを作成する必要がある。
想定するjson を入力すると自動でjsonスキーマに変換するサイトは以下。
https://app.quicktype.io/#s=coordinate
 にて左のウィンドウでJSONを選択し、右のウィンドウにJSON Schemaを選択すると表示される。
 この結果にはPostmanのtestでは不要な（エラーがでる）項目があり
 https://postman-quick-reference-guide.readthedocs.io/en/latest/schema-validation.html
 に示してある通りに整形する必要がある。
format
additionalProperties
は不要だった。
Postmanのtest の結果でエラーについてはある程度原因を教えてくれるのでそれにしたがって不要な物を消してPostmanでテスト。
VBAマクロで設計書などの格子を自動的に描画する方法

2025/05に少し更新しました。更新内容は実行中は描画をオフにして高速化しました。
おそらく前より10倍くらい早くなったと思います。

#何がしたいのか

設計書（環境設計書、詳細設計書、パラメータ、デザインシート）等で項目や値に対して格子を引く時がありますよね？（私の環境だけかな）その格子を自動的に引きたいってのが目的です。意外とこの格子作成って面倒です。複数行であればそこまで大変ではないですが、何十行、何百行もある場合はもう・・・

画像で表したほうが早いですね。

これを
![VBAマクロ格子1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617706/f5d45a07-3f9b-3f9f-1cec-8f573dd942d6.png)


こうしたいだけ
![VBAマクロ格子2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617706/e9b7087a-ba16-1769-c61e-82cd60c113a2.png)
※色は手動でつけてます



上記の操作をVBAマクロを使用して実現しています。
元々VBAを使ったことはなかったのですが社内で1日だけ研修があったので先生の話半分で作ってみました。
最近また設計書を作る機会があり、一瞬で格子の作成されるさまが気持ちいいのと楽さに改めて感動ました。


#コード
自動格子作成を実現するコードはいかになります。

```VB
Sub 格子作成()
   
    Dim Farst As Range               '値が入っているセル
    Dim Last As Range               '最終セル
    Set Last = Selection(Selection.Count)

    ' 画面更新と計算を停止
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual

    For Each Farst In Selection      '選択セル範囲ループ

        If (Farst.Value <> "") Then 'セルに値が入っている場合格子作成する
        '以降上下左右の枠線を描画
            Range(Farst, Last).Select
        Selection.Borders(xlDiagonalDown).LineStyle = xlNone
            Selection.Borders(xlDiagonalUp).LineStyle = xlNone
            With Selection.Borders(xlEdgeLeft)
                    .LineStyle = xlContinuous
                    .ColorIndex = 0
                    .TintAndShade = 0
                    .Weight = xlThin
            End With
            With Selection.Borders(xlEdgeTop)
                .LineStyle = xlContinuous
                .ColorIndex = 0
                    .TintAndShade = 0
                .Weight = xlThin
            End With
            With Selection.Borders(xlEdgeBottom)
                .LineStyle = xlContinuous
                    .ColorIndex = 0
                    .TintAndShade = 0
                    .Weight = xlThin
            End With
            With Selection.Borders(xlEdgeRight)
                    .LineStyle = xlContinuous
                    .ColorIndex = 0
                    .TintAndShade = 0
                    .Weight = xlThin
            End With
            Selection.Borders(xlInsideVertical).LineStyle = xlNone
            Selection.Borders(xlInsideHorizontal).LineStyle = xlNone
        End If
    Next

    ' 画面更新と計算を再開
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic

End Sub
```

値の一つ左のセルの中身が"○","〇","●","■","□"である場合は線を描画しないようにしています。
基本形はこのコードになりますが、一行目のみ背景の色を付けたり、一行目のみ下線を二重線にしたり等工夫する余地はあると思います。また、コードもマクロの記録で作成した箇所が大半なので無駄が多いと思います。インデント？何それ？

#使い方
格子を作りたい範囲に値を入力しその範囲を選択後、マクロを実行するだけです。

#最後に
実際このマクロが役に立つかわかりませんが、お役にたてば幸いです。
また、このコードをもとに改良できた等あれば共有していただけたら嬉しいです。
dockerで作ったRailsプロジェクトをロリポップ！マネージドクラウドにあげるのに手こずった話

# 前置き
dockerを使ってRailsの開発を趣味でやっていた。
ひと段落ついたので、サーバーに公開しようと思ったがエラーが出てなかなかうまくいかなかった話です。

# エラーの内容
```console:console
ArgumentError: Missing `secret_key_base` for 'production' environment, set this string with `rails credentials:edit`
```

# 解決法
```console:console
EDITOR=vim rails credentials:edit --environment production
```

dockerに入って上のコマンドを実行していたが、Vimが入っていなかったので、一見できてるようでできていなかった。
編集画面が出てこないのでおかしいとは思っていたが、ファイルはしっかり生成されているし大丈夫だと思っていたのが罠だった。

あとはマネクラのプロジェクト管理画面で環境変数の設定をしておく。
<img width="1792" alt="スクリーンショット 2020-05-16 23.24.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323051/61e5154b-a348-4cbd-b046-7c8d62dd5f64.png">
ここに入れる値の内容は、`/config/credentials/production.key`の内容をコピーして貼り付ける。

その後以下のファイルを作った。

```ruby:/config/deploy.rb
append :linked_files, 'config/credentials/production.key'
```

これは
> Railsがproduction.keyを参照するためのシンボリックリンクを貼る記述を追加する。

という感じらしい。

最後にSSHでマネクラにアクセスして以下のファイルを作っておいてからPushするとOK

```console:console
vim user_command.sh
```

```sh:user_command.sh
test -f ~/shared/.env && ln -s ~/shared/.env ./.env || true
export RAILS_ENV=production

bundle install --deployment --without development,test --path vendor/bundle
bin/rails db:create
bin/rails db:migrate
```

# 最後に
なかなか解決せずに６時間くらい悩みました。
３０分休憩してから再度取り掛かったらすぐに解決しました。
煮詰まったら一回休むってほんと大事

# お世話になった記事
[Rails 6でCapistranoでデプロイする際のCredentials関連エラーに対処する](https://qiita.com/tatama/items/aaa1300f55da5da2933a)
[[Ruby on Rails]ロリポップ！マネージドクラウドでRailsアプリを稼働させるまで](https://qiita.com/tosite0345/items/10db024c500a7d97cf41)
Firebaseで最短でHelloWorldを表示する

同じようなタイトルの記事は無限にあるのに、どれに沿ってやってもできなかったので書く
たしかディレクトリ（フォルダ）のとこがどこにも書かれてなかった気がする

## Firebaseに登録
https://firebase.google.com
から適当に登録
Googleに登録しとけばそれで良いのかも



## プロジェクト作成

#### プロジェクトを追加
![スクリーンショット 2020-05-16 22.12.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620387/8ce407ee-26c4-4e11-9c7c-c7b7010a3e5b.png)

####プロジェクト名を決める
![スクリーンショット 2020-05-16 22.26.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620387/3bdc4a40-7d70-b399-b224-7ced559f5892.png)
プロジェクト名は他の人と被っても大丈夫だけど、被ってる場合のドメインは下に出てる**灰色のやつがプロジェクトIDでありドメイン**になる
（今回はsample-project-39b8b、鉛筆マークで編集可、後から変更不可）

あとはなんか適当にok押しまくる

## 作業用フォルダ作成
好きな場所に空のフォルダを作成
今回は
user/Firebase/SampleProject
で作成しておくので、今後この場所が出てきたら自分の場所と入れ替えて認識して
プロジェクト名と揃えておくと良いかと


## Nodejsインストール
コマンドラインからNodejsとfirebaseをインストールします
これは他の記事で行けたので[ここら辺](
https://qiita.com/Masaki_Mori07/items/70693d0be264e2295163)参照して各自よろしく


## コマンドライン操作
コマンドプロンプトなりターミナルなりのCLIに以下コマンドを入力

#### firebaseログイン

```:CLI
cd ~/Firebase/SampleProject # SampleProjectのあるディレクトリへ移動
export PATH=$PATH:`npm bin -g` # PATHを通す
firebase login
```
ここに書いてるPATHの中身はmac用かな？
cdでさっき作った作業ディレクトリを指定して、firebaseにlogin、そのまんま


#### 作業フォルダ初期化
はじめに戻すって意味じゃなくて、初期設定って意味

```:CLI
firebase init --project=プロジェクトID
```

#### Hosting選択
![スクリーンショット 2020-05-16 22.50.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620387/4178c407-be73-247d-0ff5-d04062293228.png)
上記の画面が出たら、上下キーで選んで、スペースキーでon/offを切り替え
今回はHostingのみ選択してEnter

#### 初期設定
![スクリーンショット 2020-05-16 22.54.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620387/7fcf2a4c-b111-8b25-e492-484efea11f21.png)
デプロイ（アップロード）するフォルダの名前を聞いてると思うんだけど、デフォルトのpublicにしておいた方が混乱しないと思うのでEnter


![スクリーンショット 2020-05-16 22.55.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620387/870a244f-14c1-7739-1101-62a1bcf65085.png)
どこにアクセスしても全部index.htmlに飛ばす？って聞いてる気がする
余計なことはしない、No
大文字になっている方がデフォルトらしいのでEnter


## デプロイ
ここまでやるとさっき作ったSampleProject内にいろいろファイルが作られる
![スクリーンショット 2020-05-16 23.03.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620387/e743a0fd-9e8b-7dc4-6b34-9acd8abd8fc3.png)


CLIでデプロイをするとpublicフォルダの中身がアップロードされる（なんでアップロードじゃなくてデプロイって言うんだよ素直にアップロードって言ってくれよ）
htmlとかjsとかcssとかはここに入れる
index.htmlの中身を好きなように編集する
今回はタイトル通り、全てを消して以下の１行だけにしてみる

```:index.html
hello world
```

#### デプロイ
CLIから以下のコマンドを入力

```:CLI
firebase deploy
```


Deploy complete!って言われたら完了
![スクリーンショット 2020-05-16 23.17.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620387/839ebaa8-bb47-c437-505a-679a335fde8d.png)

今まで秘密にしてたけどプロジェクトIDはsampleproject-yukiでした
Hosting URL: https://sampleproject-yuki.web.app
って書いてあるので、ご指定のURLに行くと無事hello worldが表示されているはず
今私のURLに飛んでも私の検証用の何かがあるかもしれんしプロジェクト消えてるかもしれんけど

ログイン以降はちゃんとやりながら書いたからこれでできるはず


## 参考にした記事
[FirebaseでWebページを公開するまで](https://note.com/airis0/n/na552c7483608)
QTableWidget  の指定列をReadOnly にするStyledItemDelegate

備忘録かつ添削をお願いしたく投稿します。
C++の例を書き換えたStyledItemDelegateを書いてみました。
ReadOnlyStyledItemDelegateです。

```python:ReadOnlyStyledItemDelegate.py
from PySide2.QtWidgets import QStyledItemDelegate

class ReadOnlyStyledItemDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        super().__init__(parent)

    def createEditor(self, parent, option, index):
        return None
```
特定列更新不可は実務的には必要な機能だろうと思います。
C++の例がnull返しなのだから、Noneで良いのでは？という程度の理解で書いてます。
createできないのだからdelegateが実装すべき後の機能は親任せで良いだろうということで、createEditorのみです。