OmniAICreator/Qiita-1.07M huggingface dataset:
【GAS初歩】いらないトリガーを削除して新しいトリガーを設定する

Googleフォームで定期的に回答を収集するときなど、イベントを設定するときにトリガーを作っては消して作っては消してと手作業で繰り返すことが面倒臭かったので、コードを書いた。

```
const TM_OP = 'YYYY-MM-DD HH:mm'; //実行してほしい時間

ScriptApp.getProjectTriggers()
         .forEach(i=>ScriptApp.deleteTrigger(i)); //不要なトリガーの除去
ScriptApp.newTrigger('setFormActive') //トリガーの作成
         .timeBased()
         .at(new Date(TM_OP))
         .create();
```

肝は、先にすべてのトリガーを削除してから新しいトリガーを追加する点。
まず [ScriptApp クラス](https://developers.google.com/apps-script/reference/script/script-app)の `getProjectTriggers()` でプロジェクト内のトリガーを全部取得して、 `deleteTrigger()` でひとつずつ削除する。地道。

### 応用
もし特定のトリガーを削除したくない場合…例えば関数を基準にふるい分けをするときは `getHandlerFunction()` で関数名調べて、削除する・しないを決める。

```
ScriptApp.getProjectTriggers()
         .forEach(i=>{
           if(i.getHandlerFunction()!='[Function name]')
            ScriptApp.deleteTrigger(i)
         });
```

# コード全体
[form_open-close.gs（アンケートフォームの開閉）](https://github.com/togazo/samples/blob/master/others/GAS/form_open-close.gs)- GitHub([@togazo](https://github.com/togazo))

##### 機能解説（補足）
* 決まった時間になったらアンケートフォームの回答を受け付ける
* 決まった時間になったらアンケートフォームの回答を締め切る
* スクリプト実行後のフォームの表示確認での回答の締め切りのON/OFFを繰り返していると締め切り忘れる場合があるので、一通りの作業が終了したであろう5分後に締め切る
* ついでにスプレッドシートに収集している過去の回答を非表示にする（フォームを使い回す時にアクティブな回の分だけパッと見たいから）
AWS IAMでのポリシーに指定できるアクションやリソースの一覧について

AWS IAMでポリシーを指定する際の、`Action`や`Resource`といった指定について。

たとえば、以下はEC2のドキュメントの例。

```yaml
{
   "Version": "2012-10-17",
   "Statement": [{
      "Effect": "Allow",
      "Action": [
         "ec2:DescribeInstances", 
         "ec2:DescribeImages",
         "ec2:DescribeTags", 
         "ec2:DescribeSnapshots"
      ],
      "Resource": "*"
   }
   ]
}
```

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/iam-policies-ec2-console.html

こういったところに、なにが書けるかがよくわからなくなるので。

一覧は、こちらを見ると良いようです。

https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html

ポリシーの概念は、こちら。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies.html

よく探し方を忘れるので、メモ。
Ruby会議2021 レポート

こんにちは！最近rubyを書き始めたHiraです！
今回は、Ruby会議2021に参加してきたので紹介したいと思います！
ほとんど、自分のメモ用なので、実際の内容に関して知りたい方は、公式のYoutubeがアップロードされていたので、そちらからご確認ください！
https://www.youtube.com/channel/UCBSg5zH-VFJ42BGQFk4VH2A

イベントのタイムスケジュールとセッション

https://rubykaigi.org/2021-takeout/schedule#day1

## セッション
すべてを見ることはできなかったので、個人的に気になったトピック

### TypeProf for IDE: Enrich Dev-Experience without Annotations

https://www.slideshare.net/mametter/typeprof-for-ide-enrich-development-experience-without-annotations

IDEによる、静的型付けがメインのお話

- ruby3.1から解析が可能
- rubyの静的解析機はTypeProf,Steep,Sorbet等がある。
- 其の中でも、TypeProfは、型を明示しなくても良いが、エラーレポートが弱いらしい。
- RBSを書いて上げると静的解析の際に早く解析でき、明示しているのでご動作もあんくなる。

### Why Ruby's JIT was slow
JITと呼ばれるコンパイラのお話。正直、コンパイラの話は全然わからなかったが、AtCoderなどの競技プログラミングをする際にはコンパイルの速さとかが関係あるので、意識しなければならないポイントなのかもしれない、、、

- MJITが悪さをしていて遅くしていた。
- MJITを使うとcにコンパイルしているから、わかりやすい。
- cにコンパイルしていることで、後にgccにコンパイルするから、メンテンス性が良くなる。
- m-jit,y-jit,MIRなどの種類がある。

### RuboCop in 2021: Stable and Beyond
RuboCopによる静的解析ツールのお話
ver1.0以前の方が一番ダウンロード数が多かったらしい、、、！

https://github.com/rubocop/rubocop

- 新しいcopが入ってきた際には、pendingで選択できるようにしている。
- 新しいcopを入れるときにどうするかをnew cop: trueみたいなので、適用できる。
- 新しいrubyの場合は、最新にupdateする必要あり。
- parallelオプションを使う場合はとても早くなる。defaultになった。
- ルールが厳しいと感じたら
	- DiasabledByDefault: trueを使って、実際の遭遇したものを随時copとして、追加していく。
	- rubocop_rails_config のgemを使うことによって、ruleが厳しいと感じたら使う。
- Steepなどをいれて、静的解析をもう少し賢くするというか、型による解析を行っていこうと思っている。

### The Art of Execution Control for Ruby's Debugger
個人的に一番良かったセッション、、、！時間があるときに使ってみたい！
新規のdebug gemの話。
スライド: https://www.atdot.net/~ko1/activities/2021_rubykaigi_takeout.pdf

https://github.com/ruby/debug

- 既存のデバッガー
    - lib/debug.rb
    - byebug
    - debase  ruby-debug
- Ractorに対応するために作られた
- vscodeとも連携していて、breakpointの指定とかもできて、変数名などもみることができる。
- trace on 、trace offもできて、一部のlogみたいなのを出せる。
- リモートデバッグができる。(railsのデバッグもできる！)
- record onみたいなので、巻き戻視機能があり、変数の値などが確認できる。
- __break pointを使っても、既存のデバッガーよりも大分早い！__

### The newsletter of RBS updates

最新のRBSとして、依存関係を見たうえで勝手にRBSファイルを作成してくれるという便利になったよ的なお話。個人的に、RBSをつかうのであれば、めちゃくちゃ役立つ気がする、、、？

https://github.com/pocke/rubykaigi-2021

- RBS railsと呼ばれる、ruby on railsのためのRBS生成機がある。

__新機能(rbs collection)__
- rbsのためのbundler
- third partyのためのrbsを準備するのが厳しかったため、開発した。
	- もともと、rbsをrailsに入れるために、全て依存関係を考えた上で、行う必要があった。
	- rbsコマンドと、steepの設定が混雑していた。
- rbsコレクションコマンドを使うと、依存性を自動的に解決してくれる。
- rbsファイルの設定をコマンド操作可能になる。
- gemfile.lockから、依存関係を認識している。

### Charty: Statistical data visualization in Ruby
rubyによるグラフの可視化。

https://github.com/red-data-tools/unicode_plot.rb

- 統計的データ可視化
	- A列とB列とC列があった際に、それに対応したデータの作成が可能。
- グラフ処理は外部ライブラリに任せている
	- plotolyなどを使っている。
- 様々な入力パターンに対応している。
- adopterを書くことで、対応する型を増やすことが可能。

### Ruby, Ractor, QUIC
Ractorを使った、QUICの実現。Transport層での通信周りを行っている話で、パケット通信をrubyで行っていた。パケットの生成から、デコードまで行おうとしていたが、残念ながらRactor内でOpenSSLが使えずに終わってしまった。今後、対応していけば、こういったことも実現できるので期待大。

## 全体の所感
ruby初心者には難しいセッションが多かったですが、噛み砕いて説明してくれるセッションも多く、勉強になりました！
新しいgemや静的解析のツールが今後も出てくると思うので、いろいろと使ってみたいなと感じました！
(英語のセッションがほんとに聞き取れなかったので、そこも勉強しなきゃと感じました、、、。)
python指定フォルダ内のサブフォルダにあるファイルを別のフォルダに移動する

以下のフォルダ内に複数サブフォルダがあり、サブフォルダ内のmp4ファイルを
G:/folder/
├── folder1
│　　└── file2.mp4
└── folder2
　　　 ├── file3.mp4
　　　 └── file4.mp4

以下のフォルダのように移動するプログラムです。
G:/move_folder/
├── file2.mp4
├── file3.mp4
└── file4.mp4

絶対パスで指定できます。

```move_folder.py
#指定フォルダの下にあるサブフォルダ内のmp4ファイルを指定フォルダに移動
import os
import glob
from pathlib import Path
import shutil

#パスは/に変更
dir_path = Path("G:/folder/")#サブフォルダがあるフォルダ
move_path = "G:/move_folder/"#ファイルを移動するフォルダ
#サブフォルダをリストにする
subfolder_list = dir_path.iterdir()
#ファイルを移動
for subfolder in subfolder_list:
   #サブフォルダがあった場合
   if subfolder.is_dir():
      #サブフォルダ内のmp4ファイルをリストにする
      subfolder_file_list = list(subfolder.glob("*.mp4"))
      #mp4ファイルを指定フォルダに移動する
      for move_file in subfolder_file_list:
         print(move_file)#移動するファイル
         new_path = shutil.move(move_file, move_path)
```
dockerでNginxコンテナ立てたら.conf.templateが効かなくなった

ローカルでdocker-composeを使って構築していた環境を共用環境に構築しようとしたらNginxでtemplateが効かなくなったので、備忘録としてメモしておきます

# 設定

詳細は省略します。

```docker-compose.yml
  proxy:
    image: nginx
    container_name: proxy
    volumes:
      - ./nginx/dev.conf.template:/etc/nginx/templates/default.conf.template
    ports:
      - 80:80
   environment:
      - SERVER_PORT=3000
      - LISTEN_PORT=80
```

```nginx/dev.conf.template
server {
    listen ${LISTEN_PORT};
    server_name localhost;

    location / {
        proxy_pass http://localhost:${SERVER_PORT}/;
    }
}

```

# 結論

nginxのDockerイメージを1.20にする


### 調査内容

`docker exec -it proxy sh`でコンテナ内に入ってtemplateファイルを確認しましたがちゃんとコピーされていました。
ローカルと共用環境で`docker images`でイメージのバージョンを確認したところ、両方とも`latest`でしたがCREATEDの日付が異なっていました。
[DockerHub](https://hub.docker.com/_/nginx?tab=tags&page=1&ordering=last_updated)でバージョンを確認したところ、ローカル環境構築のlatestは1.20で共用環境構築時のlatestは1.21のようでした。

そこで、試しにNginxのDockerイメージを1.20にしてみたところちゃんとtemplateに従ってリバプロしてくれるようになりました。

```docker-compose.yml
  proxy:
    image: nginx:1.20
```

真の原因は不明ですが、いったんこれで回避することにしました

[DockerHubの説明](https://hub.docker.com/_/nginx)を見るとtemplate自体が1.19で新しく追加された機能みたいなのでまた不安定なのかもしれないですね。

> ##### Using environment variables in nginx configuration (new in 1.19)
> Out-of-the-box, nginx doesn't support environment variables inside most configuration blocks. But this image has a function, which will extract environment variables before nginx starts.
> 
> Here is an example using docker-compose.yml:
> 
> ```
> web:
>   image: nginx
>   volumes:
>    - ./templates:/etc/nginx/templates
>   ports:
>    - "8080:80"
>   environment:
>    - NGINX_HOST=foobar.com
>    - NGINX_PORT=80
> ```
> By default, this function reads template files in /etc/nginx/templates/*.template and outputs the result of executing envsubst to /etc/nginx/conf.d.
> 
> So if you place templates/default.conf.template file, which contains variable references like this:
> 
> `listen       ${NGINX_PORT};`
> 
> outputs to /etc/nginx/conf.d/default.conf like this:
> 
> `listen       80;`
>
> This behavior can be changed via the following environment variables:
> 
> * NGINX_ENVSUBST_TEMPLATE_DIR
>   * A directory which contains template files (default: /etc/nginx/templates)
>   * When this directory doesn't exist, this function will do nothing about template processing.
> * NGINX_ENVSUBST_TEMPLATE_SUFFIX
>   * A suffix of template files (default: .template)
>   * This function only processes the files whose name ends with this suffix.
> * NGINX_ENVSUBST_OUTPUT_DIR
>   * A directory where the result of executing envsubst is output (default: /etc/nginx/conf.d)
>   * The output filename is the template filename with the suffix removed.
>     * ex.) /etc/nginx/templates/default.conf.template will be output with the filename /etc/nginx/conf.d/default.conf.
>   * This directory must be writable by the user running a container.

引用：https://hub.docker.com/_/nginx
初心者の初心者によるシェル、ターミナル、zshについて

2021年4月ごろからMacを使いだした初心者が、新たにMacを使いだす初心者に向けて送る解説記事です。
シェルやターミナルなどの単語をわかりやすくまとめることを目的に書きました。

## きっかけ
プログラミングの環境構築でよく目にする「ターミナル」「zsh」「シェル」

Wikipediaで調べてみても見慣れない単語が多く、「なんだか難しそう」とすこし嫌な気分になってしまったものです。
そんな気分を感じる方が少しでも減るように、「なんとなく」「やんわりと」概要をつかめるような解説を書いてみます。


## シェル
**macと人間の仲介役**になってくれるプログラムの一つです。
自分がやりたいことをmacに噛み砕いて伝えてくれたり、逆にmacが伝えたいことを私達にわかりやすくしてくれます。

電気で動くコンピュータには、人間の行動や意思は直接理解することができないのです。

macに対し、キーボードやマウスなどで自分の意思を伝えると「なるほどね、こういうことをしたいのね〜」「macが動けるように伝えるよ〜」と働いてくれます。

## ターミナル
macに標準でインストールされている文字でmacを操作するソフトです。
**文字で入力した命令を受け取ってシェルに伝えてくれます。**
Windowsでいうコマンドプロンプトのようなものです。

commandキー + スペースを押してSpotlight検索を開き「ターミナル」と入力してEnterキーを押してみましょう。
黒い背景に白い文字…なんだかドラマでハッカーが開いているような画面が出てきました。

試しに「ls」と入力してEnterキーを押してみましょう。
フォルダやファイルの一覧が表示されます。

今回は、「ターミナルが命令を受け取り」「命令をmacが理解できるように仲介し」「macが理解してくれた」から「ls」というプログラムを実行できました。

## zsh
macOS Catalina(10.15)からmacで標準搭載となったシェルです。**シェルの種類のひとつ**ということですね。
macでターミナルからコマンドを実行した場合、このzshというシェルが仲介してくれることになります。

---

## 参考元
[Wikipedia:「ターミナル (macOS)」](https://ja.wikipedia.org/wiki/%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB_(macOS))
[Wikipedia:「macOS Catalina」](https://ja.wikipedia.org/wiki/MacOS_Catalina)
[Linux標準教科書](https://linuc.org/textbooks/linux/)
ターミナルでマトリックスを出現させて遊ぶ

映画「マトリックス」が12月に公開されるらしいので、ターミナルで出現する方法を探してみました。

Pythonでunimatrixという記述があったのでそちらを使って文字を落としていきます。
方法としては、スクリプトをインストールし実行するだけのものです。

参照
https://github.com/will8211/unimatrix

#インストール
```
$ pip install git+https://github.com/will8211/unimatrix.git
```
#使用方法① 
unimatrixを実行するとデフォルトで文字やスピードなどが実行されます　。

```$ unimatrix
```

![default.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1462552/016e36da-98f3-603a-b368-5e8bfe4e88c0.png)

#使用方法②
文字の色と表示する文字を変える方法

unimatrixを実行する際に、カラーと文字を指定します。
 
```
$ unimatrix -c green -u 'matrix'
```
また、キーボードで操作する方法もあるみたいです。
終了する時：ｃｔｒｌ　＋　ｃ
矢印キー
　左：スピードを1落とす
　右：スピードを1上げる
　下：スピードを10落とす
　上：スピードを10落とす
 
ナンバーキーで文字色を変更
  (1) 緑 (2) 赤 (3) 青 (4) 白 (5) 黃 
(6) 暗い青  (7) ピンク  (8) 黒(9) デフォルト  

Shift + ナンバーキーで背景色の変更も可能
（個人的には変更前の背景色のほうが好み）

上記の他にも機能はたくさんあるのでこちらのリンクよりお試しください。
https://github.com/will8211/unimatrix
Unity 独自の仮想キー

### 1.GameObjectのExtensionに。
```C#
    public static async Task<string> GetVKey(this GameObject @this,int delaytime=1000/200){
 ...
}

```

### 2.リソースフォルダーに入れておくのみ。
```C#
//Assets/Resources/InputGetter.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading.Tasks;
public class InputGetter : MonoBehaviour
{
    public Dictionary<string,KeyCode> keymap=new Dictionary<string, KeyCode>(){
        {"<",KeyCode.A},
        {">",KeyCode.D},
        {"^",KeyCode.W},
        {"V",KeyCode.S},
        {"A",KeyCode.J},
        {"B",KeyCode.K},
        {"X",KeyCode.L},
        {"Y",KeyCode.O},
        {"L",KeyCode.U},
        {"R",KeyCode.I},
        {"S",KeyCode.Space},
        {"P",KeyCode.Return},
    };
    [SerializeField] string vkey="";
    public async Task<string> GetKey(int delaytime=1000/200){
        vkey ="";
        while(vkey=="") await Task.Delay(delaytime);
        return vkey;//<>^V ABXYLR SP
    }
    void Update() {
        if(vkey=="")
         foreach (var k in keymap)
            if (Input.GetKeyDown(k.Value)) vkey = k.Key;
    }

}//class

public static class GameObjectInputExtension{
    static GameObject getter;
    public static async Task<string> GetVKey(this GameObject @this,int delaytime=1000/200){
        if(getter==null){
            getter = new GameObject("InputGetter");
            getter.AddComponent<InputGetter>();
        }
        return await getter.GetComponent<InputGetter>().GetKey(delaytime);
    }
}//class

```

### 3.適当なゲームオブジェクトから呼び出す。
```C#
    async void Start()
    {
        Debug.Log(await gameObject.GetVKey());   
    }

```
python初学者の備忘録　型について

#### [←目次へ](https://qiita.com/dondondon/items/cd45224ca93e65c976cc)

:::note info
python,Qiita初心者なので、備忘録として記載していきます。
なにせ初心者なので、知識不足はご容赦ください。
知識を深めながら追記していきたいと思います。
:::

# データ型とは

`基本`
<dl>
　<dt>
    <a href="https://qiita.com/dondondon/items/1c7ff18c2d9627772e8e">int型(整数型)</a></dt>
 <dd>例：「1」「-5」など</dd>
 <dt>
  <a href="https://qiita.com/dondondon/items/1c7ff18c2d9627772e8e">float型(浮動小数型)</dt>
 <dd>例：「0.1」</dd>
 <dt>
  <a href="https://qiita.com/dondondon/items/75326c64e1704ed35493">str型(文字列型)</dt>
 <dd>例：「あ」</dd>
 <dt>
  <a href="https://qiita.com/dondondon/items/412b8e5c147cc3c0c38f">bool型(ブール型)</dt>
 <dd>例：「True」「False」</dd></dl>

# 型を調べる

`type()関数`：型を返す

```python:type.py
number = 1
number2 = 1.0
number3 = '1.0'
greeting = 'こんにちは' または "こんにちは"
is_ok = True
print(number,type(number))
print(number2 ,type(number))
print(number3 ,type(number))
print(greeting ,type(number))  
print(is_ok ,type(number))

# -- 実行結果 --
# 1 <class 'int'>           # -- 数値型 --
# 1.0 <class 'float'>       # -- 浮動小数型 --
# '1.0' <class 'str'>       # -- 数値型に見えるが文字列 --
# こんにちは <class 'str'>   # -- 文字列型 --
# True <class 'bool'>       # -- ブール型 --
```
M1 Macbook AirにおけるDigispark開発環境の設定

#はじめに

DigisparkはHIDデバイスとして、マウスやキーボードのような挙動をするデバイスが構築可能な開発ボードです。
ようやく手をつけてみたのですが、環境設定で色々つまづいたのでまとめます。
なお、開発環境はM1 Macbook Air(OS Big Sur, 11.5.2)を使用しています。

#目次
<!-- タイトルとアンカー名を編集 -->
1. [Digisparkの購入](#Chapter1)
2. [Arduino IDEのインストール](#Chapter2)
3. [Arduino IDEのセットアップ](#Chapter3)
4. [困ったエラー](#Chapter4)

<a id="#Chapter1"></a>
#Digisparkの購入
Amazonで購入しました。
手っ取り早くて良いですね。

https://www.amazon.co.jp/gp/product/B01N0C5PTJ/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1

<a id="#Chapter2"></a>
#Arduino IDEのインストール
以下のサイトからmac OS X用の最新のIDEをダウンロードします。（この記事の時点の最新版は1.8.16です。）

https://www.arduino.cc/en/software

インストールは解凍するだけですね。
趣味でアプリケーションフォルダにアイコン入れてもいいですね。
MacOSなのでドライバのインストールも不要なようです。

<a id="#Chapter3"></a>
#Arduino IDEのセットアップ
###ボードマネージャの追加

Arduino IDEを開き、Arduino>Preferenceをクリックします。
追加ボードマネージャに以下のURLを追加します。

```
http://drazzy.com/package_drazzy.com_index.json
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016927/441ebaf4-117c-5c76-2a52-2104958e2122.png)

###ATTinyCoreのインストール
ツール>ボードマネージャをクリックし、「ATTinyCore」をインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016927/d3983e85-2478-3979-fd20-bee838c009eb.png)
バージョンは最新のもの（1.5.0）を選択しました。

###ボードの設定
ツール>ボード> ATTinyCore>ATtiny85 (Micronucleous / Digispark)を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016927/1bc855c6-aa7f-1d7a-3c06-d8575ed2f516.png)
書き込み装置は特にいじらなくても問題ないそうです。

###シリアル接続の確認
DigisparkをUSB経由で接続します。
ツール>シリアルポートでUSBデバイスが認識できているか確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016927/06ea85c3-7c4b-c784-0735-97ad817da914.png)
この画像では/dev/cu.usbserial-140がDigisparkボードですね。
見えない場合はUSBケーブルを変えたり、HUB経由で接続するなどしてみてください。

これで初期設定は終了です。
サンプルのLEDチカチカさせるプログラムをアップロードすれば楽にテスト出来るかな。

<a id="#Chapter4"></a>
#困ったエラー

```
Flash erase error -32 has occured ...
```

このエラーからボードの再選択って発想がきつかったなあ。

DigisparkをDigistump系のボードで開発するとこういうメッセージが出ました。
全然間違っている気がしなかったけど、きっとそういうもんなんだろう。
多分、海外の掲示板でもそこそこ間違ってる人いるんじゃないかなあ。
GASでスプレッドシートからドキュメントへ出力

# GASでスプレッドシートからドキュメントへ出力

業務で引っかかったので、覚書。
画像のサイズ設定で引っかかった。
外部ライブラリの[imgApp](https://github.com/tanaikech/ImgApp#how-to-install)で解決した。

##準備

あらかじめスプレッドシートへファイルIDなどを起こしておく。
A列　名前　B列　詳細情報　C列画像のファイルIDとしておく。

```js

/**
 * スプレッドシートの内容をテキストファイルへ出力
 */
function outputTextFile() {
  // 出力するフォルダのID(出力先のフォルダIDを設定)
  const folderId = 'フォルダID';

  // 出力するファイル名
  const Name = "出力ファイル名.txt"
  const doc = DocumentApp.create(Name);
  const body = doc.getBody();

  // アクティブなスプレッドシートを取得
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

  // アクティブなシートを取得
  const sheet = spreadsheet.getActiveSheet();

  //　最終行を取得
  const lastRow = sheet.getLastRow();

  for (let i = 1; i <= lastRow; i++) {

    // テキストに出力する範囲のデータを取得
    let imageName = sheet.getRange(i, 1).getValue();
    let description = sheet.getRange(i, 2).getValue();
    let imageId = sheet.getRange(i, 3).getValue();
    let blob = DriveApp.getFileById(imageId).getBlob();

    // 画像の縦横比を取得
    let res = ImgApp.getSize(blob);
    let width = res.width;
    let height = res.height;

    // 節の名称を14pxで最終行へ挿入
    let addImageName = body.appendParagraph(imageName);
    addImageName.editAsText().setFontSize(14);

    // 説明を11pxで最終行へ挿入
    let addDescription = body.appendParagraph(description);
    addDescription.editAsText().setFontSize(11);
    
    // 画像を横300pxでアスペクト比を揃えて大きさを編集し最終行へ挿入
    body.appendImage(blob).setWidth(300).setHeight(300 * height / width);

  } // for i
}
```

`appendImage()` で最終行へ画像を出力することができる。
アスペクト比を保ったまま縮小したかったが、`setWidth()` , `setHeight()` はpxで指定する必要があったので、先に縦横の長さを取得している。


##参考

https://developers.google.com/apps-script/reference/document/body?hl=ja#appendImage(BlobSource)
テスト46

```vb

Sub rep()

'...φ(´・ω・｀ )＜ﾒﾓです。

Dim tmp As String
Dim tmp2 As Variant
Dim i As Integer

With ThisWorkbook.Sheets("開始")

    tmp = Trim(Replace(.Cells(11, 3).Value, "　", " "))

    tmp2 = Split(tmp, " ")

End With


For i = LBound(tmp2) To UBound(tmp2)

    If InStr(tmp2(i), "テスト") Then
    
        MsgBox tmp2(i)
    
    End If

Next

End Sub
python初学者の備忘録　数値型について

#### [←目次へ](https://qiita.com/dondondon/items/cd45224ca93e65c976cc)

:::note info
python,Qiita初心者なので、備忘録として記載していきます。
なにせ初心者なので、知識不足はご容赦ください。
知識を深めながら追記していきたいと思います。
:::

# 数値型とは
`基本`

+ int型（整数）
+ float型（浮動小数点数）
+ complex型（虚数）

:::note warn
虚数、複素数については別項で行います。
:::

+ 以下の演算子を使うことが可能


_[python初学者の備忘録　代数演算子について →](https://qiita.com/dondondon/items/23f9c09e4f3555c6fbc7)_

##### `数値の演算`

```python
>>> 5 + 3
8

>>> 5 - 3
2

>>> 5 * 3
15

>>> 5 / 3
1.66666666666666667

>>> 5 % 3
2

>>> 5 ** 3 # 5 * 5 * 5と同様
125

>>> 5 // 3
1
```

##### `int型とfloat型の計算`

```python
>>> 5 + 3.0
8.0

>>> 5 - 3.0
2.0
```

:::note alert
int型とfloat型で計算した場合float型になる
:::

## [数値型で使用する関数 →](https://qiita.com/dondondon/items/79df395634a68aa82c6f)
Expanded() == Flexible(fit: FlexFit.tight)

FlutterのExpandedとFlexibleの違いのメモです。

Expandedを使って以下のコードを書いた場合。

```dart
          child: Column(
            children: [
              Expanded(
                child: Container(
                  color: Colors.pink,
                  child: Text('あいうえお'),
                ),
              ),
              Container(
                height: 150,
                color: Colors.orange,
              ),
              Expanded(
                child: Container(
                  color: Colors.purple,
                ),
              ),
            ],
          ),

```
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185927/2f57e368-246b-9fd6-ecae-53ca33681163.png  width=300>

端末一番上の `Text('あいうえお)`は、Columnの親がExpandedで囲われているため、可能な限り縦の領域を埋め尽くそうとWidgetが広がります。

```dart
              Expanded(
                child: Container(
                  color: Colors.pink,
                  child: Text('あいうえお'),
                ),
              ),
```

タイトル通り、Expandedの部分を、 `Flexible(fit: FlexFit.tight)`に変更して囲うと、結果は同じ表示になります。


```dart
          child: Column(
            children: [
              Flexible( // 変更
                fit: FlexFit.tight,
                child: Container(
                  color: Colors.pink,
                  child: Text('あいうえお'),
                ),
              ),
              Container(
                height: 150,
                color: Colors.orange,
              ),
              Expanded(
                child: Container(
                  color: Colors.purple,
                ),
              ),
            ],
          ),

```


というのも、ExpandedはFlexibleを継承していて、 `fit: FlexFit.tight`で作られています。

```dart
class Expanded extends Flexible {
  /// Creates a widget that expands a child of a [Row], [Column], or [Flex]
  /// so that the child fills the available space along the flex widget's
  /// main axis.
  const Expanded({
    Key? key,
    int flex = 1,
    required Widget child,
  }) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);

```

先程のコードで、 `fit: FlexFit.tight`の部分を `fit: FlexFit.loose`にした場合。

```dart
          child: Column(
            children: [
              Flexible(
                fit: FlexFit.loose, // 変更
                child: Container(
                  color: Colors.pink,
                  child: Text('あいうえお'),
                ),
              ),
              Container(
                height: 150,
                color: Colors.orange,
              ),
              Expanded(
                child: Container(
                  color: Colors.purple,
                ),
              ),
            ],
          ),

```

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185927/26146a96-3591-66da-0026-842e81dae060.png  width=300>

空いている領域を全て埋め尽くすことはせず、子Widgetの高さだけ広がります。

フォントサイズが大きくなるなどの、子Widget大きくなってoverflowしそうなときは、 `fit: FlexFit.tight`と同じ挙動をして、広がれる限界まで広がります。
今回は、Columnの子に3つのWidgetを置いていますが、FlexibleとExpandedの `flex: 1`がそれぞれデフォルトで設定されているため、最初と最後のWidgetが1対1で広がるようになっています。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185927/05f53e80-60c6-dc1a-37e9-04e8155592cd.png  width=300>
AWSCLIでIAMUser/IAMRoleとpolicyを紐付けてMarkDownで出力させる

# １．前置き

IAMユーザ一覧を作成する際にコンソールからコピーして作ろうとしたらIAMのポリシーを一つ一つ転機する必要があって
非常に手間だったので、AWSCLIでワンライナーでマークダウン形式で出力するコマンドを作りました。

# ２．前提
jqを使用するので予めjqのインストールが必要です。

# ３．IAMUserとPolicyを紐付けてMarkDownで出力

## ３．１．コマンド

```
echo "|User|Groups|Policies|\n|---|---|---|"; for u in `aws iam list-users | jq -r '.Users | .[].UserName'`; do echo -n "|$u|" && aws iam list-groups-for-user --user-name $u | jq -rc '.[] | [.[].GroupName] | @csv' | ghead -c -1 && echo -n "|" && aws iam list-attached-user-policies --user-name $u | jq -rc '.[] | [.[].PolicyName] | @csv' | ghead -c -1 && echo "|"; done
```

## ３．２．結果(例)

```
|User|Groups|Policies|\n|---|---|---|
|test-user1|"ReadOnly"|"xxxx-policy","xxxxx-policy"|
|test-user2|"ReadOnly"|"xxxx-policy","xxxxx-policy"|
```

上の出力結果をマークダウンで記載すると以下のようなテーブルになります。

|User|Groups|Policies|
|---|---|---|
|test-user1|"ReadOnly"|"xxxx-policy","xxxxx-policy"|
|test-user2|"ReadOnly"|"xxxx-policy","xxxxx-policy"|


# ４．IAMUserとPolicyを紐付けてMarkDownで出力

## ４．１．コマンド

```
echo "|Role|Policies|\n|---|---|"; for u in `aws iam list-roles | jq -r '.Roles | .[].RoleName'`; do echo -n "|$u|" && aws iam list-attached-role-policies --role-name $u | jq -rc '.[] | [.[].PolicyName] | @csv' | ghead -c -1 && echo "|"; done
```

## ４．２．結果(例)

```
|Role|Policies|\n|---|---|
|AmazonEC2RoleforSSM|"CloudWatchAgentServerPolicy","AmazonSSMManagedInstanceCore"|
|AmazonSSMManagedInstanceCore|"CloudWatchAgentServerPolicy","AmazonSSMManagedInstanceCore","AmazonSSMFullAccess"|
```

上の出力結果をマークダウンで記載すると以下のようなテーブルになります。

|Role|Policies|
|---|---|
|AmazonEC2RoleforSSM|"CloudWatchAgentServerPolicy","AmazonSSMManagedInstanceCore"|
|AmazonSSMManagedInstanceCore|"CloudWatchAgentServerPolicy","AmazonSSMManagedInstanceCore","AmazonSSMFullAccess"|
ロリポップでDrupal 9を動かす2021

# 概要

* ロリポップに Drupal 9 を導入するときに若干手間取ったので備忘録。
* 2021/09/13に書いています
 *  Qiitaは後から編集すると記事のタイムスタンプが変わってしまう仕様なので念のためここに書いておきます。

# 今回試した環境

* Drupal 9.2.5
* ロリポップ・スタンダードプラン

# 前提

* ここではレンタルサーバの使い方、SSHやDNSなどの仕組みはだいたいわかっている前提で進めます。また、ロリポップのコントロールパネルの説明は簡略化しています。
* 試しに入れてみようと思った時のメモなので、本番運用はあまり想定していません。
* 以下は独自ドメインにアクセスするとルート直下でDrupalが表示される、という前提の設定になります。

# ロリポップの初期設定

## PHP7.4にする。

* コントロールパネルで「独自ドメイン設定」もしくは「サブドメイン設定」を行い、ドメインに対して公開フォルダを指定します。
* 「PHP設定」に行き、上記で設定したドメインに対し、バージョンを7.4(CGI版)にします。

## OPCacheを有効にする。

* php.iniの設定で opcache.enable とopcache.enable_cli をOnにします。

## SSHでComposerを使えるようにする。

* SSHを有効にします。
* SSHでログインするとコマンドラインでは php5.5 が認識されているので、7.4に変えます。

```
$ php -v
PHP 5.5.35 (cli).....
$ ls -1 /usr/local/php
5.2
5.3
5.4
5.5
5.6
7.1
7.3
7.4
$ echo "export PATH=/usr/local/php/7.4/bin:$PATH" >> ~/.bash_profile
$ source ~/.bash_profile
$ php -v
PHP 7.4.12 (cli).....
```

## データベースを作成する
* 適当に作ってください。データベース名、データベースホスト、ユーザー名を控え、パスワードを覚えておきます。
  * ただしロリポップはパスワードを忘れてもコントロールパネルで確認できます（この仕様どうなの）。

# Drupalのインストール

## ファイルの展開

* SSHでログインし、公開フォルダに移動します。
* ComposerでDrupalをインストール

```
$ composer create-project drupal/recommended-project .
```

## ルートディレクトリの変更

* ComposerでインストールしたDrupalはwebというサブディレクトリに入っているので、コントロールパネルのドメイン設定で公開ディレクトリの後ろに/webを追加しておく。

## Drupalの初期設定

ブラウザでアクセス。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90225/4d017ed4-9764-8f1b-79d1-e4aea5b40da3.png)
日本語が良ければ日本語を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90225/18bf21b5-5c03-213e-e3ea-5e1f7a53c7ed.png)
ここはお好きに。

ここで設定を一旦中断（データベースのセットアップは現状ではうまく行かない）

## Drupal 9 を MySQL5.6 で使えるようにする

* ロリポップのMySQLは5.6のため最新の Drupal9 はデフォルトでは入らない。このため「MySQL 5.6 and MariaDB 10.0 database driver for Drupal 9」を導入する必要がある。
  * この手順では setttings.php の手動編集を行うため、上記GUIからの初期設定を途中まで進めておく必要がある。

```
$ cd web
$ mkdir -p drivers/lib/Drupal/Driver/Database/mysql
$ cd drivers/lib/Drupal/Driver/Database/mysql
$ wget https://ftp.drupal.org/files/projects/mysql56-8.x-1.2.tar.gz
$ tar -xvzf mysql56-8.x-1.2.tar.gz --strip-components=1
```

* ブラウザで設定したドメインにアクセス。Drupalの初期設定画面が表示される。
* MySQL 5.6 and MariaDB 10.0 database driver for Drupal 9のマニュアル通りに設定。ただしマニュアルでは配列名が \$databases とtypoしている。ここは \$database が正しい。

```:web/sites/default/settings.php
....
$database['default']['default']['namespace'] = 'Drupal\\Driver\\Database\\mysql'; #末尾に追加
```

## 初期設定つづき

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90225/e67931ce-423f-a317-1d9b-8b3f8037345e.png)
データベース名、ユーザ名、パスワードに加え、高度なオプションを開き、データベースホストの値を入れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90225/bc0010fc-c807-179a-c73a-c93525e69d87.png)

ここはお好きに。

以上で Drupal9 がロリポップ上にインストールされます。
フォアグラウンドサービスの作り方

## はじめに

通常のサービスには制限がありますが、フォアグラウンドサービスにすることにより制限を緩和できます。

## 実装

次のコードは通常のサービスの実装です。

```kotlin
class MyService : Service() {
  override fun onBind(intent: Intent): IBinder? {
    return null
  }

  override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    return START_STICKY
  }
}
```

それに対して次のコードはフォアグラウンドサービスの実装です。

```kotlin
class MyService : Service() {
  override fun onBind(intent: Intent): IBinder? {
    return null
  }

  override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    val CHANNEL_ID = "asdf"

    // Android 8.0 以降では必ず通知チャネルを作成する必要がある
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      val mChannel =
        NotificationChannel(
          CHANNEL_ID,
          "ここが通知チャネル名として表示される",
          NotificationManager.IMPORTANCE_DEFAULT,
        )
      mChannel.apply {
        description = "ここが通知チャネルの説明として表示される"
      }
      val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
      // 既存の通知チャネルを作成しても問題ない
      manager.createNotificationChannel(mChannel)
    }

    // Android 8.0 よりも前では `CHANNEL_ID` は無視される
    val notification = NotificationCompat.Builder(this, CHANNEL_ID).build()
    startForeground(1, notification)
    return START_STICKY
  }
}
```

通知チャネルと通知を作成し、`startForeground()` に通知を渡しています。この通知はサービス起動中は常に通知領域に表示されます。

フォアグラウンドサービスを生成する側では、次の2行のコードを実行するだけでOKです。

```kotlin
val intent = Intent(this, MyService::class.java)
startForegroundService(intent)
```

## 通知チャネルの注意点

* 一度作成した通知チャネルの名前、説明文、優先度は変更できない
* フォアグラウンドサービスを起動するだけであれば `setSmallIcon` は必須ではない（通常の通知では必須）
* ただし、`setSmallIcon` を設定しないと `setContentTitle` と `setContentText` の設定は反映されない
【Laravel】中間テーブルのmigrationファイルを作るときは順番に注意

タイトルの通りですが、何も気にせずmigrationファイルをつらつら作っていたらエラー発生したので、忘れないようにメモです。

# 前提知識
Laravelのmigrationは作成日順に実行される。今日はとりあえずここさえ覚えてもらえればOKです。

```bash
2014_10_12_000000_create_users_table.php
2014_10_12_100000_create_password_resets_table.php
2019_08_19_000000_create_failed_jobs_table.php
```
こんな順番ですね。

# さて本題
中間テーブルを作成する時にこのmigrationファイルの実行順番でエラーになりました。
が、よく考えてみれば当たり前の挙動でした。

## テーブル構成(例)
rolesテーブル
role_usersテーブル(中間テーブル)
usersテーブル

## migrationファイルを作る時に起こったこと
DB設計書通りの順番でrolesテーブル→role_usersテーブル→usersテーブルと `php artisan make:migration`でファイルを作りました。
ファイルの先頭に付く日付は、
rolesテーブル
role_usersテーブル(中間テーブル)
usersテーブル
この順番になりますね。

その後`php artisan migrate`すると、、、

```
SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table ....
```
中間テーブルで落ちました。外部キーの設定かな？と一瞬思いましたが、よく見ると参照できないって言っている。
あ、まだもう一個のテーブルが作られていない！

### 中間テーブルはこんな構成(例)
```
    public function up()
    {
        Schema::create('role_users', function (Blueprint $table) {
            $table->unsignedBigInteger('role_id');
            $table->unsignedBigInteger('user_id');
            $table->dateTimes();

            //外部キー制約
            $table->foreign('role_id')
                ->references('id')
                ->on('roles')
                ->onDelete('cascade');
            $table->foreign('user_id')
                ->references('id')
                ->on('users')
                ->onDelete('cascade');
            
            // 複合主キー
            $table->primary(['role_id', 'user_id']); 
        });
    }
```

中間テーブルが外部キーの設定をするため、usersテーブルを参照しにいくが、まだusersテーブルはmigrationが実行されていないため参照できなくてエラーになるというわけですね。

# 解決方法
解決方法は単純で、中間テーブルを最後に作ればいいだけです。

```
rolesテーブル
usersテーブル
role_usersテーブル(中間テーブル)
```
こんな感じですね。
これでエラーにならないはず。

# 補足
Laravel5.8系からはIDカラムがbigintになっているので、中間テーブル側も合わせて `unsignedBigInteger` にしないとダメです。
キーワード検索で指定フォルダ内のファイル名一覧を取得する方法 ExcelVBA


##仕様
指定フォルダ内でキーワード検索をして
該当したファイル名一覧をExcelシート上に記入する

・ 動作前に記入セル内をクリアする
・ 以下の時はポップアップ表示

1. 終了時に該当件数をポップアップ表示
1. 検索キーワード未記入の場合

##ユーザーから見た画面

①で検索ワードを記入
②「検索する」ボタンを押下
③検索結果のファイル名一覧が表示される
![マクロ定義シート見本1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433296/1a370e98-c9dd-ba8d-686b-0be6d0ad7166.jpeg)
Cドライブにtestファイルを作りました。
![テスト用に作ったフォルダ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433296/61fbc118-03b1-8910-20c1-27631f87d269.jpeg)
結果画面
![マクロ定義シート見本2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433296/3f5749e5-344e-8a49-815c-0a1286e1543f.jpeg)
検索キーワード未記入の場合
![913.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433296/cd65d176-9838-29be-8fd2-42f32c76cb62.jpeg)


```vb

Sub ファイル一覧の取得()

    Dim format As String '拡張子'
    Dim cnt As Long 'カウント'
    Dim MaxRow As Long '最終行'
    
    Const Path As String = "C:\test\" '固定ディレクトリパス'
    
    buf = Range("B4").Value '検索ワード'
    format = Dir(Path & "*" & buf & "*.xlsx") '検索するExcelファイル名'
    cnt = 6 '検索結果 ファイル名記入セルの行番号-1'
    
    
    Range("B7", Range("B7").SpecialCells(xlLastCell)).ClearContents  '検索結果セル内の値をクリアする'
    
    If buf = "" Then
    
        msg = "検索ワードを入力してください。"
    
        MsgBox msg, Buttons:=vbInformation
    
    Else
    
        Do While format <> ""  '空文字になるまで繰り返す
            cnt = cnt + 1
            Cells(cnt, 2) = format
            format = Dir() 'フォルダに存在するすべてのファイル名を取得する
            
        Loop
        
        Debug.Print cnt
    
        MaxRow = Cells(Rows.Count, 2).End(xlUp).row 'B列=2'
        FileNum = MaxRow - 6 '検索結果数'
        
        
        If FileNum < 0 Then
            FileNum = 0
        End If
        
        
        msg = "検索結果 " & FileNum & " 件"
    
        MsgBox msg, Buttons:=vbInformation
    
    End If
    
End Sub
HandleFuncとHandleでは何が起きてる？違いは？

###`HandleFunc`と`Handle`の実行部分
***注）実行したい関数、オブジェクトを`helloHandler`とする。***

#### `HandleFunc`の実行部分

`http.HandleFunc("/hello", helloHandler)`

#### `Handle`の実行部分

`http.Handle("/hello", &helloHandler{})`

とても似ている！！！
なにが違うの？？

###`HandleFunc`と`Handle`の違い
どちらも第1引数にはURLをとる。この二つには第2引数に違いがある。
#### `HandleFunc`

`http.HandleFunc`は、第2引数に`http.ResponseWriter`と`*http.Request`を取る関数を**そのまま**渡せる。

#### `Handle`
`HandleFunc関数`とは違い、`Handle関数の第2引数`には関数を指定しない。`Handle`では`helloHandler型のServeHTTP関数`を定義した`Handlerのポインタ`を指定する。

つまり、`http.Handle`は、第2引数に***`http.Handler`インタフェースを実装したオブジェクト***を渡す。
ん？`http.Handler`インタフェースを実装したオブジェクトって？
`Handler`とは**`ServeHTTP`という関数**を定義したインターフェイスのこと。[参考：Handlerの公式ドキュメント](https://pkg.go.dev/net/http#Handler)
つまり、第2引数は`ServeHTTP(http.ResponseWriter, *http.Request)`という関数を実装したオブジェクトあれば良い。

`func (t *helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { }`　のように`helloHandler`用に`ServeHTTP`を自分で実装する。
そうすると`helloHandler`は`ServeHTTPメソッド`を実装しているため`http.Handler`インタフェースを実装したオブジェクトとなる。

###これまでのことも含め、何が起きているのかを見てみる
#### `HandleFunc`
```
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
	DefaultServeMux.HandleFunc(pattern, handler)
}
```
[-公式ドキュメントより参照](https://pkg.go.dev/net/http#HandleFunc)
第1引数ではURLのパターンを受け取り、第2引数ではURLで実行したい関数を受け取る。
そして`DefaultServeMux.HandleFunc`に登録される。これはURLと`Handler`の関連付けをおこなう役割を持つ。
`DefaultServeMux`はグローバルな`ServeMuxのインスタンス`。`net/http`パッケージにおいてあらかじめ`DefaultServeMux`が用意されている。

***つまり、`HandleFunc`では引数にURLと関数を渡すことで、それら二つを関連づけたものを登録してくれる。そして、URLにアクセスすると登録したところから探し出し、関数を実行してくれる。***

#### `Handle`
```
func Handle(pattern string, handler Handler){
	DefaultServeMux.HandleFunc(pattern, handler)
}
```
[-公式ドキュメントより参照](https://pkg.go.dev/net/http#Handle)
第1引数では`HandleFunc`同様、URLのパターンを受け取る。第2引数ではURLで実行したい関数を`ServeHTTP関数`に定義した`Handlerのポインタ`を受け取る。
そして`DefaultServeMux.HandleFunc`に登録される。

###`HandleFunc`と`Handle`の実装例
最後に`HandleFunc`と`Handle`の実装例を見てみる。

***注）実行したい関数、オブジェクトを`helloHandler`とする。***

#### `HandleFunc`の実装例

```
package main
 
import (
	"fmt"
	"net/http"
)
 
func helloHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "<h1>Hello, World</h1>") //「/hello」URLで実行したい処理
}
 
