OmniAICreator/Qiita-1.07M huggingface dataset:
PowerShell で PAC ファイルを使ったプロキシ設定をしてみた

# 前提
* Windows OS のインストール直後、または、仮想マシンを起動した直後であることとする。
* PowerShell は管理者モードで起動していることとする。

# 1. バージョン情報
## 1.1. Windows OS Version
~~~
PS C:\Users\Administrator> (Get-CimInstance -ClassName Win32_OperatingSystem).Version
10.0.19045
PS C:\Users\Administrator>
~~~

## 1.2. PowerShell Version
~~~
PS C:\Users\Administrator> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      5.1.19041.3031
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.19041.3031
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
PS C:\Users\Administrator>
~~~

# 2. 事前確認
## 2.1. プロキシ設定の自動読み込み設定
* 何も出力されないことが正。
~~~
PS C:\Users\Administrator> (Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings")."AutoDetect"
PS C:\Users\Administrator>
~~~

## 2.2. プロキシ設定の PAC ファイル読み込み
* 何も出力されないことが正。
~~~
PS C:\Users\Administrator> (Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings")."AutoConfigURL"
PS C:\Users\Administrator>
~~~

## 3. PAC ファイルを使ったプロキシ設定
~~~
$pac = "http://XXX.XX.X.XX/proxy.pac"
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name "AutoDetect" -Value "0" -Type DWORD -Force
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name "AutoConfigURL" -Value $pac -Type STRING -Force
~~~

# 4. 事後確認
## 4.1. プロキシ設定の自動読み込み設定
~~~
PS C:\Users\Administrator> (Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings")."AutoDetect"
0
PS C:\Users\Administrator>
~~~

## 2.2. プロキシ設定の PAC ファイル読み込み
~~~
PS C:\Users\Administrator> (Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings")."AutoConfigURL"
http://XXX.XX.X.XX/proxy.pac
PS C:\Users\Administrator>
~~~

## 2.3. HTTP ステータスコード取得による動作確認
* Windows OS のインストール直後、または、仮想マシンを起動した直後であるとき、HTTP ステータスコード取得には、InternetExplorer のプロファイルが必要となる。
* ここでは、Web ブラウザのプロファイルを作成するために、InternetExplorer のプロセスだけを起動させる。
~~~
$ie = New-Object -ComObject InternetExplorer.Application
$ie.visible=$false
$ie.Quit()
try {
  $response = Invoke-WebRequest -Uri "http://hogehoge.com/"
} catch {
  $response = $_.Exception.Response
}
$StatusCode = $response.StatusCode
$StatusDescription = $response.StatusDescription
Write-Host "$StatusCode $StatusDescription"

200 OK
~~~
【Shell】sedコマンドで文字列を追加して改行する方法

## 改行する

追加する文字列の最後に改行するには次のように実行します。  

```terminal
sed -i "/text/a 追加するテキスト\n" sample.txt
```

```sample.txt
text
追加するテキスト

          追加テキスト
```
「Spring boot + Vue.js + MySql + VS Code + Docker で開発環境を構築する」をやってみた

### 実践した記事
https://qiita.com/PoKoPoKoTa2ry/items/2f9b54518b8158809192

### 目的
曖昧であるDocker環境の構築手順とVue.jsとSpring bootがどのように連携されるのかを確認したかった。


### 参考情報
・所要時間：7-8時間程度
・時期　2023年9月

・この環境構築でできる環境のポンチ絵
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670485/de9c8a15-ade1-8ed1-d0f9-1dba1abe9d0c.png)



### 用語集
・VSCode Remote Container=
Dockerの仮想マシンの中に入ってVsCodeを使えるようにできるVsCodeの拡張機能の一つ
　
・WSL=Windows上で動作するLinuxの実行環境
・WSL2=Windows上で動作するLinuxの仮想環境(Windows10以降で利用可)
　参考記事
　https://www.kagoya.jp/howto/it-glossary/develop/wsl2_linux/

### つまづきポイント
・node.jsのバージョンとnpmのバージョンを合わせる必要がある。
　記事内だとnode14を利用しており、npmは最新のものを利用するようにDockerFileに記述するが、最新のnpmではnode14に対応していないため、npmのバージョンを指定する必要がある。

実際に使用したDockerFile
```Docker:DockerFile
FROM node:14

WORKDIR /usr/src/app/

RUN npm install -g npm@6.14.18 && \
  npm install -g @vue/cli

```

### 感想
Vue.js⇔Spring boot はaxiosというJavaScriptのライブラリでデータの受け渡しを行っている。
DockerFileの書き方をなんとなく理解できた。
競プロの離散フーリエ変換に関する仮説

競技プログラミングで整数の並び同士を高速で掛け合わせるタイプの問題の解説を見ていると、離散フーリエ変換の話で次のようなものをよく見る。これは$A_0, A_1, A_2$...を変換したいときの説明である。

```math
f(x)=A_0 + A_1x + A_2x^2 + \cdots + A_{n-1}x^{n-1}
```

```math
\widehat{f}(t)=\sum_{i=0}^{n-1}f(\zeta_n^i)t^i
```

このうち、下の$\widehat{f}(t)$の式が離散フーリエ変換として説明してある。この説明だと話のところどころが唐突に感じる。

この部分、私は次なのではないかと思う。

```math
\widehat{f}(i)=f(\zeta_n^i)
```

これだと逆変換の話にスムーズにつながる。（添字はiでもtでも前後に合わせて決めればよい。）
この仮説の理由を以下に書く。言葉の使い方が正しくないところがあるかもしれないので先に断っておく。

 # フーリエ解析の基礎

フーリエ解析（フーリエ変換が含まれる）の基本的な考え方は

> 分析したい波形に、いくつかの基本となる波形をぶつけて、その基本波形の成分が元の波形にどれくらい含まれるか調べる。

というものである。

$f(x)$という関数（分析したい波形）に基本波形をぶつけたときの離散フーリエ変換はこうなる。これはwikipediaから持ってきたものである。

```math
F(t)= \sum_{x=0}^{N-1} f(x) \exp\left(-i\frac{2 \pi t x}{N} \right)
```

$f(x)$ : 何かの関数（分析したい波形）
$\exp(...)$ : 基本波形
$t$ : 基本波形によって異なる値。tの値によってどの基本波形か示す。


ただ、分析しようとしているものがこの記事の初めの式とwikipediaのこの式で違うので、それぞれの式の$f(x)$は同じものではない。

- この記事の初めの式の$f(x)$は分析したいものを加工したもの
- wikipediaの式の$f(x)$は分析したいもの

 # 波形じゃなくて整数の並びを変換する場合

よくあるのが

- $A_0, A_1, A_2$...
- $B_0, B_1, B_2$...

という2つの整数の並びを掛け合わせて次のようなものを求める場合である。

- $A_0*B_0$
- $A_0 * B_1 + A_1 * B_0$
- $A_0 * B_2 + A_1 * B_1 + A_2 * B_0$
(以下同じように続く)

このとき$A_0, A_1, A_2$...という整数の並びと$B_0, B_1, B_2$...という整数の並びをそれぞれ別の表現にし、演算をしてから元の表現に戻す、ということをやる。計算量が劇的に減るメリットがある。

この$A_0, A_1, A_2$...という整数の並びを別の表現するところにちょっと気になることがある。

# 整数の並びをフーリエ解析

通常、$A_0, A_1, A_2$...を使って次のような式を立てる。

$f(x)=A_0 + A_1x + A_2x^2 + \cdots + A_{n-1}x^{n-1}$

これはよく見る式であるが、この式は次のようなものを表しているのではないだろうか

![名称未設定のノート-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46631/50e7c6b3-fd2d-8175-e1de-9b6acc14c8ed.jpeg)

$A_i$を繋げたものが分析したい波にあたり図では赤。$A_i$はそれぞれの場所での値を表している。
各$x^i$は横方向の位置を表している。$x$は複素数なのでひとつ進むことはひとつ掛けること。
ある角速度を持った値を$x$に入れると、各$x^i$の位置でのその基本波形の値が決まる。図では下の各波（実際は複素数なので単純な波で書いているのはイメージです）。
各$A_i$と$x^i$を掛けるのはその基本波形が分析したい波の中にどれだけ含まれるかを求めている。

よって

$f(x)=A_0 + A_1x + A_2x^2 + \cdots + A_{n-1}x^{n-1}$

この式のxに値を代入しただけで、すでに**分析したい波形に、基本となる波形をぶつける**ということが行われているのではないか。

そして、**これこそが離散フーリエ変換なのではないかと思うのである**。

で、そう考えるとその後の逆変換のところにスムーズにつながる。
Android開発「startActivityとstartActivityForResultが共存してることってあるのか…」

## はじめに
Android開発でアプリケーションの異なる画面（アクティビティ）間での遷移は非常に一般的な操作です。
この記事では、開発時「えっ、なんでこのコード`startActivity()`と`startActivityForResult()`が両方あるの？」と思ったため、その違いについて調査しました。
（開発時に見ていたコードはJavaでしたが、今回はGoogle社がAndroidアプリの開発言語として公式認定したKotlinでサンプルコードを作成しています。）

## startActivity()
### 基本的な使い方
はじめに`startAcitivty()`についての説明も記載しておきます。
`startActivity()`これはアクティビティを単純に起動する基本的なメソッドです。
通常、このメソッドは`Intent`オブジェクトを引数として受け取ります。

```kotlin
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
```
このコードは、`SecondeAcitivity`という名前のアクティビティに遷移するものです。

### データの受け渡し
`Intent`オブジェクトには、遷移先のアクティビティに渡すデータ(Extras)を格納することができます。

遷移先の`SecondeAcitivity`でこのデータを受け取るには以下のようにします。

```kotlin
val extras = intent.extras
val extraData = extras?.getString("extraData") ?: "No extra data"

```

**`startActivity`の良い部分は、戻り値を気にする必要がないことです。**
**そのため、簡単な画面遷移をする際にはこちらを使用すれば問題ないでしょう。**

## startActivityForResult()
結果を返す必要がある場合は、`startActivityForResult()`メソッドを使用します。
以下にその使用例を示します。

#### registerForActivityResult
```kotlin
private val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
    // リザルトを取得して処理を行う
    handleActivityResult(result.resultCode, result.data)
}

// ...

    buttonStartActivityForResult.setOnClickListener {
        val intent = Intent(this, SecondActivity::class.java)
        startForResult.launch(intent)
    }
}
```

#### startActivityForResult
```kotlin
// Deprecated ?
val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("extraData", "Data from MainActivity for Result (Deprecated)")
startActivityForResult(intent, REQUEST_CODE)

// リザルトを取得して処理を行う
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == REQUEST_CODE) {
            handleActivityResult(resultCode, data)
    }
}
```

`startActivityForResult()`と`registerForActivityResult()`の2つの方法がありますが、後者が新しいAPIです。
`startActivityForResult()`は非推奨となっていた?ようなので、新しいAPIの`registerForActivityResult()`を使用するほうがよいでしょう。

## サンプル

<img width="300" alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3559577/e8978908-ace4-50fa-9e06-21a206911ade.gif">


(気が向いたときにコード追加します。）


## まとめ
* 簡単な画面遷移がしたいときには`startActivity()`
* データのやり取りが必要な時、もしくは何かデータを返したい時には`startActivityForResult()`
  * **新APIである、`registerForActivityResult`を積極的に使用しましょう。**
これで、「なぜ`startActivity()`と`startActivityForResult()`が共存してるんだ？」という謎が解けました。メソッドはそれぞれに使い道があり、使うべき場面を考える必要があります。
コマンド一発でスムーズ開発！package.json の scripts セクション活用ガイド

# `package.json` の `scripts` セクションとは？

`package.json` は、Node.jsプロジェクトの設定や依存関係を管理するためのファイルです。
この中の `scripts` セクションは、プロジェクトで使用するコマンドを定義する場所として非常に役立ちます。

以下は、 `scripts` セクションを利用することで得られるメリットをgulpを実行する場合を例に説明します。

# 一貫性の確保

チーム全体での作業の一貫性が保たれ、混乱やエラーのリスクが低減します。

導入しない場合、各開発者が独自の方法で gulp タスクを実行する可能性があります。

例：gulp build あるいは直接 ./node_modules/.bin/gulp build

scriptsを使用した場合、統一されたコマンドをチーム全体で使用できます。

例：npm run build （package.json 内で "scripts": { "build": "gulp build" } と定義）

# コマンドの簡略化

短縮コマンドを使用して、日常的なタスクの実行がより簡単かつ迅速になります。

導入しない場合、毎回長いコマンドを入力する必要があります。

例：`./node_modules/.bin/gulp serve`

導入すると、短縮されたコマンドを使用できます。

例：`npm run serve` （package.json 内で `"serve": "gulp serve"` と定義）

# クロスプラットフォームの対応

一つのコマンドセットで異なるOSをカバーでき、開発の効率が上がります。

導入しない場合、OSごとに異なる方法で `gulp` タスクを実行する必要があります。

例（Windows）：`.\node_modules\.bin\gulp watch`

導入すると、OSに関係なく統一されたコマンドを使用できます。

例：`npm run watch` （package.json 内で `"watch": "gulp watch"` と定義）

# 自動化の活用

フックを使用して、一度のコマンド実行で複数のタスクを自動的に行うことができます。

導入しない場合、手動で連続して複数のコマンドを実行する必要があります。

例：
```
gulp clean
gulp build
```

導入すると、事前/事後のタスクを自動的に実行することができます。

例：`npm run full-build` （package.json 内で `"prefull-build": "gulp clean"`, `"full-build": "gulp build"` と定義）

# まとめ

`package.json` の `scripts` セクションは、Node.jsプロジェクトの効率的な管理と開発のための強力なツールです。
これらのメリットを理解し活用することで、一貫性のある効率的な開発が期待できます。
どんどん活用していきましょう！
[OutSystems]今更だが、Traditional Web向けData Gridのチュートリアルを試してみる

OutSystemsの画面上に表形式のUIを表示するData Gridコンポーネントだが、Traditional Web版もある。
Traditional Webは使われなくなってきているだろうが、今更ながら、Data GridのTWA向けコンポーネントのチュートリアルを試し、気づいたことをメモしておく。

チュートリアル：[How to use OutSystems Data Grid Web](https://success.outsystems.com/documentation/how_to_guides/development/outsystems_data_grid/how_to_use_outsystems_data_grid_web/)

# 環境情報
Personal Environment(Version 11.23.0 (Build 39357))
Service Studio(Version 11.54.24)
OutSystems Data Grid Web (Version 2.21.4)

# 新しい環境ではTraditional Webは作成できない
Forum投稿：[I can't see Create Traditional Web Application option](https://www.outsystems.com/forums/discussion/82812/i-cant-see-create-traditional-web-application-option/#Post346047)に以下のように書かれている通り、新しい環境ではTraditional Webのアプリケーションを作成するオプションが無効になっている。

> For new paid licences, the template for Traditional Web is by default no longer installed/enabled.

この解決策として、サポートへの依頼が挙げられている（試したことないので、実際にやってくれるかは不明）。

> You can request to OutSystems, to enable the Traditional Web App template again for you. You can request this through a support case.

ちなみに、Traditional Webが有効になっている環境では、アプリケーション作成時に以下のように「Traditional Web」というオプションが表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/ce2749ef-145b-573a-8028-90b84d05cb26.png)

# Module名が変更されている
チュートリアル中では、コンポーネントのModule名が「DataGridComponent」とされているが、現バージョンをインストールして確認すると、以下の通り「OutSystemsDataGridWeb」となっている。

# 開発方法の大きな違い：サーバーデータにアクセスするためにExpose REST APIを使う
Reactive Web Appであれば、自然にクライアント側からのリクエスト（Data ActionやScreenのAggregateなど）によってサーバーのデータを取得できる。

しかし、Traditional Webの場合はそうもいかず、Expose REST APIを作成してデータ取得する。Data GridのコンポーネントにURLを設定すると、動作時にリクエストを行って、結果をGrid内に表示してくれる。

## Expose REST APIの認証問題
問題は、作成した画面とExpose REST APIのMethod間では認証が共有されないこと。
画面に配置したData GridからExpose REST APIを呼ぶとき、認証クッキーは渡っているようだが、ログインセッションは共有されない。つまり、Anonymousユーザーによるアクセス扱いになってしまう。
そのままだとAPIにセキュリティがかからないので、画面にログイン中のユーザーIdを取得するActionが提供されている。

それがData Grid Webアプリケーション/DataGridAuthentication Extension。
ExtensionにあるGetUserLogged Actionがログイン中のユーザーIdを返してくれる。

ただし、恐らくこのActionが内部で使っている以下のAPI呼び出しはAPIドキュメントが見当たらないので、非公開のもの。

``` cs
OutSystems.RuntimePublic.Session.GetUserFromSessionCookie();
```

### DataGridAuthentication/GetUserLogged Actionの動作確認してみる
以下のように、Data Gridから呼んでいるExpose REST APIロジック内で、GetUserId()とGetUserLogged Actionそれぞれの結果をログに出力してみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/3581edcc-454c-c15b-7fbe-c14614064c6b.png)

結果は以下の通り。

```
GetUserId(): 0 GetUserLogged.UserId: 2
```

GetUserId()=0=NullIdentifier()なので、OutSystemsの通常ロジックとしては未ログインの状態。
しかし、GetUserLogged Actionは正しく呼び出し元画面にログインしているユーザーのIdを返している。
【GOT】GOT Mobileとは？【三菱PLC】

GOT Mobile機能を用いることで、タブレットなどからGOTに接続し、GOTの操作と同じことが遠隔操作でできるようになります。（一部の機能を除く）
表示される画面はGOT用のベース画面ではなく、GOT Mobiole用のモバイル画面です。そのため、タブレット端末などで表示させたい画面を、端末の画面サイズに合わせて別で作成する必要があります。

https://fa-faq.mitsubishielectric.co.jp/faq/show/20448

https://fa-faq.mitsubishielectric.co.jp/faq/show/20476

![case02_03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535456/9a744359-818f-1325-60c4-f65bb58743a3.jpeg)


## VGDデバイス（GOT Mobileデバイス）とは？

VGDデバイスは、GOT内部デバイス(GD)の一部の領域を使用し、接続している端末から使用できるデバイスです。接続されている端末ごとに違うGDデバイスの領域がVGDとして割り当てられているため、同じVGDデバイスを端末で指定してもそれぞれ別の動作をさせることが可能です。
割り当てデバイス点数の設定は、「共通の設定」タブの「GOT Mobile設定」を選択し、「デバイス割当設定」画面から行います。

https://fa-faq.mitsubishielectric.co.jp/faq/show/20495


## GOTとタブレット端末の接続方法

GOTとの接続はブラウザーから行います。GOTと端末は同じネットワークに接続されている（互いに通信できる状態である）必要があります。端末のブラウザから接続先のGOTのURL(例:**http\://192.168.3.18/**)を入力します。

接続に成功すると、接続認証画面がブラウザーに表示されます。設定したオペレータ名とパスワードを入力し、ログインすることでモバイル画面をブラウザーに表示します。これで接続完了です。接続方法を変更するには、「共通の設定」タブの「GOT Mobile設定」を選択し、「接続認証設定」画面を開きます。
アンドン機能を使用すれば、接続時に接続認証画面を表示しないでそのままモバイル画面を表示できます。

https://fa-faq.mitsubishielectric.co.jp/faq/show/20453

https://fa-faq.mitsubishielectric.co.jp/faq/show/20494


### GOTとPLCの接続方法（Ethernet）

https://qiita.com/PockTTY/items/ec816f2766c88b7f5254
Gitを利用開始するときのメモ

#### 1. ローカルリポジトリの初期化
```bash
git init
```

#### 2. 最初のコミット
```bash
git commit --allow-empty -m "first commit"
```
最初は空のコミットにするといいらしい。

#### 3. リモートリポジトリの設定
```bash
git remote add origin [リモートリポジトリのURL]
```

#### 4. リモートリポジトリへのプッシュ
```bash
git push -u origin main
```
Git ローカルリポジトリ の作成

ごきげんよう、百合宮桜です。
公私ともに Git 使わないといけない感が出てきたので、設定に追われています。
Git 系はエンジニア感がありすぎて、わかるようなわからなような感じがぴえんって思いながら設定しているので、そのあたりを払拭できるように優しさに包まれた記事を書きたいと思っています。

# 前提条件
私の環境は下記のとおりです。
- OS：Windows 11 Pro
- エディター：Visual Studio Code

Visual Studio Code をインストールしたい方はこちらの記事を参照してください。

https://qiita.com/yurimiyasakura/items/5ce7821f1e3e5905c3ee

# 前提知識
## リポジトリってなに？
プログラムのソースコードやドキュメントなど関連データを一元的に管理する場所のことです。

## ローカルリポジトリってなに？
自分のコンピューター（=ローカル）に作成されたリポジトリのことです。
ファイルを直接、編集できます。
ローカルリポジトリで加えた変更は、ファイルをリモート側に複製する事で反映できます。

# 隠しファイルを見えるようにしておく
1. エクスプローラー を開きます。


2. 「表示」タブから「隠しファイル」をクリックして、チェックを入れます。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/d5b7215d-64d5-2d03-fcf2-702bf8d40d72.png)



# フォルダを作成する
ローカルリポジトリを配置する場所を作ります。
場所はどこでも構いません。

1. フォルダーを作成します。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/a6c02004-658f-9c32-8773-9f92e3ae22ad.png)

2. 半角英数字で名前をつけます。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/c6621e9f-86c5-2f1d-f7ce-b3bbfdd89b71.png)

# Visual Studio Code でターミナルを開く

1. Visual Studio Code を起動します。


2. 「ファイル」＞「フォルダーを開く」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/0717be53-7264-c515-e687-b945896ec6af.png)

3. 先ほど作成したフォルダーを選択し、「フォルダーの選択」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/fe94dfb7-0318-2651-1440-f3bdee23745d.png)

