OmniAICreator/Qiita-1.07M huggingface dataset:
MarketingCloudSDK In-App Messaging概要

# In-App Messagingとは
ユーザがアプリのプッシュ通知を許可していなくてもユーザにメッセージを配信できるアプリ内メッセージのことです。
アプリがフォアグラウンドの状態になる度にアプリ内メッセージが読み込まれ、SMCで作成したメッセージが、アプリのビュースタックの最上部に表示されます。（閉じたメッセージは再度表示されません）

メッセージのテンプレートは以下３つがあります

・***フルページ***
　レイアウトが画面全体に表示される
・***バナー***
　画面最下部または最上部に表示される
・***モーダル***
　画面の一部に全面表示される

上記３つともSMCのContent Builderで設定可能です。
また色や、画像の配置、フォントサイズなどカスタマイズ可能になっています。
※文字のフォントに関してはデバイスのシステムフォントを使用しているため、アプリ側のフォント上書きの実装が必要です。

通知するには***JourneyBuilder***からアプリ内メッセージの送信が必要です。


#実装
以下、公式ドキュメントから参照となります。

1.アプリ内メッセージング機能をViewControllerにデリゲートするために```sfmc_setEventDelegate```メソッドを使用を使用する

```ViewController.swift 
// クラス宣言のMarketingCloudSDKEventDelegateプロトコルに従います。
class MyViewController: UIViewController, MarketingCloudSDKEventDelegate

...

// 実装のどこかで、アプリ内メッセージイベントのためのSDKのデリゲートとしてクラスを設定します。

// 可能であれば、クラスの初期化の早い段階で行う必要があります。
MarketingCloudSDK.sharedInstance().sfmc_setEventDelegate(self)
```

2.ビューの表示や削除に対応するデリゲートメソッドを追加する

```ViewController.swift 
func sfmc_didShow(inAppMessage message: [AnyHashable : Any]) {
    // message shown
}

func sfmc_didClose(inAppMessage message: [AnyHashable : Any]) {
    // message closed
}
```

3.アプリ内メッセージの表示を遅延させたり、防止したりすることができる。例えば、ロード中、インストラクション中、サインインフロー中などにアプリ内メッセージが表示されないようにする。メッセージの表示を防ぐには、```shouldShowInAppMessage```メソッドをfalseを返すようにする。

```ViewController.swift
func sfmc_shouldShow(inAppMessage message: [AnyHashable : Any]) -> Bool {
    // メッセージを表示するタイミングなどのロジックを書く
    if (self.messageCanBeShown) {
        return true
    }
    else {
        // メッセージデータを取得するできる
        self.showMessageId = self.sdk.sfmc_messageId(forMessage: message)
    }
    return false
}
```

4.メッセージデータを取得（```sfmc_messageIdForMessage```）して、後から表示（```sfmc_showInAppMessage ```）することが可能

```ViewController.swift
if (self.showMessageId != nil) {
    MarketingCloudSDK.sharedInstance().sfmc_show(inAppMessage: self.showMessageId)
}
```

5.アプリ内メッセージのフォントを変更するなら以下のデリゲートメソッドを使用し、デバイスにインストールされているフォントまたはアプリのカスタムフォントの有効なフォント名をSDKに渡す。

```ViewController.swift
MarketingCloudSDK.sharedInstance().sfmc_set(inAppMessageFontName: "Zapfino")
```

#参考リンク（公式）
https://salesforce-marketingcloud.github.io/MarketingCloudSDK-iOS/in-app-message/in-app-messaging.html
AirflowやCloud Composerでpackageを定義して使いたい

# 背景
AirflowやCloud Composerで自分で定義したpackageを使いたい場合。例えば、slack通知を行うクラスの定義など。

