OmniAICreator/Qiita-1.07M huggingface dataset:
Railsチュートリアル：13章(わからないとこメモです)

#第13章ユーザーのマイクロポスト

##13.1 Micropostモデル

親であるユーザーが破棄された場合には自動的に破棄されるようにします

はい。

##13.1.1 基本的なモデル

Micropostモデルは、「特定のユーザーとマイクロポストを関連付けるuser_id属性」を持つ

このDB内の紐づけが肝だとおもい。
プロゲートのSQLでも軽くみたはず。

```ruby

rails generate model Micropost content:text user:references
```
ポストのモデルを作成
注目はuser:references
これがあると

```ruby
class Micropost < ApplicationRecord
   belongs_to :user
end
```

belong_toがついてくる。

references型を利用すると、自動的にインデックスと外部キー参照付きのuser_idカラムが追加されUserとMicropostを関連付けする下準備をしてくれます。

なるほど。


##13.1.2 Micropostのバリデーション

##13.1.3 User/Micropostの関連付け


UserモデルとMicropostモデルをそれぞれ更新して、関連付ける必要がある
Micropostモデルの方では、belongs_to :userというコードが必要になるのですが、これは リスト 13.10のマイグレーションによって自動的に生成されている
Userモデルの方では、has_many :micropostsと追加する必要があります。ここは自動的に生成されないので、手動で追加


なるほど。


```ruby

class Micropost < ApplicationRecord
  belongs_to :user
  validates :user_id, presence: true
  validates :content, presence: true, length: { maximum: 140 }

```


##13.1.4 マイクロポストを改良する

ふむ


##13.2 マイクロポストを表示する

まあはい


##13.2.1 マイクロポストの描画

ふむふむ


##13.2.2 マイクロポストのサンプル


```
users = User.order(:created_at).take(6)
50.times do
  content = Faker::Lorem.sentence(5)
  users.each { |user| user.microposts.create!(content: content) }
end
```

上記を追加seedsに追加しようとするとcloud9で×マークがでる。
なんか足りないよ、と。

どうやら、このチュートリアルがかいてるendはeachにたいするもので
seedsファイル全体のendとは別らしい。たぶん。

で、

```ruby
$ rails db:migrate:reset
$ rails db:seed
```

ここのseedは結構時間かかった。

久々にブラウザで確かめてみようとか思ってひらくと
ログインしてないのでマイクロポストが一覧で表示されるのかをみれない。

DBから落として、ログインすればいいやとか思って落とすと
パスワードが暗号化されててはいれない(当たり前だけど)

ならばと新規登録してみる。

ここでハッと気づいたのが、メール認証が必要である。

herokuにクレジット登録するのがいやでメール機能がオンになっておりません。

なので新規登録もできません。。。

終わった。。。チュートリアルの過去を探すしかない。。。

と、ここで、そういえばfixtureてきなやつをみればわかるのでは？と気づく。

```ruby
michael:
  name: Michael Example
  email: michael@example.com
  password_digest: <%= User.digest('password') %>
  admin: true
  activated: true
  activated_at: <%= Time.zone.now %>
```

すみません、ここから紐解く実力はありません。。。

グーグルさんに聞いてみると同じ症状の人がいらっしゃいました。