4. 画面左側のエクスプローラーにフォルダーが表示されます。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/636dcbe9-759d-ed5e-cc5b-0d554d1a577e.png)

    ※このウィンドウが出てきたら、「はい、作成者を信頼します」をクリックしてください。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/ce1094a7-79ed-4f2d-ad6a-3c8b2b004696.png)

5. 「ターミナル」＞「新しいターミナル」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/5e3820c3-328a-cdd0-4b8e-25405d164122.png)

6. ターミナルが開きます。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/a8616292-d085-72b6-4c57-709df58c0968.png)

# ローカルリポジトリの初期化
1. ターミナルの1行目「フォルダー名＞」の後に以下の文言を入力します。
    ~~~
    git init
    ~~~

2. Enter キーを押して、初期化を実行します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/a6fec65c-cd7e-6dc4-3e7a-61da2d7e8c90.png)

3. フォルダー内に隠しファイルができていればOKです。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/b8307718-d725-e130-2c26-811885dc199b.png)
    ※隠しファイルはフォルダの色が少し薄くなっています。
【GAS】 Google Formsの回答に自動返信する

## 背景と実施したこと
掲題の通りですが、
Google Formsの回答に自動返信をするためのスクリプトを書きました。

ちなみにMicrosoft FormsとOutlookを使う場合はPower Automateを使ってノーコードで実現できるようです。
それ以外にもZapierというツールを使ってノーコードで済ますこともできます。
※Zapier試した感じだと若干のタイムラグがありそうだったのと、スクリプト書く方が（自分は）楽だったのでGASでの実装を今回採用しました。