# Airflowのやり方
例としてslack通知を実装する(参考: [Airflowのタスク/DAGが失敗した時にSlackで通知する仕組み](https://qiita.com/munaita_/items/1a5b131839e01ea7280d))。
まずは、Airflowでは以下のように定義すればいい。


#### dir構成

```sh

ProjectRoot
.
├── dags
│   ├── slack_test.py
│   ├── packages # 任意のdir名
│   │   ├── __init__.py
│   │   └── slack.py
```

#### slack.py

```py

import json
import requests


class Slack:
    def noti(context=""):
        Slack.post('Failed: {}.{}.{}'.format(
            context['dag'], context['task'], context['execution_date'])
        )

    def post(text):
        url = "https://hooks.slack.com/services/__/__/__"
        requests.post(url, data=json.dumps({
            'username': 'Airflow',
            'channel': 'your_channel',
            'attachments': [{
                'title': text,
                "color": 'danger'
            }]
        }))
```

#### `__init__.py`

```py
from packages.slack import Slack
```

#### slack_test.py

```py

from datetime import datetime, timedelta
from airflow.operators.python_operator import PythonOperator
from packages import Slack


def test():
    Slack.post('slack test')
    return 'success'


default_args = {
    "owner": "airflow",
    "depends_on_past": False,
    "start_date": datetime(2020, 8, 1),
    "retries": 1,
    "retry_delay": timedelta(minutes=5),
    "on_failure_callback": Slack.noti, # Dagが失敗したら通知が飛ぶ
}

dag = DAG("slack_test", default_args=default_args, schedule_interval=timedelta(1))
t1 = PythonOperator(task_id='print_package', python_callable=test, dag=dag)

```

# じゃ、Cloud Composerの場合は？

### [ローカルの Python ライブラリをインストールする](https://cloud.google.com/composer/docs/how-to/using/installing-python-dependencies?hl=ja#install-local)

ここにあるように、ディレクトリ名を `dependencies` と定義する必要がある。
ディレクトリ構成は以下のようになる。

```sh

ProjectRoot
.
├── dags
│   ├── slack_test.py
│   ├── dependecies　# これ
│   │   ├── __init__.py
│   │   └── slack.py
```
cloud9でSQLite3のバージョンエラー

よくあるエラーだけれども、忘備録として書いておこうと思います。

エラー分
raise ConnectionNotEstablished, "No connection pool with id #{spec_name} found." unless pool

Gemfileの下記の部分がエラーの原因。
gem 'sqlite3'

下記の通りに変更する。
gem 'sqlite3', '~> 1.3.6'
この時command+Sで上書き保存を忘れないように。

その後 bundle install　を行うことで解決。
helm init が実行できない

## helm initを実行するとこのようなエラーが出た。
```Terminal:command
 $ helm init
Error: unknown command "init" for "helm"

Did you mean this?
        lint

Run 'helm --help' for usage.
```

## なぜ出るのか？
helmのバージョンを確認してみる

```Terminal:command
 $ helm version
version.BuildInfo{Version:"v3.3.0", GitCommit:"8a4ae.....", GitTreeState:"dirty", GoVersion:"go1.14.6"}
```
見たところバージョンは3.3.0のようだ。
helmのリファレンスにはv3(バージョン3)以降はTillerが取り除かれたようだ。
"helm init"はTillerのサーバをKubernetesクラスタ内にデプロイするためのコマンドのため、v3以降からは使えないようだ。
使用するためにはv2等に変更するしかない。

## 参考文献
https://github.com/helm/helm/issues/6996
【VirtualBox】VirtualBoxでホストオンリーアダプタを設定後、起動したらエラーが出たので、解消方法を残す。

自分用のメモとして残します。

VirtualBoxでホストオンリーアダプタを設定後、起動したらエラーが出たので、解消方法を残す

#エラーの内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213462/adc1685c-640a-cac1-c56f-5bb3af3a681b.png)


ログのコピー↓

```
Failed to open/create the internal network 'HostInterfaceNetworking-VirtualBox Host-Only Ethernet Adapter #5' (VERR_INTNET_FLT_IF_NOT_FOUND).
Failed to attach the network LUN (VERR_INTNET_FLT_IF_NOT_FOUND).


終了コード : 
E_FAIL (0x80004005)
コンポーネント: 
ConsoleWrap
インターフェース: 
IConsole {872da645-4a9b-1727-bee2-5585105b9eed}
```

#■解消方法
対象のホストオンリーアダプタのプロパティを開き、
**インターネットプロトコルバージョン6(TCP/IPv6)のチェックを外す**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213462/5c0dde37-c586-8a9e-be55-27a77d4c105c.png)


以上。
Pandas 列名×行番号で要素を抽出する

### はじめに
loc,ilocなど、行名/列名,行番号/列番号を基に要素抽出は出てくるものの、
列名×行番号による抽出方法が上手く探せなかったため、メモ投稿です。

## やりたかったこと
大元のデータフレーム（列名有り,行名無し）から、特定の要素を持つグループに分け、
各データフレームに対して1行ずつ参照して処理をしていく必要があった。

その際、列の指定は出来るが行の指定が思うようにできないため、行番号で処理を試みた。
（reset_indexも考えたが、きっと列名×行番号での指定も出来るはず…）

## 結論
<b>atとindexを組み合わせ、df.at[df.index[行番号],'列名']</b>　で抽出できる

（↓の記事をきちんと読めば良かった...）
https://note.nkmk.me/python-pandas-at-iat-loc-iloc/

### お試し

```python:DataFrame
# 列名のみのデータフレーム作成
df = pd.DataFrame({'person':['a','b','c','a','b','c'],\
                  'name':['aa','bb','cc','aaa','bbb','ccc'],\
                  'num':[100,200,300,1000,2000,3000]})

	person	name	num
0	a	aa	100
1	b	bb	200
2	c	cc	300
3	a	aaa	1000
4	b	bbb	2000
5	c	ccc	3000
```

単純に、大元のdfから"name"列 0行目　(=aa) を抽出するにはどちらでも可能

```python:person_0
df['name'][0]
# 抽出した行に(大元の)index=0があるため抽出可能
# aa

df.at[df.index[0],'name']
# aa
```

今度は"person"列が同じ人に絞り、その上で0行目を取得してみる
　※今回の話とはずれますが、行列を絞る際や要素抽出時に
　　"SettingWithCopyWarning"にハマらないよう注意（ハマりました。。）
　　https://linus-mk.hatenablog.com/entry/2019/02/02/200000
　　https://qiita.com/HEM_SP/items/56cd62a1c000d342bd70

```python:person_a_0
# "person"列がaの行に絞る
df_a = df[df['person']=="a"]
df_a
	person	name	num
0	a	aa	100
3	a	aaa	1000

df_a['name'][0]
# 抽出した行に(大元の)index=0があるため抽出可能
# aa

df_a.at[df_a.index[0],'name']
# aa
```

```python:person_b_0
# "person"列がbの行に絞る
df_b = df[df['person']=="b"]
df_b
	person	name	num
1	b	bb	200
4	b	bbb	2000

df_b['name'][0]
# 抽出した行にindex=0がないためエラー

df_b.at[df_b.index[0],'name']
# bb

```
atを使うことで、どのデータフレームに対しても行番号で要素を抽出出来た。

## 終わりに
少しでも、見つからずに困っている方の役に立てば嬉しいです。
Python基礎


# Python基礎

識別子
　Pythonでも識別子を定義することができます。プログラミングでは、さまざまなモノ（クラス、関数、変数など）に対して名前をつけていく作業が発生します。
こういった名前のことを識別子と呼びます。識別子はある程度は自由に自身が決めることが可能なのですが、ある一定のルールがあり、そこから逸脱すると実行に失敗したり予期せぬ動作を引き起こすことがあります。
また、制御に利用するような特定の文字列は一般的に予約語と呼ばれ、識別子として利用することはできません。

Pythonでは予約語のことをkeywordとも呼びます。以下、Python3.8の予約語です。

|False|await|else|vzimport|
|:---|:---|:---|:---|
|pass|None|break|except|
|in|raise|True|class|
|finally|is|return|and|
|as|assert|async|continue|
|def|del|elif|from|
|global|if|for|lambda|
|try|nonlocal|not|or|
|while|with|yield||

定数
　定数とは値の変更を許可しない変数のです。例えば、金融システムを格納する変数は価格を算出するプログラムが動作している最中に書き換わると困りますので、多くの言語では定数というものがサポートされています。Pythonに定数はありません。
慣習的に大文字の変数を定数とみなす場合がありますが、変数の書き換え自体を禁止する仕組みはありません。

変数
　Javaなどでは、変数を用意する（宣言する）際、文字列や数値といったデータの型を指定します。Pythonはこれとは異なり、型を指定する必要がありません。Pythonでは、「＝」を値の代入に使います。（number = 1）は変数（number）に（1）を代入するという意味です。
もう1つ注目したいのが、1行目の「＃」記号です。Pythonでは「＃」を先頭に付けると、その行がコメント（プログラムに影響を与えないもの）として扱われます。これを「コメントアウト」と呼びます。
　Pythonでは慣例的に変数には小文字の英語しか用いません。
大文字を利用する場面としては変数を定数的に利用するタイミングです。Pythonでは、定数という概念がありません。そのため、定数を定義するための文が存在しないのです。
そのため、定数と変数を区別する方法として、定数として扱う場合に「大文字で記述する」という慣例が生まれました。もちろん、変数に大文字のアルファベットを用いて命名しても仕組み上の問題は発生しません。

変数の使い方
　 変数は、基本的にリテラルと同じように使うことができる。 次のように計算したり、関数やメソッドに渡したりすることができます。

例：
x = 2
y = 5
sum = x + y
print(sum)

　この例では、変数に割り当てた数値を足しわせて、別の変数に割り当てています。
変数はそのままprint関数でコンソールに表示できます。 な変数の型に対して不適切な操作（数値と文字を足すなど）をするとエラーになります。

変数を使う際の注意点
　未定義の変数を使わない まだ代入されていない未定義の変数を使おうとするとエラーになります。 なぜなら、Pythonでは代入＝変数宣言となっており、まだ代入が行われていない変数は存在しないからです。 「変数は代入してから利用する」ことが鉄則です。
適切な変数名をつける 、変数名には任意の名前をつけることができますが、できるだけ内容を的確に表す適切な命名をする必要がある。 プログラムは後から何度も読み返されるため、適切な名前をつけておかなければプログラムがわかりにくくなってしまいます。
変数を異なる用途に使いまわさない Pythonの変数は異なる型を代入できるため、事実上どんな用途にでも使いまわせます。しかし、変数の使い回しは混乱を招き、バグのもととなってしまうためさける。 異なる用途に変数が必要な場合には、適宜新しい変数を作るべきです。

出力変数
Pythonのprint文は、多くの場合、出力変数に使用されています。
* テキストと変数の両方を結合するには、+文字を使用します：
1. x = “勉強”
2. print("Pythonを " + x)
* また、別の変数と変数を結合することもできます
1. x = "Pythonを "
2. y = "勉強"
3. z =  x + y
4. print(z)
* 数値の場合、+文字は、数学的な演算子として機能します
1. x = 3
2. y = 10
3. print(x + y)
* 文字列と数値を結合しようとすると、エラー が出ます 
1. x = 2
2. y = "Python"
3. print(x + y)

変数の開放（削除）
　一度宣言した変数は、後から削除することもできます。
変数を削除するには「del」を利用します。
x = “Python”
del a
print(a) # NameError: name 'a' is not defined
変数を削除する目的としては、メモリの解放です。
変数はあくまでも、メモリですので使いすぎるとパフォーマンスを悪化させる原因となります。変数が増えすぎて、プログラムの実行速度に影響を与えていそうな場合は、「del」を用いて変数を削除するという案を考えても良いかもしれません。
ネットワーク構築（OSPF）

##今回やること
今回はOSPFの構築をしていきたいと思います。
CCNA勉強をしていて、どういうものかは説明できますが、いざ構築しようと思うと
できないと思ったので、実際手を動かしていきます。

##使用ツール
GNS3
IOS: c2600-adventerprisek9-mz.124-17

2651のルータから引っこ抜いたIOSをそのまま入れているので大分古いです。。。

##ネットワーク構成図
最初から難しいのは組めないので、スタンダードな構成で作成。

![OSPF.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/c5795fd2-6205-8a5d-aa2a-13b18f2f07aa.jpeg)

##構築
では早速構築していきましょう。
**今回設定したいのは以下**
１、インターフェイスにIP付与
２、OSPFの設定
３、ネットワークの割り当て


まずは**PC1,2**にIPを振っていきます。
IP振るだけなのでログは省略します。

続いて**R1**から設定していきます。

```
R1#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
R1(config)#int f0/0
R1(config-if)#ip add 192.168.10.1 255.255.255.0
R1(config-if)#no sh
R1(config-if)#exit
R1(config)#
*Mar  1 02:59:20.916: %LINK-3-UPDOWN: Interface FastEthernet0/0, changed state to up
*Mar  1 02:59:21.917: %LINEPROTO-5-UPDOWN: Line protocol on Interface FastEthernet0/0, changed state to up
R1(config)#int f0/1
R1(config-if)#ip add 192.168.12.1 255.255.255.0
R1(config-if)#no sh
R1(config-if)#exit
R1(config)#
```
IP付与が終わったので次にOSPFの設定をいれていきます。

```
R1(config)#router ospf 1
R1(config-router)#net 192.168.10.0 0.0.0.255 area 0
R1(config-router)#net 192.168.12.0 0.0.0.255 area 0
R1(config-router)#end
R1#
```
これでPC1側とR2側向きの設定の投入が完了しました。

続いて**R2**の設定になります。

```
R2#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
R2(config)#int f0/0
R2(config-if)#ip add 192.168.12.2 255.255.255.0
R2(config-if)#no sh
R2(config-if)#exit
R2(config)#int f0/1
R2(config-if)#ip add 192.168.20.2 255.255.255.0
R2(config-if)#no sh
R2(config-if)#exit
R2(config)#
```
まずはIP付与が完了です。
次にOSPFの設定を投入していきます。

```
R2(config)#router ospf 1
R2(config-router)#net 192.168.12.0 0.0.0.255 area 0
R2(config-router)#net 192.168.2
*Mar  1 03:10:07.299: %OSPF-5-ADJCHG: Process 1, Nbr 192.168.12.1 on FastEthernet0/0 from LOADING to FULL, Loading Done
R2(config-router)#net 192.168.20.0 0.0.0.255 area 0
R2(config-router)#end
R2#
*Mar  1 03:10:34.340: %SYS-5-CONFIG_I: Configured from console by console
R2#
```
これで投入完了です。
では状態確認をしていきます。

##状態確認

では**R1**から見ていきましょう。

```
R1#show ip ospf nei

Neighbor ID     Pri   State           Dead Time   Address         Interface
192.168.20.2      1   FULL/BDR        00:00:39    192.168.12.2    FastEthernet0/1
R1#
```
ネイバーの確認はOKそう。
テーブルのほうはどうでしょうか。

```
R1#show ip route ospf
O    192.168.20.0/24 [110/2] via 192.168.12.2, 00:04:53, FastEthernet0/1
R1#
```
AD値、ネクストホップも見てみると設定上OKそうですね。

続いて**R2**を見てみましょう。

```
R2#show ip ospf nei

Neighbor ID     Pri   State           Dead Time   Address         Interface
192.168.12.1      1   FULL/DR         00:00:35    192.168.12.1    FastEthernet0/0
R2#
```
こちらもネイバーは問題なさそうです。
テーブルも見てみます。

```
R2#show ip route ospf
O    192.168.10.0/24 [110/2] via 192.168.12.1, 00:07:47, FastEthernet0/0
R2#
```
こちらもAD値とネクストホップも設定できてそうですね。

##まとめ
今回はOSPFを構築してみました。
**CCNA**の勉強をしていて思いましたが、概要や機能は説明できても、いざ構築となるとコマンドが
パっとでてこなかったり、どのような構成図を組めばいいかが分からなかったりしました。

例えば**CCNA**を取得していたとしても、実際に現場で手が動かなければ意味がない気がしてなりません。
資格を取れば色々できるかな？と思っていた自分がいましたが、やはり大事なのは現場で手を動かせるエンジニアですよね。

資格を取ったから終わりではなく、しっかり手を動かす大事さが身をもってわかりました。

なので自分で色んな構成図を組んでみて、色んなパターンを構築できるように動いていければと思いました。

ゆくゆくは自分でIPsecを組んでみたいと思います。
VPNも構築してみたいなんて思ってます。

以上となります。
【GitHub×AWS】Permission denied (publickey). fatal: Could not read from remote repository.でGit pushできない時の対処法

#前提条件
・AWS Cloud9(IDE)を使用
・GitHubをコードのバージョン管理として使用

#エラー内容

```
$ git push origin master
Permission denied (publickey). fatal: Could not read from remote repository.  Please make sure you have the correct access rights and the repository exists.
```

「公開鍵がないため、許可が却下されました。リモートリポジトリから読み込めません。正しいアクセス権限があるか、レポジトリが存在しているか確認して下さい。」という内容。

#原因
GitHubに公開鍵の登録がないため、アクセス権限がなく拒否をされてしまった。

#対処法
##SSH鍵の作成
1.下記コマンドを入力。`your_email@example.com`はGitHubで登録しているメールアドレスに置き換える。

```
$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
```

2.`Enter a file in which to save the key`で何も入力せず、エンターを押す。こうするとデフォルトのファイルの場所に作成される。

```
> Enter a file in which to save the key (/home/you/.ssh/id_rsa): [Press enter]
```

3.パスワードを設定する。確認も含めて2回入力する。

```
> Enter passphrase (empty for no passphrase): [Type a passphrase]
> Enter same passphrase again: [Type passphrase again]
```

##ssh-agentにSSH鍵を追加
1.バックグラウンドでssh-agentを起動させる。

```
$ eval "$(ssh-agent -s)"
> Agent pid 59566
```

2.ssh-agentにSSH鍵を追加させる。

```
$ ssh-add ~/.ssh/id_rsa
```

##SSH鍵をGitHubアカウントに追加

1.公開鍵の内容を下記のコマンドで表示。表示されたものをコピーする。この時スペースや改行などが入ると認識できないため、入らないように注意する。

```
cat ~/.ssh/id_rsa.pub
```

2.GitHubに行き、Settingsを選択。
![スクリーンショット 2020-08-18 12.57.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/c0e75906-8943-6b92-0fe5-5d9d57569f2a.png)

3.SSH and GPG keys>SSH keys> New SSH keyを選択。
![スクリーンショット 2020-08-18 12.58.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/0a54956c-0d76-489e-44a5-a271ba31a84a.png)

4.Titleに名前をつけて（なんでも良い）、Keyに先ほどコピーした公開鍵を貼り付ける。万が一無駄なスペースなどが入ってしまったら、この時点で削除する。そしてAdd SSH keyボタンを選択する。
![スクリーンショット 2020-08-18 13.01.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/5b5e5909-ac8c-ad90-fa9a-67c4b3888dcf.png)

エラーが出ずに鍵が作成されたら成功。

##SSHの疎通確認
1.下記のコマンドを実行し、最後の方に`...successfully authenticated...`が表示されればSSHの疎通がされたことが確認できる。

```
$ ssh -T git@github.com
```

こうして鍵を登録したアカウントの権限があるリポジトリが、操作できるようになる。

参考
https://docs.github.com/en/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent
https://docs.github.com/en/github/authenticating-to-github/adding-a-new-ssh-key-to-your-github-account
https://utano.jp/entry/2017/10/amazon-linux-github-ssh-key/
AndroidでのUnitTestざっくり入門

- Android Studio 4.0.1
- Kotlin: 1.3.72
- robolectric:4.3
- Windows 10


Androidアプリ開発でUnitTestをします。
出来る限り実機やエミュレータを使わず、JavaVM上で動かしサクサクテストできるような環境を目指します。

## テストケースの種類

### InstrumentedTest
- app/src/androidTest
- 実機もしくはエミュレータ上で実行される
- ExampleInstrumentedTest.ktというサンプルが作られる
- 今回は、こちらはできるだけ使用しない方針です。

### UnitTest
- app/src/test
- PCのJavaVM上で実行される
- ExampleUnitTest.ktというサンプルが作られる
- 今回はこちらをメインで使用していきます。



## テストケース実行

- Android Studio にて該当のパッケージ、クラス、メソッドで右クリック→ Run Testsで実行できる


## テストケース作成

- 該当の `パッケージ名(androidTest)` もしくは`パッケージ名(test)` にクラスを作成
- 実行するテストメソッドに@Testをつけます

```kotlin:SampleUnitTest.kt
package jp.co.sankosc.sample

import org.junit.Assert.*
import org.junit.Test

class SampleUnitTest {
    @Test
    fun addition_isCorrect() {
        assertEquals(4, 2 + 2)
    }
}

```

## robolectricの準備

```gradle:bundle.gradle(app)
android {
  testOptions {
    unitTests {
      includeAndroidResources = true
    }
  }
}

dependencies {
  testImplementation 'org.robolectric:robolectric:4.3'
}
```

sdk=29では動かなかったため、robolectricをskd=28で実行するよう設定します。
app/src/test/resources/[パッケージ] にrobolectric.propertiesファイルを作成します

```properties:app/src/test/resources/jp/co/sankosc/sample/robolectric.properties
sdk=28
```

## Activityのテスト

```kotlin:SampleUnitTest.kt
package jp.co.sankosc.sample

import android.widget.TextView
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.Robolectric
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class SampleUnitTest {
    @Test
    fun testActivity() {
        val activity:MainActivity = Robolectric.buildActivity(MainActivity::class.java).setup().get()
        val text = activity.findViewById<TextView>(R.id.textView).text
        Assert.assertEquals("Hello World!", text)
    }
}
```

## Realmについて

いろいろ試行錯誤しましたが、RealmをRobolectric使ってUnitTestで動かすことはできませんでした。RealmのテストはInstrumentedTestの方でやるしかなさそうです。

また、Realmを使ったアプリを作っているとUnitTestが動かなくなる場合があります。
Realmの初期化を、Applicationクラスで行っている場合で、この場合はテストのときはApplicationクラスでRealmの初期化をしないようにしておく必要があります。

何もしないApplicationクラスを作る

```kotlin:AppUnitTest
package jp.co.sankosc.sample

import android.app.Application

class AppUnitTest : Application()
```

robolectric.propertiesでRobolectricのApplicationクラスを指定する


```properties:app/src/test/resources/jp/co/sankosc/sample/robolectric.properties
sdk=28
application=jp.co.sankosc.sample.AppUnitTest
```


Realmの準備はこちらをご参照ください：[Android,KotlinでRealm](https://qiita.com/nozaki-sankosc/items/35516da505ca4f0655ec)
datetime, time

>datetime モジュールは、日付や時刻を操作するためのクラスを提供しています。
日付や時刻に対する算術がサポートされている一方、実装では出力のフォーマットや操作のための効率的な属性の抽出に重点を置いています。

###今の時間が知りたい場合
isoformatとすれば文字列に変換することができる
自分なりに表示形式を変える事もできる

```python:qiita.py
import datetime

now = datetime.datetime.now()
print(now)
print(now.isoformat())
print(now.strftime('%d/%m/%y-%H-%M-%S-%f'))
```

実行結果

```
2020-08-18 16:57:51.138416
2020-08-18T16:57:51.138416
18/08/20-16-57-51-138416
```

###年月日のみを表示

```python:qiita.py
import datetime

today = datetime.date.today()
print(today)
print(today.isoformat())
print(today.strftime('%d/%m/%y'))
```

実行結果

```
2020-08-18
2020-08-18
18/08/20
```

###時間のみ表示

```python:qiita.py
import datetime

t = datetime.time(hour=1,minute=10,second=5,microsecond=100)
print(t)
print(t.isoformat())
print(t.strftime('%H-%M-%S-%f'))
```


実行結果

```
01:10:05.000100
01:10:05.000100
01-10-05-000100
```

###過去の時間を扱いたいとき
１週間前

```python:qiita.py
import datetime

now = datetime.datetime.now()

print(now)
d = datetime.timedelta(weeks=-1)
print(now+d)
```

実行結果

```
2020-08-18 17:27:45.640006
2020-08-11 17:27:45.640006
```


一年前

```python:qiita.py
print(now)
d = datetime.timedelta(days=365)
print(now-d)
```
実行結果

```
2020-08-18 17:26:48.128885
2019-08-19 17:26:48.128885
```

###time
>time.sleep(secs)
与えられた秒数の間、呼び出したスレッドの実行を停止します。

```python:qiita.py
import time
print("hei")
time.sleep(5)
print("#####")
```


epochtime
>協定世界時 (UTC) での1970年1月1日午前0時0分0秒から形式的な経過秒数（すなわち、実質的な経過秒数から、その間に挿入された閏秒を引き、削除された閏秒を加えたもの）として表される

```python:qiita.py
import time
print(time.time())
```

実行結果

```
1597739333.901404
```

###使い所
ファイルが存在しなければ作成
存在すれば、現在の時刻が記載されたファイルのコピーが生成される

```python:qiita.py
import os
import shutil
import datetime
now = datetime.datetime.now()
file_name = "test.txt"
if os.path.exists(file_name):
    shutil.copy(file_name, '{}.{}'.format(
        file_name,now.strftime('%d_%m_%y_%H_%M_%S')
    ))
with open(file_name,'w') as f:
    f.write('test')
```
適応障害もちの生活保護だった元プログラマーが仕事に復帰できた話

## はじめに
　私は学生の頃から適応障害だったらしく（今は通院している病院のカルテに「適応障害・気分障害」と書かれている身です。）とにかく頭の中で考えが詰まってしまうとそこから進まない。会社の理解も得られないと言うことがあり、5年近くの間は仕事もできずに家でこもってました。（一応現在も精神福祉手帳3級をもってます）
　Qiitaにこんな記事を書いて良いのか？という気がしますが…

## 適応障害って？
[Wikipedia](https://ja.wikipedia.org/wiki/%E9%81%A9%E5%BF%9C%E9%9A%9C%E5%AE%B3#%E7%97%87%E7%8A%B6)によると…

- 社会生活や職業・学業などにも支障をきたし、生活機能の低下や、業績・学力の低下、場合によっては就業・就学そのものが不可能になる場合がある。

という部分が自分には当てはまるのですが…

- 特定の作業ができない。
- 無自覚なケアレスミスをしてしまう。
- 頭の中で煮詰まっていつまでも考えて時間を無駄に費やしてしまう。

などの症状が実際にあります。

## 過去を振り返ると…
　もともとパソコン好きで、プログラムすることが好きだったので、ソフト開発の仕事についていましたが、ある程度軌道に乗ってから、ストレスによるうつや適応障害にに悩まされるようになり、さらに

- ミスをするのが許されない。（一人に任せっきりでの他の人によるチェックが行われない）
- 同僚の仕事を増やしてはいけない。
- 任された仕事はすべて責任を持つ。

というようなことがあり。それがうまくいかないのが原因で、どんどん症状がひどくなっていき。最終的に『責任のある仕事はできない』という理由でその会社を辞めることになりました。

## 障がい者とは…
　仕事ができなくなり、いろんな物を失った時、働けないので障害者手帳(精神福祉手帳）の申請をして、障害厚生年金と生活保護による生活になりました。でも見た目には誰も障害を持っているなんて思ってくれませんし、家族にすら見放されました。『二度とプログラマーにならない』と心に誓いました。
　それから3〜4年後に偶然、とある障害者福祉の施設とつながり、その後1年間スタッフとして活動してましたが、そこに集まる人達は本当にさまざまな人達がいました、身体障害だけでなく精神障害を持たれた方も多くいました。すごい才能を持っている方、障害を持っていてもしっかりした考えを持っておられる方、いろんな問題を起こしてしまう方、本当に十人十色でした。作業所に通っている方もいればそうで無い方もおられました。そう言う出会いの中で障害とは何か？をもの凄く考えさせられました。でも、一般的な職には就けないし、私から見て社会の隅に投げ出された世界のようでした。そして生活保護から抜け出せない方も多かったです。
　スタッフだった頃にそこで今の嫁に出会いました。1年が経ち、結婚を許されて今の職に就きました。生活するには稼がないといけません。そして、偶然職安でアルバイト募集していた今の会社にアルバイト入りました。『二度とプログラマーにならない』とは何だったのか？

## 現在の職場は

職に就いて1年後ぐらいから

- 30分考えて判らなかったら周りに訊くこと。

　という単純明快なルールができました。もともと自分で何でも解決しようとするというメンヘラにありがちな思考をするのと、頭が煮詰まっていると先に進まなくなる思考、白黒思考などが合わさって、仕事の障害になってしまいます。緊張感を持つのはいいけど極端に緊張することも多いので、このルールに助けられてはいます。確かに、自分は他人を頼れない性格なので、これは本当に助かりました。

## GitHubを使う
　昔の職場でもVCSと言うものはあったのですが、デグレ防止なだけで、実際使いにくかったのですが、今の職場ではGitHubを使います。個人的にオープンソースのライブラリなどをとってくるのにGitHubを使っていましたが、『オープンソースのソースを配っている場所』と思いっきり勘違いしていました…
　GitHubもVCSの一つだと言うことを理解しましたが、約6年のブランクでこんなに使いやすいVCSがあるのか…と感じました。
　入りたての頃は（偶然?）Issueとかプルリクエストというものは無かったのですが、プルリクエストの文化が導入され、そしてZenHubを併用してのIssue管理に置き換わっていきました。私にとっては全く新しい概念だったので、戸惑いはしましたが、多少のヘマ（developにコミットしてpushとか）なども有りましたがなんとか覚えていきました。

## スクラム開発
　もともと公私共々一人でプログラムをすることが多かったのですが、それでは作業効率もあがりません。
　しばらくしてから[スクラム開発](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%AF%E3%83%A9%E3%83%A0_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA))という考え方を取り入れるようになり、チームが協力し合って仕事を進めていく形に変化してきました。

 この体制になってから、GitHub（ZenHub)で細分化されたIssueをこなしていく（できる範囲の責任感を持てる）のが自分に良い感じにマッチして、仕事がすいぶんやりやすくなりました。とくに特定分野に強い人をそのIssueを担当するなど、ミーティング含めて色々学ぶことができました。（逆に別分野を学ばせるためにあえてIssueを回されることもありますが…）

　もっとも、私もまだ未熟者で、ケアレスミスとか思い込みとかいろいろ問題になりました。それは何とかしなければいけないのですけれども…

## テレワーク（リモート）はどうか？
　私は古い人間なので、『仕事は会社で行うべき』という考えの方が強いです。とはいえ最近のコロナ禍事情でテレワークがある程度必要になり、最初の頃は家族が仕事内容をのぞき見してしまうなどの問題がありましたが（実際のぞき見フォルターを購入しましたが）、今では頭が詰まったときなどに、嫁が軽い運動をレクチャーしてくれるなど、協力的になりました。嫁が仕事を覗く事もほぼ無くなりました。

## あとがき - 仕事は楽しいか？
　『仕事が楽しい』というと、昭和世代（私もだ）はだいたい『仕事は厳しくて当然だ！』と否定する人が多いですが、今となっては仕事は楽しくなければできないと考えます。（もちろん責任とか自分で調べる、ミスを減らすなどは必要ですが）仕事が楽しいと、『あれもやりたい、これもやりたい』って感じになりますし、いろいろなアイデアも出ます。昔から趣味でDTMで曲作りしてますが、仕事が快調だと趣味も結構進みます。
　あと、書き忘れてましたが、会社がちゃんとしたフレックスタイム制で（それまではフレックスタイムと謳いながら全然フレックスではなかった）、朝方に体調悪くても持ち直せば仕事ができますし、フレックスのありがたみを感じることができます。

書いててこれが技術的な記事なのか?と言われると、違うんじゃない？って思いましたが、自分は障がい者だけど仕事できてるよって人が増えてくれることを願いつつ、もっと仕事ができるようになりたいと感じるこの頃です。
わかった気になるSAML認証

何番煎じ感は否めませんが、自身の学びのためにアウトプットするものですのでご了承ください。

## そもそもSAMLって何？ :thinking: 

SAMLは **Security Assertion Markup Language** の略称で、XMLの形式で定義された認証のための情報です。
これをサーバ間でやりとりすることで、認証を実現します。

XMLの中には、暗号化、署名の方式や証明書、Issuer、Assertionなどが記載されています。

定義したのは[OASIS](https://en.wikipedia.org/wiki/OASIS_(organization))という非営利団体で、2005年にリリースされたSAML 2.0が標準になっています。

## じゃあSAML認証って何？ :thinking: 

登場人物は、以下の3人です。

- ユーザ：サービスを使いたいエンドユーザ（のブラウザなどのユーザエージェント）
- SP（ServiceProvider）：SaaSなど、サービスを提供する人で、アクセスしてくるユーザが何者か知りたい
- IDP（IdentityProvider）：ユーザ情報を管理していて、ログインの仕組みを提供する

このSP、IDP間で上記SAMLのやりとりを行い、最終的にIDPからSPへユーザの認証情報が渡され、ユーザはサービスを利用できるようになります。

複数のサービス（SP）に対して、IDPは1つで良い（=アカウントも1つあればいい）ので[Single sign-on(SSO)](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%B3%E3%82%B0%E3%83%AB%E3%82%B5%E3%82%A4%E3%83%B3%E3%82%AA%E3%83%B3)だと言われます。

## 認証の流れ、、、の前に :coffee: 

SAML認証では実際の認証プロセスの前に、SPとIDP間でmetadataと呼ばれるXMLを交換する必要があります。ここで、何を暗号化・署名するか、どういったアルゴリズムで行うか、公開鍵などを事前に共有します。
交換の仕方はSP/IDPによって様々なようです。

## 認証の流れ :surfer: 

SAML認証のフローには、下記2つの始め方があります。

- SP-Initiated：ユーザは、まずSPの特定のURLを踏むところから始まる（例えばSaaSのログインページ）
- IDP-Initiated：ユーザは、いきなりIDPの特定のURLを踏んで、ログインするところからはじまる

ここでは`SP-Initiated`を選択しています。

また、SP/IDPのやりとりの方法（バインディング）にも下記の種類があります。

- HTTP-Redirect：URLパラメータにSAML情報を仕込んでやりとりする
- HTTP-POST：RequestBodyのSAML情報を仕込んでやりとりする
- HTTP-Artifact：ArtifactというIDを作成し、次のSOAPのような直接通信でやりとりするらしい
- SOAP：SP/IDP間に直接通信パスがある場合に使われるらしい

ここでは`HTTP-POST`のやり方を選択します（Redirectの場合、Html FormをPostする部分がRedirectになる）。

初回アクセス時の認証フローは下図の通りです（セッションが保存された２回目以降のアクセスの場合、ログイン画面での認証情報入力を省略できます）。
署名はリクエスト・レスポンス共に実施し、暗号化はレスポンスのみ実施しています。

![saml_auth_flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221423/7048adaf-8b29-36df-b5f5-3bd4a00ded6c.png)

## SP開発時に便利なあれこれ :tools: 

### [Chrome extension - SAML Tracer](https://chrome.google.com/webstore/detail/saml-tracer/mpdajninpobndbfcldcmbpnnbhibjmch)

SAMLのやりとりをトレースできるGoogleChrome拡張。
jsonファイルでExport/Importできて便利 :clap: 

![saml tracer image](https://lh3.googleusercontent.com/ey22DDHr2hs8TUjifnxwVJITzOYJAYZKY2M81F9zf6yk1q5c488vxgsCJaCZIv4zhZusNlsOJu4=w640-h400-e365-rj-sc0x00ffffff)

### [Onelogin - SAML Developper tools](https://www.samltool.com/online_tools.php)

Code/Decodeや署名、検証など、SAMLのデバッグに重宝するサービスがカテゴライズされて提供されています。
便利 :clap: 

### [Docker container image - test-saml-idp](https://hub.docker.com/r/kristophjunge/test-saml-idp/)

Apacheに[SimpleSAMLphp](https://simplesamlphp.org/)を抱き合わせた構成になっていて、すぐ立ち上げてIDPとしてテストできました。また、ここに書かれていない設定をしたい場合、[SimpleSAMLphp](https://simplesamlphp.org/)のドキュメントを見ながらphpを書いて、volume mountすれば反映できました。
便利 :clap: 

## まとめ :ramen: 

わかりやすくまとめたつもりが、全体的に薄いですね :innocent:
各SNS等埋め込みまとめ

## 概要
いざSNS埋め込み作業が発生した時用の、忘備録

## YouTube
1. 動画の評価が並んでいる列の`共有`を押す
![スクリーンショット 2020-08-18 13.54.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265363/55a71dc7-5ef5-88e3-401e-7abc5318e7e7.png)

2. `埋め込む` を選択
![スクリーンショット 2020-08-18 13.54.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265363/8b9ed3fc-a43b-a9ed-9331-de4bcc412868.png)

3. 動画の埋め込み というタイトルのつけられたコードをコピーしてhtmlに貼り付ければ完了
![スクリーンショット 2020-08-18 13.54.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265363/e8b0f227-4793-3df0-dc2f-cb69aa6bc648.png)


## Twitter
以下に詳しく書いてある
https://developer.twitter.com/en/docs/twitter-for-websites/tweet-button/overview

ツイートボタンの形はカスタマイズしたいことが多いので、カスタマイズできるボタンを出せるようにする
雛形は以下の通り

```
    <a class="twitter-share-button"
        href="https://twitter.com/intent/tweet">
        Tweet</a>
```
これでスタイルを自由に定義できるボタンが作れる。class名も自由にできる

`?text=Hello%20world` このように URI パラメータの text を設定することで、出力する文章を設定することができる

他、data 属性を追加することで、色々なパラメータが設定可能
詳しくは[こちら](https://developer.twitter.com/en/docs/twitter-for-websites/tweet-button/guides/parameter-reference1)を参照

## Facebook
- [いいねボタン](https://developers.facebook.com/docs/plugins/like-button)
- [シェアボタン](https://developers.facebook.com/docs/plugins/share-button)
- [フォローボタン](https://developers.facebook.com/docs/archive/docs/plugins/follow-button/)
  - フォローボタンは2018年に廃止された

## Pinterest
[こちら](https://developers.pinterest.com/tools/widget-builder/?)

## GoogleMap
1. 目的地を開き、`共有` ボタンを押す
![スクリーンショット 2020-08-18 17.35.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265363/b3ea7ad0-5e39-9785-67c4-1eab5ba626f6.png)

2. `地図を埋め込む` タブを選択し、`HTMLをコピー` をクリック、HTMLに貼り付けて完了
![スクリーンショット 2020-08-18 17.35.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265363/482bee6e-4e1a-b5f6-8b89-53d970bf65e4.png)

## Instagram
1. シェアしたい画像（動画）を選択すると出てくる画像右上の ... をクリック
![スクリーンショット 2020-08-24 17.27.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265363/a7d6db9f-b104-ed49-ccdf-2af3e6f54146.png)

2. 埋め込みを選択
![スクリーンショット 2020-08-24 17.27.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265363/f49eb5e4-9c0a-1079-cac5-7f108c46f5d5.png)

3. 埋め込みコードをコピーしてHTMLに貼り付ける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265363/c954af48-29f6-10a4-7422-8832fbdb58c2.png)
スクリーンショット 2020-08-24 17.27.37
モジュールの読み込みと使い方

# まえがき

この記事はRUSTチュートリアルをZerobillbank社内メンバー（有志）で勉強がてら、可能な限りわかりやすく内容を書き出す企画の一部です。  

なお、初学者のため（略）という免責を打ちつつ間違いなどあればコメントで教えていただけますと一同嬉しく思います！

# 概要

前項ではモジュールの作り方について説明しました。
本項では、モジュールを読み込む方法と使い方について説明します。

# 読み込み方

まず外部ライブラリを読み込む場合の読み込み方について。

```rust
pub mod a {
    pub mod series {
        pub mod of {
            pub fn nested_modules() {}
        }
    }
}

// use {library} で読み込み
use a
```

上記のように、 `use` の後に読み込むモジュールを指定します。
続いてモジュールの使用の仕方について説明します。

# フルパスで指定する

スコープを全て記述して使用する方法です。

```rust
pub mod a {
    pub mod series {
        pub mod of {
            pub fn nested_modules() {}
        }
    }
}

fn main() {
    a::series::of::nested_modules();
}
```

# スコープをuseで定義して使用時に省略する

続いてタイトルの通り `use` キーワードにスコープまで記述して、使用時の記述では省略する方法です。

```rust
pub mod a {
    pub mod series {
        pub mod of {
            pub fn nested_modules() {}
        }
    }
}

use a::series::of;

fn main() {
    of::nested_modules();
}
```

# enum などの列挙型を使用する

enumについても名前空間扱いなので、列挙子を使用することも可能です。

```rust
enum TrafficLight {
    Red,
    Yellow,
    Green,
}

use TrafficLight::{Red, Yellow};

fn main() {
    let red = Red;
    let yellow = Yellow;
    let green = TrafficLight::Green;
}
```

一つのライブラリから複数の要素をスコープに含めたい場合、enumに限らず **'波カッコ'** と **'カンマ'** 区切りで記述することで使用可能です。

# 全ての名前をスコープに導入する

列挙型もそうですが、一括してスコープに導入したい場合もあるかと思います。
そういったときは `glob` と呼ばれる演算子を使うことで全て導入することが可能です。

```rust
enum TrafficLight {
    Red,
    Yellow,
    Green,
}

// 正規表現の * が glob と呼称される
use TrafficLight::*;

fn main() {
    let red = Red;
    let yellow = Yellow;
    let green = Green;
}
```

# super を使用して親モジュールにアクセスする

rustでは、そのファイルからみて配下の階層にある関数にアクセスを行うことがデフォルトの挙動になります。

```
communicator
 ├── client
 ├── network
  |  └── client
 └── tests
```

例えば前項で作成した communicator ライブラリの階層でみたとき、testsフォルダからは
どのモジュールにもアクセスはできません。

testsディレクトリからclientディレクトリ配下のモジュールにアクセスするとき、
Linuxでいう１階層上がる処理が必要になります。
この１階層上がるためには `super` という記述を使用します。

```src/lib.rs
pub mod client;
pub mod network;

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        client::connect();
    }
}
```

上記のもともと存在していたlib.rsに記述されているテストコード `#[cfg(test)]` では、
tests内にある `it_works` 関数から `client::connect()` を実行しようとしていますので、
読み込めずエラーが発生してしまいます。
*(そもそも外部モジュールの読み込みを行う記述もないので追記が必要です。)*

ここにsuperを含むモジュール読み込みの記述を追記します。

```rust
#[cfg(test)]
mod tests {
    use super::client;

    #[test]
    fn it_works() {
        client::connect();
    }
}
```

こうすることで、エラーが発生することなく `cargo test` が実行できるようになります。
RuntimeError: DataLoader worker (pid(s) ~) exited unexpectedlyの原因と解決法

# 実行環境
- Windows10 Home
- torch 1.1.0

# PytorchでDataLoaderを使おうとしたところ以下のエラーが発生

```:実行したプログラム
torch.utils.data.DataLoader(
                            dataset = dataset,
                            batch_size = 100,
                            shuffle = True,
                            num_workers = 8)

```

```:エラー文
RuntimeError: DataLoader worker (pid(s) ~) exited unexpectedly
```

# 原因
メモリ不足が原因

# 解決策
num_workersをエラーが出ない値まで小さくする
ex) `num_workers = 0`　等
【Laravel】ORM

こちらの記事は以下の書籍を参考にアウトプットとして執筆しました。
[PHPフレームワーク Laravel入門 第2版](https://www.amazon.co.jp/dp/B08625YD7H/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)


#検索とスコープ
スコープとはレコードを絞り込むた目の機能
##where
IDによる検索はfindうぃ使えばできた。
他の検索はwhereと同じようなものがモデルクラスにも用意されている。

###複数のレコードを取得
```php5
$変数=モデルクラス：：where(フィールド名,値)=>get();
```

###最初のレコードだけを取得
```php5
$変数=モデルクラス：：where(フィールド名,値)=>first();
```

このwhereはビルダクラスのインスタスを返す。
これはDBクラスビルダとは違いうがとても似ていて、ほとんど同じを考えて構わない

##スコープの利用
whereはDBクラスとナジ感覚で操作できる。しかしモデルクラスのほうが使い勝手は良い。
モデルクラスを使うさらなるメリットとしてスコープがある。
これは特定条件の検索ができる。
whereで複雑な検索をしようとすると、whereをいくつもつなぎ合わせるとわかりにくくなるがスコープを使うとわかりやすくなる

スコープには
- ローカルスコープ
- グローバルスコープ

の2つがある

###ローカルスコープ
モデル内にメソッドを酔いするもの。
呼び出したときだけスコープが機能する。
###グローバルスコープ
ローカルスコープは
検索条件を設定してBuilderを返すメソッドを用意してそれを呼び出すもの。
グローバルスコープは処理を用意していおくだけでそのモデルでのすべてのレコード取得が適応される。

専用のメソッド通いされていおり、それを利用する。
###bootメソッド
処理の組み込みはモデルがサレク生される際の初期化処理で実行する。

####boot初期がメソッドの基本
```php5
protected static function boot()
{
  parent::boot();
  //初期化処理  
}
```
出典：[PHPフレームワーク Laravel入門 第2版](https://www.amazon.co.jp/dp/B08625YD7H/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)

静的メソッドのためモデルインスタンス自身を利用する方法は欠けない。
グローバルスコープでの処理の用意はaddGlobalScopeを使う

```php5
static::addGlobalScope(スコープ名,function(Builder $builder))
{
  //絞り込み処理
}
```
出典：[PHPフレームワーク Laravel入門 第2版](https://www.amazon.co.jp/dp/B08625YD7H/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)

これはグローバルスコープを追加するメソッドでこれをオーバーライドしてグローバルスコープを追加する
AttributeError: module ‘torch.utils’ has no attribute ‘data’の解決法

# 実行環境 
- Windows10 Home
- torch 1.1.0

## PytorchでDataLoaderを使おうとしたところ以下のエラーが発生

```:実行したプログラム
import torch

torch.utils.data.DataLoader(
    dataset = dataset,
    batch_size = 100,
    shuffle = True,
    num_workers = 0)
```
```:エラー文
AttributeError: module ‘torch.utils’ has no attribute ‘data’
```

# 解決策
`import torch`ではなく、`import torch.utils.data`とすると解決する。
javascript を使ったFizzBuzz

```javascript
<!doctype html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>fizzbuzz</title>
    </head>
    <body>
        <script>
            for (var i = 1; i < 101; i++) {
                if (i % 3 === 0 && i % 5 === 0) {
                    document.write("FizzBuzz" + "<br/>");
                } else if (i % 3 === 0) {
                    document.write("Fizz" + "<br/>");
                } else if (i % 5 === 0) {
                    document.write("Buzz" + "<br/>");
                } else {
                    document.write(i + "<br/>");
                }
            }
        </script>
    </body>
</html>

```

もし３と５で割り切れるかどうかの条件を最後に持ってきた場合、たとえば１５なら先に５のみで割り切れると判定されてbuzzが表示されてしまう。（この問題に初めて取り掛かった頃はこれに気づかなかった）
あと、一つづつ改行するやり方も検索しても何故かなかなかヒットせず、困った記憶がある。
そんなことで困りたくないですね。
Pythonのスクリプトを実行するための環境構築(for mac)

最近Instagramをやっていて思うこと、

「いいね、自動化できんかな〜」

を現実化するために調べたところ、[この記事](https://ang.tokyo/insta_auto_likes/)を見つけました。
しかしPythonワカラナイ私は環境構築がキツかったので、やったことを残しておきます。

## 手順
(1) pipのアップグレード

```
$ python3 -m pip install --upgrade pip
```

(2) seleniumのインストール

```
$ pip3 install Selenium
```
(3) chromedriverのインストール

```
$ brew tap homebrew/cask
$ brew cask install chromedriver
```

これで、`python3 <ファイル名.py>`が実行できるようになりました〜:v_tone1:
HTTP -> HTTPSのリダイレクトはELBで行う方がスマートかもしれない　(Nginxでリダイレクトを行う方法あり)


# やりたいこと
AWSのロードバランサー(ELB)を使用しており、ELBにSSL証明(ACM)を付与し、httpsアクセスが可能な状態で
httpリクエストをhttpsにリダイレクトする設定をしたい

前回記事でNginx公式docを調べていると、
すべてのトラフィックに対してif...といった処理を行うことは負荷の観点から望ましくないということを学んだ

[wwwなしの、SSL(https)にリダイレクトしたいときのNGINXの設定 -Route 53 + ELB (ACM) + EC2構成- - Qiita](https://qiita.com/naokit-dev/items/5df0d563492c1a70cd57)

**今回は、web server(Nginx)を使用せずともELBでHTTP -> HTTPSリダイレクトが可能だという事がわかったので、実践しメモを残します**
(以下、方法２が今回の内容です)


# 環境
以下のような環境を想定しています
- DNS (Route 53) -> ELB -> EC2 (NGINX -> Puma) 
- SSL証明: ACM
- ELB <-> Nginx (port: 80) 
- Rails 6 (config/environments/production.rb: config.force_ssl = true)

# 注意すること
単純にwebサーバー(Nginx)でリダイレクトするとうまくいかない

以下の記事で書きましたが、
HTTPリクエストも、HTTPSリクエストもELBからの転送に対してwebサーバー（Nginx）はport 80でlistenされているということに注意が必要

[wwwなしの、SSL(https)にリダイレクトしたいときのNGINXの設定 -Route 53 + ELB (ACM) + EC2構成- - Qiita](https://qiita.com/naokit-dev/items/5df0d563492c1a70cd57)

このような条件で単純にNginxで

```
server {
    listen 80;
    return 301 https://$host$request_uri;
```

とすると
HTTPリクエスト -> ELB(port 80) -> Nginx(listen 80) -> (上記設定によりリダイレクト) ->
-> HTTPSリクエスト -> ELB(port 443) -> Nginx(listen 80) -> (再リダイレクト) ->
-> HTTPSリクエスト...
とリダイレクト繰り返すことになってしまう

# 方法1　NginxでのリダイレクトをHTTPリクエストの場合のみに限定

公式 doc
[ELB を使用して HTTP トラフィックを HTTPS にリダイレクトする](https://aws.amazon.com/jp/premiumsupport/knowledge-center/redirect-http-https-elb/)

上記参考に
HTTPSリクエストに対してはNginxでリダイレクトを行わないようにする必要があるというのが以前殴り書いた記事の意図

[HTTP > HTTPSへのリダイレクト設定後にNGINXがリダイレクトを繰り返す問題への対応 - Qiita](https://qiita.com/naokit-dev/items/8abcef514af230ddc178)

以下のように書くことでHTTPSリクエストでない場合のみリダイレクトすることができる

```
server {
    listen 80;
    if ( $http_x_forwarded_proto != 'https' ) {
      return 301 https://$host$request_uri;
    }
```

ただしELBから転送されてきたトラフィックは全てport 80でlistenされているので
この方法だと全てのトラフィックに対してif...処理が適応される

# 方法２　ELBでHTTPSリダイレクト

webサーバーの前にELBのみでHTTPSリダイレクトができるそうです

**方法1では全てのトラフィックに対して都度if以下の処理が行われるため
非効率的で、こちらの処理のほうが無駄がないように思います**

参考: 公式doc 
[Application Load Balancer を使用して HTTP リクエストを HTTPS にリダイレクトする](https://aws.amazon.com/jp/premiumsupport/knowledge-center/elb-redirect-http-to-https-using-alb/)

上記参考に設定すると以下のようになります
![スクリーンショット 2020-08-18 16.34.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649386/57432083-44ce-a51b-835b-e5b60a690acb.png)

HTTP: 80 -> HTTPS: 443へリダイレクト
HTTPS: 443 -> Target-group (EC2, web serverへ)

希望するHTTP-> HTTPSリダイレクトが実現できております
[SwiftUI] 移除 Navigation View 上面 Back Button 的 Title

想要消掉的就是這個東西：
![ContentView_swift.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41979/38ab18db-6d92-9c06-4838-9ee6b2df5187.png)


## 基礎的畫面

由兩個畫面，第一個畫面是一組 NavigationView 、 NavigationLink ，第二的畫面就是一個簡單的 Text 。

``` swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView() {
            NavigationLink(
                "Next",
                destination: Text("Second Page").navigationBarTitle("Second")
            )
                .navigationBarTitle("Title", displayMode: .inline)
        }
    }
}

// Preview
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
```

| 第一畫面 | 第二畫面 |
|:---:|:---:|
| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41979/7403e8c8-5dca-6c55-6af4-016fc697f344.png) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41979/c0ec0dae-4371-4a18-4efc-1625ea792dcc.png) |

## 新增按鈕？

這在 UIKit 的時代也是有人這樣做過。在網路上看有一些解法是重新新增一個按鈕，放入如下的圖片，再把處理觸控事件的地方手動觸發 `dismiss()` ，但是這樣子箭頭大小和原生的箭頭不同，還要加上一些有的沒有的設定覺得有點麻煩。

``` swift
Text("Second Page")
    .navigationBarTitle("Second")
    .navigationBarItems(leading: Image(systemName: "chevron.left").foregroundColor(.accentColor))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41979/9707f8e6-b3ce-e267-943a-74a6f5e24555.png)

右側是客製化的按鈕，可以看得出來粗細和大小和原廠的箭頭還是有點距離。

於是就放棄這樣的解法。怎麼綁定到 dismiss 可以參考 [這個 Stack Overflow 的解答](https://stackoverflow.com/a/57594164)。

## 解法：根據 isActive 調整 Title

雖然在 UIKit 有更漂亮的做法，不過在 SwiftUI 這應該是目前最好的解法。

在 NavigationLink 有一個初始化方法 [init(_:destination:isActive:)](https://developer.apple.com/documentation/swiftui/navigationlink/init(_:destination:isactive:)-3v44) ，有一個 isActive 可以用。

於是我們可以在 ContentView 裡新增一個屬性 `isActive` 讓我們來綁定。

由於這邊是同一個範圍的綁定，因此我們使用 `@State`

``` swift
@State var isActive: Bool = false
```

NaigationLink 則改成這樣：

``` swift
NavigationLink(
    "Next",
    destination: Text("Second Page").navigationBarTitle("Second"),
    isActive: $isActive
)
```

透過這個綁定，當 NavigationLink 被開啟之後，isActive 會變為 true 反之則為 false 。

### 根據變化變化標題

原本的設定：

``` swift
.navigationBarTitle("Title", displayMode: .inline)
```

可以改成這樣：

``` swift
.navigationBarTitle(!isActive ? "Title" : "", displayMode: .inline)
```

也就是當下一個畫面被開啟的時候，我們就把標題的內容清空。

## 修改後的結果

修改後的程式碼如下

``` swift
struct ContentView: View {
    @State var isActive = false
    
    var body: some View {
        NavigationView() {
            NavigationLink(
                "Next",
                destination: Text("Second Page").navigationBarTitle("Second"),
                isActive: $isActive
            )
                .navigationBarTitle(!isActive ? "Title" : "", displayMode: .inline)
        }
    }
}
```

### 結果圖

| 第一畫面 | 第二畫面 |
|:---:|:---:|
| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41979/27a1fc27-3bcf-316a-c41d-516a85f43434.png) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41979/268dbd25-e162-3b19-371e-ee8ffc40a7cd.png) |

以上
制作実績 の一覧

LP制作
・鮪笑　　https://maguro-yu-shou.com/
・Animove　https://i-style.co.jp/animove/
・旬輝　http://www.shun-ki.jp/
・株式会社マルマサ工業　https://marumasa-kougyo.com/
・すずとら　http://www.suzutora.info/
・まちづくりセンター採用サイト　https://www.shizuoka-kjm.or.jp/recruit/
・株式会社池田製作所IKEDA Re:birth　　https://ikeda-mfg.co.jp/lp/
・株式会社フレアー　https://www.flair-staff.co.jp/ja/



ホームページ制作（Wordpress構築）
・小林生花店　　https://kobayashi-flower.com/
・静岡県菓子工業組合　https://shizuoka-kashi.com/
・三保ビーチステーション　https://beachstation-miho.com/
・ビーチホテルゴーシーズ　　https://beach-hotel-goseas.com/
・ISTYLE　https://i-style.co.jp/
・あたしnoエステ　　https://atashi-no-esute.com/
・株式会社イケガヤ溶接工業  https://ikegaya-welding.com/
・梅ヶ島くらぶ　 http://umegashima.love/
・株式会社ラプト　https://www.rapt.co.jp/
・株式会社ラプト動画サイト　https://www.rapt.co.jp/raptmovieworks/
・株式会社ラプトシステム部サイト　https://www.rapt.co.jp/system/
・児玉電機工業株式会社　https://kodama-denki.com/
・株式会社エー・エム・ティー  https://a-m-t.co.jp/
・ワシロック工業株式会社（Wordpress構築のみ）　　https://www.washilock.co.jp/
・静岡県プロフェッショナル人材戦略拠点（Wordpress構築のみ）　https://pro-shizuoka.com/
・株式会社ノーブル（Wordpress構築のみ）　http://www.noble-lofty.co.jp/
・株式会社タキ倉庫リクルートサイト（Wordpress構築のみ）　http://www.recruit.taki-g.co.jp/
・株式会社HOQ（Wordpress構築のみ）　https://www.hoq.jp/


#スペック
使用言語 / HTML５/ CSS3 / SCSS/ Javascript / JQuery / PHP/ Wordpress

タスクランナー　/  gulp

PhotoshopやIllustrator、Figma等のデザインデータからのコーディングでは正確な数値を測り、デザインデータと誤差が無いように作業をしています。
SEOの観点からも意識したコーディングを心がけています。
また、サイト崩れが無いように、PC、タブレット、スマートフォンのデバイスチェックは重点的に行っています。
UITableView.tableHeaderViewにNibファイルから設定する場合

UITableView.tableHeaderViewにNibから生成されたViewを設定した時に、高さが0になってしまう現象に遭遇しました。
（何度かはまっている）

## 探してみた

`UITableView tableHeaderView auto layout`でググってみても解決策が出てきませんでした。

以下は試してみましたができなかったものです。
- https://qiita.com/AkkeyLab/items/9864c741b9adb633b321
- https://bugsdb.com/_en/debug/094735585326ee5e720638561d7e4ea6


## 解決方法

- Nib側のautoresizingで上下矢印の`Flexible Height`に印がついているので、外します。（上下矢印が消える）
- 中身について上下左右にAutoLayoutで制限をつけます
- UITableView.tableHeaderViewにNibから生成したViewを入れます
- AutoLayoutエラーが起きていないことを確認します

![スクリーンショット 2020-08-18 14.49.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297014/7abd0cb4-b012-d067-3461-c66ce804b5d7.png)

## 考察
- NibからUITableView.tableHeaderViewに設定すると、AutoLayoutではなくAutoResizingMaskで設定される
    - translatesAutoresizingMaskIntoConstraintsの設定と思われる
Pythonで配列から辞書に変換する方法【応用編】

# 概要

Pythonで配列から辞書に変換する方法を10サイトくらい閲覧しました。
「よくある入門解説ブログには掲載されていないパターン」を見つけましたので応用編と称して紹介します。

# よくある例

配列から辞書に変換する方法で検索すると、キーと値が１：１の例が多数ヒットします。

```py:test002.py
key2=["name","age","kind"]
data2=["siva",4,"dog"]

print(dict(zip(key2,data2)))
```

キーと値が別々の配列になっていましたが、きれいに辞書に変換できました。

```py:output
{'name': 'siva', 'age': 4, 'kind': 'dog'}
```

# 実践

実際には以下のような複雑なデータを処理する場合があったりします。
よくある例を、そのまま当てはめても欲しい形式に変換することはできません。

```py:test001.py
key1=["name","age","kind"]
data1=[["garm",4,"dog"],["chapalu",3,"cat"],["echidna",10,"snake"],["phoenix",6,"bird"]]

print(dict(zip(key1,data1)))
```

これでは、ぐちゃぐちゃです。役に立たないデータになってしまいました。

```py:output
{'name': ['garm', 4, 'dog'], 'age': ['chapalu', 3, 'cat'], 'kind': ['echidna', 10, 'snake']}
```

# 結論

そこで、以下のように内包表記を利用してみます。

```py:test001.py
key1=["name","age","kind"]
data1=[["garm",4,"dog"],["chapalu",3,"cat"],["echidna",10,"snake"],["phoenix",6,"bird"]]

print([dict(zip(key1,item)) for item in data1])
```

上手くいきました。

```py:output
[{'name': 'garm', 'age': 4, 'kind': 'dog'}, {'name': 'chapalu', 'age': 3, 'kind': 'cat'}, {'name': 'echidna', 'age': 10, 'kind': 'snake'}, {'name': 'phoenix', 'age': 6, 'kind': 'bird'}]
```

# 回帰

For文で書き直してみると、こうなります。

```py:test001.py
key1=["name","age","kind"]
data1=[["garm",4,"dog"],["chapalu",3,"cat"],["echidna",10,"snake"],["phoenix",6,"bird"]]

mydata = []
for item in data1:
    mydata.append(dict(zip(key1,item)))

print(mydata)
```

結果は同じですね。

```py:output
[{'name': 'garm', 'age': 4, 'kind': 'dog'}, {'name': 'chapalu', 'age': 3, 'kind': 'cat'}, {'name': 'echidna', 'age': 10, 'kind': 'snake'}, {'name': 'phoenix', 'age': 6, 'kind': 'bird'}]
```

# 参考

- キーと辞書が交互に並んだ特殊なパターン
    - [要素数 2 のタプルからなるリストの場合](https://www.lifewithpython.com/2014/03/python-create-dicts-from-lists.html)

**Excelsior!!**
DynamoDBの定義をコピーして新テーブルを作る（複数個）

AWSのDynamoDB、使っていますか？

今回は・・・
わけあってもともとあるテーブルたちの名前を一部リネームしたものをそのまま複製したい！
（中身は空で良い）
となり、手で１つずつ定義を設定して作るのは面倒なので、PHPでさくっとやってみました。

●流れ●
①　AWS SDKを使えるようにする
　https://github.com/masayuki0812/dynamodb-php-wrapper
②　listTablesでDynamoの一覧を取得
③　②をforeachで回し、各テーブルの定義をdescribeTableで取得
④　リネームしたテーブル名と取得した定義を使ってcreateTable

●実際のコード●
※FuelPHPで実装しています
※SDKの処理を取得するために、一度Modelを通していますがお好みで・・・

```php
        // Dynamoテーブルのテーブル名を一覧で取得
        $data = Model_Dynamo_Base::listTables(); // いい感じの場所でsdkの「listTables」を呼び出してください
        foreach ($data['TableNames'] as $index => $base_tablename) {
		// リネーム処理
                $tabelname = str_replace(‘test’,’test2’,$base_tablename);
                // 1テーブルごとにテーブル定義を取得
                $base_table_data = Model_Dynamo_Base::describeTable($base_tablename);　// いい感じの場所でsdkの「describeTable」を呼び出してください
                // 作成したいテーブル名に変更
                $base_table_data['Table']['TableName'] = $tabelname;
                // キャパを読み取りも書き込みも調整
                $base_table_data['Table']['ProvisionedThroughput']['ReadCapacityUnits'] = 1;
                $base_table_data['Table']['ProvisionedThroughput']['WriteCapacityUnits'] = 1;
                $params = $base_table_data['Table'];
                // テーブル作成
                $bbb = Model_Dynamo_Base::createTable($params); // いい感じの場所でsdkの「createTable」を呼び出してください
            }
        }
```

dynamodb-php-wrapperに追記する形で作っています

```php
    public function listTables($ExclusiveStartTableName = null, $limit = null)
    {
        $params = array();
        if (!is_null($ExclusiveStartTableName)) {
            $params['ExclusiveStartTableName'] = $ExclusiveStartTableName;
        }
        if (!is_null($limit)) {
            $params['limit'] = $limit;
        }
        $response = $this->client->listTables($params);
        return $response;
    }

    public function describeTable($tableName)
    {
        $params = array();
        if (!is_null($tableName)) {
            $params['TableName'] = $tableName;
        }
        $response = $this->client->describeTable($params);
        return $response;
    }

    public function createTable($param) {
        $this->client->createTable($param);
    }
```

こんな感じです。
あまり参考資料がなかったので苦戦しましたが、出来てしまうとかなり楽でした。
OAuth宣言2.0

お前がアプリ作る前に
言っておきたい事がある
かなり厳しい話もするが
俺の本音を聞いておけ

パスワードフロー　使ってはいけない
インプリシットにも　リスクしかない
stateはうまく作れ
いつもPKCEしろ
できる範囲で構わないから

忘れてくれるな
OAuthは認可の仕様だってことを
OpenID Connectにしか
できないこともあるから
それ以外は口出しせずに
黙ってOAuth2.0について来い

1st-partyと3rd-party
どちらも同じだOAuth2.0にしろ
変な警察はかしこくこなせ
たやすいはずだ state使えばいい

オレオレ認証するなさすな
それからつまらぬ　手抜きをするな
俺は自前の認証機構をつくらない
多分作らないと思う
作らないんじゃないかな
ま、ちょっと覚悟しておけ

認可コードフローは二人で育てるもので
どちらかが苦労して
つくろうものではないはず
お前は俺の処へ
オレオレ認可メカニズムを捨てて来るのだから
帰る場所はないと思え
これからOAuthがお前の手段
【Nuxt.js】Nuxt文法編：layout

🎈 この記事はWP専用です
https://wp.me/pc9NHC-A4

# 前置き
HeaderやFooter, sidebar(sidemenu)など
どのページでも固定で表示させたいコンポーネントってありますよね❓
そんな時に便利なlayoutを解説していきます🍎🙋‍♀️

公式サイトを元に順番に説明しています💡
https://ja.nuxtjs.org/guides/directory-structure/layouts/

# layout
## 基本的な使い方

HeaderとFooterを固定で表示させてみます🌟

```bash:directory
layouts/
--| default.vue

pages/
--| index.vue
--| sample.vue
```

![Frame 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/9371ab23-2427-38e1-b11e-4752d0ad5d4c.png)


### コード

HeaderやFooterはテキストだけなので省きます🌠
また、CSSも省略します。

ページコンポーネント(pages内のindex.vueなど)の
レンダリングはこちらの3行です🌟

```layouts/default.vue
<template>
 <Nuxt />
</template>
```

pagesが表示される位置より上にHeader,
下にFooterを表示させましょう🎶

```layouts/default.vue
<template>
 <div class="layout">
   <Header />
   <nuxt />
   <Footer />
   </div>
 </div>
</template>

<script>
import Header from '~/components/Header.vue'
import Footer from '~/components/Footer.vue'

export default {
 components: {
   Header,
   Footer,
 }
}
</script>
```

使用するlayoutの指定は必要ありません。
layouts/default.vueがデフォルトで適応されます🍒😀

```index.vue
<template>
 <div class="page">
   <p>sample</p>
 </div>
</template>
```

index.vueとsample.vueを見てみてください👀
どちらのページでもHeaderとFooterが固定されているはずです🤗

ページ内コンポーネントのリンクは
router-linkまたはnuxt-linkを使用します🎈🧸

⬇️解説記事はこちら
https://wp.me/pc9NHC-f5

index.vueにこちらを貼り付けてみると
Headerなどは固定されたまま
sample.vueに遷移することができます🌟
<nuxt-link to="/sample">リンク</nuxt-link>

## カスタムレイアウト

index.vueでは
layouts/default.vue(Header, Footerを使用)にして
blog内のposts.vueでは
layouts/blog.vue(ブログ用ナビゲーションバー)を表示させてみます🌟

🎈 続きはWPでご覧ください👀
https://wp.me/pc9NHC-A4