OmniAICreator/Qiita-1.07M huggingface dataset:
CSSだけ使って、どんな画面サイズでも縦横比と余白を維持したいんじゃ


# やりたいこと

* 画面サイズによってメインコンテンツの大きさを変えたいけど縦横比は維持したい。
* メインコンテンツは画面から少しマージンを取る。画面からはみ出さないようにする。
* JavaScript で画面のサイズを計算してやってもいいけど動きがモッサリだから CSS だけでやりたい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215631/0623b2b5-6de7-8033-1199-8fc28f61e7c5.png)



# やってみた

* 縦と横の比は `4:3`
* 画面サイズの `95%` を超えないようにする

この条件で実装してみました。
![responsible.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215631/713b1389-fc21-4db8-741c-416ffa586855.gif)



# 実装方法

`min` と `vh` `vw` を組み合わせたらスッキリ書けました。実質２行。

```html
<div class="content">
  <div class="box"></div>
</div>
```

```css
/* メインコンテンツ */
.box {
  background: #eee;
  width: min(95vw, 95vh * 0.75);  /* 横幅の計算 */
  height: min(95vh, 95vw / 0.75); /* 縦幅の計算 */ 
}

/* ※中央寄せしたいだけなので、ここから先は本題と関係ない */
html,body, .content {
  width: 100%;
  height: 100%;
  background: #263238;
}
.content {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}
```

## 説明

場合わけして考えてみます。

まずタテに長い画面の場合は・・・こうなってほしいですよね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215631/55756304-b2c3-2f1d-a9ee-af436f628f67.png)																		
																				
次にヨコに長い画面の場合は・・・こう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215631/907e96a2-97a1-ae81-1689-f129c3ec5ce2.png)


`min` 関数を使うと、引数のうち小さい方を採用してくれるので、画面幅の95%を超えないように抑えてくれます。

```css
.box {
  background: #eee;
  width: min(95vw, 95vh * 0.75);
  height: min(95vh, 95vw / 0.75);
}
```

`95%` ではなく、かならず画面端から `20px` 離したいというときはこう書きます。

```css
.box {
  background: #eee;
  width: min(100vw - 20px, (100vh - 20px) * 0.75);
  height: min(100vh - 20px, (100vw - 20px) / 0.75);
}
```

## 補足

メディアクエリでタテ長の場合とヨコ長の場合で分けて書いても構いません。
(こっちのほうがわかりやすいですね)

```css
/* 縦長の場合 */
@media screen and (orientation: portrait) {
  .box {
    width: 95vw;
    height: calc(95vw / 0.75);
  }
}
/* 横長の場合 */
@media screen and (orientation: landscape) {
  .box {
    width: calc(95vh * 0.75);
    height: 95vh;
  }
}
```
【Laravel８】Eloquentのupsert()について

## Eloquentのupsert()って？
これです
https://readouble.com/laravel/8.x/ja/eloquent.html#upserts

```
Flight::upsert([
    ['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99],
    ['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150]
], ['departure', 'destination'], ['price']);
```
同じEloquentでupsertするメソッドだとupdateOrCreate()とかありますね。

比較的最近（8.10以降？）実装されたものらしく、またドキュメント読んだだけではイマイチ使い方がわからなかったので、自分で検証したことも含め備忘録がてら書き残しておこうと思います。

upsert()についてもですが、Laravel自体始めて日が浅いため何か間違ってる箇所があればご指摘をお願いします。

## 環境
PHP：7.4
Laravel：8.13.0

## 解説
### 基本
```
$data = [
    ['id' => 1,'departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99],
    ['id' => 2,'departure' => 'Chicago', 'destination' => 'New York', 'price' => 150]
]
Flight::upsert($data, ['id'], ['price']);
```

ドキュメントの例に少し手を加えたものです。
第一引数に更新したい内容、第二引数にプライマリーキー、第三引数に更新したいカラムをそれぞれ配列で渡します。第二引数はSQLServer以外必須だそうです。

個人的にドキュメント読んでわかりにくいと思ったのが第二引数に指定したカラムを第一引数の配列に含めるかどうか。
**結論から言うと含めます**。ないと確定でInsertになってしまいます。

例ではidカラムをプライマリーキーとして想定しているので第二引数に`['id']`と書いていますが、第一引数の$dataという配列にもidカラムの値を入れています。
第二引数でプライマリーキーさえ指定すれば第一引数の配列に含めなくてもいい感じにInsertかUpdateか判断してくれるのかと思ったのですが、そんなに甘くはありませんでした。

ただこの仕様、**複合主キーテーブルに対してUpsertするときすごく便利です。**
イマドキ複合主キー？と思われそうですが、仕事で複合主キーのテーブルを取り扱う機会がすごく多いのでupsert()は救世主でした。
（今まではクエリビルダー使ったり自前でメソッド作ったりしてました）

### 第三引数について

第三引数にはupdate時更新したいカラムを配列で指定します。先ほどの例だとpriceカラムのみ更新します。
未指定の場合は第一引数で指定したすべてのデータを更新するようです。Modelのguardedで更新しないカラムを指定していれば除外してくれるのかな？（未確認）

ただし **空の配列を指定した場合は更新日時カラム（updated_at）のみ更新します。**
なので第一引数にいくら値を指定しても更新されません。

```
$data = [
    ['id' => 1,'departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99],
    ['id' => 2,'departure' => 'Chicago', 'destination' => 'New York', 'price' => 150]
]

//$dataに含まれるModelのguardedで指定したカラム以外を更新
Flight::upsert($data, ['id']);  

//updated_atのみ更新。$dataで指定したdepartureやpriceは更新されない
Flight::upsert($data, ['id'],[]);  
```

## 参考
https://readouble.com/laravel/8.x/ja/eloquent.html#upserts
https://stackoverflow.com/questions/66198271/laravel-8-eloquent-upsert-inserting-new-records
CSSについて

CSSでタグを指定することがあると思います。

例えば、li{

}
みたいな感じです。しかし、これではファイル内のすべての<li>にcssが適応されてしまいますので、

.class名 li　{
}

とすると該当するclass名の<li>にのみ適応されます。
React Native + Expo CLI 環境構築 Mac編

## Node.jsのインストール
Node.jsのバージョン管理をするためnodebrewをインストールする

```
brew install nodebrew
```

インストール可能なnode.jsのバージョンを確認
nodebrew ls-remote

指定のバージョンのインストール

```
nodebrew install (version番号)
```

最新バージョンのインストール

```
nodebrew install latest
```

※最新バージョンインストール時に、No such file or directoryのエラーが出た。実際にディレクトリがなかったので作成し、再度インストールすることで対応。

## expoのインストール

```
npm i -g expo-cli
```

続いて、プロジェクト作成

```
expo init (プロジェクト名)
```

## 注意
インストール後に環境パスが通っていない場合、「node -v」がnode not foundと出るのでパスを通す必要がある。

```
echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.zprofile
```


## 実行
Xcodeのシミュレータを使うので、Xcodeがインストール済みが前提です。

```
expo start
```

以下のように表示されればOK
![afdwe.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035014/e101e66c-76e2-dc29-6a19-6743c588afc8.jpeg)
chrome 広告 右下　でググると出てきたのですが