func main() {
	http.HandleFunc("/hello", helloHandler)
	http.ListenAndServe(":8080", nil)
}
```
このようにURLで実行したい関数を作成し、実行では`HandFunc関数`に引数としてURLと関数を渡す。


#### `HandleFunc`の実装例

```
package main
 
import (
	"fmt"
	"net/http"
)
 
type helloHandler struct{}
 
func (*helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "<h1>Hello, World</h1>") //「/hello」URLで実行したい処理
}
 
func main() {
	http.Handle("/hello", &helloHandler{})
	http.ListenAndServe(":8080", nil)
}
```
まずオブジェクトを作成し、URLで処理したい関数を`ServeHTTP`内に記述する。
このように、`ServeHTTP関数`を定義した`helloHandler型`の`Handler`（**`ServeHTTP`という関数**を定義したインターフェイス）を作る。
実行では、`http.Handle`にはURLと`http.Handlerインタフェース`を実装したオブジェクト(`helloHandler`)を引数として渡す。

###参考文献
[Go言語の公式ドキュメント 「http.Handler」](https://pkg.go.dev/net/http#Handler)
[Go言語の公式ドキュメント 「http.HandleFunc」](https://pkg.go.dev/net/http#HandleFunc)
[Go言語の公式ドキュメント 「http.Handle」](https://pkg.go.dev/net/http#Handle)
「bundle exec cap production puma:start」が使えない時の対処方法

#はじめに
下記の記事を参考に本番環境を構築中、
https://qiita.com/d0ne1s/items/2dd0ec73db1b0f473509
「bundle exec cap production puma:start」実行時にエラーが発生したため
解決方法をまとめた。

#エラー内容
```
% bundle exec cap production puma:start
(Backtrace restricted to imported tasks)
cap aborted!
Don't know how to build task 'puma:start' (See the list of available tasks with `cap --tasks`)

