OmniAICreator/Qiita-1.07M huggingface dataset:
SQL Server 2019では行値式が利用できない

SQL Server 2019では行値式(row value constructor)が利用できないようです。

具体的には以下のようなSQLがSyntax Errorになります。

```SQL
SELECT *
FROM t
WHERE (col1, col2) IN (('A', 1), ('B', 2));
```

行値式はベンダー依存の文法ではなく、標準SQL(SQL92)に定められた文法です。その証左としてPostgres13とMySQL8およびOracle Databse 19cで上記のSQLが動作することを確認できました。

Microsoftが用意しているSQL ServerのFeedback forumを見たところ、「行値式をサポートしてほしい」というトピックが2007年ごろにたてられていますが、2021年3月3日現在、UNPLANEDタグが付けられており、少なくとも現時点では行値式がサポート外であることは間違いなさそうです。

https://feedback.azure.com/forums/908035-sql-server/suggestions/32894992-add-support-for-ansi-standard-row-value-constructo

なお行値式がサポート外であることをSQL Serverのリファレンスから見つけることはできませんでした。

https://docs.microsoft.com/ja-jp/sql/sql-server/?view=sql-server-ver15

**環境情報**

- Microsoft SQL Server 2019 (RTM-CU9) (KB5000642) - 15.0.4102.2 (X64)  Jan 25 2021 20:16:12  Copyright (C) 2019 Microsoft Corporation Developer Edition (64-bit) on Linux (Ubuntu 18.04.5 LTS) <X64>
- PostgreSQL 13.2 (Debian 13.2-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
- mysql  Ver 8.0.23 for Linux on x86_64 (MySQL Community Server - GPL)
- Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
RailsチュートリアルでNo application seems to be running here!が出たときの対処法

#起きたエラー
rails serverを起動して、ブラウザ表示する単元で初回はうまくいきました。
しかし、一度Cloud9を閉じて、もう一度同じことをしようとすると、
**No application seems to be running here!**
と表示されてしまい表示されなくなりました。

#解決方法
```
yarn install --check-files
```
を行なってから、

```
$ rails server -b $IP -p $PORT
```
でサーバーを起動する。
【Go言語】特定のTweetにリプライする

###用意するもの
・PC(WindowsでもMacでも)
・Twitter API
・Twitterアカウント

###やったこと
####1.Twitter API準備
色々な方が紹介されていると思いますので、割愛します。

####2.Go言語で書く
処理としては、"ジャイアン"を含む自分の過去ツイートにリプライしています。

```go:main.go
package main

import (
	"fmt"
    "net/url"
	"strings"
	. "fmt"

     "github.com/ChimeraCoder/anaconda"
)

//Twitter API認証用メソッド
func GetTwitterApi() *anaconda.TwitterApi {
	anaconda.SetConsumerKey("API Key")
	anaconda.SetConsumerSecret("API secret Key")
	api := anaconda.NewTwitterApi("token", "token secret")
	return api
}

func main(){
    api := GetTwitterApi() //Twitter認証処理呼び出し
    text := "おれさまがジャイアンだ！" //ツイート内容
    
    v := url.Values{}
	v.Set("count", "10") //取得するツイート数をセット

    x := url.Values{} //リプライするツイート情報を格納する
    
    tweets, err := api.GetUserTimeline(v) //自分のタイムラインを10件取得
	if err != nil {
		panic(err)
	}
   
   SearchText := "ジャイアン"
   
   //取得したツイートに対する処理
    for i, tweet := range tweets {
        //ツイート内容にジャイアンが含まれているか
		if strings.Contains(tweet.FullText, SearchText) {
			id := tweets[i].IdSt
			x.Add("in_reply_to_status_id", id) //xにidを追加
		}
	}
	
    tweet, err := api.PostTweet(text, x)
    if err != nil {
       panic(err)
    }

     fmt.Println("Finish!")
}

```


####3.参考にしたドキュメント

anacondaで実装したい処理があればやはり公式ドキュメント見るのが一番いいと思いました。

https://pkg.go.dev/github.com/chimeracoder/anaconda#section-documentation

次はいいねbot書きます～！
Power Automate Desktopで作ったフローをブラウザのPower Automateでも管理したい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311866/8b78c034-16a2-f5b2-5bf7-4e8bad95a110.png)

## 結論
**OneDriveにあった**！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311866/84e910c5-fbda-a894-f8ba-c942d6ad20c2.png)

結果としていろいろ調べるきっかけになったからよしとする。
~~個人アカウントではできない。
組織アカウントなら作ったフローをクラウドから実行することはできるみたい（未検証）。
※Microsoft Docsに「[デスクトップフローを管理する](https://docs.microsoft.com/ja-jp/power-automate/desktop-flows/manage)」というページがあるが、内容が古く、現時点でデスクトップフローを選択するとアプリを起動する以外の選択肢が選べず、記事にあるような管理画面が見れなかった。~~

## やりたかったこと
Desktopで作ったフローを、別PCでもわざわざ手動で作るとかしたくないので共有する。

~~方法としては、
・フローのファイルを共有する
・OneDriveのように共有する
を考えた。
前者のほうは、ぱっと見でファイルが見当たらないので早々にあきらめ、後者で調べてみた。しかし、今のところ方法がなさそう。
備忘録程度に組織アカウントの場合の方法で途中まで進めることができた範囲を書いておく。~~
## 作成したデスクトップフローがどこに保存されているか
### 構成
デフォルトでインストールすると
`C:\Users\{ユーザ名}\AppData\Local\Microsoft\Power Automate Desktop`
にファイルが保存される（実行ファイルは別のディレクトリ）。

実行にあたっては3つのファイルが使われているみたい。

- Designer\Data\{GUID}.settings
- Cache\cacheFile_xxxxx.bin
- Cache\cacheFileMap.bin

この時点でファイルをコピーして別PCに持っていくのは難しいと判断。

### Designer Settingsファイル
jsonで書かれていて、引数や変数、ブレイクポイントの内容が保存される。

``` sample.json
{
  "Functions": [
    {
      "Breakpoints": [],
      "IsActive": true,
      "IsOpen": true,
      "Name": "Main",
      "PinnedVariables": []
    }
  ],
  "ArgumentVariables": {
    "PinnedVariables": []
  }
}
```


## クラウドからデスクトップフローを実行する手順
### 1. Power Automate Desktopをインストール
これについてはIgnite以降記事がたくさん出てるし、Docsにもあるので省略

https://flow.microsoft.com/ja-jp/desktop/

上記公式サイト内の「無料でダウンロードする」をクリックしたらインストーラを取得できる。
設定については下のDocsを見ながらでOK（記事の内容が少し古いけど、特に問題なし）

https://docs.microsoft.com/ja-jp/power-automate/desktop-flows/setup

### 2. オンプレミスデータゲートウェイをインストール
**※ここからは組織アカウントがないとできない。**

https://docs.microsoft.com/ja-jp/data-integration/gateway/service-gateway-install#download-and-install-a-standard-gateway


上記サイトから**標準ゲートウェイ**をダウンロードし、インストールする。
手順も上記サイトに丁寧に書いてあるので、特筆しない。
※インストールしたあと、ゲートウェイの設定でサインインを求められ、組織アカウントでないIDを入力するとエラーになる。

### 3. ブラウザのPowerAutomateで設定
Docsが正義。知らんけど。

https://docs.microsoft.com/ja-jp/power-automate/desktop-flows/setup#setup-desktop-flows-connections-and-machine-credentials

### 4. おそらく接続できてるはず

## おわりに
~~IgniteでTeamsやPowerPlatformについてかなり押してたので、入れてみたけどDesktopはデバイス別の定期処理を自動化するくらいが関の山か。。。~~
Azure周りの自動化を考えるならブラウザのほうを選んだほうがいい。（ただしコネクタはプレミアムばかり）
ただ、Azure周りを何かしたいならLogicAppsでいいよねと思う。
PowerPlatformの立ち位置が非エンジニアによる簡易ツール・フロー・ビューの作成だし、Excel使ってそれなりにできる人が社内で便利ツールを作る分には十分かも。
AZ-900: Microsoft Azure Fundamentals 合格記

## :sunny:AZ-900: Microsoft Azure Fundamentals 合格記:sunny:

### 公式ページ

- docs.microsoft.com

### AZ-900の学習を終えての所感・オススメポイント

普段、「クラウド」という言葉をよく耳にしていましたが、「クラウド」についての認識が曖昧でした。そのため「クラウド」の学び始めとして、基礎知識の獲得が可能という観点から最適でした。また難易度も高くないため、低負荷で合格に至ることができました。
「クラウド」についての基礎的な知識を手に入れたことで、「クラウド」系の記事を実際に読んでの理解度も確実に変わりました。さらに、今回の学習を通して「Azure」について興味が湧きました。

### 勉強時間

15時間

### 学習に使用した参考書

- 合格対策 Microsoft認定 AZ-900：Microsoft Azure Fundamentals　　
- 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1172718/9cf760d2-3c82-a358-c157-b0fbc4336392.png)

### 試験の勉強の仕方とアドバイス