参考にした記事
[Google フォームで「自動返信メール」を設定する3つの方法＆メールが届かない場合の対処法](https://blog.hubspot.jp/marketing/google-forms-automatic-reply "Google フォームで「自動返信メール」を設定する3つの方法＆メールが届かない場合の対処法")
[【GAS】Googleフォームの回答取得から引数eの違いを理解、トリガー実行時のエラー解決方法](https://zenn.dev/gas/articles/8cb18b31507dcf "【GAS】Googleフォームの回答取得から引数eの違いを理解、トリガー実行時のエラー解決方法")

## 概要
+ GASのエディターでサジェストされたものをそのまま使ってもNG
+ スプレッドシートからGASを作る（Formsのスクリプトではない）



## 手順
手順は以下です。１～３と５はさほど難しくない＆参考記事に載っている通りなので割愛します。
1. Formsを用意する。
1. 回答をスプシに紐づける。
1. スプシからGASを設定する。
1. GASの中でスプシの内容を読み取るスクリプトとメール送信する処理を書く
1. Formsの回答をトリガーに設定する

4は以下のようなコードになります。
なお、sendEmailに関しては最新の[公式リファレンス](https://developers.google.com/apps-script/reference/mail/mail-app "公式リファレンス")にあるように使い方にいくつかバリエーションがあります。


```js:sendReply
function sendReply(e) {
  // フォームの回答を取得
  const NAME = e.namedValues['名前'][0];
  const EMAIL = e.namedValues['メールアドレス'][0];

  // 自動返信メール件名
  const SUBJECT = '【自動返信】資料請求ありがとうございます。';

  const BODY = 
  NAME + '様\n\n'
  + 'お申込みありがとうございます\n'  
  + '2営業日以内にお申込み内容を確認し資料を送付させていただきます。\n' 
  + '恐れ入りますが、今しばらくおまちください。\n'
  + 'https:\/\/drive.google.com\/file\/d\/XXXX\/view\?usp=sharing';
  
  // メール送信
  MailApp.sendEmail(
    EMAIL,
    SUBJECT,
    BODY
  );
}

```

なお以下はNG例です。大文字のメソッドやクラスがサジェストされることもあるかもですが、これだとNGです。
```js:sendReply
function sendReply(E) {
  // フォームの回答を取得
  const NAME = E.NAMEDVALUES['名前'][0];
  const EMAIL = E.NAMEDVALUES['メールアドレス'][0];

  // 自動返信メール件名
  const SUBJECT = '【自動返信】資料請求ありがとうございます。';

  const BODY = 
  NAME + '様\n\n'
  + 'お申込みありがとうございます\n'  
  + '2営業日以内にお申込み内容を確認し資料を送付させていただきます。\n' 
  + '恐れ入りますが、今しばらくおまちください。\n'
  + 'https:\/\/drive.google.com\/file\/d\/XXXX\/view\?usp=sharing';
  
  // メール送信
  MAILAPP.SENDEMAIL(
    EMAIL,
    SUBJECT,
    BODY
  );
}

```

※ちなみにGmailなどの一部のメーラーでは受信側勝手に改行されたりするようです。
　そんなときはプレーンテキストではなくhtmlBodyで送ってあげるといいかも。
## まとめ（自戒）
ついついネット記事のまま横着してコピペしがちですが、ちゃんと公式リファレンスみて実装しないとだめですね。
【S3+CloudFront+Nuxt3】 Access Deniedエラーを回避する方法

# 課題

Nuxt3で作成したWebサイトをS3+CloudFrontで配信をした時に、動的ルーティング（/item/[id]のようにURLに含めたパラメータに応じたページにルーティングする仕組み）したページのURLをブラウザに直接入力してアクセスするとAccess Deniedになり、正しく表示ができません。

# 解決策

この問題は指定されたURLに従ってCloudFrontがS3からコンテンツを配信しようとした時に、配信するページが無いために発生しています。
そこで、対策として配信ページがない場合（つまり、404や403エラーが発生した場合）はトップページを表示させることでNuxtのルーティングが動作するようにすることで解決ができます。

## 　コンソールから設定する場合

1. AWS Management Consoleにサインインし、CloudFrontサービスに移動します。
1. 対象のディストリビューションを選択し、"Error Pages"タブに移動します。
1. "Create Custom Error Response"ボタンをクリックします。
1. 404と403エラーのためのカスタムエラーレスポンスをそれぞれ作成します。

![スクリーンショット 2023-09-20 22.09.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/07a14168-030f-2edd-3acd-1de64ed80806.png)

## SAMテンプレートで設定する場合

CloudFrontのDistributionConfig内に下記のように追加します。
```yaml
CloudFrontDistribution:
  Type: AWS::CloudFront::Distribution
  Properties:
    DistributionConfig:
      ...
      CustomErrorResponses:
        - ErrorCode: 404
          ResponsePagePath: /index.html
          ResponseCode: 200
        - ErrorCode: 403
          ResponsePagePath: /index.html
          ResponseCode: 200
```

# まとめ
Nuxt3で作成したSPAをS3とCloudFrontを使用して配信する際に直面する可能性がある動的ルーティングの問題は、CloudFrontのカスタムエラーレスポンスを適切に設定することで解決できます。

この設定により、存在しないページへのアクセスもトップページにリダイレクトされ、Nuxtのルーティング機能が適切に動作するようになります。
メモ）：rust wasm 

Rust コードメモ（APIコール）

lib.rs
```rust
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use futures::prelude::*;
use js_sys::Promise;
use wasm_bindgen_futures::{future_to_promise, JsFuture};
use web_sys::{Request, RequestInit, RequestMode, Response};

#[wasm_bindgen]
pub fn getApiMessage() -> Promise {
    let url = "http://127.0.0.1:8080/api/control/text";
    let mut opts = RequestInit::new();
    opts.method("GET");
    opts.mode(RequestMode::Cors);
    let request = Request::new_with_str_and_init(&url, &opts).unwrap();
    request
        .headers()
        .set("Accept", "text/html")
        .unwrap();
    let window = web_sys::window().unwrap();
    let request_promise: Promise = window.fetch_with_request(&request);

    let future = JsFuture::from(request_promise)
    .and_then(|resp_value| async {
        assert!(resp_value.is_instance_of::<Response>());
        let resp: Response = resp_value.dyn_into().unwrap();
        resp.text()
    })
    .and_then(|text| async move {
        Ok(JsValue::from(text))
    });

    future_to_promise(future)
}
```

JS
```html
<script type="module">
    import init, {getApiMessage} from "./pkg/apitest.js";
    
    async function run() {
        await init();
        const ret = await getApiMessage();
        console.log(ret); 
    }
    run();
</script>
```
Java Silver勉強メモ

# 最初に

Java Silver 勉強のメモを記していきたいと思います。
間違いなどありましたら教えていただけると幸いです。
随時更新していきます。

## 同名のローカル変数とフィールドがある場合

同名のローカル変数とフィールドがある場合、this を使ってフィールドであることを明記しないとローカル変数が優先されます、
そのため下記では test メソッドを実行しても num フィールドの値は変更されません。

```java
public class Main {
    private static int num;
    // static初期化子
    static {
      num = 10;
    }
    static {
      num = 20;
    }

    static void test(int num) {
        num = num * num; // ここで参照しているnumは引数のnum
    }

    public static void main(String[] args) {
      test(num);
      System.out.println(num); // 20
    }

}
```

## アクセス修飾子について

| 修飾子           | 説明                                                                 |
| ---------------- | -------------------------------------------------------------------- |
| public           | すべてのクラスからアクセス可能                                       |
| protected        | 同じパッケージに属するか、継承しているサブクラスからのみアクセス可能 |
| なし(デフォルト) | 同じパッケージに属するクラスからのみアクセス可能                     |
| private          | クラスないからのみアクセス可能                                       |

protectedとなしでは同じパッケージに属するクラスからのアクセスを受け付ける点では同じですが、スーパークラスとは別のパッケージに属するサブクラスからのアクセスについては異なります。
protectedは異なるパッケージに属するサブクラスからアクセスできますが、アクセス修飾子なしではサブクラスであっても別パッケージに属するクラスからはアクセスできません。
ネットワークセキュリティ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/a47c1ea9-d273-70c3-715d-52741c62436a.png)
　部外者がLAN内部にアクセスすることは好ましくありません。また、ウイルスなどの影響で、LAN内部から機密情報が漏洩するような事態も避けなければなりません。ファイアウォールは、インターネットとLANの境界に設置して通信を監視し、不都合な通信を遮断する装置です。ファイアウォールには、パケットの宛先/送り元アドレスだけをチェックするパケットフィルタリング型と、通信nの内容までチェックするアプリケーションゲートウェイ型があります。

１：ファイアウォールの設置
　ファイアウォールは、インターネットとLANとの境界に設置します。ファイアウォールの外側を外部セグメントと呼びます。ファイアウォールの内側で、公開サーバを設置する箇所を非武装セグメント（DMZ）、LAN内部に相当する箇所を内部セグメントと呼びます。

　インターネットや内部セグメントからDMZへ向けては通信が可能なように設定します。一方、DMZへ向けては通信できないように設定します。これは、DMZのサーバが攻撃を受けて乗っっとられたとしても、乗っ取ったサーバから内部セグメントへ接続できないようにするためです。

２：パケットフィルタリング型ファイアウォール
　パケットの
・宛先IPアドレス、ポート番号
・送信元IPアドレス、ポート番号
によって、通貨の可否を決める方式のファイアウォールです。通常は許可する通信を指定して、それ以外の通信はすべて禁止するという運用を行います。このような運用をデフォルト禁止の設定、あるいは、ホワイトリスト方式といいます。
　通信の可否を設定する設定表をフィルタリングテーブルと言います。フィルタリングテーブルには、要求（行きの通信）と応答（帰りの通信）を設定します。

３：アプリケーションゲートウェイ型ファイアウォール
　パケットフィルタリング型ファイアウォールの機能に加えて、通信しているデータの内容をチェックして通貨の可否を決める方式のファイアウォールです。外部に漏洩して箱回る情報を食い止めることができます。
　この方式では、通信しているデータの内容を調べるために、アプリケーションプロトコルを理解する必要があります。例えば、ファイアウォールがHTTPを理解できないと、ウェブ通信のいないようを調べることはできません。また、STMPを理解できないと、電子メールの内容を調べることはできません。ファイアウォールが対応していないプロトコルでの通信内容は調べられないのです。この点に注意して運用する必要があります。

４：WAF(Web Application Firewall)
　ウェブサーバやウェブアプリケーションへの攻撃を遮断することを目的としたファイアウォールです。WAFは、保護対象をウェブサーバやウェブアプリケーションに特化しています。ウェブサーバやウェブアプリケーションとの通信内容をチェックし、攻撃に使われるメッセージが含まれていた場合、該当メッセージを無害か（サニタイジング）したり、通信を遮断したりします。XSSやCSRF、SQLインジェクションといったウェブアプリケーションへの攻撃を効果的に遮断できます。
Shopify テーマカスタマイズ ブランド一覧の作り方

Shopifyのテーマカスタマイズを行っているエンジニア向けに、ブランド一覧ページを作成する方法を紹介します。

ブランド一覧ページは、ショップのブランドをまとめて表示するページです。ショップのブランドをわかりやすくユーザーに伝えるために重要なページです。

<b>前提条件</b>
本記事では、Shopifyのテーマカスタマイズを行った経験があることを前提としています。また、ShopifyのLiquidについて基本的な知識があることが望ましいです。

<b> ブランド一覧ページのメリット </b>
おっさんの個人的な意見だけど…。
１、アイテムショップ系のショップさん（アパレルや調理器具など）ショップさんであればブランドをわかりやすくユーザーに伝えることができる
２、ブランド別絞り込みをできたりするので、商品を探しやすくなる
３、ブランド詳細のコレクションやテンプレートを工夫することで、ブランドの認知度を高めることができる
時と場合によってはお客さんに提案するのもいいかも？

## 手順
### ブランド一覧用のコレクションを作成する
まずは、ブランド一覧ページのためのコレクションを作成します。
今回はcollections/allと同じ内容で、価格が０円以上で全ての商品を取得しました。

この時vendorなので、/collections/vendorにしたかったのですが、これはできません。
/collections/vendorはShopify側であらかじめルーティングで確保されているからです。
（/collections/vendor?q=ブランド名でブランドに絞り込んだ商品一覧が出せます）

なのでハンドルは、/collections/brand にしました
　
### ブランド詳細になるコレクションを作成する
次に、ブランド詳細用のコレクションを作成します。
この時にコレクションのハンドルを/collections/ブランド名にします。
ブランド名のところは、product.vendorで表示されるやつです。


### ブランドページのテンプレートを作成する
最後に、ブランドページのテンプレートを作成します。

具体的なコード
```
{%- for shop_vendor in shop.vendors -%}
  {%- assign current_collection_vendor = collections[shop_vendor] -%}
  {%- if current_collection_vendor != blank -%}
    <div class="brand-item">
      <h2>{{ current_collection_vendor.title }}</h2>
      <p>{{ current_collection_vendor.description }}</p>
      <a href="{{ current_collection_vendor.url }}">詳細</a>
    </div>
  {%- endif -%}
{%- endfor -%}
```
このコードは、ショップのすべてのブランドをループで処理し、ブランド名からコレクションを呼び出し、ブランド名やブランドの説明文を表示します。

今回は、shop.vendorsにしました。
collection.all_vendorsというオブジェクトもあるのですが、この場合コレクションに紐づく全てのvendorなので、ページネーションの制限などを受けて、現在にいるページのvendorしか取れない現象が起きてくる可能性がありそうだなと思ったからです。この辺り検証はしてませんが、shop.vendorsを優先して使いました。

あと、if current_collection_vendor != blank この判定を追加することで、業務上表示しなくて良いブランドさんはコレクション詳細を作らないことで、非表示にすることが出来ます。

### 注意点
この方法では、ブランドのソートやページネーションなどの機能を実装することができません。
これらの機能を実装したい場合は、JSや.json.liquidなどを使って情報設計などから考え直す必要があります。
あと、今回のショップのブランドさんが今のところ５０件未満だったので検証してませんが、１ページのオブジェクトの読み込み件数に引っ掛かるかどうかもチャンスがあれば検証してみたいと思います。

## まとめ
今回紹介した方法は、シンプルでわかりやすいため、初心者でも簡単に実装することができます。。。多分？
ただし、ブランド名を元に紐付けを行っているので、ブランド名が英語やローマ字でないような場合は、工夫が必要になってきます。
例えば、おじさん工房のようにひらがなと漢字などの場合、そのままコレクションのハンドルに使ってしまうと、変換されてしまい紐付けが上手くいかない場合が出てくるかもしれません。
そういった場合は、ブランド名をojisankoubouなどにし、そのコレクションにメタフィールドで表示名などを持たせることで、
```
{% assign v = product.vendor %}
{{ collections[v].metafields.brand.name }}
```
みたいな紐付けで表示することが出来るのではないか？と思っています。

Shopifyのブランド一覧、色々課題がありますが.json.liquidなどを使ってAPIで表示するような形も機会があれば試してみようと思います。


### ARCHETYPからのお知らせ
ARCHETYPではShopifyテーマ、Shopifyアプリ、Webサイト/サービスなどの開発を行うエンジニアを募集中です！
正社員、副業などとわず募集です！（フルリモートも相談可です！）
https://www.archetyp.jp/recruit/
気になる方はお気軽にエントリーお待ちしております！
物体検出でよく使われてるプラットフォームDetectron2

Detectron2はMetaが開発した物体検出のプラットフォームです。（HuggingFaceみたいな感じ）
最新モデルなどが公開されたら、すぐアップデートしますので、物体検出に関してのモデルならほとんど揃いています。
学習済みのモデルを使用する場合、ホームページを参照しながら使いたいモデルを呼び出すだけで動作できます。

カスタマイズモデルを作ることもできます。
こちらは少し複雑ですが、0から全部作る必要がなくて、ベースモデルの上に、データによってニューラルネットワークを修正するような作業を行います。

以前利用した際のサンプル写真も以下に載せしました。（使用モデル:Faster R-CNNモデル）。
チューニングはまだ行っていませんが、すでに正解率、確信度も高くて使えるものレベルにはなっていますね。
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/96265d30-d138-a5c9-d476-603a039d31c4.png)


興味ある方は試してみてください
コード:https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5#scrollTo=7unkuuiqLdqd

github:https://github.com/facebookresearch/detectron2
GoogleアラートをSlackで通知する方法

# これはなに

GoogleアラートのRSSフィードをSlackに登録する方法を備忘録として残します。

# どんな方に向けた記事か？

- 楽して情報収集をしたい方
- すべての情報収集をSlackに集約したい方



# 背景

広報のお仕事をしているので自社の情報がメディア露出した際に気付ける環境を作りたいなとふと思い、
Googleアラート自体は昔から使ってましたが、メール通知が来ても気付けないのでRSS登録に挑戦してみました。

# それでは連携

## Googleアラートで指定キーワードを登録する

まずは「Googleアラート」にアクセス
https://www.google.co.jp/alerts#

特定のキーワードを登録する
![スクリーンショット 2023-09-20 21.40.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554608/8c4f4b34-a3bd-07b5-86fa-ebbaf3154fc9.png)

こんな感じで登録完了するとリストに表示されます
![スクリーンショット 2023-09-20 21.42.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554608/fd6e9a41-abc2-4353-2362-59ae2b70529a.png)

## 購読方法をRSSに変更する

✏️マークから編集画面に移動します
![スクリーンショット 2023-09-20 21.43.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554608/21ffad15-c03f-4734-ce5f-12ab8669a0c4.png)

配信先を「RSS フィード」に変更し、更新ボタンを押します
![スクリーンショット 2023-09-20 21.43.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554608/1657dd9b-ee1e-2963-e268-6c2d2fc13a3e.png)


## RSSフィードのURLを取得する

RSS登録が完了するとリスト上にアンテナのようなマークが表示されます
![スクリーンショット 2023-09-20 21.45.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554608/c690283c-393c-8e99-460a-7c17f6fdd84b.png)

RSSボタンをクリックし、遷移先のアドレスバーからRSSフィードのURLをコピーします
![スクリーンショット 2023-09-20 21.46.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554608/c4a27238-cb54-12d3-40ae-c7d3d2e4abb3.png)

## SlackチャンネルにRSSフィードを登録する

通知を飛ばしたいSlaclのチャンネル上で、`/feed` + `コピーしたURL` を送信します 
![スクリーンショット 2023-09-20 21.57.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554608/8eb8a579-f5d4-b836-63d6-cc1b21100bf5.png)


## 完了！

このような表示が出たら成功です！
![スクリーンショット 2023-09-20 21.58.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554608/da578a56-fc77-7f16-3e05-c291cc8c554d.png)

登録後に指定キーワードのネット記事などが生成されるとこのように通知が届きます:clap_tone1:
![スクリーンショット 2023-09-20 21.35.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554608/7202ab66-c568-3c72-88fa-7f03d309a7f6.png)

# おまけ

登録したリストの確認、削除などは以下のコマンドから実行できます。

- リスト確認： `/feed list`　と送信
- 削除： `/feed remove`+`ID`　と送信
    - 登録キーワードごとのIDはリストで確認できます

# まとめ

Googleアラートって無料なのに便利ですよね。
（たまに変な記事拾ってくることもあるけど笑）

RSS購読できるサービスであれば同じ要領でなんでもSlackに連携できるので、ぜひ。
Qiitaも特定のユーザーやOrganization、ハッシュタグを購読できますよ:kissing_smiling_eyes:
ずっと投稿テスト）：SQLインジェクション追問

https://qiita.com/ockeghem/items/0f3b09a0f413bdd39bd5

また問題つくってくれてたので、投稿テストでまた解いてみよ

１）ブランクパスのユーザーを作って～
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561202/9597dbdd-c770-a9a0-24ff-b428472eafb6.png)

