OmniAICreator/Qiita-1.07M huggingface dataset:
VSCode拡張でsqlfluffを使ってfixできるようにする

# はじめに
SQL Linterの「[sqlfluff](https://docs.sqlfluff.com/en/stable/ "sqlfluff")」というものがあります。
プログラムのLintは、極力システムに任せるようにしてしまいたい。
sqlfluff自体はpythonのライブラリですが、VSCodeの拡張もあって、VSCode上で
動作させることが可能です。ただ、この拡張がいまいちかゆいところに手が届かない感じでして、
Lintはできるがfixができない。なのでfixできるようにしてみました。

# sqlfluffのVSCode拡張について
まず、sqlfluffのVSCode拡張はMarketPlaceにあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23578/cfebdffb-b787-b183-19d0-29525d3f2107.png)

ですが、**ここからインストールしてはいけません！**
Marketplaceで配布されているバージョンは古くて、fixする設定が入っていません。
Githubの[vscode-sqlfluff](https://github.com/sqlfluff/vscode-sqlfluff "vscode-sqlfluff")にはfixする処理が入っているのでこちらを使います。

# 導入手順
1. githubからfix対応バージョンをclone
1. ローカルでvscode用パッケージ作成
1. VSCodeにインストール
1. VSCode設定
1. 実行

## githubからfix対応バージョンをclone
前述したvscode-sqlfluffは最新のsqlfluffに対応できていなかったので、
私のほうでforkして修正したものを使ってください。こちらで動作します。

https://github.com/wonohe/vscode-sqlfluff

## ローカルでvscode用パッケージ作成
cloneしたソースコードを使ってVSCode用のパッケージを作成します。
パッケージ作成にはnode.jsの下記ライブラリが必要です。

- tsc
- vsce

```bash:bash
npm i tsc -g
npm i vsce -g
```

上記完了したらcloneしたフォルダのルートで下記にてパッケージ作成します。

```bash:bash
# install from package.json
npm i

# create vscode package
vsce package
```

成功すると、`vscode-sqlfluff-0.0.4.vsix` というファイルが作成されます。

## VSCodeにインストール
VSCodeからコマンドパレットを開いて、`Extensions:Install from VSIX` を実行。
VSIXファイルを選択するダイアログが開くので、前ステップで作成したファイルを選びます。
インストール成功のダイアログが表示されれば完了です。

## VSCode設定
VSCodeからコマンドパレットを開いて、「setting」と入力して設定ファイルを開きます。
検索で「sqlfluff」と入力すると、sqlfluff拡張の設定画面が表示されるので、
そこで `Whether the document formatter is enabled or not`という項目があるので、
チェックをいれておきます。これでfix処理が可能になります。
![ezgif.com-gif-maker (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23578/c4d00033-261b-fb56-189f-e57afca3a0d7.gif)


## 実行
VSCodeにsqlfluffを入れた時点でlintは効くようになっています。
右クリックで「ドキュメントのフォーマット」を実行すると、今開いているファイルのfixが行われます。
![ezgif.com-gif-maker (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23578/2bf0cf85-5e2a-c0d0-16ff-7753db7d5a74.gif)


# さいごに
Githubに上がっているソースコードが少し古いので、調整が必要でした。
READMEにもありますが、VSCode拡張でのfix処理は内部で下記コマンドが実行されています。

```
sqlfluff fix --force <path>
```

というコマンドが行われています。
sqlfluff自体の使い方については公式ドキュメントに詳しいのでそちら参考ください。

それでは！
enjoy！
rbenvが最新なのに、最新のRubyバージョンをインストールできない場合

分かりづらく変なタイトルになってしまい申し訳ありません。

Rubyの最新バージョン(現時点では3.0.1)をインストールしようとした際、rbenvは最新バージョンにも関わらず最新のRubyバージョンが、インストール可能リストに出てこなかったのでその解決法を記載します。

```
#まず現在インストールできるバージョンの確認
$ rbenv install --list
  >Available versions:
  >1.8.5-p52
  > ~略~
  > 2.5.0
```
インストール可能なバージョンの最新が2.5.0でした。
そのため以下コマンドにて、rbenvとruby-buildをアップグレードしようとしたのですが、既にインストールされているとのこと。

```
$ brew upgrade rbenv ruby-build
 >Warning: rbenv 1.1.2 already installed 
 >Warning: ruby-build 20210510 already installed 

#念の為、インストール可能なバージョンの確認
$ rbenv install --list
 > 1.8.5-p52
 > ~略~
 > 2.5.0
```

？？？
なぜ既に最新のrbenvがインストールされているのに、表示されいのか…。

色々と調べ、GitHubからクローンしてくること方法でやってみることに。

```
$ git clone https://github.com/sstephenson/rbenv.git .rbenv
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
$ rbenv install --list
```

もう一度確認してみると、しっかりと3.0.1がありました！

あとはインストールするだけです。

```
$ rbenv install 3.0.1
#バージョン確認
$rbenv versions
#環境全体に適用
$ rbenv global 3.0.1
```

これにて無事にインストールが完了しました。

調べてみると、rbenvをアップデートしてから反映されるまで時間がかかることもあるみたいです。
それであればバージョン確認の際に、表示して欲しくないのですが…。
rbenvをアップデートしても目的のRubyのバージョンがインストールできない場合は、GitHubを経由するやり方を実施してみてはいかがでしょうか。

また今回の事項に関して理由が不明な点もあるので、ご存知の方教えていただければ嬉しいです。
Herokuデプロイ方法#2

Herokuデプロイ方法#1の続き、
前回は、Herokuにログインからdbの設定までを行いました。
今回は、環境変数を設定からアプリケーション公開まで行います。


##Heroku上にmaster.keyを設置
Heroku上には、環境変数としてmaster.keyの値を設置します。
Herokuへ環境変数を設定するためには、 `heroku config`というコマンドを使用します。

###`heroku config`コマンド
Heroku上で環境変数の参照・追加・削除等をする場合に用います。
環境変数の追加であれば`heroku config:set 環境変数名="値"`と実行します。
そうすることによって、Heroku上で環境変数を追加できます。

### Heroku上で環境変数を設定
Heroku上に環境変数を設定します。
下記のコマンドを入力してください。


```:ターミナル
heroku config:set RAILS_MASTER_KEY=`cat config/master.key`
```

### Heroku上で環境変数を確認
設定が正しくできているか、Herokuの環境変数一覧を表示してみましょう。
下記のコマンドを入力してください。

```:ターミナル
heroku config:set RAILS_MASTER_KEY=`cat config/master.key`
```

`RAILS_MASTER_KEY`という変数名で値が設定されていれば成功です。

コミットをHerokuへプッシュした後に、環境変数を設定すると反映されません。
コミットをHerokuへプッシュする前に設定しましょう。
万が一環境変数の設定が漏れた状態でHerokuへプッシュしてしまった場合の対処法は今後紹介する予定です。


##動作環境を変更
デプロイをする前に、Herokuで利用する環境を指定しましょう。
Herokuには、Stack（スタック）という環境が用意されています。

<details><summary>Stackとは</summary><div>
Herokuにおけるアプリケーションの動作環境のことです。
Stackはデプロイされたアプリケーションを読み取り正常に稼働させるために用意されています。
デフォルトのStackは「Heroku-20」です。一方で、別のStackを選択することもできます。
</div></details>

###Herokuで利用するStackを指定

 ```:ターミナル
heroku stack:set heroku-18 -a [アプリケーション名]
```

`Setting stack to heroku-18... done`が表示されたら完了です。

##Herokuへアプリケーションを追加(Git経由でHerokuへデプロイ)
Herokuにデプロイする際には、Gitの仕組みを使用するのでした。
Gitで管理しているリポジトリをHerokuへ反映することで、Heroku上で該当するアプリケーションの操作が可能になります。
Gitで管理しているリポジトリをHerokuに反映するためにはgit push heroku masterというコマンドを用います。

### git push heroku masterを実行
下記のコマンドを入力し、HerokuへTaskAppの情報を追加します。

```:ターミナル
git push heroku master
```

`Verifying deploy... done.`が表示されれば完了です。


##Heroku上でマイグレーションファイルを実行
Herokuにアプリケーションの情報を反映することができました。しかし、データベースにはマイグレーションの情報が反映されていません。rails db:migrateを実行したいところですが、そのままコマンドを入力しても実行できません。Heroku上で実行したいコマンドの頭には、heroku runをつけましょう。

<details><summary>heroku runコマンドとは</summary><div>
Heroku上で実行したいコマンドに用います。
rails db:migrateであればheroku run rails db:migrateと実行します。
そうすることによって、Heroku上でコマンドが実行できます。
</div></details>

###Heroku上でマイグレーションを実行
heroku runを頭につけて、マイグレーションを実行してください。

```:ターミナル
heroku run rails db:migrate
```

##公開を確認する
これまでの作業で、Herokuに反映したアプリケーションは正しく動いているはずです。
コマンドでアプリケーションの情報を確認します。
そのためには、heroku apps:infoのコマンドを実行します。

<details><summary>heroku apps:infoコマンドとは</summary><div>
Herokuにデプロイされたアプリケーションの情報を見ることができます。
</div></details>


```:ターミナル
heroku apps:info
```
公開されたアプリケーションの詳細を見ることができます。

##公開したアプリケーションを確認する
`Web URL: https://[heroku上のアプリケーション名].herokuapp.com/`
の部分のURLへアクセスすれば、公開されたページを見ることができます。



Herokuデプロイ方法については、以上です。
【PHP】ドル・ユーロ通貨換算アプリ

```php

<?php
//通貨換算アプリ
// 1ユーロは117.20円
$euro_rate = 117.20;
 
// 1ドルは108.43円
$dollar_rate = 108.43;
 
$yen = 1000;
$euro = round($yen / $euro_rate, 2);
$dollar = round($yen / $dollar_rate, 2);
?>
```

```javascript
<!DOCTYPE html>
<html lang="ja">
<head>
    <title>通貨の換算</title>
</head>
<body>
  <h1>通貨の換算</h1>
  <dl>
    <dt>日本円</dt>
    <dd><?php echo $yen; ?>円</dd>
 // ユーロ換算での金額を計算(小数第3位四捨五入)
    <dt>ユーロ換算</dt>
    <dd><?php echo $euro; ?> ユーロ</dd>
 // ドル換算での金額を計算(小数第3位四捨五入)
    <dt>ドル換算</dt>
    <dd><?php echo $dollar; ?> ドル</dd>
  </dl>
</body>
</html>
```

・実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/98bd156e-a1d5-efc6-2fdb-80c62ae1a910.png)
Gitの概要と使い方

## はじめに
今回は私も含めて、gitビギナーに向けてgitの概要と使い方をおさらいします。
同じビギナーさんの参考になれば幸いです。参考にした教材は下記リンクから見れます。
<br>

https://www.udemy.com/course/unscared_git/


## Gitとは
 > プログラムのソースコードなどの変更履歴を記録・追跡するための分散型バージョン管理システムである。Linuxカーネルのソースコード管理に用いるためにリーナス・トーバルズによって開発され、それ以降ほかの多くのプロジェクトで採用されている。Linuxカーネルのような巨大プロジェクトにも対応できるように、動作速度に重点が置かれている。(Git - Wilipediaより引用:url https://ja.wikipedia.org/wiki/Git)

簡単に言うと、ゲームのセーブに似た機能を持つシステムです。
現在の進捗を保存し、エラーでどうしようもなくなってしまったとしても、以前保存した状況(過去のバージョン)からやり直すことのできる便利なシステムです。

## Gitの用語集
ここからはgitを使うにあたって最低限覚えておかなければならない用語の解説をします。
※あくまでgitの機能を使う為に必要な最低限の用語です。

```
① リポジトリ
② ワークツリー
③ インデックス
④ .gitディレクトリ
⑤ branch
```
**リポジトリ**
ファイルやディレクトリの変更を記録する場所。変更履歴を管理したいディレクトやファイルを管理下に置くことで、変更履歴を管理することができる。

**ワークツリー**
実際に作業をするディレクトリやファイル群のこと。階層構造が樹の根に見えることから、ワークツリーと呼ばれる。

**インデックス**
ワークツリーからリポジトリにディレクトリやファイルを記録する際に、その中間に配置されるもの。インデックスを間に挟むことで、ワークツリー内の必要ないファイルを含めずにコミットを行ったり、ファイルの一部の変更だけをインデックスに登録してコミットすることができる。

**.git**
先頭の「.」は隠しファイルであることを示すものなので、正しくはgitディレクトリとなります。git initコマンドによって作られるディレクトリ。gitが含まれているディレクトリとそれより下位にあるディレクトリがgitで管理されることになる。

**ブランチ**
ブランチは作業履歴を枝分かれさせて記録していくためのもの。
ブランチ上での変更は統合されるまで他ブランチに影響しないしされない。

##最後に
今回は備忘録兼ビギナーさん向けに、Gitの概要をまとめました！
次回は基本のコマンドや一歩踏み入った内容をまとめさせていただきます！
※誤りがないよう心がけていますが、間違いに気づかれた場合はコメントを書いていただけると幸いです。
wordpressとmariaDBがつながらないときに試したこと

Kubernetesのクラスター上に別サービスでwordpressとmysqlを立てて通信する際、かなり詰まったので解決するために試したことを書いておきます。
WordPress側で発生する`Error establishing a database connection`を解決するための方法です。


##とりあえず確認したこと

###WordPress側の設定

```
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'wpdb' );

/** MySQL database username */
define( 'DB_USER', 'wpuser' );

/** MySQL database password */
define( 'DB_PASSWORD', 'wppass' );
```

`wp-config.php`の`DB_NAME`, `DB_USER`, `DB_PASSWORD`がmariaDB側と合っているか確認しました。



###mariaDB側の設定

```
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
| wpdb               |
+--------------------+
```

```
MariaDB [(none)]> select user, host from mysql.user;
+-------------+--------------+
| User        | Host         |
+-------------+--------------+
|             | bbcec86f632b |
|             | localhost    |
| mariadb.sys | localhost    |
| mysql       | localhost    |
| root        | localhost    |
| wpuser      | localhost    |
+-------------+--------------+
```

wp-config.phpで設定しているデータベース, ユーザーが存在しているか確認しました。

```
show grants for 'ユーザー'@'ホスト'
```
作成したユーザーが作成したデータベースに対する権限を持っているかの確認も行いました。

##別コンテナの時確認したこと

###wordpress側の設定
```
/** MySQL hostname */
define( 'DB_HOST', 'mysql' );
```
私は別サービスで`mariadb`と`wordpress`を構築していたので、デフォルトの`localhost`だと接続できませんでした。
サービス名で名前解決できるのでサービス名に設定しました。
`curl`等でリクエストを飛ばし、名前解決が正常に動作しているか確認する必要があるかもしれません。

###mariaDB側の設定

コンフィグの確認

[公式サイト](https://mariadb.com/kb/en/configuring-mariadb-for-remote-client-access/)を見ながら、作成したuserにアクセスできるよう設定を行いました。


https://mariadb.com/kb/en/configuring-mariadb-for-remote-client-access/


```
[mysqld]
user = root
datadir = /var/lib/mysql/
skip-networking = 0 
skip-bind-address
```
my.cnfというファイルにこのような内容を保存し、`/etc`に配置しました。

```
mysql --help | find "my.cnf"
```
検索を行い、デフォルトのコンフィグを書き換えても動作すると思います。


###DBに作成したユーザーのホスト

mariadbに追加したwordpress用のユーザーを別サービスから触るためには、適切な権限が設定されていなければなりません。

```
'ユーザー名'@'WP側のIP'
または
'ユーザー名'@'%'
ワイルドカード指定なるのですべてのホストから接続可能
```

私が接続できなかった原因はこれでした。

```
'ユーザー名'@'localhost'
```

以前作成したDockerfileからコピペしてきていたため、localhostになったままなのでMariadbに接続できず、wordpressが機能しませんでした。


##まとめ
やっと会えました。

![wp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351398/7e5ad020-e294-6eb6-100a-6f1555bb7613.png)
【pythonとJava比較】ループでメソッド呼び出し

pythonをやり始めてrange()っていいなと思ったのでJavaと比較して書いてみた。
※対象の処理だけならpythonだと短く書けるがJavaと同じことができる状態にした。

# range()でメソッド呼び出し

#### python

```python:test.py
import sys

class Test:
    """
    テストクラス
    """

    def main(args: list) -> None:
        """
        メイン処理
        :param args: コマンドライン引数
        """
        [Test.test(i) for i in range(3)]
    def test(intVal: int) -> None:
        """
        呼び出すメソッド
        :param intVal: パラメータ
        """
        print(intVal)

if __name__ == "__main__":
    args = sys.argv
    Test.main(args)
```

#### java

```java:Test.java
import java.util.stream.IntStream;

/**
 * テストクラス
 */
public class Test {

	/**
	 * メイン処理
	 * @param args コマンドライン引数
	 */
	public static void main(String[] args) {
		IntStream.range(0, 3).forEach(i -> Test.test(i));
	}

	/**
	 * 呼び出しメソッド
	 * @param intVal パラメータ
	 */
	public static void test(int intVal) {
		System.out.println(intVal);
	}

}
```

# listのメソッド呼び出し

#### python

```python:test.py
import sys

class Test:
    """
    テストクラス
    """

    def main(args: list) -> None:
        """
        メイン処理
        """
        list = []
        list.append(Item(100, 'バナナ'))
        list.append(Item(200, 'もも'))
        [print(item) for item in list]
    def test(intVal) -> None:
        """
        呼び出すメソッド
        :param intVal: パラメータ
        """
        print(intVal)

class Item:
    def __init__(self, item_no: int, item_name: str) -> None:
        self.item_no = item_no
        self.item_name = item_name
    def get_item_no(self) -> str:
        return self.item_no
    def get_item_name(self) -> str:
        return self.item_name
    def __str__(self) -> str:
        return "{} {}".format(self.get_item_no(), self.get_item_name())

if __name__ == "__main__":
    args = sys.argv
    Test.main(args)
```

#### java

```java:Test.java
/**
 * テストクラス
 */
public class Test {

	/**
	 * メイン処理
	 * @param args コマンドライン引数
	 */
	public static void main(String[] args) {
		List<Item> list = new ArrayList<Item>();
		list.add(new Item(100, "バナナ"));
		list.add(new Item(200, "もも"));
		list.stream().forEach(item -> System.out.println(item));
	}

}
```

```java:Item.java
public class Item {

	private int itemNo;
	private String itemName;

	public Item(int itemNo, String itemName) {
		this.itemNo = itemNo;
		this.itemName = itemName;
	}

	public int getItemNo() {
		return itemNo;
	}
	public String getItemName() {
		return itemName;
	}

	@Override
	public String toString() {
		return String.format("%s %s", getItemNo(), getItemName());
	}
}
```
テレワーク用の出退勤時のタスク一元化アプリ（勤怠管理とか）作ってみた！！

# 背景
筆者が務める会社でも、昨年からテレワーク勤務が標準化された。
しかし、社内のシステムやら制度やらはなかなか追いついていかず、
色々面倒くさいことがあった。。

- 出勤したら、打刻とは別に、メールで出勤報告＆タスク報告が必要。二度手間。
- 今どこにいるかが分からないから、予定表にテレワークか否かを記入する必要あり。
- 直接コミュニケーションとれず、メールが飛び交う。チャットでよくない？と思うことも。。

というわけで、、、
**打刻**ができ、**チームメンバーの勤務状態がリアルタイムに見える化**され、打刻ついでに**ToDo**も整理でき、
朝一番に伝えたいちょっとしたお知らせを**チャットで共有**できるような、
「テレワーク向けの出退勤時にやること一元化アプリ」を作りたかった。

# 作ったアプリ

[デモページはこちら！(https://the-team-run.web.app/)](https://the-team-run.web.app/)

- ログインID : test〇@test.co.jp　(test1@test.co.jp ~ test10@test.co.jpまで用意。test5@test.co.jpまでがAdminユーザ。)
- パスワード ： passowrd

※公開用ということで一部バックエンドに制限を設けており、エラーが返る箇所があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526678/31ee6aa5-e3bc-4b35-2b58-ae2a7a96e53f.png)


こんな感じのWebアプリ。メインとなる出退勤ページでは、

- 出勤・退勤
- 現在のステータス変更
- 勤務地変更
- 他のメンバーのリアルタイムの状況把握


<br />
<br />


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526678/b0771fe8-f84b-0d9c-0cac-15e36c02ac3d.png)

カレンダーページで

- 勤務実績の変更申請
- 休日申請
- 各日付の勤務地の変更
- Done(その日こなしたタスク)の確認
- 他のメンバーの勤務実績・予定等確認

が可能。

<br />
<br />


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526678/eaf9a8a6-bb2c-963e-bdb6-b03d9873e612.png)

ToDoページでは

- タスクボードによる、ToDo、Doing、Doneの整理
- 他のメンバーのタスク状況確認

が可能。


<br />
<br />


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526678/1159dba2-51ac-aa40-900c-08f258310466.png)


Requestページは、組織内のAdmin権限を持ったユーザのみが利用できる。
部長とかに割り当てるような想定。

- 組織へのユーザ新規追加申請の承認・拒否
- 勤務実績の修正申請の承認・拒否
- 休暇取得申請の承認・拒否

が可能。
<br />
他に、Settingページで細かい設定変更もできる。（admin権限の割り当てやパスワードの変更など）

<br />


# 使用した技術
- Vue.js
- Vuex
- Firebase
  - Firebase Authentication
  - Firestore
- Cloud Functions　(Node.js)

# 押しポイント★

- **テレワークでも繋がれる**
テレワークで困るポイント、寂しさを感じるポイントとして、誰がどこで何をやっているのかが分かりにくい、コミュニケーションを取る場が少ないことが挙げられる。
本アプリはただの勤怠管理システムではなく、上記の悩みを解決する機能を持っており、更にチームメンバーの状況もリアルタイムに更新されるため、「繋がっている」気分になれる。
また、**勤怠管理のついでに**触れることが大きなポイントであり、出勤地報告やToDoの整理、朝一の挨拶などをそれぞれのシステムから強制される煩わしさを感じさせない。

<br>

- **ワクワクを感じさせるUI**
ダサさMAXかもしれないが、最近よくあるオシャレなUIではなく、個性的なUIにしたかった。
目指していたのは、ゲーム性を感じる、ワクワクさせるようなUI、朝一出勤からテンションが上がるようなUIにしたかった。
筆者はワクワクするが、どうだろうか。

<br>

- **レスポンシブデザイン(スマホ対応)**
スマホにも対応してみた。
スマホでは、各アイテムをいかにコンパクトにするかを意識した。

<img width="200" alt="Screenshot_20231215-102007.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526678/1b47872a-c003-0721-eaf0-b9ad1779581e.png">


<img width="200" alt="Screenshot_20231216-004033.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526678/01b40584-c2ee-abee-c570-43ef5d1e57fb.png">


<img width="200" alt="Screenshot_20231215-102047.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526678/a087a0a0-4a0c-1700-8013-0876a726626b.png">


<img width="200" alt="Screenshot_20231216-004214.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526678/3124cee3-b80a-2d44-6d26-1414977e4d6e.png">


## 最後に
今回かかった開発期間は約1か月半。
Firebaseとか使えば、小規模の中でも少し大きめのシステムを割と短期間で作ることができるのが最高！
Webアプリの開発楽しい。
思いついたものどんどん作れるようになりたい。

[gitlabはこちら！(https://gitlab.com/teten927)](https://gitlab.com/teten927)
【Vue.js】Vue.jsでリアクティブがどう実現されるか

## はじめに
仕事で使う事になったので1からVue.jsについて学んだ。
ちゃんと覚えておかないとまずそうな事を備忘録として1つ1つ残しておく。

## Vue.jsでリアクティブがどう実現されるか
Vueインスタンスが変更されればHTMLも変更されるという挙動をするが、これをリアクティブという。

以下のように外部から新規にプロパティを作成したりすることもできるが、Vueインスタンスが作成されたときに定義されていないプロパティはリアクティブにならない。
![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/59ef664a-35e2-3300-9619-51f5c14ddc18.gif)

```html:sample.html
<body>
    <div id="app1">
        <p>{{message}}</p>
        <p>{{name}}</p>
        <button @click="message='ボタンから変更'">変更</button>
    </div>

    <!-- <script src=" https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script> -->
    <script src="./vue.js"></script>
    <script>
        const vm = new Vue({
            el: '#app1',
            data: {
                message: 'こんにちは'
            }
        })
        vm.message = '書き変えた';
        vm.name = 'こんばんは';
        console.log(vm);
    </script>
</body>
```

リアクティブを実現するには、

- Vueインスタンスが作成される際に（`new Vue()`の際に）プロパティに定義されている

必要がある。これは、

- Vueインスタンスが作成されたときに、暗黙的にgetter/setter（抽象的にwatcherと言ったりする）が作成され、それによりリアクティブを実現しているから

実際に`console.log(vm)`の中身を見ると、Vueインスタンスの中に`message`に対応するgetter/setterはあるが、`name`に対応するgetter/setterはないことが分かる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/aab5c4ff-2b2f-72bd-f83b-b8d24625e364.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/2ae0400c-326b-d450-8c18-5516623a0704.png)

## Vue.jsの勉強メモ一覧記事へのリンク
Vue.jsについて勉強した際に書いた勉強メモ記事のリンクを集約した記事。

- https://qiita.com/yuta-katayama-23/items/dabefb59d16a83f1a1d4
アラサー未経験フリーターがITインフラ業界に放り込まれてawsの資格をプロフェッショナルまで取った話　①クラウドプラクティショナー

これからawsの資格を取得しようと考えている、IT及びaws未経験者の方に少しでも参考になればと思いこの記事を書きました。

入社1年が経つ位にアソシエイト3つ取得、2年経つ直前位までにプロフェッショナル2つを取得し5冠を達成しました。
現在保有しているaws資格は以下です（取得順）
・クラウドプラクティショナー
・ソリューションアーキテクト（アソシエイト）
・SysOpsアドミニストレイター（アソシエイト）
・デベロッパー（アソシエイト）
・ソリューションアーキテクト（プロフェッショナル）
・DevOpsエンジニア（プロフェッショナル）

筆者は現職に就くまで、某黄色い看板のラーメン屋で「ニンニク入れますか？」とか言っていたり秋葉原で「お探しの商品ありましたらどうそ～」等と飲食サービス業にいることが長く、ITとは無縁の環境で過ごしてきました。
就職が決まり業界経験者の友人にlinuxの基礎を教えていただいてた際、ターミナルで叩く cd や ls について「これは何のプログラム言語？」と聞いてとても渋い顔をされたのは今でも覚えています。見捨てないでくれてありがとう。

まず、勤続2ヵ月程で未経験者のほとんどが最初に取得するクラウドプラクティショナーから取得しました（取らないと本採用されないという強制イベント...）。
しかも支給されたPCがUS配列だし（現在は洗脳され済み）。

勉強法も何もawsどころかクラウドってなんやねん状態から始まっているので、
ひたすらネットで合格記を漁り、それっぽいことを書いてありそうな気がする記事を信じてそれに沿って勉強していました。
まぁどの記事もひたすら実際にawsのサービス触れって感じで書いてあったので取っ掛かりはゲット。まずは触り始めました。

主にEC2関連のものですね。

とりあえずEC2を立ててみましょうからwebサーバーにする為apache入れてindex.html書いてみようとかその辺りから開始していきました。
EC2でwebサーバーが立ち上ったら今度は同じものをもう一台立ててALBでバランシングしてみようといった流れです。

EC2を複製するときにスナップショットというサービスを使ったら便利だなぁとか、LBにもALBとCLBがある等、実際に触りながら「こんなんあるんだなぁ」程度にすすめていきました。
バランシングが出来たらhttps化したりドメインを取得して外部公開を試みたり、とりあえずはwebサイトを実際に作ってみましょうってところが主ですね。

クラウドプラクティショナーを取得するまでに触った実機（実機じゃないんだけど。。。）はこの辺とS3程度でした。まぁ個人が無料枠で触れる範疇です。

座学に関しては以下の本が会社にあったのでそれを借りてひたすら読み込んでいました。

AWS認定資格試験テキスト AWS認定 クラウドプラクティショナー

https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9A-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%BC-%E5%B1%B1%E4%B8%8B-%E5%85%89%E6%B4%8B/dp/4797397403/ref=asc_df_4797397403/?tag=jpgo-22&linkCode=df0&hvadid=295691444786&hvpos=&hvnetw=g&hvrand=3206677217933346697&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009311&hvtargid=pla-718362586207&psc=1&th=1&psc=1

初版発行から既に2年ちょい経過しているので試験問題がどう変わっているかは把握していませんが、試験問題は主にawsとはなんぞや？といった問題が多いので、その辺を説明を薄く広く解説してくれるので私は結果的に大変参考になりました（読み始めたときは宇宙ネコ状態でしたがそこは気合で）。

試験勉強はほぼこの本のみで行きました。
あとは本に出来たサービスをaws公式のドキュメント読んで学習といった感じです。

勉強期間は大体2ヶ月位で試験に臨みました。
前日に友人と泥酔してしまい、当日は試験時間前まで会場のトイレで過ごしました。
モニターにピントが合わず苦戦しました。

結果は合格。
スコアは以下です。

総合スコア:  80%
トピックレベルスコア:
1.0  Cloud Concepts: 100%
2.0  Security: 75%
3.0  Technology: 88%
4.0  Billing and Pricing: 33%

上3つは実際にサービスに振れたこともあり上々でしたが、請求関係のスコアが低いですね。
まぁ合格したので良しとしましょう。
これでIT業界に本採用され、ひどい目にあっていく日々が始まりました。

ソリューションアーキテクト以降についてはまた次回。
最後まで閲覧いただきありがとうございました。

---

アソシエイト3種編はこちら
https://qiita.com/instant_baby/items/ee0c98df8071db2d8045
composer require -w tymon/jwt-authでエラー


## 環境

- Laravel ^8.40
- PHP 8.0

## 課題
composer require -w tymon/jwt-auth としたら下記のエラーが出てしまう

```
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Root composer.json requires tymon/jwt-auth ^0.5.12 -> satisfiable by tymon/jwt-auth[0.5.12].
    - tymon/jwt-auth 0.5.12 requires illuminate/support ~5.0 -> found illuminate/support[v5.0.0, ..., 5.8.x-dev] but these were not loaded, likely because it conflicts with another require.
```

## 解決策

以下のコマンドで実行する

```
composer require tomfordrumm/jwt-auth:dev-develop
```
スプレッドシートで別シートにストックされた内容から更新する

#はじめに
研修で、無料かつノーコードでwebアプリ開発可能な[Glide](https://www.glideapps.com/)を扱った。
Glideでは、Googleアカウントと紐付け、自分のドライブ上のスプレッドシートをデータベースとして扱うことができる。
アプリを作っているときに、インプットしたデータから元データの数値を更新したかったが、Glideだけでは対応できなかった。
そこで、スプレッドシートでGAS(Google Apps Script)を使いスクリプトを組むことにした。
(ExcelでいうVBAでマクロを組むのと同じ感覚)

筆者は研究室で楽をするために、実験装置を自動で動かしデータを収集整形するために、Excelでマクロを組んだことがあるくらいで、スプレッドシートでマクロを組むのは初めてで、GASも初めて触った。
変なところもあるかもしれないので、指摘していただけると助かります。

#スプレッドシート中身
###シート構造
| シート名| master |data |
|:-:|:-:|:-:|
|役割| データを集約 | アプリからのインプットを蓄積  |

dataのシートへはGlideのFormを用いて入力されたデータ群

###シート中身
今回は簡易的にmasterとdataともに同じ項目

|  | A | B | C |
|:-:|:-:|:-:|:-:|
| 1  | name | score | time stamp  |
|  2 |  A |  10 | 5/19  |
|  3 |  B | 4  | 5/20  |

のように名前・点数・更新日時のようにした。

#やりたいこと
dataに蓄積された点数などのデータを名前でリレーションし、masterのデータを更新し、更新し終えたらdataから消す。

#GASスクリプトエディタの開き方
スプレッドシート上部の「ツール」→「スクリプトエディタ」で表示可能
たまに開けない人がいるらしいが、原因はChromeでデフォルトのGoogleアカウントで編集しようとすればほぼ解決するらしい。
>参考：[「現在、ファイルを開くことができません」と出てスクリプトエディタが開かない](https://stafftaion.dcf7.com/438/),検温くん


#実際に組んだスクリプト

```
/** @OnlyCurrentDoc */

function myFunction() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var c_sheet = spreadsheet.getSheetByName("data");
  var v_sheet = spreadsheet.getSheetByName("master");

  while (c_sheet.getLastRow()!=1){
    var flag = 0;
    for (let i=2; i<=v_sheet.getLastRow(); i++){
      if (v_sheet.getRange("A"+i).getValue() == c_sheet.getRange("A2").getValue()){
        v_sheet.getRange("A"+i+":C"+i).setValues(c_sheet.getRange("A2:C2").getValues());
        var flag = 1;
        break;
      };
    };

    if (flag != 1){
      v_last = v_sheet.getLastRow() + 1;
      v_sheet.getRange("A"+v_last+":C"+v_last).setValues(c_sheet.getRange("A2:C2").getValues());
    }

    c_sheet.deleteRows(2);
  };

};

```

###手順
1.dataシートにデータがあるかチェック
　1.1あれば2へ
　1.2なければ終了
2.dataシートの一番上のデータを取得
3.masterシートと名前をキーとして一致するものを検索
　3.1.一致すればデータ上書き
　3.2.一致しなければ一番うしろに追加
4.一番上のデータを削除
5.終了　→　1へ戻る。


#トリガーについて
トリガー：組んだマクロを実行させるタイミング
指定しなければ、自分で実行する必要がある。
###GASにおけるトリガーの種類
Open(起動時)
ファイルが開かれたときに実行

Edit(編集時)
セル内容が変更されたときに実行
＊スプレッドシートのみ

Change(変更時)
スプレッドシートの構造が変更されたときに実行
シート・列の追加・削除など
＊スプレッドシートのみ

Form submit(フォーム送信時)
フォーム送信 or フォーム回答がスプレッドシートに書き込まれたときに実行

Time driven(時間主導型)
一定時間や特定日時に実行

###トリガー設定方法
色々ググったが昔のUIのものばっかで、現在(2021/5/20)ではGASのスクリプトエディタ左側の「目覚まし時計」マークから設定できる。

###トリガー設定
最初に"Edit"でトリガーを設定したが、Glideからのセル変更では
トリガーになってくれなかった。

そこで、今回は"Time driven"で1分おきにトリガーが発生し、マクロを実行するようにした。




>参考：[【GAS】トリガーとは！トリガーの種類と使い方を解説](https://takakisan.com/gas-trigger-introduction/),takasakisan,(2019-08-27)
Herokuデプロイ方法#1

##Herokuにログイン
ターミナルからHerokuへログインします。
下記のコードを入力し、メールアドレスやパスワードを入力します。

```:ターミナル
heroku login --interactive

=> Enter your Heroku credentials.
# メールアドレスを入力し、Enter
  => Email:
# パスワードを入力して、Enter
  => Password:

Logged in as ◯◯@sample.com
```

`Logged in as ◯◯@sample.com`に登録したアドレスが表示できていればログインできています。

##Heroku上にアプリケーションを作成
Heroku上にアプリケーションを作成するためには`heroku create`コマンドを実行します。

```:ターミナル
heroku create [任意のアプリケーション名]   //[任意のアプリケーション名]を指定しない場合はherokuが自動で命名する
```

成功すると、以下のように出力されます。

![Qiita【herokuアプリ作成1】.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1210417/b6e92e34-2cd6-697e-7981-d4a47c37dd73.png)


###アプリケーション名の命名の注意点

- 名前は文字で始まり、文字または数字で終わる必要があり、小文字、数字、およびダッシュのみを含めることができる。

- [任意のアプリケーション名]がすでにheroku上に存在する場合は作成できない。

###アプリケーションが作成できたかを確認

下記のコマンドを入力し、正しく設定できたことを確認します。

```:ターミナル
git config --list | grep heroku
```

`fatal: not in a git directory`以外が表示されていればオッケーです。


##Heroku上でMySQLを使えるようにする
アプリをデプロイする前に、まずデータベースの設定します。
Herokuでは、使用するデータベースの設定が、デフォルトでPostgreSQLというデータベースになっています。

今回は、私の開発環境と同様にMySQLを使用するための設定を行います。
ClearDBアドオンを追加することによって設定できます。

<details><summary>ClearDBアドオンとは</summary><div>
ClearDBアドオンとは、MySQLを使うためのツールです。
ClearDBというデータベースサービスが提供しているアドオンで、
これを追加することにより、HerokuでMySQLを使用できるようになります。</div></details>




下記のコマンドを入力して、ClearDBアドオンを追加します。

```:ターミナル
heroku addons:add cleardb
```

###設定を変更
データベースはMySQLに設定できました。
しかし、Ruby on Railsを使う場合は、MySQLに対応するGemについて考慮する必要があり、そちらの設定を変更します。

まず、下記のコマンドを入力。

```:ターミナル
heroku_cleardb=`heroku config:get CLEARDB_DATABASE_URL`
```

これでClearDBデータベースのURLを変数heroku_cleardbに格納できました。

続いて、下記のコマンドを入力。

```:ターミナル
heroku config:set DATABASE_URL=mysql2${heroku_cleardb:5}
```

これでデータベースのURLを再設定できました。
TaskAppではmysql2というGemを使用しているので、
DATABASE_URLの冒頭が`mysql2://`に変更されていることも確認します。



以降、アプリケーションの公開までは、
Heroku上にアプリケーションを作成#2に続きます。
Android Studio4を起動したらエラーになる

# 概要
* Android Studio4.1系を使っていて、4.2へのアップグレード通知に従いアップグレードした
* アップグレード後に起動すると、下記のようなエラーダイアログが表示されて起動しない

※この現象は、Windows版、MacOS版のどちらでも発生する。
![AS42_pleiades.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222251/956b4f12-099a-9c24-66f8-c34ec83d7574.png)

```
Internal error. Please refer to https://code.google.com/p/android/issues

java.lang.VerifyError: Expecting a stack map frame
Exception Details:
 Location:
  com/intellij/openapi/util/text/StringUtil.pluralize(Ljava/lang/String;l)Ljava/lang/String; @7: nop
 Reason:
  Expected stackmap frame at this location.
 Bytecode:
  00000000: 2ab0 0000 a7ff fe00 bf00 00a7 fffe
 Stackmap Table:
  same_frame(@2)
  same_frame(@9)
```

# 原因
このエラーは、Android Studioの日本語化をPleiadesのもので行っていると発生する。
原因は単純で、4.1系の設定しかないのに、4.2系にアップグレードした際に4.2系の設定を読み込もうとするからである。

* Pleiades Eclipse 日本語化プロジェクト
https://mergedoc.osdn.jp/


# 対処方法
対処方法は、もう一度Pleiadesの日本語化を4.2系のAndroid Studioに対して行うだけ。
これで、4.2系の設定ができるので解消する。
terminatorのフォントをRicty Diminishedにしてみた

#　Ricty Diminishedとは
イケてるエンジニアご用達のスタイリッシュでかっこいいフォント。
具体的にどのようなときに役に立つかと言うと、リモートワークでIDEを女性社員に画面共有する際に他のヤツとは一味違うぜ感を演出することができる。ちなみに今のところそのような場面は一度もなかった。
eclipseのフォントをこれにしてみたところコーディングが捗った気がしたので、terminatorにも導入してみることにした。
# インストール

```
# git clone
$ git clone https://github.com/edihbrandon/RictyDiminished.git

# フォントを格納するディレクトリを作成&移動
$ mkdir ~/.fonts
$ cd ~/.fonts

# ~/.fontsにフォントを格納する
$ mv ~/RictyDiminished*.ttf .
```
# terminatorに設定する
1.適当なところを右クリック[preferences]

2.[profiles]で使用しているprofileを選択

3.Use the system fixed width fontにチェックが入っていたら外し、RIcty Diminished Regularを選択
(Regular以外は認めない）

4.closeしたら適用される
# こんな感じになる
右がデフォルト　左がRicty Diminished
![termin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/950865/c4aacae1-df6a-1b0b-9490-f9f3d9e8e3fa.png)
どうだかっこいいだろう
左のほうがなんかちょっとシュッとしてる感じがするだろう
違いがわからないやつは一生コマンドプロンプトを使い続けるがいい
# 日本語
デフォルト
![japa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/950865/2ea9ca3c-56b7-9f3e-7241-429ee7ac314b.png)






Ricty Diminished
![japa2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/950865/7080738d-1a4a-e9a3-4dd8-5057d42056f0.png)

どうだ品があるだろう
このフォントの日本語Tシャツならスターバックスのオシャレな空気にさえ溶け込めるだろう
# おわりに
正直に言うと、私はフォントにそこまでのこだわりはない。
恐らくデスクを離れてフォントをデフォルトに戻されても気づかないだろう。
結局のところフォントもvimやemacsと同じで宗教だ。傍から見たらどうでもいいところにこだわっていてキモいが、そういうのもIT業界の醍醐味の一つだと思う。私もせっかくIT業界に入信したので、積極的に色んな沼に片足を突っ込んでいきたい。
JavaScript: 関数（function、メソッド）の書き方

処理内容を一度定義しておいて、別の場所から呼び出す（実行する）方法です。

```js
function hello() {
  document.write("hello, I like codes.");
}
```

上記が関数の定義。
下記のものを書くと、呼び出して実行されます。

```js
hello(); //実行。
```

例：
```js
<script>
  function hello() {
  document.write("hello, I like codes.");
}
hello(); //実行。
</script>
```
console出力で確認する場合：
```js
<script>
  var testMes = "I love codes";
console.log ('testMes=' + testMes);
</script>
```
変数に入れて実行する場合の例：
```js
<script>
var helloTest =  function hello() {
  document.write("hello, I like codes.");
}
helloTest(); //実行。
</script>
```
命名規則について

# 命名規則
命名規則とは、変数名や関数（メソッド）名など、名称となる文字列に設けられた一定の規則（ルール）のことです。


number ←　  宣言　（変数名をつけて変数を作る）
number ← 　 定義　（変数を格納する）

基本的に宣言と定義は同時に行う。

	
	
	
	

|  種類 |  命名規則  |
| ---- | ---- |
|  クラス名  |  頭文字大文字のキャメルケース  |
|  メソッド名 |  小文字のスネークケース |
|変数名|小文字のスネークケース|

コントローラーに二つ目の変数を定義した際、大文字・小文字、定義する名前などのミスがあったので再確認です。
【LINE LIFF】LIFFアプリでQRコードリーダーを作る

こんにちは。

LINEが提供するWebアプリ用フレームワークLIFFで、
アプリ内QRコードリーダーを実現することができるようになったので、まとめてみました。


[結論](#結論)

# はじめに

LIFFは、LINE Front-end Framework といい、LINEが提供するWebアプリの
プラットフォームです。近年耳にするLINEミニアプリについても
LIFFをベースとしたWebアプリのプラットフォームです。

LIFFはLINE上で自由にWebアプリを作成することができ、
自由度が高く、LINEの用意したデモサイトでも紹介されていますが、
会員証、予約、モバイルオーダーなどの用途での利用も可能なプラットフォームです。

https://lineapiusecase.com/ja/api/miniliff.html

# 2019/11/29 激震が走る

https://developers.line.biz/ja/news/2019/11/29/liff-functions-suspended/

LIFF上で、QRコードリーダーを実現する仕組みとして、
liff.scanCode() というメソッドが提供されていましたが、
突然の提供停止（iOSのみ）告知が行なわれます。

Webアプリにおいて、QRコードリーダーというのは
需要のある機能であり、この提供中止により"LIFFのメリット"の1つが消えてしましました。

提供終了した理由については案内は行われていないようですが、
iOS版のみ提供停止ということで、そのあたり何かしらの問題があったものと推察されます。

その後、WebRTCや、HTML5の機能などを利用して、
どうにかiOS環境においてもLIFFアプリ内でQRコードリーダーを実現できないか模索していましたが、
結局可能な方法は発見できませんでした。

# ときは流れ2021/4 

2021/4 頃LINEのAPI USE CASEサイトに以下のような記事が
アップロードされました。
https://lineapiusecase.com/ja/usecase/smartretail.html

この記事では、LIFFアプリ内で、Barcode Scanner SDKを利用して
バーコードリーダを実装していました。

もちろんiOS端末でも動作しました。
この記事を発見し、なぜLINE社のバーコードリーダは動作しているのか
調査を行いました。

するとiOS14.3がリリースされ、WKWebViewがgetUserMedia対応したと
いう情報がありました。
https://bagelee.com/programming/ios-14-3-wkwebview/
https://bugs.webkit.org/show_bug.cgi?id=208667#c77

LIFFは以下のページにも記載がある通り、iOSではWKWebViewを
利用していると記載があるため、もしやと思い、QRコードリーダーを実装しました。
https://developers.line.biz/ja/docs/liff/overview/

# 結論

2021/05/20現在、
Vue Qrcode Readerや、jsQRなど、WebRTCを利用して実装したQRコードリーダーは、
LIFFブラウザ内で利用可能でした。
<img width="400"src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620553/60a36b86-93a0-b380-a53a-8f2367086e57.jpeg">


https://github.com/gruhn/vue-qrcode-reader
https://github.com/cozmo/jsQR

そのため、iOS14.3以降およびAndroid端末においては、LIFFブラウザ内でも
QRコードリーダーや、バーコードリーダは実現可能だと考えられます。


# デモアプリ 
https://liff.line.me/1654102793-9lBWLxEL
※LIFFの仕様上profileスコープを指定していますが、
情報の取得や保存はしていないのでご安心ください。
またherokuなのでしばらくアクセスが無いと起動に時間がかかります。
aws-vaultを用いてAWS SAMローカル実行をIDE上で行う方法。 

## 事前設定

IDEはPyCharmを使用します。
AWS Toolkit for PyCharmのPluginインストール

## アクセスキーによる認証ではなく、aws-vaultにて認証処理

- ~/.aws/config にて[default]にcredential_process追加します。
    ※credential_processとは外部プロセスの標準出力から認証情報を取得する仕組みとのことです。セキュリティ面の考慮が必要であることに留意してください。

- 通常使用しているprofileはそのままで大丈夫です。なければ追記をお願いします。

```
[default]
region = ap-northeast-1
credential_process = aws-vault exec --json default

[profile pycharm-test]
source_profile = default
role_arn = arn:aws:iam::xxxxxxxxxxxxxxxxxxxxxx
region = ap-northeast-1
```

以上で設定完了です。

## おまけ
コマンドによる実行方法

```
sam build [SAMリソース名] && aws-vault exec pycharm-test -- sam local invoke [SAMリソース名]
```


参考
[https://github.com/99designs/aws-vault/blob/master/USAGE.md#using-credential_process](https://github.com/99designs/aws-vault/blob/master/USAGE.md#using-credential_process)
Embedオブジェクトを定義するときに埋め込み要素を指定する。

##最初に
[前回の記事](https://qiita.com/Miyakepp_098/items/3862313764e96a81fa68)に書いていなかった部分があったので簡単に書いておこうと思います。

##Embedオブジェクトを定義するときに埋め込み要素を指定する。
Embedオブジェクトを定義するときに埋め込み要素を指定することができます。
書き方はこんな感じ↓

 ```c#
var embed = new EmbedBuilder()
{
    Title = ("タイトル"),
    Description = ("ここに説明など"),
    Color = (Color.Green),
    ImageUrl=("https://example.com/sample/image.png"),
    ThumbnailUrl=("https://example.com/sample/image.png"),
    Timestamp=(DateTime.Now)
};
```
詳しくは[こちら(Embed APIドキュメント)](https://docs.stillu.cc/api/Discord.Embed.html)を参考にしてください。

##定義したEmbedオブジェクトに追加、または上書きをする。
作成したEmbedオブジェクトに埋め込み要素を追加や上書きをすることができます。

Discord上のサーバーでユーザーが「test1」と送信すると作成したEmbedをメッセージとして返信、
「test2」と送信すると埋め込み要素を追加や上書きをしたEmbedをメッセージとして返信させてみます。


 ```c#
var embed = new EmbedBuilder()
{
    Title = ("タイトル"),
    Description = ("ここに説明など"),
    Color = (Color.Green),
    ImageUrl=("https://example.com/sample/image.png"),
    ThumbnailUrl=("https://example.com/sample/image.png"),
    Timestamp=(DateTime.Now)
};

if (CommandContext == "test1")
{             
    // 作成したEmbedをbotに送信させる。
    await message.Channel.SendMessageAsync("テスト", embed: embed.Build());
}

if (CommandContext == "test2")
{
    //埋め込み要素を作成
    embed.WithTitle("タイトル上書きすることができます");
    embed.WithDescription("同じように説明も上書きできます");
    embed.WithColor(Color.Red);                
    embed.AddField("フィールド1", "値1", true);
    embed.AddField("フィールド2", "値2", true);
    embed.AddField("フィールド3", "値3", true);
    embed.AddField("YouTubeリンク", "[こちら](https://www.youtube.com/) をクリック。");
    embed.AddField("Yahooリンク", "[こちら](https://www.yahoo.co.jp/) をクリック。");
    embed.AddField("Googleリンク", "[こちら](https://www.google.com/) をクリック。");
             
    // 作成したEmbedをbotに送信させる。
    await message.Channel.SendMessageAsync("テスト", embed: embed.Build());
}
```

###実行結果

![実行結果１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/06bd88fb-ccfc-c23a-6f6a-2b6bd715905b.png)

![実行結果2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/2c227a8b-d542-1974-20ce-7408ab379e1d.png)


埋め込み要素の追加や上書きをすることができました。

##最後に
Embedオブジェクトを定義するときに載せておきたい要素を指定しておき、後から追加したい埋め込み要素を追加したり、上書きをするようにしたらいいと思います。

##参考文献
・ [Embed APIドキュメント](https://docs.stillu.cc/api/Discord.Embed.html)
Twitchスタンプ用の画像をリサイズするコード

#概要
Twitchでスタンプを作成する時、
画像をリサイズする作業が手間なので、
簡単にリサイズできるコードを考えました。

#使い方
pythonスクリプトへ画像をドラッグアンドドロップすることで、
スクリプトの保存されているフォルダに、リサイズされた画像が保存されます。


#ソース

```ruby:twitch_resize.py
import sys
from PIL import Image

#ドラッグされたファイルのパスを開く
fp = sys.argv[1]
img = Image.open(fp)

#リサイズ用関数
def resize_save(img,size):
    img = img.resize((size, size))
    img.save(str(size) + ".png")

#サイズを28,56,112に変更する
resize_save(img,28)
resize_save(img,56)
resize_save(img,112)
```
[Ruby]attr_accessorの使い方を簡単に解説してみました(照

# アクセッサーメソッドとは
Rubyではデフォルトだとインスタンス変数にアクセスできないように設定されています。
下記がその例です。

```ruby
class Foo
  @foo = ''
end
 
foo = Foo.new
foo.foo = 'foo'
puts foo.foo #=> NoMethodError
```

ではインスタンスからインスタンス変数にアクセスするには、アクセッサーメソッドを定義する必要がある。
アクセッサーメソッドには2種類あります。

## attr_reader
インスタンス変数にアクセスするためのゲッター(読み取り)としての役割を持つ。

```ruby
class Foo
  attr_reader :foo
  def initialize(word)
    @foo = word
  end
end
 
foo = Foo.new('foo')
puts foo.foo #=> "foo"
```

## attr_writer
インスタンス変数にアクセスするためのセッター(書き込み)としての役割を持つ。

```ruby
class Foo
  attr_reader :foo
  attr_writer :foo

  def initialize(word)
    @foo = word
  end
end
 
foo = Foo.new('foo')
puts foo.foo #=> "foo"

foo.foo = 'bar'
puts foo.foo #=> "bar"
```

# アクセッサーメソッドを定義するメソッド
## attr_accessor
ゲッターとセッターの両方の性質を併せ持つメソッド。

```ruby
class Foo
  attr_accessor :foo

  def initialize(word)
    @foo = word
  end
end
 
foo = Foo.new('foo')
puts foo.foo #=> "foo"

foo.foo = 'bar'
puts foo.foo #=> "bar"
```

# まとめ
デフォルトでは、インスタンスからインスタンス変数へのアクセスが出来ないRubyではアクセッサーメソッドを利用する、といったことが分かれば良いかと思います！
改行をbrタグに変換するやつを作った

# はじめに

最近はブログやSNSが興隆しましたが、やはりHTMLを弄ってサイトを生み出して作品を投稿したいと思う日もあります。
そんな私たちのために作ったお助けツールです。

## 何ができるの

プレーンなテキストをHTMLにそのまま貼り付けられるように変換します。15000文字まで対応しています。それ以上の場合は……ごめんなさい、何度かに分けて変換ください。

「Pタグで囲む」にチェックを入れるとPタグが挿入されます。
「Pタグのクラス」はCSSを使って小説に装飾をしている私のための加工です。

![2021-05-20 21.16.08 bandolu.github.io 65cdae6825c5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315665/0271f380-8e5d-dcbc-007a-2123f3104234.jpeg)
(サイト内引用：[宮沢賢治 よだかの星](https://www.aozora.gr.jp/cards/000081/files/473_42318.html))



## URL
[HTML: Pタグ加工ツール(beta)](https://bandolu.github.io/useful-benri/p-tag.html)


## 参考サイト
[HTMLやWikiの改行タグ自動挿入機](http://www.cost-simulator.com/eco/etc/enter.html)
お世話になっております。

### 上記サイトとの差異
+ `<p>`タグ内の`class`属性自動付与（選択可）
+ 改行タグ除去・置き換えには非対応
imageviewの画像の向きがおかしくなった時にExif使わず直す

結構ハマったのでメモ。

imageviewの画像が回転したりはみ出して表示したりされてしまったので調査。

画像と一緒に保存されているExifフォーマットの中に”Orientation”という属性があり、その値によって表示される向きやサイズが変わってしまうんだそう。
ここまでは比較的すぐわかったが、ハマったのはこの後。
https://qiita.com/murapon/items/1a39746cd4aab7b2c245
↑こういった記事を参考にさせていただきながらOrientation値を取得しようとするが、なぜかすべて 0 になってしまう。

原因はよくわからなかったが、画像表示の命令文を変えたら問題なく表示された。
Orientationに依存しない表示方法なのかもしれない。

ハマった命令文

```kotlin
val inputStream = context.contentResolver.openInputStream(Uri.parse(uri))
            imageView.setImageBitmap(BitmapFactory.decodeStream(inputStream))//bitmapを表示
```

うまくいった命令文（Orientation値に影響されない？）

```kotlin
imageView.setImageURI(Uri.parse(uri))//uriから直接
```

ただ、私の機種固有の問題かもしれないので、原因は探る必要ありか。
原因わかったら追記します。
IBM Watson Studio, Auto AIで人口予測（2024年世界一の人口はあの国に）

　以前ご紹介したAutoAIに時系列データの予測が追加されたようなので使ってみました。
なお過去の記事
 AutoAI使ってCSVデータの一括予測
 https://qiita.com/osonoi/items/54cd435d10985b0bae61
今回参考にした記事（こちらを先に読んでいただくといいかもしれません）
　WiDS Tokyo@IBM 2021開催記念?: AutoAIの時系列予測で今後30日の東京の新型コロナ感染数予測をしてみる
　https://qiita.com/nishikyon/items/c9daa7f21adda5043da0

上記記事との違いは今回の検証は複数項目のデータの予測を行なっているところです。
データはこちらのThe World Bankの各国の人口データを使いました。
https://data.worldbank.org/indicator/SP.POP.TOTL
こちらのデータですがダウンロードすると以下のようなデータになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/e6e3d2c0-1ac2-9337-c009-ff7e3dbce0f8.png)



 これだとAutoAIでは扱いにくいので下のようなフォーマットに変換しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/51489f3d-0d17-ec84-2e73-785ab66335a4.png)
各国のデータが年別に縦に並んでいます。
では早速AutoAIで予測しましょう。
AutoAIの使い方は同じようにこちらが丁寧に書かれているので参考にしてください。
https://qiita.com/nishikyon/items/c9daa7f21adda5043da0
それではAutoAIのモデル作成からやっていきましょう。プロジェクトページを開いたら右上のプロジェクトに追加でAutoAIエクスペリメントを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/a2aedd5f-e85c-7ba4-8fe1-18c3637df208.png)
任意の名前をつけて（ここではWorld Population),作成をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/c61213c1-cb1a-0189-2664-b70c275b0792.png)
上記のcsvデータを読み込みます。そうすると”時系列予測をしますか？と出てくるので”はい”を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/926b6380-de23-13be-4c1c-5d9e0baf2c6c.png)


次に予測する内容を選択します。複数選択できるのですが今回はこの二カ国
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/39befe12-92c7-4c97-3beb-a66935d2831d.png)

その下の予測範囲を１０にします。（１０年後まで予測）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/16e20758-b60b-0461-4a4a-bda478d3446f.png)

あとは”エクスペリメントの実行”をクリックするだけです。
数分まつと完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/a6947d29-30db-cf06-f807-dd48699a748b.png)

一番上のパイプラインをクリックしてみてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/ca866467-1b4e-183d-6460-f7924e614f99.png)
左側のメニューからModel evaluationを選ぶと予測データが見れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/a0a19137-d538-3e42-db21-fdcae9b01394.png)


今回は２カ国予測したので選択することもできます。
元データは２０１９年までなのでStep５人口世界一は２０２４年に人口世界一の座が入れ替わると予想が出ました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/615c344a-0a58-5051-348a-915097363125.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/22d69abc-2829-32e8-6725-ffcb99fa299d.png)
【Vue × Firebase】doc.id と doc.data() をセットにしてデータを取得する方法


#doc.id と doc.data() をセットにしてデータを取得する方法


```html:board.vue
<template>
  <div>
    <Header />
    <Post />
    <div class="post">
      <h2 class="post-tll neon">投稿一覧</h2>
      <div class="post-inner">
        <div class="post-items">
          <List
            v-for="(list, index) in allData"
            :index="index"
            :list="list"
            :key="list.id"
          />
          <!--allDataのデータをlist関数とindex関数にそれぞれ格納-->
        </div>
      </div>
    </div>
  </div>
</template>
```

```js:board.vue
<script>
import firebase from "firebase";
import Header from "@/components/header.vue";
import Post from "@/components/post.vue";
import List from "@/components/list.vue";
export default {
  data() {
    return {
      title: "",
      contents: "",
      image: "",
      allData: [],
    };
  },
  components: {
    Header,
    Post,
    List,
  },
  created() {
    // "posts"コレクションの全ドキュメントを取得。
    firebase
      .firestore()
      .collection("posts")
      .orderBy("time", "desc")
      .limit(16)
      .get()
      .then((snapshot) => {
        snapshot.forEach((doc) => {
          this.allData.push({ ...doc.data(), id: doc.id });
        });
      });
  },
};
</script>
```

以下でリストのデータを取得する際に、doc.data()だけでなく doc.idも覚えさせてあげる。

this.allData.push({ id: doc.id, data: doc.data() }); とする方法もあります。
 allData の各要素は{ id: "hBvXkdTKSzQ4OJ9cmn03", data: { description: "test", genre: "ホラー", ... } }
というものになるので、それに合わせて list.vue 側も変更する必要があるので、

this.allData.push({ ...doc.data(), id: doc.id });として id を上書きしてしまう方法をとってます。

```doc.data()
0:
description: "test"
genre: "ホラー"
id: "hBvXkdTKSzQ4OJ9cmn03"
time: t
title: "test"
uid: "HdMqnGMSCcfxLclnkxyItq3W7S63"

1:
description: "休日一人になるので感動できるドキュメンタリー映画を楽しみたいのでおすすめがあれば教えてほしいです。"
genre: "ドキュメンタリー"
id: "p1qQmAnhdoXPgOy73JsvOdDS8SX2"
time: t
title: "感動するドキュメンタリー映画を楽しみたい。"
uid: "p1qQmAnhdoXPgOy73JsvOdDS8SX2"

2:
description: "日頃のストレスで疲労感がすごいです・・爽快なアクション映画でストレス解消したいのでおすすめを教えてください！"
genre: "アクション"
id: "T3DZdGFB5XhLgCiUyUBUyOlYTbp1"
time: t
title: "爽快なアクション映画でストレス解消したい！"
uid: "T3DZdGFB5XhLgCiUyUBUyOlYTbp1"
```

```js:board.vue
   .then((snapshot) => {
        snapshot.forEach((doc) => {
          this.allData.push({ ...doc.data(), id: doc.id });
        });
```

あとはリストを表示させるlist.vueにて以下のようにしてboard.vueで取得したidを参照して削除しています。

```js:list.vue
 deletePost() {
      firebase
        .firestore()
        .collection("posts")
        .doc(this.list.id)
        .delete();
      this.$swal({
        title: "内容確認",
        text: "投稿を削除しますか？",
        icon: "warning",
        buttons: true,
        dangerMode: true,
      }).then((willDelete) => {
        if (willDelete) {
          this.$swal("投稿を削除しました", {
            icon: "success",
          });
          this.$router.go({
            path: `/board/${this.$route.params.uid}`,
            force: true,
          });
        } else {
          this.$swal("キャンセルしました。");
        }
      });
　　},
```
Nuxt.jsでopenapi-generatorを使って型セーフなAPI呼び出しを実現する

先日axiosをpluginでラッピングする記事を書きましたが、結局のところフロント側でAPIクライアントを手書きするのはリスクがあるので、サーバーサイドから提供されるopenapi.jsonから安全にAPIを呼び出せるようにしようと思います。

https://qiita.com/teracy55/items/f89c98507d8c3793a016

(2021/07/11追記)
JWTによる認証したい場合のやり方について記載しました

https://qiita.com/teracy55/items/47da98910e94fd370054


# openapi-generator呼び出し用のスクリプトを追加

Dockerでopenapi-generatorを使います。
npmでもあるんですが、JREのインストールが別途必要なのでDockerの方が楽です。

ただ、コマンドが長いのでpackage.jsonに追加して`npm run`で実行できるようにしておきます

```package.json
"scripts" {
  ・・・
  "generate:api-client": "docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate -i http://host.docker.internal/api-json -g typescript-axios -o /local/openapi"
}
```

※検証環境は[NestJSでOpenAPI対応のAPIサーバー](https://docs.nestjs.com/openapi/introduction)を立てています
　→https://localhost/api-json でopenapi.jsonが取得できるのでおすすめです
　ローカルにopenapi.json/yml等あれば、`-i`オプションの引数は適宜変更してください


# APIクライアントを作成

上記で追加したスクリプトを実行します

```shell
npm run generate:api-client
```

成功するとopenapiディレクトリが作成されます


# pluginで呼び出せるようにする

以下の対応だけで`this.$api.xxxx()`でAPIが呼び出せます。
※`xxxx`のメソッド名はopenapi.jsonにてoperationIdで指定した名前になります

- declareで`this.$api`に型定義します
- `Vue.prototype.$api = new TodoApi();`でAPIクライアントの実体を定義します

```plugins/api-client.ts
import Vue from 'vue';
import { TodoApi } from '~/openapi';

declare module 'vue/types/vue' {
  interface Vue {
    $api: TodoApi;
  }
}

Vue.prototype.$api = new TodoApi();
```

※クラス名はopenapi.jsonのschemaに依存するので、各自のAPIに合わせて修正してください
東京都が公開しているAPIで毎日コロナ感染者数を取得するコード②

前回公開した東京都が公開しているAPIで毎日コロナ感染数を取得するコードにてうまく1000件以上の件数が取れなかったためその対応を行なった。
コードは以下の通り

```python3:tokyo_corona.py
import requests
import datetime
import pandas as pd
import json

today = datetime.date.today().strftime('%Y-%m-%d')
url = "https://api.data.metro.tokyo.lg.jp/v1/Covid19Patient"

def corona_infection(start_date=today, end_date=today):
    payload ={
        'from': start_date,
        'till': end_date,
        'limit': 1000
    }
    
    res = requests.get(url, params=payload)
    data = res.json()
    
    infect_data = data[0]
    endCursor = data[1]
    
    df = pd.DataFrame(infect_data)
    total = df.shape[0]
    
    while True:
        if endCursor['moreResults'] == 'MORE_RESULTS_AFTER_LIMIT':
            payload['cursor'] = endCursor['endCursor']
            res = requests.get(url, params=payload)
            data = res.json()
            
            infect_data = data[0]
            endCursor = data[1]
            
            df = pd.DataFrame(infect_data)
            over_count = df.shape[0]
            total += over_count
        else:
            break
    return total
```

```:実行方法
corona_infection('2021-05-19','2021-05-19')
```
上記の通りcorona_infection関数の第1引数と第2引数に開始日と終了日を指定する
※ただし引数を省略した場合は当日のデータを取ってくる

これで予定通り感染者の総計を指定して取れるようになったため、
次はmatplotlib等を使ってグラフ化等を行なっていこうと思う。
Socket.IO の使いかた

こちらの記事にあるプログラムを改造してみました。
[Socket.IOを使用して、サーバーからブラウザへデータを送信する](https://armadillo.atmark-techno.com/blog/53/4224)

環境設定

```bash
mkdir socketio-simple
cd socketio-simple
npm init -y
npm i -S express node-cron socket.io
```

ソースファイルの作成

```js:index.js
// ---------------------------------------------------------------
//	index.js
//
//					May/20/2021
// ---------------------------------------------------------------
const app = require('express')()
const http = require('http').Server(app)
const io = require('socket.io')(http)
const cron = require('node-cron')
 
var count = 0

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html')
})
 
http.listen(3000, () => {
  console.log('listening on *:3000')
})
 
io.on('connection', (socket) => {
  console.log('a user connected')
  socket.on('disconnect', () => {
    console.log('user disconnected')
  })
})

 
cron.schedule('*/3 * * * * *', () => {
  const text_aa = 'hello ' + count

  console.log('send ' + text_aa)
  io.emit('message', text_aa)
  count += 1 
})

// ---------------------------------------------------------------
```

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" />
<title>receive messages.</title>
</head>
<body>
    <ul id="messages"></ul>
    <script src="/socket.io/socket.io.js"></script>
    <script src="https://code.jquery.com/jquery-3.6.0.js"></script>
    <script>
      jQuery( () => {
        const socket = io()
        socket.on('message', (msg) => {
          jQuery('#messages').append($('<li>').text(msg))
        })
      })
</script>
<hr />
May/20/2021 PM 20:20<br />
</body>
</html>
```

サーバーの起動

```bash
node index.js
```

ブラウザーで
[http://localhost:3000(http://localhost:3000)
にアクセス
![socket_io_may20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/9ddf0e71-a884-05cc-e808-5615dd17ffb8.png)
cloudwatcheventでAWSコンソールログインを検知する際にハマったこと

#CloudWatchEventのコンソールログインイベントを使う
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659469/cfa49048-a7a8-f967-6859-74917499e96f.png)
CloudWatchEventのコンソールサインインイベントでlambdaをトリガーし、slackに通知しようとした。
しかし、コンソールにログインしてもlambdaが起動せず、cloudwatchevntのruleのメトリクスを見ても、ログインを検知している様子がなかった。

#CloudWatchEventのコンソールイベントの対応リージョンについて

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/EventTypes.html#console_event_type

どうやらus-east-1でのみコンソールログインイベントに対応している模様

#cloudwatcheventのルールとlambdaをus-east-1で作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659469/984272ea-da85-5588-9678-e3b7c98f9ae5.png)