OmniAICreator/Qiita-1.07M huggingface dataset:
メタプログラミングRuby クラス定義について

## クラス定義
クラスにはメソッド以外にもあらゆるコードを記述できます。
```
class Example
  puts 'Hoge!'
end #=>Hoge!

result = class Example
  self
end

result #=> Example
```
クラス定義の中では、クラスがカレントオブジェクトになるんです。つまりselfになるんです。

### クラスインスタンス変数
クラス定義の中で定義されたインスタンス変数のことをクラスインスタンス変数といいます。
実際にコードを見ていきましょう
```
class Example
  @var = 1
  def self.read; @var; end
  def write; @var = 2; end
  def read; @var; end
end

obj = Example.new
obj.read #=> nil
obj.write #=> 2
obj.read #=> 2
Example.read #=> 1
```
1つ目の```@var```は```obj```がselfになるんです。objオブジェクトのインスタンス変数なんです。
2つ目の```@var```は```Example```がselfになるんです。Exampleクラスというオブジェクトのインスタンス変数なんです。

## 特異メソッド
特異メソッドとは特定のオブジェクトで参照できるメソッドのことを特異メソッドといいます。
たとえば、あるオブジェクトが本のタイトルかどうかを調べるメソッドを記述しましょう。
```
str = 'Qiitaのタイトルが入ります' #動的に文字列が入ると仮定してください

def str.title?
  self.upcase == self
end

str.title?　#=> false
```
そして実はクラスメソッドも実は特異メソッドなんです。
以下の記事で詳しく解説しているのでご一読ください。

https://qiita.com/wangqijiangjun/items/3e97b5bfe9d61a5d5cd5

## 特異クラス
Rubyという言語は、オブジェクトにクラスを聞くとすべてを教えてくれるわけではないんです。
実は、オブジェクトは裏に特別なクラスを持っているんです。その特別なクラスが特異クラスと呼ばれるものなんです。
以下のコードを見てみましょう。
```
'abc'.singleton_class
=> #<Class:#<String:0x000001e1626b1378>>
```
ここから分かるのは特異クラスはクラスであることがわかるんです。
そしてインスタンスは1個しか持てないんです。
そして、1番大事なことは、**特異クラスはオブジェクトの特異メソッドが存在する場所**なんです。
ここを理解するにはRubyのオブジェクトモデルについて深く理解していかないといけないので見ていきましょう。

### メソッド探索
以下のコードをもとにメソッド探索をしていきましょう
```
class C
  def a_method
    'a_methodが出力されます'
  end
end
    
class C
  class << self
    def singleton_a_method
      'singleton_a_methodが出力されます'
    end
  end
end

class D < C; end
obj = D.new
obj.a_method

class << obj
  def a_singleton_method
    'a_singleton_methodが出力されます'
  end
end


obj.singleton_class.superclass #=> D

C.singleton_class
D.singleton_class
D.singleton_class.superclass
C.singleton_class.superclass
```

図示すると以下のような図になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2485775/d203760b-0bf5-2c76-3539-e2ecfa6eb1be.png)
この図から分かる通り、特異クラスのスーパークラスがスーパークラスの特異クラスなんです。
Rubyという言語において、スーパークラスや特異クラスがなぜこのような配置になっているのでしょうか？
それは、このような配置することで子クラスからクラスメソッドを呼び出せるからなんです。

この本において、この章が1番難しいとおもいます。
抽象的な話が多いので個人的にはスゴイむずかしく感じました。

残りの数ページは次回にしようとおもいます

以上です。何か間違いがございましたら、ご教示いただけますと幸いです。

【参考資料】

https://www.amazon.co.jp/%E3%83%A1%E3%82%BF%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0Ruby-%E7%AC%AC2%E7%89%88-Paolo-Perrotta/dp/4873117437
[FastAPI]複数ファイルをrequests.post()で渡す


外部のスクリプトファイルからFastAPIにrequests.post()で複数ファイルを渡す際につまづいたのでメモをここに残します。

```python:uploadFile.py
from typing import List

from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse

app = FastAPI()

@app.post("/uploadfiles/")
async def create_upload_files(params:dict,fileList: List[UploadFile]):
    return hogehoge(params, files)
```



requests.post()で複数ファイルを渡したい場合は下記のようにすることで出来ました。
※dictのキーがエンドポイントのfileList(今回はこの名前にしました)という名前と一致していないとFastAPI側で受け取ることが出来ないので注意が必要です。
{エンドポイントの変数名：タプル(ファイル名、バイナリファイル)}
```python:request.py
import requests
 
url = 'http//hogehogehogehoge:8000//uploadfiles/'
params = {
'キー1':'値1',
'キー2':'値2'
}

fileName1 = 'hoge1.xlsx'
fileName2 = 'hoge2.xlsx'

fileDataBinary1 = open(fileName1, 'rb').read()
fileDataBinary2 = open(fileName2,'rb').read()
#ここはリスト[]でも辞書{}でもどちらでも良いようです。
#FastAPIで受け取った際にfileListにちゃんと格納してくれました
fileList = {
'fileList': (fileName1, fileDataBinary1),
'fileList': (fileName2, fileDataBinary2)
}

#このパターンで書くとファイル渡せますが、ファイル名がfileListとなってしまい、拡張子も消えてしまいます
#fileList = {
#'fileList':fileDataBinary1
#}


res = requests.post(url, data= params, files= fileList)

```

```python:uploadFile.py
@app.post("/uploadfiles/")
async def create_upload_files(params:dict,fileList: List[UploadFile]):
    # print()でファイル名がしっかり渡せてることが確認できます
    print(file.filename for file in files)
```
** （Elixir）

**名にし負はば逢坂山のさねかづら人に知られで来るよしもがな**

Advent Calendar 2022 74日目[^1]の記事です。
I'm looking forward to 12/25,2022 :santa::santa_tone1::santa_tone2::santa_tone3::santa_tone4::santa_tone5:
私の[Advent Calendar 2022 一覧](https://docs.google.com/spreadsheets/d/1HQvFjagQLRPjOYAjDVzWp9S4b8dKixxvvaz_TtbZWto/edit#gid=1723448955)。

[^1]: @kaizen_nagoya さんの「[「@e99h2121 アドベントカレンダーではありますまいか Advent Calendar 2020」の改訂版ではありますまいか Advent Calendar 2022 １日目　Most Breakthrough Generator](https://qiita.com/kaizen_nagoya/items/49ebebee3a0377f3b59b)」から着想を得て、模倣いたしました。 

---



# はじめに

[Elixir](https://elixir-lang.org/)を楽しんでいますか:bangbang::bangbang::bangbang:

`**`がありました。
[Elixir](https://elixir-lang.org/) 1.13 or laterです。
1.13から追加されています。

`**`の意味はもちろんべき乗の計算です。
Power operatorです。

`base ** e`は、

$base^e$

です。

# 実行

```elixir
iex> 2 ** 3
8

iex> 2 ** 0
1
```

# 内部実装

https://github.com/elixir-lang/elixir/blob/v1.13.3/lib/elixir/lib/kernel.ex#L4108-L4151

`base`、`exponent`ともに整数である場合の実装を抜き出してみます。


```elixir:lib/elixir/lib/kernel.ex
  def base ** exponent when is_integer(base) and is_integer(exponent) and exponent >= 0 do
    integer_pow(base, 1, exponent)
  end

  # https://en.wikipedia.org/wiki/Exponentiation_by_squaring
  defp integer_pow(_, _, 0),
    do: 1

  defp integer_pow(b, a, 1),
    do: b * a

  defp integer_pow(b, a, e) when :erlang.band(e, 1) == 0,
    do: integer_pow(b * b, a, :erlang.bsr(e, 1))

  defp integer_pow(b, a, e),
    do: integer_pow(b * b, a * b, :erlang.bsr(e, 1))
```

https://en.wikipedia.org/wiki/Exponentiation_by_squaring

詳しい説明は省きます。

- [Exponentiation by squaring](https://en.wikipedia.org/wiki/Exponentiation_by_squaring)に従っているようです
- ビット演算を巧みにつかって計算量を減らしています
- `:erlang.band`は、[Bitwise AND](https://www.erlang.org/doc/reference_manual/expressions.html#arithmetic-expressions) です
- `:erlang.bsr`は、[Bitshift right](https://www.erlang.org/doc/reference_manual/expressions.html#arithmetic-expressions)です


$2^3$と$2^2$を紙に書いてどう実行されるのかを書き出してみると、なんとなくみえてくるとおもいます。

ちなみに、`2 ** 4.0`といったように整数以外を含んで使用した場合は、 [:math.pow/2](https://www.erlang.org/doc/man/math.html#pow-2) が呼び出されています。

---

# Wrapping up :lgtm::lgtm::lgtm::lgtm::lgtm:

この記事は、[Elixir](https://elixir-lang.org/) 1.13で追加された`**`（Power operator）について説明をしました。


Enjoy [Elixir](https://elixir-lang.org/):bangbang::bangbang::bangbang:
<font color="purple">$\huge{Enjoy\ Elixir🚀}$</font>


以上です。





---

I organize [autoracex](https://autoracex.connpass.com/).
And I take part in [NervesJP](https://nerves-jp.connpass.com/), [fukuoka.ex](https://fukuokaex.connpass.com/), [EDI](https://fukuokaex.connpass.com/), [tokyo.ex](https://beam-lang.connpass.com/), [Pelemay](https://pelemay.connpass.com/).
I hope someday you'll join us.

[We Are The Alchemists, my friends!](https://www.youtube.com/watch?v=04854XqcfCY)
[Flutter] デバイスに保存したファイルの存在確認の方法

## はじめに
`path_provider`などを使ってデバイスに保存したファイルが存在するかのチェック処理が必要になったので調べてみました。

## 実装

```dart 
import 'dart:io';

String path = '存在を確認したいファイルのパス'; 

if (File(path).existsSync()) {
  print('存在しています');
} else {
  print('存在していません');
}
```

## 説明
ファイルの存在チェックは`File`クラスの`existsSync()`メソッドで行うことができます。

## 補足
非同期で行いたい場合は`exists()`を使用するといいみたいです。(参考参照)
また、ディレクトリの存在チェックは`Directory`クラスの同じメソッドで行うことができるみたいです。(参考参照)

## 参考
https://stackoverflow.com/questions/52614610/check-if-a-file-exists-before-loading-it
Laravel API 何故かコントローラーの関数を用いて値を返すと405エラーを返す

# 概要

- LaravelをAPIサーバーとして用いてとあるルーティングにリクエストを送ったが405を返す問題が発生してちょっと詰まったので原因をまとめる。

# 問題発生までの経緯

- 下記の様にルーティング、コントローラーに記載を行った。
    - ルーティング

        ```web.php
        // thunder client動作確認用
        Route::get('/get_test', function(){
            return 'ROOT GET OK';
        });
        Route::post('/post_test', function(){
            return 'ROOT POST OK';
        });
        
        Route::post('/send', [LineMessageController::class, 'send']);
        ```

    - コントローラー

        ```TestController.php
        public function send(GetSendRequest $request)
        {
            return 'XXX';
        }
        ```

- DockerでPHPコンテナ内にApacheを立てている。
- ローカルの8000ポートをコンテナ内の80ポートにフォワーディングしている。
- `app/Http/Middleware/VerifyCsrfToken.php`の`$except`の配列に`post_test`と`send`を追加した。
- VScodeのThunder Clientを用いてそれぞれ下記のURLにリクエストを投げた。
    - GETリクエスト: http://localhost:8000/get_test
    - POSTリクエスト: http://localhost:8000/post_test
    - POSTリクエスト: http://localhost:8000/send

# 問題発生

- `http://localhost:8000/send`にリクエストを投げたときだけ`405 Method Not Allowed`が帰ってきた。

    ```
    Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException: The POST method is not supported for this route. Supported methods: GET, HEAD. in file /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/AbstractRouteCollection.php on line 118
    ```

# 問題解消までの経緯

1. Thunder Clientに登録しているリクエストのURLに誤りが無いことを確認 → 問題なさそう。
1. ルーティングファイルで当該のルート情報がpostになっている事を確認 → 問題なさそう。（なぜ「Supported methods: GET」と言われているのか分からない。）
1. 「Supported methods: GET」と言われているので当該のルート情報のgetで受け付ける様に修正して実行してみた。

    ```web.php
    Route::get('/send', [LineMessageController::class, 'send']);
    ```

1. 下記のエラー`405 Method Not Allowed`が帰ってきた。

    ```
    Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException: The GET method is not supported for this route. Supported methods: POST. in file /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/AbstractRouteCollection.php on line 118
    ```

1. 「Supported methods: POST.」と帰ってきてプチパニック（「Supported methods: GET.」って言われたからGETにしてリクエスト送ったのに「Supported methods: POST.」ってなんでや）
1. 下記の知見を発見したが、自分のリクエストを確認して問題無かった。
    - [https://tetrablog.net/laravel-post-405-error](https://tetrablog.net/laravel-post-405-error)
1. 下記の様にルーティングに記載して、コントローラーを呼び出しているルーティングはコメントアウトした。

    ```
    Route::post('/send', function(){
        return 'ROOT SEND POST OK';
    });
    ```

1. ↑これだと「ROOT SEND POST OK」の文字が帰ってくる。どうやらコントローラーのメソッドに問題がありそう。
1. もう一度当該のコントローラーの当該の関数をよく見てみる。

    ```TestController.php
    public function send(GetSendRequest $request)
    {
        return 'XXX';
    }
    ```

1. よく見たら独自に作成したリクエストクラスであるGetSendRequestを通してデータが当該関数に入ってきている。
1. GetSendRequestを見たところ、Postしていない値が必須バリデーションされていた。下記の様に修正したら「XXX」の文字が返された。

    ```TestController.php
    use Illuminate\Http\Request;    

    public function send(Request $request)
    {
        return 'XXX';
    }
    ```

# 原因

1. 意図しないバリデーションが設定されていた。
1. リクエストのテストでは何も値をPostしていなかったため、バリデーションエラーが発生 → エラー画面へのリダイレクトが行われたが、リダイレクト先のルーティングがGETで定義されていたため「Supported methods: GET,」のエラーが出たものと思われる。
JavaScriptの超きほん　〜モジュールってなに？〜

# モジュールとは
モジュールとは、肥大化したコードを`機能ごとに分割して管理する仕組み`です。

モジュール化することで、メンテナンスが容易になり、再利用もしやすくなります。

# モジュールシステムの種類
`ESM`と`CJS`の２種類があります。

- ESM: ECMAScript Modules
- CJS: CommonJS

## ECMAScript Modules（EMS）
`ECMAScript`の仕様にもとづくモジュールシステムです。
主にブラウザ上で使用します。

ファイルの読み込みは`import`、
ファイルの書き出しは`export`で記述します。

モジュールファイルの拡張子は`.js`ですが、
ESMとわかるよう明示的に`.mjs`とすることもできます。

## CommonJS（CJS）

`Node.js`上に組み込まれているモジュールシステムです。

ファイルの読み込みは`require`、
ファイルの書き出しは`exports`で記述します。

モジュールファイルの拡張子は`.js`ですが、
CJSとわかるよう明示的に`.cjs`とすることもできます。

# ESMの例
次からはESMの記述方法を紹介します。
ESMで`export`したモジュールは、`import`でしか読み込めません。

（`require`はつかえない）

## 名前付きエクスポート
`export`するモジュールを用意します。
```js:module.js
export let sampleVal = 123;

export function sampleFn() {
  console.log('Hello World!');
}
```

変数に名前をつけて`export`したら、
{ }をつかって`import`します。
```js:main.js
import { sampleVal, SampleFn } from './module.js';

console.log(sampleVal); // => 123
sampleFn(); // => Hello World!
```

### 名前を変更して使用する場合
`import`の際、変数名を`as`で変更できます。
```js:main.js
import { sampleVal as val, SampleFn as fn } from './module.js';

console.log(val); // => 123
fn(); // => Hello World!
```

### 変数を一括で読み込む場合
変数を一括で`import`する際は、`*`をつかいます。
```js:main.js
import * as module from './module.js';

console.log(module.sampleVal); // => 123
module.sampleFn(); // => Hello World!
```

## デフォルトエクスポート
モジュールごとに１つまで、変数名なしで書き出しができます。
`export default` をつかいます。
```js:module.js
export default 'default text';
```

デフォルトエクスポートの場合は、{}は不要です。
また、`as`なしで変数名を設定できます。
```js:main.js
import defaultText from './module.js';

console.log(defaultText); // => default text
```

# 補足
さいごまでお読みいただき、ありがとうございます！

この記事はプログラミング初心者であるわたしが、毎日の学習ログとして書きました。
ご質問やご意見、間違いのご指摘などがあれば、気軽にコメントください。

また、平日にもくもく作業したり質問しあえる仲間も募集しています。
ご興味がある方は[Twitter](https://twitter.com/yutaka_pg)などでご連絡くださいー！

これからもどうぞよろしくお願いします:rabbit:
クラウドに関連資格取得・勉強に効果的な学習サイト（acloudguru.com）

# [A Cloud Guru](https://acloudguru.com/)
僕だと下記の理由でこれは一番いい学習サイトだと思います。
- ビデオの講座（英語のスクリプトあり）、長さは数分から２０分以内
- 練習できる環境が用意された（最高）
![sandbox.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/dd83f6cc-bf93-e790-f58b-f57c8a6edc43.png)
- 練習（模擬）問題がある
- Learning pathに従って複数の認証を取得可能。
- 料金プラン（年間：４６８ドル、月度：４７ドル）
![pricing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/5c1886eb-fe15-4204-95b6-51f384dff222.png)
- コンテンツの難易度は下記の４種類です。
Novice（初心者）
Apprentice（見習い）
Practitioner（専門者）
Guru（達人）
  <img width="400" alt="learn_path_step1.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/b4237c1f-b295-a899-b27a-f0245e04b13f.jpeg">
- amazonのAWS,googleのGCP,microsoftのAzure大手三社の資格認定内容を対応している
且つLinuxに関する内容も対応している
☆aws learning path
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/6957a1f9-6060-1032-9587-d4c7a5a17ce8.png)
☆Azure learning path
![azure_path.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/7240d007-f5fa-ed8c-baec-c085c2016211.jpeg)
☆GCP learning path
![gcp_path.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/70dde092-ceae-2c25-4930-afa757be5133.jpeg)
☆Linux learning path
![linux_path.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/db26bed1-094d-78e3-a842-78cd3e02a725.jpeg)

料金はちょっと高いですが良質な内容なので毎日勉強してお金を無駄せずに資格を取れるように頑張ります。
WSL2環境構築からVirtualBox, Vagrantセットアップまで

## Virtualization Technology有効化
##### システムメニューより、`タスクマネージャー`を開く（Windowsキー + x）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1742664/625ead67-286e-4718-acf5-a6f46e100a47.png)

##### 有効化されているか確認する。  
パフォーマンスタブの`仮想化`が`有効`であること
![タスク マネージャー 2021-08-25 23.05.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1742664/3c5ae852-d0df-cbaa-de60-b6ca7c9af0b2.png)

有効化されていない場合、BIOSの設定を変更する

## WSL有効化
##### システムメニューより、PowerShellを管理者権限で起動（Windowsキー + x）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1742664/c02ff724-8226-8289-7023-47a705d84e48.png)

##### Linux用Windowsサブシステム、仮想マシンプラットフォーム有効化

```powershell
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform
```

完了後、再起動

Linux用Windowsサブシステム、仮想マシンプラットフォームのチェックがONになっている。  
ファイル名を指定して実行に`OptionalFeatures.exe`を入力して、Windowsの機能の有効化または無効化画面を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1742664/58a196b5-de94-788b-4565-70dfcf977aac.png)

### Linux Kernel Update Packageインストール
##### アップデートプログラムをダウンロード  

1. [ダウンロード](https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi)

2. ファイル（wsl_update_x64.msi）を実行し、インストール

### WSLのバージョンを2に変更
##### システムメニューより、PowerShellを起動（Windowsキー + x）
```powershell
wsl --set-default-version 2
```

## Ubuntu20.04 LTSインストール  
Microsoft Storeより、`Ubuntu20.04 LTS`をインストールする。

##### Microsoft Storeを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1742664/40bd6e99-f9a0-5c39-d94a-80387de777e7.png)

##### Ubuntuを検索し、`Ubuntu 20.04 LTS`を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1742664/26ed45c1-5da2-0679-3321-720658c92b18.png)

##### インストール 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1742664/a0ac353c-eb4f-1caa-e5fb-0f68e157973d.png)

##### Ubuntu 起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1742664/462d1b1b-fe1e-7902-c00e-0c92e0cb43dc.png)

##### ユーザー、パスワードを設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1742664/10980441-1267-f7f2-e71c-c30bbb6f2712.png)

##### データの取得先を日本に変更

```
sudo sed -i -e 's%http://.*.ubuntu.com%http://ftp.jaist.ac.jp/pub/Linux%g' /etc/apt/sources.list
```

##### パッケージアップデート

```
sudo apt update && sudo apt upgrade -y
```

##### DNS変更

`/etc/systemd/resolved.conf`に追記

```
sudo sed -i -e 's/#DNS=/DNS=8.8.8.8/' /etc/systemd/resolved.conf
```

##### sudoのパスワード入力なし

```
sudo visudo
```

```
<自分のユーザ名> ALL=NOPASSWD: ALL
```

## Virautl Box Install

```
sudo apt-get install virtualbox
```

`Do you want to continue? [Y/n]` と聞かれるので `Y`を入力する。

## Vagrant Install

```
sudo apt install vagrant
```

`Do you want to continue? [Y/n]` と聞かれるので `Y`を入力する。
Pythonのデコレータのイメージ

関数の上についてる@マークもといデコレータについて
細かい事は置いといて、デコレータってどんなことしてるの？という記事です。

## 実例
内容はひとつの関数で書けというものですが、とりあえず実例を出します。
### コード
```decorater.py
#デコレータを定義
def greet(func):
    def inner(*args,**kwargs):
        print("こんにちは。")#1
        result = func(*args,**kwargs)#2
        print("よろしくお願いします。")#3
        return result#4
    return inner

#使い方
@greet
def myName(name):
    print(f"私は{name}です。")
    return "挨拶 終"
    
print(myName("ねこでべろん"))
```
### 結果
```
こんにちは。
私はねこでべろんです。
よろしくお願いします。
挨拶 終
```
### 解説
`myName()`の上に`@greet`を付ける事で`myName()`を`greet()`でデコレートしました。
#1 デコレータが「こんにちは。」と出力
#2 `myName()`を実行。名前を出力し返り値をresultに格納
#3 デコレータが「よろしくお願いします。」と出力
#4 返り値を返す（`print`で出力される）
このような流れで実行されます。

## どんなイメージなのか
少しコードを変えます

### コード
```decorater.py
#デコレータを定義
def greet(func):
    def inner(*args,**kwargs):
        print("こんにちは。")
        result = func(*args,**kwargs)#関数本体
        print("よろしくお願いします")
        return result
    return inner 

#@greet
def myName(name):
    print(f"私は{name}です。")
    return "挨拶 終"
    
#print(myName("ねこでべろん"))
print(greet(myName)("ねこでべろん"))
```
### 結果
```
こんにちは。
私はねこでべろんです。
よろしくお願いします。
挨拶 終
```
### 解説
さっきとほとんど変わりません。`@greet`をやめて、
`myName("ねこでべろん")`を`greet(myName)("ねこでべろん")`に変えただけです。そしてこれこそが**デコレータの本質**です。
`greet(myName)`によって`func`に`myName`が代入された`inner`という関数が返ってきます。よって`greet(myName)("ねこでべろん")`は`inner("ねこでべろん")`を実行している事になります。
その結果inner内の処理が順に実行されていき`func`では`myName`が代入されているのでその処理が行われます。
つまり、`@greet`はこの一連の流れを簡単に記述するために使われているということです。

## ところで`*args`、`**kwargs`って何者
メインではないので少しだけ紹介程度に。
`*args`、`**kwargs`は可変長引数と呼ばれるものです。
`*args`が普通の引数、`**kwargs`が引数名を指定した引数をそれぞれ格納します。
`args`、`kwargs`の文字であることに意味はありません。重要なのは`*`と`**`です。*args*は*arguments*、*kwargs*は*keyword arguments*の略語で慣例的に使われています。
ちょっとした実例
```python
def task(day,task,limit):
    print(f"{day}は{task}を{limit}までにする")  
    
task("土曜日","買い物",limit="15時")
```
`"土曜日"`と`"買い物"`は`*args`、`limit="15時"`は`**kwargs`に格納されます。

## 一般化したデコレータ
一応貼っときます
```python
def decorater(func):
    def inner(*args,**kwargs):
        toDo()
        result = func(*args,**kwargs)
        toDo()
        return result
    return inner 
```
## 最後に
私的にわかりやすい解説を作りました。
ミスなどあればお知らせください。
Qiitaの投稿から、QiitaユーザーのAIとAR/VRへの関心を比較してみた！

### はじめに

Qiita初投稿です！先週からプログラミングの学習を始めた初心者ですが、暖かい目で見守って下さい！小さなアウトプットを積み重ねることを目標に発信しています。皆さんの学習に少しでもお役立ていただければ幸いです。

### 目的
+ **QiitaAPI**を使い、いま興味のある**AIとVR/ARの投稿**を比較して、Qiitaユーザーに何が人気か理解したいと思います。

+ それぞれの投稿の中身を見ることで、**人気のトレンド**に触れて、AI, VR, ARの理解を深めたいと思います。


【疑問1】 AIは、VR/ARより注目されているのか？
【疑問2】 どんな投稿がトレンドなのか？

これらの疑問を、Qiitaの投稿記事から考察したいと思います。

### 環境
Visual Studio Code v1.65.0

### 方法
+ /api/v2/itemsを使ってAI/ VR/ ARが本文に含まれている記事のタイトルを抽出します。
+ 抽出された結果をエクセルに取り込み、投稿数と記事の内容を考察します。

### ソースコード
+ 今回使用したQiitaAPIです。
  GET /api/v2/items

```ruby
'use strict';

// axiosモジュールを読み込む
const axios = require('axios');

// main() という関数をここで定義しておきます。
// 定義するだけでは、中身はまだ実行されません。
async function main() {
    let url = "https://qiita.com/api/v2/items?query=" + encodeURIComponent("AI")
    // Rakuten APIに「HTTP GET」という形式で「リクエスト」を送り、「レスポンス」を受け取ります。
    let response = await axios.get(url);
    let data_list = response.data;

    data_list.forEach(row => {
        //console.log(row.title)
        if ( row.body.indexOf('AI') != -1) {
             console.log(row.title);
    }
    });


}

// 上で定義した関数をここで実行します。
main();
```
同様に検索したいキーワードに合わせ、2箇所をARやVRに変更します。
(↓はARに変更した場合です）

```ruby
  let url = "https://qiita.com/api/v2/items?query=" + encodeURIComponent("AR")
```
```ruby
  data_list.forEach(row => {
        //console.log(row.title)
        if ( row.body.indexOf('AR') != -1) {
```
その他以下解説をご参照ください。
+  console.log()」を使って任意の文字列を抽出します。今回の例ではタイトルを抽出しました。
+  if ( row.body.indexOf('キーワード') != -1)= if文を使って、結果が-1でなければ、キーワードが検索にヒットしていることを表現します。つまり返り値が-1でなければ検索にヒットしていると読み替え、条件文として使用します。
+ items?query=”検索文字列”を使うことで対象の文字列が含まれている文字列を検索することができます。
+ URLエンコードに対象文字列を変換するために、encodeURIComponent()関数で「AR」をURLエンコード変換しています (URLエンコードの基本を理解したい方は、以下の「URLエンコード」をご参照ください）。

[URLエンコード](https://qiita.com/taro0219/items/c69a46498dad31ba9f66)


### 結果と考察 
抽出した結果をグラフにまとめました。

予想通り、AIに関連する投稿が多いことが判明しました。一方でVRに関わる投稿がARと比較して少ないのは、少し意外な感じがしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2554652/1569a0a3-9d06-7fc3-8dc1-261565d813e8.png)


次に、投稿数が多かったAIと、ARの内容を分析しました。
+ AI、ARともに投稿内容は多岐にわたり、知らない言葉が沢山あります（涙）
+ ARの投稿内容をみると、**SwiftUI**や**ARKit**が人気投稿になってます


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2554652/969c0788-7424-4585-6222-5d1cdb6cac37.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2554652/dbb45725-fa46-0e3b-23bc-2949e12c1247.png)

【参考】
*「SwiftUI」とは、iPhoneなどAppleプラットフォームのユーザーインターフェースを、従来よりも簡単に構築できるユーザーインターフェースのフレームワークです。オススメのアプリが以下リンクよりご覧いただけます。*
[SwiftUIおすすめライブラリ](https://qiita.com/shira-shun/items/492dcdd79ed9dde09bf6)

*「ARKit」は、Apple社が開発したiOSに対応したARフレームワークです。 ARKitを使って開発したアプリは、特別なデバイスを準備する必要がなく、iPadやiPhoneなどのiOS端末のカメラを使って動作させることができます。*





### 結論
+ AIに関する記事は、ARとVRと比較して、Qiitaユーザーの投稿数が多く、投稿内容は多種多様なことが分かりました。
+ ARの投稿数はVRを上回り、人気の投稿は「SwiftUI」と「ARKit」となっていました。

### おわりに
特定のワードが出てくる記事が読みたい！そんなときに、今回のアプローチは大変役に立つことが分かりました。自身が興味のある、AI/VR/ ARについて調べるプロセスは楽しく、更に色々な事例に触れていきたいという意欲が湧きました。また、興味のあるマッチングビジネス、決済プロセスなどの情報収集にも、今後同様の方法を活用していきたいと思いました。

### 参考にした記事
[MCUの映画公開とQiitaユーザーの動向の関係について分析してみた！](https://qiita.com/kkyosuke17/items/a941fe685edf1b739fbe)
smartyの値を確認する方法（var_dumpが使える）

- smartyの中身を確認するコマンド。
- PHPでvar_dumpを使うことがあると思うが、smartyでもvar_dumpを使うことができる。

## 使い方
```smarty:var_dunp
{{$hoge|@var_dump}}
```
＄hogeの値を確認することができる。
（　{} が1個か2個は自分が使用している方で書く。）
Xcodeのインストールでクルクルから先に進まない件

ひょんなことからxcodeをインストールすることになったのですが、![スクリーンショット 2022-03-15 20.34.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186346/d67658dc-6f04-eed3-803c-f84b1143bd65.png)

このクルクルから一向に動きがなくてどうなっとんねんって感じな人生でした。


## 結論：単純に時間がかかってるだけです。

試しに、

```
tail -f /var/log/install.log
```
こちらを叩いてみるとわかるのですが、ちゃんとログがでてるはず。
これを見ながら安心して、コーヒー飲んだり、ウマ娘やったりしてるといいです。


僕はだいたい30分くらいのクルクルで終わりました。
DL自体にも30分くらいかかった気がするのでxcodeのインストールにはだいたい1時間は見込んでおきましょう。

インストールが終わったら、
ctrl + c
でtailから抜けましょう。


そんな感じです。
GitHub Actions でメタデータ (actions.yml) 側のスクリプトを実行する方法

# TL;DR
`${{ github.action_path }}` を使う。



# メタデータとワークフロー
GitHub Actions には、メタデータとワークフローの 2 種類が存在する。ファイル名やディレクトリ構造、使用用途についての違いは以下のとおり。

| 名称 | ファイル名・ディレクトリ構造 | 使用用途 | 備考 |
| --- | --- | --- | --- |
| メタデータ | `action.yml` | 外部のリポジトリで特定の処理を実行させたり、他のユーザに使ってもらったり、[マーケットプレイス](https://github.com/marketplace?type=actions) に公開したりしたい場合 ||
| ワークフロー | `.github/workflow/***.yml` | そのリポジトリ内のみで任意の処理を実行したい場合 | ファイル名 (`***` の部分) は任意 |

ワークフローはそのリポジトリで動作するものなので、任意のコマンドやスクリプトを実行させたい場合はそのままパスを指定すれば良い。

たとえば、リポジトリのルートディレクトリに `main.rb` というファイルがあり、それを実行したい場合は、単に `ruby main.rb` のように記述すれば良い。



# 問題点
しかし、メタデータでそのように記述してしまうと、そのメタデータを使うリポジトリ側、つまりワークフロー側のパスを参照してしまう。

たとえば、リポジトリ A (`username/repo-a`) には、以下のようなメタデータ (`action.yml`) が置かれているとする[^1]。

[^1]: 他にも必要な記述はあるが、説明の都合上、省略している。

```yaml:action.yml
runs:
  using: "composite"
  step:
    - run: ruby main.rb
      shell: sh
```

上記のメタデータをリポジトリ B で使いたいとする[^1]。ファイル名は適当に `ruby.yml` としている。

```yaml:.github/workflow/ruby.yml
jobs:
  ruby:
    runs-on: ubuntu-latest
    steps:
      - uses: username/repo-a
```

この状態で、リポジトリ B でワークフローを実行すると、`ruby main.rb` が実行されるのだが、ここでいう `main.rb` はリポジトリ B の `main.rb` を参照してしまう[^2]。

[^2]: その他の例として、メタデータ (リポジトリ A) 側の `Gemfile` に記載されているライブラリをインストールしたくて `bundle install` を実行すると、ワークフロー (リポジトリ B) 側の `Gemfile` を使ってインストールしようとしてしまう (リポジトリ B 側に `Gemfile` がない場合はコマンドが失敗する) 。

ワークフロー側 (リポジトリ B) ではなく、メタデータ側 (リポジトリ A) にある `main.rb` を実行させたい場合はどうすれば良いだろうか。



# 解決策
`${{ github.action_path }}` を使うことでメタデータ側のパスを指定することができる。メタデータを以下のように書き換える。

```diff:action.yml
 runs:
   using: "composite"
   step:
-    - run: ruby main.rb
+    - run: ruby $GITHUB_ACTION_PATH/main.rb
       shell: sh
+      env:
+        GITHUB_ACTION_PATH: ${{ github.action_path }}
```

すると、`main.rb` はメタデータ (リポジトリ A) のほうを参照してくれるようになる。



# 参考
* [changed-files/action.yml at 9125e4d5da611929abd53b039acc130bc6d19a01 · tj-actions/changed-files](https://github.com/tj-actions/changed-files/blob/9125e4d5da611929abd53b039acc130bc6d19a01/action.yml#L131-L148)
* [github-to-qiita/action.yml at 7cb850a7bbf9a3b23eb7896c0e1e8c5c50d798c6 · noraworld/github-to-qiita](https://github.com/noraworld/github-to-qiita/blob/7cb850a7bbf9a3b23eb7896c0e1e8c5c50d798c6/action.yml#L60-L69)
* [Workflow syntax for GitHub Actions](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions)
* [Metadata syntax for GitHub Actions](https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions)
エンジニアとして、ブロックチェーンについて知っておいた方が良いこと

2022年3月15日にgreedy'sイベントで話した内容です。

スライド
https://docs.google.com/presentation/d/1j7DTHtb2B1KnvkAdkdif5tbIZ6jBoiuZJtY3oox8R0c/edit?usp=sharing

## この話を聞くメリット
1. このようなわからないことがなくなる

- 誰のどういう課題を解決しているのか、わからない。
- 話題になっている理由がわからない
- それブロックチェーンでやる必要はない。

2.時代に取り残されて、老害にならない
今後このweb3が高い確率で世の中で使われるようになっていく。
その理由をまず知る必要がある。
理由を知った上で参入する必要があるかどうかするのは、本人次第ですが、
知らずにいて、web3時代がきて、取り残されないようになれます。

3.間違った情報に騙されなくなる
ニュースや本やインフルエンサーの説明で間違った表現が多いです。
今日の話を聞けば間違った解釈して騙されることがなくなります。

## ブロックチェーンの歴史
  - ビットコインの誕生 2009
  - イーサリアムの誕生 2016
  - ICO詐欺の乱立 2016
  - コインチェックのハッキング事件 2016
  - 各国の仮想通貨規制 2017
  - DeFiリリース 2019
  - NFTブーム到来 2021

歴史を学べば、今後も伸びていくと予想できる

今後
NFTゲーム
CBDC(政府によるステーブルコイン)の発行
xxペイなどの電子決済がCBDCに置き換わる
サブスクサービスのNFT化される
分散型のSNS
クラウドファンディングの手段として仮想通貨を使うことが出てくる
メタバース

## インターネットの歴史
TCP/IPについて記述された最初の文書が公開される - 1973
HTMLの概念が初めて提案される - 1989
「Windows 95」が発売を開始　- 1995
Amazonが創業 -1994
Googleが創業 - 1998
Facebookが創業 - 2004
「iPhone」が発売を開始 - 2008
Google Apple Facebook Amazonがグローバル巨大企業になる - 2019
インターネット利用率が80%を超える - 2020

## ブロックチェーン技術は何に使われているのか？
### 通貨
クレジットカード決済や他の電子決済と違って、オープンソースなので、バージョンアップによりシステムを改修する手間が発生するリスクがなかったり、
ブロックチェーンを使っているのでシステム障害が起きづらい、
送金手数料が少なかったりなどのメリットがあります。

#### ステーブルコイン
USDT, USDC, JPYCなど

JPYC
https://jpyc.jp/

#### ビットコイン
エルサドバドルでは、国が発行している通貨が、bitcoinより信用力がないので、
2021年ごろからbitcoinを法廷通貨にしている。

### 資産
#### ビットコイン

ビットコインと他の仮想通貨の違うところは、完全に分散化されているということです。
サトシナカモトという方が作りましたが、その方のウォレットに送受信はなく、すでになくなっているのではないかと言われています。

他の仮想通貨は、ブロックチェーン上で取引しているとはいえ、運営している団体がハードフォーク(ブロックチェーンの上書き)をしようすればできます。
実際にイーサリアムは、2016年にThe Daoがハッキングされ、364万ETHが流出した時に、イーサリアム財団がハードフォークしました。
それに反発したコミュニティのメンバーは、イーサリアムクラシックを作り、現在イーサリアムとイーサリアムクラシックの二つがあります。

### NFT
- アート
- チケット
- サブスク会員証明書
- ゲームのアイテム

### Dapps
#### DeFi
分散化された仮想通貨の交換所
仮想通貨同士を交換するときに使えます。
Defiに仮想通貨を預けて、流動性を提供することで、収益を得ることもできます。

サービス例
Uniswap
https://uniswap.org/

Acala
https://acala.network/

#### NFTマーケットプレイス
サービス例
Opensea
https://opensea.io/

Metaplex
https://www.metaplex.com/

### トレーサビリティ(流通の追跡可能性)
流通の追跡可能性を商品に付けることにより、
盗難や偽物などを防止することができます。
漁業や農業、ブランド品を扱う企業などが使い始めています。

### 分散型ホスティングサーバー
#### IPFS, ICP
IPFS, ICPなどは仮想通貨を支払うことによって、ホスティングサーバーとして使うことができます。
自分のPCを貸すことによって、収益を得ることもできます。
分散化されたfirebase Hostingのようなものです。

IPFS
https://ipfs.io/

Definity
https://dfinity.org/

## それブロックチェーンでやる必要があるの？
ここまで聞くと「それブロックチェーンでやる必要があるの？」と技術の知識がある方なら、言いたくなると思います。
ちなみに私も、少し前までは「それブロックチェーンでやる必要ない」と思ってました。

ブロックチェーンを使うことにより下記のメリットがあります。

- 分散化されることに、透明性、民主制を維持
- ブロックチェーンノードが大量にあることにより、単一障害点をなくせる
- オープンソースにすることにより、みんなが欲しいものが無料で作られて、無料で使える
- 仮想通貨を発行することにより、初期に収益化する必要がなくなる

## NFTに関するよくある説明の間違い
- アートがユニークであることを担保している

- 同じアートのNFTは発行できない

- 持つことによって、限定のデータにアクセスできる
「音楽NFTを買ったら音楽がフルで聴ける」「本NFTを買ったら、本が読める」などの機能はNFTにはなく、所有していることの証明しかできないので、NFTを買っても買わなくても取得できる情報は同じです。

- ブロックチェーンにアートの画像データが保存されている
ブロックチェーン上にはアートデータは保存されておらず、画像のURLのみがブロックチェーン上に保存しています。
ブロックチェーンは数秒おきに、世界中の数十〜数千のノードで情報を共有しているため、膨大なデータをブロックチェーンに保存しておくことはできません。
【UniTask】ボタンの入力待ちをする

タイトル通りのことがやりたかったので備忘録です。
UniTaskを使用した際のボタンの入力待ちをする方法です。

## UniTaskサンプルコード

```
[SerializeField] private Button _button;
    
private async UniTask Hoge()
{
    // UnityEventを変換
    var buttonEvent = _button.onClick.GetAsyncEventHandler(CancellationToken.None);

    // ボタンの入力待ち
    await buttonEvent.OnInvokeAsync();
        
    Debug.Log("Fuga");
}
```

### コルーチンを使用した場合

ちなみにコルーチンを使用する場合はこんな感じでしょうか。

```
[SerializeField] private Button _button;

private IEnumerator Hoge()
{
    var isOk = false;
        
    _button.onClick.AddListener(() => isOk = true);
        
    yield return new WaitUntil(() => isOk);
        
    Debug.Log("Fuga");
}
```


## キーボードの入力待ちをする場合

補足ですが、ちなみにキーボードの入力待ちをする場合はこちら。

``` 
private async UniTask Hoge()
{
    await UniTask.WaitUntil(() => Input.GetKeyDown(KeyCode.A));
        
    Debug.Log("Fuga");
}
```

こちらはUniTask使わずコルーチンでも同じようにできます。

``` 
private IEnumerator Hoge()
{
    yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.A));
        
    Debug.Log("Fuga");
}
```

以上、入力待ちあれこれでした。
git rebaseの個人的な理解

## rebase
### 概要
今いるbranchの根本を変えるコマンド

![git_rebase.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548975/cabe44f6-372b-4732-2466-74bceffab56b.jpeg)

### コマンド

```bash
$ git rebase develop
```

### rebaseの途中で止まったら

コンフリクトがあります。

`git status`で出てきた赤いプログラムを見に行って、変更箇所のどっちを残すか指定しましょう。

明らかにpythonとかそういうプログラムじゃないもの(`>>>なんちゃら`)みたいなもののが追加されているんで、それがコンフリクト起こしてるものです。

上の図の場合はdevに入っているほうが(`>>>なんちゃら`)になっていました。

それが直し終わったら`git rebase --continue`を打ってrebaseの続きを行いましょう。

終わると上の赤色のfeature/1みたいなブランチになります。
Automation 360のインタラクティブフォームを使ってみる

# はじめに
Automation 360のインタラクティブフォームを使ってみました。
今まで、自動実行バンザイのRPAなのになぜ応答待ちダイアログ使うのだ？！と食わず嫌いでした。
ここではAARIライセンスが不要なAARI for Desktopを使ってみます。
AARI自身の詳しい説明は省きます。
単にAutomation 360で応答待ち画面を使ってみるという話です。

#  概要
おおまかな手順です。
- フォームを作る
- フォームを表示するBotを作る
(a)フォーム変数を作る
(b)フォームの応答を待つトリガーループを作る
(c)ハンドルの中で何等かの処理をしてBreakでループを抜ける

ここの(a)で作っておいたフォームの名前が直接指定できるのかと勘違いし、少し悩みました。


#  何を作るか
画像を表示して、その内容を見てOKなら「承認」ボタンを押す、
という画面を作ってみます。
社内システムで大抵は自動処理できるけど領収書があった場合は部長の承認が必要、というケースを想定しています。

# フォームを作る
オートメーションのアイコンからフォームを作ります。「新規作成」から「フォーム」を選んでもOKです。
![form001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/7998a033-4baf-274c-c6d9-73a0b2af24f2.jpeg)

フォーム名は「form領収書承認」にします。
左側の要素から「画像」と「ボタン」を配置します。
![form002.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/371502e8-6845-46d3-c571-416d0658fa02.jpeg)

画像のパスに「c:\temp\領収書.png」
ボタンのテキストに「承認」と入れています。

# Botを作る
先ほど作成したフォームを表示し、「承認ボタン」を押されたら何等かの処理を行うBotを作成します。

・インタラクティブフォームから「表示」を追加
![formBot01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/32c70397-7260-85dd-d927-b04cbfddcfc2.jpeg)
どのフォームを表示するか指定するために「フォーム名」を変数で指定します。
変数は (x)+ を押すと作成できます。

ここで変数名はformVarにしています。
デフォルト値として「選択」から先に作ったフォーム「form領収書承認」を選択します。

![formBot02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/f133697b-c327-db2e-e375-3a331d7ea086.jpeg)

このままだとフォームを表示してすぐ閉じてしまいます。
表示したあと待ち状態になってボタンが押されたら処理が動くようにします。

・表示の後に「トリガーループ」を追加する。
![formBot03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/2537fb56-308b-6b18-beb8-a6d3a6256237.jpeg)

・すると、トリガーループとハンドルが作られるので「ハンドル」を選択し、トリガー条件を指定する。
![formBot04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/51f1d4ac-3e9e-6e82-c8ee-5d485884c941.jpeg)

・トリガー条件は「インタラクティブフォーム」を選択し、フォーム名と条件となる要素（ここではボタン）を選択します。またアクショントリガーとして「クリック時」を選択。
![formBot05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/74746371-e051-c543-24fc-505c80ea47c8.jpeg)

・ボタンが押されたときの処理として、「メッセージボックス」と「Break」を追加します。
![formBot06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/8d5d91ce-9e08-e197-1d3b-6252aec5bcdc.jpeg)


かなり手抜きですが、これで
画像を表示して、ボタンを押すと何等かの処理をするBotができました。


# 使い方としては
例えば、部長のPCをAttended Runnerにしておきます。そしてC:\tempフォルダの下に画像ファイルが置かれたら上のBotが起動するようなトリガー実行の設定をしておく。共用の実行マシンで処理をしているときに要承認のものがあれば、そのファイルを部長のPCにコピーする。
などが考えられそうです。

本当はプロセスを組んで、１つの枠組みで処理するのが本当なのでしょうが、お手軽なフォームの使い方として書いてみました。これだけならAARIランセンス不要ですし。

RPAは人がやってて大変だった単純処理を機械にやらせるという使い方が多かったと思いますが、インタラクティブフォームを使って簡単な対話プログラムを作るのも良いかも。ノーコード・ローコードツールとしてRPAを使う、という事で。

# 参考になるリンク

https://docs.automationanywhere.com/ja-JP/bundle/enterprise-v2019/page/enterprise-cloud/topics/aae-client/forms/using-interactive-forms.html
AA社公式のページ。



https://autodojo.hatenablog.com/entry/aari-scenario
AARIの入門として。まとめられていてわかりやすい
Unity Oculus Quest2でapkファイル容量にご注意


UnityからOculus Quest２へアプリを書き出すには、
Androidへビルド先を変更して、「Build and Run」すればよい。

そんな開発の途中に、あれれ？
実機書き出しができなくなった。

エラー文には以下のメッセージがあった。

```
CommandInvokationFailure: Unable to install APK to device. Please make sure the Android SDK is installed and is properly configured in the Editor. See the Console for more details.
````

さらにエラー文を読む。

```
Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed to collect certificates from /data/app/vmdl2008565484.tmp/base.apk using APK Signature Scheme v2: integer overflow]
]
````

調べると以下が怪しいということで、
こちらを参考に　https://www.create-forever.games/unity-android-copy-error/#INSTALL_FAILED_UPDATE_INCOMPATIBLE

すべて試してみるも、ビルド通らず。。。

- INSTALL_FAILED_UPDATE_INCOMPATIBLE
- JDKやSDKのバージョンが違う
- Android 容量不足
- adb.exe 多重起動


コピーできるapkファイルは、2GBで制限が入るとの記事を発見。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152481/41b56c81-722e-32dd-ae37-40ebca20655b.png)


Split　Application Binary にチェックを入れるとアプリケーションファイルを分割してくれるようでした。

こちらにチェックをしたら、ビルドが通りました。

開発中にデータ容量が大きくなってしまったようでした。
突然ビルドが通らなったら、ご用心ということでした。
DBeaver で MariaDB に mysqldump --no-data をする際の注意点と TIPS

# DBeaver で MariaDB に mysqldump --no-data をする際の注意点
ググっても同様な問題で悩んでいるような事例が見つからなかったので、
かなりニッチと思われるが、件名の内容で手間取ったので備忘録を残す。

## Database Task で mysqldump --no-data したら sequence が DDL に含まれない
Windows10 に DBeaver CE 22.0.0 をインストールし、docker の MariaDB 10.6 に使用していた。
DDL をまとめて作ろうと、Database Tasks に mysqldump --no-data な task を作り、 run してみたが、
吐き出された dump ファイルには create sequence が含まれない。

### 原因
以下記事を読むと、MariaDB の mysqldump に元々そういった不具合があったが、
10.3.26, 10.4.16, 10.5.7 で fixed となったらしい。
[jira.mariadb.org: [MDEV-21786]mysqldump will forget sequence definition details on --no-data dump](https://jira.mariadb.org/browse/MDEV-21786)
では、なぜまだ問題がおこるのか。
本来、 MariaDB の mysqldump は mariadb-dump というツールのエイリアスに過ぎない。
参考:[MariaDB Knowledge Base: mariadb-dump/mysqldump](https://mariadb.com/kb/en/mariadb-dumpmysqldump/)
しかし、DBeaver CE 22.0.0 Windows 版で使われる mysqldump は MySQL オリジナルのものらしい。
この mysqldump はドライバマネージャの native client (local client とも書かれる)で設定されている。
create sequence で作られる sequence オブジェクトは MariaDB 独自の機能で MySQL には今のところない機能なので、
MariaDB の mysqldump(mariadb-dump) で Fix した不具合が MySQL オリジナルの mysqldump では 再現してしまうのだろう。

### 解決
以下は前提として、 create sequence を含んだデータベースをバックアップ対象とするとして、
DBeaver CE 22.0.0 をインストールした Windows に [MariaDB Community Server 10.6](https://mariadb.com/downloads/) をインストールし、
mariadb-dump とそのエイリアスの mysqldump をインストールする。
インストール途中で mariadb サーバを起動するか聞かれるが、こちらはスキップして良い。
インストール完了後、Windows の左下のスタートボタンを押下するとMySQL Client という DOS アプリケーションが出てくるので、
それを起動して、DOS プロンプトから "where mysqldump" とコマンド入力すればインストールされたフォルダが分かる。
```
C:\Program Files\MariaDB 10.6\bin>where mysqldump
C:\Program Files\MariaDB 10.6\bin\mysqldump.exe

C:\Program Files\MariaDB 10.6\bin>where mariadb-dump
C:\Program Files\MariaDB 10.6\bin\mariadb-dump.exe
```
インストールしたら、 DBeaver の「データベース」->「ドライバマネージャー」から、
「MariaDB」の「編集」を押下して、「ネイティブクライアント」タブを押下。
「ホームを追加」で「where mysqldump」で確認したパスを C:\Pro...\bin まで入力する。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24674/1366d132-31be-e823-5f92-b378f3157c8d.png)


あとは、「create new task」から「MySQL dump」を選び、
「Local clinet:」に先ほど追加したものを選んで進め、
![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24674/9963faca-461b-f45b-3c83-20bdd2dff3f5.png)

「extra command args:」に --no-data を追加し、task を作成したら run する。
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24674/0ee9892e-70b6-4523-1076-297982c2819e.png)
出力された dump ファイルを確認して create sequence が含まれていればOK。
gem 'rspec_junit_formatter'について

circleciのconfigファイルを作成している時に
こちらのgemが気になったので、備忘録として書いておきます。

# CircleCIとは
Sass型のCI/CDサービスのことです。クラウド上のコンテナorVMを実行環境いとして使用します。
CircleCIではコンテナの利用を推奨しているようです。

## CircleCIでできること
CircleCIに限らないですが、一般的にCI/CDでやることはビルドとテストとデプロイの3点です。

### ビルド
ソースコードから実行可能なアプリケーションを構築します。
具体的には、Dockerイメージのpull、依存パッケージのインストール、コンパイルなどです。

### テスト
UTなどのテストコードを実行して動作確認をしたり、Rubocop(Ruby)などのコードスタイルチェックなどを行います。

### デプロイ
ビルドしてテストが通ったものを本番環境や検証環境などにリリースします。

# 本題へ
こちらのgemになります
```
gem 'rspec_junit_formatter'
```
調べて見たところ
rspec ビルドステップを使用するプロジェクトにテストメタデータ コレクションを追加するみたいです。

### メタデータとは
データの作成者や作成日やサイズなどの付帯情報のことです。

# まとめ
CircleCI上で付帯情報を確認できるgemだと思います。
今後も気になった事を投稿します。
プラネックス社製　ドコデモセンサーとM5Stackを連動してみた。

# はじめに
以前Amazonで購入したプラネックス社製のIoTセンサ　ドコデモセンサーとM5Stack Core2と連動してみたので記事を書いてみたいと思います。

このセンサはWeb api機能が搭載されており、api理解のためにも勉強してみました。

このAPIというサーバ情報にアクセスできれば、どこからでもセンサ情報を取得することが可能ということが判りました。


# やってみたいこと
・ドコデモセンサー、APIというのを具体的に使ってみたい。
・ドコデモセンサーが便利かどうか確認してみたい。
・M5Stackの画面作成をM5Flowという開発環境でプログラミングしてみたい。


# できたこと
・3分間の間にセンサーが検知していた場合、M5StackのLCD画面を真っ赤にして警告表示できた。


# 難しかったこと。



# 疑問点
・プラネックス社側では、APIのURLへのアクセスは1日500回程度にしてほしいとのサイト掲載がある。現在3分に1回程度でポーリングしている。そのため、検知したら即警告ができない。もっと検知を早く通知したい。


# 今後の課題
・API
[その4]AWS-SAA-躓いたメモ

#### Direct Connect
専用線接続サービス

#### Snaball edgeは転送
ビデオ、画像リポジトリ、`データセンター`にある膨大なデータを簡単に転送できる


#### Route53のヘルス機能で異常が検知された場合、対象のインスタンスに振り分けないようにする。


#### AWS Snawmobileはエクサバイト
超大容量データをAWSに移動する為に、使用できるエクサバイト規模のデータ転送サービス

#### Lambda@Edge
cloudFrontのエッジロケーション
Lamda関数はユーザーに近いロケーションで実行される
CloudFront ←→ lambda@Edge ←→ DynamoDB

#### WAF
SQLインジェクション/XSSから保護する
送信元のIPアドレスに基づくアクセス制限、`CloudFront、ELB`

許可されたIPアドレス → `cloudfront(WAF)` → `ELB(WAF)`→EC2


#### AWS CloudTrail
APIコールをログとして記録する
Apple Silicon（M1）で iOS 開発環境を爆速構築する方法

# はじめに
この記事は、とにかく早く Apple Silicon 環境で iOS アプリ開発環境を整えなければならない方を対象に執筆しました。
Apple Silicon で動かないと業務に支障が出るから買い換えられない…
なんて方を救えたら嬉しいです。

なので、
Rosetta を使うのは嫌！ワークアラウンドも嫌！という方は別記事を参考にしていただければと思います。

# 検証済み環境
- Tool
    - CocoaPods
    - Carthage
    - SPM
    - Mint
    - XcodeGen
    - Homebrew
- Env
    - MacBook Pro 14 inch 2021
        - Apple M1 Pro
    - macOS Monterey 12.2.1
    - [mac-auto-setup](https://github.com/akkeylab/mac-auto-setup)
        
# Rosetta を使いましょう
サードパーティ製ツールをあまり使っていない場合を除き、Apple Silicon 対応にはある程度の工数が必要になることが多いです。
まずは Rosetta 環境下で動くようにして、快適な環境下で少しずつ Apple Silicon 対応を進めていくことをお勧めします。

## Shell commands
お使いのターミナルアプリを Rosetta で起動するようにチェックを入れるか、`arch -arch x86_64` を付けてコマンドを実行しましょう。どちらも同じですが、うまく動かないときは前者で試してみてください。

## Ruby に関連する問題
rbenv のインストールや rbenv 経由での Ruby インストールを Apple Silicon （No use Rosetta）環境下で実行した場合は特に問題に遭遇する可能性が高いです。その一例をご紹介します。

```shell
# 以下エラー発生時に実行
# ffi-X.XX.X/lib/ffi_c.bundle' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64e'))
bundle config --local build.ffi --enable-system-libffi
```

`bundle install` を試みた際、rbenv で導入した Ruby と ffi の相性が悪く、エラーが発生する場合があります。その場合、ffi のインストールに必要な libffi をシステム標準の物を使うように強制することで回避可能です。

https://github.com/ffi/ffi#requirements

## Xcode
Xcode も Rosetta で起動するようにチェックを入れるか、`arch -arch x86_64` を付けて open コマンドを実行しましょう。
ただし、これだけで安心してはいけません。

シミュレータも合わせて Rosetta で起動するように明示的に設定しないと挙動が不安定になります。
`/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app` に対しても `Open using Rosetta` を有効化しましょう。

# Homebrew の仕様変更
Xcode プロジェクト内で Homebrew でインストールしたコマンドが `command not found` になる場合があります。これは、Homebrew 経由でのソフトウェアインストール先が変更になったことによるものです。

```shell
# mint の場合
sudo sh -c "mkdir -p /usr/local/bin & ln -s $(brew --prefix)/bin/mint /usr/local/bin/mint"
```

Xcode 内で実行される Shell Script は一部の PATH しか許可されていないため、従来の PATH にシンボリックリンクを作成することで回避可能です。

# Mint 経由のコマンド実行に失敗
```shell
xcrun --sdk macosx mint run swiftlint
# ↓
/opt/homebrew/bin/swiftlint
```
`mint run` コマンドが失敗する事象に遭遇しました。
調査・試行錯誤を行いましたが、まだ解決できていないため、一時的に Homebrew 経由でインストールした物を呼び出すように書き換えて対応しています。今回は特に lint 系だったこともあり、ワークアラウンド対応としました。

ワークアラウンドとしてコミットする場合、一律で書き換えるのではなく Apple Silicon の場合のみコマンドを変えるように分岐処理を追加すると良いでしょう。

# Break Point によるデバッグに失敗
Break Point を利用して `(lldb) p value` のようにコマンド経由でメモリ上のデータにアクセスを試みると以下のようなエラーが出力される場合があります。

```
Cannot create Swift scratch context (couldn't create a ClangImporter)Cannot create Swift scratch context (couldn't create a ClangImporter)
```

これはシステム側で設定されているディレクトリに zsh が無いことが原因である場合があります。これもいくつか対処方法がありますが、Xcode が参照する PATH にシンボリックリンクを作成することで回避可能です。

```shell
sudo sh -c "mkdir -p /usr/local/bin & ln -s $(brew --prefix)/bin/zsh /usr/local/bin/zsh"
```

# さいごに
いかがだったでしょうか。
他にも環境構築系で苦戦することがあるかと思います。その際には私の環境構築スクリプトも参考にしていただけたらと思います（[mac-auto-setup](https://github.com/akkeylab/mac-auto-setup)）。

最後まで読んでいただき、ありがとうございます。
パイプで繋がったコマンドをバックグラウンドで実行した際に、最初のプロセスのプロセスIDを取得する

シェルにおいて、バックグラウンド実行のプロセスIDは`$!`で取得することができる。

```bash
sleep 10 &
echo $!          # sleepコマンドのプロセスIDが取得できる。
```

では、コマンドがパイプで繋がれている場合はどうなるだろうか？

```bash
tail -f log.txt | grep 'keyword' &
echo $!
```

この場合、`$!`で取得されるのは、パイプの後半のプロセス`grep`コマンドのプロセスになる。

ここで問題となるのは`kill $!`として、`grep`をキルしても`tail`のプロセスが残ってしまうことである。

```bash
$ kill $!       # grepのみがキルされる
$ ps aux | grep tail            # tailのプロセスがまだ残っている
# >  9210   0.0  0.0 34122900    900 s000  SN    6:17PM   0:00.00 tail -f log.txt
```

前半のプロセスのプロセスIDを取得するにはどうすれば良いだろうか？

答えを言うと以下のようにすればよい。

```bash
tail -f log.txt > >(grep 'keyword') &
echo $!        # $!はtailのプロセスIDになっている
```

ここで見慣れない文法 `>( コマンド )` というものがある。
これはコマンド置換と呼ばれるbashの文法で、コマンドを実行したときのIOをファイルのように扱うことができるものである。
(参考：https://techblog.raccoon.ne.jp/archives/53726690.html )
つまり、`tail -f ...`の結果をリダイレクトした先は本来ならファイルであるはずだが、そのファイルへの書き出しが`grep ...`の標準入力に渡されるようになる。
一般にプロセス置換を使うと `cmd1 | cmd2` とパイプで繋ぐものと等価なものが`cmd1 > >(cmd2)`として実現できる。

しかし、パイプと違うのがバックグラウンド実行した際に`$!`で得られるプロセスID。コマンド置換を使った場合、前半の`tail`のコマンドのプロセスIDが取得される。
これによって`kill $!`としても、tailが残ってしまうことなく終了するし、ついでにgrepプロセスも終了する。

参考: https://stackoverflow.com/questions/1652680/how-to-get-the-pid-of-a-process-that-is-piped-to-another-process-in-bash
fortranでモジュールのみコンパイルした時のエラーの原因と解決方法

# 問題
gfortranでモジュールファイルのみコンパイルするとき。
コンパイル時に以下のエラーメッセージが現れる。

```
    C:/TDM-GCC-64/bin/../lib/gcc/x86_64-w64-mingw32/10.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
    C:/TDM-GCC-64/bin/../lib/gcc/x86_64-w64-mingw32/10.3.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-crt0_c.o):
    in function `main':
    C:/crossdev/src/mingw-w64-v8-git/mingw-w64-crt/crt/crt0_c.c:18: undefined reference to `WinMain'
    collect2.exe: error: ld returned 1 exit status
 ```
    
# 原因
このエラーは、リンカがmain関数を見つけられない場合に発生する
https://stackfinder.jp.net/questions/5259714/undefined-reference-to-winmain16
（至極当たり前だが）モジュールのみコンパイルした場合はmain関数を見つけられない
# 解決方法
解決策1. コンパイル文にmainプログラムを含める
　　　　（1行でmainプログラムまでコンパイルする）
解決策2. gfortranのコンパイルオプションに `-c` を加える
　　　　(コンパイル、アセンブルを行う。リンクは行わない)
QMK開発環境　パソコン


Windows10にQMK入れなくても
Raspberry Pi 400 日本版か英語版
使った方が楽かもしれない


自作キーボードをキーボードを使ってする
開発は面白い。

SDカードにOSまるごとインストールするので
事前にSD Card Copierで複製しておけば
バックアップ時点には戻れる

OSを再インストールもWindowsよりは手間が少ない

qmkコンパイル専用機にしても良いぐらいの
手軽さが良いね

Visual Studio CodeがRaspberry Pi OSに
対応してるから、それだけでもWindowsにこだわる
理由が1つ減った。


安くて
　本体のみで1万以下の9790円
　スターターキット 13200円
　
　スイッチサイエンス販売価格で記載

速くて
　CPU 1.8GHz 他のラズベリーパイで1番速い
  2番目がラズベリーパイ４Ｂ　1.5GHz

大きい
　　4Kモニターを2枚表示可能
　　4K 2枚接続時は30Hzに下がります
　　HDMIケーブルを4K対応品で使う必要あり
[初学者/At_Corder] A.Range Productを解いてみた

# [初学者/At_Corder] A.Range Productを解いてみた
## 目次
- 概要
- 開発環境
- 解答と説明
- まとめ

## 概要
A.Range Productの問題です。

## 開発環境
- Ruby 2.6.3
- Visual Studio Code
- Ubuntu 20.04.3

## 解答と説明
問題文は下記のサイトにて、ご覧いただけます。

https://atcoder.jp/contests/agc002/tasks/agc002_a

##### 解答
```ruby:range_product.rb
a,b = gets.split.map(&:to_i)
 
if a <= 0 && 0 <= b
  puts "Zero"
elsif b < 0
  num = b-a+1
  if num.even?
    puts "Positive"
  else
    puts "Negative"
  end
else
  puts "Positive"
end
```
##### 説明
**＜流れ＞**
※問題文のまま、連続数の配列を作ってから、inject(:*)にて、すべてをかけあわせる処理だと、配列の長さに応じて、実行時間が長くなってしまうため、下記のような条件にて分岐。
- 入力された値をa,bに代入。
↓
- （if）入力値の範囲に0が含まれた場合、Zeroを出力。
理由：0に何の数字をかけても、答えは0になるため。
↓
- （elsif）入力値の範囲すべてがマイナスの場合、数字の個数が偶数の時は、Positiveを出力。奇数の時は、Negativeを出力。
理由；(-1)×(-2)=2、(-1)×(-2)×(-3)=(-6) のように、マイナスの数字の個数が偶数の時は、マイナスを打ち消し、奇数の時は、マイナスが残るため。
↓
- （else）入力値の範囲すべてがプラスの場合、Positiveを出力。
理由：マイナスの数字が含まれず、0が含まれない場合は、答えはすべてプラスの数字になるため。

上記流れをコメントとして、実際のコードに付け加えると下記のようになります。

```ruby:説明コメント付き
# 入力された値をa,bに代入。
a,b = gets.split.map(&:to_i)

# （if）入力値の範囲に0が含まれた場合、Zeroを出力。 
if a <= 0 && 0 <= b
  puts "Zero"
# （elsif）入力値の範囲すべてがマイナスの場合、数字の個数が偶数の時は、Positiveを出力。
# 奇数の時は、Negativeを出力。
elsif b < 0
　# b-a+1とすると、マイナス範囲の数字の個数が取得できる。（今回は、a<bでaの方が小さいため、b-a+1）
　# => (-1)-(-3)+1 => (-1)+3+1 = 3個
  num = b-a+1
  if num.even?
    puts "Positive"
  else
    puts "Negative"
  end
# （else）入力値の範囲すべてがプラスの場合、Positiveを出力。
else
  puts "Positive"
end
```
**＜メソッド説明＞**
- 入力された値の取得
空白区切りの取得に、splitを用い、
すべてIntegerで取得するために、a,b,cそれぞれに、to_iをmapメソッドにて、処理しています。
```ruby:入力された値の取得
# a,b = とすると、一度に代入できます。
a,b = gets.split.map(&:to_i)
```
- 偶数の判定
even?メソッドを用いて、b-a+1が偶数であるかを判定しています。
```ruby:偶数の判定
num.even?
```

## まとめ
ざっくりと解答をまとめてみました。
より良いコードになるよう、アドバイスいただけると、嬉しいです！
さくっと、メールサーバーでの送受信の仕組みを理解

# メールサーバーはメールの送受信をやりとりしてくれています。
|メールの送信 |→　①　→　①　| 自分のサーバー(SMTP) |
|:-----------|-----------:|:------------:|
|       |　② ↙︎　↗︎③| ↓④ |
|    |　　②↙︎　↗︎③　　| ↓④   |
|　　　　　　|DNSサーバー　　　　　  | 相手のサーバー(POP/IMAP) |
|         |           |  ↓⑤         |
|        |       |   ↓⑤    |
| | |メールの受信      |


①自分のメールサーバーに送信メールを送る
②送信元と送信先のIPアドレス（住所）を検索
③宛先を照合して自分のサーバーに返す
④送信先のメールサーバーにメールを転送する
⑤受信メールとして相手先に届く

## SMTPサーバー
メールアドレスの`@`以降の部分(ドメイン)から具体的な送信先のIPアドレスをDNSサーバーで検索にかけ送信先のサーバーを探して送信してくれます。
## DNSサーバー
メールアドレスの`@`以降の部分(ドメイン)を管理していて、ドメイン名と送信先のIPアドレスを紐づけて割り出し、SMTPサーバーに送信先を間違えないよう指示してくれます。
## POPサーバー
受信メールを携帯やパソコン端末にダウンロードしてメールを閲覧できます。受信したメールはオフラインでも閲覧でき、受信したメールソフトのみで閲覧ができるようになっています。通常メールサーバーにデータを残さないのですが、受信方法によってはメールを残せるので推奨されます。
## IMAPサーバー
オンライン上でメールを閲覧でき、複数の端末でメールを確認することができます。データが蓄積していくタイプなのでサーバーの容量が大きい場合に向いているが、最近はPOPサーバーの方が使われています。
VScode Thunder Client 変数を定義して使う

## 概要

- 別記事で導入方法を紹介したVScodeの拡張機能 Thunder Clientにて変数を定義して使用する方法をまとめる。

## 前提

- 導入方法は下記の記事で紹介している。
    - [VScode Thunder Client の導入方法](https://qiita.com/miriwo/items/5abec919de64c6c90717)
- 導入が完了し簡単なレスポンスとリクエストで動作確認ができているものとする。

## やること

- リクエストのURLで使用している`localhost:8000`の値を変数として定義し、複数のリクエストで値を使い回せる様にする。（筆者は`http://`を省略していますが明示的に記載したほうが良いかもしれません。）

    | 変数名 | 値 |
    | --- | --- |
    | host | localhost:8000 |

## 設定グループの作成と変数の定義

1. 設定グループの作成
    1. VScodeのサイドバーのThunder Clientのアイコンをクリックする。
    1. 表示されたThunder Clientのメニューで「Env」をクリックする。
    1. 表示されたメニューの「New Environment」をクリックする。

        ![messages_—_line_crm_project-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/4d2037de-4395-fb3f-2978-25220f8ea3f4.png)

    1. VScodeのエディター上部に設定グループ名の入力欄が表示されるので任意の設定グループ名を入力してEnterを押下する。コレクション名と同じものにしておくと識別しやすいかもしれない。（設定グループ名は後から変更できる。）

        ![messages_—_line_crm_project-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/516515d6-f195-71ac-cddc-e1e693919063.png)

    1. 「Env」に今追加した設定グループが追加される。

        ![messages_—_line_crm_project-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/1c6fa70e-2331-d355-1cda-c11246f7fd61.png)

1. 変数の定義
    1. 設定グループをクリックする。

        ![messages_—_line_crm_project-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/e4f91007-eacf-aac1-985a-11fa1590acd9.png)

    1. エディター部分に設定グループの詳細が表示される。

        ![Environment_Variables_—_line_crm_project.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/acd48fe4-b3b1-ed90-52e0-034fc4e64229.png)

    1. 「Variable Name」に「host」と入力し、「Value」に「localhost:8000」と入力し「Save」をクリックする。「Save」の左部に「Save Compoleted」的な文字列が出れば保存できている。（筆者は`http://`を省略していますが明示的に記載したほうが良いかもしれません。）

        ![Environment_Variables_—_line_crm_project-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/bda870b5-eebb-86c1-a18d-f6e9c2e77399.png)

## 定義した変数の呼び出し

1. リクエストの詳細を開く。
1. 今回はリクエストを投げるURLのホスト部分を変数`host`に格納したため、`host`を`{{}}`の中に記載して設定した変数を呼び出す。URL部分が変更できたら「Send」をクリックしてリクエストを送信する。

    ![messages_—_line_crm_project-8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/835c63d0-1428-a439-0b56-ece201e05c5a.png)

1. ステータス200と「OK」の文字列が帰ってきたので問題なさそうである。

    ![messages_—_line_crm_project-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/38c2ba38-6d15-623c-988b-f07a3daa0050.png)