２）SQLインジェクション作って～
```
xxx' UNION ALL SELECT 1 AS id, 'admin' AS userid, password, '' as email from users WHERE userid = '2
```

３）実行！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561202/8d4c525e-6a86-54d8-e000-fd457f0c74e8.png)


いじょ
Re: パスワードがハッシュ値で保存されているサイトのSQLインジェクションによる認証回避の練習問題

[徳丸さんの練習問題](https://qiita.com/ockeghem/items/787f74801a24e1fc6960
)を考えてみます。

https://qiita.com/ockeghem/items/787f74801a24e1fc6960

# お題

お題のSQL組立文字列は、このようになっています。

```php
"SELECT * FROM users WHERE userid = '$userid'"
```

`$userid` には好きな文字列を入れることができますので、SQLインジェクションし放題というわけです。

# 結論から考える

認証処理の部分は次のようになっています（一部書き換え）。

```php
password_verify($_POST['password'], $user['password'])
```

`$user['password']` に任意の文字列を入れることができれば、認証突破できそうです。

\# お題はSQLインジェクションですから、PHP固有の問題ではないですよね。きっと。

# 任意の結果を返すSQLを考える

WHERE 句をいじりまわしても、GROUP BY やら ORDER BY やら使っても、任意の結果は返せません。
なにか使えましたっけ？