[chrome 広告 右下 - Google 検索 ](https://www.google.com/search?q=chrome+%E5%BA%83%E5%91%8A+%E5%8F%B3%E4%B8%8B&oq=chrome+%E5%BA%83%E5%91%8A&aqs=chrome.3.69i57j0l9.9343j0j7&sourceid=chrome&ie=UTF-8)

【Google Chrome】右下に出る広告を無効にする方法
Google Chromeの右上のボタンから、設定を選択します。 プライバシーとセキュリティ項目の、「サイトの設定」を選択します。 続いて、「通知」を選択します。 通知を無効にします。2020/03/05

との事……

なんでこんな深い所に設定しているのだろうか……(^_^;)
Xcodeを起動する

```shell
xed .
```

Xcodeプロジェクトをターミナルから起動する場合、
以下優先度に応じて表示する。
[macos \- How to run xcode from terminal? \- Stack Overflow](https://stackoverflow.com/questions/19639914/how-to-run-xcode-from-terminal/52739630#52739630)

1. the folder, if it's a Package (Xcode 11+)
2. xcworkspace
3. xcodeproj
4. playground
「メモ」pandas：日時でｄｆ

#カレンダー的データフレームの作製

日付別に日足の経年のデータをまとめる。

```python:sample.py

import pandas as pd
import datetime

day_df = pd.read_pickle("C:/Users/aaaa/Desktop/USDJPY_M1/USDJPY_D1.pickle")

x=pd.DataFrame(columns=['A','B'])#Aに日付、Bに値を入れる予定
for a in range(1,13):
    if a==(1|3|5|7|8|10|12):#3131日月
        for b in range(1,32):
            f = day_df[(day_df.index.month==a) & (day_df.index.day==b)]
            g = f['close']-f['open']
            h= g[g>0].size/g.size
            tmp_se = pd.Series( [ datetime.datetime(2024,a,b),h ], index=x.columns )
            x = x.append(tmp_se, ignore_index=True)
    elif a ==2:#2月は今回は28日とした
        for b in range(1,29):
            f = day_df[(day_df.index.month==a) & (day_df.index.day==b)]
            g = f['close']-f['open']
            h= g[g>0].size/g.size
            tmp_se = pd.Series( [ datetime.datetime(2024,a,b),h ], index=x.columns )
            x = x.append(tmp_se, ignore_index=True)
    else:
        for b in range(1,31):#30日月
            f = day_df[(day_df.index.month==a) & (day_df.index.day==b)]
            g = f['close']-f['open']
            h= g[g>0].size/g.size
            tmp_se = pd.Series( [ datetime.datetime(2024,a,b),h ], index=x.columns )
            x = x.append(tmp_se, ignore_index=True)
x=x.set_index('A')
```
#未達成なこと
今回はカレンダ―作成に年のデータが必要だったので2024年を適当に取ったがこれをなくしたい。クラスを作るか2次元配列で表すのが早そう。ただそうすると日時計算はできなくなるのが難点。まあいらないかな・・・

#参考

[Pythonのdatetimeで日付や時間と文字列を変換（strftime, strptime）](https://note.nkmk.me/python-datetime-usage/)
[Python pandas で動的に行を追加するTips（プログラマ向け）](https://qiita.com/567000/items/d8a29bb7404f68d90dd4))
win32oleを使って、Excelファイルを開く


## 環境
ruby 2.4.1p111
Windows10 Pro

## はじめに

恐らく、殆どの企業では、Excel文化がまだまだ根強かったりする事でしょう。ファイルサーバーにExcelファイルを置いて、共有使用しているケースも普通だと思います。他の人が開いていたら、更新ができないというジレンマがあったり、自分が長時間開いていたら、気まずかったりもします。そこで、ファイルサーバーにあるExcelファイルを参照する場合は、ローカル環境にコピーしてきて、そこで、ゆっくり参照するといったやり方を時々します。この一連の作業をRubyで自動化させてみました。
やっている事は、ファイルサーバーにExcelファイルをローカル環境にコピーして、指定したシートを開くといった流れになります。Rubyソースは、バッチでコマンドを打って流しますが、割とサックリ観があって便利だったりします。
そのRubyの作り方の解説です。Excelを扱うgemはいくつかあるようですが、win32oleを利用しました。gemの名前から想像できるように、このgemは、Windows上でしか利用できない事になります。

## 解説

PATH変数にはExcelファイルのコピー元とコピー先のパスを指定します。FILE変数には、Excelファイルのファイル名を指定します。ローカル環境にはリネームしてコピーするようにしています。SHEET変数には、初期表示したいExcelのシート名を指定します。

Excel VBA定数のロードします。（おまじないのように）

```
module Excel; end
```

Excelオブジェクト生成します。

```
excel = WIN32OLE.new('Excel.Application')
```
表示可にして、メッセージは非表示にします。

```
excel.visible = true
excel.displayAlerts = false 
```
Excelを起動します。

```
WIN32OLE.const_load(excel, Excel)
```
ExcelをOpenします。

```
book = excel.Workbooks.Open("#{PATH_L}#{FILE_L}")
```
指定したシートをアクティブにします。（上記の記述はググれば、情報は出てくるのですが、ここのやり方がググってもネットであまり流れてないようだったので、参考になるかな？）

```
sheet = book.sheets("#{SHEET}")
sheet.Activate
```

## 全ソース

```ruby
require "fileutils"
require 'win32ole'

PATH_S = '\\\192.168.19.12\share\\'
PATH_L = 'D:\\'
FILE_S = 'エクセルファイル.xlsx'
FILE_L = 'エクセルファイル_ローカル.xlsx'
SHEET = 'ユーザー一覧'

module Excel; end

def excel_init?

    begin
        excel = WIN32OLE.new('Excel.Application')
        excel.visible = true
        excel.displayAlerts = false
        WIN32OLE.const_load(excel, Excel)

        puts    "#{PATH_L}#{FILE_L}"
        book = excel.Workbooks.Open("#{PATH_L}#{FILE_L}")
        
        sheet = book.sheets("#{SHEET}")
        sheet.Activate
        true

    rescue => e
        puts "例外エラーが発生しました => " + e.message.to_s
        false
    end
end

def get_file?

    unless File.exist?("#{PATH_S}#{FILE_S}")
        false
    else
        FileUtils.cp("#{PATH_S}#{FILE_S}","#{PATH_L}#{FILE_L}")
        true
    end
    
end

unless get_file?
    puts "コピー元ファイルが存在しません。"
else
    puts "コピーOK"
end

puts "正常終了しました。" if excel_init?
exit
```

C'est fini  :no_mouth:
VBAの基本操作（ワークブック）

VBAの初心者向けに基本操作方法（ワークブック）を紹介していきたいと思います。


```:ワークブック新規作成
Set wb = Workbooks.Add
```


```:ワークブックの保存
Dim Path As String, WHS As Variant          '変数PathとWHSを設定
Set WSH = CreateObject("Wscript.Shell")     'WHSオブジェクトを設定
Path = WSH.SpecialFolders("Desktop") & "\"  'デスクトップへパスを設定
ActiveWorkbook.SaveAs Path & "foobar.xlsx"  'foobar.xlsxという名前で保存
Set WSH = Nothing                           'オブジェクトの設定を空にする
```
デスクトップへの保存方法はいくつかある為、上手くいか無い場合は調べて見ていろんなやり方を試してみると良いでしょう。


```:ワークブックを開く
Workbooks.Open "C:\Users\Owner\Desktop\foobar.xlsx"
```
今回はデスクトップにあるfoobar.xlsxを開いています。


```:foobarのブックのA1の操作中のブックのA1コピーする
    Dim Wb1, Wb2
    Set Wb1 = ThisWorkbook 'このブック
    Set Wb2 = Workbooks("foobar.xlsx") '別ブック
    
    Wb2.Worksheets("Sheet1").Range("A1").Copy Wb1.Worksheets("Sheet1").Range("A1")
```


```:ワークブックを閉じる
ThisWorkbook.Close

'ワークブックを閉じる（保存の有無を確認される）
ActiveWorkbook.Close True

'ワークブックを保存せずに閉じる
ActiveWorkbook.Close SaveChanges:=False
```

　今回は変数やオブジェクトと言った新しい概念がが入ってきました。恐らく初心者の方が最初につまづく部分だと思います。変数やオブジェクトはなかなか理解出来無いかもしれませんが、どんな言語でもコードを書く上で最も大事な要素なのできちんと理解しておきましょう。

変数解説　▶︎　https://wa3.i-3-i.info/word1603.html
オブジェクト解説　▶︎　https://wa3.i-3-i.info/word1119.html
React初心者から初心者に送る初歩的知識

私はバリバリのReact初心者（初めて2週間）ですが、そんな私でも簡単なタイピングゲームを作れました
https://hobbypro.github.io/typing/
そんな初心者な私が、これからReactを始める人に「Reactやるならこの知識覚えといたほうがいいよ」を共有したいと思います。


# React始めるなら覚えておくべき知識
###心構え編
#### ほぼjavascript・jQueryという認識でOK
Reactを勉強し始めると、やれSPAだ仮想DOMがあーだこーだと小難しい話が出てきます。
しかし、最初のうちはそんなことを覚えなくても、結構テキトーに使えます。
あまり難しいことは考えず「js使える場面ならReactも使える」くらいの認識でOKです。

###環境構築編
#### webpackとbabelの背景と用途を知っておく
残念ながらReactを使うには、環境構築の知識も必要らしいです。
それがwebpackとbabelです。
nodeでこれらを含めたツールをインストールして、せっせとReact開発用の環境を作る必要があります。


#### 環境構築が面倒な場合は、CDNだけでもできるらしい
自分はこれ試してないのですが、CDNでもできるらしいです。
環境構築とか面倒クセェって人は、こちらを採用しても良いのかも。
[【React.js】CDNを使ってReactを手軽に試す(React 入門) | Code Database](https://code-database.com/knowledges/106)


### 初っ端編
#### まずはReact公式のチュートリアルをやってみるのがオススメ
様々な入門記事があると思いますが、Reactの使い方を簡単に知りたいなら公式チュートリアルが一番な気がします。
実際、抑えておくべき利用法をめちゃくちゃ丁寧に解説してくれてます。
また、実際に手を動かして検証できるページも用意してくれているので、頭への定着度が抜群です。
チュートリアルを始めるために環境構築をするなんていうこともありません。ブラウザひとつあればReactを体験できます。
初心者の方々はまずこのチュートリアルを行うことをオススメします
[チュートリアル：React の導入 – React](https://ja.reactjs.org/tutorial/tutorial.html)


### Tips編
#### 「state」と「props」は厚めに理解する
この2つはReactのキモです。
チュートリアルをやるとわかると思うのですが、ありとあらゆる場面でstateとpropsが登場します。
なのでこれらの背景や用途はサボらずに理解すると良いです。
[state とライフサイクル – React](https://ja.reactjs.org/docs/state-and-lifecycle.html)
[コンポーネントと props – React](https://ja.reactjs.org/docs/components-and-props.html)

#### とりあえずメソッドはbindする
```jsx:example.jsx
<div onClick={this.handlerClick.bind(this)}>
</div>
```
このようにメソッド？をコンポーネントなどに渡す時にはbindしておくと安全です。
逆にbindしないことで、うまく動かないということが結構おきます。
もっと詳しく知りたい方は、他の記事で調べちゃってください。
[コンポーネントに関数を渡す – React](https://ja.reactjs.org/docs/faq-functions.html)

#### key属性を理解しとく
私的にReact１番のハマりポイントです。
ちゃんと理解してないと、「stateを更新してるのに表示が全く変わらない！！」なんてことが発生します。
実は私もあまり正確に理解しておらず、ぽいkey属性を与えて乗り越えてまして...
皆さんは、エラーで時間を無駄にしないよう、ちゃんと理解しちゃってください！
[https://ja.reactjs.org/docs/reconciliation.html](差分検出処理 – React)

#### ReactでCSSを使いたいなら、一旦脳死でstyled-componentsを採用
Reactコンポーネントを装飾する方法は結構あるそうです。
[Reactのコンポーネントのスタイリングをどうやるか - Qiita](https://qiita.com/lightnet328/items/218eb1c4a347302cc340)
ただ自分が調べた感じ「styled-components」を使ってる方々が多い印象を受けました。
なので脳死でstyled-componentsを利用してみましょう。
使い方もそんなに複雑ではないです。
[styled-components](https://styled-components.com/)


# まとめ
以上、React初心者からReact初心者に送る初歩的知識たちでした！
他にも覚えておくといい知識はたくさんありますが、やりながら調べれば間に合うと思います。
gitコマンドの使い方(チーム開発)

#GitとGitHubとは

コマンドの使い方に入る前に、まずはGitとGitHubについて説明します

##Gitとは
wikipediaから引用
>Gitは、プログラムのソースコードなどの変更履歴を記録・追跡するための分散型バージョン管理システムである。

##GitHubとは
Github公式から引用
>GitHubは、ユーザのみなさんからヒントを得て作成された開発プラットフォームです。オープンソースプロジェクトやビジネスユースまで、GitHub上にソースコードをホスティングすることで数百万人もの他の開発者と一緒にコードのレビューを行ったり、プロジェクトの管理をしながら、ソフトウェアの開発を行うことができます。

##結論
語弊を恐れずに記載するならば、GitとGitHubの関係は以下のようなものです。

- Git<br>
  **ローカル環境**でソースコードのバックアップを取れるもの
- GitHub<br>
  **リモート環境**でGitで取ったバックアップをアップロードすることで、そのソースコードの共有ができるもの

**ローカル**とは、「自分のパソコン内で」という意味なのでネットに繋がっていない**オフライン環境でも利用することができます**。
**リモート**とは、「ネット上の」という意味なのでネットに繋がっている**オンライン環境でのみ利用することができます**。

- **ブランチ**<br>
  チーム開発を想定した場合に、同じプロジェクトのソースコードを複数人で編集していくことになります。その際に一人が作業しているときに他の人が作業できないという状況では困ってしまいます。そのため、ブランチという形でそのプロジェクトを複製(ブランチを切る)し、それを編集し、後から合体(マージ)させることで複数人での作業を可能にしています。


#チーム開発で使うコード一覧
チーム開発の場合は、個人での開発と違いブランチをきったり、ソースコードをマージする作業が増えます。

[個人開発はこちら](https://qiita.com/kunrenyouAcount/items/a39c683916213beb80be)

###既存のソースコードを使う場合

- GitHubからソースコードをクローンする(ダウンロード)

```termina:クローン
git clone [URLを入力]
```


###リモート上のブランチの一覧を取得

- リモート上に存在しているブランチの一覧を取得
→この作業をすることで新規作成したリモートブランチなどもブランチ一覧の表示コマンドを打ったときに反映されるようになります。

```terminal:フェッチ
git fetch -p
```
※「-p」は省略することもできますが、リモート上で閉じたブランチであってもコンソール側にはその情報は自動で反映されないため、削除された情報も含めてリモートの最新情報を取得する場合にはつけます。


###ブランチの一覧の表示

- ブランチの一覧の表示(ローカルのみ)

```terminal:ブランチの一覧の表示(ローカルのみ)
git branch
```

- ブランチの一覧の表示(フェッチで取得したリモートブランチも含めて取得)<br>
→リモート上のブランチは使用しているツールによっては文字色がローカルとは違う色で表示されます。

```terminal:ブランチの一覧の表示(フェッチで取得したリモートブランチも含めて取得)
git branch -a
```


###リモートブランチの内容をローカルに反映させる

- マージする<br>
→フェッチ作業は変更内容を取得しただけで、まだローカルのブランチにその内容が適用されていないため、適用する作業が必要になります。

```terminal:マージ
git merge origin/[ブランチ名]
```


###リモートの内容を直接ローカルに反映させる

- リモートにある情報をローカルにすぐに反映させる<br>
→フェッチ+マージにあたるコマンドです

```terminal:プル
git pull
```

###ローカルブランチの新規作成

- ローカル上に新規で名前をつけてブランチを作成します<br>
→特別な場合がない限り、リモートで作成したブランチ名とローカルで作成するブランチ名は同じものにした方が良いです。違う名前にしていると、コマンド操作を行うときにリモートの名前を毎回指定しなくてはいけなくなり面倒です。<br>

```terminal:ローカルブランチの新規作成
git branch '[ブランチ名]'
```
※「'」を省略することもできますが、先頭に記号がきた時などに正常にコマンドが適用されないことがあるので、つけた方が間違いないです。


###作業ブランチの移動

- ローカルで今作業しているブランチを移動<br>
→デフォルトではmainブランチが選択されているため、移動したいブランチ名を入力して、移動してからソースコードを書き始めます

```terminal:作業ブランチの移動
git checkout '[ブランチ名]'
```
※「'」を省略することもできますが、先頭に記号がきた時などに正常にコマンドが適用されないことがあるので、つけた方が間違いないです。


###ローカルで編集した作業内容のコミット

- 編集した変更をステージング<br>
→変更箇所の確認

```terminal:ステージング
git add .
```

- ステージングした内容をコミットする<br>
→ローカルにバックアップを作成する

```termina:コミット
git commit -m '[コメントの内容]'
```


###コミットした内容をプッシュする

- コミットした内容をプッシュする<br>
→コミットで作成したローカルにあるバックアップをアップロード

```terminal:プッシュ
git push
```
[カラム重複によるerror]Mysql2::Error: Duplicate column name ''カラム名"

#概要
### ターミナルで「rails db:migrate」を入力した際に起きたerror。インターネットで調べてみるとカラムが重複していることが原因だった。


#原因
### db/migrateを調べるとemailカラムが重複していた

```ruby:qiita.rb
t.string :email,              null: false, default: ""
t.string :email,              null: false, default: ""
```
#改善方法
### rails db:rollbackでマイグレーションファイルをdownさせる  
###→重複している内容を削除し、データを１つにする  
###→rails db:migrateする。以上のことでerrorが改善された。
PHP Notice: Array to string conversion エラー

###PHP Notice: Array to string conversion エラーとは
「配列が文字列に変換」されてしまうという趣旨の警告。
配列は、文字列化されると強制的にArrayという文字列に変換されてしまう。

原因別に異なる対処が必要となる。
参考にさせていただいたサイトに各種の方法が記載されていた。
今回は、配列を文字列に変換する関数「 implode() 」で解決できた。

```
implode( 配列 )
```




###参考サイト
https://marycore.jp/prog/php/notice-array-to-string-conversion/

https://webkaru.net/php/function-implode/
Node-RED チュートリアル はじめてのフロー (フローのインポートとエクスポート)

[Node-RED チュートリアル はじめてのフロー](https://qiita.com/nogayama/items/179484abebe748252d64) の続きです。フローのインポートとエクスポートの部分だけ別の記事にしました。

## チュートリアル

1. Shift を押しながら、ノードを一つクリックするとすべて選択される。

2. 全て選択した状態で書き出しを呼び出す。
    ![image-20210416154105309.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/a23a7e36-d36a-90a6-3cea-65f8b5384b09.png)
    ![image-20210416154654804.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/038e044b-fb8f-0671-b3f1-e4a945b4a661.png)

3. 一度、全てのノードとワイヤを削除する。

5. Json をコピーしてクリップボードに入れる。
    
    ```json
    [{"id":"874de768.ca95a8","type":"inject","z":"8de137de.1b2808","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":180,"wires":[["eb2b563d.c4b698"]]},{"id":"eb2b563d.c4b698","type":"function","z":"8de137de.1b2808","name":"","func":"// ペイロードから日付オブジェクトを生成\nvar date = new Date(msg.payload);\n// 日付文字列に変換して再度ペイロードをセット\nmsg.payload = date.toString();\n// 次のノードへmsgオブジェクトを返す\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":370,"y":200,"wires":[["b53b3bb3.063e98"]]},{"id":"b53b3bb3.063e98","type":"debug","z":"8de137de.1b2808","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":580,"y":220,"wires":[]}]
    ```

6. 読み込みダイアログを開いてコピペする。
    ![image-20210416153737865.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/447dd47a-611a-f2e2-9c58-d1209ec78965.png)

7. フローをスタート
    ![image-20210416154851580.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/f1ca4ce4-2224-0c86-bca8-03bdff08e915.png)
CentOS7でclangとlibc++を動かす


## 概要


- libc++を動かすにはlibc++abiが必要。
- CentOS7向けのlibc++abiパッケージは出回っていない
- libc++abiのgcc互換実装としてlibsupc++が存在する。
- clangのコンパイルオプションに`stdlib=libc++ -lc++ -lsupc++`をつければ動く

## モチベーション

昨日書いた記事[ある環境でstd::chronoが遅い](https://qiita.com/pochman/items/997fcf9b04afe574a0b4)で、CentOS7+devtoolsetの環境で`std::chrono`が遅いというのを取り扱った。原因は何となく`libstdc++`の問題(というより配布されているdevtoolsetのビルドの問題)ということが分かった。その時のコメントで`libc++`ならどうかというものがあって試したいが、どうやらCentOS7ではclang + libc++を動かすのはかなり大変な様子。

試行錯誤したら動いたのでレポート。

## 手順

前提として、CentOS7にdevtoolset-9がインストール済みであるとする。

ここから、は以下の手順でclang, llvm, libc++(libcxx)をインスコ。末尾の`--disableplugin=show-leaves`は私の環境ではrpmがぶっ壊れているのか必須[^1]。


```
rpm -i https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install clang llvm-devel libcxx libcxx-devel --disableplugin=show-leaves
```

ここでclangでコンパイルを試みてもリンクエラーになる。


```
clang -O2 -std=c++17 -stdlib=libc++ test_timer_stdonly.cpp
/opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/../../../../bin/ld: /tmp/test_timer_stdonly-d0d52b.o: in function `main':
test_timer_stdonly.cpp:(.text+0x11): undefined reference to `std::__1::chrono::steady_clock::now()'
/opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/../../../../bin/ld: test_timer_stdonly.cpp:(.text+0x19): undefined reference to `std::__1::chrono::steady_clock::now()'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
```

webではいろいろな情報が出回っているが、**libc++を動かすにはlibc++abiが必要**ということ。しかし、コンパイルオプションに`-lc++abi`を入れるなどの処方箋は殆どがUbuntu環境のもの。CentOS7にはそもそもlibc++abiがパッケージとして出回っていない。

しかし、本の虫[^2]によれば**libc++abiのgcc実装としてlibsupc++が存在する**そうだ。これはdevtoolset-9に入っている。試行錯誤の結果、次のようにコンパイル時に`-lc++ -lsupc++`の二つをつければ動いた。


```
clang -O2 -std=c++17 -stdlib=libc++ -lc++ -lsupc++ test_timer_stdonly.cpp
```

## Intel icpxとlibc++の併用

OneAPIとなった最近のIntel コンパイラの場合は、gccだけでなくclang相当の実装もある。

- icpc : g++ 相当
- icpx : clang++相当

なので、icpxでもlibc++が動かせる。その場合には`-lc++ -lsupc++`ではごまかせないが、シンボリックリンクでごまかせる。


```
#管理者権限で
cd /opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/;
ln -s libsupc++.a libc++abi.a 

#以下は一般ユーザで
icpx -O2 -std=c++17 -stdlib=libc++ test_timer_stdonly.cpp
```

## さいごに

それで結局CentOS7環境でのlibc++のstd::chronoは速いのか遅いのかというと、、、[こちら](https://qiita.com/pochman/items/997fcf9b04afe574a0b4)

[^1]: [yum updateに失敗したのでshow-leavesを無効化](https://qiita.com/pochman/items/60c367a764284af727df)
[^2]: [本の虫: GNU/Linuxでlibc++をビルドする方法](https://cpplover.blogspot.com/2013/04/gnulinuxlibc.html)
UnityでPostProcessを追加して発光(Bloom)させる方法

# Global Volumeの追加
- Hierarchyで右クリックして Volume -> Global Volume

# Profileの作成
- Global Volumeを選択
- Profile -> "New"を押す
- "Add Override"ボタンを押す -> "Bloom"を選択

# IntensityをONする
- Bloom -> Intensity : ONして値を変更する
python2.7 と python3.7 と ctypes

python2.7 で動いていたプログラムを python3.7 で動かそうとすると時々変なことが起こる。

### ctypes
C言語で記述されたライブラリを他の言語から利用したいことがある。
python では ctypes というモジュールが標準で用意されており、これを利用すればC言語のソースコードに手を加えることなく python から利用することができる。

### 問題
例えば、以下のようなC言語のプログラムがあり、これを python で動かしたいとする。
単に引数で与えられた文字列を標準出力するプログラムである。

```printstr.c
#include <stdio.h>

void printstr(char* str)
{
  printf("%s\n", str);
}
```

これを libprintstr.so として動的リンクができるようにコンパイルする。gcc なら以下のように。

```
gcc -c -fPIC printstr.c
gcc -fPIC -shared -o libprintstr.so printstr.o
```

以下のように python から利用することができる。

```ctype.py
from ctypes import *

lib = cdll.LoadLibrary("./libprintstr.so")
str = "hoge"
lib.printstr(str)
```

python2.7, python3.7 での実行結果はそれぞれ以下の通り。
見ての通り、python3.7 では意図しない結果となっている。

```python2.7
hoge
```

```python3.7
h
```

### 対応
```ctype.py
from ctypes import *

lib = cdll.LoadLibrary("./libprintstr.so")
str = "hoge".encode('utf-8')
lib.printstr(str)
```

```python3.7
hoge
```
【２０２１年４月最新版】爆速でGatsbyでTailwindcssを使う方法

今回の記事は最近巷で有名なGatsby.jsでTailwindcssを使用する手順をご紹介します。

ほぼ公式のドキュメント通りに進めていくのですが、いくつか変更点があるのでそれらを説明しながらやっていきます。

一応公式ドキュメントを載せておきますね。

[https://www.gatsbyjs.com/docs/how-to/styling/tailwind-css/](https://www.gatsbyjs.com/docs/how-to/styling/tailwind-css/)

#はじめに#

~~GatsbyでTailwindcssを使用する場合、Reactもそうなのですが``className="text-center"``のようにクラス名に指定してもTailwindcssを適用することはできません。~~

そこで登場するのが``twin.macro``です。

これを使って例えば``tw="text-center"``と指定するとTailwindcssを適用することが可能です。

設定も全然難しくないので肩の力を抜いてご覧ください！

それでは早速説明を見ていきましょう！

#必要パッケージのインストール#

まずは必要なパッケージをインストールします。

```powershell
npm install tailwindcss autoprefixer postcss gatsby-plugin-postcss sass gatsby-plugin-sass
```

```powershell
npm install -D twin.macro @emotion/react @emotion/styled gatsby-plugin-emotion
```

#プラグインの設定#

次はプログインの設定を行っていきます。

``gatsby-config.js``に以下のコードをコピペしてください。

```gatsby-config.js
module.exports = {
  /* Your site config here */
  plugins: [
    'gatsby-plugin-material-ui',
    'gatsby-plugin-postcss',
    'gatsby-plugin-emotion',
    {
      resolve: `gatsby-plugin-sass`,
      options: {
        postCssPlugins: [
          require("tailwindcss"),
          require("./tailwind.config.js")
        ],
      },
    },
  
  ],
}
```

``postcss.config.js``にて``tailwindcss``を追加（``postcss.config.js``を作成していない方は手動で作成してください）。

```postcss.config.js
module.exports = () => ({
  plugins: [require("tailwindcss")],
})
```

#tailwindの設定#

下記のコマンドで``tailwind.config.js``を作成。

```powershell
npx tailwindcss init
```

そして``gatsby-config.js``と同じ階層で``gatsby-browser.js``と``tailwind.css``を作成してください。

そしたら、``tailwind.css``にて以下をインポート。

```tailwind.css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

``tailwind.css``の読み込み。

```gatsby-browser.js
import "./tailwind.css";
```

これで準備は整いました。

あとはローカルサーバーを立ち上げ、以下を例にTailwindcssを適用させてみて下さい！

```jsx
import React from "react"
import 'twin.macro'  // これをインポートしないとtwが使えない
import { Header } from "../components"

export default function Home() {
  return (
    <div>
      <h1 tw="text-black">Hello</h1>
    </div>  
  )
}
```

#追記#

``pakage.json``に以下のマクロを登録すると、``className``でTailwindcssを適用することができました。

```json
{
  // 省略
  "babelMacros": {
    "twin": {
      "config": "./tailwind.config.js",
      "preset": "emotion",
      "hasSuggestions": true,
      "debug": false
    }
  },
}
```

このようにしてGatsby.jsでTailwindcssを適用することができました！

そこまで難しくは無かったような気がする。

他にもたくさん記事を上げているので是非ご覧下さい！

Thank you for reading

#参考記事#

・[GatsbyにTailwind CSSを導入する最短手順(CSS-in-JS)](https://qiita.com/suin/items/7281351779b5206e17b3)
実際にAzure上のCentOS 8.3をAlmaLinux 8.3に移行してみた

RedHatがCentOS8を今後（2021/12/31以降）CentOS Streamとしてのみ提供することになったのはすでにご存知かと思います。
https://blog.centos.org/2020/12/future-is-centos-stream/
（ちなみにCentOS7のライフタイムの方が長く2024/06/30まで）

かつてRedHatがEnterpriseをリリースして有償化した際にCentOSプロジェクトなどが立ち上がったのと同様に、いくつかのCentOS後継プロジェクトが発表されています。
AzureでもAlmaLinux 8.3のイメージが公開されていますが、既存のCentOS 8.3をどうするかが問題になってきます。

そこで今回は、AlmaLinuxを取り上げ、実際にMicrosoft Azure上で移行できるのかをやってみます。

AlmaLinuxはCloudLinuxが提供する無償のRedHat Enterprise互換OSです。
https://almalinux.org

2021/03/31にはStable版がリリースされました。
https://almalinux.org/blog/almalinux-os-stable-release-is-live/

このリリース記事の中に、既存のCentOSのリポジトリをAlmaLinuxに変更して移行するスクリプトへのリンクがあり、GitHubで公開されているので試してみます。
https://github.com/AlmaLinux/almalinux-deploy

まず、Azure上のCentOSのバージョンを確認します。

``` bash:バージョン確認
[azureuser@centosalmatest ~]$ cat /etc/redhat-release 
CentOS Linux release 8.3.2011
```

次に、先程のGitHubのREADMEに従って、移行スクリプトをダウンロード、実行します。

``` bash:ダウンロード
[azureuser@centosalmatest ~]$ curl -O https://raw.githubusercontent.com/AlmaLinux/almalinux-deploy/master/almalinux-deploy.sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 12999  100 12999    0     0  54848      0 --:--:-- --:--:-- --:--:-- 54848
```

``` bash:almalinux-deploy.sh実行
[azureuser@centosalmatest ~]$ sudo bash almalinux-deploy.sh 
Check root privileges                                                 OK
Check Secure Boot disabled                                            OK
Check centos-8.x86_64 is supported                                    OK
Download RPM-GPG-KEY-AlmaLinux                                        OK
Import RPM-GPG-KEY-AlmaLinux to RPM DB                                OK
Download almalinux-release package                                    OK
Verify almalinux-release package                                      OK
warning: /etc/issue.net saved as /etc/issue.net.rpmsave
Remove centos-linux-release package                                   OK
Remove centos-gpg-keys package                                        OK
Remove centos-linux-repos package                                     OK
Verifying...                          ################################# [100%]
Preparing...                          ################################# [100%]
Updating / installing...
   1:almalinux-release-8.3-4.el8      ################################# [100%]
Install almalinux-release package                                     OK

以下 yum upgrade を実行...

Complete!
Run dnf distro-sync -y                                                OK
Generating grub configuration file ...
done

Migration to AlmaLinux is completed
```

yum upgrade が終わるまで待ち、再起動します。
再度バージョンを確認してAlmaLinuxに変わっていることが確認できます。

``` bash:バージョン確認
[azureuser@centosalmatest ~]$ cat /etc/redhat-release 
AlmaLinux release 8.3 (Purple Manul)
```

なお、どうしてもサポートが必要だという場合は、素直にRedHat Enterprise Linuxに移行するのが一番だと思います。
こちらに手順がありますので参考まで。
https://access.redhat.com/ja/articles/5678351
ウインドウ関数とCouchbaseにおけるその実現（序）

# はじめに

ウィンドウ関数は、分析関数とも呼ばれ、標準SQL仕様にて定められています。

### 本稿の位置づけ
本稿は、Couchbaseのウィンドウ関数に関する解説の、序章の位置づけとして、できるだけ簡潔な記述で、ウインドウ関数についての概観を与える事を目的としています。
また、本稿では、標準SQLとCouchbaseにおけるその実現との間に区別を設けず、Couchbase実装をベースに整理します。

# ウインドウ関数とは

- 集合関数(MAX、SUM、AVG等)と同様の集計計算を行う
- 集合関数と異なり、集計単範囲の指定のために、GROUP BY句を用いない。OVER句を用いる。

# OVER句

- OVER句は、集合関数の後に記載する。（例えば、`COUNT(*) OVER()`）
- `OVER()`のカッコ内のパターン
    - 何も指定しない： 全行が対象となる
    - PARTITION BY: GROUP BYと同様
    - ORDER BY: 行を順番に並べた上で、集計の対象とする。
        - ウィンドウフレームを指定しない場合、最初の行から現在行までが対象となる。
        - ウィンドウフレーム: ORDER BY句のオプションとして使用する。（ユースケース例として、「移動平均」など）


## ウィンドウフレーム

ウィンドウ関数のユースケースの中でも、高度な、言い換えれば実践的なユースケースを実現するためには、ウィンドウフレームを駆使する事が重要になります。ここでは、その構造の概観を見る事で、その表現することのできる範囲について、イメージを掴むことから始めたいと思います。

### シンタックス

```SQL
<関数> OVER (PARTITION BY ... ORDER BY ... 
                    <モード> BETWEEN <frame_start> AND <frame_end> [ <frame_exclusion> ])
```

### モード
- ROWS
- GROUPS
- RANGE

## 非集約関数

上述の通り、ウィンドウ関数によって、GROUP BY句との組み合わせで行われる集計関数の適用を別のシンタックスで実行する事ができますが、GROUP BY句で実現されない機能を把握することが、分布関数・ウィンドウ関数の意義を理解するために有意義と考えられます。そのため、Couchbaseから提供される非集約関数をカテゴリー毎に紹介します。

### ランク関数
- ROW_NUMBER
- RANK, DENSE_RANK

### 等分関数
- NTILE

### 相対関数
- FIRST_VALUE, NTH_VALUE, LAST_VALUE
- LAG, LEAD

### 分布関数
- CUME_DIST
- PERCENT_RANK
- RATIO_TO_REPORT

# 最後に
以上が、（Couchbaseにおける）ウィンドウ関数についての素描になります。より進んだ、具体的な解説については、別稿に譲りたいと思います。

# 参考情報

## Couchbase

### Blog
[Window functions in Couchbase Analytics](https://blog.couchbase.com/window-functions-in-couchbase-analytics/)

[On Par with Window Functions. ](https://blog.couchbase.com/on-par-with-window-functions-in-n1ql/)

[Deep Dive: Window functions in Couchbase Analytics ](https://blog.couchbase.com/deep-dive-window-functions-in-couchbase-analytics/)

[Get a Bigger Picture with N1QL Window Functions and CTE](https://blog.couchbase.com/get-a-bigger-picture-with-n1ql-window-functions-and-cte/)

## Youtube
[Analyze Your Data With Window Functions](https://www.youtube.com/watch?v=gY_XchGn2ho)

## Qiita

[分析関数（ウインドウ関数）をわかりやすく説明してみた](https://qiita.com/tlokweng/items/fc13dc30cc1aa28231c5)

## Couchbase以外のデータベース

### BigQuery
[標準 SQL の分析関数のコンセプト](https://cloud.google.com/bigquery/docs/reference/standard-sql/analytic-function-concepts?hl=ja)
cartopy でローカルにあるデータを利用する

basemap と比べて cartopy について日本語で書かれたサイトは少ない気がする。何故だろう……？
Qiita でも cartopy の記事数は basemap の記事数に比べて少ないし……

### そもそも cartopy とは何か
cartopy とは python で地理データを描画する為のライブラリである。
anaconda 環境なら conda install で簡単にインストールすることができる。

```
conda install -c conda-forge cartopy
```

似たようなライブラリに basemap があるが、こちらは既に開発が終了しており、cartopy はその後継らしい。
であれば、今から使うのであれば cartopy で描画するのが良いだろう。

### 何がしたいのか
cartopy では、スクリプト実行時に [Natural Earth](https://www.naturalearthdata.com/) というサイトから地理データを自動でダウンロードして描画する。
しかし、セキュリティの問題等何らかの理由でインターネットからダウンロードが行えない環境では、これでは困ってしまう。
また、cartopy を頻繁に使うのであれば、データをわざわざインターネットからダウンロードするのではなく、ローカルにあった方が良いだろう。
ということで、あらかじめローカルにデータを手動でダウンロードしておき、そのデータを参照して描画を行いたい。

### どうすれば良いのか
[Natural Earth のダウンロードページ](https://www.naturalearthdata.com/downloads/)から zip データをダウンロードする。
この zip データを解凍し、anaconda のあるパスに以下のようなディレクトリ構造でデータを置く。シンボリックリンクでも良い。
ここで、category は Cultural, Physical, Raster で、resolution （解像度）は 10m, 50m, 110m のいずれかである。
name はデータの名前を指しており、例えば海岸線なら category が Physical の Coastline である。

```
anaconda3/lib/python3.7/site-packages/cartopy/data/shapefiles/natural_earth/{category}/ne_{resolution}_{name}.[ext]
```

そして、ソースコードに以下のように書いておく。

```python
import cartopy
cartopy.config["data_dir"] = cartopy.config["repo_data_dir"]
```

これで、ローカルにあるデータを参照し、地理データを描画してくれる。めでたしめでたし。
Node-RED チュートリアル はじめてのフロー

`Node-RED` の最初のチュートリアルです。公式ドキュメント [はじめてのフロー](https://nodered.jp/docs/tutorials/first-flow) を画像つきで書いてみました。

## セットアップ

1. `Node.js`をインストール。
2. `Node-RED` を `Node.js`にインストールする。([”ローカルでNode-REDを実行する : Node-RED日本ユーザ会"](https://nodered.jp/docs/getting-started/local) を参考に)


```
$ npm init
# (yes) to all

$ npm install -g node-red
```

3. `Node-RED` を起動し、ブラウザで開く

```
$ node-red
$ open http://localhost:1880
```

## チュートリアルを実施

1. Injectノード, デバッグノードをフローに追加
    ![image-20210416142026129.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/e7e483da-51dc-cdbf-26d5-5fdbb09cf8fb.png)

2. Injectノードから Debug Node にワイヤを接続する
    ![image-20210416142141071.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/eb7d39e8-0e46-8d16-82cd-5fe011c45467.png)

3. 右サイドバーのデバッグタブを表示し、デプロイボタンをクリックする
    ![image-20210416142400176.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/e66fc109-750e-3517-b416-3e6a8982e245.png)

4. Injectノードの左側にあるボタンをクリックすると、その時点のタイムスタンプがmsg オブジェクトに載せられて、デバッグノードに流れ着く。Debugノードは流れ着いたmsgオブジェクトをデバッグタブに書き込む。
    ![image-20210416142639799.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/9e27a66a-f194-3728-e8be-d2f770cd5642.png)

1. InjectノードとDebugノードの間のワイヤを削除、functionノードを挿入し、インジェクトノードとデバッグノードと接続する。
    ![image-20210416143115850.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/9001bd69-c36a-431f-d85a-8a5f66a1abed.png)

2. functionノードにJavascriptのコードをコピペする。タイムスタンプのメッセージは、unix time の整数から、x年x月x日という人間に見やすい文字列に変換される。
    
    ```js
// ペイロードから日付オブジェクトを生成
var date = new Date(msg.payload);
// 日付文字列に変換して再度ペイロードをセット
msg.payload = date.toString();
// 次のノードへmsgオブジェクトを返す
return msg;
    ```
    ![image-20210416143307614.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/a3255f24-42ba-7006-74ec-6ed216e2eb51.png)
    ![image-20210416143506195.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/7dcf3e65-1cac-44d9-dd20-cbfff29e8b73.png)

3. デプロイして、もう一度フローを実行すると、デバッグタブの表示が変わっている。
    ![image-20210416143747465.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/18a46256-8702-ff25-b4e4-a5f96f1aa63b.png)

----

続きは [Node-RED チュートリアル はじめてのフロー (フローのインポートとエクスポート)](https://qiita.com/nogayama/items/0e9ae80736e7faebdeda)
seleniumでeachなどで作られた一覧の要素全てに対して操作をする

### seleniumでeachなどで作られた一覧の要素全てに対して操作をする
　例えば「投稿一覧」のような画面で各投稿を1つずつクリックして開きたい時のパターンを想定。
### 操作する要素の例
　こんな感じのやつを想定。多分よくあるやつ。
　各post以下のlinkを1つずつ全てクリックしたい。

```
div class="index"
  div class="post"
    p hoge class="title"
    a class="link"
  div class="post"
    p huga class="title"
    a class="link"
  div class="post"
    p hugahoge class="title"
    a class="link"
```

### 取得し直すごとにオブジェクトが変わる場合がある
　Selenium::WebDriver::Elementオブジェクトのfind_elementsは要素を取得し直すごとに各種値が変わってしまう場合がある。

```ruby
# 子要素に対してクリック操作をしたいループ
@driver.find_elements(:class, "index").each do |element|
  element.find_element(:class, "hoge").click
end

# 1回目の取得
> @driver.find_elements(:class, "index")
[#<Selenium::WebDriver::Element:0x..f693ec4bf80c6eee id="2d75628b-0b8f-4d92-a7db-7e242210b403">,
 #<Selenium::WebDriver::Element:0xbc5fe1f4062f650 id="462b6e29-ef2f-4f1f-bad4-5acb980c74e5">,
 #<Selenium::WebDriver::Element:0x687a1921db97e860 id="193e8b33-669a-4381-8b74-039dcd379dd5">]

# 要素を一つクリックして新しいタブで開く
> element.find_element(:class, "hoge").click

# 2回目の取得
> @driver.find_elements(:class, "index")
=> [#<Selenium::WebDriver::Element:0x..f9a79e5201fcda17a id="08f92ae9-4ecc-4af0-b98b-94eb2bd9b843">,
 #<Selenium::WebDriver::Element:0x..fd075870720e89f2a id="a2d55dd1-1fab-4918-b95e-dfde8b2da705">,
 #<Selenium::WebDriver::Element:0x..fd3599185fcb5576a id="375c0957-1cfd-485f-be29-b8397d9ec2f1">]

# ループ2回目では以下のエラーが出る
Selenium::WebDriver::Error::StaleElementReferenceError: stale element reference: element is not attached to the page document
```

### 上記の場合の対処方法の例
　取得するごとにオブジェクト番号が変わってしまっては雑にeachで回してクリックすることはできなくなる。なので、以下のように対処した。  

```ruby
current_window = @driver.window_handles.first
# 要素の総数を取得
index_elements_count = @driver.find_elements(:class, "index").count

index_elements_count.times do |time|
  @driver.find_elements(:class, "index")[time].find_element(class: "link").click
  @driver.switch_to.window(current_window)
end
```
　これなら@driver.find_elements(:class, "index")の値がループごとに変わっても、配列のtime番目から取得するので問題ない。
gitコマンドの使い方(個人開発)

#GitとGitHubとは

コマンドの使い方に入る前に、まずはGitとGitHubについて説明します

##Gitとは
wikipediaから引用
>Gitは、プログラムのソースコードなどの変更履歴を記録・追跡するための分散型バージョン管理システムである。

##GitHubとは
Github公式から引用
>GitHubは、ユーザのみなさんからヒントを得て作成された開発プラットフォームです。オープンソースプロジェクトやビジネスユースまで、GitHub上にソースコードをホスティングすることで数百万人もの他の開発者と一緒にコードのレビューを行ったり、プロジェクトの管理をしながら、ソフトウェアの開発を行うことができます。

##結論
語弊を恐れずに記載するならば、GitとGitHubの関係は以下のようなものです。

- Git<br>
  **ローカル環境**でソースコードのバックアップを取れるもの
- GitHub<br>
  **リモート環境**でGitで取ったバックアップをアップロードすることで、そのソースコードの共有ができるもの

**ローカル**とは、「自分のパソコン内で」という意味なのでネットに繋がっていない**オフライン環境でも利用することができます**。
**リモート**とは、「ネット上の」という意味なのでネットに繋がっている**オンライン環境でのみ利用することができます**。

#個人開発で使うコード一覧
ブランチをきったりしないので個人で開発する範囲であれば、以下のコマンドで十分だと思います。

[チーム開発はこちら](https://qiita.com/kunrenyouAcount/items/5d5dab29fb30add2d172)


###既存のソースコードを使う場合

- GitHubからソースコードをクローンする(ダウンロード)

```termina:クローン
git clone [URLを入力]
```

###ローカルで編集した作業内容のコミット

- 編集した変更をステージング<br>
→変更箇所の確認

```terminal:ステージング
git add .
```

- ステージングした内容をコミットする<br>
→ローカルにバックアップを作成する

```termina:コミット
git commit -m '[コメントの内容]'
```

###コミットした内容をプッシュする

- コミットした内容をプッシュする<br>
→コミットで作成したローカルにあるバックアップをアップロード

```terminal:
git push
```
【備忘録：vscode】vscodeでファイルを保存時、prettierでコードを自動整形する

表題通りですが、vscodeでprettier拡張機能をインストール、設定する方法を備忘録として残します。
※Macの場合です。

## prettier拡張機能をvscodeにインストール
まずは、vscodeを開いてprettierの拡張機能を入れましょう。

![スクリーンショット 2021-04-16 14.36.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625199/ce58588d-b8ac-f55e-e0c2-26ed33cca1eb.png)
## prettier機能をファイル保存時に走らせる
prettier拡張機能を入れただけではファイルの保存時に、prettierが動きません。
なので、ファイル保存時にprettierが動くようにvscodeの設定を行います。

「**commond+,(カンマ)**」を押すことで、以下のvscodeの設定画面が開きます。
![スクリーンショット 2021-04-16 14.41.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625199/996339cb-5fec-231e-3d66-d34976da2309.png)
まずは、上にある検索エリア（赤枠の箇所）に、**onsave**と入力します。

すると、黄色枠の「**Format On Save**」という設定箇所がでてきますので、これにチェックを入れます。

これでファイルを保存時にprettierが走りコードが自動整形されるはずです！

## もし、自動整形されない。自動整形対象のファイルを除外したい。自動整形オプションを設定したいという方

上記の場合は、再度vscodeの設定画面を開きましょう。（**commond+,(カンマ)**）

![スクリーンショット 2021-04-16 14.47.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625199/765d9ed2-bd7a-0630-2b53-1e02271eff0a.png)
そして、上記スクショ右上の赤枠の箇所をクリックします。

そうすると、**settings.json**が開きますので、こちらに任意のファイルや、任意の自動整形オプションを記述します。

### 任意のファイルにprettierを行う
任意のファイルにprettierをかけたい場合以下のように記述します。

```json:settings.json
	"settings": {
        // javascriptやcss、typescriptなども設定可能 //
		"[javascript]": {
			"editor.defaultFormatter": "esbenp.prettier-vscode",
		},
	}
```
上記は、**javascriptファイルを保存時、フォーマッターをprettierにする**と言うことになります。

### prettierの自動整形オプションを変更する。
こちらも同じ**settings.json**ファイルにオプションを書き込みます。


```json:settings.json
	"settings": {
        // javascriptやcss、typescriptなども設定可能
		"[javascript]": {
			"editor.defaultFormatter": "esbenp.prettier-vscode",
		},
		"prettier.singleQuote": true, // シングルクォートで囲む
		"prettier.semi": true, // 最後にセミコロンを付ける
		"prettier.tabWidth": 2, // タブサイズは2
	}
```

こうすることで任意のファイルに、任意の自動整形オプションを設定できます。

prettierのオプションについては以下の公式サイトが分かりやすいのでこちらを参照して、オリジナルの自動整形をしてみてください。
https://prettier.io/docs/en/options.html

以上がvscodeでprettierの設定を行う方法でした！

大規模アプリ開発や複数人で触る案件などは、
ESLintなどのリンターと組み合わせて、構文エラーがある箇所を自動整形するのが多いかと思います。

ただ、LP制作など小規模でもprettierでコードの自動整形ができるので入れておいて損はないかと思います！
【React】useHistoryのstateから値を取得する【TypeScript】

```typescript
const param = history.location.state["param"];
```

**＿人人人人人人人人人人人人人人人人人人＿
＞　オブジェクト型は 'unknown' です。　＜
￣Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^￣**

# 概要

* `TypeScript`で構築した
* `React`のプロジェクトにて
* `Link`または`useHistory.push`で設定した`state`の値を

取得するためのワークアラウンド的な実装のメモ。

# 実装
`state`に値を設定したはいいものの、`Props`とかどう書けばいいの？
実装方法がわからんなー、と困っていまして。以下の様にして対処しました。

`state`の値を取得するための関数は以下ように実装しました。
ポイントは一度`any`型に変換をかけるところです。
これで`JavaScript`同様にブラケットを使ったプロパティアクセスができるようになります。

```typescript:stateの取得
const getState = (state: any, name: string): string =>
  (state as any)?.[name] ?? "";
```

あとはリンクに`state`を仕込み、必要に応じて値を取り出すだけです。

```tsx:stateの設定
<Link to={{ pathname: "/", state: { param: "top" } }}>トップ</Link>
```

```typescript:stateの取得
const history = useHistory();
const param = getState(history?.location?.state, "param");
```

**オプショナルチェイニング演算子**を活用すればかなり簡潔に記述できますね。
[Optional chaining (?.) - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining)
>オプショナルチェイニング演算子 ?. は、接続されたオブジェクトチェーンの深くに位置するプロパティの値を、チェーン内の各参照が正しいかどうかを明示的に確認せずに読み込むことを可能にします。 ?. 演算子の機能は . チェーン演算子と似ていますが、参照が nullish (null または undefined) の場合にエラーとなるのではなく、式が短絡され undefined が返されるところが異なります。 関数呼び出しで使用すると、与えられた関数が存在しない場合、 undefined を返します。

# 注意
これは手っ取り早く実装を済ませるための、その場しのぎ的な方法です。
適切な`Props`の設定などがおそらくあるはず。
他に適した実装が無いか、注意深く検討してください。
App Development with Swiftに合格してきた

# はじめに
iOSエンジニアになり早9ヶ月。
弊社も資格取得に力を入れている中、せっかくならiOS関連の資格を何か取得できないかと思い、"App Development with Swift"を受験してみることに。
取得にあたり、Qiitaや他のサイトでも合格体験記があまりなかったので、せっかくなのでここに残すことにします。

これから取得を目指す人、何か資格を探している人などは是非読んでいってもらえたらと思います。

ちなみに受験時の筆者スペック
- iOS開発歴：9ヶ月
- センター試験・英語：150点（くらいだった気がする。なお5年前）
- TOEIC：450点（くらいだった気がする。なお3年前）

## 試験概要
- 資格名：App Development with Swift
- 科目名：App Development with Swift Level 1
- 試験時間：50分
- 試験の言語：英語（2021年4月現在、日本語対応は未定）
- 試験方式：CBT試験
- 問題数：45問
- 合格ライン：（おそらく）７割

要はSwift、Xcodeなど、iOSアプリ開発者として必要な知識、スキルを証明する資格です。
Level2はまだ無いのではないでしょうか。筆者が調べてみた限りでは見つからなかったですね。

詳しくはこちらのサイトをご覧ください。
[App Development with Swift 公式HP](https://www.odyssey-com.co.jp/app-dev-with-swift/)

## 出題範囲
大きく分けてセクションは以下の3つです。

- Developer Tools Xcode & Builder Interface
- Swift Language Fundamentals
- iOS API Fundamentals

上記サイトにて、学習教材が提供されているので、そちらをやれば十分かと。
ただし、過去問などは一切出回っていないので、他の試験で過去問をやりまくって合格してきた人は大変かもしれません。
逆に言うと、実際に開発経験のある方はそこまで難しくないと言えます。

Swiftの基本的文法から、Xcodeの説明、ライフサイクルやMVCなど満遍なく出題されます。

## 出題形式
- 選択問題（択一問題）・・・複数の選択肢の中から一つ選択
- 選択問題（複数回答）・・・選択肢の中から複数を選んで回答
- 記述問題・・・ソースコードの穴になっている箇所の補完、文章が正しくなるように単語の記述など
- ドラッグ&ドロップ・・・並び替え、選択肢を対応するものにドラック＆ドロップ、問題に対応する箇所をクリック

Apple推奨の教材にも問題は載っていますが、ほぼほぼ参考にならないので、自分で手を動かして一つずつ理解していくことをオススメします。

## 勉強法
1. Apple推奨教材を読み込む
2. 日頃の開発（笑）

以上です！笑
問題集がない以上、やはり手を動かさなければ理解できないです。
私の場合は、たまたま開発業務があったので、それである程度は実践経験を積めたのでよかったですが、もし開発業務がないって人はApple推奨の教材に一緒にハンズオンしていく箇所もあるので、そちらを進めることをオススメします。

しかしながら、Xcodeの画面を見て答える問題やAutoLayoutの説明、UIパーツの説明などは、やはり日頃から開発に触れていないと答えるのが厳しい気がします。なので、簡単なアプリでも良いので作ってみることをオススメします。

開発はやっていないけど資格だけ取ろうって人はかなり厳しいのではないかと。
開発をやっている人前提の資格というイメージですね。

## 受験結果と感想
正直に言います。１回目は落ちました。笑
推奨教材が900ページを超えるということと、その900ページが全て英語ということで、英語弱者の筆者としてはやりたくなかったです。
日頃の開発知識だけでどうにかしようと実質ノー勉で行きました。
が、結果は1000点満点中680点でした。700点が合格ラインなはずです。

敗因としては、
1. 開発でカバーしている箇所とそうでない箇所の理解の差が激しい
2. 無意識に使用しているものをいざ聞かれたときに回答できない

この2点だったかなと思います。

ということで、1ヶ月後にもう一度受けました。
その際は、教材とGoogle翻訳をiPadに並べ、開発で触れない箇所を重点的に勉強しながら、ひたすらコピペで読み進めました。
そうして迎えた再試験、なんとか830点とって合格でした。

## 英語は実際どうなの？
多くの方が気になる箇所って、これだと思うんですよ。
ご存知の通り、問題文、回答全て英語です。そりゃそうですよね、Apple主催の試験なんですから。笑

筆者もこれがネックで受験することを渋っていました。筆者の英語スペックは上記に挙げた通りで、極力英語に触れないように生きてきました。
しかし、受けてみての感想は、ぶっちゃけあまり関係ないです。

「以下の選択肢から選びなさい」
「上記のソースコードの空白部分に対応するものを選びなさい」
「画面で対応する箇所をクリックしなさい」
「正しい順番に並べ替えなさい」

などなど、なんとなく読まなくても問題を見れば文章は予測できます。
たまに、絶妙に単語の意味がわからなくて2択で悩んだりしますが。笑

また、45問の問題数に対して試験時間は５０分あるので、1問に1分かけたとしてもお釣りがきます。ゆっくり文章を読んでもらって大丈夫です。
筆者の場合は、2回目は一周して見直しをしても30分ほどで試験は終了しました。

結局大事な知識は、英語力よりもSwiftやXcodeに関する知識です。
これがあれば多少英語で詰まって怪しい問題があったとしても、合格点数を下回ることはないでしょう。

## 最後に
今回二度目ではありましたが、なんとか合格できてよかったなという感じです。
普段使わない分野や、これから開発で使おうとしていた知識も身につけることができたので、開発の質や守備範囲も広がったなという印象です。
引き出しの数は多くて損することはないですね。
ただ、じゃあ「App Development with Swiftもってます！」って言ったところでどこまで影響があるかは正直微妙なところですね。
それでもマイナスに働くことは当然ないです。
iOS開発をしている方は、是非知識整理やスキルチェックのためにも受験してみてはいかがでしょうか。

AppleがLevel2を出したら、そちらも受験してみようかなと思います。

それでは。
DXのケース・スタディ / モビリティ

**MaaSは、多くの人が思っている以上に進んでいますね。そのなか、今、ビジネスモデル構築という非常に難しいフェーズにあります。**
**　▶技術課題は、国主導の実証実験等でほぼクリア
　▶ビジネスモデルの確立が課題（実証実験はこの部分が弱い）
　▶規制緩和（貨客混載）の援護射撃で
　　　⇒利益がでて継続できるビジネスに
　　　⇒地域ビジネスに貢献するビジネスに**

##1. “CASE”から、日本のモビリティ技術の状況を知る
**来年には“公共交通分野”“物流分野”のデジタル技術環境が整う**

**公共交通分野 >>> 自動運転　⇒　来年、無人路線バスが本運営**
**物流分野 >>> 車間、サービス間でのデータの共有・活用**
**　　　　　　　　⇒　今年、貨物車が連携する為のデータの標準化**


https://www.slideshare.net/MMurakamiMurakami/case-246306177

##2. 日本の“MaaS”の状況を知る
**a. 国主導の実証実験等で、技術課題はほぼクリア
b. 現在の課題は、MaaSの“ビジネスモデルの確立”
c. 旧来の法制度の枠組みではビジネス・モデルが成立しにくい
d. 「貨客混載」で“リソースの稼働率向上”、“収入源の多様化”が必須**

https://www.slideshare.net/MMurakamiMurakami/maas-246306335

##3. ビジネスモデルに求められるもの
**a. 安定した「MaaSビジネス」の収支モデルの確立
b. 地域産業に貢献する「関連ビジネス」の収益モデルの創出**

https://www.slideshare.net/MMurakamiMurakami/ss-246354582

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585213/6fec528d-d226-9aaa-26e6-17c03abcd14c.png)
【GCP】Cloud Identity / Workspace / Gmailアカウント　の違いについて

#背景
GCPを利用するには掲題のアカウントが必要ですが、それぞれどんな違いがあるかわかりずらいので、こちらにまとめます。

#各アカウントの違い
GCPを使いたい場合、アカウントの用意どうしよう？ってことも考えると思います。
でも、Goolgeに関するアカウントって、いろいろある。
その違いを簡単にまとめます。
それぞれが、なんとなく違うんだなってことくらいしか書いてないので、詳細を知りたい場合は、ググってください。

###Gmailアカウント
無料アカウントを作成してメールサービスを利用したいとき、アンドロイドを買ったとき、作成するのがこのアカウント。
簡単に取得できますが、このアカウントでもGCPを利用開始することができるのです。
個人向けとなっています。
セキュリティを少しでも高めるために2段階認証を使っておくことを推奨します。
gmailの他、カレンダー、chatなどいろんな機能も使えます。

#####特徴
無料でメールアカウントを作成できる
容量が15GBなので大量のメールを保存できる
迷惑メールフィルターが優秀
送受信メールの検索機能が充実している
送受信の機能が豊富
デバイスを破損・紛失してもデータが残せる
セキュリティがしっかりしている
メール以外のツールも使用できる

#####利用シーン
個人でメールアドレスの取得をする。
そのほかのツールを使用したい。

#####メリット
とにかくお手軽。無料でいろんな機能を使えるのはマジで神。

#####デメリット
完全に個人用なので、企業用で使うのは絶対にお勧めしない。

###Google Workspace
Googleが提供する企業向けグループウェアサービス
個人用のGmailとGoogle Workspaceの最大の違いは、Google Workspaceのリソースは、アカウントを所有する企業が、社員全てのアカウントとアカウント内のビジネスデータを一元管理できることです。
使える機能は似ていますが、Gmailは個人ユーザー向けに設計されているのに対し、Google Workspaceはビジネスやチームの視点で設計されています。
会社の独自ドメインのメールアドレスを使用してメールの送受信を行うことができます。
管理者が異なるユーザーのアカウント権限を管理できる「管理者コンソール」を提供しています。
アカウント発行機能があり、この機能によって作成されたドメインに紐づくアカウントもGoogle アカウントになります。
お申込みをする際は、事前にドメインの取得を済ませておく必要がありますので注意ください。

#####特徴
会社の独自ドメインのメールアドレスを使用してメールの送受信を行うことができます。
管理者が異なるユーザーのアカウント権限を管理できる「管理者コンソール」を提供しています。
アカウント発行機能があり、この機能によって作成されたドメインに紐づくアカウントもGoogle アカウントになります。

#####料金
いくつかプランがある
「Business Starter:¥680/月」「Business Standard:¥1,360/月」「Business Plus:¥2,040/月」

#####利用シーン
Google Workspaceのリソースは、アカウントを所有する企業が、社員全てのアカウントとアカウント内のビジネスデータを一元管理する。


| |個人Gmail|Google Workspace（企業版Gmail）|
|:----|:----|:----|
|設計|個人向け|法人向け|
|所有権|個人ユーザー|企業|
|個々のアカウントのデータへのアクセスは|パスワードを知っているユーザー|企業の管理者|
|個人アカウントに関連する情報へのアクセスを要求する場合|ユーザーの許可が必要|初期からアクセス可能|
|人事異動により個人アカウントにアクセスできなくなった場合|アカウントに関連するすべてのデータやサービスへのアクセスが失われた場合は、再構築する必要があります|データの保存、転送、元々利用していたサービスへの継続的なアクセスが可能|

###Cloud Identity
IDaaS（Identity as a Service）ソリューション
Google Workspaceからアカウント発行、管理機能のみを使えるようにしたアカウントサービスになります。
ドメイン(組織)の管理下でアカウントを管理できます。
二段階認証も企業として設定必須にできます。
無料で50アカウントまで作成が可能
プランは、Free　無料（50アカウントまで）とPremium　1ユーザー/月/645円。使える機能も異なるので、詳細なページも記載⇒https://support.google.com/cloudidentity/answer/7431902#zippy=%2C%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E7%AE%A1%E7%90%86
Cloud Identity を申し込むには、前述したGmail アカウントの作成と後述するプロジェクトの作成まで済ませる必要があります。

#####特徴
Google Workspaceからアカウント発行、管理機能のみを使えるようにしたアカウントサービス

#####利用シーン
IDaaS（Identity as a Service）ソリューションのみ導入したい
Google Workspaceからアカウント発行、管理機能のみを使えるようにしたい


#参考URL
https://onl.tw/bE22dVu
https://apps-gcp.com/gcp-basic-01-preparation/#i
https://onl.tw/WYecwkg
VBAの基本操作（ワークシート）

VBAの初心者向けに基本操作方法（ワークシート）を紹介していきたいと思います。


```:シートの選択
Sheets("Sheet1").Select      'シート名"Sheet1"を選択する
Sheets(1).Select             '一番目のシートを選択する
ActiveSheet.Next.Select      '次のシートを選択する
ActiveSheet.Previous.Select  '前のシートを選択する
```


```:ワークシートの追加
Worksheets.Add After:=ActiveSheet   '前にシートを追加
Worksheets.Add Before:=ActiveSheet  '次にシートを追加
```
ActiveSheetは現在選択中のシートを意味します。


```:シートの名前変更
ActiveSheet.Name = "注文書"
```


```:シートの貼り付け
ActiveSheet.Copy Before:=ActiveSheet　'今のシートを前のシートにコピーする
```


```:シート内のセルを別シートへコピー
Cells(1, 1).Copy          'コピーする
ActiveSheet.Next.Select   '次のシートを選択する
Cells(1, 1).PasteSpecial  '貼り付ける
```


```:シートを削除する
ActiveSheet.Delete  '選択したシートを削除する
```
FragmentStatePagerAdapterの復元処理でハマった話

## 起こった事象
Activityが破棄された時、FragmentStatePagerAdapterのデータが残っているため、
Fragmentに対して直接指示する時に内部変数が初期化されてない状態になっている。
そのため、呼び出し行うとクラッシュする。

## 対処方法
https://qiita.com/ntsk/items/6eafe7bd7edbab61341e

保存の流れとして、
`onSaveInstanceState` -> `onDestroy` -> `onRestoreInstanceState`
のため、`onRestoreInstanceState`で
FragmentStatePagerAdapterの`fragmentManager`のデータを削除する。

データを削除し、改めて`onCreate`から生成し直せばいい。

## 誤った対処
メモリ破棄できてないから、きちんと破棄すればいい。という思考だけで、対応しようとしてしまった。

破棄処理の`onDestroy`でクリア処理を追加する形にしたが上手くいかなかったため、
破棄する方法が違うと思って、あれやこれや（※１）と試してやってしまった。。
が、先に書いた"対処方法"の通り、いい感じに消し込めたとしても、
`FragmentStatePagerAdapter`が`onRestoreInstanceState`をいい感じに実行するため復元されてしまう。
ので、消し込み処理が意味ないものとなっていた。

（※１）
OnDestroyのタイミングで、
viewPagerをリセットしたり、FragmentStatePagerAdapterのデータを空にし通知したり、
framentManagerのfragmentを全て破棄したり、FragmentStatePagerAdapterの渡すf配列のfragmentをWeakReferenceにしたり
FragmentStatePagerAdapterをFragmentPagerAdapterにしたり..etc..

## まとめ
破棄時のライフサイクルを意識しきれてなかったのと、
FragmentStatePagerAdapterの理解度が浅かったのものあるが無駄にハマった。
「破棄しきれてないから破棄すればいいじゃん」というバイアスが取れないと詰みます。
みなさんこうならないようにしてくださいw

## おまけ
前ふりをよく書いてたけど、やめようと思う。
コンテンツがストーリー的になってないなら結論言った方が早いよねと・・・
テンション高まった時だけにしよう:frowning2: