OmniAICreator/Qiita-1.07M huggingface dataset:
BootstrapのCardにtransitionをかける方法

#はじめに
Vue.jsの便利機能の一つのtransition。今回はそちらを使ってBootstrapのカードを並べるタイプの表示に対してtransitionをかけていきたいと思います。

#具体的なシチュエーション
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/861182/f8bc77b3-3471-c412-7251-6cc59016c042.png)

#ソースコード
```song.vue
<div class="container">
	<transition-group class="row"> <!--ここをdivから変える-->
 		<div class="card border-info col-lg-4 col-sm-6" v-for="item in items" :key="item.Artist+item.Title">
			 <div class="card-body">
				<h2 class="card-title">{{ item.Title }}</h2>
 				<ul class="list-group list-group-flush">
					<li class="list-group-item">アーティスト名：{{ item.Artist }}</li>
					<li class="list-group-item">ボーカル： {{ item.Vocal.join('、') }}</li>
					<li class="list-group-item">作詞：{{ item.Word.join('、') }}</li>
					<li class="list-group-item">作曲：{{ item.Composer.join('、') }}</li>
					<li class="list-group-item">編曲：{{ item.Arranger.join('、') }}</li>
					<li class="list-group-item">作品：{{ item.TieUp[0] }}</li>
					<li class="list-group-item">ブランド：{{ item.Brand[0] }}</li>
					<li class="list-group-item">ジャンル： {{ item.Genre.join('、') }}</li>
				</ul>
 			</div>
		</div>
	</transition-group> <!--ここをdivから変える-->
 </div>
```

```song.css
.v-enter-active, .v-leave-active {
  transition: opacity .5s;
} /*遷移に0.5秒かける*/

.v-enter, .v-leave-to{
  opacity: 0;
} /*現れる時の最初と消える時の最後のopacityを0に指定*/
```

#簡単な解説
ぼくが最初にハマってしまったのは既存のdivタグをそのままにしてtransition-groupタグをいれようとしてしまったところです。エラーこそは出ませんがカード自体が表示されなくなります。classがrowのところを指定してあげるのが一番いい感じなのかなと個人的に思います。あとtransition-group使うときはkeyを必ず設定してください。ちゃんと表示されません。

次にcssについてです。本当はここで指定した4つ以外にも.v-enter-toと.v-leaveを指定しないといけないのですがどちらもopacityが1なのでここでは省略できます。ちなみにそれぞれのCSSクラスの意味をまとめると次のような感じです。

* v-enter ： 表示する時の最初の状態
* v-enter-active ： 表示するときの遷移の設定
* v-enter-to : 表示する時の最後の状態
* v-leave : 消すときの最初の状態
* v-leave-active : 消すときの遷移の設定
* v-leave-to : 消すときの最後の状態

また今回はnameを指定せずにデフォルトのvを使いましたが、できればnameは指定した方がいいと思います。transition-groupタグでnameを指定して、その時に指定したnameをcssのvと入れ替えてください。