(See full trace by running task with --trace)
```
#環境
rails 6.1.4
ruby 2.7.3
nginx 1.20.1
puma 4.3.8

#解決方法
Capfileに「install_plugin Capistrano::Puma::Daemon」を追加する。

```
require "capistrano/setup"
require "capistrano/deploy"
require 'capistrano/rails'
require "capistrano/rbenv"
require "capistrano/bundler"
require "capistrano/rails/assets"
require "capistrano/rails/migrations"
require "capistrano/scm/git"
require "capistrano/puma"

install_plugin Capistrano::SCM::Git
install_plugin Capistrano::Puma
install_plugin Capistrano::Puma::Daemon.                      ＜ー追加
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

・
・
・
```

#まとめ
pumaをデーモン化していたため、Capfileに追記が必要だった。

#参考

https://qiita.com/d0ne1s/items/2dd0ec73db1b0f473509

https://matthewhoelter.com/2020/11/10/deploying-ruby-on-rails-for-ubuntu-2004.html
59日後にITパスポートを受けるFラン私大文系既卒(46日目)

# デフォルトゲートウェイ
* デフォルトゲートウェイとは?
 * 他のネットワークへの出入り口を担っている機器(ルータ)

# SDN(Software Defined Network)
* SDNとは?
 * ネットワークを構成する通信機器をソフトウェアで制御する技術

# ESSID(Extended Service Set Identifier)
* ESSIDとは?
 * 無線LANにおけるネットワークの名前

# ESSIDステルス
* ESSIDステルスとは?
 * ESSIDを周囲から見えないようにする機能

# PoE(Power over Ethernet)
* PoEとは?
 * イーサネットケーブルを用いて電力を供給する技術

# PLC(Power Line Communication)
* PLCとは?
 * 屋内の電力線を通信回線としても利用する技術

# 輻輳
* 輻輳とは?
 * 通信回線が渋滞すること

# IMPA(Internet Message Access Protocol)
* IMPAとは?
 * 電子メールをダウンロードせずに、メールサーバ状で閲覧するためのプロトコル

# IPv6
* IPv6とは?
 * IPv4に変わる次世代のIPアドレス

# NAT(Network Address Translation)
* NATとは?
 * プライベートIPアドレスをグローバルIPアドレスへ変換する技術

# DHCP(Dynamic Host Configuration Protocol)
* DHCPとは?
 * IPアドレスを各コンピュータに自動的に割り当てるプロトコル

# RSS(Rich Site Summery)
* RSSとは?
 * Webサイトの見出しや要約などを記述するフォーマット

# FTTH(Fiber To The Home)
* FTTHとは?
 * 光ファイバを使った家庭向けの通信サービス

# ルーティング
* ルーティングとは? 
 * 異なるネットワークにパケットを送信するときに、最適な配達経路を決めること

# 回線交換方式
* 回線交換方式とは?
 * 一つの回線を独占して使う通信方式

# パケット交換方式
* パケット交換方式とは?
 * データを小分けにして送って、届いたところで復元させる方式

# TCP/IP(Transmission Control Protocol / Internet Protocol)
* TCP/IPとは?
 * 世界基準的に利用されている通信プロトコル
 * 送ったデータが届いたか、その都度確認しながら通信をする方式


# ISP(Internet Service Provider)
* ISP
 * インターネットサービス事業者


# サブネットマスク
* サブネットマスクとは?
 * ネットワークアドレスとホストアドレスを識別する値
 * コンピュータが同じLAN内にいるか判断するときに使用されることが多い

# キャリアアグリゲーション(Carrier Aggregation : 集約)
* キャリアアグリゲーションとは?
 * 複数の異なる搬送波を束ねて、一つの通信回線としてデータの送受信を行う技術



# イントラネット
* イントラネットとは?
 * 組織内でのみ構築されたネットワーク環境 

# トラックバック
* トラックバックとは?
 * ブログで他の人が書いた記事を参照・引用した際に、そのことをその記事を書いた人に通知する機能

# クローラ
* クローラとは?
 * 検索エンジンが検索順位を決める要素を、サイトから収集してくるロボットのこと
pycharmでインスペクション(値の評価)

# 方法
ソースコード内で評価したい箇所を選択して右クリック、式の評価で見ることができる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351239/335ae4b5-7569-ac76-6701-28984a13ddb9.png)
JTrimを利用して複数のキャプチャ画像から同じ位置・同じサイズで切り出す

いきなりですが、皆さんは以下のような画像(資料)を作成する場合、どのような方法で作成しますか？

![SECUAL_masa_投稿記事視聴数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1236186/dd5bec3b-0ce0-104d-509e-95108f8cd598.png)

上記の画像は私が投稿した記事の視聴数を一覧化したもので、おおまかな作成フローは以下の通りです。

1.ブラウザのタブを利用し各記事を表示。
2.タブ毎・記事毎の表示を切り替えながらキャプチャソフトでキャプチャ。
3.キャプチャ画像から資料としてまとめたい部分を切り出し保存。
3.PPTにキャプチャ画像を貼りつけ列挙。(+整形)
4.PNGに保存

この記事ではこの手の画像・資料を作成する際に私がいつも利用する「手順3」の切り出し＆保存をJTrimという画像編集ソフトを利用して実現する方法について説明したいと思います。(JTrimを利用することで複数のキャプチャ画像から同じ位置・同じサイズの切り出しが容易に行えます)

# 利用するJTrimの機能

![JTrim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1236186/285cd6cd-dbdd-ef61-dee3-6866c4cffcdc.png)

上図にもある「切り抜き」と保存だけです。

# 準備

手順1～手順2で各記事をキャプチャします。
今回は以下の3枚で説明を進めます。

![キャプチャした画像群.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1236186/c5b5f61a-8b40-af30-6fa2-be0d7cb57404.png)

# 切り出し(初回のみ)

初回だけ切り出したい位置と範囲を選択します。

## 1. ツールバー上の「切り抜き」ボタンを選択し、位置と切り出し範囲の決定

![JTrim_切り出し位置の決定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1236186/581e2bea-fb08-9497-ab8a-72e40542cbac.png)

※JTrimのウィンドウの中に、キャプチャ画像(Edgeで1つ目のタブ/1ページ目)を表示している画像です。
※画像中のQiitaロゴ～「はじめに」に掛かっているグレーの枠が切り出し位置・範囲を示しています。

## 2. 「座標指定切り取り」ダイアログの「OK」を選択して切り出し

![JTrim_切り出し後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1236186/1545b9c0-3775-a3d6-c402-453fdb753ce4.png)

※上記手順1のグレーの枠内の画像だけに切り出された画像です。

## 3. 保存

ツールバー上の「保存」アイコンや、ショートカットの「Ctrl+S」を利用して保存します。

![初回の切り出し後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1236186/1ff226f4-328a-900e-b008-1710a576cfe8.png)

# 切り出し(2回目以降)

あとは「切り出し(初回のみ)」の手順1～3を繰り返すだけになります。
「切り出し(初回のみ)」で実施した位置と切り出し範囲が保持されているため、再度位置と切り出し範囲を決定する必要なく、ボタン ポチポチ(最後はCtrl+Sかも？)だけで終わります。

その時の様子は以下になります。

![op.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1236186/cda050f4-87ee-7c7b-06c6-02b2d4488ca0.gif)

# 最後に

紹介しつつ実はこのソフト、随分前から更新が止まっています。(2014年頃から)
以下のように2018年に脆弱性の対応はいただいているようですが。

「WinShot」「JTrim」のインストーラーにDLL読み込みに関する脆弱性 ～ZIP版の利用を - 窓の杜
https://forest.watch.impress.co.jp/docs/news/1109770.html


もし同様の機能が、こんなやり方でできる！などあれば是非教えてください。
［Laravel8］少量のダミーデータを入れたいとき。シーダーの設定方法メモ

大量のダミーデータをデータベースに入れたいときは、FakerとFactoryを組み合わせて使います。
今回は、数個程度の少量のダミーデータを入れる為の、シーダーの使い方をメモしておきます。
管理者（Admin）のダミーデータを入れる想定で書いていきます。

環境：XAMPP for Windows, Laravel8
公式マニュアル：
https://laravel.com/docs/8.x/seeding#writing-seeders

#1. artisanコマンドでシーダーを作る。

まずは以下のようにartisanコマンドでシーダーを作ります。

```
php artisan make:seeder AdminSeeder
```

そうすると、以下画像の通り、database\seeders配下にAdminSeederのファイルが作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235741/cfd9eba8-9711-8527-db7e-46c4141a4f20.png)

#2.　シーダーファイルを設定する。

作成されたAdminSeederファイルに設定していきます。
まずは、DBファサードを使うので、use文で読み込みます。また、今回はパスワードもデータベース保存したいので、パスワードをHash化する為のHashファサードも読み込みます。
次に、run()メソッド内部を書いていきます。DBファーサードのtable()メソッドには、挿入したいテーブル名を書きます。また、insert()メソッドで、ダミーデータを連想配列形式で書いていきます。（キーの部分はテーブルのカラム名。）

```C:\xampp\htdocs\ec-site\database\seeders\AdminSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;   //DBファサード読み込み
use Illuminate\Support\Facades\Hash;   //Hashファサード読み込み

