OmniAICreator/Qiita-1.07M huggingface dataset:
WebサービスのQA立ち上げ時の留意点

# この記事について
 - **対象：WebサービスのQA担当者**
 - **概要：WebサービスのQA立ち上げ時における留意点**
 - **読了までにかかる時間：3分**

# テーマ選定の背景
複数のWebサービスの初期段階のQAを担当した結果
(当然ですが)運用QAにはない留意点が共通して存在したのでメモとしてまとめようと思います。

あくまで経験に基づくものなので網羅性などはなく
こういうものもあるのかという意識で読んでください。


# 留意点メモ
### テスト開始前
#### 数段階に分けたテスト計画の提案が必要になる
立ち上げ時はリソースの制約が厳しく、特に費用に関しては厳しくみられるケースが多いです。
そのため全ての機能を組み合わせまで考慮してテストを実現することは困難です。

そこであらかじめQAの方で数パターンの検証方針を検討しておくことで
QAとして譲れない部分は必ずテストに組み込むストーリーを作ることが重要です。
(そしてだいたい最少工数のパターンが選択されます)

#### QA側での仕様書管理が求められる
私の現場では仕様書がないことも多く、
あったとしても更新が反映されておらず実装と合致していないことも散見されました。

また更新している場合でも、QAに連携のないサイレント修正が頻発し
仕様書を基に作成したテストケースが実装とそぐわないものになることもありました。

その対策としてQA側で毎朝仕様書の更新状態を確認するという体制を構築しました。
QA側が行う作業として本来は過剰なように思いますが
時間的リソースも限られる場合は初期フェーズのみという制約付きで巻き取る場合が多いです。

#### 開発⇔QAの連携体制が必須である
「QA側での仕様書管理が求められる」にも関連しますが当初よりQA側で行う作業が増える場合があります。
そういった場合、多くは開発側から見えづらいため
理由なくQA側の進捗が遅いと映ってしまう可能性があります。

このような認識齟齬を解消するため朝会による状況報告会を実施しました。
認識齟齬が発生したときの手戻りを考えると工数的に多少無理をしてでも行ったほうが良いと思います。


### テスト設計時
#### テストケースに落とし込みづらいバグが多い
アプリゲームのような動的なテスト対象ではないものの
初期段階となるとテストケースに落とし込みづらい項目でのバグが散見されます。

そのため一定の能力/経験を持ったテスターをアサインするか
テストケース作成にかなりの工数を割く必要があります。
私がテストケース作成を担当した際は全工程で一番テストケース作成に時間をかけた覚えがあります。

参考までにテストケースに起こしづらい項目でのバグを記載します。

- サービス内の広告ごとに文字/画像/アイコンの大きさが微妙に異なる
- 一部機能の読み込みが他より若干時間がかかる
- 特定の繊維方法の場合に画面が真っ白になる(確率で発生)
- タップしたハイライトがページ箇所によって異なる

# 感想
まとめようと思った背景として自身の気の緩みがあります。
定常の業務としてゲームのQAを担当しているため
静的なテスト対象であるWebサービスはゲームより検証は楽だろうという心構えで臨んだ結果
想定よりもかなり工数がかかってしまったという過去があります。

もちろん新規だから大変だったというのもありつつ
Webだからこそ細かい修正が頻発したという特性もあると思うので
今後WebサービスのQAを担当する方の参考になれば幸いです。
electronアプリから初期メニューを消す方法

Webサイトを開く単純なサンプルアプリをつくっていて、初期メニューを消す方法を探していたが正解までのノイズが多くて手間取ったので。

```console:electronのバージョン
> "./node_modules/.bin/electron" -v
 v7.1.4
```

## BrowserWindowに対して色々やるのは :no_good: 

ググって出てくるメソッドはどれも古いようでした。

```js:以下、効果のないメソッド
// winはBrowserWindowのインスタンス
win.setMenu(null);
win.setMenuBarVisibility(false);
win.removeMenu();
```

## `Menu.setApplicationMenu(false)` :ok_woman: 