・・・
・・・・・
・・・・・・・

そういえば UNION というものがありました。
O/Rマッパー脳は、すっかり忘れていましたよ。


# UNION をインジェクションする

どんな列を返せばよいか、あらかじめわかっているホワイトボックスハックですので、さっくりといってみます。

こんなSQLでいけるでしょうか？

```sql
SELECT * FROM users WHERE userid = ''
UNION
VALUES (NULL, 'Admin', 'ハッシュ化したパスワード', NULL) --'
```

パスワードを **abc** とすると、ソルト付きハッシュは `$2y$10$NzNs.erlBALZjj2YZJTtl.9wfZcB7dv00OgwF7Dn6BG6XcpBoeCEq` です。

試してみます。 :athletic_shoe: :soccer:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/6620763c-468c-be0a-43e7-d95ce9a3a5fd.png)

成功しました。:heart:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/05121ffd-6b3b-721b-9f41-28fcf9a277a1.png)


# 参考サイト

* [OWASP SQL Injection](https://owasp.org/www-community/attacks/SQL_Injection)
* [PortSwigger SQL Injection](https://portswigger.net/web-security/sql-injection)
* [SQLite ドキュメント](https://www.sqlite.org/lang.html)


# ひとりごと

それにしても、PHPには`password_verify`なんていう、 ~~きな臭そうな（偏見）~~ 便利な関数があるんですね。使ったことなかったです。
オープンデータを利用してTableauで地図上の可視化練習

## 目的
最近社内のTableau勉強会に参加してみたところ、Tableauをつかって地図上での可視化ができることを知ったので試しにやってみる。
ある程度実務でもつかうことを意識していくつかの機能を盛り込んで動かしてみる。
無料でつかえる[Tableau Public](https://public.tableau.com/app/discover)と東京都のオープンデータを利用。

## 作成方針
1. データセットの準備
    1. 東京都の公共施設のオープンデータをダウンロード
1. データセットの加工（Excel）
    1. 市区町村でのフィルタをかけられるように市区町村名を付与（デフォルトではNULL）郵便局の市区町村データでVLOOKUP、不明分は住所を目検で入力
    1. 公園や庭園、美術館、博物館等のフラグをつけてカテゴリでのフィルタをかけられるように処理
1. ダッシュボードの作成（Tableau）
    1. データの読み込み（Google Driveに接続）
    1. 地図での可視化
    1. フィルタ機能で市区町村・カテゴリを絞り込む機能をつけたい
    1. カテゴリごとにマークの色を分けたい
    1. カーソルを合わせると施設の説明が出るようにしたい
    1. 施設一覧の作成
    1. 施設一覧と地図を並べて見られるようにしたい

### 1. データセットの準備
[東京都オープンデータカタログサイト](https://portal.data.metro.tokyo.lg.jp/)から[公共施設一覧](https://catalog.data.metro.tokyo.lg.jp/dataset/t000003d0000000033/resource/27d1ce20-9023-4690-944c-5da47ed1427e)のデータをダウンロード
![ローデータ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1127172/9cfa93df-8ea2-0f07-ed71-e1b09c8047ea.png)


### 2. データセットの加工（Excel）
1.ダウンロードしたデータでは市区町村名が空欄のため、郵便番号を利用して埋めたい。[郵便局の市区町村データ](https://www.post.japanpost.jp/zipcode/download.html)をExcelにコピーし、郵便番号でVLOOKUP、不明分は住所を目検で入力。
![市区町村付与.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1127172/c262c94b-ea73-0655-15ee-3b0e883d1b3f.png)

2.公園や庭園、美術館、博物館等のフラグをつけてカテゴリでのフィルタをかけられるように処理する。
名称に公園や図書館を含む場合は該当のカラムに1を立てる。（ダミー変数化）
![カテゴリ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1127172/478931e2-0a63-c103-660a-53b8cbb8f51f.png)
いずれにも該当しないものをその他として扱う
![その他.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1127172/78c50364-3d15-3da8-9b0f-1bbf0bbe2abb.png)
ここで加工したデータセットをCSVで保存し、Google Driveに格納。
[データ加工に使用したExcel](https://docs.google.com/spreadsheets/d/1X2KkwQPAkL1IxbIlgtiDnUkL4ZZ4Y6D2/edit?usp=sharing&ouid=116593816208164636862&rtpof=true&sd=true)

### 3. ダッシュボードの作成（Tableau）
1.データの読み込み（Google Driveに接続）
![接続.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1127172/42540eba-1f40-22b9-3f44-a65e0f749fbc.png)
2.地図での可視化
→列に経度を、行に緯度を設定

3.フィルタ機能で市区町村・カテゴリを絞り込む機能をつけたい
→フィルタに市区町村名・カテゴリを設定。**施設一覧の表示の際にもこのフィルターを連動させたいのでフィルターの設定を、適用先ワークシートからこのデータソースを使用するすべてに設定。**
ついでに料金要否と駐車場有無も追加。

4.カテゴリごとにマークの色を分けたい
→カテゴリを色に設定

5.カーソルを合わせると施設の説明が出るようにしたい
→ツールヒントに説明を設定
![マップ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1127172/540050d1-47b0-1a18-c097-5418fd1235f4.png)

6.施設一覧の作成
![リスト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1127172/c2fd0986-568e-c2da-aa6b-552f810fe889.png)

7.施設一覧と地図を並べて見られるようにしたい
→上で作った２枚のシートをダッシュボードにまとめる
![ダッシュボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1127172/0410baa0-0d12-80e7-4254-51443b799339.png)

パブリッシュを押して完了
![パブリッシュ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1127172/3b4ee9e0-e028-a185-716d-552f0a43ac4f.png)


[作成したTableauダッシュボード](https://public.tableau.com/views/_16951330705070/sheet2?:language=ja-JP&:display_count=n&:origin=viz_share_link)
![Tableau.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1127172/dd71f0d8-376b-1d73-eccd-02209e121152.png)
【Swift】特定の要素が配列の何番目に入っているかを知りたい

# はじめに
要素が配列の何番目に出現するかを調べる方法を記事にしておきます

# 実装
```swift
struct XXX {
    let id: String
}

let array: [XXX] = [XXX(id: "000"), XXX(id: "001"), XXX(id: "002"), XXX(id: "003"), XXX(id: "004")]

let selectedItem = XXX(id: "003")

// `firstIndex`を使用することでIndexを調べることができる
if let index = array.firstIndex(where: { $0.id == selectedItem.id }) {
    print("`selectedItem`は配列の\(index)番目の要素です。")
} else {
    print("`selectedItem`は配列に存在しません。")
}
```

# おわり
`firstIndex`は覚えておきたいです
【GOT】レベル認証やオペレータ認証で、特定のスイッチの操作にパスワード入力を必要とする方法【三菱PLC】

GOTのスイッチやコメント表示などのオブジェクトは、オブジェクトや画面ごとに現在のセキュリティレベルの値に応じて非表示や入力可否を切り替えることが可能です。
ベース画面やスイッチ、コメント表示の編集画面を開いたら拡張機能タブを選択し、そこにあるセキュリティレベルの項目から、現在のセキュリティレベルに応じた入力や表示の制限の設定を行います。

https://fa-faq.mitsubishielectric.co.jp/faq/show/20173

パスワードによる認証機能の追加は大きく分けて二種類あります。

## レベル認証でのセキュリティレベル変更方法

ユーザーがGOTの画面から現在のセキュリティレベルを変更できるように、画面に拡張機能スイッチを配置し、動作設定を「パスワード(セキュリティレベル認証)」にします。このスイッチを押すことで、ユーザーがパスワード入力画面を開けるようにします。

あらかじめ設定しておいた特定のパスワードを入力することで、そのパスワードに応じたセキュリティレベルがGOTのセキュリティレベルデバイスに格納され、その値に従って画面上のオブジェクトの表示などが変わります。
レベル認証用のパスワードの設定は、「共通の設定」タブから「GOT環境設定」を選択し、「セキュリティ」の設定画面で「レベル認証」を選択します。ここから各セキュリティレベルのパスワード設定を行います。



https://fa-faq.mitsubishielectric.co.jp/faq/show/24622


## オペレータ認証でのセキュリティレベル変更方法

ユーザーがGOTの画面からオペレータを変更(ログイン)できるように、画面に拡張機能スイッチを配置し、動作設定を「ログイン/ログアウト(オペレータ認証)」にします。このスイッチを押すことで、ユーザーはオペレータ名とパスワードを入力しログインできるようになります。

オペレータ認証を有効にするには、「共通の設定」タブから「GOT環境設定」を選択し、「セキュリティ」の設定画面で「オペレータ認証」を選択します。

オペレータの追加はGOTのユーティリティから行います。GOT本体画面の左上を三秒以上長押ししユーティリティメニューを開いたら、GOT基本設定内のオペレータ認証からオペレータ管理をタップします。管理者（Administrator）パスワードの入力を求められますが未設定（デフォルト）の場合はそのままEnterを押します。この画面でオペレーターの作成や編集、削除を行います。
「追加」を選択すると、オペレータの作成画面に入ります。ログイン用のオペレータ名とパスワード、オペレータのセキュリティレベルを決め、OKを選択し、編集が終わったら「保存」をタップし設定内容を保存します。

https://fa-faq.mitsubishielectric.co.jp/faq/show/20564

https://fa-faq.mitsubishielectric.co.jp/faq/show/24623


また、パスワードではなく外部認証機器によるオペレータ認証を行う方法もあります。

![index.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535456/dea91fe3-d002-d040-754e-484debe1c86b.jpeg)


#### GDデバイスの設定方法

https://qiita.com/PockTTY/items/ff8da197b333663bf432
awsのインフラを構築して、Terraform化しようとしたときに調べたことをまとめてみた。


Terraformについて完全理解した。(ダニング＝クルーガー効果)

# Terraformについて
- HashiCorp社がGo言語で開発したツールである。
- インフラを構造化言語で記述することができる。

# Terraformで、できること
- インフラをコード化できる。
    - 何度もインフラを構築する時に、手作業で構築しなくて良い。
- 構築後のインフラを管理も可能。
    - 変更やインフラの追加に対応することが可能。
- 既存のインフラの設定をtfstateファイルという設定を保存するファイルにimportすることができる。


# Terraformは何をしてくれるのか。
- 記述した構造化言語の記述を元に、AWSのAPIを叩いてインフラを作成する。
- APIでインスタンスを作成可能だが、Terraformを使うことで状態の管理もできるところが良い。

# Terraformでコードを書くときには、何のドキュメントを参考にするのか。
- まず参考にしたのは、下記の2点です。
    - [Terraformのドキュメント](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)
    - [AWSのAPIドキュメント](https://docs.aws.amazon.com/index.html)
    - 基本的にTerraformのドキュメントを参考にして、terraformを記述していくが、terraformで指定する値がわからないときに、AWSのAPIドキュメントを参照して、値やパラメータの設定を確認します。

# 私がTerraformでインスタンスを構築するときにやったデバッグ手順
Terraformでどこのパラメータを設定したら良いのか、何の設定が不足しているのか、わからないことが多々あった。いろいろなドキュメントを見たりして、やってみたが、うまくいかなかった。とりあえず、awsのコンソールを触って、インフラを構築することはできるため、Terraformを使ってコード化するときに現物とterraformのコードを見比べながら、デバッグの方法をやっていました。
- まず、手作業でインスタンスを構築する。
    - terraformのimportコマンドで、手作業で構築したインスタンスをtfstateファイルにimportする。【1】
`terraform import aws_instance.<インスタンス名> <インスタンスID>`
[terraformのimportコマンド](https://developer.hashicorp.com/terraform/cli/commands/import)

- 次に、terraformで簡単なインスタンスを構築する。
    - terraformで作成した場合、tfstateファイルができる。【2】
        - 例えば、こちらを参考にする。
            - [terraform ec2 instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance)

- 手動で作成してimportしたtfstaeファイル【1】に、terraformで作成したtfstateファイル【2】を比較して、不足していそうなパラメータなどを調べて、Terraformのファイルに追記する。

この方法を繰り返すことで、実際に構築してあるインフラをTerraformのコードとして実装していました。
awsのコンソールを触ってインフラを構築できる人が、Terraform化するときの助けになってくれると良いと思っております。
簡単なGitコマンドの復習

# はじめに
業務では主にSVNを使用しているため、Gitを触ることがありません。
なので、勉強がてらここに備忘録として残しておきます。
# ① git init
```
$ git init
```
```git init```は、現在のディレクトリ内に新しいGitリポジトリが初期化されます。
Gitは、リポジトリの管理に必要なディレクトリやファイル（.gitディレクトリ）を作成します。

# ② git add
```
$ git add
```
```git add```は、変更したファイルや新しいファイルを、次のコミットで記録するための一時的なリストに追加するコマンドです。つまり、変更を「次にコミットする準備をする」というイメージです。
コミットする前に、どの変更を含めるかを指定するために使います。

# ③ git commit -m "コメント"
```
$ git commit -m "コメント"
```
```git commit ``` は、行った変更を「確定」するためのものです。
-m を付けることでコメントを残すことができます。

# ④ git remote add origin ×××××
```
$ git remote add origin https://github.com/〇〇/〇〇.git
```
```git remote add origin ```は、インターネット上にあるサーバーと接続を設定する際に使用されます。

# ⑤ git push origin master
```
$ git push origin master
```
```git push origin master ```は、```git commit```を実行して確定したファイルやフォルダを、
オンラインにアップロードし、インターネット上で共有することができます。

# おわりに
ローカルにあるプロジェクトは今後、Gitで管理していこうと思います。
【Kotlin入門】抽象メソッドとポリモーフィズムを理解しよう

この記事では、Kotlinでの抽象メソッドとポリモーフィズムについて解説していきます。抽象メソッドとポリモーフィズムは、オブジェクト指向プログラミングの重要な概念です。コードの再利用性や拡張性を高めるために、ぜひ覚えておきましょう。

## 抽象メソッドとは

抽象メソッドとは、具体的な処理内容を定義しないメソッドのことです。抽象メソッドは、abstractキーワードを付けて宣言します。例えば、以下のようにAnimalクラスにspeakという抽象メソッドを定義することができます。

```kotlin
abstract class Animal {
    // speakという抽象メソッド
    abstract fun speak()
}
```

抽象メソッドを持つクラスは、必ずabstractキーワードを付けて宣言しなければなりません。また、抽象クラスはインスタンス化できません。抽象クラスを継承したサブクラスで、抽象メソッドをオーバーライドして具体的な処理内容を定義する必要があります。例えば、以下のようにDogクラスとCatクラスでspeakをオーバーライドすることができます。

```kotlin
// DogクラスはAnimalクラスを継承する
class Dog : Animal() {
    // speakをオーバーライドして具体的な処理内容を定義する
    override fun speak() {
        println("ワンワン")
    }
}

// CatクラスもAnimalクラスを継承する
class Cat : Animal() {
    // speakをオーバーライドして具体的な処理内容を定義する
    override fun speak() {
        println("ニャー")
    }
}
```

抽象メソッドをオーバーライドするときは、overrideキーワードを付ける必要があります。また、抽象メソッドのパラメータや戻り値の型は、親クラスと同じでなければなりません。

## ポリモーフィズムとは

ポリモーフィズムとは、多様性や多形性という意味で、同じ型の変数やメソッドが、実行時に異なる振る舞いをすることを言います。ポリモーフィズムを利用すると、コードの可読性や拡張性を高めることができます。例えば、以下のようにAnimal型の変数に、Dog型やCat型のインスタンスを代入することができます。

```kotlin
fun main() {
    val animal1: Animal = Dog() // Animal型の変数にDog型のインスタンスを代入
    val animal2: Animal = Cat() // Animal型の変数にCat型のインスタンスを代入

    animal1.speak() // Dogクラスのspeakが呼び出される
    animal2.speak() // Catクラスのspeakが呼び出される
}
```

このように、同じ型の変数やメソッドでも、実行時に代入されたインスタンスの型に応じて、異なる処理が行われます。これがポリモーフィズムです。ポリモーフィズムを使うと、親クラス型の変数やメソッドでサブクラスのインスタンスを扱えるようになります。これによって、コードの柔軟性や再利用性が向上します。

## まとめ

この記事では、Kotlinでの抽象メソッドとポリモーフィズムについて、初心者向けに解説しました。抽象メソッドとは、具体的な処理内容を定義しないメソッドで、サブクラスでオーバーライドする必要があります。ポリモーフィズムとは、同じ型の変数やメソッドが、実行時に異なる振る舞いをすることで、コードの可読性や拡張性を高めることができます。これらの概念は、オブジェクト指向プログラミングの基礎ですので、ぜひ覚えておいてください。

Source: Conversation with Bing, 2023/9/20
(1) Kotlin Serialization ガイド 第4章 ポリモフィズム - Qiita. https://qiita.com/guijiu/items/b177808b03b59f76c8ee.
(2) 【Kotlin入門】オーバーロードとポリモーフィズムについて .... https://kotlin-study.com/overload-polymorphism/.
(3) 【初学者向け】ポリモーフィズムをわかった気になろう! - Qiita. https://qiita.com/yuta_931214/items/a588e9d7bd8872aedb9c.
GitHub PagesでWebサイトを公開するまでの手順


# GitHub Pagesとは
GitHub Pagesを一言でまとめると、

作成したWebページ(HTML/CSS,JSのWeb上で動作するページ)を
**インターネット上で公開するための無料で使用できるサービス**です。

上記を行うとなると
一般的に、まず使用するサーバーを立ち上げて、あれこれ設定が必要で、インフラに疎い人にとってはかなりハードルが高いものとなっています。
一方で、GitHub Pagesを使えば、簡単に作成したWebページをインターネット上に公開することができます。

# 手順

### 準備

GitHub Pagesを使用する前に
- [ ] 既にGitHubのアカウント登録の設定、初期設定が済んでいる
- [ ] 手元に公開するためのHTML/CSSファイルおよび画像が用意できている

ということを前提に話を進めていきます。
もしまだGithubの初期設定が完了していない場合は下記を参考にいただければと思います。

https://qiita.com/yasuyuki_sadahira/items/01bb04d039589d1e8e42

### 流れ
1\. GitHub Pagesで使用するためのリモートリポジトリを作成する

2\. 上記のリモートリポジトリに公開したいHTML/CSSファイルをローカルからプッシュする

3\. ファイルがアップされたリモートリポジトリを開きSettings > Pagesにて上記ファイルの公開設定を行う

の３点となっております。
以下で詳細を説明していきます。

#### 1.リモートリポジトリの作成


* 「Ripositories」タブにて「New」をクリック
![スクリーンショット 2023-09-20 14.48.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265379/31e10c0d-aaf1-cd22-c57e-092b4e7e9928.png)

↓

* 「Repository name」に任意の名前を入力
* 「Public」にチェックを入れる（**※ここでPrivateにcheckを入れるとWeb上で公開できなくなるので注意！**）
* 「Create repository」をクリックし、リモートリポジトリの作成完了
![スクリーンショット 2023-09-20 14.50.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265379/b8d3f42d-c621-0208-6267-a89ce22acbb2.png)


#### 2.公開したいHTML/CSSファイルをローカルからリモートへプッシュする

* ローカルにファイルを作成する

* GitHubにて先ほど作成したリポジトリを開き、SSHのURLをコピーする。

![スクリーンショット 2023-09-20 15.16.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265379/d96c00f4-e615-cecc-c7d3-56749f31f92a.png)

↓


* ローカルPCにファイルを作成し、VSコードで開き、ターミナル画面にて``git clone 上記URL``と入力
→リモートリポと接続されたローカルリポ(ここではresume)が作成される

![スクリーンショット 2023-09-20 15.20.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265379/3e94bc38-d956-dd5f-b990-0129feb8285d.png)

↓

* 　``cdコマンド``にてローカルリポジトリのファイルに移動する。
* リモートリポジトリのファイル(ここではresume)にWeb上で公開したいファイルもしくは画像を設置する。

![スクリーンショット 2023-09-20 15.28.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265379/fa6a5ea0-cef2-e81c-d758-0dfe7b7d10b0.png)

↓

下記コマンドを実行し、今回Web上で公開したいファイルまたは画像をリモートリポジトリにpushする。

```git:コマンド
git add ファイル名
git commit -m 'コミット名'
// ローカルリポジトリにファイルを反映

git push origin main
//リモートリポジトリにファイルを反映

```

![スクリーンショット 2023-09-20 19.21.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265379/755c279b-33d1-bcc4-2a8a-a2bf83907e7b.png)



#### 3.Settings > Pagesにて上記ファイルの公開設定を行う

* 公開ファイルが置かれたリポジトリから「Settings」を選択
![スクリーンショット 2023-09-20 19.40.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265379/daffb767-c82a-e5de-6100-de40dc6a1f34.png)

↓

* 「Pages」を選択
* 「Branch」から公開したいファイルが置かれたブランチを選択し「Save」をクリック
* 「Visit site」を選択
![スクリーンショット 2023-09-20 19.42.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265379/8d6f16d1-19d4-e812-3b8d-bce8e4f6cc2c.png)

↓
* 目的のファイルをWeb上で公開することができました！！
![スクリーンショット 2023-09-20 19.54.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265379/322f1424-8f06-dc0f-552c-2f4971046b34.png)


# おわりに
いかがだったでしょうか
GitHub Pagesを使えば、簡単に自分で作成したWebページをインターネット上で公開することができます。
便利かつ無料の機能なので是非とも活用いただければと思います。
最後まで閲覧いただきありがとうございました！！
[Go] defer, panic, recover 簡単整理 (備忘録)

> 記事の内容は間違いがあり得ますので、ご了承いただけると幸いです。内容の間違い、認識の違い、違う意見などありましたら、コメント大歓迎です！

# defer

deferとして定義した構文や関数をStackに保持しておき、現在の関数処理の終了とともにPOPされて実行する

### Example

```go
package main

import "fmt"

func main() {
    fmt.Println("Main func start") // 1
    defer func() { fmt.Println("First defer") }() // 4
    defer func() { fmt.Println("Second defer") }() // 3
    fmt.Println("Main func end") // 2
}
```

### Result

```
Main func start
Main func end
Second defer
First defer
```

# panic

現在の関数処理を止めて、Stackに登録されているdefer関数をPopし実行する

### Example

```go
package main

import "fmt"

func main() {
    fmt.Println("Main func start") // 1
    defer func() { fmt.Println("Main func first defer ") }() // 6

    foo()

    defer func() { fmt.Println("Main func second defer") }()
    fmt.Println("Main func end")
}

func foo() {
    fmt.Println("Foo func start") // 2
    defer func() { fmt.Println("Foo func first defer ") }() // 5

    bar()

    defer func() { fmt.Println("Foo func second defer") }()
    fmt.Println("Foo func end")
}

func bar() {
    fmt.Println("Bar func start") // 3
    defer func() { fmt.Println("Bar func first defer ") }() // 4
    panic("Ops..")
    defer func() { fmt.Println("Bar func second defer") }()
    fmt.Println("Bar func end")
}
```

### Result

```
Main func start
Foo func start
Bar func start
Bar func first defer 
Foo func first defer 
Main func first defer 
panic: Ops..

goroutine 1 [running]:
main.bar()
	D:/repository/go-testcode/main.go:28 +0xbe
main.foo()
	D:/repository/go-testcode/main.go:19 +0xa3
main.main()
	D:/repository/go-testcode/main.go:9 +0xa3
```

# recover

- panic状態を正常状態に戻す
- defer関数ないで利用するのが一般的
- panic発生の関数の処理は止められるが、panic発生関数の上位関数の処理は継続される

### Example

```go
package main

import "fmt"

func main() {
    fmt.Println("Main func start") // 1
    defer func() { fmt.Println("Main func first defer ") }() // 10

    foo()

    defer func() { fmt.Println("Main func second defer") }() // 9
    fmt.Println("Main func end") // 8
}

func foo() {
    fmt.Println("Foo func start") // 2
    defer func() { fmt.Println("Foo func first defer ") }() // 7

    bar()

    defer func() { fmt.Println("Foo func second defer") }() // 6
    fmt.Println("Foo func end") // 5
}

func bar() {
    fmt.Println("Bar func start") // 3
    defer func() {
        fmt.Println("Bar func first defer ") // 4
        recover()
    }()
    panic("Ops..") // 함수를 종료
    defer func() { fmt.Println("Bar func second defer") }()
    fmt.Println("Bar func end")
}
```

### Result

```
Main func start
Foo func start
Bar func start
Bar func first defer 
Foo func end
Foo func second defer
Foo func first defer 
Main func end
Main func second defer
Main func first defer
```
ゲストログイン機能

# 初学者の備忘録
初学者の備忘録です。今回はdeviseを使用したゲストログイン機能編


## ゲストログイン
ゲストログインとはユーザーログインのようにメールアドレスやパスワード登録などをしなくても、ある程度制限のある中で気軽に会員と同じ機能を使えるログイン方法のことです。実務ではあまり使用しない機能らしいのですが、PFなど自分の作品を誰かに発表するときなどはある方が便利らしいです。

今回はそんなゲストログイン機能をdeviseを使用して作成したいと思います。



## 実装
【１】　コントローラー
deviseでサインイン機能はできているので、あとはどのユーザーをログイン状態にするか指定してあげればいいです。
```ruby:app/controllers/users/sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
  def guest_sign_in
    user = User.guest
    sign_in user
    redirect_to user_path(user), notice: "guestuserでログインしました。"
  end
end
```


【２】　ルーティング
ルーティングの設定をします。
```ruby:app/controllers/users/sessions_controller.rb
:
:

  devise_scope :user do
    post "users/guest_sign_in", to: "users/sessions#guest_sign_in"
  end

:
:
```


【３】　メソッド
モデルにguestメソッドを定義します。
```ruby:app/models/user.rb
:
:
# 定数にメールアドレスを格納
GUEST_USER_EMAIL = "guest@example.com"

  def self.guest
    # find_or_create_byでメールアドレスが存在するかどうか判断。存在しない場合はデータを作成する。
    find_or_create_by(email: GUEST_USER_EMAIL) do |user|
    　　　　# SecureRandom.urlsafe_base64:ランダムな文字列を生成するRubyのメソッド
      user.password = SecureRandom.urlsafe_base64
      user.name = "guestuser"
    end
  end

:
:
```
ゲストユーザーに必要なカラムが存在したら
<details>
  <summary>補足</summary>
    find_or_create_byとは条件を指定してその条件に合致した場合、合致した１件のデータを取ってくる。存在しなかった場合は新規作成するメソッドです。<br>
似たようなものでfind_or_create_byメソッドがありますが、こちらは作成ではなくnewアクションになるのでデータベースに保存されません。保存したい場合はsaveをしないいけません。<br>
whereメソッドは条件に合致したデータを全て取得してしまいますので、今回の場合はふさわしくありません。
</details>


【５】　ログインボタン
ビューにゲストログインボタンを追加しましょう。ここは自由に作成してください。
例としてあげて起きます。
```ruby:app/views/homes/top.html.erb
<%= link_to "ゲストログイン（閲覧用）", users_guest_sign_in_path, class: "btn btn-secondary btn-sm btn-block mb-3 sign_in", method: :post %>
```

以上で実装終了です。お疲れ様でした。