class AdminSeeder extends Seeder
{
    public function run()
    {
        DB::table('admins')->insert([
            'name' => 'アドミン太郎1',
            'email' => 'admin1@test.com',
            'password' => Hash::make('password123'),
            'created_at' => '2021/09/13'
        ]);
    }
}
```

#3. DatabaseSeeder.phpファイルに登録する。

database\seeders\DatabaseSeeder.phpファイルのrun()メソッド部分に、作ったシーダーファイルを登録します。

```C:\xampp\htdocs\ec-site\database\seeders\DatabaseSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        $this->call([
            AdminSeeder::class     //作ったシーダーファイルを登録する。
        ]);
    }
}
```

#4. artisanコマンドでテーブルに挿入する。

以下いずれかのコマンドでテーブルに挿入します。

普通にデータを入れたいとき。

```
php artisan db:seed
```

既存のデータを消して、新たにデータを入れたいとき。（他のテーブルの既存データも消える。）

```
php artisan migrate:fresh --seed
```

これで指定したカラム名にデータが入ります！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235741/a44d55a1-0381-73b9-41a8-72f7bc549347.png)

#5. おまけ

上記ではダミーデータが一個だけだったけど、複数個入れるときは、以下のように配列の配列にします。

```C:\xampp\htdocs\ec-site\database\seeders\AdminSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