[友よ、、、](https://teratail.com/questions/136408)


解決しないのでログインはあきらめて進みます。


と、おもったらここはログインしてなくともみれる場所でありました。

最後に
/users/1
をつければ見れます。


##13.2.3 プロフィール画面のマイクロポストをテストする

##13.3 マイクロポストを操作する

##13.3.1 マイクロポストのアクセス制御

##13.3.2 マイクロポストを作成する

##13.3.3 フィードの原型

ユーザーがフィードを持つので、feedメソッドはUserモデルで作るのが自然

##13.3.4 マイクロポストを削除する

##13.3.5 フィード画面のマイクロポストをテストする

##13.4 マイクロポストの画像投稿

##13.4.2 画像の検証

ファイルサイズに対するバリデーションはRailsの既存のオプション (presenceやlengthなど) にはありません。したがって、今回は手動でpicture_sizeという独自のバリデーションを定義

##13.4.3 画像のリサイズ

##13.4.4 本番環境での画像アップロード

世の中には多くのクラウドストレージサービスがありますが、今回は有名で信頼性も高いアマゾンの「Simple Storage Service (S3)25 」を使います。セットアップの手順は次のとおりです。

(1.2.1でAWSアカウントを作成していない場合) Amazon Web Servicesアカウントにサインアップする
AWS Identity and Access Management (IAM)でユーザーを作成し、AccessキーとSecretキーをメモする
AWS ConsoleからS3 bucketを作成し (bucketの名前はなんでも大丈夫です)、2.で作成したユーザーに対してRead権限とWrite権限を付与する

↑ここはとばす


あまり書くこともなかった。。。
理解できてなさ過ぎて。。。二周目に期待。
Sourcetree でクローン失敗したら VScode でやればうまくいくことがあるよ

Sourcetree は直感的で使いやすいのでメインのgitクライアントとして使っているのですが、ちょくちょくエラーになってしまいます（ cline や push 時）。

今回は、 clone 時に以下のエラーが出ました。

fatal: Remote branch 200509_ログインエラー時に処理停止 not found in upstream origin

ブランチ名を日本語にしてみたのが良くなかったのかな？と思いましたが、Visual Studio Code でクローンしてみたところ、なんのエラーも出ず、通常通りクローンできました。

Sourcetree をお使いの方、vscode の方が良いかもしれません！😁
IntelliJ+KotlinでDagger2を使う

Androidプロジェクトではなく、IntellijでDagger2を試したいと思い、調べつつ試してみた。

Intellijのkotlinプロジェクトを作成する。

build.gradleの初期状態はこうなってる。

```groovy:build.gradle
plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.3.70'
}

group 'org.ikemura23'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
```

## Dagger2 導入する

dagger2をbuild.gradleに追加する。

また、kaptを有効にする記述も追加している。

```groovy:build.gradle
plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.3.70'
}

group 'org.ikemura23'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

apply plugin: 'kotlin-kapt' // kaptを有効にする記述を追加

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
    // Dagger2 追加
    implementation "com.google.dagger:dagger:2.27"
    kapt "com.google.dagger:dagger-compiler:2.27"
}
// kaptを有効にする記述を追加
kapt {
    generateStubs = true
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
```

## IntelliJの設定を変更する

IntelliJ > Preferences を開いて、

`Preferences | Build, Execution, Deployment | Build Tools | Gradle`

IntelliJ IDEA から `Gradle(Default)`に変更する。

<img width="1094" alt="スクリーンショット 2020-05-09 10.23.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52227/f4c8166f-78fc-c368-f25c-a8c7809fc478.png">

これで設定は完了。

## Daggerの動作確認

### Component
`DaggerAppComponent`を作成するためのComponentを作る。

```kotlin
@Component(modules = [AppModule::class])
interface AppComponent {
    // Component.Factoryパターン
    @Component.Factory
    interface Factory {
        fun create(): AppComponent
    }

    fun hoge(): Hoge
    fun fugaProvider(): Provider<Fuga>
}
```

### Module

```kotlin
@Module
class AppModule {
    @Provides
    fun provideHoge(): Hoge {
        return Hoge()
    }

    @Provides
    fun provideFuga(hoge: Hoge): Fuga {
        return Fuga(hoge)
    }
}
```

これでビルドすると`DaggerAppComponent`が作成されて使用できればOK

```kotlin:main.kt
fun main(args: Array<String>) {
    // hogeの取得
    val hoge = DaggerAppComponent.factory().create().hoge()

    // fugaの取得
    val fuga = DaggerAppComponent.factory().create().fugaProvider().get()
}

```



## 使用コード
https://github.com/ikemura23/kotlin-sandbox/tree/dagger2/src/main/kotlin
【Rails】CRUDとHTTPメソッドとアクションとヘルパーメソッドと内容を一緒に

# 一覧表
タイトルのように、横一線で覚える方が実用的だと思い、まとめました！

Userモデルを例に

| CRUD |HTTPメソッド|アクション|URLパターン|ヘルパーメソッド|内容|
|:---:|:---:|:---:|:---:|:---:|:---:|
|Read|GET|index|/users|users_path|ユーザー一覧ページの「表示」|
|Read|GET|show|/users/(1)|user_path|ユーザーのページを「表示」|
|Read|GET|new|/users/new|new_user_path|ユーザー作成ページの「表示」|
|Create|POST|create|/users|users_path|ユーザーの『作成』|
|Create|PUT|create|/users/(1)|user_path|指定ユーザーに関わる『作成』|
|Read|GET|edit|/users/(1)/edit|edit_user_path|ユーザー編集ページの「表示」|
|Update|PATCH|update|/users/(1)|user_path|ユーザー情報の一部を『更新』|
|Update|PUT|update|/users/(1)|user_path|ユーザー情報の全体を『更新』|
|Delete|DELETE|destroy|/users/(1)|user_path|ユーザーの『削除』|

## 補足
### POST, PUTの違い
- **リソースを指定した操作なのかどうか**の違いと、**結果が冪等であるかどうか**の違い（後ほど冪等性について解説）

### PUT, PATCH の違い
- ユーザー情報を**一部**更新する（PATCH）のか、**まるっと全て**を更新する（PUT）のかで判断

### 冪等性（べきとうせい）
冪等性は、**何度やっても同じ結果を返すこと**という意味ですが、ここで覚えることは、

- `POST`が**唯一**、HTTPメソッドの中で**冪等性がない**

ということです。

例えばユーザーを作成する`create`（POST）の実行結果を考えてみると、毎回違うユーザーが作成されるはずですね。

その他のメソッドは常に1つの結果にしかなりません。（`destroy`などの一回しかやらない操作も、1つの結果であることは同じ）

以上、RESTfulなリソース選定にご参考にしていただければ幸いです！

## 参考
- [PUT か POST か PATCH か？](https://qiita.com/suin/items/d17bdfc8dba086d36115)
- [冪等性とは「同じ操作を何度繰り返しても、同じ結果が得られる性質」のこと](https://qiita.com/suin/items/316cb8aaf8dfcf11abae)
- [WEBの成功理由は制約 ８つしかないHTTPメソッド](http://kaihooo.com/http-method/)
まずは簡単なnpmパッケージを半日で作ってみよう

# 動機

[e-stat-population](https://github.com/wafuwafu13/e-stat-population)というnpmパッケージを公開したので、簡単に備忘録としてこの記事を書いています。

プログラミングの学習を初めて約1年、がっつりコードを書き始めてから約半年が経ちました。
そろそろチュートリアルをする側から作る側へ、インストールする側からインストールされる側へと興味が移行してきた年頃です。

npmパッケージの公開は、審査もないので、簡単なものだったらアプリの審査を通るとかOSSへのコミットとかよりもだいぶ敷居は低いと思います。(OSSへのコミットはしたことがないので難易度は計り知れません)

まず、読むべき記事は[初めてのnpm パッケージ公開](https://qiita.com/TsutomuNakamura/items/f943e0490d509f128ae2)です。
この記事を読んで[rpncc](https://github.com/TsutomuNakamura/rpncc)を作る流れを完全理解してよし、作ろう！ってできる人は対象読者外です。
このアルゴリズムはそこそこ複雑なので、やっぱむずそうだからやめとこ。。。ってなってる人はあと少し読み続けてください。

npmパッケージを公開することで得られる知見は、かかる時間の割には多いと思います。
というのも、いつもインストールしているnpmパッケージがどのように作成されているのかをざっくりと実感できる、自分も作れるようになりたいという感情が芽生える、作成されたパッケージのソースコードを読みにいく、という高度な世界への入り口になると思うからです。
ついでに普段の個人開発ではなかなかできないTDDも体験できます。

# 作成

では、僕がはじめに半日で作った簡単なnpmパッケージを見てもらいます。
[random-multiple-integers](https://github.com/wafuwafu13/random-multiple-integers)
``index.js``を見てもらえればわかると思うのですが、11行の簡単なプログラムです。
ちなみにこれは[【Javascript】ランダムな整数を桁指定で作る方法](https://qiita.com/wafuwafu13/items/698230f587ed3c92d45e)でまとめたのですが、ランダムな整数を桁指定で作るのが意外と難しかったのでnpmパッケージにしました。

これくらいならnpmパッケージをインストールせず関数にしろや、と自分でも思うのですが、最初はそこを考えずに、テストを書いて、通して、公開して、インストールする、readme、ライセンスをかく、という手順を踏むんだということを優先的に考えます。

[初めてのnpm パッケージ公開](https://qiita.com/TsutomuNakamura/items/f943e0490d509f128ae2)で丁寧に手順を解説されているので特に詰まるところはないと思います。

僕の場合は、テストにavaじゃなくてjestを使ったので、そこでbabelの設定が必要でした。
あと、パッケージの名前を、はじめは random-integer にしていたのですが、同じ名前のパッケージがすでに公開されていたみたいで、``package.json``の name を変えないといけませんでした。

# 発展

簡単なパッケージを公開できたら、もっと高度なnpmパッケージを考えてみます。
僕の場合は、ReactNativeで``<Text>``を``<View>``で囲むのがめんどくさい時があるからどうにかしたい、ラジオボックスの良いライブラリが少なかったから作ってみたい、と思ってましたが、めちゃくちゃむずそうなので一旦やめました。

[e-stat-population](https://github.com/wafuwafu13/e-stat-population)は、e-Stat関連のnpmパッケージが今までなかったのと、発展させてグラフ表示とか相関関係とかをcliだけで表示できたら面白そうだな、と思ったのでまずは人口だけ作りました。

詰まったところは、e-StatのAPIを叩くのにaxiosを使っていたのですが、公開した後にインストールして試してみると、パッケージの依存の関係(? まだ詳しく調べていない)でエラーが出たので、他のnpmパッケージを使わずnode.jsで``require('http')``をする方針に切り替えました。[参考](https://github.com/wafuwafu13/e-stat-population/commit/0c9f02b143f59eb4a06aeff4d07e39d345d7a645)

# 感想

合計2日で前から興味のあったnpmパッケージの公開ができました。
多分気のせいですが一段とレベルアップできた気がします。
npmパッケージの公開は審査がなくて無法地帯なのでちょっとでも興味があったらまずはサクッと作ってしまうことをおすすめします。
車輪の再発明という言葉はひとまず気にしないでおくことも精神衛生面上よろしいです。
モジュールによる共通化

#モジュールとは
一連の振る舞いを一箇所にまとめたもの。
クラスと似ているが**モジュールはインスタンス （オブジェクト）を生成できない**点が異なる。
`includeメソッド`を使うことでモジュールを使い回せる。

```***.rb
#モジュールを作成
module Chatting
  def chat
   "Hello"
  end
end

#モジュールをDogクラスに取り込む
class Dog
  include Chatting
end

#Dogクラスからpochiインスタンスを生成
#pochiをレシーバとしてChattingモジュールのchatメソッドを使用
> pochi = Dog.new
> pochi.chat
=> "Hello"  
```
WSL 環境における Git の credential helper 設定

元ネタ: [Edward Thomson: Git Credential Manager with Windows Subsystem for Linux](https://www.edwardthomson.com/blog/git_credential_manager_with_windows_subsystem_for_linux.html#configuration)

以下から Git for Windows をインストール

* https://gitforwindows.org/

WSLのシェル上で以下のように git credential helper を設定（Git for Windows の credential helper を利用する）

```bash
git config --global credential.helper \
  "/mnt/c/Program\ Files/Git/mingw64/libexec/git-core/git-credential-manager.exe"
```

すると git コマンドでリポジトリの認証が必要な箇所で以下のようにウィンドウが開いて認証を求められる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8219/e19854b7-214e-394d-9c6d-8c7fcaedfe14.png)

認証情報は一定期間保持されているらしい。便利だ。
Linux Mint19.3で設定変更等の保存可能なLiveUSBを作成する方法

#はじめに
Linux mint19.3のLiveUSBで設定保存が可能な状態にするのにちょっとはまったので、備忘録として記録します。
Puppy Linuxでは簡単に設定保存が可能なLiveUSBができたのですが、WiFiの対応ドライバが少ないのか、
内蔵のWiFiが認識されないケースが多々あり、Linux mintの方がこの辺の対応は良い印象。

#概要
LiveUSBの作成はUnetbootinを使用し、出来たLiveUSBにてgrubの設定ファイルを編集します。

#環境
- 作業環境：Windows10 pro 1909
- 作成するLiveUSBのOS：Linux mint Cinnamon 19.3 64bit
- LiveUSB作成：UNetbootin


ちなみに、LiveUSB作成にrufusも使用してみましたが、こちらで作成したものはOSが起動できませんでした。
（こちらの原因は深堀りしていません。）
 
#構築の流れ
##UNetbotinでLiveUSB作成
現時点で、UNetbotinにてOSイメージのダウンロードからできるLinux Mintのバージョンは19.2なので、
最新版の19.3は本家のサイトからダウンロードしました。
https://linuxmint.com/download.php
保存スペースはUSBの容量と相談。今回は16GBのUSBメモリで2,000MBに設定。
日本語化やWiFiの設定などちょっとした保存ができればよかったので。
この状態では、Linux Mintは起動しますが設定変更は保存されませんでした。
##出来たLiveUSBのgrub.cfgをテキストエディタで編集
X:\boot\grub\grub.cfg
【編集前】
<pre>
menuentry "Start Linux Mint 19.3 Cinnamon 64-bit" --class linuxmint {
	set gfxpayload=keep
	linux	/casper/vmlinuz  file=/cdrom/preseed/linuxmint.seed boot=casper iso-scan/filename=${iso_path} quiet splash --
	initrd	/casper/initrd.lz
}
</pre>
【編集後】
<pre>
menuentry "Start Linux Mint 19.3 Cinnamon 64-bit" --class linuxmint {
	set gfxpayload=keep
	linux	/casper/vmlinuz  file=/cdrom/preseed/linuxmint.seed boot=casper iso-scan/filename=${iso_path} quiet splash -- persistent
	initrd	/casper/initrd.lz
}
</pre>

linuxの行の末尾に[persistent]を追記しています。

これで準備完了です。これで設定変更が保存されるようになりました。

#　参考
-Ubuntu日本語フォーラム
https://forums.ubuntulinux.jp/viewtopic.php?id=20556
#Rails で JSON リクエストを受け取ると Controller でパラメータがキメラみたいにネストされるのだけど... ( rails JSON request params in controller nested - wrapped -  )

wrap_parameters の設定が原因っぽい

いろんなキーワードでググっても全然見つからなかった答え

# 参考

```rb
// post data
{"title":"asdsad"}

// rails parameters 
Parameters: {"title"=>"asdsad", "presentation"=>{"title"=>"asdsad"}}
```


https://stackoverflow.com/questions/27672954/rails-duplicated-the-parameters-inside-the-resource

https://guides.rubyonrails.org/action_controller_overview.html#parameters

https://api.rubyonrails.org/classes/ActionController/ParamsWrapper.html

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/3149











<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
docker-composeでLaravelの開発環境構築【LEMP環境】

**はじめに**
laravel開発環境(nginx、laravel、mysql、phpmyadmin)をdockerとdocker-composeで作ってみた。かなり創造性に溢れた？構成になっているので、異論は認める。

**豆知識**
LAMP環境のapacheがnginxになったらLEMPになるらしい。読み方が「エンジンエックス」だからEになるっていう説が濃厚

<h2>今回作成する開発環境</h2>
PHP:7.2.30
Laravel:7.9.2
nginx：latest
mysql:latest
phpmyadmin:latest

<h2>用意する環境</h2>
docker:19.03.8
docker-compose:1.25.4
composer:1.9.3→入れとくと便利


<h2>リポジトリ</h2>
https://github.com/atsugitakuya/docker_laravel_for_develop


<h2>使い方</h2>
①git cloneしリポジトリをローカルにクローンする

②「/sh」に移動し、以下のコマンドを実行する

```ruby:zsh
$sh setup.sh
```


③「/」に移動し、以下のコマンドを実行する

```ruby:zsh
$docker-compose up -d
```

④以下のメッセージが出力されたことを確認する

```ruby:zsh
.......
Creating laravel ... done
Creating nginx   ... done
Creating mysql   ... done
Creating phpmyadmin ... done
```


⑤以下に接続し、それぞれ画面が正しく表示されることを確認する。
[laravel](http://localhost)<img width="1373" alt="laravel.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631619/def498d4-c97f-3f18-9f81-7328d175bfd0.png">

[phpmyadmin](http://localhost:1234)
<img width="1345" alt="phpmyadmin.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631619/97fc048d-2a5f-fc0b-98e4-974d42506009.png">

⑥（必要であれば）migrationの実行
以下のコマンドを順番に実行していく。

```ruby:zsh
$docker exec -i -t laravel bash
$php artisan migrate
$exit
```

<h2>詰まったことリスト</h2>

<h3>詰まった事１</h3>
**laravelとmysqlのコンテナ間通信に失敗する**
このリポジトリではないが、laravelからmysqlに接続しようとする(sql実行しようとすると)とconnection refusedが出た。php artisan migrateでlaravelで定義されているmigrationファイル通りにmysqlにもテーブル作成されているのに、なぜか画面起点のときに接続できなかった。

**原因**
接続先IP（サービス）の設定ミス。
laravelの「.env」でmysql接続先IPをlocalhostにしていたが、これはlaravelコンテナ内localhost見ていることになる。コンテナが別なので、これでは接続できるはずがない。以下のように変更したら接続できた。

```ruby:.env（変更前）
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
```

```ruby:.env（変更後）
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
```

php artisan migrateが実行できたのは、（laravelコンテナ外の）ローカルPCのlocalhost:3306がmysqlコンテナに向いていたからっぽい。ちゃんとコンテナ入って実行してれば、よくわからない詰まり方をしなかったのになぁ、と反省。

<h3>詰まった事2</h3>
**composerのinstallが失敗する**
laravel用のDockerfileビルド時、Composerをinstallするのだが、記事で紹介されているコマンドを真似しているのに、インストール自体が失敗してしまう。謎すぎる。

**原因**
Composerのinstall方法が複数あり、その中でも最低の物をチョイスしていたらしい。
Qiitaに[ベストプラクティス](https://qiita.com/ucan-lab/items/17c806973e69792ada99)を紹介してくれている記事がある。これをコピペしたらインストール成功した。ありがたや...


---
なんだかんだ、業後の時間を使って２日でできた。
laravelは今後も使いたい？し、dockerの理解も少し深まったので良しとしよう。
以上！！！！
Node memo

■環境変数とは
https://techacademy.jp/magazine/16243
http://nayucolony.hatenablog.com/entry/2017/07/14/003251

■Gulp 4.0
https://zzz.buzz/2016/11/19/gulp-4-0-upgrade-guide/

■ミドルウェア
https://wa3.i-3-i.info/word178.html

■Router
https://expressjs.com/ja/guide/routing.html
https://qiita.com/irico/items/1beb6ccf8479b12d7065

■404
https://blanktar.jp/blog/2014/12/nodejs-errorhandling

■Postで受け取る
bodyParser
https://qiita.com/H__Goro_/items/050ebb62143ada022a32
https://qiita.com/ktanaka117/items/596febd96a63ae1431f8

■app.set
https://e-yota.com/webservice/express_object_app_set/
PHP コンストラクタとは(簡易メモ)

# 目的

- LaravelやPHPのコンストラクタとはなんなのかを簡単にメモする。

# コンストラクタとは

- とあるメソッドの名前である。
- クラスからインスタンスを生成する（オブジェクトがnewによって作られる)時に自動で呼び出されるメソッドのこと。
- 戻り値はない。
- インスタンスを生成するタイミングで実行されるので、プロパティの初期化やクラス内部で使用するリソースの初期化などを行う。

# 記載例

- 下記にコンストラクタの記載例を記載する。

    ```php
    <?php
    
    class クラス名{

        public function __construct(){
            処理;
        }
    }
    ?>
    ```
【JavaScript】関数の戻り値について。値を戻す場合、真偽値を戻す場合

#【JavaScript】関数の戻り値について。値を戻す場合、真偽値を戻す場合

戻り値を理解すると、共通処理である関数を使うメリットが増えるので整理します。

##計算結果を返す戻り値
計算結果を返す関数の例。

```js

    const add=(number1,number2)=> {
        return number1+number2;
    }
    console.log(add(1,2));
```

これを
・計算処理のadd関数
・addに引数を渡す定数sum
・省略記法(returnと{}の省略）
でさらに整理。

```js

    const add=(number1,number2)=> number1+number2;
    const sum = add(1,2);
    console.log(sum);
```

この場合、戻り値（return）の対象であるnumber1+number2は値を返している。
関数addは計算の共通処理を実行している。
実行結果は3となる。

##判定結果を返す戻り値
判定結果を返す関数の例。
returnにtrueとなる条件を書くことで判定結果を返している。
trueとなる条件を書く＝比較演算子(===,!==,>,<...など)ということ。

```js

    const checkNumber = (targetNumber) =>{
        return targetNumber === 0;
    }
```

引数targetNumberの値が0かを判定するcheckNumber関数。

引数に0を渡した場合checkNumber(0)
引数に1を渡した場合checkNumber(0)
それぞれの実行結果は次の通り。

```js

    console.log(checkNumber(0));//true
    console.log(checkNumber(1));//false
```

##応用：判定処理+メッセージ表示
targetNumber === 0;の判定に加えてif文を使った分岐を書いた例。
returnは処理を終了させる性質を持つので、return targetNumber === 0;から
targetNumber === 0;としている。

```js

    const checkNumber = (targetNumber) =>{
        targetNumber === 0;
        if(targetNumber === 0){
            console.log(`0です。`);
        }else{
            console.log(`0以外です。`);
        }
    }

    checkNumber(0);
    checkNumber(1);
```

実行結果

```js

1行目：checkNumber(0)
2行目：checkNumber(1)
```

    0です。
    0以外です。
Laravel7を日本語化する方法

Laravel5,6,7に対応。
ログイン画面や、エラーメッセージ、確認メールなどを日本語化します:blush:

Laravelはデフォルトでは以下のような英語表記になっています。
これを日本語にしていきます。

<img width="1148" alt="スクリーンショット 2020-05-08 15.54.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435447/b8063fe1-46ba-fce1-2a0b-1540259a5bc5.png">

##app.phpの設定を変更する
プロジェクトフォルダのconfig/app.phpの**'locale' => 'en'を'locale' => 'ja'**に変更する。

```php
    /*
    |--------------------------------------------------------------------------
    | Application Locale Configuration
    |--------------------------------------------------------------------------
    |
    | The application locale determines the default locale that will be used
    | by the translation service provider. You are free to set this value
    | to any of the locales which will be supported by the application.
    |
    */

    'locale' => 'ja',
```

##GitHubからダウンロードする
以下からZipファイルをダウンロードします。
https://github.com/caouecs/Laravel-lang

ダウンロードが終わったら、解凍してください。

##ファイルを配置する
1. 解凍したLaravel-lang-masterフォルダのjson/ja.jsonを、プロジェクトフォルダの resources/langに移動
2. Laravel-lang-master/src内のjaフォルダを、プロジェクト内のresources/langに移動
<img width="480" alt="スクリーンショット 2020-05-08 16.09.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435447/5bc95fad-778b-eea6-af6b-e282ae0ad2ff.png">

##日本語化完了！
ブラウザで確認してみてください:blush:
無事、日本語化できました。
<img width="1184" alt="スクリーンショット 2020-05-08 16.10.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435447/105c5a9a-b8e4-b530-19d7-968c24b2c01a.png">
Clang を入れてみる

# LLVM 単体では面白くなかった
LLVM を楽しもうと思ってインストールした(https://qiita.com/evakichi/items/3f2c69b827314c28f972) のはいいものの、それだけではお楽しみいただけないようで、Clang を入れてみないと面白いことができなさそうだったため Clang も入れてみます。
# Clang を入れる
早速 Clang を入れてみます。ダウンロードした2020年5月9日時点ではバージョンは10.0.0みたいです。Clang のソースディレクトリで以下をおこないます。

```
$ mkdir build
$ cd build
$ cmake3 -G "Unix Makefiles" -DCMAKE_C_COMPILER=/usr/local/bin/gcc  -DCMAKE_INSTALL_PREFIX=/opt/clang ../.
$ make -j8
$ sudo make install
```

で、インストールはできますので、あとはパスを通すと終わり。
TypeScript でインスタンスでないオブジェクトを渡すコードをコンパイル時に検出する

TypeScript で class の constructor で前提条件を満たすようチェックを入れたい。
しかし、クラスがメソッドを持たない public メンバーのみで構成される場合、クラスのインスタンスでないオブジェトを代入できてしまう。

```typescript
class Klass {
  readonly val: number
  constructor(val: number) {
    if (val < 0) throw new Error("error")
    this.val = val
  }
}
function fn(k: Klass) {}

fn({ val: 1})  // ok
const k: Klass = { val: 1} // ok
```

色々調べたが、コンパイルオプションなどで検出することはできないようなので、自分なりに方法を考えてみた。

# TL;DL

class にダミーのメンバを持たせることでコンパイル時に検出可能。

```typescript
class Klass {
  readonly val: number
  private _: void
  // 略
}
const k: Klass = { val: 1} // compile error
```

# 方法1: instanceof を使う

```typescript
class Klass {
  // 略
}

function fn(k: Klass) {
  if (!(k instanceof Klass)) throw new Error("error")
}

fn(new Klass(1)) // oK
fn({ val: 1})  // runtime error
const k: Klass = { val: 1 }  // ok
```

コンパイル時に検出されないし、代入は検出できないのでよろしくない

# 方法2: ダミーメンバを持たせる

```typescript
class Klass {
  readonly val: number
  private _: void // 追加
  constructor(val: number) {
    this.val = val
  }
}

function fn(k: Klass) {}

fn(new Klass(1)) // oK
fn({ val: 1})  // compile error
const k: Klass = { val: 1 } // compile error
/*
 * Argument of type '{ val: number; }' is not assignable to parameter of type 'Klass'.
 * Property '_' is missing in type '{ val: number; }' but required in type 'Klass'.
 */
```

コンパイル時に検出できる。生成されたJSにはメンバ _ は存在しないので、オーバーヘッドもなし。いい感じ。

ダミーメンバの型が `void` なのは、`'_' is declared but its value is never read.` を回避するため。
【Expo】ios,androidのストア公開で詰まったメモ

少し詰まったのでメモします。
基本的なビルドの仕方は、udemyの[React Native で iOS / Android アプリ開発をゼロから始めよう！](https://www.udemy.com/course/react-native-ios-android/)の通りにやればいけると思います。

# iOS

## 「Guideline 2.3.8 - Performance - Accurate Metadata」 の対処法

<img width="925" alt="スクリーンショット 2020-05-05 08.35.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/39fe175f-fa6a-8a85-3707-e3cad78de4c4.png">

Developer Accountで設定したのと同じ名前をapp.jsonに設定する。

```app.json
"expo": {
    "name": "多面！フラッシュ暗算",
    ...
```

## Application Loader でビルドファイルをアップロードできない

```
Please sign in with an app-specific password. You can create one at appleid.apple.com.
```

Application Loaderからサインアウトし、下にアクセスして、パスワードを生成してそのパスワードで再度サインイン

https://appleid.apple.com/account/manage
<img width="255" alt="スクリーンショット 2020-06-11 12.28.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/d8ec2881-df4f-9620-20d1-d1f5ccd643df.png">


# Android

## 「有効な電話番号を入力する必要があります」の対処法

080-9999-9999の場合、+81-80-9999-9999

## 「APKが最適化されていません」の対処法

```
警告:
この APK では、使用されていないコードやリソースがユーザーに送信されます。Android App Bundle を使用すると、アプリのサイズを小さくすることができます。
デバイスの設定に合わせてアプリを最適化しないと、ユーザーのデバイスにダウンロードしてインストールするアプリのサイズが必要以上に大きくなります。
アプリは、サイズが大きくなるほどインストール成功率の低下を招き、ユーザーのデバイスのストレージを消費します。
Android App Bundle を使用してデバイスの設定に合わせて自動的に最適化するか、複数の APK を使って自分で管理します。
```

```expo build:android --type app-bundle``` でビルドし直す。


## 「別のバージョン コードを使用する必要があります」の対処法　

```
バージョン コード 1 の APK または Android App Bundle がすでに存在するため、別のバージョン コードを使用する必要があります。
```

app.jsonに1つ上のversionCodeを指定

```app.json
"android": {
      "versionCode": 2,
      ...
...
```

## スクリーンショットの作成

コマンドは「cmd + s」

iphoneのサイズは
https://qiita.com/tomohisaota/items/f8857d01f328e34fb551

5.5 => iPhone6Plus
6.5 => iPhoneXSMax

## build時の「Build in progress...Request failed with status code 502」

You can monitor the build at の下のURLに飛んだらStatus Finishedになっていてビルドファイルをダウンロードできた。

## 宣伝用画像のダウンロード

意外とすぐ見つからなかったのでリンクを貼っておきます。
「Appleストアからダウンロード」、「Google Playで手に入れよう」のバッジと、本機の画像です。[こんな感じで使えます(宣伝)](https://tamen.jimdofree.com/)

[ios](https://developer.apple.com/app-store/marketing/guidelines/#section-badges)
[android](https://play.google.com/intl/ja/badges/)
Google アカウントを送信アドレスにしてアプリパスワードを活用して VirtualBox CentOS8 サーバからメールを送る

```
# dnf install mailx
```

テストメール送信

```
# mail <email_address>
Subject: test
test
.
```

```
# tail -f /var/log/maillog
```

Connection timeout...

メール転送設定

設定ファイル

```
/etc/postfix/sasl_passwd
[smtp.gmail.com]:587 <googleアカウントのメールアドレス>:16桁のアプリパスワード
```

```
# postmap /etc/postfix/sasl_passwd
```

設定ファイル

```
/etc/postfix/main.cf
relayhost = [smtp.gmail.com]:587
smtp_use_tls = yes
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_tls_security_options = noanonymous
smtp_sasl_mechanism_filter = plain
```

```
# systemctl restart postfix
```

firewalld の設定

```
# firewall-cmd --list-services --permanet
cockpit dhcpv6-client ssh
# firewall-cmd --add-service=smtp --permanent
Success
# firewall-cmd --add-service=smtps --permanent
Success
# firewall-cmd --list-services --permanet
cockpit dhcpv6-client smtp smtps ssh

```

テストメール送信

```
# mail <email_address>
Subject: test
test
.
```

キューの確認

```
# postqueue -p
```

(参考)キューの削除

```
# postsuper -d ALL deferred
```
[備忘録]JavaScritptでRange配列を作る


以下の結果はすべて同じになるので

```js
console.log(
  Array.from({ length: 10 }).map((_, index) => index)
);

console.log(
  Array.from({ length: 10 }, (_, index) => index)
);

console.log(
  [...Array(10).keys()]
);
```

```
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
```

上記のどれかを使って以下のようなRange関数がつくれる。

```js
function range(start, end) {
  return Array.from({ length: end })
    .map((_, index) => index + 1)
    .filter((num) => num >= start && num <= end);
}

console.log(range(2, 8));
```

```
[2, 3, 4, 5, 6, 7, 8]
```
【JavaScript】function構文とアロー関数の違い、省略した書き方について

#【JavaScript】function構文とアロー関数の違い、省略した書き方について

function構文で書いた以下の記事を発展させ、アロー関数について整理します。

【JavaScript】関数、ローカルスコープ、グローバルスコープ、引数、戻り値
https://qiita.com/kuro_96/items/21e670aa10861d997f8a

##アロー関数を使うメリット
次の条件で省略が可能、コードがシンプルになる
　・引数が1つの場合：引数を囲む()を省略できる
　・引数がない場合：()だけ記載する
　・実行内容が1文である場合：{}を省略できる
　・多くの学習サイトでfunction構文からアロー関数への移行が進んでいる（情報が多い）

以上がfunction構文よりもアロー関数を使う理由です。

##function構文の関数の書き方（復習）

###関数を作る
constで関数の容れ物を作り、

```js

    const 関数名 = function(){
        実行内容;
    }
```

作った関数を呼び出すときは

```js

        関数名();
        関数名(引数);
```

とする。
以下は引数を受けとり、表示させる関数hello。

```js

        const hello = function(name){
            console.log(`こんにちは、${name}さん`)
        }
        hello("you");
```

##アロー関数の書き方
###function構文との違い

function構文と比較して説明。

・function()から"function"をとる
・()の後に"=>"を追加する
　矢印（アロー）を実行処理{}に向けて指すと覚えている

```js

    const 関数名 = () => {
        実行内容;
    }
```

先の関数helloの場合

```js

        const hello = (name) => {
            console.log(`こんにちは、${name}さん`)
        }
        hello("you");
```

###省略した記法
・引数が1つの場合、引数を囲む()を省略できる
・実行内容が1文である場合、{}を省略できる

```js

    const 関数名 = 引数 => 実行内容;
```

先の関数helloの場合

```js

        const hello = name => console.log(`こんにちは、${name}さん`);
        hello("you");
```

・引数がない場合は()だけ記載する

```js

    const 関数名 = () => 実行内容;
```

あるいは

```js

    const 関数名 = () => {
        実行内容;
    }
```

決まった文章を表示するgreet関数の場合

```js

    const greet =  () => console.log("こんにちは。個人ゲーム作家のkuroと申します。");
    greet();

```

実行結果

```js

    こんにちは。個人ゲーム作家のkuroと申します。
```

こちらで書いたadd関数の場合
【JavaScript】関数、ローカルスコープ、グローバルスコープ、引数、戻り値
https://qiita.com/kuro_96/items/21e670aa10861d997f8a

```js

    const add = function(a,b){
        function add(a,b){
            return a + b;
        }
        console.log(1,2);
    }
```

アロー関数+省略記法

```js

    const add = (a,b) => a+b;
    console.log(add(1,2));
```
MacでOctaveの環境構築備忘録

どの分野にもBibleと呼ばれる書籍は必ず有ります。それが万民にとって有益な書籍で有るかは議論の分かれる所かもしれません[^bible]。機械学習の世界でもBibleと呼ばれる書籍[^prml]が有ります。厄介なのが演習問題のソースプログラム。何と全てMatLabで実装されています。。。いくらBible解読の為とは言え、時価数100万円もするMatLabを購入する様な財力は筆者には有りません。困り果てていた所、友人からOctaveというOSSがMatLabと粗！？完全互換！？だと教えて貰ったので早速環境構築したところ様々な災難に遭遇した為、備忘録メモとして残しておこうと思います。

# 検証環境
* macOS 10.14.6 Mojave

# Octave(CLI)版のインストール
Homebrewを利用してインストール出来ます。

```bash
brew install octave
```

インストールが完了したら`~/.octaverc`に以下の内容を記載します。

```shell

setenv('GNUTERM', 'qt')
graphics_toolkit("gnuplot")
```

## 謎のエラーでグラフが描画出来ず。。。

通常はこれでセットアップが完了し、正常に動作する筈ですが。。。筆者の環境の場合、グラフ描画時に以下のエラーが表示され強制終了されてしまうトラブルに遭遇しました。

```bash
dyld: lazy symbol binding failed: Symbol not found: ___emutls_get_address
  Referenced from: /usr/local/opt/gcc/lib/gcc/9/libgomp.1.dylib
  Expected in: /usr/lib/libSystem.B.dylib

dyld: Symbol not found: ___emutls_get_address
  Referenced from: /usr/local/opt/gcc/lib/gcc/9/libgomp.1.dylib
  Expected in: /usr/lib/libSystem.B.dylib

fatal: caught signal Abort trap: 6 -- stopping myself...
Abort trap: 6
```

既出のバグ情報を探しましたが、そもそもこの様なエラーの情報は無く、頭を抱えていました。しかし、インストールの行程で以下のエラーが。。。筆者の環境は別の検証でインストールした`gfortran`が既にインストールされていた為、それが原因ではないかとの疑いが。。。

```bash
==> Pouring gcc-9.3.0_1.mojave.bottle.tar.gz
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink bin/gfortran
Target /usr/local/bin/gfortran
already exists. You may want to remove it:
  rm '/usr/local/bin/gfortran'

To force the link and overwrite all conflicting files:
  brew link --overwrite gcc

To list all files that would be deleted:
  brew link --overwrite --dry-run gcc

Possible conflicting files are:
/usr/local/bin/gfortran -> /usr/local/gfortran/bin/gfortran
```

## 綺麗にアンインストールしてやり直し

Octaveのアンインストールは依存関係の有るライブラリーを全てアンインストールする必要が有る為、`brew-rmtree`を有効化します。

```bash
brew tap beeftornado/rmtree
```

Octaveをアンインストールします。

```bash
brew rmtree octave
```

gfortranもアンインストールしました。

```bash
brew cask uninstall gfortran
```

## 再度インストール

```bash
brew install octave
```

今度はインストール中に前述のエラーは出ず、グラフの描画も正常に実行出来ました。gfortranが悪さをしていた様です。

```bash:サンプル
octave:1> x=-2*pi:0.1:2*pi;
octave:2> y=sin(x);
octave:3> plot(x, y);
```

美しいサインカーブが表示されました。セットアップ成功です。:grin:

![sin curve](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/09175bf7-2a89-e6a8-a94c-2f4990231e1e.png)


# Octave GUIもインストール
GUI版もインストールします。Octaveは`octave --force-gui`を実行するとGUIが起動しますが、version 5.2.0のGUIには不具合が有り、なぜか終了出来ません。故に別途GUI版をインストールします。

```bash
brew tap octave-app/octave-app
brew cask install octave-app
```

Octave4.4.0がインストールされました。CLI版とバージョンが揃っておいて欲しいですが、現状はGUIは旧版で凌ぐより他無い様です。。。

# Reference
* [Octave for macOS](https://wiki.octave.org/Octave_for_macOS)
* [Octave.app](http://octave-app.org/)
* [homebrewでのoctaveインストールにハマった](https://qiita.com/U-MA/items/96aace033f075667c978)
* [OctaveをMac OS X Yosemiteへインストール](https://qiita.com/ykoga/items/614c81a9d679b86ca96a)
* [MacBookへのOctaveダウンロード手順と実行](https://qiita.com/KouJu/items/8b5eac18c95f3ab5ad7d)



[^bible]: プログラミング言語CのBibleとして知られるK&Rはその難解さや出版された時代独特のフォントによる読みにくさも手伝って毀誉褒貶の激しいBible書籍の代表格かと思われます。

[^prml]: 機械学習のBibleとして取り上げられる書籍は数多！？有る様に思われますが、ここでは厚焼き卵の様な色の表紙が特徴的なあの本です。
【GitHub】無料でプライベートリポジトリを作成する方法

##はじめに
アメリカ時間2019年1月8日から無料のGitHubユーザーもプライベートリポジトリが作れるようになりました。
この機能は今までは有料版のユーザーのみの機能でしたので朗報だと思います。
無料版のGitHubでもチーム開発において利用できたり、個人開発でも世の中に公開したく無いコードでもGitHub上に保存したりできるようになります。
ただしチーム開発においてはリポジトリごとにCollaborators（共同開発者）は3人までという制限がありますのでご注意ください。

##無料でプライベートリポジトリを作成する
###①[個人ページのTOPページ](https://github.com/)からスタート

###②左上の「New」ボタンをクリック
<img width="1279" alt="スクリーンショット 2020-05-09 8.16.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384180/7cd67929-fa85-872a-d7d9-56fd8c942f40.png">

###③Privateのラジオボタンにチェックを入れるCreate repositoryする
※Repository nameはその名の通りリポジトリの名前なので入力してください。
<img width="1278" alt="スクリーンショット 2020-05-09 8.23.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384180/35ccd546-bd48-d565-48d3-9c1461f02b96.png">
これで完成です！！！！

https://github.com/yukachin0414/Qiita

##無料でパブリックリポジトリからプライベートリポジトリを作成する
###①変更したいリポジトリのcodeページからスタート

###②やや上にあるcodeと同じ階層の一番右のSettingsをクリック
リンクは`https://github.com/ユーザー名/リポジトリ名`です。
<img width="1275" alt="スクリーンショット 2020-05-09 8.52.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384180/9b27b5f3-4d43-09f2-b56d-1b44b24a323c.png">

###③一番下までスクロールしてDanger Zoneの一番上のMake privateをクリック
**Danger Zoneの名前の通り他を選ぶとリポジトリ消して復活できなくなるボタンもあるのでご注意ください。**
<img width="1280" alt="スクリーンショット 2020-05-09 8.54.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384180/059b6972-a3e6-4153-a39c-abf23294929e.png">

###④指定された文字を下の枠にコピペしてI understand〜をクリック
入力する値は個人個人で異なりますのでご自身の画面を見てコピペしてください。
入力する時にスペースなどがあるとI understand〜をクリックできませんので正確にコピペしてください。
<img width="1276" alt="スクリーンショット 2020-05-09 8.59.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384180/0985f4ca-0ec2-2084-b0e1-c12417ec204b.png">
これで完成です！！！！

##プライベートリポジトリかパブリックリポジトリか確認する方法
左上のユーザー名/リポジトリ名の後ろを見てください。
プライベートリポジトリの場合はPrivateの文字があり、パブリックリポジトリの場合はこの文字がありません。
<img width="1277" alt="スクリーンショット 2020-05-09 9.04.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384180/dc5abd00-6fa9-6a36-c5b7-e3a63bc15864.png">

##おわりに
いかがでしたでしょうか。
著作権問題や見られてはいけないコードもあると思いますので公開範囲には気をつけて開発を楽しみましょう。

参考：[GitHub Free users now get unlimited private repositories](https://techcrunch.com/2019/01/07/github-free-users-now-get-unlimited-private-repositories/)
AlexaからCognito User Poolの属性情報を取得する方法

# 背景

AlexaのCognitoによるアカウントリンク後、Cognito(User Pool)が保持する属性情報を取得したかったのです。

[こちらの記事](https://qiita.com/miyatay/items/9755f3ec81961a822edb#%E6%A1%882authorization-code-grant%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%83%AA%E3%83%B3%E3%82%AF%E3%81%A8cognito%E3%82%92%E7%9B%B4%E6%8E%A5%E9%80%A3%E6%90%BA%E3%81%95%E3%81%9B%E3%82%88%E3%81%86)を参考にさせていただいて、「あれ？できない？いやでも、これはIdentity Poolに関する話だから違うよな？User Poolならいけるよな？」というところからスタートです。

# とりあえずマニュアル見る

[これかな？](https://developer.amazon.com/ja-JP/docs/alexa/account-linking/add-account-linking-logic-custom-skill.html#get-token)

> ユーザーがアカウントをリンクすると、ユーザーのアクセストークン（accessToken）がスキルに送信されるすべてのリクエストに含まれるようになります。

アクセストークンは取得できるので、何とかなりそうです。

> accessTokenをすべてのリクエストに含まれるapiAccessTokenと混同しないでください。apiAccessTokenは、デバイスアドレスAPIやプログレッシブ応答APIなどのAlexa Skills Kit APIで使用されます。

ふむふむ、なるほど。了解です。
で、実装例は？

```typescript
const OrderCarIntentHandler = {

    //...

    handle(handlerInput){
        // このインテントではユーザーのタクシー予約プロフィールと支払い情報を
        // 取得するためにアクセストークンが必要です。

        // アクセストークンはContextオブジェクトにあります。ハンドラーに渡される
        // HandlerInputオブジェクトでリクエストに
        // アクセスします。

        var accessToken = handlerInput.requestEnvelope.context.System.user.accessToken;

        // ...
    }
};
```

ちゃうねん。そのトークンの利用方法知りたいねん。

> トークンがリソースサーバーの有効なユーザーを表していることを確認します。

はい。

> トークンが有効な場合、リクエストを正常に処理します。トークンを使い、必要に応じてリソースサーバーからデータにアクセスできます。

はい。

・・・え、これで終わり？
え、このトークンってCognitoのCredentialなの？これでAuthorizedなIAM Roleの権限取れるん？なんか違うような、、、
リソースサーバーって、Cognitoの「ホストされたUI」とかで定義されてるやつだっけ。

# 解答
素直にサポートの方に教えてもらいました。

https://dev.classmethod.jp/articles/alexa-account-link-with-device/

```typescript
// User Poolから情報を取得する
const domain = 'alexa-user-pool';
const url = 'https://' + domain + '.auth.ap-northeast-1.amazoncognito.com/oauth2/userInfo';
const accessToken = h.requestEnvelope.session.user.accessToken;
const options = {
    uri: url,
    method: "GET",
    headers: { Authorization: 'Bearer ' + accessToken },
}
const id = JSON.parse(await rp(options)).profile;
```

あー！こういうこと！
認証周りに詳しい方なら一瞬でたどり着きそうな話でした。そうか、oauth2/userInfoのエンドポイントか、、、

よく調べたら、[LINEとアカウントリンクした場合の実装](https://qiita.com/imajoriri/items/0e975b15b9023cafce24#%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E5%AE%9F%E8%A3%85)に関する記事もありました。

OIDCとかOAuth2.0とか、完全に理解したとか言ってないでちゃんと勉強しないとダメな好例でした。

アカウントリンク設定時のClient Secretに与えるread権限次第で、User Pool内の任意の属性を取得できることも確認できました。

どなたかのお役に立ちましたら幸いです。
オンライン授業・遠隔授業関連のメモやらリンク集やら

（随時更新）

##Zoom
- Zoomを使った遠隔授業について: https://zoom.les.cmc.osaka-u.ac.jp/

##iPad
- iPadで画面収録・録画(動画キャプチャ)する
: https://www.ipodwave.com/ipad/howto/screen_recording.html

##効果音
- チャイム: https://otologic.jp/free/se/school_bell01.html

##動画編集
- 【Mac版】imovieの使い方と編集のテクニックを解説
: https://www.somethingfun.co.jp/video_tips/imovie-howto

##データ削減（音声教材やビデオ教材の作成後）
- HandBreak: https://handbrake.fr/
--Dimensions タブ内で，サイズを 960*720 （比率は 16:9）くらいに
--Audio タブ内で，Bitrate を 64 に
--Filter・Video・Subtitles・Chapters タブ内はいじらない
-https://bbb9780.wordpress.com/2017/01/29/movie-resize-handbrake-windows-10/

#評価
- オンラインで学習を評価するための10のポイント
: https://www.tlsc.osaka-u.ac.jp/project/onlinelecture/tips02.html
【Python/Tkinter】Menuにキーボード・ショートカットを結びつける

## はじめに
TkinterのMenuでは，コマンド付きのメニューボタンを加える際にacceleratorオプションを指定することでいい感じの見た目で表示させることができますが，実際にはこれだけでキーボード・ショートカットを有効にすることができません。メソッドと紐付ける作業が必要となります。そのためのサンプルを示します。

##サンプル

```py
import tkinter as tk
from tkinter import ttk


class Application(tk.Frame):
    def __init__(self,master):
        super().__init__(master)
        self.pack()
        self.master.geometry("300x300")
        self.master.title("Menubar Sample")
        self.create_menubar()

    def create_menubar(self):
        menubar = tk.Menu(self)
        file_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="File", menu=file_menu)
        file_menu.add_command(label="Open", command=self.onOpen, accelerator="Ctrl+O")
        self.master.config(menu=menubar)
        self.bind_all("<Control-o>", self.onOpen)

    def onOpen(self, event=None):
        print("onOpen")


def main():
    root = tk.Tk()
    app = Application(master=root)
    app.mainloop()


if __name__ == "__main__":
    main()
```

self.bind_allでアプリケーションにonOpenを紐付けています。キーボード・ショートカットでonOpenを実行する際はeventが引数として渡されますが，直接メニューボタンをクリックした際には渡されません。そのため，後者に対応すべくeventの初期値をNoneにしています。これが面倒な場合は別途定義しましょう。
簡単に述べると、PHPの実体は

簡単に述べると、PHPの実体は、Webサーバに置かれるソフトウエアの [apache](https://www.scollabo.com/banban/php/apd_03.html#apache)モジュールとして動作するスクリプト言語を実行する環境を指します。HTML文書中に記述されたスクリプトを PHPが実行し、結果を HTMLデータとしてWebブラウザに出力する仕組みがあります。
その意味では、PHPを実行させるための Apacheモジュールを Webサーバに置かなければなりません。幸いなことに、Apacheは、世界中で最も普及しているオープン・ソフトであるため、ほとんどの Webサーバに実装されています。
■ PHPの生い立ち
1994年秋、Rasmus Lerdorf氏（グリーンランド生まれのデンマーク育ち） が自分の履歴書ページの閲覧者を調べるために作っていた Perlスクリプト 「Personal Home Page Tools」 を C言語で書き直し、HTMLフォームを扱える動的な Webアプリケーションのための機能 「Form Interpreter」 に拡張したのが始まりとされ、その頭文字をとって、「PHP/FI」と呼ばれました。
Rasmus Lerdorf氏はこのソフトウエアの開発に誰でも参加できるようにしていたことから、つまりオープン・ソースとしたことで大勢の開発者の支持を得ました。
PHP開発の主体は個人からグループへ変化し、やがて、C、Perl、Java、VisualBasic の新しい仕様まで取り入れるように拡張されました。
その後、技術者にとって非常に取り組みやすい新しい開発言語として発展したことは、現在の PHPの普及をみれば理解できることでしょう。
現在では、PHPの略として「PHP is Hypertext Pre-processer」として呼ばれるようになっています。
なおこのページの執筆時点では、PHP4.3 までがバージョンとしてリリースされている関係で、PHPプログラミングに関しては、PHP4.3 を基本として解説します。
(追記： 2004年3月に PHP5.0がリリースされています。)
PageTop
■ 何故 PHPなのか？
PHPは、Webサーバ上で情報を提供し表現する HTMLに埋め込むタイプのスクリプト言語で、JavaScriptと同じように、プログラムのコンパイル（実行可能なバイナリファイル作成）をする必要のない、テキストベースのインタープリター言語です。
Webアプリケーションを開発する言語は、お馴染みの Perl、Java、Ruby、ASP などが挙げられます。古くからそうした多くの開発言語がありながら、何故今 PHPが注目されているのでしょうか？
CGIプログラムを開発する Perl言語は、多くの Webアプリケーションで利用されてきました。多分これからもその主役の座を担うことでしょう。しかし、Perl は、言語的に難しくソースコードが汚くなりやすい欠点を持っています。
PHPは、Perl と同様にテキストベースで構築できる手軽さがあります。基本的には、HTMLファイルに埋め込む言語であるため、簡単なテキストエディタがあれば、誰でも書くことができます。加えて、CGIのようなサーバ負担も少なく、実行が早い利点も持っています。
以下に、PHPが利用されている理由を列挙しました。
Webアプリケーション開発に特化した言語である。
文法が比較的容易に誰でも習得することができる。
テキストベースで手間がかからず、デバックも簡単に行える。
短期開発に向いている。
CGIと比較すると、実行速度が断然早い。
どのような種類のデータベースとも接続可能である。
こうした特徴を持つ PHPは、Yahooや 楽天などの商用サイトでも採用され、素早い開発が行われています。また、多くの Webサーバでも PHPを実装しつつあることから、より多くのサイトでも PHPの採用が進められています。
PageTop
■ LAMPプラットフォーム
オープン・ソース・ソフトウェアとして普及しているプラットフォームに Linux があります。オープンであるが故に、世界中の技術者がボランティアとして開発され日々成長しています。
何より大きな特徴として、この Linux がオープンであること、つまり無償で誰もが自由に利用でき、自由に改変し再配布することができるということです。
この Linux をベースとして、同じくオープン・ソース・ソフトウェアの Apache、MySQLデータベース、そして　PHPを組み合わせたのを、LAMPプラットフォームと呼んでいます。
Linuxは、標準で Apacheを実装し、Linuxディストリビュータの中には、最初から PHPや MySQLをインストールできるようになっているものさえあります。
現在、私の部屋にある Red Hat Linux には、これらのソフトウェアが実装されて、約１年前から Webアプリケーション開発に勤しんでいます。
PageTop
■ Windowsプラットフォーム
驚くべきことに、Apache、MySQL、PHP は、Windowsへの移植も採用されており、UNIX系プラットフォームでなくても、Windowsのデスクトップ環境でも開発することが可能になりました。
こうしたことから、PHPによる [web](https://www.playermall.com)アプリケーション開発は更に加速し、大手商用サイトで次々と採用され始め、Perlに代わる新しい開発言語として、ますます PHPが重要視され普及しています。
localstackを使用して「Unable to get IAM security credentials from EC2 Instance Metadata Service.」でハマった件

# はじめに
localstackを使用してハマった内容について、備忘録としてまとめました。

# localstackとは
localstackとは、クラウドアプリケーションをオフラインで開発／テストするためのツールで、[公式ページ](https://localstack.cloud/)には、以下のように書かれています。

>(原文)
It spins up a testing environment on your local machine that provides the same functionality and APIs as the real AWS cloud environment.
(google翻訳)
実際のAWSクラウド環境と同じ機能とAPIを提供するローカルマシンのテスト環境を起動します。

# 設定と動作
私は、[dockerイメージ](https://hub.docker.com/r/localstack/localstack/)を利用して、localstack環境を構築しました。
その時のdocker-compose.yamlがこちらです。

```docker-compose.yaml
version: '2.1'
services:
  localstack:
    image: localstack/localstack
    ports:
      - "4566-4599:4566-4599"
      - "8080:8080"
    environment:
      - SERVICES=dynamodb,s3,sqs
```

クラウドアプリケーションは、[AWS SDK for .NET](https://docs.aws.amazon.com/ja_jp/sdk-for-net/index.html)を使用して作成しました。

で、いざ動かしてみると、以下のような例外が発生して上手く動きません。

```Exception:Exception
Unable to get IAM security credentials from EC2 Instance Metadata Service.
```
以前、別の環境でlocalstackを使った事があったのですが、その時は上記の現象は発生しませんでした。

# 解決策
ネットでいろいろ調べていると、[localstackのGIT](https://github.com/localstack/localstack)に[issue](https://github.com/localstack/localstack/issues/1918)上がっていましたので、それらを試してみたのですが、まったく変わらずでした。

その後もいろいろ調べていたのですが、有効な情報も出てこず、途方に暮れていた時に、ふとどこかで「**AWS SDKは認証情報としてawscliの設定情報を参照することがある**」というのを聞いた事を思い出して、credentials/configの設定を見直すと、defaultの設定をしていませんでした。

defaultが設定されてないので情報が取れないのではと思い、試しに以下のように設定して再度アプリケーションを動作させると、見事に動きました！！！！！

```file:credentials
[default]
aws_access_key_id = dummy
aws_secret_access_key = dummy
region=us-east-1
```
```file:config
[default]
region = us-east-1
```
今回は、各KEYにdummyを登録しましたが、値は何でも良いようです。

# まとめ
awscliはちゃんとdefaultを設定しておきましょう。
【JavaScript】関数、ローカルスコープ、グローバルスコープ、引数、戻り値

関数について理解を整理しました。
アロー関数ではなく、function構文で説明しています。

##関数
処理をまとめたもの。
たとえるなら自動販売機、ツクールならコモンイベント。

関数を作る＝処理内容（商品）を登録しておく。
関数を呼ぶ＝ボタンを押して処理（商品）を取り出す。

###関数を作る、実行する

```js

    function 関数名(){
        実行内容;
    }
    関数名();
```


```js

    function hello(){
        console.log("こんにちは");
    }
    hello();//関数helloを実行
```

引数と戻り値を加える場合
　引数……関数に与える値、入力値
　戻り値……関数に与えて戻る値、出力値

```js

    function 関数名(引数){
        実行内容;
        return 戻り値
    }
    関数名(引数);
```

```js

    function hello(name){
        return "hello" + " " + name;
    }
    let greet = hello("taro");
    console.log(greet);

```

実行結果

```js
hello taro
```

引数は,区切りで複数与えることもできる

```js

    function hello(firstName,lastName){
        return "hello" + " " + firstName + " " + lastName;
    }
    let greet = hello("taro","yamada");
    console.log(greet);

```

実行結果

```js
hello taro yamada
```



##ローカルスコープ
関数で定義された変数（var,let）は関数内でしか使用できない。

```js
    function hello(){
        let name = "you";
        console.log(`スコープ内からこんにちは${name}さん`);
    }
    hello();
    console.log(`スコープ外から、こんにちは${name}さん`);

```

実行結果。

```js

    スコープ内からこんにちはyouさん
```

変数nameの値を使用できる

```js

    スコープ外から、こんにちはさん
```

hello関数の外なので変数nameが使用できない


##グローバルスコープ
・関数の外(function{}の外)で変数、定数を定義した場合、関数の外で扱える
・同名の変数、定数が存在する場合はローカル変数が優先される

```js

    let name = "who";
    function hello(){
        let name = "you";
        console.log(`ローカル変数のあなたは${name}さん`);
    }
    hello();
    console.log(`グローバル変数のあなたは${name}さん`);
```

実行結果

```js

    ローカル変数のあなたはyouさん
    グローバル変数のあなたはwhoさん
```

##引数
関数名()の"()"に与える追加情報。

関数を作る時に引数を設定すれば、処理内容と紐づけられる。

```js

    function hello(name){
        console.log(`引数を使って、こんにちは${name}さん`);
    }
```

関数を使うときは()内に値を指定する。

```js

    hello("who");
```

実行結果

```js

    引数を使って、こんにちはwhoさん
```

複数の引数がある場合は","で区切る。

```js

    function hello(lastName,firstName){
        console.log(`引数を使って、こんにちは${lastName} ${firstName}さん`);
    }
    hello("Tailor","Swift");
```

実行結果

```js

    引数を使って、こんにちはTailor Swiftさん
```

##戻り値
returnを使って値を戻す（returnする）

```js

    function add(a,b){
        return a + b;//引数aとbの足し算
    }
    console.log(add(1,2));//戻ることを期待して、引数に1と2を与えて実行
```

実行結果

```js

    3
```

応用：
①処理内容を関数を作る＝呼び出されたときに対応する仕組み。自販機
②関数の外から引数を渡す変数を作る＝呼び出す処理。コインを入れてボタンを押す所作

```js

    function add(a,b){
        return a + b;
    }
    let sum = add(1,2);
    console.log(sum);
```
codeコマンドでVisual Studio Codeを起動と同時にSSHリモート接続する方法

# 結論

コメントをいただいた @kerikun11 の素敵なzshファンクションで解決です！

https://github.com/kerikun11/.dotfiles/blob/ac0ecd7052d6bc724e7819a1ab788ad84068f26c/tools/zsh/sshcode.zsh

以下は経緯です。ご参考まで。

# codeコマンドでリモートディレクトリを開きたい

Visual Studio CodeでSSHリモート開発する機会が増えてきました。

`code`コマンドでVisual Studio Codeを起動して、同時に指定ホストにSSH接続、ディレクトリまで開く方法がきっとある！…と信じつつも上手く見つけられず手間を感じていましたが、やっと発見。

https://github.com/microsoft/vscode-remote-release/issues/190

`--folder-uri`オプションを使い、こんな感じに指定するようです。

```bash
code --folder-uri "vscode-remote://ssh-remote+<hostname>/<path>"
```

普段遣いには冗長なので、こんな感じのスクリプトを作りました。

```bash:/usr/local/bin/sshcode
#!/bin/bash

# 引数(ホスト:ディレクトリ)は必須
location="$1"
if [ "$location" = "" ]; then
  echo "usage: $0 <host:path>"
  exit 1
fi

# ホストとディレクトリに分割(ディレクトリ部がない場合は引数=ホストとみなす)
host=${location%%:*}
dir=${location##*:}
if [ "$host" = "$dir" ]; then
  dir=""
fi

# ディレクトリ部が空または/で始まらない場合はホームディレクトリを取得
home=""
if [ "$dir" = "" -o "${dir:0:1}" != "/" ]; then
  home="$(ssh $host pwd)/"
fi

# vscodeでSSH直接接続
path="$home$dir"
code --folder-uri "vscode-remote://ssh-remote+$host$path"
```

こんな感じでVisual StudioによるSSHリモート開発がとっても楽に！

```bash
sshcode foo # ホストfooのホームディレクトリにリモート接続接続
sshcode bar@foo # barユーザーとしてホストfooのホームディレクトリにリモート接続
sshcode foo:project # ホストfooのホームディレクトリにあるprojectディレクトリにリモート接続
sshcode foo:/app # ホストfooの/appにリモート接続
```

※ `host:port`記法は非対応です(自分が特に困らないので…)。

# ~~Help!~~ zshタブ補完機能

~~引数を`host:path`にしたのは、ついでに`scp`のシェル補完を流用してパスを探しやすくしたかったのですが、私の技能では短時間で作れず断念…~~

~~zshでのいい感じの補完を実装する方法を教えて下さい！~~
【Golang】パッケージのインポート

#【Golang】パッケージのインポート
Golangの基礎学習〜Webアプリケーション作成までの学習を終えたので、復習を兼ねてまとめていく。
基礎〜応用まで。

```
//package
package main


//標準パッケージ（ライブラリ）
//内部（自分のsrc）＝ライブラリ
//それ以外＝パッケージ  特に違いはない
//公式ドキュメントにパッケージ一覧がある https://golang.org/pkg/
//import "fmt"
//import "time"

//独自ライブラリ
//GOPATH/src　以下にライブラリ用フォルダを作成する。
//GOPATHに無いとimportできない


//importしたパッケージは使用しないとエラーになる
//複数の場合()で囲んだほうがいい
//import()
import (
	"fmt"
	"time"

	//読み込む アルファベット順にする。自分のパッケージと、標準と分ける。
	//Aproject
	//    |- Alib - a.go
	//    |    |-under - b.go
	//    |- main.go
	"AProject/Alib"
	"AProject/Alib/under"
)

//パッケージの中身見る方法
//ターミナルで
//go doc fmt println

func main(){
	fmt.Println("パッケージ")
	fmt.Println("Hello world!", time.Now())


	//PublicとPrivate スコープ
	//独自ライブラリの関数使用例
	//外部から呼び出す関数は、先頭大文字にする
    //逆の場合、小文字にする。
	Alib.Function()

	//頭文字が小文字なので呼び出せない
	under.function()
}


/*
mainパッケージの分割

main.goと同じ場所にmain2.goがあるとする。
このmain2.goの関数をmain.goで呼び出す場合、同じパッケージ内なのでライブラリの指定なしで呼び出せそう。
go run main.goで実行する場合、これはエラーになる。
go runコマンドはオプションで指定されたmain.goのみ実行対象として選択し、main2.goの存在を無視する為。

main2.goも含めて実行する場合、
go run main.go main2.goとするか、go run *.goとしなければならない.

mainのgoファイルがあるディレクトリには、main.goのみにする方が良さそう。


その他機能は、パッケージごとにディレクトリを作成して、その中で定義した方が見た目もよくなる。
*/
```
コミュニティドリブンの SaaS のつくりかた

先日、イエメシというテイクアウト対応店舗の地図アプリをほいほいつくるためのフレームワークをオープンソースで公開しました。

[
地元のテイクアウトが利用可能なお店を Google スプレッドシートで管理できる地図アプリをつくりました。](https://blog.geolonia.com/2020/04/29/iemshi.html)

![](https://www.evernote.com/l/ABUkdhH6FDxOHrWSlLBvg-F-TO1C00yc5s8B/image.png)

https://github.com/iemeshi/app

このイエメシは、地域ごとの派生サイトに対してサブドメインを発行して、さらに iemeshi.jp のポータルから各地域のウェブサイトを探すこともできるようになっています。

![](https://www.evernote.com/l/ABW4Z4bsaDxEGaFCUBwHgpCEq6oKXROgPIAB/image.png)

このイエメシの開発には約1週間ちょっとかかったのですが、これを始める当初から SaaS のような感覚で広めることはできないかなと考えていて、以下のような仕様となることを意識していました。

## サーバーレス

開発を始める前の時点で、このイエメシに収益性は期待していなかったので（笑）、飽きたらほっとける仕組みであることは超大事でした。

そのために、バックエンドにデータベースを使うなどの仕組みは嫌だなと思っていて、Google スプレッドシートに店舗データを保存する仕組みにしました。

あと、GitHub Actions などの CI ツールは、単純にフォークしてもらう時にめんどくさいだろうなと思い、Netlify 上にホストしてもらうことを前提としました。

Netlify に依存することでややハードルが上がるだろうなーとは思いましたが、無料でも使えるサービスですしね！

結果的には、フォークして Google スプレッドシートでデータを用意して、アプリの設定を書き換えて、Netlify へのデプロイという一連の手順が、すべてブラウザだけで行えるようになりました。

## イエメシレジストリ

イエメシレジストリというのは勝手に今思いついてなづけたものですが、このイエメシでは、以下のリポジトリに必要事項を記述した JSON のプルリクエストを貰えれば、それをマージした時に、`xxx.iemeshi.jp` というサブドメインが自動的に付与され、冒頭で紹介したイエメシのポータルにも掲載されます。

https://github.com/iemeshi/registry

以下は、そのためのプルリクエストの一例です。

https://github.com/iemeshi/registry/pull/13

イエメシのポータルへの掲載は、シンプルにこのリポジトリの JSON を AJAX で読み込んでいるだけですが、DNS の方は AWS の Route53 を CircleCI で蹴っ飛ばして、サブドメインを登録するということをしています。

以下は、そのための Node のスクリプトです。

https://github.com/iemeshi/registry/blob/master/bin/deploy.js

この部分に関してはコストを負担をしている感じにはなっていますが、ドメインの管理費と Route53 のコストだけなので、タダ同然と言っても問題ない程度のコストではあります。

イエメシでサーバーサイドのコードを書いたのはこれだけです。便利な世の中になりましたよね。

## まとめ

というわけで、イエメシを使って自分の地域のテイクアウトマップを作る際に、それ用のインフラを用意したりとか、特定のコマンドとかは必要なく、立ち上げまでのすべてのプロセスをブラウザだけでも行うことができ、まさに SaaS と呼べるのではないかと思っています。

本体側のアップデートを反映させるためには Git の操作が必要で、そこだけが残念。。。

こういう仕組み、応用できるのではないかと思いまとめてみました。
Rails でクッションページを作る

# なにこれ
[体系的に学ぶ 安全なWebアプリケーションの作り方 第2版](https://www.sbcr.jp/product/4797393163/)という本の p.239 に「コラム：クッションページ」というのがある。Rails でこのクッションページを作ったらどうなるかな、と思って作成することにした。

# コードについて
- 今回のコードは [Github のレポジトリ](https://github.com/seahal/qiita) にもあります
- slim という gem を使っています

# さて、作っていきますか
とりあえず、コントローラーをつくる

```sh
$ rails g controller confirmation_of_external_pages show
```
 ルーティングはこんなかんじ

```ruby
Rails.application.routes.draw do
  resources :confirmation_of_external_pages, only: [:show]
end
```
コントローラーはこんな感じ

```ruby
class ConfirmationOfExternalPagesController < ApplicationController
  def show
    @uri =  Base64.urlsafe_decode64(params[:id])
  end
end
```
ビューはちょっとプロダクション向けでないコードを含む

```slim
h1 クッションページ

hr

p 外部へ移動しますが、よろしいでしょうか。よろしければ上記のリンクをクリックしてください
p =link_to @uri, @uri

hr

p 練習用
ul
  li =link_to "https://google.co.jp/", confirmation_of_external_page_path("aHR0cHM6Ly9nb29nbGUuY28uanAv")
  li =link_to "https://www.yahoo.co.jp/", confirmation_of_external_page_path("aHR0cHM6Ly93d3cueWFob28uY28uanAv")
  li =link_to "https://www.sbcr.jp/product/4797393163/", confirmation_of_external_page_path("aHR0cHM6Ly93d3cuc2Jjci5qcC9wcm9kdWN0LzQ3OTczOTMxNjMv")
```

# できあがったもの
![Screenshot from 2020-05-09 06-22-23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190937/1dc43a47-aee5-e38b-cf40-e88ecadcb052.png)

# テスト
System Test とコントローラー向けのコードは書いたが、あまり自信がないのでココにはのせない。[Github のレポジトリ](https://github.com/seahal/qiita) をみていただければと思う。

# おわりに
クッションページなんてすぐにできるでしょ、と思ったら２時間も経っていた。まぁ、そんなものか。