参考書は今回の試験で必要な知識が凝縮されていて、ページ数も多くないため、参考書の内容のすべてに目を通して理解するべきだと思います。(太字以外の内容の方が大事なことを書いてあるケースがある)
クラウドについての基本知識を持っている人は、Azure特有のサービス名や仕組みを重点的に学習した方いいかもしれないです。
また、参考書についている問題集の難易度は実際の試験よりも簡単に感じたため参考書の問題集を解きなおすよりは、過去問を解き直した方が、時間を効率的に使えると思います。(時間がある場合は参考書の問題を解きなおすことも大事)

### 問題形式

一問一答　　　　　　　　　→　セレクトボックス形式
正誤問題        　　　　  →　ラジオボタン形式(yes,no)
用語と説明の関連付け　　　→　ドラッグ＆ドロップ形式
操作画面　　　　　　　　　→　実際に実機画面がでて対象のボタンをクリック

### 最後にひとこと

僕みたいにコツコツ勉強することが苦手なひとは資格試験を受験することで必要な知識を蓄えられると
感じました。
試験は嫌いですが、Azureのサービスを一通り学ぶことができるので、その点はやっぱり楽しいですね。
次受験する人の参考になればと思います。
inputタグとtextareaタグでのvalueの渡し方について

# 概要
Laravelで編集機能を実装中にDBから取得したデータをviewへ表示しようとした時が
inputタグの場合は取得したデータが表示されているのに、texereaタグでは表示されなかった原因を記載します。

## 問題
なぜかタイトルは取得したデータが取得できているのに本文ではできていなかった。
（DBには確かにデータはあるにも関わらず）

```form.balade.php

<label for="name">タイトル</label>
<input type="text" class="form-control" name="title" value="{{ $memo->title }}">

<label for="text">本文</label>
<textarea class="form-control" rows="10" name="memo" value="{{ $memo->text }}"></textarea>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308656/c5f82972-023d-ba90-15e8-5350c0716dac.png)

## 解決

正しい書き方はこうだ

```form.balade.php

<label for="name">タイトル</label>
<input type="text" class="form-control" name="title" value="{{ $memo->title }}">

<label for="text">本文</label>
<textarea class="form-control" rows="10" name="memo">{{ $memo->memo }}</textarea>
```

## 原因：texereaタグにvalu属性には対応していない
inputタグにはclass属性と同じ箇所にvalue属性も記述することでデータを表示することができるが、textareaタグにはそうではない。
私はなぜかinputタグと同じ要領でやれば表示されると勘違いしていたが、そうではなかったのだ。

```form.balade.php

//間違い
<textarea class="form-control" rows="10" name="memo" value="{{ $memo->text }}">

//正しい
<textarea class="form-control" rows="10" name="memo">{{ $memo->memo }}</textarea>
```

## 追記:JavaScriptの場合は指定できる

@il9437 さんからコメントで教えて頂きました。

JavaScript場合は、textareaにもvalue値を指定できるようです。

```test.js
<textarea id='ta'></textarea>
<script>
  document.getElementById('ta').value = 'test';
</script>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308656/80b0b1bd-3892-ab88-331a-03790e9143b6.png)

以上となります。
もし悩まれている方の解決策になれば幸いです。
【Numpy】BGR画像をRGB画像へ変換

# 目的
画像データのNumpy配列をBGRからRGBに可逆変換する。

Opencvで画像を取り込み、Numpy配列としてデータをコネコネした後、
matplotlibで表示して色がおかしい...となることが多いのでメモ。

# 事前準備
## インポート
必要なライブラリをインポート

```python
import os
import numpy as np
import cv2
import matplotlib.pyplot as plt
```

## 画像の読み込み
今回は画像3枚を読み込む。
ちなみに読み込む画像はこんな感じ
![original.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364219/adf02c73-f0b8-24f1-1653-99ad6ba0a8fa.png)

```python
# 3枚の256x256xRGB画像を読み込むための行列
imgs = np.ndarray((3, 256, 256, 3))

for i, img in enumerate(os.listdir()):
    # .pngファイルのみリードする。
    if os.path.splitext(img)[1] == '.png':
        imgs[i] = cv2.imread(img)
```

# 表示してみる
画像の準備ができたので表示する。

```python
for i in range(len(imgs)):
    plt.subplot(1, 3, i+1)
    plt.title(img_names[i])
    plt.imshow(imgs[i])
plt.show()
```
opencvで読み込んでいるので表示されるのはRBGの画像ではなく、BGRの画像。
![bgr-img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364219/6a3fb78a-be32-4240-4fae-53138a14f1e8.png)

# BGRに変換して表示する
## 変換

```python
rgb_imgs = imgs[:,:,:,::-1]
rgb_imgs.shape # -> (3, 256, 256, 3)
```

## 表示してみる

```python
for i in range(len(rbg_imgs)):
    plt.subplot(1, 3, i+1)
    plt.title(img_names[i])
    plt.imshow(rbg_imgs[i])
plt.show()
```
ちゃんと元のRGB画像にもどせました。
![original.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364219/aa01b0ae-dd31-baa2-b978-2635993a7448.png)

## なにしてる？
「:, :, :, 」は行列のshape、つまりここでは3枚の256x256の部分に該当し、
「::-1」の部分で3チャンネル逆順で取り出している。

```python
rgb_imgs = imgs[:,:,:,::-1]

x = np.array((1,2,3))
x # -> array([1, 2, 3])
x[::-1] # -> array([3, 2, 1])
```
コミットせずに他のブランチで作業したい

# シチュエーション
ある対応をしている時に別の依頼をされることは仕事ではよくあること。
現在行っている対応が、コミットするには中途半端で、
コミットせずに別の依頼の対応を行いたいときのGitのTIPSです。

git stashを使います。

# 手順

①　現在行っている対応（now-branch）を一時退避

```
$ git stash
```

②　別の対応のブランチに切り替え

```
$ git checkout other-branch
```

③ 止めていた対応のブランチに切り替える

```
$ git checkout now-branch
```

④ 一時退避していたものを戻す

```
$ git stash pop
```

#最後に
とても便利なTIPSです。同じようなことで悩んでいる方はぜひ使ってみてください。
Djangoでブログ投稿日"１週間前"のように表示するtimesinceとカスタムテンプレートタグ・フィルターを使った方法

# はじめに

Djangoで作成したブログに投稿してから"1時間前"などの相対時刻表記を実装する方法を解説します。
もし、誤っていたり修正した方が良い箇所があればコメント欄にて指摘して頂けると嬉しいです。

# 環境

python 3.9
django 3.1.6

# 手順

## 1. 相対時刻表記で表示する

日付を呼び出す変数に`timesince`フィルターを付けます。

```html:index.html
<p > {{ blog.posted_date|timesince }}前</p>
```

## 2. 時間単位を１つにする

１の手順を終えた時点で下記のように最大２つの時間単位がカンマ区切りで表示されます。

1 分
1 日, 2 時間
1 週間, 2 日
1 ヶ月, 2 週間
1 年, 2 ヶ月

これをカスタムテンプレートタグ・フィルターを使い１つの時間単位だけが表示されるようにします。
これにはカスタムテンプレートタグ・フィルターを定義する必要があります。

---

Q. カスタムテンプレートタグ・フィルターとは?
A. djangoには様々な組み込みタグ・フィルターが用意されていますが、自分で定義することも出来ます。これをカスタムテンプレートタグ・フィルターと呼びます。

---