class AdminSeeder extends Seeder
{
    public function run()
    {
        DB::table('admins')->insert([
            [
                'name' => 'アドミン太郎1',
                'email' => 'admin1@test.com',
                'password' => Hash::make('password123'),
                'created_at' => '2021/09/13'
            ],
            [
                'name' => 'アドミン太郎2',
                'email' => 'admin2@test.com',
                'password' => Hash::make('password123'),
                'created_at' => '2021/09/13'
            ],
            [
                'name' => 'アドミン太郎3',
                'email' => 'admin3@test.com',
                'password' => Hash::make('password123'),
                'created_at' => '2021/09/13'
            ],
        ]);
    }
}
```

以上です。
【個人開発】コードレビューサービスKanon CodeでOGP設定するときにハマったこと

#【個人開発】コードレビューサービスKanon CodeでOGP設定するときにハマったこと
フロント：Next.js
ホスティング：vercel


この記事ではOGPの説明は割愛します。

## 参考記事一覧
[Next.jsにおけるSSG（静的サイト生成）とISRについて（自分の）限界まで丁寧に説明する](https://qiita.com/thesugar/items/47ec3d243d00ddd0b4ed)
[nextjsのISRを使うときのfallback指定について理解するまでの話](https://zenn.dev/terrierscript/articles/2021-04-28-nextjs-isr-fallback)
[fallbackに関して【公式】](https://nextjs.org/docs/basic-features/data-fetching#fallback-true)

## 下調べが足りなかった箇所
- OGPで表示される画像の拡張子
- OGPで表示される画像の最小サイズ
- fallbackの挙動についての理解

## OGPに関すること
これは自分がドキュメントを読むのが遅かったです。
まずドキュメント
まずドキュメント
まずドキュメント
大切なことなので3回言いました。

## fallbackの挙動
fallbackの説明をする前にまずはSSGです。
SSGは事前に htmlファイルをレンダリングします。
クライアントは、事前にレンダリングされたhtmlをただ表示させるだけです。

こちらがSSGに設定するコードです。
まずエラーになっていたコードがこちらです。

```js
import Head from 'next/head'

