OmniAICreator/Qiita-1.07M huggingface dataset:
【Rails】パフォーマンス改善にすぐに役立つTips集

## はじめに
Railsにおけるパフォーマンス改善に役立つTipsを集めてみました。
すぐに使えるものから、少し改善に時間がかかるものまで幅広く集めています。

開発中のアプリのパフォーマンス改善のお役に立てれば幸いです。


##【Tips1】 N+1を改善する

何はともあれN+1が発生していたら、それを解消するようにしましょう。
大抵の場合、そこがアプリのパフォーマンスのボトルネックになっているはずです。

```ruby:books_controller.rb
class BooksController < ApplicationController
  def index
    @book = Book.all
  end
end
```

```erb:index.html.erb
<% @book.each do |book|
  <%= book.title %>
  <%= book.user.name %> # ここでN+1が起きている
<% end %>     
```

上のコード例だとbookの関連先のuserを読み込むところでN+1が起きています。

下記のようにコントローラーを書き換えましょう。

```ruby:books_controller.rb
class BooksController < ApplicationController
  def index
    @book = Book.includes(:user)
  end
end
```

`モデル.all`で全てのモデルを取得してきている場所はN+1が起きている可能性が高くなり、大抵allは使わなくなることが多いです。
N+1を検知するためにgemの`bullet`をアプリへ導入するのもおすすめです。

https://github.com/flyerhzm/bullet

また、上の例だと`includes`を使用していますが、`preload`と`eager_load`を使い分けられるようになるといいですね。