electronは流れが早いのか、破壊的な変更が多いのかはよく知らないのですが、公式docsがイチバン（[Menu \| Electron](https://electronjs.org/docs/api/menu#menusetapplicationmenumenu)）だというのはよくわかりました。

```js:メニューなしでGoogleをひらくサンプル
const { app, BrowserWindow, Menu } = require("electron");

Menu.setApplicationMenu(false);

app.on("ready", () => {
    let win = new BrowserWindow({ width: 800, height: 600 });

    win.on("closed", () => {
        win = null;
    });

    win.loadURL("https://google.com");
});
```


## 余談

- [globalShortcut](https://electronjs.org/docs/api/global-shortcut)がアプリがアクティブじゃなくてもキーボードをフックしててすごい（こわい）
    - localShortcutを使うと良いらしいです。
    - [Electronアプリは、まずelectron\-localshortcut入れて、Command\+R、Command\+Wを潰すのがセオリーだと思う \- サイト更新停滞ちうっ](https://taku-o.hatenablog.jp/entry/20181020/1540026153)
    - ちなみに、使えるキーの一覧（[Accelerator \| Electron](https://electronjs.org/docs/api/accelerator)）
- `win.loadUrl`が動かない→`win.loadURL`でプチハマり
- `main.js`なの？`index.js`なの？
僕と上司と1on1

# はじめに
現職に転職して1年、最近流行？の1on1を初めて1年経過しました。
コミュニケーション積極的に取りたいマンとしては個人的にアツい手法だと思っているので、是非広まればいいな。

# なに話してるの？
週に1回30分、上司と1on1してます。
内容は「最近どう？」。

実は困ってることとか、こっそり頑張ってることとか、そういえば今週飲み会めっちゃありますね、とかなんでも話してよくて、そこから今後どうしていくかの方向に流れていきます。

ちなみに自分は週一ですが、ほかのチームメンバーは隔週らしいです。
その辺は自分が細かく見てほしいのか、隔週ペースくらいで様子うかがって欲しいのかで決めたらいいと思います。

# 1on1やってみてどう？
1on1広まれ広まれ。
流行れ流行れ。

転職後1年ちょっとで上司は3人目ですが(笑)、がっつり一緒に仕事することはないので、上司を知る上でも、上司に知ってもらう上でも貴重な場です。

ちなみに今回のタイトルでは上司って書いてますが、他チームの人と1on1もしてます。
オフィス全員と話してみたい！っていう企画の人とか、ストレングスファインダーのコーチ資格持ってる方と自身の強みについて話したり。

あと社会人あるあるだと思ってるんですが、他部署の人との心の距離めちゃくちゃ遠い感。
些細なことを聞くのにも「XXのXXと申します。」から始まるメールを送ったり。

個人的にはそういうの「ち～っす。ちょっと教えてくださいな。」くらいのラフさでたくさんやりとりを重ねたい派なので、1on1であらゆる人と顔見知りになればいいと思う。

# まとめ
1on1やったことない人にはぜひやってほしいです。
コミュニケーションお化けの方よりは、複数人だと会話に入っていけない内気なエンジニアにオススメ。
archのViewModelProvider(s)から卒業するには

過去のrepositoryでarchのViewModelProvider(s)がdeprecatedになっていることに気づいたのでどうしたものかと思い、備忘録も兼ねてまとめることにする


## archのViewModelProvider(s)はもうメンテされないYO

> The android.arch Architecture Components packages are no longer maintained. They have been superseded by the corresponding androidx.* packages. See androidx.lifecycle.ViewModelProviders instead.

引用元
[arch ViewModelProvider](https://developer.android.com/reference/android/arch/lifecycle/ViewModelProvider)
[arch ViewModelProviders](https://developer.android.com/reference/android/arch/lifecycle/ViewModelProviders)

乗り換えるなら
`androidx.lifecycle.ViewModelProvider(s)`によろしくということですね

## androidx.lifecycle.ViewModelProviders

だがしかし
![スクリーンショット 2019-12-10 11.30.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260353/b96e095a-edc0-381a-9f20-d838add49de4.png)

<font color="red"><b>deprecated</b></font>なのね

かつViewModelProviderを直接使って呼び出せといっています

そのため、archの際に行っていたような
`ViewModelProviders.of(this, factory).get ...`
のような使い方は推奨されないということですね

引用・参照元
[lifecycle ViewModelProviders](https://developer.android.com/reference/androidx/lifecycle/ViewModelProviders.html)

## androidx.lifecycle.ViewModelProvider
そのため、こちらを使うのがお利口さんということになります

使い方としては直接ViewModelを指定していくので


### ViewModelの引数がない場合(AndroidViewModelの場合はapplicationのみの場合)

```HogeActivity.kt
private val hogeViewModel :HogeViewModel by lazy { ViewModelProvider.NewInstanceFactory().create(HogeViewModel::class.java) }
```

という形で呼び出すことができます

### 引数ありの場合
ただ、たいていViewModelに引数があるのでその場合は継承した独自のFactoryクラスを作ることになります
※今回はrepositoryがコンストラクタにあることを想定しています、何でも良いです　あくまで一例

```HogeFactory.kt
class HogeFactory(private val repo: HogeRepository) :
    ViewModelProvider.NewInstanceFactory() {

    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return HogeViewModel(repo) as T
    }
}
```

そして呼び出します

```kotlin
private val hogeViewModel: HogeViewModel by lazy { ViewModelProvider(this, HogeFactory(repo)).get(HogeViewModel::class.java) }
```

もしくは長いなと思う場合は、`activity-ktx`, `fragment-ktx`を導入すると

```build.gradle
def ktx_version = "1.1.0"
// fragment-ktx
implementation "androidx.fragment:fragment-ktx:$ktx_version"
```

このような書き方で済みます

```HogeActivity.kt
private val hogeViewModel: HogeViewModel by viewModels { HogeFactory(repo) }
```

引用・参照元
[lifecycle ViewModelProvider](https://developer.android.com/reference/androidx/lifecycle/ViewModelProvider.html)

# まとめ
* archからlifecycleのViewModelProvider(s)へ移行しよう
* lifecycleのViewModelProvidersはdeprecated

間違い点や他にもやり方がある場合はご教授ください🙏🙏🙏
grep で自身の検索プロセスを除外したい時

# Overview

```shell
$ ps aux | grep zsh
qiita   10548   0.6  0.0  4268056    808 s000  S+   11:43AM   0:00.00 grep zsh
qiita   1294   0.4  0.0  4334752   2896 s000  S    10:04AM   0:00.22 -zsh
```

grep で grep 自身のプロセスは無視して表示させたい時ありますよね。
そんな時に使える方法を2つ紹介します :thumbsup: 

# `grep -v` を使う

多分よく知られている方法。

```shell
$ ps aux | grep zsh | grep -v 'grep zsh'
qiita   1294   0.0  0.0  4334752   2896 s000  S    10:04AM   0:00.23 -zsh
```

もう一回パイプして `grep -v 'grep *'` で自身のプロセスを除外できます。

# `[](brackets)` を使う

`grep -v` でもいいんですが、もう一個パイプを挟んでいる関係で余計にプロセスをフォークしていることが気になったりしませんか？そんな時は `[](brackets)` を使いましょう。

```shell
$ ps aux | grep [z]sh
qiita   1294   0.3  0.0  4334752   2896 s000  S    10:04AM   0:00.24 -zsh
```

仕組みとしては `z 1文字 + sh` という条件で検索が実行されるが、grep に渡されている文字列は `[z]sh` なので `z 1文字 + sh` という条件には引っかからないので表示されませんよ、という話。
エレガントですね。
AWSにおけるデータベースの違いを整理しよう

#AWSで適切なデータベースを使おう
![db.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543591/d95d0e5d-67bf-0b67-1be0-12c387fb3256.jpeg)

おはようございます．

皆さんは要件によってDBの使い分け出来ていますか？

MySQLやpostgresのみしか使えないとなると，
最新の技術についていけません．

例えば，
「ユーザー検索の出来るアプリを作って欲しい」
と言われて無理やりSQLで書いていませんか？
構造の奥深い値を取るために，冗長なコードになってしまう可能性が非常に高いです．
その分，検索も遅くなります．

それなら，「NoSQLで用意されたメソッドで一発で取り出し」
なんかの方が遥かに効率的で，高性能です．

ということで，


今回はデータベースのお話です．
正直，私も全ては理解をしていなかったので，アウトプットにもなるので
わかりやすくまとめようと思います．

##AWSにおけるデータベース
DBごとに詳細を別リンクに書いています．
一言で表すならこんな感じ．
<a href="https://qiita.com/moyuta/items/88d5330e2e15f14f7db1">RDS</a> ... MySQL,postgresと互換性がある
<a href="https://qiita.com/moyuta/items/6c89e536d1d10766a012">DynamoDB</a> ... 非SQL．莫大なデータ量の格納が可能
<a href="https://qiita.com/moyuta/items/1dd2ece39eba5e91c656">ElasticCache</a> ... メモリをストレージとする超高速なアクセスが可能
<a href="https://qiita.com/moyuta/items/e124f8117c2e8b51da1a">Redshift</a> ... 複雑なSQLを並列に処理することが可能.分析専門のDB

##使用例
RDS ... アクセスが多いもの
DynamoDB ... 大量の検索や集計に適する
ElasticCache ... 高速で小さなデータを一時的に保存する
Redshift ... 大容量データを蓄積．データ分析によく使われる

最も適したDBを使いこなせるようにしましょう
ASP.NET MVC ベリーシンプル多言語対応【2019 アドカレ】

## 概要

ASP.NET MVC で多言語対応をこころみてみます。多言語対応だけシンプルにこころみます。

(2020-03-07)アップグレード版を書きました。

- [ASP.NET MVC ベリーシンプル多言語対応2020](https://qiita.com/yuu-eguci/items/40f171dff0f8c2cb4748)

## ベリーシンプル多言語対応

1. 各言語リソースファイル作成
1. http リクエストの `Accept-Language` に応じて言語を切り替えるよう設定

これだけやります。

## 今回やることを図にして整理

図にするとこうですね。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270842/be0d2c2c-83da-6dcc-5850-2b5b61076aa5.png)

解説していきます。

## 今回使うプロジェクト

今回使うプロジェクトは次のように New しました。

- ASP.NET Web Application (.NET Framework)
- .NET Framework 4.7.2
- MVC
- Authentication: No Authentication

## 各言語リソースファイル作成

リソースファイルは拡張子 resx のファイルですね。多言語対応のためのリソースファイルは xxxx.[culture name].resx という名称でつくります。デフォルトの言語リソースと、多言語のリソースは同じ階層に並べましょう。リソースファイルのアクセス修飾子は忘れず `Public` にします。

- Localize.resx: デフォルトで使うもの
- Localize.ja.resx: ja カルチャで使うもの
- Localize.en.resx: en カルチャで使うもの

**場所は?**

場所はどこでもよさそうです。私は Resource/I18n/Foo/Localize.resx みたいなフォルダ階層をつくって置きます。 I18n は internationalization の略です。

**カルチャ?**

カルチャというのは、 http リクエストヘッダ `Accept-Language` の値のことみたいです。サイトの閲覧者さんが、何語を求めているかということですね。

**resx なくない?**

ないですね。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270842/71d83aed-9b8f-e453-142f-85d4b4f623f6.png)

ないときもあるみたいです。そういうときはリストにとらわれず resx の拡張子を手打ちしてファイルを作成すれば OK です。(えぇー?!
あるいはすでにある resx ファイルをどこかから見つけてきて、 Add Existing Item から追加することもできます。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270842/4f9023e6-b053-70db-474b-5779b9b53a38.png)

**リソースに書いたテキストを使うには?**

`String1` というテキストを用意したなら……

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270842/892380d3-76c5-270a-3a81-662820804cd1.png)

こういうふうに呼び出します。

```html:Views/Home/Index.cshtml
@MyApp.Resources.I18n.Foo.Localize.String1
```

実はこの時点で `CurrentUICulture` の値に応じた言語スイッチが可能になっています。 `CurrentUICulture` というのは `System.Threading.Thread.CurrentThread.CurrentUICulture` のことで、上述したカルチャの情報を設定する項目みたいですね。値を `en-GB` とかにすると Localize.en.resx の `String1` が呼び出されます。

```csharp:Controllers/HomeController.cs
// CurrentUICulture の変更。
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-GB");
```

プログラム内で言語を切り替えるだけでよいのならここでおしまいです。

## Accept-Language に応じた言語切り替え

トップディレクトリの Web.config の `system.web` タグ内に `<globalization culture="auto" uiCulture="auto" />` を記述します。

```xml:Web.config
<system.web>
  <compilation debug="true" targetFramework="4.7.2" />
  <httpRuntime targetFramework="4.7.2" />
  <globalization culture="auto" uiCulture="auto" />  <!-- 追加 -->
</system.web>
```

リクエスト・ヘッダの `Accept-Language` に応じて、自動で `CurrentUICulture` が変わるようになります。ということはつまり、 `Accept-Language` に応じて言語が切り替わるようになるってことですね。

**Accept-Language はどう変更する?**

- Chrome: メニュー > 設定 > 詳細設定 > 言語
- Firefox: メニュー > オプション > 言語

毎回ブラウザの再起動が必要になってしまうので、ふたつ開いてそれぞれでアクセスして確認するとラクでした。
はじめての開発

はじめまして！
CODEBASE４期生のおおしろたかこです。
現在、東京の会社でエンジニアとして働いております。
先日、初めて自社内のサービス開発して気づいたことや学んだことをまとめました！


## 企画・設計の重要性
当たり前かもしれないのですが、開発において何よりも重要だと感じました。

そもそも、企画の段階ですごくつまりました:joy:
最低限過ぎますがこれくらいのことはしないと何も進められないと思いました。

- どういう目的で、誰に向けたサービスなのかを明確にすること
- その後具体的に必要な機能を洗い出し最低限必要なものを選択していくこと
- 画面遷移の重要さ
- データの保存方法


何をどこからやっていいのかわからず、ビジネスサイドの方に手伝っていただきながら、画面設計まで落とし込みましたが、これが意外と時間がかかってしまいました。

そして、テーブル設計のあと、開発を進めていく中で、ちょっとした認識のズレで一部設計の変更が出てしまい、リリースが遅れてしまいました。

今回、マッチングアプリを作ったのですが、マッチングした際のデータの保存に関してまちがった設計をしてしまってました。
エンジニアとして気づけなかったことが原因です。

ミスに気づいたときはリリース予定約3日前。
もう、絶望。むりだあああああああああああって発狂してました:joy::joy:
上司の方がサポートしてくれてなんとかリリースできました…
ホント感謝しかないです:bow::bow:

ビジネスサイドの方は基本的に設計などに関しての知識がないので
矛盾がある際にはエンジニアが気づくべきなんだなと今回勉強になりました。
（よくある話らしいですが、初体験すぎて泣きそうでした)
今後の機能追加の際にあらゆる角度からしっかり話を詰めて、開発に移りたいと思いました。

## 現実の複雑さ

技術不足を痛いほど感じました。
登場人物が少し増えるだけで、認証の方法やルーティングの設計、テーブルの関係性が現実はこんなにも複雑なのかと思いました…

何度心が折れそうになったことか…笑
ここはhas_manyだからあああああ
ネストおおおおおおおおおお
って何度もなってました:joy::joy:


ですが、今までの学習が役に立ったこともたくさんありました！！
フォローやフォロワーの関係性を理解しておくことや認証の仕組みの理解、アクティブレコードの操作などなど、基礎を理解していれば実装できるものもたくさんあるなと思いました。
また、エンジニアはたくさんの事例を知っていて、少しでもやったことがあることを増やして、引き出しを作っておくことは大事だなと思います。

ゼロと１では全然理解とスピードが違うと思います。
もっといろんなことにチャレンジしていきたいです:sparkles::sparkles:

## 周りの人に感謝

上司の方に技術不足の部分をじっくり見守りながらヒントを沢山出していただいたり、
ビジネスサイドの方は、もっと増やしたかった機能を厳選に厳選を重ねて調整していただいたり
デザイナーさんにLP画面をものすごくかっこよくしていただいたり、
是非利用したいですと言ってくれるユーザーさんがいたり、
様々な方が関わってサービスはできているんだなと改めて感じました。

ほんとうに何もできない私に、ゼロから作ることをやらせていただける環境に巡り合えたことに本当に感謝でいっぱいです。
今後も精進していき、サービスに貢献していきたいです！


## おわりに
とにかく、技術不足すぎて追い込まれまくってた１ヶ月半でした:joy::joy:
本当に無力すぎる自分と時間がどんどん進んでいくことが怖かったです。笑
サービスに貢献できていなさすぎる自分に本当に申し訳ない気持ちでいっぱいでした。
上司の方がいなければ絶対にリリースできなかった…
でも、本当に貴重な経験ができました！！！！
目の前でユーザーさんに登録いただいたときはちょっぴり泣きそうでした。笑
そして、もっとサービスを使っていただくためにより良いものにしていきたいです！！
Railsの enumとjoins selectでハマった件


## 要点

- joinsで内部結合してselectしたデータを、enumで比較しようとしてハマった
  - 内部結合してselectした際、**基準となるテーブル以外**のテーブルは、enum定義されててもデータベースに登録されている素の値が出る模様


## 確認した環境
- Ruby 2.5.5
- Rails 5.2.3
- MariaDB 10.4.8

## 例

```ruby:app/models/company.rb
class Company < ApplicationRecord
  has_many :offices
end
```

```ruby:app/models/office.rb
class Office < ApplicationRecord
  belongs_to :company
  has_many :employees
end
```

``` ruby:app/models/employee.rb
class Employee < ApplicationRecord
  belongs_to :office

  enum type: {
   regular: 0, # 正社員
   contract: 1, # 契約社員
   temporary: 2, #派遣
  }

```

※実際に上のモデルで動作確認してないので、挙動異なったらすみません。


## 起きた問題
「A社の社員に関して、社員の契約形態ごとの情報を扱いたいやで。あ、オフィスの付属情報もほしいから、selectして頼むわ」

ほんほん、なるほどな〜〜

``` ruby
office_employees = Company.find_by(name: "A")
  .offices.joins(:employees)
  .select("offices.*, employees.name, employees.type")
```

「eachしてtypeごとにif文書いてくれやで」

おう、こうやろ？

``` ruby
office_employees.each do |employee|
  if employee.regular?
    ...
  elsif ...
  end
end
```

ん、regular?はあかんのか、じゃあこうか。

``` ruby
office_employees.each do |employee|
  if employee.type == 'regular'
    ...
  elsif ...
  end
end
```

んん……全部elseに入ってしまう……。
ちょっとpryで止めて見てみるか……。


```
pry(main)> employees.first.type 
=> 0
```
enumの文字列じゃなくてDBの数字そのまま返ってくるやんけ！

## 動作確認

```
pry(main)> Employee.first.type
=> 'regular'

pry(main)> employees.first.type 
=> 0
```

直接呼び出した場合はenum定義した文字列で返ってくるが、関連テーブルのjoins select経由の場合はデータベースに入っている数字がそのまま返ってくる。
ちなみに基準となるテーブル（この例の場合Office）のenumは、selectしていてもそのままenumで扱える模様。

## Railsガイド、RailsAPIを読む
ふわっとした認識で使ってたこれらのメソッドに関してリファレンスをちゃんと読んでみる。

### enum
enumマクロは整数のカラムを、設定可能な値の集合にマッピングする。
対応するスコープ、及び状態の遷移や現在の状態の問い合わせ用のメソッドが自動で追加される。

```ruby

enum status: [:active, :archived]
```

のように配列形式で指定した場合は、配列のindexが数値として設定される。
そのため、配列の順序を維持することが必須で、新規追加する場合は配列の最後に追加すること。
ハッシュで明示的にマッピングすることが推奨される。（今回の例の場合はそうしてる）

### select

selectメソッドを使うと、関連付けられたオブジェクトのデータ取り出しに使われるSQLのSELECT句を上書きする。Railsはデフォルトではすべてのカラムを取り出す。
配列を返すように見えるが、実際はリレーションオブジェクトを返している。

メソッドの引数は、フィールドの配列にすることもできる。文字列を使用した場合は、変更されずにSELECTフィールドとして使用される。

```
pry(main)> employees.class
=> Office::ActiveRecord_AssociationRelation

pry(main)> employees.first.class
=> Office(id: integer, ......)
```

恐らくこのリレーションオブジェクトが結合元のモデルを基準にして結合したものなので、その結合元のモデルに定義のないenumはDBの値そのまま出す形なのだろう。
enumの定義のないモデルにenumで呼びかけている、って考えたらまぁ当たり前なのかもしれないが、何も考えないで使っているとハマる……（普段はenum意識せずに文字列として使ってる場合もままあるので）。


## 対応

```ruby

office_employees.each do |employee|
  if employee.type == Employee.types["regular"]
    ...
  elsif ...
  end
end
```
Employee.types["regular"]の返り値はenum定義した数値なので、上記例の場合はこれで対応可能。
便利なものだからとAPIとかあんま読まずに雰囲気で使ってるとだめですねー。

## 余談
後で知ったが上記例の場合、selectでなくpluckを使うほうが、リレーションオブジェクトを作らないため速くなるし安全な模様。
pluckにsql書く発想がなかった。
チャットボット運用者が紹介するチャットコマースの面白さ

##はじめに
こんにちは！株式会社ZEALSのみっちーと言います。
みなさんチャットコマースって知ってますか～？:raising_hand:

2019年はチャットコマース元年と呼ばれるように、チャットコマース界隈はかなり盛り上がりました。
ですが、まだ新興サービスがゆえに、「チャットコマース」でググっても、その運用に関しての情報はほとんどありません。
そこで本稿では**チャットボット運用して知った、マーケター目線でのチャットコマースの面白さ**をお伝えしたいと思います:open_hands:

[チャットコマースってなんぞ？の方のための参考](https://lp.fanp.me/blog/chat_commerce_ec_site_trend/
)


##ここが面白いぞ！チャットコマース

###その1：行動、インサイトが具体的に分る
チャットコマースでは、下図のようにユーザーは基本的に「選択肢を選ぶ」「テキストを入力する」というアクションによって、チャットボットと対話をします。
質問内容によっては具体的なユーザーインサイトが分かりますし、ボット内で何をしたかも詳細に分ります。
そのため、かなり精度の高いパーソナライズ体験をユーザーに届けることが可能です。
![advent.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540273/17b65969-e06b-3f73-a30a-b5f37fb117f7.png)


大体のWeb施策は大部分が「想定」の上に成り立っていると思います。
想定を重ねて施策を考え、ABテストを実施して何が正解だったのかを探っていく流れが、一般的ですよね。
パーソナライズ体験を提供できるMAツールですら、スコアリングは「多分このページを見てるからこのはず」と想定の域を出ません。

チャットコマースでは違います。
**分からんことはユーザーに聞けばいいんです。**
何に困っているのか？何に興味があるのか？なぜ買わないのか？
前職でWebマーケをしていた時に喉から手が出るほど欲しかったユーザーの定性的な情報が、いとも簡単に取得できるので笑いが止まりません。（実際は笑っていません）

###その2：自分だけで高速改善・検証
チャットボットなので、修正・改善は基本的にはテキストを変えるだけです。
また、その１でお伝えしたようにユーザー行動やインサイトも具体的に取得できるので、改善施策の精度も上げやすいため、PDCAをかなり早いサイクルで回すことが可能です。

コーディングも必要なく、デザインも難しいものは必要がないので、コミュニケーション設計さえできれば
自分1人で面白いくらい多くの施策を回すことが出来ます。
チャットコマースはまだまだ**勝ちパターンが分からないので、それを自分で探っていく**のも面白さの一つです。

###その3：ユーザーファーストのパーソナライズコミュニケーションができる
チャットコマースでは流入→CVへの誘導→CV後のコミュニケーションまでを一貫してチャットで行います。
また、CVしなかったユーザーにもプッシュ会話で接点を持つこともできます。

そしてこれら全てに、**パーソナライズしたコミュニケーション**が提供可能です。
まさにその人に合ったコミュニケーションを取り続けることが出来るんです。

ユーザーインサイトが分からないので、同じコンテンツのメルマガ一括送信、結果、メールリストがどんどん減って真顔になる、という状況もチャットコマースではなかなかありません。
常にユーザーファーストで考えることが出来ますし、またそれを実現することが出来ます。

###その4：CVが生々しい
チャットコマースの会話体験設計から、会話作成までは基本一人で行います。
そのため、ユーザーがの行動が思った通りに行ってCVなんかすると脳汁がドバドバでます。
商談で、こっちの発した言葉で思ったように相手の温度感が上がり、成約に至ったみたいな...そんな経験ほとんどないのですが...そんな感じです。


##最後に
まだまだチャットコマースの面白いところはたくさんありますが、今回はこの辺で。
既存のマーケティングに面白みを感じなくなってきたら、ぜひ一度チャットコマースを触ってみてくださいね:ok_hand:

具体的にはどんなUXがあるのか？については@morimi0430 が書いてくれているので、興味があればぜひこちらもどうぞ！
[LINEのチャットボットでできるUXデザイン](https://qiita.com/morimi0430/items/0fcf6e75cbca61e5103d)
OFFICE 文字の前後にキーワードを自動入力

まず、CSVはOFFICEで見るためにUTF-8かShift-JISにしないと文字化けする。


#文字の前にキーワードを自動入力したい


B2の文字の前にお菓子とつけたい。

=B2"お菓子"&

これで、B２の文字の前にお菓子と付く。


#文字の後にキーワードを自動入力したい


ユーザー定義を使用
LibreOfficeの場合
タブの書式→セル→ユーザー定義


B2の文字の後に様とつけたい。
ユーザー定義画面で

@"様"

と入力すれば自動的に様と付く。
Chatworkの「チーム機能」が便利。使ってみよう、と思ったら。。。

新規ユーザが参画した場合やプロジェクト異動があった際の
必要なグループチャットへの各種追加って手間だなーと思ってました。

すると「**チーム機能**」なるものを発見しました。
2017年12月から開始されています。


## チーム機能とは？

> 今回リリースした「チーム機能」では、ユーザーをチームごとに管理することができるようになります。今までは「ユーザーリスト」で全ユーザーを管理する必要がありましたが、「チーム機能」を使うことで今後は部署やチームごとにユーザー情報を確認することができます。

## よし使ってみよう、と思ったら。。。

これは求めてた機能だ！
と思ったら二つ懸念が

- 組織管理者/ユーザー管理者

のみがチーム作成・チームのユーザ追加/編集/削除の権限があるとのこと。

- 「ビジネス」と「エンタープライズ」プランのChatworkが対象

とのこと。

該当してなかった。残念。



ここを満たしている方はとても便利そうなのでグループ管理が楽になるといいですね。

## 参照
https://blog-ja.chatwork.com/2017/12/blog-post.team.html
サービスに登録したMySQLが停止しなくなったときの対応方法

- 環境
    - Windows 10 Pro 64bit
    - MySQL 5.6.19 (GPL)


# 事象 : MySQLをサービスに登録して起動したら止まらなくなった
- 経緯1 : MySQLをサービスに登録して起動した
    - [MySQL :: MySQL 5.6 リファレンスマニュアル :: 4.3.1 mysqld — MySQL サーバー](https://dev.mysql.com/doc/refman/5.6/ja/mysqld.html)
    - [MySQL :: MySQL 5.6 リファレンスマニュアル :: 2.3.5.7 Windows のサービスとして MySQL を起動する](https://dev.mysql.com/doc/refman/5.6/ja/windows-start-service.html)

```bash
# サービスへ登録して
$ mysqld --install MySQL56 --defaults-file=C:\path-to\mysql-5.6.19-winx64\my.ini
Service successfully installed.
# 登録されていることを確認して
$ sc query state=all | grep SERVICE_NAME | grep -i my
SERVICE_NAME: MySQL56
# MySQLを起動した
$ sc start MySQL56
SERVICE_NAME: MySQL56
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x3
        WAIT_HINT          : 0x3a98
        PID                : 15704
        FLAGS              :

```
- 経過2 : `mysql`コマンドを実行したら怒られた

```bash
$ mysql
ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)
```
- 経過3 : [サービス]ダイアログで確認すると[状態]が「開始中」のままになっていた
- 経過4 : MySQLサービスが止まらない
    - 試した方法1 : `sc stop MySQL56`を使ったが止まらない
    - 試した方法2 : [サービス]ダイアログで停止しても止まらない

# 原因 : 不明
インストールに失敗している可能性が考えられたので、MySQLを停止してから再インストールをしました。

## 対応 : パソコンを再起動する
1. `Win + R` > `services.msc`で[サービス]ダイアログを開く
1. MySQLを選択して右クリック > [プロパティ]でダイアログを開く
1. [スタートアップの種類]を「自動」から「手動」へ変更して[OK]ボタンでダイアログを閉じる
1. PC再起動
Omitで複数のプロパティを同時に除外する

TypescriptのOmitで複数のプロパティを除外する時に、

``` typescript
Omit<Omit<HOGE,"fuga">,"piyo">
```
というような恰好悪いことをやっていたのですが、
全然意味を理解していなかったことを痛感したので備忘を兼ねて

## 正しいやり方

``` typescript
Omit<HOGE,"fuga" | "piyo">
```

複数のフィールドを除外したい場合は、それらのプロパティ名をUnion型で渡してやればOK。

## 原理
Omitの定義をたどると、

``` typescript
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
```
となります。

この時重要なのが``keyof``で、これは後に続く型のプロパティ名をUnion型で返します。
Omitの場合anyなのでstringがnumberかsymbolで構成されたUnion型ならOKです。
このため、上記の正しいやり方で示した`` "fuga"|"piyo"``のように複数のプロパティ名をを渡すことが可能です。

### Kがどう扱われるのか
その後の定義を見ていくと、``Exclude<keyof T,K>``しています。
ここでT全体のpropertyを列挙したUNION型からKで指定したものを抜くわけです。
さらに、得られた残りのプロパティ名の集合(UNION型)をPickに渡しています。
Pickも似たような形で、 ``K extends keyof T``という形で第二型引数を受けているので、UNION型を渡せます。

### Pickの中身
``` typescript
type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};
```
Pickの定義は上記の通り。
Kに含まれるプロパティPの方はTにPでアクセスしたときのものと同じという意味。
仕組み的には以下と同じ。

``` typescript
type HOGE = {
    [fuga:number]:string
}
type s = HOGE[number]//s はstring
```

このような型定義をしているため、PickのKは extends keyof Tでなければならないわけですね。

## まとめ
* OmitやPickに複数指定したい時はUnion型で渡す
* keyofはプロパティをUnion型で返す
Googleデータポータル(現 LookerStudio)で「年度ごとに同月を比較するグラフ」を書く

この記事は [ノンプロ研 Advent Calendar 2019](https://adventar.org/calendars/4208) の2019-12-10 分の記事になります。

私はこのところデータポータルが便利だなーと感じていて、ノンプログラマでも十分使いこなせますし、もはやエクセル、ワード、パワポと同じレベルで使えるようになるべきITツールだと思ってきました。

可視化するときの一つのTipsとして「年度ごとのグラフをつくる」を書きます。(ただ、この表現だと多分伝わらないのですよね、、、年度ごと、なのか年度別なのか、「年度ごとに同月を比較するグラフ」がわかりやすいのかな、、、こういうの正式にはなんて呼ぶのだろうか)


# 前提情報

- データソースはGoogleスプレッドシート
- 可視化はGoogleデータポータル
- データポータルを使ったことがある(使ったことがない人は [こちら](https://qiita.com/sakaimo/items/e64481813f238f30d373
)に使い方を書いてあります！


# 出したいのはこういうグラフ


**東京都の平均気温**
![last.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8612/cd7e86df-bb1d-661e-c926-300efe03e458.png)

1本の線はある年の情報で、X軸は「月」、Y軸は「平均気温」というグラフです。
(気温じゃなくても、例えば売上だったり、集客数だったり、を、「異なる年を月ごとに比較したい」ときのグラフです)


# データソースの用意

今回は東京都の平均気温をグラフにしてみるので、データを [気象庁\|過去の気象データ・ダウンロード](https://www.data.jma.go.jp/gmd/risk/obsdl/index.php) よりデータいただきました。(今が 2019/12/09 の夜なので、2019年12月分は 12/8 までのデータです)

![tk.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8612/d03e4bc8-f297-7c54-0d2e-6da9de56a472.png)




# データポータルの設定

## データソースの選択

データポータルで、新規のレポートつくって、データソースに上記のスプレッドシートの「DP用」のシートを選択したところ。

![dp02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8612/6819580f-2605-907d-4d80-8d4f8d49ad37.jpeg)


## フィールドの選択

デフォルトではこうなってると思います。
![dp03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8612/cecef514-da03-1f2a-13ea-023d76ee93cb.png)


「年月」の情報が「YYYYMMDD」なので「何年何月何日の値」という情報になります。(スプレッドシートのA列が `2017/01` になってたとして、実際は `2017/01/01` という情報を持ってるから)

今回は「年ごと」「月ごと」の情報として扱いたいので、それ用のフィールドを作ります。

「年月」のフィールドを複製して「年」「月」のフィールドを作ります。

![dp04.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8612/495e4070-0802-8451-a300-6d7813582301.gif)



## グラフの作成

「グラフを追加」から「折れ線グラフ」を追加。
下記の赤枠のように設定するとデータ期間の最初から最後までをX軸として、全期間分のグラフができます。これだと2017年から2019年までが並んでいます。

![dp05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8612/79e1fc37-fb34-4a63-3bf7-0dabbfdc29d6.png)

今回は「月ごと」に比較したい！！

- ディメンションに「月」を設定 → X軸が「月ごと」になる
- 内訳ディメンションに「年」→ 折れ線グラフの線が「年ごと」になる

を設定するとこうなります ↓

![dp06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8612/57659bb8-b81b-9bb2-087e-e71bde500835.png)


できた！


# まとめ

データポータルで日付けデータを扱うときは、そのデータを何のデータとして扱うのか、によって、それぞれのフィールドを作ってあげる必要があります。

「何のデータ」については、「フィールド」の「タイプ」で指定ができます。

![dp08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8612/dfbcd383-73f0-8a77-bd9a-8252dc0adb5b.png)

「日付けと時刻」のタイプには下記が設定できます。どの単位で集計したいのか、によって使い分けるのがポイントですね。

- 年(YYYY)
- 年と四半期(YYYYQ)
- 年月(YYYYMM)
- ISOの年と週(YYYYww)
- 日付(YYYYMMDD)
- 日時(YYYYMMDDhh)
- 年月日時分(YYYYMMDDhhmm)
- 四半期(第1、第2、第3、第4)
- 月(MM)
- ISO週(ww)
- 月日(MMDD)
- 曜日(D)
- 日(DD)
- 時(hh)
- 分(mm)


ということで、仕事でもプライベートでもいろんなものを可視化したら面白いと思います！

**ナイスポータル！**  (←社内でまったく流行らない)
Blender2.81以降で、Shapekeyを持ったオブジェクトのModifierを適応したオブジェクトを得る方法

9日が空いていたので書きました。

#なんでもいいからワンクリックでさせてくれ
アドオンを御用意しました。
####<font color = red >ただし、いきなりいじると参照が弱いのか落ちるので、実行したら保存して開き直すことを推奨します。</font>
適応したいメッシュオブジェクトを選択し、虚無を右クリックからAdd Modifier Applied Objectを実行するととなりに出来ます。
https://github.com/iCyP/Add_Modifier_Applied_Object_forBlender2_8 から 
    1. <font color=green> Clone or Download </font> からZIP DOWNLOAD 
    2. zipをそのままaddon install
    3. testingから有効にする
    4. あとは実行するだけ

#説明
2.80以前からの変更概要：2.81からto_mesh()で得たメッシュは一時的なものとなり、直接オブジェクトの作成のソースにすることができなくなりました。
そのため、to_mesh()で得たメッシュをcopy.copy()で複製したものをオブジェクト作成のソースにする必要があります。
いいたかったことはそれだけ。


ではやる事（スクリプトベース）（上のアドオンにコメントをつけたようなものです）

```
ob_eval = base_obj.evaluated_get(bpy.context.view_layer.depsgraph)
#にて、現在ビューポートにあるメッシュの状態を持ったオブジェクトを入手します。
tmp_mesh = ob_eval.to_mesh().copy()
#to_mesh()でモディファイアがApplyされたメッシュを入手し、copy.copy()で複製します。
#これをシェイプキーを一個のみずつ値を1にして、すべてのシェイプキーのメッシュを得ます。
#得たメッシュを
meshs = [bpy.data.objects.new(s.name,s) for s in shapes[1:]]
for s in meshs:
    context.collection.objects.link(s)
#のような形でシーンに紐づけます
#以下のコードで頂点グループをベースから適応後に転送します
for vg in base_obj.vertex_groups:
    dup_obj.vertex_groups.new(name=vg.name)
    #元のオブジェクトにある頂点グループの名前で、新しいオブジェクトに空の頂点グループを作る。
mod = dup_obj.modifiers.new(name="tmp", type="DATA_TRANSFER")
mod.object = base_obj
mod.use_vert_data = True
mod.data_types_verts = {'VGROUP_WEIGHTS'}
bpy.ops.object.modifier_apply(apply_as='DATA', modifier=mod.name)
#ここまででDATA_TRANSFERモディファイアで頂点グループを転送し、適応します。
    #shapekey_transfer
    #シェイプキー用メッシュをすべて選択し、適用後用オブジェクトをアクティブにしたのち、
    #blenderの機能で一気にシェイプキーを転送します
    dup_obj.shape_key_add(name="Basis")
    bpy.ops.object.join_shapes()
    #一時的に作成した、シェイプキー用メッシュオブジェクトとそのオブジェクトを削除します
    for s in shape_objs:
        bpy.data.objects.remove(s)
    for shape in shapes[1:]:
        bpy.data.meshes.remove(shape)
    #マテリアルスロットにマテリアルが割り当てられていないので、もとのオブジェクトから割当ます。
    for fmat, tmat in zip(base_obj.material_slots, dup_obj.material_slots):
        tmat.material = fmat.material
```

雑文ご拝見ありがとうございました。
Kotlinで引数からEnumを生成する


実装時に迷ったのでメモ

```kotlin

enum class LinkType(val linkType: String) {
    TYPE1("type1"),
    TYPE2("type2");

    companion object {
        @JvmStatic
        fun fromString(linkType: String): LinkType {
            return values().first { it.linkType == linkType }
        }
    }
}

```

Stringを受け取ってEnumを返す `fromString` の使い方は下記

```kotlin
LinkType.fromString(serviceList.get(i).getLinkType())
```

Enumに対応していない、Stringの文字列がくるとクラッシュするようにしています。
[Python3] unittestの書き方メモ (setUp や mockなど)

## 基本の書き方

```python

import unittest

class TestWhateverYouWant(unittest.TestCase):
    
    @classmethod
    def setUpClass(cls):
        """
        ユニットテスト開始時に一度だけ実行される
        """
        pass

    def setUp(self):
        """
        一つ一つのテストメソッド実施前に実行される
        """
        pass

    def tearDown(self):
        """
        一つ一つのテストメソッドの実施後に実行される
        """
        pass

    def test_hoge(self):
        """
        テスト実行時、def test_〇〇〇 というように
        testから始まるメソッドがすべて実行される
        """
        pass

```

## モックについて

テスト対象のクラスでテストが書きにくいものがあった場合にモックオブジェクトで置き換えることができる。

```python

from unittest import mock

class TestMock(unittest.TestCase):
    
    @mock.patch('module.ClassName2')
    @mock.patch('module.ClassName1')
    def test_class(self, mock1, mock2):
        assert mock1 is module.ClassName1
        assert mock2 is module.ClassName2

    @mock.patch('module.some_method_name')
    def test_method(self, mock1):
        """
        some_method_name()をモックに置き換えてテストを書くことができる
        """
        pass
```

モックは以下のように使うこともできる。
下の例では、メソッド内で使用しているrandomの実行結果をこちらから指定し、テストを書いている。

```hoge.py
import random

class Hoge:
    def return_joined_random(separator='あああ'):
        hoge_list = ['AAA', 'BBB', 'CCC']
        return separator.join(random.sample(hoge_list, 2))
        # >> 'BBBあああCCC' とかがランダムに返ってくる

```

```test_hoge.py
import hoge

from unittest import TestCase
from unittest　import mock

class TestHoge(TestCase):
    @mock.patch.object(try_mock.random, 'sample', return_value=['BBB', 'CCC'])
    def test_return_joined_random(self, sample):
        """
        期待する値が返ってくるかテストしたい、でもrandom使っているから固定のテストを書くのが難しい？
        こういう場合はmockを使う！
        """
        self.assertEqual(
            hoge.Hoge().return_joined_random(separator='テスト'),
            'BBBテストCCC')

    def test_hoge(self):
        print(hoge.random.sample([1,2,3], 2))
```

ポイントはテストメソッド宣言の真上に書いてあるこの部分⬇️

```
@mock.patch.object(hoge.random, 'sample', return_value=['BBB', 'CCC'])
``` 

これは、「hogeモジュール(hoge.py)でimportしているrandomのsample関数はreturn_valueを['BBB', 'CCC'] とする」 という意味。

ランダム要素であるrandomの実行結果をこっちが予め定義することで、その結果だった場合のテストをすることができる。すなわちrandomの動作を気にすることなく単体テストを書くことができるのだ。

ちなみに`test_hoge()`の結果は[2, 3] など普通にrandom.sample()の実行結果が返ってくる。
このことにより、パッチは当てたメソッドにのみ作用することがわかる。
（random.sample() 全体に効いちゃってたら、ここでもreturn_value が['BBB', 'CCC'] になっているはずだから）

## 参考
https://docs.python.org/ja/3/library/unittest.html
https://docs.python.org/ja/3/library/unittest.mock.html
https://blog.amedama.jp/entry/python-unittest
Unity 2019.3でAndroidビルドすると"Android NDK not found"


<img width="320" alt="notfound.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54417/e9417660-1b0a-3cb3-4d69-be67c99f5194.jpeg">

HUBのバグのようなのですが、2019.2の時からバグがずっと発生しています。
修正されたり、ぶり返したりしていて面倒なバグです。


## 先に結論
HUBからNDK等をインストールしている前提です。

メニューから設定を開く`Preference -> External Tools`
Androidの設定で、NDKのパスを手動で設定します。

<img width="512" alt="setting.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54417/110c6d0c-ab65-82c7-4405-d159d52b52d8.jpeg">

HUBがインストールしたNDKのパスはデフォルトならこのあたりにあります

Windows
```
C:\Program Files\Unity\Hub\Editor\2019.3.0f1\Editor\Data\PlaybackEngines\AndroidPlayer\NDK\android-ndk-r19
```

macOS
```
/Applications/Unity/Hub/Editor/2019.3.0f1/PlaybackEngines/AndroidPlayer/NDK/android-ndk-r19
```

まだ黄色くなっていますが、これでAndroidのビルドが通るようになりました。


## このバグについて
フォーラムなどはこの辺りのページを参考
* [Android NDK missing](https://forum.unity.com/threads/solved-android-ndk-missing.689122/)
* [Failed to build Android Build](https://forum.unity.com/threads/case-1201831-failed-to-build-android-build.785294/)
* [[HUB] HUB doesn't install the right Android SDK and NDK tools](https://issuetracker.unity3d.com/issues/hub-hub-doesnt-isntall-the-right-android-sdk-and-ndk-tools)

```
PlaybackEngines\AndroidPlayer\NDK
```

普段は上記NDKフォルダの直下にNDKがインストールされるのですが、1つフォルダが作られてパスが通らないというのが現在発生しているバグのようです(2019.3.0f1 RC1)

RC1でも直っていないので、今後も同じような事が発生しそうな為メモを残します・・・
vue.js element-ui el-radio-group fill 色の設定！ 

##背景##
vue.js element-ui el-radio-group で　ラジオボタングループの色　を変更したい！

##問題##
下記コードのように　https://element.eleme.cn/#/en-US/component/radio からのコードはそのままに、
el-radio-groupに　fill='#4c993a'  を追加しても、効かない！！！ blueのままだ！

```test1.vue
<el-radio-group fill='#4c993a' v-model="radio1" @change='changeValue'>
    <el-radio  :label="1" border>りんご</el-radio>
    <el-radio  :label="2" border>なし</el-radio>
</el-radio-group>
```


##解決策##

なんで？！！！
色々調べみたら、、、！

```<el-radio> </el-radio>  ``` ではなく、、、

```<el-radio-button> </el-radio-button>```    だ！！！！

```test2.vue
<el-radio-group fill='#4c993a' v-model="radio1" @change='changeValue'>
    <el-radio-button  :label="1" border>りんご</el-radio-button>
    <el-radio-button  :label="2" border>なし</el-radio-button>
</el-radio-group>
```

##イメージ図##

![スクリーンショット 2019-12-10 10.29.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181748/44765c50-9361-ad39-3d60-72eecfa69c49.png)
今更ながらjQueryのセレクタにハマった話

[ディップ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/dip-dev)の10日目です。

## はじめに
こんにちは、ディップ株式会社に2018年新卒で入社し、求人系サービスの開発や社内向けツールの開発を行なっている@taku-0728です。
今回は私がjQueryのセレクタでハマった話を書きたいと思います。
知ってる方からすれば当たり前だと思うかもしれませんが、自分用メモとして残します。
よろしくお願いいたします。

## 結論
細かいことはいいから結論が知りたい忙しい人用に僕がこの記事で言いたいことを一言でいうと「**jQueryでセレクタに使う際にエスケープが必要なものがある**」ということです。エスケープが必要な文字は下記です。先頭に半角スペースを含んでいます。

```
 !"#$%&'()*+,./:;<=>?@[\]^`{|}~
```
(先頭の半角スペースを含んだ)これらの文字は2つのバックスラッシュ`\\`を使ってエスケープする必要があります。

## 実例
```html
<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  </head>
  <body>
    <p id='test'>test</p>
    <button id='button[0]'>消す</button>
    <button id ='button[1]'>表示する</button>
  </body>
  <script>
    $('#button[0]').on('click', function(){
      $('#test').hide();
    })
    $('#button[1]').on('click', function(){
      $('#test').show();
    })
  </script>
</html>
```

3分で書いた雑なコードですがご了承ください。「消す」ボタンをクリックするとtestという文字列が消え、「表示する」ボタンをクリックすると文字列が表示される・・・と思われるかもしれませんが、このコード実はこのままでは期待した動作をしないんです。セレクタに`[]`が入っているので、下記のようにエスケープしてあげる必要があります。

```html
<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  </head>
  <body>
    <p id='test'>test</p>
    <button id='button[0]'>消す</button>
    <button id ='button[1]'>表示する</button>
  </body>
  <script>
    $('#button\\[0\\]').on('click', function(){
      $('#test').hide();
    })
    $('#button\\[1\\]').on('click', function(){
      $('#test').show();
    })
  </script>
</html>
```

## 理由
なぜエスケープする必要があるのでしょうか？
以下[公式](https://api.jquery.com/category/selectors/)より

To use any of the meta-characters as a literal part of a name, it must be escaped with with two backslashes: \\. For example, an element with id="foo.bar", can use the selector $("#foo\\.bar"). 

公式曰く、「メタ文字など &nbsp;!"#$%&'()*+,./:;<=>?@[\]^`{|}~ を名前のリテラル部分として使用するには、2つのバックスラッシュを使用してエスケープする必要があります。」とのことです。

## どうすればいいか
本来はエスケープする必要がないように記述するべきだと思います。
ただもし特殊文字を使用したい場面があった場合、エスケープする必要があるとはいえ記述時にバックスラッシュを2つ入れるのは面倒ですし、可読性が落ちる原因にもなりそうです。エスケープする関数を作りそっちで対応する方がいいと思います。

```JavaScript
function selectorEscape(val){
    return val.replace(/[ !"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~]/g, '\\$&');
}
```

さっきのコードに加えるとしたらこんな感じですね

```html
<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  </head>
  <body>
    <p id='test'>test</p>
    <button id='button[0]'>消す</button>
    <button id ='button[1]'>表示する</button>
  </body>
  <script>
    $('#' + selectorEscape('button[0]')).on('click', function(){
      $('#test').hide();
    })
    $('#' + selectorEscape('button[1]')).on('click', function(){
      $('#test').show();
    })

    function selectorEscape(val){
      return val.replace(/[ !"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~]/g, '\\$&');
    }
  </script>
</html>
```

## まとめ
セレクタには極力特殊文字は使わないようにするべきですが、どうしても使いたい場合はバックスラッシュ2つ`\\`でエスケープするのを忘れないようにしましょう。
私はこの問題にハマって数時間無駄にしてしまったので、この記事を読むことによって2度と私のような人が現れないことを祈っています。

## 参考
[jQueryセレクタのエスケープ](https://qiita.com/mk_summer/items/6eb745c7babf2abfc03c)
[公式](https://api.jquery.com/category/selectors/)
Ionic/Angularにコードフォーマッタを導入する

Ionicのコードをレビューする機会が度々あるのですが、独自フォーマットを読むのは困難なので、最初にフォーマッターを導入してもらい整形してもらってからレビューするようにしています。

AngularのデフォルトテンプレートとIonicのスターターテンプレートのふたつとっても、フォーマットが微妙に違うことは有名？ですが、そこに複数の実装者が「私はここで改行をいれる！」「私はタブだ！！」みたいに独自性をだしたコードはちぐはぐになってしまうので、ぜひ皆さんもフォーマッタを導入してみてください。

簡単に導入できるように以下のコマンドを作成しました。（`@ionic/angular@4.7以上でご利用ください）

```bash
% ng add @rdlabo/ng-add-formatter
```

フォーマッタであるprettierや、ステージにあげたコードのみに適用するためのlint-stagedなどいくつかのパッケージがインストールされ、自動的に設定Scriptsが追記されます。

とてもシンプルですので、ぜひ今すぐ自分のプロジェクトを開いて、実行ください。差分をみるととても爽快ですよ！

それでは、また。
いつも「あれ何だっけ？」とググってしまうExcelの小技まとめ

##Excelのマクロが使えなくても小技を知っていれば安心
私はVBAでマクロも組めるのですが人間は基本**頭を使いたくない生き物**なのでもっぱら小技で乗り切っています。

私は極端な例でいうと**擦り切れるまで使いたいExcelシート**を作りたいです。
想定されるユーザーは家が本であふれてる自分自身、シートを使う目的は**HTMLの自動生成**、そして**家計簿**が中心です。

以下、いつもググってしまう小技とそのリンクを紹介させていただきます。

##いつもググってしまう小技

###シートのタブ名を取得

[リンク先](https://www.extendoffice.com/documents/excel/2618-excel-reference-tab-name.html)

``` excel
=MID(CELL("filename",A1),FIND("]",CELL("filename",A1))+1,255)
```

###便利なTEXT関数

**月日(曜日)で表示する**

``` excel
=TEXT([セル],"mm月dd日(aaa)")
```

**桁区切りで表示**

``` excel
=TEXT([セル],"###,###")
```

###リストの出現回数でランキングを作成

以下のような表から出現回数とランキングを表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280363/c9d785ea-4771-30b4-b287-ba22bfcad0a2.png)


**出現数の出し方**

``` sample.xlsx
=COUNTIF($B:$B,D4)
```

**順位の出し方**

``` sample.xlsx
=RANK(E4,E:E,0)
```




##更新履歴

- 2019/12/10 作成
mockmockでAmazon API Gatewayにデータを送るプロジェクトを作成する

この記事は、[mockmockアドベントカレンダー](https://qiita.com/advent-calendar/2019/mockmock)10日目の記事です。

今回は公式ドキュメントに載っていない、Amazon API Gatewayで作ったAPIに向けてデータを送る方法を書いてみます。

## プロジェクト認証
API Gateway宛にデータを送るプロジェクトを作る場合、サーバータイプを`General`にします。
独自に作成したサーバー向けにデータを送る場合に使うサーバータイプですが、
ユーザーの管理下にないホストに向かってデータを送信するのを防ぐため、認証作業が必要となります。
API Gatewayを使う場合、ココをクリアするのが一番の山場になります。

プロジェクトを作成する際に、mockmockから認証キーが提示されるので、
`http(s)://[送信先ホスト]/[認証用パス]`に対してリクエストを行い、認証キーが含まれるレスポンスが返れば認証となります。

方針としては、[チュートリアルAPI](https://console.mock-mock.com/docs/tutorials/simple_data#create_project)で行なっているものと同様です。
`http(s)://[送信先ホスト]/auth/[認証キー]`というGETのAPIを用意し、`[認証キー]`の部分をオウム返しさせることで、認証をクリアさせます。

## SAMプロジェクト作成
今回はSAMでAPI Gateway + Lambdaを設定していきます。

サンプルを以下に作っていますので、全体は以下を参考にしてください。
https://github.com/fusic/mockmock-amazon-api-gateway-sample

### テンプレート
以下のように、`/auth/{auth_key}`のGETのAPIを設定します。
`auth_key`はリクエストパラメーターです。

```
Resources:
  AuthFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: app/app.auth
      Runtime: python3.6
      Events:
        Auth:
          Type: Api
          Properties:
            Path: /auth/{auth_key}
            Method: get
            RequestParameters:
              - method.request.path.auth_key:
                  Required: true
                  Caching: false
```

### Lambda
Lambdaの内容はとても簡単です。

```
import json

def auth(event, context):
    auth_key = event["pathParameters"]["auth_key"]
    return {"statusCode": 200, "body": auth_key}
```

### デプロイ
必要に応じて`--profile`を指定してください。

```
$ sam package --output-template-file packaged.yaml  --s3-bucket REPLACE_THIS_WITH_YOUR_S3_BUCKET_NAME
$ sam deploy --template-file packaged.yaml --stack-name api-gateway-sample  --capabilities CAPABILITY_IAM
```

デプロイされたAPIは以下で確認できます。

```
aws cloudformation describe-stacks --stack-name api-gateway-sample --query 'Stacks[].Outputs[?OutputKey==`AuthApi`]' --output table
```

## プロジェクト設定
これで、以下のようにプロジェクトを設定すると認証をクリアできると思います。
生のAPI Gatewayのエンドポイントだと`Prod`などステージを表す階層が付きますが、それは認証用パスの方に入れます。

<img width="672" alt="スクリーンショット 2019-11-19 9.42.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39565/948c8466-249b-303c-52fa-e93a9b93e9e6.png">

## まとめ
API Gatewayで作ったAPIに向けてデータを送る場合、認証部分が山場でした。
ちょっと大変ですが、そこを乗り越えればあとは普通のAPIサーバーに行う設定と同様です。
(もちろんデータ送信用のAPIは別途作る必要がありますが。)

明日は@yukabeokaです。
グラフバリュージェネレーターの原点基準についてです！
日本語版PHPUnitマニュアルを英語版と同期していきたい話

[^1]: https://github.com/sebastianbergmann/phpunit/blob/7.5/ChangeLog-7.5.md#deprecated-1 を参照

この記事は「[PHP Advent Calendar 2019](https://qiita.com/advent-calendar/2019/php)」の10日目の記事です。

## はじめに

PHPUnitのマニュアルはバージョン7以降は次のページで公開されています。PHPUnitを使っている方の多くが見たことあるページだと思います。

- 日本語版：https://phpunit.readthedocs.io/ja/latest/ 
- 英語版：https://phpunit.readthedocs.io/en/latest/

英語版以外は最新バージョン（latest）のみ、英語版だとhttps://phpunit.readthedocs.io/en/7.5 のように、古いバージョンのマニュアルも見れる運用になっているようです。

## 日本語マニュアルの現状

日本語版のマニュアルは最新バージョンの英語版との同期が必要な関係で、記述内容がどうしても古くなってしまいます（まあこれは他言語にもいえることですが・・・）。
ほんの一例になりますが、日本語版で古くなってしまっている箇所を挙げます。

### `@expectedException`のアノテーション
`@expectedException`は例外テストをするためのアノテーションです。この記述はPHPUnit 9から削除予定で非推奨になっています。[^1]

次の画像は、左が英語版の「[Annotations](https://phpunit.readthedocs.io/en/latest/annotations.html)」で、右が日本語版の「[アノテーション](https://phpunit.readthedocs.io/ja/latest/annotations.html)」です。
英語版は`@doesNotPerformAssertions`の下が`@group`になっていて、`@expectedException`の説明が消えていますが、日本語版にはまだ残っています。

![annotations.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232357/54b6f48a-6033-1430-14b5-81011798421e.png)

### `assertAttributeEquals()`のアサーション

`assertAttributeEquals()`はクラスのプロパティをテストするためのアサーションです。この記述もPHPUnit 9から削除予定で非推奨になっています。[^1]

次の画像は、左が英語版の「[Assertions](https://phpunit.readthedocs.io/en/latest/assertions.html)」で、右が日本語版の「[アサーション](https://phpunit.readthedocs.io/ja/latest/assertions.html)」です。
英語版の`assertEquals()`の説明からは`assertAttributeEquals()`が消えていますが、日本語版にはまだ残っています。

![assertions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232357/be7b2ffd-7389-456e-2c0a-e158738fff2d.png)

### `setUp()`への`void`が抜けている

単純ミスだと思いますが簡単な例として紹介します。PHPUnit 8だと`setUp()`は`setUp(): void`のように`void`を付ける必要があります。
この点については私が確認した限りほとんどの箇所で反映済みになっていましたが、「[フィクスチャ](https://phpunit.readthedocs.io/ja/latest/fixtures.html)」の「Example 4.2 利用可能なすべてのテンプレートメソッド」のサンプルコードの`setUp()`では、`void`が抜けてしまっています。

![setup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232357/bb19ae79-ff91-42c6-5f63-5a51b1a9d41f.png)

## コラボレーターになりました

といったわけでこれだけの差分がある以上、特に最新の8系とかを使っている環境だと日本語版マニュアルがどこまで正しいのか分からない状況になっているように感じます。
私自身も一人のPHPUnitユーザとしてこれは良くないと思い、日本語版マニュアルをメンテナンスしていきたいと思うようになりました（タイトルの回収）。

日本語版マニュアルは「[sebastianbergmann/phpunit-documentation-japanese](https://github.com/sebastianbergmann/phpunit-documentation-japanese)」のGitHubリポジトリで管理されています。[Issue](https://github.com/sebastianbergmann/phpunit-documentation-japanese/issues/3)でコラボレータを募集していたのでそこから追加してもらって、晴れてコラボレーターになりました。

## コントリビュートについて

コラボレーターになったからには自分自身の貢献もですが、他の方に対しても貢献していきやすいような環境にしていきたいと思っています。
まずは第1ステップとして現在の英語版との差分コミットを記載したIssueをバーっと作ってみました。「Differences from current english version」というタイトルが付いているIssueで、マニュアルの章ごとに分けています。
https://github.com/sebastianbergmann/phpunit-documentation-japanese/issues

見て頂けると分かるのですが、現状英語版と結構遅れてしまっていて上記の例で紹介したのはほんの一部です。さらに日本語への翻訳もプラスで必要なため、みなさんにもコントリビュートしてもらえると大変嬉しく思っています🙏
今後も日本語PHPUnitユーザが幸せになれるような、マニュアルにしていけるように頑張っていきたいです！
vCenter Server をDNSなしでインストール

#vCenter Server をDNSなしでインストール

検証環境でローカルIPのみで簡単にスタンドアロンVDIを作るとき躓くポイント。
DNSが無いとvCenter Server Applianceがうまく入らないので、その回避策。
Step1とStep2の間にひと手間入れる必要があります。

1,　ノードにESXi 6.7をインストール
2,  Vcenter Server ApplianceをDNS無しで入れる


#ネットワーク構成
|ノード  |VMware Network  |vCenter Server |
|---|---|---|---|
|A  |192.168.100.30   |192.168.100.50|
|ノートPC  |192.168.100.100  | ||
---

#1, ノードAにESXi 6.7をインストール

各ESXiでTroubleShootingのESXi ShellとSSHをEnableにしておく
ESXi Shell Enable
SSH Enable

#2, Vcenter Server Applianceを1台に入れる
ノードAに対してWindowsのノートPCからvCenter Server Applianceを入れる。
今回使用したのは下記で、展開して出来たvcsa-ui-installerフォルダの中にinstallerという
ファイルがあるので、それを実行。
VMware-VCSA-all-6.7.0-11726888
![vcsa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478729/6dd20c44-3060-c657-70b9-6195d38a40e3.png)
基本的にNextでどんどん進めばStep1はクリア。
設定のFQDNを入れる所ははDNSの設定が無いのでIPアドレスで指定します。

Step1が終わったら次に行かずに、下記追加作業を実施します。


---

###StaticIPでDNSが無い場合の追加作業。

1)まずはノードAのESXi(ここで言う192.168.100.30)にブラウザでログインし、仮想マシン"vmware vcenter server appliance"をクリックしてコンソールを立ち上げます。
2)コンソール内でAltと➡を押して、CLIコンソール画面でログインします。(root/rootのパスワード)
3)2つのファイルを編集するためにshellモードに入ります。
\>shell
3-1) \#vi /etc/dnsmasq.conf
\#no-hosts <コメントアウト
no-resolv　<追加
bogus-priv　<追加
server=192.168.100.1　<追加
![dns.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478729/6da2b6b2-2482-0101-b5c6-1cef3499a550.png)

3-2) \#vi /etc/hosts
192.168.100.50 localhost localhost.localdomain
![hosts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478729/72d157f9-1b04-ae0a-8d01-cac0627dfb45.png)

4)確認
\#systemclt restart dnsmasq
\#nslookup 192.168.100.50　>localhostと出ればOK

---

Step1が終わったら引き続きStep2をNEXTで進む。
Single Sign Onのパスワードの設定が終わると、インストール確認画面後インストールが進む。
![step2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478729/01a0d41c-e511-8171-d2f0-0e6fed8f6fa6.png)

終わると、https\://photon-machineにログインしようとするけど、DNS無いので繋がらない。
でも大丈夫。
IPアドレスでアクセスすれば、vCenter Serverにログインできます。
ちなみにSSOのログインはrootではなく、`administrator@xxxx.local`のような名前ですよ！
![SSO.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478729/fba0e0af-8ae2-52cf-6fab-6f5cce7b0e28.png)
linestringで取得した複数行をmultilinestringに変換する方法

linestringで取得した複数行をmultilinestringに変換する方法


以下のようなTBLがある場合
全行のlinestringをまとめてmultilinestringにしたいのですが
その方法ってどんなものがありますでしょうか・・・

id            geo
1             linestring(0 10, 2 11)
2             linestring(5 20, 6 21)
3             linestring(3 5, 10 20)

期待結果
multilinestring((0 10, 2 11),(5 20, 6 21),(3 5, 10 20))
Git ステージングしたファイルをgit diffしたいとき

# 目的

- ステージングをしてしまった後にコマンド`$git diff`を実行して差分を取得したいときの方法を先輩から教えてもらったのでまとめる。

# 結論

- コマンド`$git diff`にオプション`--cached`をつけて実行する。

# ちょっとしたまとめ(manコマンドで調べてみた)

- ステージングしていない差分はコマンド`$git diff`のみで取得可能である。
- コマンド`$git diff`はindexとtreeを比較して差分があったときに表示する。
- コマンド`$git diff --cached`は指定したコミットに関連する現在ステージングされている変更点を出力する。
よく使われるコマンド一覧とviコマンド

## コマンド
**mkdir** make directory。ディレクトリ（＝フォルダ）を作成。「mkdir XXX」でXXXフォルダを作成という意味
**cd** change directory。ディレクトリに移動。cd XXXで、XXXフォルダに移動という意味
**pwd** $cd /フォルダ名 | print working directory。現在いるディレクリを表示
**ls** list segments。現在いるディレクリのファイルをリスト形式で表示

## viコマンド
**iキー** インサートモード。現在のカーソル位置に文字を挿入する
**Escキー** インサートモードからコマンドモード（表示モード）に切り替え
**$ vi フォルダ/ファイル名** ファイルを開く
**$ vi rm フォルダ/ファイル名** ファイルを削除
**:q** viを閉じる

## Git hub関連
**git init** リポジトリを作成
**git clone** クローンを作成
**git branch**ブランチの一覧を表示。頭に * のついているものが現在のブランチを表す
**git branch**  XXXブランチを作成。「git branch XXX」でXXXというブランチを作成という意味
**git checkout** ブランチを移動。「git checkout XXX」でXXXというブランチに移動するという意味
**git commit** -aこれまでの修正をすべてコミット
**git push** originファイルをプッシュ。「git push origin XXX」でXXXというブランチにファイルをプッシュするという意味
さくらのクラウドを社内システムで使っている話

この記事は、https://qiita.com/advent-calendar/2019/sakura 18日目の記事です。

さくらインターネットで情シスをしている 小泉行生(dumixnet) と申します。
初投稿となりますが、よろしくお願いします。

情シスと言っても会社によって色々違うようですが、
私は「社内だけで使われるシステムの構築/運用」を主に行っています。
SaaSに置き換わったシステムも多いですが、やはりいくつかのシステムはオンプレで残っています。

社内には専用のさくらのクラウド環境があり、
物理サーバーからクラウド環境にシステムサーバーを移したり、
クラウドを前提に構築したシステムもあります。

構築と運用を数年やってきた「さくらのクラウド」のアレコレを書いていきます。

#すごーーーーーく安定している！！！
運用をしていると不意の障害は訪れるものです。
ただ、さくらのクラウドで動いている私が管理しているサーバーは、
ここ数年 **「長時間の障害で泣きながら復旧作業」** という事に見舞われたことがない！
と感じるくらい安定して稼働してます。
(自分でやらかしてしまった事案は置いといて…)

さらにさくらのクラウドであれば、
「ハードウェア的にどうこう」や「ネットワーク的にここには設置して欲しくなかった」というトラブルは皆無！
設置や構築時のハードウェア、ネットワーク的なトラブルに悩まされることがなくなりました。

#テスト環境や参照環境が超簡単に作れる！！！
物理環境で同じことをしたら作るまでに心が折れそうな調整が始まりますが…
クラウドならクリックして必要な入力を行えば簡単にコピー環境が作れます！

「システム」と「データ」のドライブを分けて構築すれば、
テスト環境やメンテナンス時の参照環境が短時間で構築できます。

システムドライブのコピーを作り、
バックアップしておいたデータドライブを一緒にマウントして起動。
これだけで新しい環境が簡単に作り上げられます。
(細かいことはおいといて… ですけどね)

#マシンパワーも抜群！！！
**クラウドなんてそんな速度出ないんでしょ？** と思ってるあなた！
私も正直そう思ってました！！
そんな思いを払拭する出来事がありましたのでご参考までに！！

あるシステムを導入する前に「負荷テスト」を行いました。
こちらはシステムの推奨環境と同等のスペックのクラウドサーバを用意
※12Core/48GBメモリ/SSDストレージ Windows用のパフォーマンス調整済

そこでの結果は **「1000人の同時アクセステストを難なくクリアしてしまう」** パフォーマンス！
この結果を元に私はさくらのクラウドにシステムを構築/移行していこう！と誓いました！
負荷テストを難なくクリアしたサーバーは今日も700人のユーザーがアクセスしてスケジュールやワークフローを使っています。

#過信は禁物！
今まで「安定してて、簡単に作れて、パフォーマンス最高！」とべた褒めしてきましたが…
IaaS環境でもハードウェア面での心配がいらなくなったとはいえ、
ソフトウェア面でのバックアップやシステムのチェックは重要です！
この辺をおろそかにしてしまうとシステムを安定して従業員へ提供出来なくなります。
私もいくつものトラブルの現場に立ち会い泣きながら復旧させてきました。
その際に「あれやっとけばよかった」はよくあることです…
ハードウェア面での心配がさくらのクラウドでなくなったからこそ、
ソフトウェア面でシステムを手厚く守っていく心がけが大事です。

#ホストサーバーを分けて構築！
WebサーバーとDBサーバーを分けて構築する事があったとき、
ホストサーバーが同じだったら…
**落ちてしまった時は泣きながら両者の復旧を待つ** ことになります…
そんな事より「石狩と東京のリージョンを分けて構築しろよ！」と言われてしまいそうですが…
そうは問屋が卸さない時が多数あります。
そんなときは「group」タグを使うことでホストサーバーを分けることが出来ます。
詳細は以下のマニュアルを参考にしていただくとして…
https://manual.sakura.ad.jp/cloud/server/special-tags.html#id3
「ホストだけに起動するサーバーをご指名！」とはいきませんが…
システムの共倒れを防ぐために「group」タグを使えば、
最大4サーバーは違うホストサーバーで稼働できます！

#さいごに
さくらのクラウドを社内システムで使う事によって、
「構築」「運用」の面で負担が軽減されました。
おかげさまで「泣きながら対応する」事も減り、
他にやりたかったことができるようになりました。

この辺のお話はまた今度できればと存じます。