type Props = {
  user: UserType
}

const IndexPage = (props: Props) => {
  const user = props.user
  return (
    <Head/>
    // この中でuserを使う
  )
}

export const getStaticPaths = async () => {
  return {
    paths: [],
    fallback: true,
  };
};

export const getStaticProps = async (props: any) => {
  const result = await sameApi();
  return {
    props: {
      user: result.data.user,
    },
    revalidate: 30,
  };
};

export default IndexPage;
```

要らない部分は省略していますが構成はこんな感じです。
このソースコードをbuildすると以下のようなエラーが吐かれます

>TypeError: Cannot read property 'user' of undefined

このエラーを見てSSGってgetStaticPathsとgetStaticPropsの実行後にbuildされるんじゃないの？と思いました。
原因はfallback: trueでした。

### fallbackとは
fallbackでは、SSGで生成されていないパスにアクセスした際の挙動の設定ができます。

false: 404を返す
true: CSRに近い動きをする。データ取得を要する部分以外がレンダリングされてレスポンスされる
blocking: SSRされる。サーバー側でレンダリングしてレスポンスする

そして、このfallbackをtrueにした場合はpropsが空になるのです。
>In the “fallback” version of a page:
The page’s props will be empty.
Using the router, you can detect if the fallback is being rendered, router.isFallback will be true.

https://nextjs.org/docs/basic-features/data-fetching#fallback-true

なぜ空になるのかは恐らくこの部分だと思います。
>The paths that have not been generated at build time will not result in a 404 page. Instead, Next.js will serve a “fallback” version of the page on the first request to such a path (see “Fallback pages” below for details).
ビルド時に生成されなかったパスは、404ページにはなりません。代わりに、Next.jsはそのようなパスへの最初のリクエストに対して、「フォールバック」バージョンのページを提供します（詳細は後述の「フォールバックページ」を参照）。

つまり用意されていない場合は、fallbackページを返したいためbuild時にデータ取得を要する部分以外をレンダリングしているのだと思います。

なので、propsが空になるんだろうと思います。

fallbackをblockingにして対処しました。

まずドキュメント
まずドキュメント
まずドキュメント


### まとめ
不具合が起きたときは何が問題になっているかの切り分けが非常に大切だと感じます。
ドキュメントを読んだところで、何が問題になっているのかが分からないと検討のつけようがないので。

またkanon Codeでは、Next.js node.js pythonのコードレビューを受け付けております。
基本使用料はもちろん無料で、コードレビューには金額を設定して販売することも可能です。

また、Kanon Codeでは現在ユーザーインタビューを実施しています。
ユーザーインタビューに答えていただけた方にはお礼として、最大¥2000のAmazonギフト券をプレゼントしております。
十分な金額ではございませんが、技術書だったり日用品の購入の足しにしていただければと思います。

[Kanon Code](https://kanon-code.com)
[ユーザーインタビューお問い合わせ](https://twitter.com/kanon_code_com)
退会したユーザーの表示を変える

現在投稿系のアプリを作っていて退会したユーザーの扱いどうしようかなーと考えていたら、teratailなどのサービスで「退会済みユーザー」のような表記になっているのを見受けました

直感的に見てもわかりやすいし実装もしやすそうだなと思ったのでこれで行こうと思います。
<h1>実装</h1>

まず退会機能なんですが、完全にデータを削除といったことはせずに退会したことにするといった
__論理削除__といった状態にするといいといろんな記事に書いてありました。

論理削除の概要については下記記事がわかりやすかったので参考させていただきました

https://qiita.com/wanko5296/items/f1af9c7bf020e867c2dd

情報提供を依頼されたりするときにすぐに出せるようにするみたいなこともあるみたいですね。
誹謗中傷とか犯罪予告とか

まあ僕の場合は投稿系なので100件投稿してくださったユーザーが退会した時にそれを全部削除するってなったら中身がスカスカになりそうだと思ったんで退会した場合はユーザーネームを
__退会済みユーザー__みたいな表記に変えてコメントや投稿を残すことにしました


まずは退会の扱いですが、users,テーブルに__is_deleted__とか__deleted_flag__みたいなカラムを持たせてboolean型で追加します

```ruby:maigration
class AddIsDeletedToUsers < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :is_deleted, :boolean, default: false, null: false
  end