#参考文献
* [Vue.js の transition-group でリストのアニメーションに挑戦](https://nujawak.online/blog/247/)
* [公式ドキュメント：Enter/Leave とトランジション一覧](https://jp.vuejs.org/v2/guide/transitions.html)
Airレジ

・Airレジって？
Airレジ(エアレジ)は、株式会社リクルートライフスタイルが提供する0円でカンタンに使えるPOSレジアプリです。手持ちのiPadやiPhone、インターネット環境さえあればすぐに始めることができます。
                    そんな手軽さが魅力のAirレジですが、2019年12月の時点では登録店舗数が469,000アカウントを突破しており、小売店や飲食店、サービス業まで業種・規模を問わず、国内で一番選ばれているPOSレジアプリとして多くの店舗に支持されています。 

・Airレジの特徴

1,キャッシュレス決済への対応もスムーズ
 AirレジとAirペイを一緒に使えば、専用のカードリーダー1台で、クレジットカード決済や交通系電子マネーなど、さまざまな決済手段に対応することができます。また、Airレジで会計した情報はそのまま決済端末に反映されるので、 金額の再入力の手間がなく、スムーズに会計が行えます。

2,シンプル、使いやすい機能
 誰でもカンタンに使える操作性で会計業務をミスなくスピーディにできます。軽減税率にも対応しているので、複数税率でも迷うこともありません。打ち間違いや計算ミスがなくなり、レジ締めの時間も短縮することができます。

3,売上集計・分析もおまかせ
 Airレジで会計するだけで、売上などの数字が自動的に集計されます。もう、手書きで日報やレポートを作成する必要はありません。 売上データは、いつでもどこでも確認することができます。

4,店舗経営に役立つサービスとの連携が可能
 他社が提供するいろいろなサービスと連携することができます。クラウド会計ソフトと連携すれば、Airレジの日々の売上データを自動で連携することができ、帳簿入力の手間が大幅に削減できます。また、会計ソフト以外にもさまざまなサービスと連携することができるため、会計にまつわる業務が効率化できます。 

5,基本レジ機能は0円、月額費用もかかりません
 商品登録や会計などの基本レジ機能、管理・分析、サポート全般はすべて無料。月額費用も無料です。導入にかかる費用を抑えることができます。

・感想
　とても便利だと思いました。バイトで初めてレジ打ちをする人にも優しいし、カンタンに導入できるため今後様々な店で利用されるとと思います。

参考サイト：https://airregi.jp/
図表作成に役立つステンシル、クリップアート、アイコン集

　アーキテクチャダイアグラムを作成する際に役立つアイコンセットのリンクをまとめています。クラウドベンダー各社によって、作図への利用が許可されているリソースを集めています。正確な使用許可範囲と禁止事項（図形の切り抜き・回転・反転等）は各社の規定を確認するようにしてください

### Azure アーキテクチャ アイコン

　SVG 形式で画像データがまとめられています。各種サービスのカテゴリごとに（Compute, Databases, Storage 等）幅広い種類のアイコンが用意されています

- [Azure アーキテクチャ アイコン](https://docs.microsoft.com/azure/architecture/icons/)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/295e3c55-85eb-116f-abf1-60253bc3fbcb.png" width="600px" />

### AWS アーキテクチャアイコン

　PowerPoint (.pptx 形式) で画像データがまとめられています。Example ページも多く用意されているため、作図にあたって大変参考になります

- [AWS アーキテクチャアイコン](https://aws.amazon.com/jp/architecture/icons/)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/4edb7a7b-c378-45a1-9969-fb241b5bf4c1.png" width="600px" />

### GCP アーキテクチャ図用のソリューション アイコン

　PowerPoint (.pptx 形式) で画像データがまとめられています。User Cards，Product Card というように、要素がわかりやすく整理されています

- [Google Cloud Platform アーキテクチャ図用のソリューション アイコン](https://cloud.google.com/icons/)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/13d8abf1-ca1f-6d5c-7e94-546916cf56ff.png" width="600px" />

<!--

- [Oracle Cloud Infrastructure Graphics for Topologies and Diagrams](https://docs.cloud.oracle.com/ja-jp/iaas/Content/General/Reference/graphicsfordiagrams.htm)
- [Editable architecture diagram resources](https://www.ibm.com/cloud/architecture/architectures/edit)
- [Cisco Network Topology Icons](https://www.cisco.com/c/en/us/about/brand-center/network-topology-icons.html)

-->
Basic認証がある環境でBearerトークンを使用する(Sample: nginx+PHP Laravel)

これは[SOUSEI Technology アドベントカレンダー](https://qiita.com/advent-calendar/2020/st)3日目の記事です。
記事の内容は会社の業務とは一切関係ありません。

## 前置き

セキュリティ的に良いとは言えないですが、まだ開発中で非公開だし、クローラやボットの巡回で画面が表示されたりするのを避けられれば良いやくらいのお手軽な手法として、今でもBasic認証は度々使われることがあると思います。
そんな他のアクセス制御かかかった環境にAPIを追加するようなケースでのお話なので、開発用の環境を想定しています。
結果的にRFCを無視しますので、所謂production(実運用している)環境でやるようなことではありませんよー、と前置きさせていただきます。

**nginxのBasic認証の設定については、他に良い記事がたくさんありますので省略しています。**

## ざっくりまとめ

結論から言うと、ミドルウェア(nginx)の設定を変えるのが難しい(できない？)ので、Bearerトークンを送るHTTP headerを変える。アプリケーションで、そのheaderからトークンを取り出してあげる。です。

実験した環境
webサーバ: nginx
アプリケーション: php-fpm7.3/7.4
フレームワーク: Laravel6/7/8

## 順番に解説

### HTTP header

Basic認証のRFC 
https://tools.ietf.org/html/rfc2617#section-2

```
# Basic
Authorization: Basic xxxxx
```

BearerトークンのRFC
https://tools.ietf.org/html/rfc6750#section-2.1

```
# Bearer
Authorization: Bearer xxxxx
```

ということで、どちらも通常はHTTP headerは`Authorization`を使うことになっています。
このままではどちらかしか使えませんので、片方に場所を譲ってもらいます。

どちらのheaderを変えるか？
-> Bearerトークンのheaderを変えます。headerの取り扱いの制御が可能なアプリケーションで解決しましょう。(※)

例えば以下のように、Basic認証は標準のまま、Bearerトークンはカスタマイズしたheaderで送信するようにしてみます。
RFCを無視することになりますが、**非公開の、自前のバックエンドに、自前で用意したクライアントから**リクエストさせる分には特に問題にはならないでしょう。

```
# Bearer
Authorization: Basic xxxxx
Auth-Token: Bearer xxxxx
```

※ いろいろ調べてみた+知人のインフラエンジニアさんにも聞いてみたのですが、nginxでBasic認証を扱うモジュールではAuthorization header以外で待ち受けるような設定がなさそうでした。情報お持ちの方は是非ご教示ください。

### アプリケーション

サンプルとしてPHP Laravel(ver.6/7/8で確認)を使用しますが、HTTP headerの取り扱いに関しては他のプラットフォームでも大きくはかわらないでしょう。

まず、headerを変更せずに扱う場合どうしているのかを確認してみます。
Laravelでは通常リクエストを`Illuminate\Http\Request`（あるいはその派生）で扱いますが、このクラスはBearerトークンを取り出すためのメソッドが用意されています。

```php
// リクエストオブジェクトにアクセスできれば何でも良いです

Auth::viaRequest('bearer', function ($request) {
    $bearer = $request->bearerToken();
    /** ここで何某かのトークン検証処理 */
});
```

メソッドは以下のように、規定のheaderからトークン部分を取り出してくるだけのシンプルな実装になっています。

```php
public function bearerToken()
{
    $header = $this->header('Authorization', '');

    if (Str::startsWith($header, 'Bearer ')) {
        return Str::substr($header, 7);
    }
}
```

さて、これでやるべきことが見えました。
上記の動作を、変更したheaderが対象になるように自前で用意してあげれば良いだけです。

```php
// リクエストオブジェクトにアクセスできれば何でも良いです
// 例外処理は省略しています

Auth::viaRequest('bearer', function ($request) {
    $bearer = null;
    $header = $this->header('Auth-Token', '');

    if (Str::startsWith($header, 'Bearer ')) {
        $bearer = Str::substr($header, 7);
    }
    /** ここで何某かのトークン検証処理 */
});
```
Rubyの計算

#はじめに

Qiitaに記事を初投稿してから3日目になります。

昨日の段階からAWSに関するアウトプット投稿をするぞ〜！と意気込んでおりましたが、自力で解けず、つまづいた問題と出逢ってしまったので、先にその投稿から行って、解き放たれたいと思います。

#問題


Q.任意の3つの数値の合計を出力するメソッドを作りましょう。ただし、同じ数が含まれている場合は合計にカウントされません。

#解答

```ruby:
def long_sum(ary)
 uniq_nums = []
 ary.each do |num|
  count = 0
  ary.each do |i|
   if num == i
    count += 1
   end
   if count < 2
    uniq_nums << num
   end
  end

 sum = 0
 uniq_nums.each do |unique_num|
  sum += unique_num
 end

 puts sum

end
```

#解説

```ruby:
 uniq_nums = []
 ary.each do |num|
  count = 0
  ary.each do |i|
   if num == i
    count += 1
   end
   if count < 2
    uniq_nums << num
   end
  end
```

↑重複しない値のみを取り出す処理

```ruby:
 sum = 0
 uniq_nums.each do |unique_num|
  sum += unique_num
 end
```

↑重複しない値のみになった配列内の合計を求める処理

この2つの処理の塊が合わさって計算処理が実現していました。

例としてlong_sum([１, 2, １])でメソッドを呼び出した場合を考えてみると、、

```ruby:
ary.each do |num|
```
解答の上から3行目のこの部分で最初にnum=1となります。その後,

```ruby:
ary.each do |i|
   if num == i
    count += 1
   end
```

解答の上から5行目の部分でi=1,2,1となり、それぞれに対してnum=iとなったとき、つまり数字が同じになった時にcountが増えるようになっています。

そして、

```ruby:
if count < 2
 uniq_nums << num
end
```

上記の部分で重複した値が1つのときだけuniq_nums配列に値を追加しています。num=1のときはcount=2となるので、uniq_nums配列には追加されません。これを後2回繰り返した結果、uniq_nums配列には2だけが追加されることになります。

そして、重複しない値のみになった配列内の合計を求める処理の部分でuniq_nums配列内の合計を求めています。この場合はsum = sum + 2となり、最終的に合計は2と出力されます。

#おわりに

間違っている点、他に良い方法がありましたら、ご教授ください。よろしくお願いします。
明日こそAWSの記事を投稿します！！！！！
Dynamics 365 Business Central トライアル版を試す

　Micorosft Dynamics 365 Business Central のトライアル版を試す手順です。内容は 2020 年 11 月時点のもので、手順は変更になる可能性があります。

　Businses Central を試験的に試す目的であれば、オンプレミシス版や Windows コンテナ を利用するという方法もあります。この記事では 1 か月間有効なオンライン（SaaS）のトライアル版について説明しています。また、トライアルについて説明している Microsoft Learn のモジュールが既にあり、こちらも参考になります。

**参考リンク**

- [Microsoft Learn - Start your free Dynamics 365 Business Central trial][01]
- [Docker Hub - Dynamics 365 Business Central Generic image][02]
- [Microsoft Docs - Business Central On-Premises 2020 Release Wave 2 Updates][03]
- [CustomerSource - Download Business Central on Premises 2020 Wave 2 Release][04]

　トライアルの開始にあたって、支払情報の入力やソフトウェアのインストールは必要ありません。ただし、Microsoft がローカライズしている地域の組織アカウント（職場または学校のメール アドレス）が必要です。

- 利用可能な地域の一覧は [aka.ms/bccountries][05] で確認できます
- 組織アカウントがどの地域に属しているかは [Azure Active Directory 管理センター][06] で確認できます

## 1) サインアップする

　トライアル版のサインアップは [Business Central の製品ページ][11] の **Get started** のリンクから開始できます。Get started のリンクは Microsoft がローカライズしている地域の言語でないと表示されないようなので `en-us` 等の言語で試します。後は組織アカウントのメールアドレスを入力してサインアップするのみです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/07fab0b6-1f77-7595-b839-8c72318e488b.png" width="700px" />

## 2) セットアップを待つ

　初期のセットアップを待ちます。2～3時間程度かかることもあるようです。セットアップが完了したら [home.dynamics.com][21] のタイル、または [businesscentral.dynamics.com][22] のリンクから Business Central へアクセスできます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/2e940f8c-a7ac-2e03-c163-2c98e24808cb.png" width="700px">

　[home.dynamics.com][21] には下図のように Business Central のタイルが表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/93120c5a-5a6c-0dd3-7b94-a018386cccb0.png" width="700px">

## 3) サインインする

　デモ用のデータ（CRONUS USA, Inc.）がセットアップされた環境にサインインします。ライセンス情報は [Azure Active Directory 管理センター][31] または [Microsoft 365 admin center][32] で確認できるようです

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/bf5aa5f7-01f6-36dc-7e8b-94ecb31d74ce.png" width="700px">

[01]: https://docs.microsoft.com/learn/modules/trial-dynamics-365-business-central/
[02]: https://hub.docker.com/_/microsoft-businesscentral
[03]: https://docs.microsoft.com/dynamics365/business-central/dev-itpro/deployment/update-versions-17
[04]: https://mbs.microsoft.com/customersource/Global/365Business/downloads/product-releases/msdbcentralonprem20wave2
[05]: https://aka.ms/bccountries
[06]: https://aad.portal.azure.com/
[11]: https://dynamics.microsoft.com/en-us/business-central/overview/
[21]: https://home.dynamics.com/
[22]: https://businesscentral.dynamics.com/
[31]: https://aad.portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/Licenses
[32]: https://admin.microsoft.com/AdminPortal/Home#/licenses
セルフサービスBI管理者ツールについて①

#自己紹介＆Power BI歴
どうも、susumutanakaです。
私、Power BIで弊社内でのセルフサービスBIを展開しているものです。

Power BIで、
セルフサービスBIで始めたのが、2017年6月で、約3年5ヶ月ほどが経ちました。

僕の頑張りのおかげだと思うのですが、
（うそうそ、組織としてしっかり進めたおかげ？だと思うですがｗ）

おかげさまで、「Power BI」という言葉が弊社内では市民権を得て、
通常業務で、Power BI Service に発行されたBIレポートが活用されており、
普通の日常会話で、Power BIとでてくると、とても嬉しくなります。

そんなこんなでPower BI活用が認められ
11月中旬になりますが、MS様から事例取材を受けてきました！！パチパチ。
絶賛記事制作中で、1月どっかでMS様の事例サイトに弊社のPower BIの記事が掲載されますので、お楽しみをー！

#弊社のPower BI活用状況
さて、長い前フリはさておき、少し弊社の実績を紹介します。
まずは、ユーザ数ですが、
Power User（レポート作れる人ね）が約200名までおり、
一般ユーザ（Power BI無料ライセンス付与）が3000名弱おり、コスト削減の観点から、
2019年からPremium契約に変更しております。
（P2を10月切り替えたばかり）
ライセンスの違いに関しては以下の参照してください。

■Power Premium計算ツール 
https://powerbi.microsoft.com/ja-jp/calculator/

■ProとPremiumライセンスの違い
https://powerbi.microsoft.com/ja-jp/pricing/

#弊社での実績をPower BI
管理ポータル上の数字ですが、以下の通り、

ダッシュボードが369個
レポートが847個
データセット715個

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322851/78139e7c-f748-5552-6904-91f345b5fd1f.png)

うーん、ものすごい数のレポートでデータセットをUpされてますが、
ちゃんと運用されているか？微妙な感じはしますが、管理ポータル上の数字は嘘じゃないです。
（ちゃんとモデルしろと総ツッコミ受けそうですがｗ）

#データ鮮度と管理者の悩み

さて、ここから本題となりますが、
セルフサービスBIを展開するにあたり一番の気がかりなのが、**データの鮮度**です。
弊社は某グラウド上にデータレイク（分析基盤）を構築し、
そこから必要なデータをBI環境に構築されたDBに日々データを連携しています。

DBを参照して、
Power BI Serviceでデータ更新するに、オンプレミスゲートウェイが
必要となりますが、設定は以下のURLを参照してください。
（今後記事にしてくれる人期待！）

■Power BI オンプレミス データ ゲートウェイとは
https://docs.microsoft.com/ja-jp/power-bi/connect-data/service-gateway-onprem

そして、データセットの設定でろもろも設定するのですが、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322851/482d1737-0cfb-d5c6-a18b-b663556b05aa.png)

悩ましいのが、データ更新でエラーが出たときのメール宛先になります。
個人のメアドを設定するのもいいのですが、ここはPower BI管理者のメアドをオススメします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322851/0c06a7f4-97a7-bfc9-e804-9153217483d3.png)
※この画像の例では、個人になってますが、Power BI管理者にしましょう

個人に送られても個人が対応しないかぎりは、データが更新されないので、
IT部門で管理しているPower BI管理者のメアドにしましょう！

その上で、Power BI管理者のOutlook（Exchange）のデータソースにして
Power BIレポートを作成すれば、全体のエラー状況を把握できる以下のようなレポートを作成することができます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322851/af0f55a2-da73-9c28-634c-10bade231ef6.png)

どうでしょうか？参考になりましたでしょうか？
レポートの作り方などは続きは、12/17の枠で書きたいと思います。
（残枠あるので、まだまだ書いちゃうかも。データフローか、機械学習あたり）

他、こんなこと知りたいということがあれば、コメントいただければ、検討します！

今日はここまで。
今後とも宜しくお願い致します。

追記：
本日の障害とかなければ、もっと早くアップできたんですがね・・
業務中に記事書くとかもできたんですが・・
ゆうごさんの告知どおり前もって書くのをオススメします。m(_ _)m
なぜ、Webサーバが必要か説明できますか？

##はじめに
ざっくりと理解している程度を記事を書くことで理解度をあげることが目的。
railsのアプリ想定の話になります。

##Webサーバとアプリケーションサーバとはなにか？
Webサーバとは、ブラウザからのリクエストにHTMLやCSSを表示する動きをするサーバの事。

詳しく解説していた記事を一部拝借。  

>
Webサーバとは、Web3層構造の場合フロントエンドにある、ユーザーと直接やりとりを行うサーバです。
Webサーバには２つの役割があります。
ユーザーが操作するクライアントソフトウェア（Webブラウザなど）からの要求に応じて、ネットワークを通じてHTMLなどの静的Webコンテンツファイルを送信すること。
もう一つが、中間層にあるアプリケーションサーバに動的コンテンツを要求し、返ってきた結果を送信することです。
ただしWeb2層構造の場合は、Webサーバがアプリケーションサーバの役割も兼ねます。
>

[引用元](https://www.b-architects.com/blog/wiki/web-server)  
  
  
Web3層構造は**「WEBサーバー」****「アプリケーションサーバー（APサーバー）」****「DBサーバー」**の３つの構造になっている形

処理の流れをわかりやすく求めた記事がありました。

>
1. WEBサーバー  
↓：クライアントからの要求（リクエスト）をAPサーバーに伝える。  
↑：ブラウザが理解できる静的HTMLを返す（レスポンス）。  
>
2. APサーバー  
↓：・WEBサーバーからのリクエストに沿って、DBにデータを要求する。
　 ・ブラウザから受け取ったデータを元に処理する
↑： ・DBから受け取ったデータを、WEBサーバーに渡す。
　　・処理結果をWEBサーバーに渡す。
>
3. DBサーバー
↓：APサーバーからのリクエストに沿ってデータを検出する。  
↑：抽出したデータをAPサーバーに渡す。
>

[引用元](https://qiita.com/yuta-38/items/5d8bb6421495113e1602)


簡単に言えば、  
Webサーバは静的HTMLを返す
アプリケーションサーバは、処理を要求する。

大半のアプリケーションは、Webサーバを使わずに使用することが出来るそう。

じゃ、なぜWebサーバを使用するのか？

**webサーバーは複数のアプリケーションを一度に処理したり、**

**アセットを素早くレンダリングしたり、リクエストごとに発生する多くの処理をさばいたりしてくれます。**

サーバを分けることで、処理の速さを上げてるってことですね！


##Webサーバの種類

####Apache（アパッチ）
全世界のおよそ40% のWebサーバーはApacheが占めているそうです。

オープンソースであり、Apacheで扱うことのできる機能が豊富。

さらに、LinuxやUNIX、WindowsやMac OSなど、ユーザーの環境を選ばない点も魅力。

また、Apacheはマルチプロセッシングモジュールを採用しており、1つのスレッドごとに新しいプロセスを起動する方式です。動的なコンテンツの処理に適しており、CGIやPHPなどに向いている。

※MPM は (Multi Processing Module) の略で、Webブラウザからのリクエストを Apache がどのように並行処理するか、という部分の処理をモジュール化したものです。


####Nginx（エンジンエックス）
Nginxはキャッシュサーバー不要でHTMLや画像などをキャッシュできるので、静的コンテンツを扱うのに適したWebサーバーといえます。シングルスレッドを採用しており、1つのプロセスが複数の処理を行ないます。

※シングルスレッドとは、プログラムの処理が単一に行われることです。それに対して、マルチスレッドというものもありまして、こちらは同時にいくつもの処理が行われます。


大容量のデータを処理することを想定して開発されているため、アクションが起こったときに処理を行なうイベント駆動型を取り入れています。メモリを効率的に使用できるので、処理速度が非常に高速な点が魅力。

処理能力や同時接続数などの負荷への耐久力は、Apacheよりも高いといわれています。


####IIS（アイアイエス）
IISはWindows用のWebサーバー機能です。Microsoft社が提供しているため、Windowsに特化しています。ApacheやNginxと違い、IISはOSSではありません。

IISはWindowsベースなので、情報表示においてグラフィックを多用しているので、直感的に操作可能なGUIである点も大きなメリット。

Linuxなどのようにコマンドを扱う必要がなく、直感的に開発を行なうことができます。また、ApacheやNginxに比べて日本語のマニュアルが充実。

[参考記事](https://www.rworks.jp/system/system-column/sys-entry/16296/)


##アプリケーションサーバの種類

####Unicorn
プロセス上で動作するサーバで、masterプロセスとworkerプロセスがある.

masterプロセスがアプリケーションのソースコードを保持しこれをforkしたworkerプロセス群が実際のリクエストを処理ソースコードをロードするのがmasterプロセスのみであるため起動が早い。

デプロイ時のダウンタイムがない。

######Unicronの弱点

スロークライアント(リクエストが遅いクライアント) に弱い。

スロークライアントが来た場合、workerが待ちのまま止まってしまうという特徴がある。
そのためNginxなどリバースプロキシを挟んで、スロークライアントをバッファしてもらう必要がある。

これは、Unicornの不具合というより仕様。Unix哲学の「一つのことをうまくやる」に沿って作られているため。スロークライアントのバッファは、リバースプロキシに任せるように作られている。

NginxとUnicornの組み合わせが多い理由はこの辺にあるのかもしれないですね！

[参考記事](https://qiita.com/sunoko/items/3989865bf915887f8d2b)


####puma
pumaはスピードと並列性を追求しており、ユーザーからのリクエスト受け取りとアプリケーションサーバへ処理を投げるのが速い。

処理をスレッド単位で溜めて、それをマルチに実行することです。（スレッドは処理の単位）

要するに、pumaは処理を小さな単位で分けて同時実行しているから速いということです。

イメージの通り速いって感じですね！

[参考記事](https://arma-search.jp/article/ruby-puma)



##まとめ
特長をかいつまんで、まとめてみました。
間違っている箇所があれば教えてください。

なぜ、この技術を使うのかまで理解して使用することを意識して行きましょう！
モーダルウィンドウの後ろがスクロールされてしまう時の対策方法（jQuery）

# どうも7noteです。背景がスクロールされてしまう問題の解決方法

モーダル処理に対策を入れていなければモーダルが開いている間でも背景（本文）がスクロールされてしまいます。

![miss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/36380894-c98f-4347-89b6-9d7ee0271d5a.png)


さっそくソースの方へ。

## ソース

jQueryを使用しています。jQueryって何？という方は[こちら](https://qiita.com/7note/items/45bd8efbedd557667218)

```index.html
<p>みなはその間どうもその享有地としてののためを打ちでまし。もし当時で尊重方はもっともその意見なけれうなどに加えるがいらっしゃるたらには懊悩なれですうて、どうには組み立てうありんん。金力にしましのは単に元来でもうましませで。

〜〜〜〜省略〜〜〜〜〜〜〜〜〜〜〜

無論大森さんを公言兄ちょっと意味がありあり敵その縁私か満足でにおいてご相当たないありですて、その事実は君か人心持で眺めて、大森さんの事へ日本人の私をよくお観念と衝くから私示威にお安心しです。この他も私上に罹って今などしからくれ点か思いうなけれが、このためあれをたてどこの校長になりがいらっしゃるから、反抗に間違っれる旨は、事のろという正しく心丈夫でましがいつはかけるていのないて、しかし上が知れて、そう何院の附随曲げようたない修養は、もっと私をこの自己を知ればならばは自由にしれものなもですなとは待っ事です。
</p>

<div class="open">開く</div>

<div class="modal">
  <div class="box">
    <p>ここがモーダル</p>
    <div class="close">閉じる</div>
  </div>
</div>
```


```style.css
/* 開くボタン */
.open {
  color: #fff;        /* 文字色を白に指定 */
  background: #000;   /* 背景色を黒に指定 */
  position: fixed;    /* 画面左上に固定 */
  top: 0;
  left: 0;
  padding: 10px;      /* 適当な余白を指定 */
}

/* モーダルウィンドウ */
.modal {
  background: rgba(0,0,0,0.5);  /* 半透明の背景を設置 */
  position: fixed;              /* 表示位置に固定 */
  width: 100%;                  /* 横幅を幅いっぱい */
  height: 100%;                 /* 高さを縦幅いっぱい */
  top: 0;                       /* 上から0pxの位置 */
  left: 0;                      /* 左から0pxの位置 */
  display: none;                /* 最初は非表示にする */
  box-sizing: border-box;       /* 余白や幅の計算を簡単にする */
  margin: 0 auto;               /* 左右中央に配置*/
  padding: 50px;                /* 上下左右に適度な余白 */
}

/* モーダルの中の要素 */
.modal .box {
  background: #fff;                /* 背景色を白に指定 */
  padding: 20px;                   /* 適度な余白を指定 */
  max-height: calc(100vh - 100px); /* モーダルウィンドウが画面の縦（+余白）より大きくなった際の対処のため指定 */
  overflow-y: scroll;              /* max-heightを超えたらスクロールになるよう指定 */
  box-sizing: border-box;          /* 余白や幅の計算を簡単にする */
}

/* 閉じるボタン */
.modal .close {
  color: #fff;         /* 文字色を白に指定 */
  background: #000;    /* 背景色を黒に指定 */
  text-align: center;  /* 文字を中央揃えにする */
  margin: 10px 0 0;    /* モーダルのテキストと距離をとるため */
}
```


```script.js
$(function(){
  //「開く」がクリックされた場合
  $('.open').on('click',function(){
    $('body').css('overflow-y', 'hidden');  // 本文の縦スクロールを無効
    $('.modal').show();                     // モーダルウィンドウを表示
  });
  //「閉じる」がクリックされた場合
  $('.close').on('click',function(){
    $('.modal').hide();                     // モーダルウィンドウを非表示
    $('body').css('overflow-y','auto');     // 本文の縦スクロールを有効
  });
});
```

## 解説

まず先にモーダルが開いたり閉じたりする仕組みを作ります。開くボタンの設置と閉じるボタンをモーダルの中に配置しておきます。
そして、本題の背景スクロールですが、body要素に`overflow-y:hidden;`を当てることでスクロールを無効化することができます。

これを開くボタンを押した瞬間に切り換えるためにscript.jsのように記述します。
スクロールを許可する時は逆になるだけで、モーダルを非表示にもどした後、`overflow-y:auto;`をbodyに当てることで元に戻ります。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】HTML・CSSのちょいテク詰め合わせ](https://qiita.com/7note)
Linux  /etc/passwd, /etc/group 【重要】

#【Linux  /etc/passwd, /etc/group】

#ユーザ管理

Linuxを扱う上でユーザ管理はとても重要
今後のためにもしっかり理解したい。

##/etc/passwd

<strong>書式</strong>

例）　user50:ｘ:500:500::/home/user50:/bin/bash

「:」で各情報が区切られる。

第1フィールド　ユーザ名
第2フィールド　パスワード
第3フィールド　ユーザID
第4フィールド　グループID
第5フィールド　コメント欄
第6フィールド　ホームディレクトリ
第7フィールド　ログインシェル

※第2フィールドのパスワードは、設定済みであれば「ｘ」が記載される。
　→「ｘ」パスワード情報は /etc/shadow に格納される。rootユーザーしか読めない。

###それぞれのパーミッション

/etc/passwdは、644 （rw-r---r---）
　→ rootユーザは、読み書き可能。それ以外は、読み取りのみ。

/etc/shadowは、400 （r----------）
　→ 一般のユーザがパスワードを見ることはできない。

##/etc/group

<strong>書式</strong>

例）　group50:ｘ:500:tanaka

「:」で各情報が区切られる。

第1フィールド　グループ名
第2フィールド　グループパスワード
第3フィールド　グループID
第4フィールド　グループに所属するユーザのリスト

※第2フィールドのグループパスワードは、設定済みであれば「ｘ」が記載される。
　→「ｘ」グループパスワード情報は /etc/gshadow に格納される。

##・問

<strong>Q、</strong>/etc/shadowを参照するために/etc/passwdの第２フィールドに記述するのは。
<strong>A、</strong>x

<strong>Q、</strong>ユーザのプライマリグループが記述されているのは。
<strong>A、</strong>/etc/passwd

<strong>Q、</strong>/etc/groupに記述されているのは。
<strong>A、</strong>グループ名、グループパスワード、グループ名、グループに所属するユーザのリスト
AWSとGCPの障害発生件数をどう取得するか

# AWSとGCPの障害発生件数をどう取得するか

## はじめに

「ところで、AWSとGCPってどっちが障害多いの？」　こういう質問をされたクラウド・インフラ系エンジニアはいるのではないだろうか。
その調べる方法について記載する。

## 結論

それぞれ、statusのサイトの情報をjsonで取得するので、それをjqでカウントする。

AWS : `curl https://status.aws.amazon.com/data.json | jq  '.archive[] | select (.date > "任意のUNIXTIME" )' | jq length --slurp`
GCP : `curl https://status.cloud.google.com/incidents.json | jq length`

_注意点_
GCPは 過去1年分しか取得できないっぽい。
AWSは 執筆時点では 2018-05-10 10:06:41 のやつから取得できる。

## そもそも・・・

AWSもGCPも、リージョンやゾーン、提供しているサービス数が全然違うのに、どっちのほうが障害が多い、どっちのほうが優れているとかを障害数から比べることがナンセンスだと思う。
Create React Appで作ったReactアプリケーションを相対パスへデプロイする

[同じ内容をZennにも投稿しました。](https://zenn.dev/backpaper0/articles/create-react-app-context-path)

---

## 概要

Create React Appで作ったReactアプリケーションを`https://example.com/`のようなルートではなく、`https://example.com/foobar/`のような相対パスへデプロイする方法を書きます。

## 相対パスへデプロイできるようにする方法

方法はCreate React Appの公式ドキュメント、Deploymentの[Building for Relative Paths](https://create-react-app.dev/docs/deployment#building-for-relative-paths)というセクションに書かれています。

まず`package.json`に`"homepage": "/foobar/"`を追加します。
公式ドキュメントでは`http://mywebsite.com/relativepath`というような絶対URIが書かれていますが、`/`から始まるパスでも大丈夫です。

それから、[React Rotuer](https://reactrouter.com/)を使用している場合は`BrowserRouter`に`basename`属性を設定します。

```
<BrowserRouter basename="/foobar/">
```

`basename`属性さえ設定しておけば、`Link`要素の`to`属性や`Route`要素の`path`属性は相対パスを気にすることなく設定できます。

## どうやって実現しているの？

`package.json`から`homepage`を読み取っているのは[paths.js](https://github.com/facebook/create-react-app/blob/v4.0.1/packages/react-scripts/config/paths.js#L28)です。

読み取った値は[webpack.config.js](https://github.com/facebook/create-react-app/blob/v4.0.1/packages/react-scripts/config/webpack.config.js#L223)で[WebpackのPublic Path](https://webpack.js.org/guides/public-path/)に渡されています。

あとはWebpackが`js`ファイルや`css`ファイルを設定した相対パスから読み込むようにビルドしてくれます。

なお、React Routerの方はまだソースコードを読んでいないので省略します。

## コード例

- https://github.com/backpaper0/sandbox/tree/master/react-relative-paths-example
javascript 問題集 No.20 数値をtoStringを使わずに2進数にする。

数値を2で割り切れなかったら1、割り切れたら0。

まず、0と1を入れる配列。

割る数（商）を確認する配列。

for文を商が1以下になるまで回し続ける。

このような基盤が出来たら、あとは配列を逆に回して配列を反対にする。

consoleに.join("")して2進数の完成
開始距離、終了距離を指定してラインを分割する

[開始点、終了点を指定してラインを分割する](https://qiita.com/amay077/items/4592ac20ea52bd0cfe15) と似ていますが、こちらは、「距離 L メートルのラインの内、開始から S メートル ～ E メートル区間を切り取る」というものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8227/befc6c21-c572-8e77-a26f-5f652af1cbea.png)

``lineSlice`` の兄妹メソッド ``lineSliceAlong`` を使います。

- [Split line by distance - JSFiddle - Code Playground](https://jsfiddle.net/amay077/51v6zrfp/)

```javascript
const routeSource = {
  'type': 'geojson',
  'data': {
    'type': 'Feature',
    'properties': {},
    'geometry': {
      'type': 'LineString',
      'coordinates': [
        [-122.48369693756104, 37.83381888486939],
        [-122.48356819152832, 37.82954808664175],
        [-122.48751640319824, 37.83168351665737],
        [-122.49223709106445, 37.83337825839438],
        [-122.49378204345702, 37.83368330777276]
      ]
    }
  }
};

const lineFeature = {
  type: 'FeatureCollection',
  features: [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type":"LineString",
        "coordinates": []
      }
    }
  ]
};

const map = new mapboxgl.Map({
  container: 'map',
  center: [-122.486052, 37.830348],
  zoom: 15,
  style: {
    version: 8,
    sources: {
      OSM: {
        type: "raster",
        tiles: [
          "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
        ],
        tileSize: 256,
        attribution:
        "OpenStreetMap",
      },
    },
    layers: [{
      id: "BASEMAP",
      type: "raster",
      source: "OSM",
      minzoom: 0,
      maxzoom: 18,
    }],
  },      
});

map.once('load', () => {

  map.addSource('route', routeSource);
  
  map.addLayer({
    'id': 'route',
    'type': 'line',
    'source': 'route',
    'layout': {
      'line-join': 'round',
      'line-cap': 'round'
    },
    'paint': {
      'line-color': '#888',
      'line-width': 8
    }
  });


  map.addSource('lineOnLine', {
    'type': 'geojson',
    'data': lineFeature
  });
  lineSource = map.getSource('lineOnLine');
  
  map.addLayer({
    'id': 'lineOnLine',
    'type': 'line',
    'source': 'lineOnLine',
    'layout': {
      'line-join': 'round',
      'line-cap': 'round'
    },
    'paint': {
      'line-color': 'red',
      'line-width': 12
    }
  });
  

});


document.getElementById('split').addEventListener('click', () => {
	const fromDist = Number(document.getElementById('from').value);
	const toDist = Number(document.getElementById('to').value);
  const slicedLine = turf.lineSliceAlong(routeSource.data, fromDist, toDist, { units: 'meters' });
  lineSource.setData(slicedLine);
});
```

使い方は turf.lineSliceAlong(ライン, 開始距離, 終了距離, 単位) です。
なんで lineSlice と引数の順序が違うんだ...。

## 参考

- [lineSliceAlong - Turf.js | Advanced geospatial analysis](https://turfjs.org/docs/#lineSliceAlong)
filebeat で ISO8601 形式のタイムスタンプを @timestamp に変換して elasticsearch にインデキシキングする

この記事は、[みらい翻訳 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/miraitranslate) 3日目の記事です。

こんにちは、[株式会社みらい翻訳](https://miraitranslate.com/) プラットフォーム部の@kobarasukimaroです。
バックエンドエンジニアですが最近は SRE をやっています。
ちょうどアドベントカレンダーに空きがあったのでねじ込んでみました。

## 記事について

filebeat を使ってログを読み込むときに logback のデフォルトタイムスタンプ ISO8601 形式のタイムスタンプのパースにハマったのでメモ

## 環境
Filebeat 7.8.0
Elasticsearch 7.8.0

## 内容
filebeat で Logstash と同じ感覚で ISO8601 形式のタイムスタンプをそのままパースできると思ったら出来ませんでした。
[Logstash とかとフォーマットが違うよというのはドキュメントに書いてありました。](https://www.elastic.co/guide/en/beats/filebeat/master/processor-timestamp.html)

filebeat.yml 内で色々と試行錯誤したのでその結果を残しておきます。

## 先に結論
以下のように定義を書いたら上手くパースできました

```yaml
filebeat.inputs:
- type: s3
  processors:
    - dissect:
        tokenizer: '%{timestamp} %{message}'
        field: "message"
        target_prefix: "dissect"
    - script:
        lang: javascript
        id: convert_timestamp
        source: >
          function process(event) {
              var timestamp = event.Get("dissect.timestamp");
              event.Put("dissect.new_timestamp", Date.parse(timestamp));
          }
    - timestamp:
        field: dissect.new_timestamp
        layouts:
          - 'UNIX_MS'
```

### yaml について
#### dissect
filebeat が受け取ったデータをトークナイズします。ここは受け取ったものによって内容は変わってきますが、今回だと↓のようなログを想定しています。

```
2020-12-03T05:35:32.010+0000 hogehoge
```

https://www.elastic.co/guide/en/beats/filebeat/master/dissect.html

#### script
filebeat でデータを加工する時 ECMAScript が使えます。
https://www.elastic.co/guide/en/beats/filebeat/master/processor-script.html

ISO8601 の日時だとそのままパースできないため、ここで UNIX タイムにパースします。
さらにそのあと elastic search の timestamp に変換するため `event.Put` を使ってイベントに値を入れます。

#### timestamp
最後に elastic search でタイムスタンプとして取り扱えるように変換します。
`new_timestamp` は UNIX タイムが入っているので `layouts` で `UNIX_MS` を指定します。
そうすると elastic search の `@timestamp` に dissect で 取り出した `timestamp` と同じ日時のデータを入れることができます（別のフィールドに入れたければ `target_field` でフィールド名指定）
https://www.elastic.co/guide/en/beats/filebeat/master/processor-timestamp.html

## 最後に
filebeat 色々できるので楽しいですね。
他、良いパースの方法ありましたら教えていただけると幸いです（logback のタイムスタンプ直した方が早いというのもありますね・・・）。

明日は @m-chika が何か書くそうです！
インスタンスの時間は信用できないという話

# 時間に依存したコード
サーバーサイドのアプリケーションを開発する際、インスタンスの時間に依存したコードを書くことは多いと思います。例えばチャットアプリケーションのAPIサーバーをイメージしてみてください。メッセージ投稿APIでアプリケーションで現在時刻を投稿時間としてセットしてDBにインサートし、メッセージ取得APIではDBに入っているレコードを投稿時間順に並び替えて取得する、といった感じでしょうか。
メッセージ投稿APIで使用した`投稿時間`をアプリケーションでセットしましたが(Goなら`time.Now()`、Rubyなら`Time.now`とか)、その値は信用できるものなのでしょうか。

# インスタンスの時間は信用できない
そもそもインスタンスの時間はどうやって決まっているのかというところですが、サーバーの時刻は一般的にNTP(Network Time Protocol)という仕組みを使って同期が取られています。定期的にNTPサーバーと通信を行い、NTPサーバーが返す時間と大幅にずれていたら時間を進めるor戻すといったことを行っています。そのためこの精度はNTPサーバーと通信を行う間隔、ネットワークの遅延、ハードウェアの故障等様々な要因によって左右されてしまいます。一般論としてズレは数十ms以内に収まるようですが、必ずその範囲に収まるわけではないのでズレを許容するもしくはインスタンスの時間を使用しないなど、アプリケーション側で対応する必要があります。
ちなみに金融機関等、時刻の正確性がかなりの精度で求められるところではハードウェアに十分な投資を行い精度を高めているそうです。

# 問題が発生した例
では実際にインスタンスの時間に依存したコードを書いていたがために問題が発生した例を紹介します。

### 環境

- Go v1.15
- GKE
- Cloud Spanner

### 背景

データ(仮に`Storages`テーブルとします)の変更履歴を保存し競合を防ぐための`Revisions`テーブルというものがあります。

#### `Revisions` テーブル
|name|type|
|:-:|:-:|
|ID|STRING|
|Revision|STRING|
|CreatedAt|TIMESTAMP|

storageを追加するリクエストには最新のRevisionも一緒に含め、DBに入っている最新のRevisionと比較することで競合を防ぐ仕組みになっています。

```go
// クライアントからのリクエスト
// Storage:      新しく更新したいストレージの内容
// PrevRevision: 一つ前のRevision
// NextRevision: 次のRevision
req := getRequest()

// CreatedAtで並び替えて最新のrevisionをDBから取得する
rev := getLatestRevision()

// Revisionが競合しているためエラー
if req.PrevRevision != rev {
  return errors.New("invalid revision")
}

// 最新のrevisionを作成してDBにINSERTする
new := &Revision{
    ID: uuid,
    Revision: req.NextRevision,
    CreatedAt: time.Now(), // 現在時刻をセット
}
insertRevision(new)

// わかりやすくするため簡略化しています
// 上記のコードはspannerのtransaction内で実行しています
```

### 発生した問題
膨大なリクエストを送るとたまに`invalid revision`エラーが発生していました。リクエストのログによると問題なく直列に正しいRevisionを指定して送信していました。しかしDBに入っているレコードを見ると、CreatedAtで並び替えた時にリクエストの逆の順序でレコードが挿入されていました。
このCreatedAtは正確には`DBにコミットされたタイミングでのDB上の時間`ではなく、`DBにコミットするタイミングでのpod上の時間`なため、リクエストを処理した実際の時間とpodの時間の順序が逆転してしまったためにこの問題が発生したと考えました。

#### リクエスト
- リクエストは直列(前のレスポンスが返ってきてから次のリクエストを送信する)に実行していた
- リクエストには正しいPrevRevisionが指定されていた(前回のリクエストで設定したNextRevision)
- リクエストはそれぞれ別のpodに送られている
- リクエストは1つあたり数十msで完了している

```
1. {prevRevision: a, nextRevision: b} -> ok
2. {prevRevision: b, nextRevision: c} -> ok
3. {prevRevision: c, nextRevision: d} -> invalid revision error
```

#### DB
- CreatedAtで並び替えた時、Revisionがa->bの順序で入っているのが正しいが、実際はb->aの順序で入っていた。

|Revision|CreatedAt|
|:-:|:-:|
|a|2020-01-01T00:00:00.001000Z|
|b|2020-01-01T00:00:00.000000Z|


### 解決策
RevisionsテーブルのCreatedAtカラムにはDBにコミットされたtimestampを入れるようにコードを変更することで`invalid revision`エラーは発生しなくなりました。(Cloud Spanner の commit_timestamp)。

# まとめ
インスタンスの時間に依存したシステムを作るときは、その時間は必ずしも正確ではなくずれる可能性がある、ということを頭の片隅においておくと良いと思います。

# 参考リンク
https://www.oreilly.co.jp/books/9784873118703/

---

この記事を読んで「面白かった」「学びがあった」と思っていただけた方、よろしければ Twitter や facebook、はてなブックマークにてコメントをして頂けると嬉しいです。
また [DeNA 公式 Twitter アカウント @DeNAxTech](https://twitter.com/DeNAxTech) では、 Blog記事だけでなく色々な勉強会での登壇資料も発信してます。こちらもぜひフォローして頂けると嬉しいです。
<a href="https://twitter.com/DeNAxTech?ref_src=twsrc%5Etfw" class="twitter-follow-button" data-size="large" data-lang="ja" data-show-count="false">Follow @DeNAxTech</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【画像投稿】サムネイルのサイズをモデルごと動的に変えて保存する (Rails carrierwave) 備忘録

# 前提
gem 'carrierwave'
gem 'mini_magick'

・ 画像投稿機能は実装済とする(投稿機能の参考リンクは下に記述します)
・ 中間テーブルで画像を管理
###環境
・Rails 5.2.3
・ruby 2.5.1

# コード
結果から記述しますと下記の様になります。

```ruby:image_uploader.rb
  def dynamic_resize_fill
    if defined? model.class::THUMBNAIL_SIZE
      size = model.class::THUMBNAIL_SIZE
    else
      size = [540, 540]
    end
    resize_to_fill size[0], size[1], "NorthWest"
  end

  version :thumb do
    process :dynamic_resize_fill
  end

process resize_to_fit: [800, 800]
```
```ruby:user_image.rb
  belongs_to :user
  THUMBNAIL_SIZE = [780, 400]
  mount_uploader :image, ImageUploader
```

# 説明

画像投稿可能なモデルで適当な変数に好きな画像サイズを定義します。[横ピクセル, 縦ピクセル]↓

```ruby:user_image.rb
  belongs_to :user
  THUMBNAIL_SIZE = [780, 400]
  mount_uploader :image, ImageUploader
```
画像投稿の際に、「THUMBNAIL_SIZE」が定義されていれば定義されていたサイズを使用する。
していなければ、[540, 540]を使用します。
 "NorthWest"は中心点を左したに指定しています。(default: center) ⇨ Link : [ImageMagick Gravity 指定](https://qiita.com/yoya/items/b6926f01b7cb90217e07)
↓

```ruby:image_uploader.rb
  def dynamic_resize_fill
    if defined? model.class::THUMBNAIL_SIZE
      size = model.class::THUMBNAIL_SIZE
    else
      size = [540, 540]
    end
    resize_to_fill size[0], size[1], "NorthWest"
  end
```

投稿される際に、version :thumbでサムネイル用の画像が生成されます。
process :dynamic_resize_fill は上記の関数(dynamic_resize_fill)を呼び出して、サイズと中心点を決定します。
↓

```ruby:image_uploader.rb
  version :thumb do
    process :dynamic_resize_fill
  end
```


# 参考

画像投稿
https://qiita.com/matcham/items/ab8158dba16d2f21fd85

ImageMagick Gravity 指定(中心点)
https://qiita.com/yoya/items/b6926f01b7cb90217e07

サムネイルのサイズをモデルごとに変更
https://nabeatsu.hatenablog.com/entry/2017/09/18/134107

CarrierWave+MiniMagickで使う、画像リサイズのメソッド
https://qiita.com/wann/items/c6d4c3f17b97bb33936f
display: grid; で上下左右中央揃えのあれ

なんだかいい感じに上下左右に中央揃えしてくれるやつをいつも忘れるので備忘録．

# 本編
```css
.container {
    display: grid;
    place-items: center;
}
```

# さらに

現代では 1 行で実現できる

```css
align-content: center;
```

# おわり
おわりです
エラーduplicate symbols for architecture x86_64の対処法

## はじめに

**Qiita Advent Calendar**初参加！
Advent Calendarの温度感を全くわからない状態で「これも挑戦」というメンタルだけで参加させてもらいましたw

お手柔らかにお願いします♪

## 環境
MacOS BigSur 11.0.1
Swift version 5.3.1
Xcode version 12.2 

## duplicate symbols for architecture x86_64エラー発生

リモートブランチからmasterブランチにマージをおこなったあとにビルドを実行すると`duplicate symbols for architecture x86_64`というエラーが発生。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643372/f820f38a-7b37-1563-aaee-a2981ebea56a.png)
要約すると`シンボルが3つ重なっている`と言われています。

ん？
なんのこっちゃ？といった感じですw
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643372/a50e90bd-1dbb-d0b0-7d66-28e0798ce75b.png)
ひとまず検索をかけたところ、古い記事が多く、問題解決に直結しそうな記事にはありつけませんでした...
こうなるとエラー文を読み解いていくしかないですね！

## エラー文解析（仮説）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643372/707171a6-6bfc-86b9-72c7-0b9f90a3ef7f.png)
一度お茶🍵をしばき、`シンボルが3つ重なっている`という情報をヒントにエラー文を冷静に読み解いていくと気がかりなことが2点。

①赤帯エラー文の上にある`duplicate symbol '_pb_files_iter_find'`から始まるログ？が3件あるが、いずれも内容が同じだという点。この時点で`シンボルが3つ重なっている`と濃い関係であることを仮説としてあげられる。

②`duplicate symbol '_pb_files_iter_find'`からログを読み進めると`Pods.build`というのが存在する。ここでpodに関するエラーである仮説が浮上する。

## 仮設検証
仮説①②をまとめると`podに関する何かが3つ重複している`ということになる。

podに関することでできそうなことは2点。

①podをupdateして更新。
②podを一度全て削除して再度インストール。

①はすでに存在するpodをあくまでも更新するのみなので、得策である対処法は②なので実行してみる。

```
//podに関する3つのファイルをFinderから削除
  Podfile
  Podfile.look
  Pods

//ターミナルで下記コマンドを実行してPodfileを改めて作成
  $ pod init

//必要なpodをPodfileに記述して下記コマンドでinstall
  $ pod install
```
これでpodのリセットができたのでビルドを実行すると解決できると思います！

## 原因
はっきりとしたことは分かりませんが、リモートブランチでマージをおこなった際にpodに関係する何かがうまく処理されず、今回の場合は関数が重複してしまった、ということになりそうですね。
`duplicate symbols for architecture x86_64`エラーに関してはログを読んで、関係しているであろう何かを発見することで対処できそうですね！（まあ他もそうなんでしょうが...w）

## 最後に
今年は初めてQiitaさんとお会いし、アウトプット面で非常にお世話になりました！
ありがとうございます！

年内もしくわ年始には個人アプリの開発が完成しそうなので、その後転職活動を行う予定です。
来年のAdvent Calendarは現役エンジニアとして成長した記事を投稿することを目標に精進します！
Puppeteerで環境変数を設定

# ■ Node.jsで環境変数を使えるようにする。
### 1. dotenvをインストール
```bash
npm install dotenv
```

### ２. 環境変数(.env)を設定

```bash:.env
NAME=まんちゃん
```


# ■ Puppeteerで動かしてみる。
### 1. 動作確認
日本Seleniumユーザーコミュニティの[テストサイト](http://www.selenium.jp/test-site)を利用

```js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('http://example.selenium.jp/reserveApp/');

  // 入力画面
  await page.screenshot({path: 'before.png'});
  await page.type('#guestname', process.env.NAME); // .envの環境変数を取得
  await page.screenshot({path: 'after.png'});

  await browser.close();
})();
```

実行

```bash
node --require dotenv/config dotenv_test.js 
```

![before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/9e8ef986-e1c2-4df6-a798-d7671b54f40d.png)
![after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/7d4a48ce-538b-9ca9-c47f-f50889cdc8e6.png)
GASで作る、サイトを監視しSlackに通知する

## はじめに

1時間に１度サイトの監視行い、サイトがダウンしている場合にSlackに通知が来るGASを作成しました。

とても簡単に作成できて手順としては下記の3STEPです。

1. サイトを監視するGASを作成
2. トリガーを利用してGASを定期実行する
3. 結果をSkackに通知する

順番に説明していきます。

## 1. サイトを監視するGASを作成

まず、GAS(Google App Script)を開きます。
手順は、「Google Drive」 → 「新規」 → 「その他」 → 「Google App Script」です。

<img width="600" alt="GASを開く" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342028/a31371f2-f583-a159-0691-736222952f6d.png">

GASが開けたら、下記コードをコピペします。

```js
function main() {
  var url = "監視したいサイトのURL";
  
  var response = UrlFetchApp.fetch(url, {
    muteHttpExceptions: true // 例外処理を除外している
  });
  var response_code = response.getResponseCode(); //サイトの返答コード。正常時は200。
  
  if(response_code == 200) {
    Logger.log('正常に動作しています');
  } else {
    Logger.log('サイトが落ちています。')
  };

}
```

上部のタブから再生ボタンを押すとGASを実行することができます。
*実行する時に権限の許可を求められるので、流れに合わせて許可してください。

![スクリーンショット 2020-12-03 14.32.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342028/040b8dd4-eb43-4a2a-3b80-25ff30970e23.png)

`⌘command` + `Enter`を押すと実行結果のログをみることができます。
<img width="600" alt="ログ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342028/a19807cb-591d-a616-7074-88a284bd8b45.png">


## 2. トリガーを利用してGASを定期実行する

次は、作成した関数を定期実行していきます。
定期実行にはトリガーを使います。

手順は、「時計マークを押す（再生ボタンの横）」 → 「右下のトリガーの追加」 でトリガーの設定ができます。

設定する際は、「実行する関数を選択」で、コードの関数の名前と同じになっていることを確認ください。（今回の場合はmain()になります。）

<img width="600" alt="トリガー" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342028/b9d5e4dc-986c-e17c-d601-a8937439d742.png">

[GASトップのマイトリガー](https://script.google.com/home/triggers)をみて、今設定したトリガーがでてきてたら定期実行の設定完了です。

## 3. 結果をSkackに通知する

次にSlackとの連携を行います。
今回は「Incoming WebHooks」をいうアプリを使って実装していきます。

「Incoming WebHooks」の導入に関しては、こちらの記事がわかりやすく説明されていたので、こちらを参考にしてください。
[GAS超入門⑤ - Slackに通知してみよう](https://note.com/skipla/n/na3f7f9cd9b7d)

コードの全体像は下記のようになります。

```js
function main() {
  var url = "サイトのURL";
  
  var slack_url = "SlackでコピーしたURL";
  var user_name = "サイト監視"; //Slackで通知する際の名前
  var icon = ":scream"; // Slackで通知する際の絵文字
  var message = ""; // 通知の文
  
  var response = UrlFetchApp.fetch(url, {
    muteHttpExceptions: true 
  });
  var response_code = response.getResponseCode();
  
  // サイトが落ちてる時だけ通知するように200以外がかえってきた時の処理のみにしています
  if(response_code != 200) {
    message = "<!channel> サイトが落ちています";
    
    // Slackに通知するためにJSONにする
    var jsonData = {
      "username": user_name,
      "icon_emoji": icon,
      "text": message
    };
    
    var payload = JSON.stringify(jsonData);
    
　　 // Slackに通知する際のオプションを指定
    let options = {
      "method": "post",
      "conyentType": "application/json",
      "payload": payload
    };
    
    // Slackに送る
    UrlFetchApp.fetch(slack_url, options);
  };  
    
}
```

## 終わりに

最近、GASを使っているという声がちらほら上がっているので、少し触ってみたいと思い開発してみました。
触ってみた所感としてはJSのように簡単にかけて、学習コストは低いと感じました。
また、学習コストが低いにもかかわらず、幅広いことをできそうだと感じたので、これから少しずつ触ってみたいと思いました。


### 参照

[サーバーを用意しなくてもプログラムを実行できる無料サービス](https://blog.capilano-fw.com/?p=7675)
[【初心者向け】GASを使ってSlackへ自動通知](https://qiita.com/chihiro/items/c7b11abc78f5d806c3a8)
[GAS超入門⑤ - Slackに通知してみよう](https://note.com/skipla/n/na3f7f9cd9b7d)
[CSS] position:absolute;の指定で要素を重ねる

#要素に要素を重ねたい

親要素に子要素を重ねたい場合、CSSで子要素にposition:absolute;の指定をします。
position:absolute;は、要素の位置の絶対配置を意味しています。
要素の位置は top, right, bottom, left の値で指定します。

親要素には、position:relative;を指定します。
親要素に、positionの指定が無い場合、子要素の位置の起点はブラウザ全体の左上になってしまいます。

```html:index.html
<div class="parent_element">
  <span class="child_element">子要素を重ねる</span>
</div>
```

```css:stylesheet.css
.parent_element {
  height: 150px;
  width: 300px;
  background-color: #02ccba;
  position: relative;
}

.child_element {
  color: white;
  position: absolute;
  top: 25px;
  left: 25px;
}
```

この例は、以下のように表示されます。
<img width=300px src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/897250/ee5e9859-598d-6955-d5fb-68a65cff92e0.png">
コンピューターにおける時間制御

コンピュータの時間制御の仕組みについて、基本を理解しようと思って調べてみた。
重要概念と仕組みを書いていく。

# 時間制御の大枠

1. 起動時に、hardware clock から system clock を設定する。
2. カーネルが system clock を正確に維持する。
3. シャットダウン時に、system clock から hardware clock を設定する。

# Hardware clock

名前の通り、ハードウェアのクロック。
Real Time Clock (RTC) や CMOS Clock とも言う。

年、月、日、時、分、秒を保持する。
2016年以降のみ、UEFI のファームウェアが time zone や夏時間使用の有無を保持できる。

---

`hwclock`コマンドで hardware clock を読み込む。

```
$ hwclock --show
2020-12-02 20:53:32.887578+09:00
```

time zone を考慮された現在時刻がでてきた。localtime で表示される。

次に hardware clock を system clock に同期する。

```
# hwclock --systohc
```

これで hardware clock が調整された。
同時に`/etc/adjtime/`というファイルが更新される。

```
$ cat /etc/adjtime
0.000000 1606910322 0.000000
1606910322
UTC
```

このファイルの詳細は`hwclock(8)`の man ページの`The Adjtime File`というところに書いてある。
たった3行のファイルなのだが、その中に hardware clock が調整された最新の時刻が書かれている。これが更新されるようである。

# System clock

時刻、タイムゾーン、(必要な場合は) 夏時間をトラックする。
Linux カーネルによって、1970/1/1 00:00:00 からの秒数の数字で管理/計算されている。
初期値は hardware clock から計算され、起動後は hardware clock から独立して動く。

---

`timedatectl`コマンドで system clock を読み込む。

```
$ timedatectl status
               Local time: Wed 2020-12-02 21:23:19 JST
           Universal time: Wed 2020-12-02 12:23:19 UTC
                 RTC time: Wed 2020-12-02 12:23:19    
                Time zone: Asia/Tokyo (JST, +0900)    
System clock synchronized: no                         
              NTP service: inactive                   
          RTC in local TZ: no
```

色々でてきたが比較的読みやすい。
RTC は real-time clock の略であり、つまり hardware clock。
`RTC in local TZ: no`はそのまま、hardware clock が local time zone を使っておらず、UTC 時間ということだろう。

# Time standard (時刻標準?)

2つの time standard がある。
UTC と localtime。

hardware clock がどちらの standard を使うかは OS が決定する。
例えば、デフォルトでは Windows は localtime を使い、macOS は UTC を使う。
だから複数の OS がPCに入ってた場合、コンフリクトが起こることがあるのだそう。こわい。

# Time zone

システム全体の local time の time zone は、`/etc/localtime`ファイルが定義している。
このファイルは`/usr/share/zoneinfo/XXX/XXX`ファイルのシンボリックリンクで、例えば`Asia/Tokyo`の time zone を使用する場合は、下記のように設定する。

```
$ ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
```

なお下記のようなコマンドを使っても自動で time zone を設定できる。
実行される内容は上と同じ。

```
$ timedatectl set-timezone Asia/Tokyo
```

# Time skew (時間のずれ)

完全に正確な時計というものはない。電子時計は一貫した不正確さを維持する。
この不正確さを time skew とか time drift と呼ぶ。

hardware clock に新しく時間が設定されると、drift 値が`/etc/adjtime`ファイルに書き込まれる。
1行目1番目の値が drift rate。

```
$ cat /etc/adjtime
0.000000 1606920696 0.000000
1606920696
UTC
```

この値は以下の要素から計算される。

- 前回の hardware clock 設定時刻 (`/etc/adjtime`の1行目2番目の数字)
- 前回設定時の drift rate
- 新しく設定される time value と、そのときに hardware clock が保持していた time value の差異

この drift rate を保持しておくことで`hwclock --adjust`コマンドで hardware clock を正確に調節できる。
また`hwclock`デーモンが動いている場合は、シャットダウン時に同じことが実行される。

もしこの drift value が大きい値になった場合、なにか想定外のことが起きている。
例えば、不正確な時間を hardware clock に設定してしまったり、または time standard の同期がおかしかったりする。

# おわり

コンピューターの時間制御の基本について理解できたかも。

なおこの記事のほとんどは、参照欄に載せた Arch wiki による。
とてもすばらしい wiki だと思う。

なにか間違ったことを書いていたら指摘していただけるとありがたいです。

# 参照

Arch wiki
https://wiki.archlinux.org/index.php/System_time

man ページたち

- hwclock(8)
- timedatectl(1)
- localtime(5)
【Rails】備忘録：戻るボタンを実装する方法:複数ページの場合



## railsで「前のページに戻る」ボタンを実装する方法

戻るボタンの一番ベターな方法が、以下の処理です。

```
= link_to '戻る', :back
```
ボタンで実装する際は、erbの場合例えば

```erb
<%= link_to :back do %>
  <button>戻る</button>
<% end %>
```

hamlで書くと

```haml
= link_to :back do
  %button 戻る
```
とするといいようです。

しかし、これでは３ページ以上ある場合、そのうちの最後から2ページしか遷移しなくなります。
（無限ループ状態・・・）

## railsで「複数のページ（元辿ってきたページ）に戻る」ボタンを実装する方法

そのため、無限ループ状態にならないように

```
= link_to '戻る', 'javascript:history.back()'
```
という処理を書いていきます。

:historyとあるようにこれは”元辿ってきた過去の”ページから戻るイメージです。

では同じようにerbで実装する際は

```erb
<%= link_to 'javascript:history.back()' do %>
  <button>戻る</button>
<% end %>
```

hamlで書くと

```haml
= link_to 'javascript:history.back()' do
  %button 戻る
```

とするといいかと思います。

教材での学習において前者の単に戻るボタンの実装しかなかったので
疑問に思い、stackoverflowでリサーチをして備忘録的にまとめました。

おかしな点があればご教授いただけると幸いでございます。
【Docker】Dockerとは

# Dockerとは
- コンテナ型の仮想化サービス
- あたかも別のマシンがOS上に動いているかのように動かすことが可能  
　　コンテナはプロセスやユーザ等をサーバごとに隔離するため

# 構成
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924380/9d80886e-4f92-e3e2-0c34-7574747f9559.png)

## Dockerイメージ
- コンテナを立ち上げるために必要な設定やコマンドをまとめたテンプレート
- Dockerイメージを使えば以下の作業を省略できる
  - ソフトウェアをインストールする
  - 初期設定を行う
  - 詳細設定をカスタマイズする

## コンテナ
- Dockerイメージをもとにつくられた仮想環境  
　　WebサーバやDBサーバ等が動く環境

## Dockerサーバ
- コンテナとDockerイメージを管理するサーバ

## Dockerクライアント
- 利用者がDockerを使用するために操作するコマンドやツール群

## Dockerレジストリ
- Dockerイメージを公開・共有する
- レジストリ内には公開したいイメージ（NginxやNode.js等）のカテゴリごとに「リポジトリ」がある  
　　イメージはリポジトリに登録される
- 利用者はコンテナからDockerレジストリにアクセスし、イメージをダウンロードする
- サーバやDBの設定をあまり気にせず、ソフトウェアを使ったシステムの構築が可能となる
- Docker社公式のレジストリはDockerHub

# 特徴
## システム導入の高速化
- システムを構築するために必要となる最低限のプログラムのみのインストールで良い  
　　OSはすでに共有して利用しているため、それらの設定を省略できる

## 起動時間の短縮化と多くの処理実装が可能
- サーバの起動時間を短縮化できる  
　　OSを複数のサーバが共通して利用しており、OSが既に立ち上がっているため
- 1度に多くのプログラム処理の実装が可能  
　　リソースの使用量が少なく、サーバへの負荷が低いため

## コンテナ設定の再利用が可能
- 1度作成したコンテナはDockerイメージを作成し、他のコンテナへ適用することで再利用が可能

# 参考
- [Dockerとは何かを入門者向けに解説！基本コマンドも](https://udemy.benesse.co.jp/development/system/docker.html)
- [さわって理解する Docker 入門](https://www.ogis-ri.co.jp/otc/hiroba/technical/docker/part3.html)
読書会「プログラマが知るべき97のこと」 #8

# 1．今回の読んだ記事
No.86　[WETなシステムはボトルネックが見つかりにくい](https://xn--97-273ae6a4irb6e2hsoiozc2g4b8082p.com/%E3%82%A8%E3%83%83%E3%82%BB%E3%82%A4/WET%E3%81%AA%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AF%E3%83%9C%E3%83%88%E3%83%AB%E3%83%8D%E3%83%83%E3%82%AF%E3%81%8C%E8%A6%8B%E3%81%A4%E3%81%8B%E3%82%8A%E3%81%AB%E3%81%8F%E3%81%84/)　
著者: Kirk Pepperdine

# 2．記事の概要
**DRY（Don't Repeat Yourself：同じことを繰り返すな）原則**
**アンチパターン：WET（Write Every Time：必要なものをその都度書く）**

+ WETになりがちなパターン
    + 例えば、xのリストのなかから、yなものを探す等の処理、各々が毎回実装してしまいWETになりがち
+ 対象領域（ドメイン）の状況に適合した設計をしよう！

# 3．この記事を選んだ理由・感想
**理由**
設計について、意識してることについて議論したかった

# 4．議論
**よい設計（DRYで可読性が高く変更が容易等）をするために気を付けていること**

  - 変更も容易に加えることができて、拡張性があるように設計できたらよいと思っている
    - ただ時間が経ったり、想定外の要求があってそのとき考えた方針とは違う方向に行ってしまう場合もあって、結果うまくいかないときもある
  - 共通化できるところは、なるべく共通化するようにする
    - 同意見多数


**設計のアンチパターンについて（自身の経験や想定しうるもの）**

- 以降の改修を見据えて、処理を共通化するように設計・実装したが結果あまり意味がなかったりした
    - 想定の仕様や要件ではなくなったので、せっかく共通化したが意味がなかった
- アンチパターン？というか悪い設計・実装になっていることにあとから気づいて文句を言ったことがある
    - 実装の指針があったのにその通りではなかった
- 似ている処理だが少しだけ違う場合はどうするか悩む
    - 共通化はしたいがどこまで共通化するか難しい？
- 単体試験などがしにくいのはよくないので、試験も見据えて設計を気を付ける
- （あるチームは）ドメイン駆動の設計をやったと思うがよかったか？
    - あまり使われないシステムなので効果が測れていない

**DRY（Don't Repeat Yourself）は前回のエッセイでも出てきた**

- DRY、重要なので意識しましょう！



# まとめ
弊社もコロナ禍により、在宅勤務となりまして会議は基本オンラインで行っている。今回は「オンライン + 飲み会」で開催してみた。
終わった後は、本格飲み会へ移行して懇親会を行った。
オンラインだと、話す人が決まってしまうということがあるが、「読書会」という議題があることと議長による指名があったので一通りみんな発言して議論ができたかなと思う。飲み会（アルコールあり）ということで議事が少なめですみません。
次回に続く。
flutter_blocを使ってみる その3

[flutter_blocのExample](https://pub.dev/packages/flutter_bloc/example)の説明の続きです。「+」「-」ボタンを押した際に使われるBLoCのコードを解説します。

# BLoCの説明
「+」「-」ボタンを押すと中央の数値が増減しますが、これは`CounterBloc`を使っています。

## 動作の説明
- ユーザーがボタンを押す等の作業により、UIが**BLoCにEventを送る**。
- 呼び出されたBLoCのメソッドがStateを変更して、その変更を通知する。
- 新しいStateを通知として受け取ったUIが再描画する。

Cubitと異なるのはUIがメソッドを呼び出すのではなく、Eventを送ることです。通常Eventは複数種類あり、その中のひとつを送ります。
今回のExampleでは「+」ボタンを押すと `CounterEvent.increment`、「-」を押すと`CounterEvent.decrement`を送ります。このExampleでは`CounterEvent`は`enum`になっています。


## BLoCの中身の動作の説明
- int型初期値0の`State`を持ちます。
- UIから受け取ったイベントに応じて`mapEventToState()`メソッドが`State`を変更して通知します。

# コードの説明
BLoCのコードはこのようになっています。

```dart
// Eventをenumで定義、incrementとdecrementの２つを持つ。
enum CounterEvent {
  increment,
  decrement
}

class CounterBloc extends Bloc<CounterEvent, int> {
  // 初期値を0に設定する
  CounterBloc() : super(0);

  @override
  Stream<int> mapEventToState(CounterEvent event) async* {
    // Eventの種類によってStateを変更して通知する
    switch (event) {
      case CounterEvent.decrement:
        yield state - 1;
        break;
      case CounterEvent.increment:
        yield state + 1;
        break;
      default:
        addError(Exception('unsupported event'));
    }
  }
}
```

UIのコードの抜粋です。

```dart
class CounterPage extends StatelessWidget {
// ...省略
// Stateを受け取って再描画する。
body: BlocBuilder<CounterBloc, int>(
  builder: (_, count) {
    return Center(
      child: Text('$count', style: Theme.of(context).textTheme.headline1),
    );
  },
),
// ...省略
// FloatingActionButtonを押すとCounterEvent.increment(or decrement)が送られる
FloatingActionButton(
  child: const Icon(Icons.add),
  onPressed: () => context.read<CounterBloc>().add(CounterEvent.increment),
),
//...省略
```

## もう少し詳しい説明
`flutter_bloc`にてBLoCはEventのStreamを受け取り、StateのStreamを通知(broadcast)します。コードをみると `mapEventToState()` メソッドがStreamを受け取りStreamを返していることがわかると思います。
これは例えばデータ取得の際に、まず`LoadingState`、次に取得結果に応じて`SuccessState`または`ErrorState`を通知するというように、**複数のStateを順次通知するような挙動**を前提としています。

コードで書くと以下のようになります。Loading中はViewにスピナーを表示しておいて、データが取得できたらリストを表示する、というようなことができますね。

```dart
if (event is FetchData) {
  yield LoadingState();
  try {
    final data = await repository.getData();
    yield SuccessState(data);
  } catch (error) {
    yield ErrorState(error);
  }
}
```

# BLoCとCubitとの違い
これまでにBLoCとCubitの挙動を説明したので、両者の違いも説明できるかなと思います。

- BLoCは複数種別のEventを受け取ることができるが、Cubitは複数種別を扱えない
    - ExampleではCubitはColorThemeの切り替えのみ、BLoCは数値のインクリメント、デクリメントの2種類のイベントを使っている
- BLoCは連続したEventをStreamで受け取り都度StateをStreamで返すが、CubitはひとつのEventを処理する
    - BLoCの`mapEventToState()`はStream型のメソッドだが、Cubitの`emit()`はvoidとなっている


こんな感じで使い分けるといいと思います。