[ActiveRecordのjoinsとpreloadとincludesとeager_loadの違い](https://qiita.com/k0kubun/items/80c5a5494f53bb88dc58)






##【Tips2】 countではなくてsizeを使用する

countを使用するとSQLを発行してしまいます。
そのため、モデルの数などを調べたい時は`size`などで代用しましょう。

意外とやってしまいがちなケースですが、`count`を`size`へ置き換えるだけなので、手軽にできます。

**countを使用した場合**

```ruby

user = User.all
user.count
# count関数を用いたSELECT文が発行されてしまう
   (4.6ms)  SELECT COUNT(*) FROM `users`
=> 100
```
**sizeを使用した場合**

```ruby
user = User.all
user.size
# SQLクエリは発行されない
=> 100

```

##【Tips3】exist?の使用を控える
`count`と同じく`exist?`はモデルオブジェクトに使用すると、sqlを発行してしまいます。
存在するかを確認したい場合などは`present?`などで代用しましょう。

***exsit?を使用した場合***

```ruby

user = User.where(deleted: true)
user.exist?
# SQLが発行される
  User Load (5.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`deleted` = TRUE
=> []
```

***present?を使用した場合***

```ruby
user = User.where(deleted: true)
user.present?
# SQLは発行されない
=> []
```

##【Tips4】allで取得した結果をeachで回さない

全ユーザーを`all`で取得してそれをeachで回す・・・のようなパターンです。
バッチ処理とかにありがちなパターンですね。

```ruby
User.all.each do |user|
  # 何かuserのオブジェクトを使用して処理をするコード
end
```

N+1のTipsでも触れましたが、にallが処理に入ってきたときは一度そのコードを疑ってかかりましょう。

上述の実装だとUserの全件をメモリに展開してから、ひとつひとつの処理をeachで行っていくため、メモリ消費が激しくなります。

allのかわりにfind_eachを使いましょう。

```ruby
User.find_each do |user|
  # 何かuserのオブジェクトを使用して処理をするコード
end
```

find_eachはレコードを1000件取得ずつ取得し、その取得したレコードを1件ずつ処理してきてくれます。

1000件取得し終わったらまた、次の1000件を取得してきて・・・の繰り返しとなります。

ちなみにレコード展開数を指定したかったらその姉妹メソッドであるfind_in_batchesを使用しましょう。メソッドの引数で、レコード数を指定できます。

##【Tips5】不必要なActive Recordオブジェクトの生成

上述のN+1問題や、eachパターンほどではないですが、これも気をつけないとやってしまいがちな実装となります。

```ruby
user_names = User.all.map(&:name)
```

上述のmapを使用したやり方は不必要なActive Recordオブジェクトを生成してしまい、パフォーマンスがあまりよくありません。

Active Recordオブジェクトは膨大な数のモジュールやメソッドをラップしているので、生成コストが高く、それだけでメモリを費やしてしまいます。

Active Recordオブジェクトを生成しなくてもよいやり方があるならば、そちらのやり方を考えましょう。

```
user_names = User.pluck(:name)
```

pluckを使用することで、不要なオブジェクト生成を回避できました。

##【Tips6】   キャッシュや非同期処理の導入を検討する

パフォーマンス悪化箇所にはキャッシュを使ったり、処理を非同期にする方法もあります。

**キャッシュを使う**
Redisなどの導入を検討する。マスター系のデータ読み込みなどに検討してみるといいかも。
ただ、導入箇所をよく検討しないとバグの原因になりがちです。

**処理を非同期にする**
gemの`sidekiq`や`delayed job`などで重い処理を非同期にしてしまう。
メール送信処理を非同期にする方法をよく見かけます。

## 終わりに
いかがだったでしょうか。
以上、Railsでコーディングする上で意識するだけで簡単にパフォーマンス改善ができるTipsを紹介しました。

他にもこんなやり方あるよだったり、ここが間違っているよなどありましたらコメント欄でそっとお知らせください笑
わて「なにっ！？韻を踏むだけで保守性があがるやと！？」

> 無職やめ太郎さんの許可はこれから取ります→相互パクリへ

# ある日の会社にて

わて「バイトくん、何してるん？シャボン玉楽しいで？」

バイトくん「何いってるんですか、仕事中ですよ。大概にしてくださいね」

わて「げほげほっ、このシャボン玉液ちょっと美味しい」

バイトくん「・・・」

わて「で、何してるん？」

バイトくん「あー、関数を薄くラッパーして、保守性を高めてるんですよ」

わて「ラッパー？わても好きやで。昔はフロアを沸かしていたもんや。フロアっていうかほんとは風呂なんやけどな」

バイトくん「・・・」

わて「にらまんといてや・・・」

# 薄くラッパーするってなんなん？

バイトくん「例えばここに **Http Request** をするライブラリがあるんですね」

```js

const sugoiHttpLibrary = new SugoiHttpLibrary();
const url = 'https://qiita.com';
const response = sugoiHttpLibrary.request('GET', url);
```

わて「これくらいならわてもなんとなくわかるで。Qiita のサイトにアクセスして Htmlデータをもらってきてるんやろ」

バイトくん「そうです。これで別になんの問題もないんですね」
バイトくん「例えば数ヶ月経って、このライブラリに脆弱性が見つかったりして、使えなくなったりすることもあるじゃないですか」

わて「せやね、、き、、脆弱性が見つかったら大変やもんな！」

バイトくん「・・・そうしたら別のライブラリに変えたりするわけで、こうなるわけです。」

```js

const kashikoiHttpLibrary = new KashikoiHttpLibrary();
const url = 'https://qiita.com';
const response = kashikoiHttpLibrary.getRequest(url);
```

わて「なるほどな、新しいライブラリに変えたらそうなるな。。。ん？呼び出しメソッドが `getRequest` に変わっとるで！」
わて「これ、たくさんの画面があったらどうなるん？全部直さなあかんの？」

バイトくん「そうなんです。それってとても大変じゃないですか」

わて「え、そんなんやってられへんやん。ライブラリ変更手当を会社に請求せなあかんやん。申請めんどいから大変やん」

バイトくん「そんな手当ないですよ。。たくさんの修正が大変なんです。なので薄くラッパーしておくんです」


# どうやってラッパーするん？

バイトくん「こうやるんです」

```js

class HttpLibraryWrapper {
  const sugoiHttpLibrary = new SugoiHttpLibrary();

  function get(url) {
    const response = sugoiHttpLibrary.request('GET', url);
    return response;
  }
}

const httpLibraryWrapper = new HttpLibraryWrapper();
const url = 'https://qiita.com';
const response = httpLibraryWrapper.get(url);
```

わて「なんか記述長くなってもたやん。こんなんでdopeにライム刻めるん？」

バイトくん「記述が長くなるんですけど、こうすると中身のライブラリ変えた時にはこうなるんです」

```js

class HttpLibraryWrapper {
  const kashikoiHttpLibrary = new KashikoiHttpLibrary();

  function get(url) {
    const response = kashikoiHttpLibrary.getRequest(url);
    return response;
  }
}

const httpLibraryWrapper = new HttpLibraryWrapper();
const url = 'https://qiita.com';
const response = httpLibraryWrapper.get(url);
```

わて「なんやて！呼び出し側はまったく変わってへんやん！」

バイトくん「そうです。そうしたらたくさんの画面を直す必要なくなるんですよ」
バイトくん「それにライブラリ側の使い方に癖があったりすると、呼び出し側を一般的なメソッド名にできるメリットもあるんです」

わて「ライブラリによっては変わった使い方するものもあるもんなぁ。それを使いやすくするってこともできるんかあ」
わて「バイトくん、頭ええなぁ、、さすがわてが育てただけあるわぁ」

バイトくん「・・・そうですね、いつも感謝はしてます」


# その後

わて「あー、できたで！たくさん画面あったけど、ラッパーしてたからライブラリの入れ替え簡単やったわ！」

バイトくん「お疲れ様です」

わて「ラッパーするって大切やな。保守性が上がることで社内（ハコ）のバイブスもアガったと思うわ、マイメン」

バイトくん「これからうるさくなるな・・・」

〜おしまい〜


# スペシャルサンクス

@Yametaro さん
記事の書き方パクらせてもらった。
そして自分は何気ない会話でネタを提供していて、
知らず知らずのうちに相互パクリの状況が完成した。

[ワイ「なに！？ライブラリをラップするやと！？」](https://qiita.com/Yametaro/items/111ce26637d6a3c2e763)

なんだこれｗ
[Swift5]コードオンリーのUITabBarController

Main.storyboardは削除した状態が前提です。

まずはUITabBarControllerを継承したクラスを作ります。ここでは"TabController"

```Swift
class TabController: UITabBarController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        var viewControllers = [UIViewController]()
        
        let firstViewController = FirstViewController()
        firstViewController.tabBarItem = UITabBarItem(tabBarSystemItem: .mostRecent, tag: 1)
        viewControllers.append(firstViewController)
        
        let seccondViewController = SeccondViewController()
        seccondViewController.tabBarItem = UITabBarItem(tabBarSystemItem: .mostRecent, tag: 2)
        viewControllers.append(seccondViewController)
        
        let thirdViewController = ThirdViewController()
        thirdViewController.tabBarItem = UITabBarItem(tabBarSystemItem: .mostRecent, tag: 3)
        viewControllers.append(thirdViewController)
        
        self.setViewControllers(viewControllers, animated: false)
        self.selectedIndex = 1
    }
}
```

続いてSceneDelegateでTabControllerを初期画面に設定

```Swift
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let _ = (scene as? UIWindowScene) else { return }
        
        guard let windowScene = (scene as? UIWindowScene) else { return }
        let window = UIWindow(windowScene: windowScene)
        self.window = window
        
        window.rootViewController = TabController()
        window.makeKeyAndVisible()
    }
```

あとはFirstVC, SeccondVC, ThirdVCをお好きなようにカスタマイズしてください。
Vueでtransition-groupの再利用とscoped CSSを組み合わせるにはdeepする必要がある

こんにちは、猫チーズです。

Vue公式ドキュメント「[Enter/Leave とトランジション一覧 - Vue.js](https://jp.vuejs.org/v2/guide/transitions.html#トランジションの再利用)」の「トランジションの再利用」を参考にしながら、transition-groupを再利用するコンポーネントを作っていたら、リスト移動トランジションが適用されなくてハマりました。

海外系の質問サイトを漁ってもそもそも同様の問題にぶつかってる人が見当たらなかったので、transition-groupの再利用とscoped CSSを組み合わせること自体レアケースなんでしょうか。
何時間か試行錯誤した結果、タイトルの通り原因が分かったのでここに記しておきます。

動作環境：Vue 2.6.12

## 問題のコード
問題の部分を簡潔に切り出すと以下のような単一ファイルコンポーネントです。

```Vue
<template>
	<transition-group>
		<slot></slot>
	</transition-group>
</template>

<script>
	// 略
</script>

<style lang='scss' scoped>
	.v-move {
		transition: transform 400ms;
	}
</style>
```

slotの部分には、呼び出し側でv-forを使って要素たちを並べます。
その要素たちの順番が入れ替わった時には、入れ替わりのトランジションが自動で付く想定です。
ところがこのコードだと、どうしてもトランジションされませんでした。

## 解決法を探る
❶ slotの代わりに適当な要素を配置して、動的に順番入れ替えしてみる。
→ **トランジションされた。**単一ファイルコンポーネントだからうまくいかない、という訳ではない。原因はslot周りにある。

❷ 一つのslotに複数要素を読み込ませるのではなくて、要素数分だけslotを動的に用意して、それらをtransition-groupで囲ってみる。
→ **トランジションされない。**templateの段階でtransition-groupの子要素が複数あればいい、という訳ではない。

❸ templateの代わりにrenderオプションを使い、slotの中身を要素ごとにバラし、それぞれの要素を新しいdivで囲ってtransition-groupの子要素として配置する。
→ **トランジションされた。**このコンポーネント内で生成された要素がtransition-groupの子要素なら、トランジションされる？

❹ ふと、CSSをカプセル化するためのカスタム属性（data-v-abcd1234みたいなもの）によってtransition-groupの子要素を選別してしまってるのでは？と思い、cssからscopedを除いてみる。
→ **トランジションされた。**これが原因ぽい。

❺ このコンポーネントに割り当てられたカスタム属性を手動でコピーして、呼び出し元のslotへ読み込む要素たちに手動でカスタム属性を貼り付けてみる。
→ **トランジションされた。**やっぱりScoped CSS用のカスタム属性がtransition-groupの子要素たちにもつけられていないと、トランジションが適用されない。

❻ scopedを取り除く代わりに、トランジション指定用のCSSのセレクタ `.v-move` に/deep/を付ける。
→ **トランジションされた。**カスタム属性がマッチしてようがマッチしてなかろうが、トランジション中にはtransition-groupの子要素に `.v-move` クラスが付けられるらしい。トランジションが適用されてなかったのは、scopedしてるが故にCSSのセレクタ側で暗黙的にカスタム属性　`.v-move[data-v-abcd1234]` によって選別してしまっていたからだった。



## ということで解決法
コンポーネントのCSSをscopedで安全にカプセル化しつつ、問題の箇所だけ限定的にカプセル化を解くと、下のようなコードになった。

```Vue
<template>
	<transition-group class='items'>
		<slot></slot>
	</transition-group>
</template>

<script>
	// 略
</script>

<style lang='scss' scoped>
	.items > /deep/ .v-move {
		transition: transform 400ms;
	}
</style>
```

変更したのは2箇所。
1. transition-groupにクラス名を付ける。
2. `.v-move` に/deep/を付けてカプセル化を解きつつ、完全に解いてしまうと影響範囲が広いので、 `.items >` によってtransition-groupの子要素のみに縛っている。

私が実際に作っているコンポーネントはもう少し複雑なので、影響範囲が最小限となるようにこのようにdeepや子要素縛りなどをしているけど、もっと緩めの環境の人は単にscopedを取るだけでもいいかも。
【WIP】vim資料（dein.vim）

##この記事の対象者（自分）

- 開発をよりスピーディーに効率化したい
→vimを使うぞ！と決めた人

- vimrcで色々設定できるけどどうやらプラグインがあるっつポイぞ！NeoBundleかdein.vimが良さげ！

- どっち選べばいいかわからないor導入方法わからん！←対象者


##結論

dein.vim 使おう！

##理由

早いから！

```
vim --startuptime /tmp/time.log +q
```

参考記事（いつもありがとうございます）
---

[dein.vimを使ってみる
](https://qiita.com/yoza/items/2f8bd33a18225754f346)

[dein.vimによるプラグイン管理のマイベストプラクティス
](https://qiita.com/kawaz/items/ee725f6214f91337b42b)

[NeoBundle から dein.vim に乗り換えたら爆速だった話
](https://qiita.com/delphinus/items/00ff2c0ba972c6e41542)

[Vimを使う - 自動で文法チェックする「ALE」
](https://news.mynavi.jp/itsearch/article/hardware/5012)
Firebase init でいつもつまづくのでメモっとく



Actions On Googleを久しぶりに作ろうとしてググっていたところ、Actions on googleの場合のwebhooksというかAPIの定番はFirebaseホスティングだと聞いたので、苦手なFirebase CLIをまた叩いてみました。

仕事でもApp EngineへのデプロイなどでFirebase CLIを使っているので、環境が混ざらないようにするTipsが必要だったため、忘れないようにメモっておきます。

ActionOnGoogle用のFirebaseプロジェクトは、[こちら](https://note.com/mizutory/n/n9043630c8847)の手順通りに進めて、Firebaseのコンソールでプロジェクトを作ってある状態からスタートです。

firebase cliはすでにインストールしてある状態です。

Macローカルに作業用ディレクトリを作成します。

```
cd ~/workspace
mkdir googleAssistant
cd googleAssistant
```

仕事でも若干Webサイトのデプロイなどで使うのでfirebase cliを使っているので、まずアカウントを変更するためにログオフします。 プロジェクトのエイリアスを止める方法は、[こちら](https://www.hanachiru-blog.com/entry/2018/12/14/182336
)を参照させていただきました。

```
firebase logout
firebase use --clear
firebase use --unalias default
firebase login
```
ブラウザが開くので、個人の方のアカウントでログイン。


```
firebase projects:list
　→Firebaseのコンソールで作ったプロジェクトが、この一覧に出てくる事を確認。

firebase use --add プロジェクトID

```
ではいよいよ、雛形を作成します。

```
firebase init

You're about to initialize a Firebase project in this directory:
  /Users/sitopp
```

あれ？？？
ナンデ？

このまま作ると /Users/sitopp 以下に firebase.jsonなどを生成してしまうため、現在地＝作業用のディレクトリを向いていなければならないのに。。

いろいろ調べていて、PATHが通ってないのかなと思い、こちらの記事を参考に、パスを追加しました。ありがとうございます。
https://qiita.com/ebichan_88/items/e3e30461ad4ddd9368f5

調査方法：

```
npm bin -g
```
→結果が
/Users/sitopp/.nodebrew/node/v10.16.3/bin
(not in PATH env variable)
とのように2行目のメッセージが出てしまってたので、パスが通っていない事がわかりました。


```
export PATH=$PATH:`npm bin -g`
```
と実行してから、

```
npm bin -g
```
→結果は
/Users/sitopp/.nodebrew/node/v10.16.3/bin
となります。今度は(not in PATH env variable)は出てこなかったので良いはず。


再度、初期化を実行

```
firebase init
```
You're about to initialize a Firebase project in this directory:
  /Users/sitopp/workspace/googleAssistant
と出たので、今度は良さそう。
続けて、必要な回答を打ち込んでいきます。

```
=== Project Setup


? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to confirm your choices.
 上下移動してスペースキーで Functions, Hosting にチェックを入れ、エンター。

? Please select an option: Use an existing project
? Select a default Firebase project for this directory: プロジェクトID (プロジェクト名ではなくID)
? What language would you like to use to write Cloud Functions? JavaScript
? Do you want to use ESLint to catch probable bugs and enforce style? No
? Do you want to install dependencies with npm now? Yes


=== Hosting Setup

? What do you want to use as your public directory? public
? Configure as a single-page app (rewrite all urls to /index.html)? No
? Set up automatic builds and deploys with GitHub? Yes

? For which GitHub repository would you like to set up a GitHub workflow? sitopp/リポジトリ名


? Set up the workflow to run a build script before every deploy? No
? GitHub workflow file for PR previews exists. Overwrite? firebase-hosting-pull-request.yml Yes

? Set up automatic deployment to your site's live channel when a PR is merged? Yes
? What is the name of the GitHub branch associated with your site's live channel? main
? The GitHub workflow file for deploying to the live channel already exists. Overwrite? firebase-hosting-merge.yml Yes

✔  Firebase initialization complete!

```

できました。あーよかった。


途中、ディスクが100%になっててFirebase toolのインストールができなかったので不要ファイルも整理しました。とことん相性悪いなぁ。
Xserver SSH接続のサーバーIDで一瞬ハマった

XserverのSSH接続にて一瞬ハマったので備忘録として残します。

# 公式マニュアル
まずは公式マニュアルです。
https://www.xserver.ne.jp/manual/man_server_ssh.php

# Xserver側の設定
XserverのSSH接続は`SSH接続用の公開鍵認証用鍵ペアの生成`もしくは`公開鍵の登録`の2パターンがあります。

今回は`公開鍵の登録`にて行います。

公開鍵の生成に関してはこの辺りをご参考に。
https://qiita.com/shizuma/items/2b2f873a0034839e47ce

特に名前を指定しない場合は、`id_rsa`と`id_rsa.pub`が生成されると思います。

（手順）
1. `id_rsa.pub`をXserverの公開鍵登録・更新のところに貼り付ける
2. SSH設定の状態をONにする

以上でXserver側の設定は完了です。

# ターミナルから接続
あとはターミナルにて下記コマンドを叩くだけ。

```
$ ssh -i 秘密鍵が置いてあるパス（上のやり方だと .ssh/id_rsa） サーバーID@サーバーID.xserver.jp -p 10022
```


```
Could not resolve hostname *****.xserver.jp: nodename nor servname provided, or not known
```

あれっ？

ここを変更して再度

```
サーバー番号@サーバー番号.xserver.jp
```

```
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
```

あれっ？

正しくはこっちでした。

```
サーバーID@サーバー番号.xserver.jp
```

もしこれでもエラーが出る場合は、.sshディレクトリと秘密鍵のパーミッションが変更されてないかもしれません。

その場合は下記コマンドでOK。

```
$ chmod 700 ~/.ssh
```

```
$ chmod 600 ~/.ssh/id_xserver_rsa
```

# おまけ
```
$ ssh -i 公開鍵が置いてあるパス（上のやり方だと .ssh/id_rsa） サーバーID@サーバー番号.xserver.jp -p 10022
```
いちいち上記コマンドをうつのはだるいため、簡素化します。

```sh:.ssh/config
Host xserver
HostName サーバー番号.xserver.jp
  Port 10022
  User サーバーID
  IdentityFile ~/.ssh/id_rsa
  ServerAliveInterval 60
```

これで次から下記コマンドにてSSH接続できるようになりました🎉

```
$ ssh xserver
```
CodeBuildでECRのイメージを環境イメージに指定した時に BUILD_CONTAINER_UNABLE_TO_PULL_IMAGE でつまづいた話



## 結論

[CodeBuild の Amazon ECR サンプル](https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/sample-ecr.html) に忠実に従う

## 概要

CodeBuildを使ってテストを自動化したい
→ 毎回イチからイメージをビルドしてテストを走らせると時間がかかるし、お金も勿体無いよね
→ イメージの中身が変更された時だけECRにあげて、基本的にテストを走らせる時はECRに上がっているイメージを使おう

となりました。

そして、CodeBuild から ECR に push する分にはビルドプロジェクトで作成したポリシーに ECR への権限を付与したら出来たのですが、ECR のイメージをビルドプロジェクトの環境イメージに指定した場合はそれではうまく出来ませんでした。

![BUILD_CONTAINER_UNABLE_TO_PULL_IMAGE.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304114/7b5b0f0f-732f-31c4-5b0a-840175b165cd.png)

のように「BUILD_CONTAINER_UNABLE_TO_PULL_IMAGE」が出てしまい、少し時間を使ってしまったので備忘録。



## 解決策

ECRをビルドプロジェクトの環境イメージに指定する場合は、ECRの画面からCodeBuildのアクセス許可をしてあげる必要がありました。

[CodeBuild の Amazon ECR サンプル](https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/sample-ecr.html) の通りではありますが、

 1. ECRにアクセス
 2. リポジトリを選択
 3. 左側のペインに出てくる「Permission」をクリック
![ECR.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304114/89e06e3b-2a87-479e-f0fd-aaa7c8ec3d19.png)
 4. 「編集」をクリック
 5. 「ポリシーJSONの編集」をクリック
 6. 下記のように入力

```:ポリシーJSONの編集
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CodeBuildAccess",
      "Effect": "Allow",
      "Principal": {
        "Service": "codebuild.amazonaws.com"
      },
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:BatchGetImage",
        "ecr:GetDownloadUrlForLayer"
      ]
    }
  ]
}
```

これできっとできるようになるhazu☆
第三者データーベース

## 一般的に
* ステークホルダー以外の機関が保持しているデータのことと思われます。

## SSL証明書申請
* 申請者、発行元の二者以外の機関が保持しているデータに即して、承認・確認が行われます。
* [グローバルサイン社の場合](https://jp.globalsign.com/introduce/document/)は下記がそれに当たります。
    * [帝国データバンク](http://www.tdb.co.jp/lineup/code/)
    * [DUNSナンバー](https://www.tsr-net.co.jp/service/product/get_a_duns_number/)
    * 職員録: 最新の「職員録」（国立印刷局発行）に記載のある組織・団体
    * オンライン電話帳: 各電話会社が提供している情報を利用して電話番号を確認
* [デジサート社](https://www.digicert.co.jp/repository/CPS1.1/CPSCH5.html)は第三者データベースが何を指すかは明記されていませんが、他と同様と思われます。

## 注意事項
* 第三者データベースはあくまでその機関が保持しているデータのため、対象者が公にしている情報と異なることがあります。
【Swift】case-letによるパターンマッチをループする

# この記事はなに？
Appleのサンプルコードを読んでいる時に見かけない構文を見つけたので、調べました。

````Swift:サンプルコードの一部
for case let foundObject as VNRecognizedObjectObservation in results {
    let bestLabel = foundObject.labels.first!	
    let objectBounds = foundObject.boundingBox
    print(bestLabel.identifier, bestLabel.confidence, objectBounds)	
}
````

気になったのは、1行目です。
`for case let foundObject as VNRecognizedObjectObservation in results`
コレクションに対して、処理を反復していることは理解できましたが、`case let x as T` が謎でした。
ちなみに、このサンプルコードは、`Vision`フレームワークを使った画像認識アプリです。
`results`には、`Vision`による検出結果が並んでいると思われます。

> Swiftを基礎から学ぶには
自著、工学社より発売中の「[まるごと分かるSwiftプログラミング](https://amzn.asia/d/7YPWJwl)」をお勧めします。変数、関数、フロー制御構文、データ構造はもちろん、構造体からクロージャ、エクステンション、プロトコル、クロージャまでを基礎からわかりやすく解説しています。

## マッチした値だけキャストする
単純にしたコードを実行して、動作を確認しました。

### 実行環境
Xcode 12.1
Swift 5.3
macOS 10.15.7


````swift:要素の型が一貫していない配列
let values: [Any] =  [ "1", 2, 3.4]
````


````swift:配列の要素のうち「Int型にキャストできる値」に対してのみ、処理を行う
for case let number as Int in values {
    print(number)
}
// Prints 2
````

### 考察
同じ実行結果を得るだけであれば、他にもいろんなアプローチがありそうです。
ただ、Appleのサンプルコードだけあって、極めてシンプルな記述で実装されているのではないかと思います。
Javascriptで同じクラスを持つ複数の入力値を取得する

`Javascript`を使って、任意のHTML要素にアクセスする方法です。

##同じクラスのinput(入力値）を取得
例えば、このようなコンタクトフォームがあるとします。

```html:index.html
<h2>お問い合わせフォーム</h2>
<form class="contactForm" action="" method="post">
<table>
 <tr>
  <th><label>お名前</label></th>
  <td><input class="item" type="text" name="name" value="タンジロウ"></td>
 </tr>
 <tr>
  <th><label>メールアドレス</label></th>
  <td><input class="item" type="email" name="email" value="kisatsu@gmail.com"></td>
 </tr>
 <tr>
  <th><label>電話番号</label></th>
  <td><input class="item" type="tel" name="tel" value="090-1234-5678"></td>
 </tr>
 <tr>
  <th><label>お問い合わせ内容</label></th>
  <td><textarea class="item" name="message">お問い合わせ内容テキスト</textarea></td>
 </tr>
 <tr>
  <td><input type="submit" id="submitBtn" name="btn_confirm" value="送信"></td>
 </tr>
 </form>
</table>
```
全ての入力値に適切な値が入っているかを確認する為に、同じクラス`item`をキーに要素を取得します。

##getElementsByClassName

`getElementsByClassName`は同じクラス名を検索して、返り値に配列風の`HTMLCollection`を返します。elementに`s`がついていることに注意してください。

```javascript:main.js
const ItemList = document.getElementsByClassName("item"); 

for(let i = 0; i < ItemList.length; i++) {
    console.log(ItemList.item(i).value);
}
```

### コンソールの出力結果
コンソールの出力結果です。`Item`にアクセスすることで好きな値をチェックすることができます。
<img width="400" alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.amazonaws.com/0/482880/91516d53-c044-c57f-5809-498a616f7400.png">
クラス名を複数指定すると、`and`指定となり両方のクラスを持つ要素を取得できます。

```javascript
document.getElementsByClassName("item email")
```

## HTMLCollectionを配列に変換
配列に変換することで、配列のメソッドが使えるようにすることもできます。用途によって、使い分けましょう。

```javascript:main.js
const ItemArray = Array.prototype.slice.call(ItemList);

ItemArray.forEach(function(array) {
    console.log(array);
});
```

### コンソールの出力結果
<img width="600" alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.amazonaws.com/0/482880/d3e67c4f-73b7-d740-ab2e-03d6bb5d3be2.png">
Markdownにペーストした画像サイズを簡単に変更できるようにする

# やりたいこと

**Markdownで資料作成をするとき、Pasteした画像サイズを簡単に修正できるようにしたい！**
そんなときの設定方法です

（4Kディスプレイで画像キャプチャーするとムダに画像が大きくなるとかあるよね？）

使用イメージ👇
![ajust_image_size.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485510/ee53a002-8247-f583-043c-d95f0f958721.gif)


# 使用ツール

- [Visual Studio Code](https://code.visualstudio.com/)
- [Paste Image \- Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=mushan.vscode-paste-image)：クリップボード上の画像をMarkdownファイルなどに直接貼り付けられる拡張機能

<!-- - [Markdown Preview Enhanced \- Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced)：Markdown用拡張機能。プレビュー表示に使用 -->

# 設定方法

**Markdownのimgタグはサイズ指定に対応していません**
そのため画像サイズを変更する場合は、下記のようにHTMLで指定する必要があります

Markdown
``![***代替テキスト***](***画像URL***)``
↓
HTML
``<img src="***画像URL***" width="***サイズ***">``


そこで**[Paste Image](https://marketplace.visualstudio.com/items?itemName=mushan.vscode-paste-image)のInsert Patternを下記のようにHTML記法に変更します**

- ユーザー設定 ⇒ 設定 ⇒ 拡張機能 ⇒ Paste Image Configuration ⇒ Paste Image: Insert Pattern

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485510/302ed25c-5fee-437c-2749-58fe5864a4d6.png)

``` json:setting.json抜粋
"pasteImage.insertPattern": "<img src='${imageFileName}' width='100%'>"
```

デフォルトで``width=100%``が付与されるので、必要に応じて調整します
Preview画面での確認以外に、VSCodeのウィンドウ右下に表示されるサイズを確認し調整してもよいと思います

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485510/ba72c3db-12bb-9072-2a3c-6bb633d0b5c9.png" width="1000%">

これでMarkdownへの画像ペーストが捗ります♪
複数オブジェクトからなる配列を、要素内のプロパティ値を基準にソート

## Array.prototype.sort()について
Javascript初心者です。
paizaで練習問題を特訓していましたが、以下のような配列をsortするのに
一苦労したので備忘録として残しておきます。
間違いや拙い点などあるかと存じますが、何卒ご了承ください。

~~~javascript
// 配列の中のオブジェクトの中のプロパティ値を基準に並び変えたい
// これを
[
  { name: 'cat', power: 50 },
  { name: 'dog', power: 100 },
  { name: 'mosquito', power: 1 },
  { name: 'lion', power: 2000 },
]

// こうしたい
[
  { name: 'lion', power: 2000 },
  { name: 'dog', power: 100 },
  { name: 'cat', power: 50 },
  { name: 'mosquito', power: 1 },
]
~~~

 
## その前にsort()の基本形
上記の例とは別で、配列の中にそのまま何らかの値が列挙されている場合の使い方。

<strong>辞書順に並べる<strong>

~~~javascript
const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]
~~~

名前の辞書順に並べたいだけならば、このように引数無しのsort()でOK。
だけど、ほとんどの場合は数値を基準に並べたい...

<strong>数値の昇順・降順で並べる<strong>

~~~javascript:昇順
const months = [3, 1, 2, 12];

months.sort((a,b) => {
    return a - b;
});

console.log(months);
// expected output: Array [1,2,3,12]
~~~

~~~javascript:降順
const months = [3, 1, 2, 12];

months.sort((a,b) => {
    return b - a;
});

console.log(months);
// expected output: Array [12,3,2,1]
~~~
sortの引数に比較関数を渡します。
a,bにはそれぞれ配列の中の数値が入っています。

returnが正の値 : 第１引数を第２引数の後ろに並べ変える 
returnが負の値 : 第1引数を第2引数の前に並べ替える
returnが０ : 並べ変えを行わない

（となっていますが、正直よくわからないので機械的に覚えちゃってます...）
>引用
>https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/sort



## 本題
~~~ javascript
let creatures = [
  { name: 'cat', power: 50 },
  { name: 'dog', power: 100 },
  { name: 'mosquito', power: 1 },
  { name: 'lion', power: 2000 },
]

// a,bにはオブジェクトが入っているので、そのプロパティ名を指定して比較すれば並べ替え可能。
creatures.sort((a,b) => {
    return b.power - a.power; 
}); 

console.log(creatures);
// expected output:
//[
//  { name: 'lion', power: 2000 },
//  { name: 'dog', power: 100 },
//  { name: 'cat', power: 50 },
//  { name: 'mosquito', power: 1 },
//]
~~~

## ひとこと
配列ループ系の関数は全部知っておいた方が良さそうです...
(forEach,map,filter ...etc)
【Ruby on Rails】URLのidをカラム名に変更

# はじめに
Railsでは、routes.rbでresourcesメソッドを使用すると、通常:idパラメータがデフォルトで使われますが、
場合によっては表示を変更したい場合もあるかと思います。
今回はidをnameカラムに変更する方法を記載します。

# 目標
![スクリーンショット 2020-10-25 16.32.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700999/23bf404c-3202-d3c9-d55b-29adba113c57.png)
↓
![スクリーンショット 2020-10-25 16.31.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700999/c4d02151-65cd-3d7f-f186-509488fdf5f0.png)

# 開発環境
ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina

# 前提
※　▶◯◯　を選択すると、説明等が出てきますので、
　　よくわからない場合の参考にしていただければと思います。

[【Ruby on Rails】gemのdeviseを使用し、名前とパスワードのみでログインする方法](https://qiita.com/japwork/items/275110b810965fbdf72f)
こちらをベースにURLを変更していきます。



# 準備
前提記事では、URLがmypageになっているため、
今回はあえてidをつけたURLにしていきます。
※変更点のみ記述します。

```rb:config/routes.rb
get 'mypage', to: 'homes#mypage'
↓
get 'mypage/:id', to: 'homes#mypage', as: 'mypage'
```

```rb:app/controllers/users/registrations_controller.rb
def after_sign_up_path_for(resource)
  mypage_path
end
↓
def after_sign_up_path_for(resource)
  mypage_path(@user)
end
```

```rb:app/controllers/users/sessions_controller.rb
def after_sign_in_path_for(resource)
  mypage_path
end
↓
def after_sign_in_path_for(resource)
  mypage_path(@user)
end
```
```rb:app/controllers/homes_controller.rb
def mypage
end
↓
def mypage
  @user = User.find(params[:id])
end
```
これでidがついたURLができました。

# idをnameカラムに変更
## 同一の名前のURLをなくす
URLをカラムにするためには、同一のnameをなくす必要がありまあす。
そこでvalidationをかけます。

### モデルのバリデーション
```rb:app/models/user.rb
validates :name, uniqueness: true
```

### DBのバリデーション

```:ターミナル
$ rails g migration add_index_users_name
```
```rb:db/migrate/xxxxxxxxxxxxx_add_index_users_name.rb
class AddIndexUsersName < ActiveRecord::Migration
  def change
    add_index :users, :name, unique: true
  end
end
```
```:ターミナル
$ rails db:migrate
```

## 実際にidをnameに変更
findをfind_byにするのが肝です。

```rb:config/routes.rb
get 'mypage/:id', to: 'homes#mypage', as: 'mypage'
↓
get 'mypage/:name', to: 'homes#mypage', as: 'mypage'
```
```rb:app/controllers/homes_controller.rb
def mypage
  @user = User.find(params[:id])
end
↓
def mypage
  @user = User.find_by(name: params[:id])
end
```
加えてリンク先もnameで指定するために
to_paramメソッドを使用します、

```rb:app/models/user.rb
validates :name, uniqueness: true

# ↓追加
def to_param
  name
end
```
これで目標と同じになるはずです。

# resourcesを使用する場合
resourcesに下記のように追記すればOKです。
```resources :users, param: :name```



これでリンク先もnameで表示されるはずです。


# まとめ
このように数字ではなく、文字列にすることで、
どのページにいるかがわかりやすく、利便性が高まります。
また、SNSのようなサービスで数字のIDを使用してしまうと、
今何人の登録者がいるかわかってしまうため、あまり推奨できる方法ではないです。
その時はこの方法を試してみてください。

またtwitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら　https://twitter.com/japwork
[初心者]レビューで指摘されがちなポイントを共有

就活の選考の際に初めてガッツリレビューしてもらいました。(約2ヶ月間)
その時に指摘されたことについて、自分なりにまとめておこうと思います。
初心者が注意されるようなポイントがいくつもあると思いますので、他の方の参考になればと思います。


## プログラマが常に意識すべきこと


- 新人プログラマが知るべきプログラミングの原則６選！

https://qiita.com/ryotanatsume/items/018cae5c5be8faba367a

- より汎用的になるように
- より簡潔になるように
- ネストが2重3重になっている箇所があったらネストを浅くできないか、リファクタリングできないか検討する。
- 同じようなコードが複数回でてきたらまとめられないか検討する。
- メソッド名からはずれた処理内容をコードしていないか確認する。


## 命名について

- ディレクトリ名はローマ字での命名は避けましょう。プログラミングでも同様です。
- クラス名はそのクラスの内容・責務を適切に表しているべきです。例えば、DataGetterと聞いただけではどんな内容のクラスかわかりません。もっと具体的かつ端的に命名しましょう。
- 基本的にメソッド名は動詞で始めましょう。
- 基本的には「クラス名＋メソッド名」と並べた際に英語として適切であれば良い命名です。
- _HASHのようなsuffixは付けないようにしましょう。
- dataやinfoなどのように抽象的な命名は避けましょう。


##レビューする人への思いやり

- ガード節を使いましょう。

ネストが深くならないように、また、無駄なコードを実行しないような工夫です。
https://qiita.com/kouyan/items/7b8b456b626447a1e24e


- 基本的に一時変数のメリットはあまりありません。削除しましょう。

説明のために一時変数にしたい気持ちもわかりますが、大抵の場合はメソッド抽出をし、適切なメソッド名をつけた方が、再利用もでき、テストもかけるので推奨されます。


##リファクタリングをするに当たっていくつかのポイント
- ネストはなるべく浅く
    - if文のネストが減らせないか検討
    - ガード節なども使用

- 1メソッド1処理
- 内容を的確に表現した命名
- 同じような処理は共通化
- 意味のある単位でメソッドとして抽出できないか検討
- eachなどではなくmapを採用できないか検討



##その他細かい注意箇所

- Ifで否定の場合はunless文を使用するのがいいでしょう。
- 後置ifで簡潔になる場合は積極的に使いましょう。

ただ、闇雲に使うと返って可読性が低下することもあるので注意してください。
https://qiita.com/jnchito/items/4e47559a4c821474233a

- メソッドは依存しないように独立させる
参考サイトとして表示するurlを形式ごと取得する

初書：2020/10/25

# 前書き
QiitaのMarkdownを書く際に、参考サイトとしてurlをコピーして貼り付け・・・をするわけだが、
それをJavascriptで形式ごと（`[タイトル](url)`）取得するコードを作成する。
元々これを書いてくれていたページがあって、LGTMしていたはずなのだが、知らぬ間に消えていたので改めて自分でコードを作ることにした。

# 前提
mac版safari:14.0
mac版chrome:86.0
の二つで動作確認。それ以外(特にIE)は知らない

# タイトル・urlを取得する
これは調べたらいくらでも出てくる。

```js
    var str = "["+document.title+"]("+location.href+")";
    alert(str);
```
これで、例えばこのページなら`[参考サイトとして表示するurlを形式ごと取得する - Qiita](https://qiita.com/yuu_1st/items/11c2ca89276962b2e488)`が表示されるはず

一応これで完成なのだが、せっかくなのでもう少し便利にしたい。

# 取得したものをクリップボードにコピーする

調べてみると、以下のサイトに出会った。
[[JavaScript]クリップボードを使ったコピーとペースト - Qiita](https://qiita.com/butakoma/items/642c0ec4b77f6bb5ebcf)

`ClipboardEvent.clipboardData`と`Async Clipboard API`があったのだが、後者の方が簡単に記述できるので、今回はこちらを使用する。
対応状況をみると、IE以外は対応しているみたい？ [Clipboard API - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API#Browser_compatibility)

ということで、コードを記述してみる

```js
if(navigator.clipboard){
    navigator.clipboard.writeText("["+document.title+"]("+location.href+")")
        .then(()=>alert("コピーしました"))
        .catch((e)=>console.error("コピーできませんでした"));
}else{
    alert("コピーできませんでした。");
}
```
一応alertでコピーできたかのエラーを吐くようにした。
writeTextは非同期処理なので、thenとcatchを使用している。仕様がわからない人は`javascript promise`で検索

・・・せっかくなのでもっと便利にしよう。

# ブックマークに追加する

ブックマークに追加すれば、ボタン一つでクリップボードにコピーすることが出来る。ctrl+cは一切使わない。
一応上記を独自minifyしたコードを下に置いておく。

```js
if(navigator.clipboard)navigator.clipboard.writeText("["+document.title+"]("+location.href+")").then(()=>alert("コピーしました")).catch(()=>console.error("コピーできませんでした"));else alert("コピーできませんでした。");
```
これをコピーして、先頭に`javascript:`を追加してブックマークすれば、完成。
（ブックマークへの追加の仕方の説明は要らないよね。。。？）

# 終わりに
上のコードをChromeのアドレスバーに入れると、「アクティブウィンドウがありません」というエラーを吐くので、とりあえず試してみようって感じで入れる場合は注意。

括弧の順番いつも迷うので、こういうのを保存しておくと便利かも。
GCP Professional Cloud Architect 合格体験記

2020年10月後半にGCPの**Professional Cloud Architect**を取得したので、合格までの勉強方法をまとめます。ご参考になれば幸いです。

※ちなみに私はAWS SAPを保持していたので、勉強期間は2週間ぐらい

# 教材
+ **GCPのドキュメント**
プロダクトのコンセプト、ベストプラクティス、アーキテクチャ、選定方法などに関するものはある程度目を通しておく。それぞれのプロダクトの特徴がわかったら、ケーススタディを参考にどんなプロダクトを利用すれば要件を達成できるかなどを考えてドキュメントの深堀りをする。

+ **Whizlabs**
やっておいて損はない。いい感じに出題範囲がカバーされています。ただし、単純に解いているだけなら意味はない。解説読んでドキュメント読むってサイクルを回し続ければ問題ないです（ちなみに私は全部の問題５周して定着を図りました）。

+ **CloudOnAir（YouTube）**
Googleが出している動画。スタートしたばかりのときはこれを見て全体像を掴みましょう。私はネットワーキングとKubernetes Engineぐらいしか見てません。ぶっちゃけ見なくてもいい笑。

+ **GCP模擬問題** 
GCPの認定ページから何回でも挑戦できるので、適当に実力を確認してください。これは100点取るまでやったほうがいいです。


以下はGCP PCA認定のページ、ケーススタディはくまなくチェックしよう
https://cloud.google.com/certification/cloud-architect?hl=ja

ちなみにCouseraは少しやったのですが、長くてめんどくさくなって途中でやめました。
ちょっと情報古くなっていたので、正直やらなくていいと思います。

# 勉強方法

>1．GCPドキュメントのコンセプトや始めの紹介ページで各プロダクトの概要を掴む
2．GCP模擬問題を100点になるまでやる（間違ったところは必ずドキュメントを読む）
3．Whizlabsを適当な問題選んでやる
4．間違ったところは基本ドキュメント読む
5．3～4を繰り返す

上記をやりながら、GCPコンソール触ったりチュートリアルやったり、YouTubeでGCP関連の動画見たりするとなお効果的。やっぱGCPに触れるのが一番の勉強！！

# 注意点

+ GCPの問題っていうよりアーキテクトとしての問題が多い
+ Kubernetesに関する理解はある程度あったほうがいい
+ GCPのドキュメントは読みにくいので思ったより学習が進まない
+ GUIよりCLIが大好きなGCP文化（AWSに比べるとGUIでできることが少ない印象）

AWSに触りなれている人はGCP触ったら、いろいろ煩わしいと感じるかも。少なくとも私はそうでした。

ちなみにGCPドキュメントはまじで読みにくいです。試しにGCPドキュメントで、左ペインにある目次を適当に押してみてください。たまに紹介ページだったり、アーキテクチャの検索ページに飛ばされます。

とまあ愚痴はいろいろあれど、ベストプラクティスとかは読み応えがあり、とても勉強になります。

--------------------------------------



以上、参考になれば幸いです。

**Thanks.**
ACID特性の理解

#【ACID特性の理解】

業務内でもトランザクション処理に携わっています。
AWSの学習の際にもトランザクション処理を考慮して、サービスを選択する必要がありました。

ACID特性についての理解が乏しかったため学習しなおしました。

##ACID特性

ACID特性は、DBMSでのトランザクション処理に必須とされている。

##Atomicity　（原子性）

トランザクション処理結果は、「すべて実行される」か「全く実行されない」のどちらかで終了。
中途半端な実行を許さない。許容しない。

##Consistency　（一貫性）

データベースの内容は、矛盾がない状態であること。
トランザクション処理結果に矛盾が生じてはいけない。

##Isolation　（隔離性）

複数トランザクションを同時に実行した場合、実行した処理結果の順番が一致すること。
排他処理をしっかりして相互に影響を及ぼさないように。

##Durability　（耐久性）

正常に終了したトランザクション処理の更新結果は、もし障害が発生してもデータベースから消失しないこと。
その場合の何らかの復旧手段が保証されている必要がある。
JavaScript　組み込みオブジェクト　まとめ

よく使いそうな標準データ型を扱うオブジェクトをまとめます。他の、構文などは今回はまとめません。


##文字列操作　Stringオブジェクト

| メソッド       |       概要 |
|:-----------------|:------------------|
| slice(A,B)| 文字列からA+1 ~ B文字目を抽出 |
| split(str,[lim])| strの文字で文字列を分割し、その結果を配列として取得、limは最大分割数|
| toLowerCase()| 小文字に変換|
| toUpperCase()| 大文字に変換|
| concat(str)| 文字列の後方にstrを連結|
| trim()| 文字列の前後から空白を削除|
| length| 文字列の長さを取得|


##数値を操作する　Numberオブジェクト
無限大やNumberで表せる最大値などのプロパティもある。今回はメソッドのみまとめる。

| メソッド      |       概要 |
|:-----------------|:------------------|
| toFixed(dec)| 小数点第dec位になるように四捨五入 |
| toPrecision(dec)| 指定桁数になるように変換（足りない場合は０で補足） |
| parseFloat(str)| 文字列を小数点数に変換  |
| parseInt(str)| 文字列を整数に変換 |


##基本的な数学演算の実行　Mathオブジェクト

| メソッド      |       概要 |
|:-----------------|:------------------|
| abs(num)| 絶対値 |
| max(A,B,...), min| A,B,..の中での最大値（最小値）|
| random()| 0~1未満の乱数 |
| PI| π  |
| 三角関数（num)| 三角関数系 |

##配列操作　Arrayオブジェクト

| メソッド      |       概要 |
|:-----------------|:------------------|
| length| 配列のサイズ |
| toString()| [要素,要素,..]の形式で文字列に変換 |
| entries(),key(),value()| 全てのキー/要素のそれぞれを取得 |
| concat(ary)| 指定配列を現在の配列に連結 |
| slice(A,B)| 配列ないのA〜B番目の要素の抜き出し |
| pop()| 配列末尾の要素を取得し、削除 |
| push(A,B,...)| 配列末尾に要素を追加 |
| shift()| 配列先頭の要素そ取得し、削除 |
| unshift(A,B,...)| 配列先頭に指定要素を追加 |
| reverse()| 逆順に並び替え（反転） |
| sort()|要素を昇順に並び替え |


##日付・時刻　Dateオブジェクト
Dateオブジェクトは必ずnew　でコンストラクターを経由する必要がある。
Dataオブジェクトの値を変更するには、setXxxxメソッドにすれば良い。

| メソッド      |       概要 |
|:-----------------|:------------------|
| getFullYear()| 年（４桁） |
| getMonth()| 月（0〜１１）  |
| getDate()| 日（１〜３１）  |
| getDay()| 曜日（０：日曜〜６：土曜） |
| getHours()| 時（0〜２３）  |
| getMinutes()| 分（0〜５９）  |
| getSeconds()| 秒（0〜５９）  |
日付などの加算・減算については値を超えたとしても先月に戻るなど自動でよしなにしてくれる


##よく使う機能　Globalオブジェクト

| メソッド      |       概要 |
|:-----------------|:------------------|
| isFinite(num)| 有限値かどうか  |
| isNan(num)| 数値でないかどうか（Not a Number）  |
| Number(val),String(val)| 数値形、文字列形に変換 |
| parseFloat(str),parseInt(str)| 文字列を不動小数点・整数値に変換  |
AWS CDK コマンドチートシート

## インストール

```
npm install -g aws-cdk
```

Linuxの場合は、`sudo`が必要です。


## プロジェクトの作成

```
mkdir my-first-cdk
cdk init app --language typescript
```

## モジュールの追加

たとえばec2のモジュールを追加するには、

```
npm install @aws-cdk/aws-ec2
```

or

```
yarn add @aws-cdk/aws-ec2
```

こんなかんじ。

## bootstrap

CDKを実行するために必要なAWS内の環境を初期化。

```
AWS_PROFILE=your_profile cdk boostrap
```

## ビルド

```
npm run build
```

## deploy

```
AWS_PROFILE=your_profile cdk deploy
```

## 変更差分の確認

```
AWS_PROFILE=your_profile cdk diff
```

## 変更適用

```
AWS_PROFILE=your_profile cdk deploy
```
3つのGB（ギガ）

#【3つのGB（ギガ）】

家族がiPhoneを買い換えるにあたり、3つの違いについて聞かれたので勉強しました。

##コンピュータの性能をあらわすGB

RAM。揮発性。

俗にいうメモリ。
コンピュータの性能をあらわす。
作業の領域をあらわす。

「机の広さ」として、例えられることが多い。
→広い方が出来ることが多い。

##ストレージの容量をあらわすGB

ROM。不揮発性。

書き込みは不可、読み出しのみ可能なメモリ。
内蔵されているストレージ。データを保存するためのもの。

「本棚」として、例えられることが多い。

##携帯電話などの通信をあらわすGB

比較的快適な通信が可能な量。
限度いっぱいに近づくと快適に通れなくなる。

「通信の道路の広さ」として、例えられることも。
快適に通信が可能な量であると理解しておく。

（大手3大キャリアのモバイル通信道路は広いが、格安SIMの通信道路は狭い？）

##コンピュータの単位について

まず、コンピュータの扱う最初の単位は、ビット（bit）である。
このビットを8つで8ビットとして、ひとまとめにした単位をバイト（Byte）である。
コンピュータでは主にこの単位が用いられている。

※「nビット = 2のn乗」 あらわす数の範囲。
例）1ビット = 2通り。2ビット = 4通り。3ビット = 8通り。
→ 8ビット = 1バイト = 256通りとなる。

###・大きい数値をあらわす補助単位

キロ（k）　10の3乗（基本単位×1,000倍）
メガ（M）　10の6乗（基本単位×1,000,000倍）
<strong>ギガ（G）　10の9乗（基本単位×1,000,000,000倍）</strong>
テラ（T）　10の12乗（基本単位×1,000,000,000,000倍）

###・小さい数値をあらわす補助単位

ミリ（m）　10の-3乗（基本単位×1/1,000倍）
ﾏｲｸﾛ（μ）　10の-6乗（基本単位×1/1,000,000倍）
ナノ（n）　10の-9乗（基本単位×1/1,000,000,000倍）
ピコ（p）　10の-12乗（基本単位×1/1,000,000,000,000倍）
俺的RxSwiftまとめ③(Observableとは何か? )

この記事は、[俺的RxSwiftまとめ①](https://qiita.com/_Masa_asaM_/items/5b15094e047633070b92),[俺的RxSwiftまとめ②](https://qiita.com/_Masa_asaM_/items/4c75b2be7e4074efec45)の続きです。

#Observableとは何か?
`observable`,`observable sequence`,`sequence`,`stream`これらは全部同じ意味を持つ言葉で、**イベントの流れ**である。(RxSwiftでは、`sequence`ということが使われることが多い)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595260/78b9e2d2-dda2-7b91-03cd-2f570870921b.png)
([引用](http://slides.com/robwormald/everything-is-a-stream))

***Everything is a sequence***なのだ。

ここでいうイベントとは、数値や自身で定義したクラスのインスタンス、タップジェスチャーなどが含まれる。

このイベントは、以下の`Enum`で定義されている。

```swift:Event.swift
public enum Event<Element> {
    case next(Element)
    case error(Error)
    case completed
}
```

それぞれの`case`の場合どうなるか、`Observable(sequence)` 下記を表すマーブルダイアグラムとともに見ると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595260/cba274d6-319e-2902-494c-adc3ce7d3cf7.png)
`next`の場合は、`Observable`は次のイベントを放出する。また、`error/completed`が呼ばれるまで、イベントを放出し続ける。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595260/6cf9a7a7-7d97-9333-4c68-2bae493063fb.png)
`error`の場合は`Error`を放出し、`observable`はイベントの放出をストップする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595260/446f3094-8624-2ad3-22d8-e6b52cc89c62.png)
`completed`の場合は、`observable`が停止し、イベントを放出をストップする。

##どうやってObservableを用いて処理をするか?
`Observable`から放出されるイベントを使用するためには、`subscribe`する必要がある。(`Observable`は`Subscribe`されるまで、イベントを放出したり、`operator`での処理を行わない)
この際、イベントタイプごとに、`handler`を追加することができる。
また、`next`だったら`Element`,`error`だったらエラーインスタンスを`handler`に渡すことができる。

### 例
下図のマーブルダイアグラムに示されたObservableについて考える

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595260/446f3094-8624-2ad3-22d8-e6b52cc89c62.png)

```swift:Example.swift
let one = "1"
let two = "2"
let three = "3"

let observable = Observable.of(one, two, three)
observable.subscribe { event in
  print(event)
}
```

```swift:出力
next(1)
next(2)
next(3)
completed
```

`subscribe`すると、イベントが順次扱えるようになる。
それを`print`すると、出力のように`next`が3回流れ、最後に`observable`の停止を意味する`completed`が流れてくる。
脳死でアップデートは危険！Vue3.0の破壊的変更点を要チェック！！

# はじめに
Vue3.0がリリースされましたが、Vue2系からアップデートしましたか？
実は破壊的な変更点があり、思考停止でアップデートすると危険です。
今回は破壊的変更点の中で特に影響が大きそうな部分を抽出して解説します！！

動画でも解説してるので、動画が好きな方はそちらを確認してみてください！！
[【YouTube動画】 Vue3.0の破壊的変更点](https://youtu.be/yN2WSZjsYdY)
[![Vue3.0の破壊的変更点](https://img.youtube.com/vi/yN2WSZjsYdY/0.jpg)](https://www.youtube.com/watch?v=yN2WSZjsYdY)

# Global API
実際のコードの変更をみていきましょう！
以前は以下のように使っていた部分が

```js
import Vue from 'vue'
import App from './App.vue'

Vue.use(/* ... */)
Vue.mixin(/* ... */)
Vue.component(/* ... */)
Vue.directive(/* ... */)

new Vue({
  render: h => h(App)
}).$mount('#app')
```

こうなります！

```js
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

app.use(/* ... */)
app.mixin(/* ... */)
app.component(/* ... */)
app.directive(/* ... */)

app.mount(App, '#app')
```

createAppでインスタンスを作成した後に、Vueの設定を追加していきます。
Vue.xxxxと書いていた部分は修正しないといけませんね。

# Global API Tree Shaking
Tree Shakingは使われないコードを除去する仕組みです。
webpackではサポートされてますね。

以前のバージョンでは使わないメソッドもバンドルされていましたが、新しいバージョンでは明示的に書かないとバンドルされないようになりました。
これのおかげで、ファイルサイズがより小さくなります！

影響を受けるのは以下のAPIなので、使ってる方は修正が必要です。

```plaintext
Vue.nextTick
Vue.observable
Vue.version
Vue.compile
Vue.set
Vue.delete
```

修正するときはimportで使うAPIを指定します。

```js
// Before
import Vue from 'vue'

Vue.nextTick(() => {
  // something DOM-related
})

// After
import { nextTick } from 'vue'

nextTick(() => {
  // something DOM-related
})
```

# v-model
v-modelの書き方も変わりました。
例えば、以下のように書いていた場合

```js
<Comp :value='pageTitle' @input='pageTitle=$event'/>
```

このように変更する必要があります。

```js
<Comp :modelValue='pageTitle' @update:modelValue='pageTitle=$event'/>
```

# Functional Component
Functional Componentを使っていた方は書き方が簡単になりました。
以下のようにhをインポートして使います。

```js
import { h } from 'vue'
```

# まとめ
いかがでしたか？
間違ってる部分やもっと解説して欲しい部分があれば、コメントいただけると嬉しいです！

また、[twitter](https://twitter.com/yassun_youtuber)や[youtube](https://www.youtube.com/channel/UCajrdoGzHzDogrNrLYYmGsg/featured?view_as=public)でのコメントもお待ちしています！
【JavaScript】jQueryを使わずにスムーススクロール

他人の記事を引用しています。
今回は自分用の備忘録です。

```js:main.js
const smoothScrollTrigger = document.querySelectorAll('a[href^="#"]');
  for (let i = 0; i < smoothScrollTrigger.length; i++){
    smoothScrollTrigger[i].addEventListener('click', (e) => {
      e.preventDefault();
      let href = smoothScrollTrigger[i].getAttribute('href');
       let targetElement = document.getElementById(href.replace('#', ''));
      const rect = targetElement.getBoundingClientRect().top;
      const offset = window.pageYOffset;
      const gap = 60;
      const target = rect + offset - gap;
      window.scrollTo({
        top: target,
        behavior: 'smooth',
      });
    });
  }
```
AWS CDKでNAT GatewayにEIPを割り当てる方法

2020年10月時点ではきれいにやる方法を公式が提供していないので、EIPを取得して作成したNAT Gatewayの既存のEIPを削除して付け直すみたいな無理やり的な方法でできる。しかたないね。

```typescript
export class VpcStack extends cdk.Stack {
    private vpc: ec2.Vpc;
  
    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
      super(scope, id, props);

      const allocationIds: string[] = [];
      const eips: string[] = [];

      const numberOfAz = 2;
  
      this.vpc = new ec2.Vpc(this, 'MyVpc', {
        cidr: '172.16.0.0/16',
        maxAzs: numberOfAz,
        subnetConfiguration: [
          {
            name: 'ingress',
            subnetType: ec2.SubnetType.PUBLIC,
            cidrMask: 24,
          },
          {
            name: 'application_1',
            subnetType: ec2.SubnetType.PRIVATE,
            cidrMask: 24,
          },
          {
            name: 'application_2',
            subnetType: ec2.SubnetType.PRIVATE,
            cidrMask: 24,
            reserved: true,
          },
          {
            name: 'database',
            subnetType: ec2.SubnetType.ISOLATED,
            cidrMask: 24,
          },
        ],
      });

      // Create as many EIP as there are AZ/Subnets and store their allocIds & refs.
      for (let i = 0; i < numberOfAz; i++) {
          var eip = new ec2.CfnEIP(this, `VPCPublicSubnet${i+1}NATGatewayEIP${i}`, {
              domain: 'vpc',
              tags: [
                  {
                      key: 'Name',
                      value: `MyApp/VPC/PublicSubnet${i+1}`,
                  },
              ]
          })
          allocationIds.push(eip.attrAllocationId)

          // Do whatever you need with your EIPs here, ie. store their ref for later use
          eips.push(eip.ref)

          // Add a dependency on the VPC to encure allocation happens before the VPC is created
          this.vpc.node.addDependency(eip)
      }

      this.vpc.publicSubnets.forEach((subnet, index) => {
          // Find the NAT Gateway
          var natGateway = subnet.node.children.find(child => child.node.id == 'NATGateway') as ec2.CfnNatGateway
          // Delete the default EIP created by CDK
          subnet.node.tryRemoveChild('EIP')
          // Override the allocationId on the NATGateway
          natGateway.allocationId = allocationIds[index]
      })
    }
  
    getVpc(): ec2.Vpc {
      return this.vpc;
    }
  }
```

## refs

https://github.com/aws/aws-cdk/issues/4705
stashしたものが行方不明になった時やったこと

# 事の起こり
編集途中のものを一旦 `stash` した。それから `rebase` したりブランチを削除したりして最後にstashしたものを戻そう（`stash pop`）しようとら、stashしたものがない。`stash list` に何も出てこない。
`stash` した時のブランチを削除したから？

# 対応
`git fsck` で追跡不能なリビジョンを表示する。

```
$ git fsck
Checking object directories: 100% (256/256), done.
Checking objects: 100% (3778/3778), done.
dangling commit d8c140de7dbe0f0695790e94631f9f4c041ede54
dangling tag bb4efddf60954be66b6cfd7235d14bf2635264c2
dangling tag 6bf9af0329e00ab9661781147ca34e7b39070975
```

"dangling 何とか" というのが追跡不能なリビジョンらしい。
これらのリビジョンのアーカイブを作る

$ git archive --format=zip d8c140d -o rev_d8c140d.zip

$ git archive --format=zip bb4efdd -o rev_bb4efdd.zip

$ git archive --format=zip 6bf9af0 -o rev_6bf9af0.zip

で、そのアーカイブを展開してワークツリーと比較して（WinMergeを使った）差分から d8c140d が行方不明になっていたstashしたものらしいと判断した。
もっといい方法があるのかもしれないが、自分の頭ではこれが限界。


# 参考ページ
[誤って削除した git stash を戻す | deadwood](https://www.d-wood.com/blog/2015/02/12_7407.html)
[Gitを使いこなすための20のコマンド | OSDN Magazine](https://mag.osdn.jp/09/03/16/0831212#git4-fsck)
[Git - git-fsck Documentation](https://git-scm.com/docs/git-fsck)
【Vue.js】動的なデータの反映まとめ

Vue.jsの十八番である`リアクティブなデータの反映`の種類をまとめてみました


| ディレクティブ等  |  紐付け先 | どうしたいか  | 実例  |
|:-:|:-:|:-:|:-:|
| v-model  | data  | 入力内容や選択内容を動的にしたい  | input(type="text", v-model="todo.message") |
|  v-bind | data  | htmlタグの属性を動的にしたい  |  img(:src="todo.image) |
| {{ }}  | data  | 表示させる文字を動的にしたい  |  p{{ todo.message }} |
| {{ }}  | computed  | dataの値を変化させたものを動的にしたい  | p{{ remaining }}  |



#v-model

```vuejs:

<template>
  <input type="text" v-model="todo.title">
</template>

<script>
let vm = new Vue({
  el: '#app',

  data: {
    todo: {
      { title: '' },
    }
  },
})
</script>

```


#v-bind

```vuejs:

<template>
  <img :src="todo.image">
</template>

<script>
let vm = new Vue({
  el: '#app',

  data: {
    newItem: '',
    todo: {
      { title: 'task1', image: "" },
    }
  },
})
</script>

```


#{{ }}

###dataオプションと連動

```vuejs:

<template>
  <span>{{ todos[0].title }}</span>
</template>

<script>
let vm = new Vue({
  el: '#app',

  data: {
    todo: {
      { title: 'task1', isDone: false },
    }
  },
})
</script>

```

###computedオプションと連動


```vuejs:

<template>
  <span>{{ remaining }}</span>
</template>

<script>
let vm = new Vue({
  el: '#app',

  data: {
    todos: [
      { title: 'task1', isDone: true },
      { title: 'task2', isDone: false },
      { title: 'task3', isDone: false },
    ]
  },
  computed: {
    remaining: function(){
      let remainItems = this.todos.filter(function(todo){
        return !todo.isDone;
      });
      return remainItems.length;
    }
  }
})
</script>

```
HackMD のドキュメントをPDFでいい感じに出力する

## HackMDで作成したドキュメントをPDFとして出力したい
ここ数年、研究メモとかいろんなドキュメントを[HackMD](https://hackmd.io/)にて作成して管理しています。
最近は、「notionがとても良いぞ！」との話も聞くのですが、個人的にはhackMDすごく便利に使っております。

先日、HackMDで作成した資料をPDFファイルで共有するということがありました。
なんだかんだ、PDFで出力したことがなかったため、**HackMDの見やすさを崩さないままにPDF出力するため**に少し試行錯誤したので、まとめておきます。

今回は、hackMDで作成したこのドキュメントをPDF保存していきます。閲覧できるので、見比べながら記事を読んでください。
[HackMD をPDFに出力したい。](https://hackmd.io/@kohei108/SkRKqFzdw)

## 手法１ 「ChromeでPDF保存する」
まずは、ブラウザでPDF保存してみます。

オプションから、「印刷」を選択します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222325/f483976a-172a-745d-0697-d1dde2bb38e0.png" width=60%>
<p></p>

<img src="" width=60%>
<p></p>

プレビューが出てくるので、「PDFに保存」を選択し、保存をクリック。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222325/3c9479bc-d7de-331b-7980-960769514c1a.png" width=70%>
<p></p>

出力されたPDFがこちら。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222325/d0450462-c017-ad79-b7d7-4654100ae649.png" width=80%>
<p></p>

- リンクが文字に格納されていない
- 引用の表示が見づらくなった
- コードブロックが消えた
- 動画のプレビューが消えた
- ページごとに勝手にタイトルと日付が記載された

などの問題が発生し、個人的にはこのPDF出力方法だと見づらい印象です。


## 手法２ 「AtomでPDF保存する」
Markdownをプレビューしながら書ける、Atomでもツールをインストールすることで、PDF保存できるようです。

まず、HackMDからMarkdown形式でローカルにダウンロードした、ドキュメントをAtomで開きます。

[AtomでmarkdownをPDFで保存する。](https://miguse.hatenablog.com/entry/2015/09/11/000642)
この記事にしたがって、Atomに「markdown to PDF」をインストールし、「Packages」から「Markdown to PDF」を選択し「Convert」をクリックすると、PDFが保存されます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222325/4cadd5e2-f631-f36e-d95d-dc6b90a5cc68.png" width=80%>
<p></p>

出力されたPDFがこちら。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222325/b5ef6956-bbdd-23fe-0791-de14aceff3c2.png" width=80%>
<p></p>

ほとんど問題ないですが、以下の問題が発生しています。

- 表が表示されない
- 動画がプレビューされない

## 【採用！】手法３「TyporaでPDF保存する」
[Typora](https://typora.io/)という使いやすい無料のMarkdowエディタがあり、こちらのデフォルトの機能でPDF保存するとフォーマットが崩れず、綺麗に保存できることがわかりました。

まず、HackMDからMarkdown形式でローカルにダウンロードした、ドキュメントをtyporaで開きます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222325/1d1a038c-a0f8-c2ae-de57-d5e39dc49ea0.png" width=80%>
<p></p>

- 動画が画像プレビューされない

という問題以外は、すべて解決しました。
正直なところ、PDFファイル上で動画の画像がプレビューされなくても、問題ないかなーと思います。
動画の画像をスクショなどして別にアップロードすれば、画像プレビューっぽく扱えるかなあと思います。

「もっといい方法あるよ！」って方は教えて下さい！
Flutter+FirebaseAuthでtwitterログイン。（初心者向け、2020/10/25)

#Flutterの記事はすぐに陳腐化して使えなくなる。
twitterログインについてはすでに日本語記事は二つあります。

https://qiita.com/0maru/items/a46f5e5b1a9644bb58af
https://www.typea.info/blog/index.php/2020/05/04/flutter-firebase-auth-twitter-signin/

でもどっちも上手くいきませんでしたので、修正法を記録しておきます。
（最も、この記事もすぐ使えなくなるかもしれませんが・・笑）

#修正
セットアップ方法、使い勝手共に、後者のこっちの記事の方が良いので、こちらをベースに話を進めます。
https://www.typea.info/blog/index.php/2020/05/04/flutter-firebase-auth-twitter-signin/
（前者記事も同様の修正で使えるようになります。）

##①セットアップ追加
Firebaseのtwitterログインを有効にしたら、生成されるcallback URLをtwitterアプリに設定します。
![スクリーンショット 2020-10-25 15.03.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762871/cf578c83-df63-2640-8ce3-8a21a896f7eb.png)
![スクリーンショット 2020-10-25 15.07.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762871/f00ac56b-5189-7959-d355-6c6dc3dc477d.png)
![スクリーンショット 2020-10-25 15.10.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762871/dd09e9a2-8c9a-b8f0-4617-32bfac21bc3c.png)
![スクリーンショット 2020-10-25 15.11.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762871/c40355a5-ecc0-490a-4cc6-aaeecbd4e671.png)

##②getCredentialメソッドの更新
twitter_sign_in.dartの中の、

```
final result = TwitterAuthProvider.getCredential(
      authToken: tokenCredentialsResponse.credentials.token,
      authTokenSecret: tokenCredentialsResponse.credentials.tokenSecret,
    );
```

ですが、TwitterAuthProviderのメソッド名が更新されていて使えません。
今はcredentialです。パラメータ名も変わってます。以下の通りに更新してください。

```
final result = TwitterAuthProvider.credential(
      accessToken: tokenCredentialsResponse.credentials.token,
      secret: tokenCredentialsResponse.credentials.tokenSecret,
    );
```

以上です。
もしかしたら、対応したけど忘れてしまってることもあるかも・・・笑

しかし、firebaseの公式パッケージ・・変数名とかメソッド名とか変わりすぎですね・・
Flutterがまだ歴史が浅いからということなのか・・・？？