end
```

*add_column (追加したいテーブル), (カラム名), (データ型), null:falseなどの制約*

デフォルトをfalseにすることで退会処理が実行された時にtrueになり、このユーザーは退会したユーザーとして扱えます。

```ruby:view
例) <% if @user.is_deleted == false %> *is_deletedがfalseなので退会していないことになる
     <%= @user.username %>
   <% else %>　　  *elseでis_deleted == trueの場合、つまり退会した場合の表示にする*
     退会済みユーザー
   <% end %>
```

もっと適切な使い方があるのだと思いますが、僕はこれが精一杯でした。。
こんな感じで投稿やコメントは残したまま退会ユーザーとして扱えます。

結構穴がある実装だと思います。
正直これ以外でつかえる場面が思いつかないのでこれでいいか不安ですがとりあえず現状は問題ないのでこのまま行きます。
退会したら30日間は同じメールアドレスで登録できないみたいな感じの動作が理想なのでしょうが、データが変わるのはis_deletedだけなので他のカラム(username,email,password)達は残っているので退会したら同じメールアドレスでログインすることが2度とできなくなるっぽいです
まあデータが残ったままですからね

自分でも調べますが、こんなん良いよみたいな案がありましたらコメントで教えていただけると幸いです。
AWS Elastic Beanstalkで環境作成時の注意点

## 発生していた現象

* AWS Elastic Beanstalk からアプリケーションを作成しようとすると「The instance profile aws-elasticbeanstalk-ec2-role associated with the environment does not exist.」のというエラーメッセージが表示されてしまい環境構築に必ず失敗してしまう
* 強い権限があるはずのルートユーザで実行しても上記と同様のエラーで起動できなくなってしまっている
* `aws-elasticbeanstalk-ec2-role` ロールはIAMロールに定義されている

## 原因

AWS ElasticBeanstalkの初回のアプリケーション作成時にIAMロール（`aws-elasticbeanstalk-ec2-role` および `aws-elasticbeanstalk-service-role`）の自動作成を行うが、作成時のユーザの権限によって中途半端な状態でIAMロールが作成されてしまう場合がある。
一度IAMロールが作成されてしまうと、以降のElastic Beanstalkのアプリケーション作成時にそのIAMロールが使用されてしまうため、ルートユーザなど強い権限のユーザでもアプリケーション作成を行うことができない状態になってしまうと考えられる。

## 回避方法

##### 1. IAMロールを操作できる権限のユーザで以下を実施

* `aws-elasticbeanstalk-ec2-role` ロールの削除
* `aws-elasticbeanstalk-service-role` ロールの削除

##### 2. ElasticBeanstalkでアプリケーション作成を行うユーザにIAMロールの作成権限を付与

* https://docs.aws.amazon.com/ja_jp/emr/latest/ManagementGuide/emr-iam-roles-create-permissions.html に記載されている権限を付与する

##### 3. ElasticBeanstalkでアプリケーション作成を行う

* 2.のユーザでElasticBeanstalkのアプリケーション作成を実施する
* 初回起動時に 1.で記載した2つのIAMロールが自動生成される