導入方法やファイル名は[Django公式ドキュメント](https://docs.djangoproject.com/en/3.1/howto/custom-template-tags/)を
フィルターの構文は[stackoverflow](https://stackoverflow.com/questions/6481788/format-of-timesince-filter)を参考にさせて頂きました。

アプリフォルダ内に`templatetags`フォルダを作成し、
中に`__init__.py`という空のファイルと`[アプリ名]_extras.py`を作成します。
構成は下図の通りです。

```
myproject/blog/
├── __init__.py
├── models.py
├── templatetags
│   ├── __init__.py
│   └── blog_extras.py
└── views.py
````

タグ・フィルターを作成し、

```python:blog_extras.py
from django import template
from django.template.defaultfilters import stringfilter # 文字列を想定したフィルター

register = template.Library()


@register.filter
@stringfilter
def upto(value, delimiter=None):
    return value.split(delimiter)[0] # カンマの前までの部分を返す


upto.is_safe = True # カンマを含むため、自動エスケープを外す必要があります
```

`index.html`で`{% load blog_extras %}`で作成したフィルターを読み込み、
日付を呼び出す変数に作成した`upto:',' `フィルターを付けてください。

```html:index.html
{% load blog_extras %}


<p > {{ blog.posted_date|timesince|upto:',' }}前</p>
```

---
記事中では紹介しておりませんが、下記のサイトも参考にさせて頂きました。
https://medium.com/@kjmczk/django-timesince-176780a9005
https://djangobrothers.com/blogs/custom_template_tags_filters/
Class 'App\Providers\view' not found 解決方法

##エラー：Class 'App\Providers\view' not found
参考書Laravel入門(p.101)の「クロージャ(無名関数)でコンポーザ処理を作る」で、サービスプロバイダを登録しビューコンポーザを利用する為に、/helloにアクセスしたところ、
![スクリーンショット 2021-03-03 22.14.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601015/541646c2-40d5-fe84-359d-beab6108abc0.png)

```
Class 'App\Providers\view' not found
```
エラーが発生！
このエラーは、viewが適切に読み込まれていないという意味なので、
viewを読み込むよう、HelloServiceProvider.phpに下記のuse宣言を追加すればOKです。

```
use Illuminate\Support\Facades\View;
```

![スクリーンショット 2021-03-03 22.14.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601015/603a42e6-fc63-cdf5-ef2a-f975ac16a41a.png)
これで無事ブラウザ表示が確認できました。

参考記事はこちら
https://qiita.com/janet_parker/items/4b63804fe7f8aa3e74c6
https://qiita.com/niiyz/items/5b83ef5255a1ec64d9d6
https://stackoverflow.com/questions/63655253/error-class-app-providers-view-not-found
Laravelでquery parametersで空文字渡ってくるはずが謎にnullが取れる件

# はじめに
こんにちは。楽天モバイルの楽天回線エリアに住んでますが、パートナー回線しか繋がらない筆者です。

さて、Laravel使ってまして、query parametersで空文字来てるはずなのに、**null**になっちゃうことに地味に小一時間悩んだので共有します。

# 結論：こいつの仕業
https://github.com/laravel/laravel/blob/8.x/app/Http/Kernel.php#L23

```php:Kernel.php
protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, // これ
];
```

こいつが**空文字**を**null**に変換しているんです... :sob:

# 地味に小一時間悩んだ話
以下を例にすると、2のときに**null**になっているという恐ろしさ...。
そして、3のときも空文字が入っていたもののそれが**null**に変換されてsetされているので、デフォルト値の1が適用されないという恐ろしさ...。

```php:HomeController.php
public function index(Request $request)
{
    // 1: http://localhost?hoge=1
    $hoge = $request->input('hoge');
    dd($hoge); // 1

    // 2: http://localhost?hoge=
    $hoge = $request->input('hoge');
    dd($hoge); // null

    // 3: http://localhost?hoge=
    $hoge = $request->input('hoge', 1);
    dd($hoge); // null
}
```

# 勝手に変えてほしくない人は
以下コメントアウトしましょう:ok_hand:
あと、ちゃんとコメント書いておきましょう:pray:
https://github.com/laravel/laravel/blob/8.x/app/Http/Kernel.php#L23

# おわりに
便利なのかもしれないのですが、良し悪しあると思います:thinking_face:
何かのお役に立てていれば幸いです。
それでは。
蕎麦・文章

■１、というのも、もう年末が近づいてきましたが日本では「年越しそば」と言って、12月31日大晦日の間もなく年が明けますよーっ、ていう時間に蕎麦を食べる習慣があるんですね。
1）というのも

2）～が～てきましたが～
▽①～が～てきましたが～
　②～が近づいて～
△③～てきましたが～

3）～と言って、～
　解説：https://dictionary.goo.ne.jp/word/%E3%81%A8%E8%A8%80%E3%81%A3%E3%81%A6/

4）大晦日の～っていう～


■２、現代は様々な昔からの風習が失われているとはいえ、この年越しそばを食べる習慣っていうのは割とまだ、若い人の間でも残っているのではないかと思います。
1）～とはいえ、～
　解説：
　https://dictionary.goo.ne.jp/word/%E3%81%A8%E3%81%AF%E8%A8%80%E3%81%88/
　https://dictionary.goo.ne.jp/word/%E3%81%A8%E3%81%AF%E8%A8%80%E3%81%86%E3%82%82%E3%81%AE%E3%81%AE/#jn-159821

2）～というのは～　（っていうのは）
　解説：https://dictionary.goo.ne.jp/word/%E3%81%A8%E8%A8%80%E3%81%86%E3%81%AE%E3%81%AF/
【Node.js】https.getメソッドでJSONをパースする方法

#プログラミング勉強日記
2021年3月3日


#JSON・JSONパースとは
　JSONはJavaScript Object Notationの略で、色々な情報をやり取りするためのデータ形式で、単純な文字列のサーバー間のデータ通信に最適である。JSONの中身はJavaScriptのオブジェクト形式のような構造をしているので、JavaScriptやNode.jsと相性がいい。

　JSONパースは、JSONデータを解析して使用するということである。

#https.getの使い方
　httpsモジュールは、HTTPS通信をNode.jsから簡単に構築できる基本的なモジュールである。

```js:Node.jsでhttps通信を使用できるようにする
var https = require('https');
```

　JSONでイベント情報を取得できるATND APIを使用して、Node.jsから通信を行う通信を行うURLとhttps.getメソッドを次のように記述する。

```js
// urlにANTDのAPIを設定する
var url = 'https://api.atnd.org/events/?keyword_or=javascript&format=json';

https.get(url, function (res) { });
```

　基本的には取得したJSONデータは、コールバック関数のresに格納されるので、on()を使って取得する。


```js
var data = [];
 
https.get(url, function (res) {
  // 取得するデータを配列dataに格納する
  res.on('data', function(chunk) {
 
      data.push(chunk);
 
  }).on('end', function() {
 
      var events   = Buffer.concat(data);
      
      console.log(events);
 
  });
});
```

#https.getメソッドでJSONをパースする方法
　取得したJSONデータはそのままだとNode.jsでは扱いにくいデータになっているので、パースする。具体的には、一般的なオブジェクト形式に変換する。そのために、JSON.parse()メソッドを使う。

```js
https.get(url, function (res) {
  res.on('data', function(chunk) {
    data.push(chunk);
  }).on('end', function() {
 
    var events   = Buffer.concat(data);
    // オブジェクト形式に変換する(パースする)
    var r = JSON.parse(events);
 
    console.log(r);
 
  });
});
```

#参考文献
[Node.jsでhttps.getしてJSONパースする方法【初心者向け】](https://techacademy.jp/magazine/16447)
[【Node.js入門】https.get / requestによるJSONの取得・パース方法まとめ！](https://www.sejuku.net/blog/80176)
Pythonを使ってPDFを目標ファイルサイズ以下に分割する

# はじめに
ある日、巨大なPDFファイルを作成したところ、先方からクラウドストレージが使えないのでメールで送ってくれと言われました。7zipで圧縮して分割して送ったらセキュリティポリシー違反で届きませんでした。

そんな時に30分くらいで作ったコードです。どんぴしゃのものが見つからなかったのでやり方をメモしておきます。いろいろ雑なのはご愛敬。

# コード

実行環境:

- ubuntu 20.04 on WSL1
- Python 3.8.2
- PyPDF2 1.26.0
- pathlib 1.0.1

```{python: split_pdf.py}
import PyPDF2
from pathlib import Path
import os


def split_file(pfin):
    # 目標サイズに応じて変更
    MAX_SIZE = 9000000
    if os.path.getsize(pfin) > MAX_SIZE:
        # PDF読み込み
        r = PyPDF2.PdfFileReader(str(pfin), strict=False)
        lastpage = r.numPages
        # 1ページに達したら終了
        if lastpage == 1: return
        # 真ん中で分割するためのページ
        split = lastpage // 2
        # ファイル名生成 suffixはお好みで
        f1 = Path(f'{pfin.stem}_1.pdf')
        f2 = Path(f'{pfin.stem}_2.pdf')
        w = PyPDF2.PdfFileWriter()
        # 1ページづつwriterに追加
        for i in range(lastpage):
            w.addPage(r.getPage(i))
            # splitに達したらファイル名f1として保存
            if i == split:
                with open(f1, 'wb') as f:
                    w.write(f)
                    del w
                    w = PyPDF2.PdfFileWriter()
        # 最後まで追加したらファイル名f2として保存
        with open(f2, 'wb') as f:
            w.write(f)
            del w
        # f1が目標ファイルサイズを超えていたら再帰的に渡す
        if os.path.getsize(f1) > MAX_SIZE:
            split_file(f1)
        # f2が目標ファイルサイズを超えていたら再帰的に渡す
        if os.path.getsize(f2) > MAX_SIZE:
            split_file(f2)
        # 処理が終わったら元ファイルを削除(残したかったらコメントアウト)
        pfin.unlink()

if __name__ == "__main__":
    # 例としてhoge.pdfを分割したいとする
    split_file(Path('hoge.pdf'))

```

# 補足
- このプログラムを実行すると

```
input:
    hoge.pdf
output:
    hoge_1_1.pdf
    hoge_1_2.pdf
    hoge_2.pdf
```
のように出力されます。最後にお好みでリネームしてください。

- 巨大すぎるファイルを細かく分割するとファイル名が長くなります。ほどほどの深さになるように適切にパラメータを設定してください
- あくまで`MAX_SIZE`を超えない程度に分割したいという思想で作ったプログラムです。`MAX_SIZE`ギリギリに作りたいときは別のやり方をお勧めします
- このやり方は1ページのサイズが`MAX_SIZE`を超えた場合は`MAX_SIZE`以下にできません

# 最後に
最初に受け渡し方法を相談しておきましょう
Psychtoolboxを用いたウインドウ上でボタンを生成する方法

# 前提状況
matlab上での想定

Pychotoolboxを用いて心理実験用、脳波実験用の刺激を制御しなさいと急に言われた人向けです。
Screen関数で制御するウインドウ上にボタンを描画したいときがあると思います。
例えば心理実験なら選択肢が必要だったり。
しかし、Pychotoolboxのリファレンス読んでもScreen関数のボタンに関するオプションは見当たりません
（あったら教えてください）
というわけで今回自作でボタン作ったのでその備忘録

# Screen関数でFrameからFillにする
```matlab:title
Screen('FrameRect', win, color, [rectX rectY rectX+rect_size rectY+rect_size]);
t = Screen('Flip',win,t,1);
while hoge
    [click_c,x,y,buttons] = GetClicks;
        if(x > rectX && y > rectY && rectX > x && rectY > y )
             Screen('FillRect', win, color, [rectX rectY rectX+rect_size rectY+rect_size]);
             t = Screen('Flip',win,t+time,1);
             hoge = 0;
        end
end

```
`FrameRect`で描画した後`FillRect`で描画し直します。座標はそのままに二回目の`Flip`の`time`でボタンが押されてる状態の時間を指定できます。
`GetClicks`の`buttons`はクリックしたときに`true`を返すので別の変数で`while`を抜け出します。
お名前ドットコムで登録したメールサーバーと「nodeemailer」を連携させてみた

最近気温の差が激しい。。。

今日はお名前ドットコムで登録した独自ドメインでメール送信を行いたいと思います。

早速説明に参りたいと思います。

#はじめに#

お名前ドットコムのドメイン登録のやり方は説明致しませんので、まだ登録していない方はご登録してから本記事をご覧ください。

また、メールを送信するためにはレンタルサーバーの登録が必要なので、こちらもご登録してから本記事をご覧ください。

#nodeemailerでメール送信#

##メールアドレス登録##

お名前ドットコムの「レンタルサーバー一覧」から登録したドメインでログインしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/4d800b37-0af9-a45f-3a6f-703081614183.png)

このような画面になると思います。

「メール」をクリック

まずは、「メールアドレスを追加」でメールアドレスを追加してください。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/c440374d-2cc6-c391-0ef7-b04815669133.png)

パスワードは忘れずに！この後使います！！

また、ここで登録したメールアドレスは「info@example.com」として説明していきます。

次に追加したメールアドレスの「詳細」へ。

ここで、受信サーバーやら送信サーバーの情報が表示されます。

この情報をもとに``nodeemailer``でメールを送信していきます。

##transporterの作成##

また、今回``nodeemailer``は「FirebaseFunctions」で行います。

```index.js
const nodemailer = require('nodemailer')

exports.sendContactMail = functions.region('asia-northeast1').https.onCall((data, context) => {
  const mailAddress = `info@example.com`
  const password = `メール作成したときのパスワード`
  const transporter = nodemailer.createTransport({
    pool: true,
    host: 'mail**.onamae.ne.jp',
    port: 465,
    secure: true,
    auth: {
      user: mailAddress,
      pass: password
    }
  })
})
```

##mailOptionsの作成##

次に、誰にメールを送信するか、タイトルは何か、メールの内容を書いていきたいと思います。

```index.js
const nodemailer = require('nodemailer')

exports.sendContactMail = functions.region('asia-northeast1').https.onCall((data, context) => {
  const mailAddress = `info@example.com`
  const password = `メール作成したときのパスワード`
  const transporter = nodemailer.createTransport({
    pool: true,
    host: 'mail**.onamae.ne.jp',
    port: 465,
    secure: true,
    auth: {
      user: mailAddress,
      pass: password
    }
  })

  // ここから追加
  const mailOptions = {
    from: mailAddress,
    to: data.to,
    subject: 'タイトル',
    html: `
      <p>${data.name} 様</p>
      <p>メールを受け取りました</p>
      <p>本メールへの返信によるご質問は承っておりません。</p>
      <p>今後とも何卒よろしくお願いいたします。</p>
      <p>メール送信者より</p>
      `
  }
  
  return transporter.sendMail(mailOptions, (erro, info) => {
    if (erro) {
      return { 
        error: erro.toString(),
        message: 'To send mail is failed'
     }
    }
    return { 
      message: 'To send mail is successed'
    }
  })
})
```

このようにしてメールを送信する関数を作成することができました！

後は呼び出して送信するだけ！！

##メール送信##

```
const sendMailFunc = this.$function.httpsCallable('sendContactMail')

sendMailFunc({
  to: 'akki@gmail.com'
  name: 'akki'
})
```

これで実際にメールが届いたら成功です！

ただし、メールサーバーを作成したばかりだとメールが届かない場合があります。

なので、２日ほど開けてからまた実行して見て下さい！

以上、「お名前ドットコムで登録したメールサーバーと「nodeemailer」を連携させてみた」でした！

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

あと、最近「ココナラ」で環境構築のお手伝いをするサービスを始めました。

気になる方はぜひ一度ご相談ください！

Thank you for reading
【ReactNative】入門者用　おすすめサイト

ReactNativeの使い方を調べたときに、基礎から解説してくれているサイトがなかなか見つからず困ったので、同じような方におすすめのページをご紹介します。

##前提
expoを使用した環境でReactNativeを学ぶためのサイトです。

##おすすめページ
React Native Express
https://www.reactnative.express/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820337/08043909-6861-7b3b-1147-55887c92669a.png)


英語のページなので翻訳サイトを活用して何とか解読していくことになりますが、内容はとても良く、環境構築から始まりReactNativeの特徴解説、レイアウトの整え方、コンポーネント化のやり方など基本的なことはもちろん、画面遷移機能の実装などアプリを作る上で必須となる内容を解説してくれています。
Formオブジェクトを使用した際の単体テスト(FactoryBot)

Formオブジェクトを使用した場合のテストコードを記述した際に、
何度もエラーが出てしまった部分を、忘れないように記録します。

フリマアプリで商品購入機能を実装し、その時のテストコードの一部になります。
以下がその一部です。


```ruby:qiita.rb

   before do
    @user = FactoryBot.create(:user)
    @item = FactoryBot.build(:item)
    @item.image = fixture_file_upload('app/assets/images/test_image.jpeg')
    @item.save
    @order_purchaser = FactoryBot.build(:order_purchaser, user_id: @user.id, item_id: @item.id)

  end

```

@itemの部分でbuildアクションを使用しているのは、その後の記述で画像情報を@itemに追加するためで、
createアクションで定義してしまうとデータが保存され、後からの記述で追加ができなかったためです。


```ruby:qiita.rb

 @order_purchaser = FactoryBot.build(:order_purchaser, user_id: @user.id, item_id: @item.id)

```

今回のフリマアプリで扱った購入者情報（@order_purchaser）は、user、itemに紐づいているため、カッコ内の記述で、user_id、item_idのデータを使用できるようにしています。

今回のコードが必要になったのは、Formオブジェクトを使用しており、モデル間のアソシエーションが記述されておらず、FactoryBotでassociationを組めなかった為です。

不足箇所や間違えているところがあれば、随時更新します。
Fortranでメモリリーク？-どこまでも増えていくメモリ使用量（原因不明）

オブジェクト指向Fortranを使ってコードを書いていたら、使用メモリ量がどんどん増えていくバグに遭遇しました。deallocateしているはずなのにどんどん増えていきます。

# 問題のコード
コードはこんな感じです。

```fortran
program main
    use test
    implicit none
    integer::N
    
    complex(8),allocatable::vec_data(:)

    N = 100000

    allocate(vec_data(N))

    vec_data = pmap(N,wrap)

    contains 

    function wrap(i)
        integer,intent(in)::i
        complex(8)::wrap
        type(type_test),allocatable::testdata
        allocate(testdata)
        testdata = type_test(N)
        wrap = 0d0
        deallocate(testdata)
    end function

end program 
```
ここで、```type_test```というクラスはmodule testで定義されており、

```fortran
module test
    implicit none

    type type_test
        class(type_inner),allocatable::vec
    end type

    interface type_test
        module procedure::init_test
    end interface

    type type_inner
        complex(8),allocatable::x(:)
    end type

    interface type_inner
        module procedure::init_inner
    end interface

    contains 

    type(type_test) function init_test(N) result(testdata)
        integer::N
        allocate(testdata%vec)
        testdata%vec = init_inner(N) 
    end function

    type(type_inner) function init_inner(N) result(vec)
        integer::N,i
        allocate(vec%x(1:N))
        do i=1,N
            vec%x(i) = i
        end do
    end function

    function pmap(N,func) result(vec_data)
        interface 
            function func(i)
                integer,intent(in)::i
                complex(8)::func
            end function
        end interface
        integer,intent(in)::N
        integer::i
        complex(8)::v
        complex(8)::vec_data(N)

        do i=1,N
            vec_data(i) = func(i)
        end do

    end function

end module
```
です。フィールドに```type_inner```というクラスを持ち、そのクラスの中で配列が確保されています。ですので、構造体のフィールドに構造体がありそのフィールドに配列、というものを用意しています。

# 結果
moduleを上に、mainを下に書いてgfortranでコンパイルして実行すると、なぜか使用メモリが増えていきます。```deallocate(testdata)```しているのに、メモリが増えていきます。


- Mac OS 10.14および10.15
- gfortran 9と10

で確認しました。

原因は不明です。

# 追記
@cure_honeyさんのコメントの通り、

```fortran
    type(type_test) function init_test(N) result(testdata)
        integer::N
        type(type_inner) :: dummy
    
        dummy = init_inner(n)
        testdata%vec = dummy
    end function
```
とすることでメモリーリークが消えることが確認できました。

@implicit_none さんの提案のfinalizer処理の追加

```fortran
    type type_test
        class(type_inner),allocatable::vec

        contains
        final :: vec_final ! finalizer
    end type

    subroutine vec_final(this)
        use, intrinsic :: iso_fortran_env
        implicit none
        type(type_test) :: this ! not "class"

        if (allocated(this%vec)) deallocate (this%vec)
    end subroutine vec_final
```
をやってみましたが、問題は解決できませんでした。deallocateを明示的に書いてもやってくれないのは、@cure_honeyさんのおっしゃるclassの具体形がわからないからでしょうか...
実務未経験者が共同開発をして公開するまで

#1.はじめに
オンラインサロンにて共同開発のお知らせがあり、チームリーダーとして開発を行いました。
未経験者が共同開発を終えて学んだこと、気をつける点を書いていきます。
これから共同開発に参加する方の少しでも参考になれば幸いです。

#2.簡単な自己紹介
・学習期間2020年10月〜　
・実務未経験
・転職に向けて学習中

#3成果物について
（トップ画面）
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/953175/1e21b781-744e-8b20-cbae-9b5aec76e5ac.jpeg)

[成果物はこちら]
(https://tenkuehotel-r018.netlify.app/)(架空サイト）


#4.概要
概要
・開発期間は3週間
・週1のミーティング
・完全再現ではなく、納期優先

メンバー構成
・現役エンジニア（メンター）1名
・実務未経験者3名

環境 / 技術
・EJS
・Sass
・Javascript（jQuery)
・Node.js
・記法 Scss
・CSS設計（FLOCSS)
・GitHub（ソースコード管理）


#5.事前準備、環境構築
【実施事項】
・初回ミーティング
・[Trello](https://trello.com/ja)でタスク管理
・実装内容をissueに登録
・チーム内のルール決め
・Node.jsのバージョンを統一
・GitHubでリポジトリ作成
<br>
【実施したこと】
チームリーダーとしてスケジュールの管理、進捗の確認、ミーティングの日程調整を行いました。
また、1日の進捗報告を必ず行うことでメンバー全員で個々の状況を把握することができました。

【学んだこと、気をつけた点】
[Trello](https://trello.com/ja)のガントチャートでタスク管理。ヘッダーやお問い合わせフォーム等の担当ページをチーム全体で管理・共有することでスケジュールを把握して、デプロイから逆算して実装を進めていくことができました。


#6.実装
【実施したこと】
・GitHubでソースコードを管理
・[npm](https://www.npmjs.com/)でパッケージをインストール
・ブランチの作成
・担当部分の実装
・CSS設計：[FLOCSS記法](https://github.com/hiloki/flocss)
<br>
【学んだこと、気をつけた点】
メンバー全員が仕事の合間を縫って開発に取り組んでいたため、質問する時は**何を**、**どのように**、**試したこと**、実装したい内容を詳細に説明するように心がけました。また、わからないことはSlackで質問して記事の共有やコードの確認、修正をして開発を進めていきました。





コードの記述はSassを使用。
[FLOCSS記法](https://github.com/hiloki/flocss)で開発を進める仕様でした。初見でしたが、FLOCSSについての記事を読んだり、メンバーのコードを確認することで書き方を知ることができました。FLOCSSを使用して一番最初に実感したことは、CSSの記述が少なく済むことです。Project、Componentでコードの再利用ができたり、BEMを取り入れることで要素と要素の繋がりがわかりやすくなりコードの可読性が上がります。チーム開発やコードを確認するときには重要な記法だと開発を通じて経験することができました。

→[FLOCSSを使ってCSSファイルを20,000行から9,000行にした話](https://qiita.com/Atsss/items/4f9d98fb1d0546539c09#comments)



ブランチはmasterと担当ページごとにブランチを切り、pushしていきました。個人でブランチを切ることは少ないと思いますが、共同開発でのmasterブランチは本番環境リポジトリになるため、誤ってmasterブランチにpushしてしまうと他のメンバーにも影響してしまうので、gitコマンドを調べたり、git branchで現在の作業ブランチの確認を行い、プルリクをしてからpushするようにしました。結果として、gitコマンドの理解が深まりました。


#7.実装ページ
・TOPページ
・ROOMページ
・AREA GUIDEページ
・ACCESSページ
・CONTACTページ
・Faqページ
・Header
・Footer

【学んだこと、気をつけた点】
開発中に大変だったことは以下の2点です。
**①実装したいコードの書き方がかわからない**
**②エラーの修正**
<br>
**①実装したいコードの書き方がかわからない**
実装を担当したHeader、Footer、ARIA GUIDEページを進めていく中で、JavaScriptの実装では動作がうまくいかないときが何度もありました。そのときに実践していたことは、似たようなサンプルをGoogle検索やQiitaで調べてコードを少し書き換えてみる。それでもうまくいかないときはメンバーやメンターに質問をするようにして実装を進めていきました。
<br>
**②エラーの修正**
エラーコードの内容がわからないときはGoogle翻訳で日本語に変換してから、ネットで検索したり、コードがどこまで動作しているかconsol.logを使い検証ツールで確認作業を行いました。

また、エラーはメモに保存してエラーの内容と解決方法を残しながら進めていき、同じエラーが起きてもメモを見返して対処するようにしていきました。




#8.コードレビューまでの流れ
【実施したこと】
・ローカルリポジトリへ保存
・リモートリポジトリ（現在と同じ作業ブランチ）にプッシュ
・プルリクエスト
・チーム内でコードレビュー
・レビュー結果に基づき修正
・メンターによるコードレビュー
・再度、修正
・リモートリポジトリ（masterブランチ）へプッシュ
<br>
【学んだこと、気をつけた点】
gitコマンドの一連の流れを学習することができました。特に頻繁に使うコマンドやエラーはメモを取るようにして、次回以降に同じ内容のエラーが出てもすぐ対処できるようにしていきました。

また、メンバーやメンターからコードレビューをしていただいたことで、コードを変更する時の注意点や、文章が事前に用意されているときは手打ちせず、コピペをすることだったり、修正依頼が来たときに対処しやすいコードの書き方をご教授いただき見本に近い実装をすることができました。



#9.まとめ

共同開発でデプロイするまでの開発フローやコミュニケーションの取り方を経験することができました。
特にGitHub、Git、コミュニケーションの取り方は重要だと考えます。

GitHubのリモートリポジトからローカルリポジトリにクローン、ブランチを切って作業を進めることや、ローカルリポジトリにコミット、プルリクエストしてissueを閉じるまでの流れを理解すること、Gitはコマンド操作、コミュニーケーションを取るときには詳細を伝えることで開発をうまく進めていけると思います。
<br>

最後にここまで読んでいただきありがとうございました。
bashスクリプトでJSONを組み立ててcurlでPOSTする

# やりたいこと

bashスクリプトで簡単なテストデータをループで作成してcurlでPOSTしたい。

##ハマる

最初は変数にJSONをつっこんでcurlの引数に付けてましたが、ダブルクォートや波括弧が邪魔して思うように行かないのでググる。
stackoverflowで解決方法を見つけました。

ポイントはjson作成を関数にして標準出力経由でコマンドに渡す感じみたいです。
なるほど。

```bash
#!/bin/bash
set -Ceu

generate_post_data() {
    cat << EOS
{
    "Id": ${1},
    "Name": "Name${1}"
}
EOS
}

URL='http://127.0.0.1:3000/hoge'

for i in {1..10} ; do
    /usr/bin/curl --request POST --data "$(generate_post_data ${i})" "${URL}"
done
```

## 参考

https://stackoverflow.com/questions/17029902/using-curl-post-with-variables-defined-in-bash-script-functions
[C#/WPF/prism] ボタン押したときに時間がかかる処理をawaitでやるときに、ボタン連打を防止したい 

もくじ

https://tera1707.com/entry/2022/02/06/144447

**■連打防止関連**
ボタン押したときに時間がかかる処理をawaitでやるときに、ボタン連打を防止したい
→https://qiita.com/tera1707/items/a6f11bd3bf2dbf97dd40
ボタン押したときに時間がかかる処理をawaitでやるときに、ボタン連打を防止したい その2
→https://qiita.com/tera1707/items/946116bf32d0f1203006

# やりたいこと

prism(6.3)を使ったWPFアプリで、下記のような感じでボタンを押したときの処理を書きたい。

```UserControl1の一部.xaml
<Button Content="ボタン" Command="{Binding ButtonCommand}"/>
```

```UserControl1のビューモデル.cs
// コンストラクタ
public UserControl1ViewModel()
{
    this.ButtonCommand = new DelegateCommand(async () =>
    {
        // 時間のかかる処理
        await Task.Delay(500);
    });
}
```

が、上記をそのまま実行して、ボタンを連打すると、「時間のかかる処理」が終わってボタンの処理を抜ける前に何度も「時間のかかる処理」が走ってしまう。

これを、一度ボタンを押したら一連のボタン処理が終わるまでボタンを押せないように(ボタンを押したときの処理が同時に複数回走ってしまわないように)したい。

# 今回やったやり方

`DelegateCommand`が持つ`ObservesProperty`メソッドと`DelegateCommand`の引数が2つある方のコンストラクタの第二引数`canExecuteMethod`を使用する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/029262ce-11d4-f54e-ee52-5b01231cdc02.png)

# サンプル

```cs
// 有効無効を設定するプロパティを一つ作成する
private bool _flag = true;
public bool Flag
{
    get { return this._flag; }
    set { this.SetProperty(ref _flag, value); }
}
　　　・
　　　・
　　　・
// コンストラクタ
public UserControl1ViewModel()
{
    this.ButtonCommand = new DelegateCommand(async() =>
    {
        Flag = false;               // ボタン押下直後に有効無効フラグをOFF(無効)にする
        await Task.Delay(500);      // 時間のかかる処理
        Flag = true;                // 処理終了後に有効無効フラグをON(有効)にする
    },
    () => Flag)                     // CanExecuteでFlagを見て有効無効を制御
    .ObservesProperty(() => Flag);  // ObservesPropertyでFlagを監視するよう指定する
}
```

やったことは言葉で書くと下記のとおり。

- 準備
    - 有効無効を設定するためのプロパティを1つ作成する
- DelegateCommandをnewするときに
    - 第一引数の、ボタンを押したときの処理を書くActionの冒頭でフラグをON、最後でフラグをOFFさせる
    - 第二引数のCanExecuteで、そのフラグを返す(フラグのONOFFで有効無効を制御できるようにする)
    - ObservesPropertyで、Flagが変化したらCanExecuteを実行してくれるようにする

# 備考

時間のかかる処理を実行中に「無効」になっている間、スタイルによってはボタンがグレーアウトしているように見える。
そういうのが気になるという場合は、無効でも見た目が変わらないようにするとか、さらなる逃げをしないといけなくなる可能性がある。

またなにより、そういうことをしたいボタンが一つだったらこのやり方も現実的ではあるが、たくさんこういうボタンが画面上にあったとしたら、似たフラグだらけになりそう。

もっとうまいことできないものか...

# 参考

AsyncReactiveCommandでWPFのお手軽ダブルクリック抑制
https://qiita.com/soi/items/eca0601ad0fc4e401623
ReactivePropertyを使うと、今回やりたいことが簡単にできる様子。
ただ、元々ReactivePropertyを使っていたら使いたいが、今回の私の場合、二度押し防止のため**だけ**にReactivePropertyを入れるというのもどうなのか...
Drupalに登録されている全てのルートを確認する方法

- Develモジュールをインストール

```
composer require drupal/devel
drush en devel
drush cr
```
- `/devel/routes`にアクセス
![スクリーンショット 2021-03-03 21.24.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/645c57fe-17d8-47e2-87e5-038e7f3500aa.png)
AWS Step Functions とは

## 勉強前イメージ

全然イメージつかん・・
そういうサービスがあるってことだけは知ってる

## 調査

### AWS Step Functions とは

分散アプリケーションやマイクロサービスをステートマシンと呼ばれる仕組みで設定や管理の自動化ができます。
AWSコンソール上では各サービスをコンポーネントとしてワークフローという形式で可視化することが出来ます。
また、各種実行履歴などもログから追うことも出来ます。
Step Functionsを使用することで、タスクで構成される複雑なワークフローを簡単に定義できます

### ステートマシンのイメージ

例えば自販機だと3つのプロセスに分割できます。

- 入金待ち
	- ユーザが購入に十分な金額を投入するまで待機。
	- 入金され次第、次のプロセスに進む
- ジュースの選択
	- ユーザがジュースの選択を行うまで待機。
	- 選択され次第、次のプロセスに進む。
- おつり・ジュースの出力

このフローをStep Functionsでは `ステートマシン` と呼び、
人間による操作を必要とするような長時間実行されたり・半自動化されたワークフローを作成することもできます。

### AWS Step Functions の費用

Step Functionsは状態の遷移ごとに課金が発生。
毎月4000回までは無料だが、4000回を超えると課金が発生。
リージョンごとに費用は異なります。

### コンソール上で確認

- ステートマシンの作成

![1Step Functions Management Console - Google Chrome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/9f12e112-41aa-a274-aa22-bb02132b0a8f.png)


- ステートマシンを定義する

試しに作るだけなので、標準のタイプで進めます。

![2Step Functions Management Console - Google Chrome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/0d99a8ba-5552-e31b-0ca2-2cc57597b265.png)


ワークフローを定義して、それを可視化(右の図)することが出来ます。

![3Step Functions Management Console - Google Chrome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/3384c360-b61b-74dd-32be-f3148d036761.png)


- 詳細を指定

ステートマシン名やアクセス制御など、デフォルトで進め、記載できるとステートマシンの作成を行います。

![4Step Functions Management Console - Google Chrome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/b9c76998-5e39-d6e1-6ff7-4e1586a37cf9.png)


- 作成されました

![5Step Functions Management Console - Google Chrome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/ff906e77-b064-1bd4-3ec2-c70ba2e3e62f.png)


- ステートマシンを実行する

![6Step Functions Management Console - Google Chrome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/3b215a31-5dcc-a676-5ba2-d1c3862b6da7.png)


- 実行

デフォルト値で実行します

![7Step Functions Management Console - Google Chrome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/52c52092-9c63-39c6-eab7-546bb1aeff4a.png)


- 結果を確認

グラフインスペクター で、各ステップごとの実行結果も確認することが出来ます。

![8Step Functions Management Console - Google Chrome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/6aa6340b-7a19-3789-f423-5b5afccd1eea.png)


## 勉強後イメージ

今まで全部自動で・・・みたいなのはよくAWSのサービスでもあったけど、
途中で人間が入力しないといけないという場合も使うことができるのか！

## 参考

- [AWS Step Functions をゼロからざっくり理解する](https://dev.classmethod.jp/articles/aws-step-functions-for-beginner/)
- [入門 AWS Step Functions](https://hironsan.hatenablog.com/entry/introduction-to-aws-step-functions)
SQLiteでファイルを使用してテーブル作成する方法(ターミナル/Python)

Pythonの標準ライブラリにはSQLiteと呼ばれるデータベースが付属しており、別途データベースを用意しなくとも簡単にプロトタイプなどを作成することができます。

# 環境
- Mac OS Big Sur 11.2.1
- Python 3.9.1
- SQLite 3.32.3

# 使い方
SQLiteはPythonの標準ライブラリに含まれているため、Pythonが使用できる状態であればすぐに使用することができます。

```terminal
$ sqlite3 <DATABASE_FILE>
sqlite>
```

## ターミナルでファイルを使用する
仮に単語カードのデータを保存するようなテーブルを考えます。必要なのはIDと質問、答えだと思いますので以下のようなSQLを用意します。

```schema.sql
DROP TABLE IF EXISTS card;

CREATE TABLE card (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  question TEXT,
  answer TEXT
);
```

これを直接実行する場合、sqliteに接続した上で`.read`コマンドを実行します。

```terminal
sqlite> .read schema.sql
```

## Pythonでファイルを使用する
上記ターミナルと同じファイルを使用する場合、以下のようにファイルを読み込んだ上で`executescript`を実行します。

```python
import sqlite3

conn = sqlite3.connect('<DATABASE_FILE>')
cursor = conn.cursor()
    
with open('./schema.sql') as f:
    cursor.executescript(f.read())
```

## テーブル確認
テーブルの情報は`sqlite_master`テーブルに保存されています。よって正常に実行できていれば、以下の通り先ほどのテーブル情報が表示されるはずです。

```terminal
$ sqlite3 <DATABASE_FILE>
sqlite> select * from sqlite_master;
table|card|card|2|CREATE TABLE card (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  question TEXT,
  answer TEXT
)
table|sqlite_sequence|sqlite_sequence|3|CREATE TABLE sqlite_sequence(name,seq)
```
LINE NotifyからのLINE通知を改行する方法【Python/LINE Notify(API)】



キノコードさんの動画↓を見ながら、LINE Notifyを使ってみました。

https://youtu.be/FuCJd0ftVsU

動画内では「通知を改行する方法」には触れられていなかったので、自分用にメモ。

Lineで通知する文章を改行したい場合、「\n」を入れると改行できます。
つまり、通常のpythonと同じように書けば大丈夫みたいです。

#例

通知したい文章に対して…

```python:line_notify_test.py
send_contents = f'今日は{strftime}({day_of_the_week[weekday]})です。'
```

改行したい部分に「\n」を入れる。

```python:line_notify_test.py
send_contents = f'\n今日は\n{strftime}({day_of_the_week[weekday]})です。'
```
結果
![Line改行.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486558/debbd770-e844-cd03-968e-6e87319adb28.jpeg)

(念のために…上のコードだけで自動でLINEに通知は来ません。
APIを使ってLINEに通知を送る方法を知りたい方は、冒頭紹介した動画を見てください。)

#ちなみに…

f文字列（フォーマット文字列）…つまり、f''で囲うやつじゃなくて、普通(?)に書く場合。

「シングルクォーテーションではなく、ダブルクォーテーションで囲まないと改行してくれない」みたいな記事を見ました。
ただ、やってみると僕はどちらでもできました。

```python:line_notify_test.py
send_contents = "\n今日は\n" + str(strftime) + "(" + str(day_of_the_week[weekday]) + ")です。"
```


```python:line_notify_test.py
send_contents = '\n今日は\n' + str(strftime) + '(' + str(day_of_the_week[weekday]) + ')です。'
```
昔はできなかったのかもしれません。
プログラミング超入門(２)〜GO言語〜

#データ型について

変数に入れるデータの種類のことを指し、**①数値型**(number「ナンバー」型)**②文字列型**(string「ストリング」型) **③ブール型**(Boolean「ブーリアン」型)に分けデータを代入する際に、Go言語ではデータ型として指定する**静的型付け言語**が用いられる。逆に、変数にデータを入れる際にデータを指定する必要がなく自動的に判断してくれるプログラミング言語を**動的型付け言語**といいます。

#数値型には、整数型と小数点型がある

|数値型|説明|
|:-----:|:------:|
|int|コンピューターで表せるだけの範囲の整数値を表す（int8 int32等、-127〜127）|
|float64|６４ビットのコンピューターで少数値を表す(３２ビットの場合はfloat32型)|

```ints.go
package main

import "fmt"

func main() {
    var a int
    a = 4
    b := 6    
    fmt.Println(2 * a)
    fmt.Println(b - a)
}
```
[前回までの応用](https://qiita.com/ume-bar/items/3f92fbb223e93bd5df3f)で、データ型を自動判別させ変数を定義して値を代入し実行してみます。
###・実行結果

```
./ints

8
2
```
---------------------------------------
##変数自身の値に処理を加える
変数は「変」数という名前から伝わるように、一度値を代入したあとでも別の値を再代入することができ、前にあった変数の値は新しく上書きされて消されます。例えば、`a := 100` の下に`a = 50`　と代入すれば、aの値は50になります。
##変数自身の値にを処理して、新しく代入する
変数の元の値を処理してその変数に代入し直す事ができます。

```
                a = 50　(↓のaには値50が用いられる)
(新しい値80が代入→)a = a + 30
```
代入演算子の右側では、元の値が使われたうえで処理が行われます。そして、代入演算子の左側の変数に新しい演算子が代入される仕組みです。更に、`a = a + 30` は `a += 30`のように省略して書くことができます。
**省略形には、加算代入(+=)、減算代入(-=)、乗算代入(*=)、除算代入(/=)、剰余代入(%=)があります。**

```ints.go
package main

import "fmt"

func main() {
    a := 4
    b := 6    
    fmt.Println(2 * a)
    fmt.Println(b - a)
    
    a = 50
    b += a 
    fmt.Println(a)
    fmt.Println(b)
}
```

変数自身の値を処理して再代入する処理を追記させて実行してみます。
###・実行結果

```
./ints

8
2
50
56
```

##float64型の宣言を省略した書き方
`a := 4.0`

```floats.go
package main

import "fmt"

func main() {
    a := 4    
    fmt.Println(2 * a)
    fmt.Println(2.0 * a) 
    fmt.Println(2.2 * a)
}
```
floats.goというファイルを作り、数値の型を確認してみます。
###・実行結果

```
./floats

8
8
8.8
```

![スクリーンショット 2021-03-01 20.39.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/c136a5b1-ffd3-71c2-a4ea-8de6d7482b96.png)
変数 **a** には**int型**、変数 **b** には**float64型**が渡されている場合、データ型の異なる値同士で減算するとエラーが乗じます。Go言語を始めとしたプログラミング言語の多くは、データ型が異なる数値同士での計算を禁じています。また、Go言語のデータ型は、**reflect（リフレクト）**のパッケージのTypeOf（タイプオフ）を使用して確認することが出来ます。

```nums.go
package main

import ("fmt" "reflect")

func main() {
    num01 := 123
    var num02 int = 123456789
    num03 := 1.23
    var num04 int = 1.23456789    
    
    fmt.Println(reflect.TypeOf(num01))
    fmt.Println(reflect.TypeOf(num02))
    fmt.Println(reflect.TypeOf(num03))
    fmt.Println(reflect.TypeOf(num04))
}
```
###・実行結果

```
./nums

int
int
float64
float64
```

[←前回の記事](https://qiita.com/ume-bar/items/3f92fbb223e93bd5df3f)　[次の記事へ→](https://qiita.com/ume-bar/items/8c14f2c6372e425fe3ed)
Could not open input file: artisan解決方法

##エラー：Could not open input file: artisan
Laravelでサービスプロバイダを作成する為に、

```
$ php artisan make:provider HelloServiceProvider
```
上記のコマンドをターミナルで叩くと、

```
Could not open input file: artisan
```
というエラーが発生します。

このコマンドは、arisanファイルのあるディレクトリにいないと実行できない為、
エラーが発生するということは、コマンドを実行するカレントディレクトリが間違っている可能性があります。

現在どこのディレクトリで実行しているか確認しましょう。
![スクリーンショット 2021-03-03 20.59.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601015/96813d58-f0e2-189d-26d1-e6862772ea0d.png)
こちらの場合だと、

```
$cd docker-laravel-demo/backend
```
これで、artisanファイルのあるbackendディレクトリまで移動し、

```
$ php artisan make:provider HelloServiceProvider
```

サービスプロバイダを作成するコマンドを叩くと、

```
Controller created successfully.
```
こちらが表示され、Providersディレクトリ内にHelloServiceProviderファイルが作成されます。
ファシリテーション困った時メモ

## このページの目的
スクラム開発でファシリテータをしていて気づいたことのメモ(一旦自分用)
良さげなメモが溜まったらパターンランゲージとして発表したいなぁ。。。
量が多くなりそうなので会議前の準備は別途。

## Good
### 負の感情は捨てよう
* 状況：打合せのファシリテータ
* 課題：効率よく会議を進めたい
* アクション：喜怒哀楽の怒と哀は出さない
* 結果：参加者がリラックスするようになった気がする。心理的安全は重要

### 気負わない
* 状況：打合せのファシリテータ
* 課題：効率よく会議を進めたい
* アクション：打合せを進めなきゃという意思を持たない。（やれることはやるけど）進むかどうかは参加者次第
* 結果：ファシリテータが焦ることがなくなる。その方が上手くいく気がする

### 知ってる人でもアイスブレイク
* 状況：計画会議のファシリテータ
* 課題：効率よく会議を進めたい
* アクション：最初にアイスブレイクを実施
* 結果：発言量が多くなった

### 集中力維持は60分まで
* 状況：計画会議のファシリテータ
* 課題：効率よく会議を進めたい
* アクション：タイムキーパを設置し60分計測
* 結果：集中力が続いて議論が活性化

### 一旦休息してみる
* 状況：計画会議のファシリテータ。打合せ時間も長引いており集中力低下気味
* 課題：結論が出ない
* アクション：とりあえず5分休む
* 結果：休んで頭がスッキリして発言量が増え、結論に早く辿り着けた

### 細かく時間区切る
* 状況：計画会議のファシリテータ
* 課題：意見がどこまでも発散し結論に向かわない
* アクション：発散、収束フェーズを分け、それぞれタイマを設定(発散時間、収束時間＝1:2くらい)
* 結果：参加者が時間に収まるように忖度してくれる

### とりあえずなんか書いてみる
* 状況：計画会議のファシリテータ。議論内容を完全に理解できない状態で沈黙が多い
* 課題：発言量が少ない
* アクション：自分の理解を書いていく
* 結果：間違いがあれば指摘してくれたりで議論が活性化された。付いていけてなかったメンバも理解が追いつく

### たまには流れに任せる
* 状況：打合せのファシリテータ。議論が活性化しているがやや脱線気味
* 課題：効率よく会議を進めたい
* アクション：時間決めて様子見してみる
* 結果：自然に脱線から戻ることもあるが、戻らないこともある:sweat_smile:

### ファシリテータと書記は分けよう
* 状況：打合せのファシリテータ
* 課題：スムーズに打合せが進まない
* アクション：書記担当を別に指名する
* 結果：多くの意見を引き出し進行することに集中できた。議事担当から曖昧な点も指摘が上がるメリットもある

### 一番理解度の低いであろう参加者に話を振る
* 状況：打合せでのファシリテータ
* 課題：発言量が少ない
* アクション：一番理解度の低いであろう参加者に名指しで意見を求める
* 結果：答えらても答えられなくても他のメンバの意見が活性化した。発言のハードルが下がる？

### アウトカムを再確認
* 状況：計画会議のファシリテータ
* 課題：結論に辿りつけず煮詰まる
* アクション：バックログの目的を改めて読んでみる
* 結果：アウトカムが再認識され価値に繋がらないアイデアは除外された

### Why、What、How
* 状況：計画会議のファシリテータ。意見は出るが結論に向かってる気がしない
* 課題：結論に向かってる気がしない
* アクション：Why、What、Howの順に整理して共有する
* 結果：Howが適切？って議論になった。Howに意識向きすぎてWhyを見失う開発者は結構多い

### 失敗はチームのせい
* 状況：不具合の振り返り
* 課題：ポジティブに振り返りたい
* アクション：失敗はチームのせいって最初に宣言する
* 結果：参加者が本音ベースで語るようになった

### 誰の意見かを気にしない
* 状況：不具合の振り返り
* 課題：ポジティブに振り返りたい
* アクション：匿名性を確保し意見収集（Miroで全員Guestだと良い）。その後も記載者を誰かを特定しない
* 結果：多くの意見が出た。なんでこういう意見が出たかを皆で議論するのでそこから発展した

### 意見を出すことが正義
* 状況：計画会議のファシリテータ
* 課題：多くの意見を出したい
* アクション：意見を出すことを褒める、参加者同士の否定も止める
* 結果：発言量が増えた気がする

### チームの結論を尊重する
* 状況：打合せでのファシリテータ。チームの出した結論が自分の考えてたものと違う
* 課題：この場合の課題ってなんだろ？？？ SMの不安？
* アクション：チームの結論を受け入れる
* 結果：その後のアクションにメンバが責任持って対応してくれる。たとえ失敗してもメンバに気付きが多いので長い目で見るとプラス

### リアクションは大きく
* 状況：計画会議のファシリテータ
* 課題：多くの意見を出したい
* アクション：共感とか賞賛の反応を意識的に実施。うなずくのも多め
* 結果：発言量が増えた気がする

### コメントスクリーン
* 状況：打合せのファシリテータ
* 課題：多くの意見を出したい
* アクション：コメントスクリーンを採用
* 結果：コメントスクリーンでの意見も出た。タイミングとか気にせず言える？匿名性があるから？

## Bad
### 自分の意見を発するのはダメ
* 状況：打合せでのファシリテータ
* 課題：意見が少ない
* アクション：自分の意見を言ってみる
* 結果：SMの言うことは正しいという先入観があるのか、それに従う流れになり意見が出なかった。SMは意見言うべきではなさそう

### 最初にテックリードに話を振るのもダメ
* 状況：打合せでのファシリテータ
* 課題：意見が少ない
* アクション：最初にテックリードに話を振る
* 結果：上と同様テックリードの言うことは正しいという先入観があり意見が出なかった。最初に振らない方がいい

### 切りの良いところまで進めようと思っちゃダメ
* 状況：計画会議のファシリテータ。時間も長引いており集中力低下気味。
* 課題：結論が出ない
* アクション：切りの良いとこまで頑張って進めようとする
* 結果：あとちょっとのはずなのに進まなかった。集中力切れてる状態で結論出すのは効率悪い

## 今後解決したい課題
##### テックリードの意見に従いすぎる
##### 参加者間で発言数の偏りが大きい
検証ツールなどを使った情報の改竄を防ぐControllerの実装

## なぜ必要か
商品を出品するフリマアプリのようなサービスを例に考えます。
あるユーザーが商品を出品後、その商品の情報を編集したり、商品を削除したりする場合、そうした操作をするのは当然、商品を出品した当事者であるべきです。
そこでビューファイルの実装においては、以下のようにif文を用いた条件分岐により、商品を出品したユーザーと現在ログイン中のユーザーが一致した場合に限り、「編集」や「削除」のボタンを表示するようにしています。

## Viewファイルの実装
```
 <% if current_user.id == @item.user_id %>
      <%= link_to "商品の編集", edit_item_path(@item.id), method: :get, class: "item-red-btn" %>
      <p class="or-text">or</p>
      <%= link_to "削除", item_path(@item.id), method: :delete, class:"item-destroy" %>
   <% end %>　
```
しかし、これだけですと、検証ツールなどを使用して、第3者が勝手に商品の情報の編集をできてしまう状態です。
そこで、Controller側でも制限を設ける記述をすることで、そうしたリスクを排除します。

## Controllerの実装
```
 @item = Item.find(params[:id])
  unless @item.user_id == current_user.id
　  redirect_to root_path
  end
```
このように、unlessメソッドを使い、その商品を投稿したユーザーと現在ログインしているユーザーが一致しない場合、ログイン画面に遷移する実装をすれば検証ツールによる編集も防げます。
ちなみに、current_userメソッドを使っているのは、ユーザー管理機能を実装するにあたり事前にdeviseを導入しているためです。

## まとめ
検証ツールを用いた悪意ある情報編集などを防ぐためにも、Controllerにおいて頻繁に使われる記述のようなので、これを機に覚えておきたいと思います。
webpack-dev-serverにドメインでアクセスする

## やりたいこと

Dockerコンテナ上で`npm run serve`したときに任意のドメインでアクセスしたい

## 設定

nginx-proxyを利用して設定したドメインで各コンテナにアクセスできる状態にする。

nginx-proxyを利用した環境の構築は[ここ](https://kahoo.blog/docker-php-mysql-developing-environment/)等を参考にしてください。

docker-compose.ymlはこんな感じ

```docker-compose.yml
version: '3.5'

services:
  node:
    build: ./infra/node
    environment:
      VIRTUAL_HOST: "任意のドメイン"
      HTTPS_METHOD: "noredirect"
    expose:
      - 3000
    networks:
      - app-network
      - local-network
    command: sh -c "npm run serve"

networks:
  app-network:
    name: app-network
  local-network:
    external: true
    name: local-network
```

`vue.config.js`に設定を記述します。

```vue.config.js
module.exports = {
  devServer: {
    host: '0.0.0.0',
    port: 3000,
    disableHostCheck: true, 
    watchOptions: {
      poll: true
  }
}
```

以上の設定で`npm run serve`した後に任意のドメインでアクセスが可能になります。

## 所感
今回やりたいことを実現するにあたって正直理解できていないところがたくさんある(host: '0.0.0.0'やnginx-proxyの仕組み等)ので、一つ一つ調べて理解して使うことが大事だと痛感しました。

## 参考
nginx-proxyを利用した環境の構築
[【超便利】DockerでPHPローカル開発環境の最強構築方法](https://kahoo.blog/docker-php-mysql-developing-environment/)
個人開発でデザインするときに目を通すべきサイト+素材集

# はじめに
個人開発をする際に、毎回デザインどうしようかで結構悩んでしまいます。
そんな時に目を通すべきサイトのまとめがあったらうれしいと思ったので、紹介します。

あと、普段使っている素材集も紹介します。

# デザインの基本を学べるサイト

## PhotoshopVIP
https://photoshopvip.net/design-basic-rule

## chot.design
https://chot.design/

## Cocoda
https://cocoda.design/contents

# 参考にできるWebページを紹介しているサイト
## MUUUUU.ORG
https://muuuuu.org/

## SANKOU!
https://sankoudesign.com/

## RWDJP
https://responsive-jp.com/

## Design Valley
https://designvalley.club/

## SaaS landing page examples
https://saaslandingpage.com/

# CSSスニペットを紹介しているサイト
## CSS-TRICKS
https://css-tricks.com/

## サルワカ
https://saruwakakun.com/html-css/reference

## wweb.dev
https://wweb.dev/resources/css-separator-generator

## gradienta
https://gradienta.io/

## haikei
https://haikei.app/

## softr
https://www.softr.io/tools/svg-wave-generator

## Toolbox
http://santhoshsivan.com/glass.html

# カラーパレットを紹介しているサイト
## Colorsinspo
https://colorsinspo.com/

## Curls
https://www.culrs.com/#/?ref=appydev

## Color Hunt
https://colorhunt.co/?ref=appydev

## Nord
https://www.nordtheme.com/?ref=appydev

## HueSnap
https://www.huesnap.com/?ref=appydev

# イラストを紹介しているサイト
## Joe Schmoe
https://joeschmoe.io/

## ITG
https://app.itg.digital/

## LooseDrawing
https://loosedrawing.com/

## avataaars
https://avataaars.com/?ref=appydev

## Blush
https://blush.design/ja?ref=appydev

## CraftWork
https://error404.fun/?ref=appydev

## Humaaans
https://www.humaaans.com/?ref=appydev

## Storyset
https://storyset.com/?ref=appydev

## OUCH!
https://icons8.com/illustrations?ref=appydev

## OpenDoodles
https://generator.opendoodles.com/?ref=appydev

## unDraw
https://undraw.co/?ref=appydev

## flaticon
https://www.flaticon.com/pattern/?ref=appydev

## icons8
https://icons8.com/?ref=appydev

# Webページに導入できるアニメーションを紹介しているサイト
## LottieFiles
https://lottiefiles.com/featured

## Drawer
https://drawer.design/?ref=appydev

# (おまけ)CSSスタイル集や、UIに関する情報を発信しているサイト
## UX MILK
https://uxmilk.jp/
## コリス
https://coliss.com/

## WebNAUT
https://webnaut.jp/

## bagelee
https://bagelee.com/

## creive
https://creive.me/design/

# まとめ

紹介した素材集には、OSSとして公開してくださっているところも数多くあります。
ライセンスには気を付けて、ルールを守って使わせてもらいましょう！
【Vue.js】v-modelを使った双方向データバインディングについて


v-model、双方向データバインディングについて少しだけまとめ。

## データバインディングとは？
データを結びつけること

## 双方向とは？
vueの記述を変えると、HTML側も書き変わるような仕組み。

##簡単なコード
```vue
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

<div id="app">
<input type="text" v-model="message"> 
  <h1>{{message}}</h1>
</div>
```
```ruby
new Vue({
	el: '#app',
  data: {
  	message: 'がんばれ'
  }
})
```

これで下のような表示になるが、ここで文字を入力すると、リアルタイムでｈ１タグで囲んでいるmessageの文字も変わる。

![スクリーンショット 2021-03-03 20.36.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628093/3be36550-ded2-426c-0d6d-f3b26f2fc9e6.png)

これがv-model。