OmniAICreator/Qiita-1.07M huggingface dataset:
Rails+jQuery　イベントの発火により部分テンプレートを更新させる方法

## はじめに
[インクリメンタルサーチについて書いた記事](https://qiita.com/iiyama_makoto/items/49cbd18c6f57313e6c21)ではajaxとjsonの組み合わせを使ってビューを変化させていましたが、今回はjsonを使わずRailsの部分テンプレートを更新させる方法でビューを変更する方法について自分なりにまとめていきます。

## 環境
Ruby 2.5.1
Rails 6.0.2
haml、jQueryを使っていきます。

## やりたいこと
form_withのsubmitを使わず、jsのイベント発火（clickやchangeなど）により非同期通信で部分テンプレートを更新させたいです。
jsonを活用して更新する方法もありますが、ここでは部分テンプレートを活用して、js内の記述を簡略化させていきます。

### まずはsubmitを使った時の更新

```rb:post_controller.rb
class PostController < ApplicationController
  def index
    @posts = Post.all
  end

  def create
    @post = Post.create(message: params[:message])
    @posts = Post.all
    render partial: "post", collection: @posts
  end
end
```

```rb:index.html.haml
%h2
  Posts

= form_with model: @post do |f|
  = f.text_field :message
  = f.submit "Post", id: :submit

.posts
  = render partial: "post", collection: @posts
```
```rb:_post.html.haml
= post.message
```
![pict1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495421/7c741c24-bc0a-398f-dfeb-4170ed5d7730.png)

まずは比較として、jsを使わず更新してみます。

#### 結果
![pict2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495421/f0185043-c726-0bac-78a6-e944711a549f.png)
部分テンプレートのみの更新ではなく、ページ全体を部分テンプレートに変更されてしまいました。

### 部分テンプレートのみ更新させる
```rb:post_controller_rb 
class PostController < ApplicationController
  def index
    @posts = Post.all
  end

  def create
    @post = Post.create(message: params[:message])
    @posts = Post.all
    #  partial: "post", collection: @posts  <- 削除
  end
end
```

```rb:create.js.haml（新規作成）
$('.posts').html("#{j(render partial: "post", collection: @posts)}");
```

#### 結果
![pict3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495421/fdc283d4-7b95-904b-8737-7e8d169a9920.png)
![pict4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495421/11193caa-3ee6-00d2-5c58-75b35e32d3a0.png)
部分テンプレートのみ更新させることができました。

### 本題　submitでの送信ではなく、jsのイベントで部分テンプレートの更新を行う

```js:post.js
$(function() {
  $('#submit').on('click', function(event) {
    event.preventDefault();
    var input = $('#message').val();
    console.log(input)
    $.ajax({
      type: "POST",
      url: "/post",
      data: {message: input}
    })
    .done(function(response) {
      $('.posts').html(response);
    })
  })
})
```

```rb:post_controller.rb
class PostController < ApplicationController
  def index
    @posts = Post.all
  end

  def create
    @post = Post.create(message: params[:message])
    @posts = Post.all
    render partial: "post", collection: @posts  <- 復元
  end
end
```

サーバーから返されるデータの形式を指定しないことで、標準的なHTMLで記述された部分テンプレートの情報が返されてきているようです。

#### 結果
![pict5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495421/a63cc3f4-07ce-7e57-b4f4-37a6c852fe0e.png)
jsで更新させる部分にajax通信で返されたデータを置換させることで部分テンプレートの更新が実現できました。

### 活用できそうな場面
マウスオーバーと組み合わせてマウスの位置によってビューを更新させたり、一時的に処理を停止させたりといったjsとの組み合わせで活用できそうです。
IT業界の構造から見るシステム営業

タイトル通りの内容なんですが
営業マン向けにこの内容を発信します。

エンジニアも見た方がいいですが
関係ある人はこれ見るより労基なり弁護士に相談する方が
先かもしれませんが。

まず、IT業界には大きく3つの階層に分かれています。

①ユーザー企業
②プライムベンダー
③協力会社（下請け企業）

順番に解説します。

まず①ユーザー企業
これは実際にソフトウェアを使用する会社です。所謂、お客様です。
大手企業だと情報システム子会社なども該当します。
一般的には発注者になるので、ここが基本的には取り仕切ります。

②プライムベンダー
Sierと呼ばれる受託開発をメインにやってる所が多いです。
NEC、NTTデータ、富士通、日立製作所、野村総研など
ここら辺は主に要件定義から進捗管理など上流工程を担当します。

③協力会社（下請け企業）
はい、IT業界がブラックと呼ばれる部分の解説行きます。
いわゆる技術者派遣して常駐メインがここです。
SESもここだけどまとめて解説します。
んで、大抵の技術者はここの階層のIT企業の人なので
技術力、マネジメント、スキルセットなどはバラバラです。
最近はかなりホワイト化してますが
一昔前は200万のSASエンジニア（データ分析ツール）25次請けで手取り14万とか
聞きますね。（ここら辺のブラックな話は別の機会に）

--------------------------------
本題になりますが営業をかける人は何処を狙うか？

基本的にプライムベンダーはユーザー企業に。
協力会社（孫請け）などはプライムもしくはセカンドベンダーに行きます。

何故か？

ユーザー企業は大規模なシステムを発注するので
必然的に大手Sierに依頼せざるを得ません。
開発リスクを考えると中小企業に発注するメリットはないですね。

そして大手Sierは大量の人員を必要になるので
中小企業から調達するんですね。
そうすることで開発に必要なリソースを確保する
と言うのが今の日本のIT開発の大雑把な内容です。

そして2次請けは基本的に人を集めているので零細派遣や
SES企業は「情報交換」と称してガンガン企業を回って
人や案件の情報を集めて上位となる会社に配信するんです。
これがいわゆるIT派遣の営業です。

プライムは要件定義書や提案書などをまとめて持っていき
新規開発提案を行いますが、これはベンダーロックにより
そのシステムのナレッジが一社に集中していることがあります。
（これが公取になんも言われていないのは割とヤバいけど）

まぁ、そんな内容です。

以上
既存のJavaScript (Node.js)をTypeScriptにする

# TL;DR;
- 迷ったら最初からTypeScript入れておくが吉
- 移行するなら`implicit*`系のオプションはOffにして優しいTypescriptに
- `tsc` + `nodemon`で効率のいい開発

# この記事の対象
- 今あるJavaScriptで書かれたプロジェクトにTypeScriptを導入したい人
- JavaScriptに少しずつTypeScriptを入れたい人
- Node.jsで動かすことを想定しています。（フロントエンドではない）


## 1. まずTypeScriptを導入する
これは簡単。`yarn add --dev typescript`だけ。
## 2. tsconfigを書く
これが面倒。include, excludeは各自頑張ってください。どこかのを参考にすればどうにかなります。（node_modulesとかをexcludeに入れるのを忘れずに。とっても重くなります）
`compilerOptions`で悩んだので、必要そうなところを載せます

- `target`は[ここ](https://node.green/)見て自分のNodeがどこまで対応しているかで決めるがいいと思います。Node 13を使っているのならes2019まで対応しているのでes2019でいいかと思います。

- `lib`は「es2018にはないけれど、これもあることにしてね」とtypescriptに伝える設定です。polyfillされるわけではないことに注意してください
- `implicit*`は、導入前に死なないようにとりあえず`false`にしておくことをおすすめします
- `implicitAny`は個人的にずっと`false`でいいように思います。必要なところだけ形を書いて安全にしていけるところがJavaScriptをTypeScriptのいいとこどりができると思いますし、一番効率的かと思います。

```json-doc:tsconfig.json

{
  "compilerOptions": {
    "moduleResolution": "node",
    "target": "es2019",
    "module": "commonjs",

    // ReactのSSRをしている場合はこの辺の設定が必要
    "jsx": "react",
    "lib": [
      "dom",
      "es2019.array" // targetがes2017だけどArray.flatとか使いたいよーと言う場合に追加してください。他にもいろいろあります。
    ],

    // 段階的に移行するならtrueにします。tsファイルからjsを読み込めるようになります。逆は無理
    "allowJs": true,

    // jsファイルの形チェックもしたければtrueにしましょう。全部のエラーに対応しなければいけなくなるのでfalseがおすすめ
    "checkJs": false,

    // d.tsファイルのtypeチェックを無効化します。（falseだとnode_modules内でエラー出まくりました）
    "skipLibCheck": true,

    // 後述するモジュールと組み合わせるとtsファイルの行数でスタックが見られるので楽です
    "sourceMap": true,

    // デコレーター使いたい場合はtrueで。Reactで使っているので必要でした。
    "experimentalDecorators": true,

    // TypeScript 3.4以上で使えます。watchしながらのトランスパイルが爆速になります。付けない理由はない。
    "incremental": true,

    // ここから先はlint的な要素です

    // JavaScriptから移行する場合、この辺はfalseにしておかないとかなり辛いです。特にanyは無理です。
    "noImplicitAny": false,
    "noImplicitReturns": false,
    "noImplicitThis": false,

    // 使っていない変数が定義されてたら怒られるオプション。これはes-lintとかを導入していればトランスパイル自体はエラーにしなくてもいいかもしれません。
    "noUnusedLocals": true,

    // ここも移行していく場合とりあえずfalseでいいと思います
    "strictNullChecks": false,　// trueにすると例えば`number`にnullやundefinedを代入できなくします
    "strictFunctionTypes": false,
    "strictBindCallApply": false,
    "strictPropertyInitialization": false,
  },
}
```

### 3. 変更があったらサーバーを自動で再起動とかしたい
全部入りな`ts-node`を使う方法もありますが、今回は`tsc`コマンド + `nodemon`を使います
トランスパイル済みjsは`./dist`に吐き出されるものとします。

nodemon.jsonを作ります。`dist`をwatchして、変更があれば`"exec"`に書かれている内容を実行します。この場合`server.js`の再起動です
`"restartable"`はその文字を打つとexecを強制的に再実行します。あんま使いませんがたまに便利です。

```json-doc:nodemon.json
{
  "restartable": "rs",
  "watch": [
    "./dist",
  ],
  "exec": "node ./dist/server.js"
}
```

まずtypescriptのトランスパイルを実行します
`yarn tsc --watch -p tsconfig.json`

次にnodemonを起動します
`nodemon --config ./nodemon.json`


これで、
ファイルを変更したらtypescriptがトランスパイル -> 吐き出されたファイルをnodemonが検知して再起動
となり効率の良い開発が可能になります。
git filter-repoってなんぞ

ある日、いつものようにgitで歴史改竄をしようとしたらこんな警告文が…

```bash
WARNING: git-filter-branch has a glut of gotchas generating mangled history
         rewrites.  Hit Ctrl-C before proceeding to abort, then use an
         alternative filtering tool such as 'git filter-repo'
         (https://github.com/newren/git-filter-repo/) instead.  See the
         filter-branch manual page for more details; to squelch this warning,
         set FILTER_BRANCH_SQUELCH_WARNING=1.
```

要するに`git filter-branch`が新しくなんかいい感じになった`git filter-repo`があるらしいです。

## インストール

デフォルトではインストールされていないので、追加でインストール作業が必要です。
Homebrewだとこんな感じ。それ以外は[こちら](https://github.com/newren/git-filter-repo/blob/master/INSTALL.md)を見てください

```bash
brew install git-filter-repo
```

(Windowsはpipからインストールするしかないのか…)

## 使い方

マニュアルは[こちら](https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html)。オプションは`git filter-branch`よりわかりやすくなってますね。

```bash:フォルダ移動
git filter-repo --to-subdirectory-filter my-module
```

```bash:src以下だけ残す
git filter-repo --path src/
```

```bash:ReadMe.mdだけ消す
git filter-repo --path ReadMe.md --invert-paths
```
JSの正規表現の先読み後読み

## 肯定先読み
```typescript
> /a(?=b)/.test("ab")
true
```

## 否定先読み
```typescript
> /a(?!b)/.test("ab")
false
```

## 肯定後読み
```typescript
> /(?<=a)b/.test("ab")
true
```

## 否定後読み
```typescript
> /(?<!a)b/.test("ab")
false
```
seleniumIDEで要素の有無をチェック

##何故やろうとしたのか
ログイン画面対策のため
→ログイン後に再度アクセスした際にログイン画面が無いと、フロー上にあるログイン画面での処理部分でseleniumIDEが止まる
→見かけた『${!LastCommandOK}がtrueかどうかで判断』が上手く機能しなかったため
　→具体的にはverifyElementPresentをif文の前でかけると1回目は問題ないのだが、2回目以降で走らせると確実にfalseになる状況でもなぜか貫通してtrue側を通ってしまった　なんで？(憤怒)
##どうやった
ログイン画面に「のみ」ある要素の数を「store xpath count」で数え、それが1かどうかで判断
→「0かどうか」の判断の方が考えやすいかもしれない
##コード

```例：ログイン画面の有無
store xpath count | xpath=//input[@value='ログイン'] | id
if　　　　　　　　 |${id}==="1" ←ここは適宜書き換えで
　～ログインID記入なりパスワード記入なりログインボタンクリックなりの「ログイン画面における処理」～
end
```
"特定画面にのみある要素"の"数"を判別の基準にしてる
今回はたまたまログイン画面における"input"且つ"valueがログイン"の要素が一つだけだったのでこの形で行けたが、ちと汎用性に欠ける気がせんでもない

##オチ
seleniumIDEは記録した後にこまい部分を書き換えられるのが良いね
ブラウザで完結するものならば、ボクがpython使って書いてる普通のseleniumよりも直感的で扱いやすい感じ
この要素数が0かそれ以外かはボクがVBAでよく使っていた条件式だから、色々と使える考え方だと思う
【Git】中途半端でコミットしたく無いけど別の作業がしたい！(git stash)

Git コマンド紹介：`stash`
まあまあ使うので、まとめておきます。

# stash
## こんな時に使う
作業が中途半端だ！コミットしたく無い！でも、別のブランチにチェックアウトしたい！

## 使用例
`git stash save`：いったん保存
↓
`git checkout 別branch`
別の作業...
`git checkout 元branch`
↓
`git stash list`：保存したものの確認
↓
`git stash pop stash@{スタッシュ番号}`：保存してたものを戻す(listから消す)
or
`git stash apply stash@{スタッシュ番号}`：保存してたものを戻す(listに残す)

### 解説
```
% git sss
## master...origin/master [ahead 1]
 M index.html
```
今、`master`ブランチで作業していて、`index.html`が未コミットです。
stashコマンドを使っていきます。

```
% git stash save
Saved working directory and index state WIP on master: 6c22e4e add directory
```
保存できました。これで、**別ブランチにチェックアウトしてOK。**
`branch`ブランチで別の作業をします。

```
% git checkout branch
Switched to branch 'branch'

作業...

% git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)
```
作業が終わり`master`ブランチに戻ってきました。

```
% git stash list
stash@{0}: WIP on master: 6c22e4e add directory
```
保存がしっかり確認できます。これから、戻していきます。

#### apply（保存を残す）
```
% git stash apply stash@{0}
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   index.html

no changes added to commit (use "git add" and/or "git commit -a")
```
これで無事`master`での作業に戻れました。ちなみに、

```
% git stash list
stash@{0}: WIP on master: 6c22e4e add directory
```
`stash apply`はlistに残ります。

#### pop（保存を残さない）
```
% git stash pop stash@{0}
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   index.html

no changes added to commit (use "git add" and/or "git commit -a")
Dropped stash@{0} (732983fc2774b21734c7ee64d1d463f42ac6a41f)

% git stash list

```
`stash pop`はlistに残りません。

---

## その他のstashコマンド
- `git stash save "コメント"`：コメントをつけて保存
- `git stash drop stash@{スタッシュ番号}`：listから消す
- `git stash clear`：listから全て消す
今作っているものの構成をまとめたい

# 前置き
・書いてる人はWEBエンジニア1年の素人です。
・Docker初めてさわる
・GCP初めてさわる
・Django初めてさわる

# 今作っているもの
CloudRun上で動作するウェブアプリケーション
 - Django 3.0.3
 - Python 3.8.0
 - gunicorn 20.0.4
 - Docker 19
 - Docker-compose (ローカルでしか使わない、cloudrunで動かないので（動かせるかも？まだよくわかってない））
 - Cloud SQL (mysql)
 - SQLAlchemy
 - alembic

# これから似たような構成を作ろうとしている方へ
 - なるべく公式のtutorialを参考にする
 - なるべく最近の記事を参考にする（かなり最近の方が良いです）
 - GCPの公式リファレンスはとても有用（Djangoのsampleプロジェクトまでありました…）

# 環境構築中の所感
 - Docker何それから始まったのでとても苦労した
 - Docker上で環境を構築してからcloud runの流れでやろうとすると苦労するかも
 - 最初からcloud runの公式チュートリアルで進めた方が無難かも
 - とはいえDockerでイメージを作ったりコンテナの中に入ったりDockerを体で理解するためには遠回りも意味があった
 - Dockerまわりの参考記事は基礎知識が端折られてたりする
 - Docker run はホストマシンとポートをバインドしないとコンテナとやり取りできない

最後のが個人的にはかなりつらい思いをした。
当たり前といえば当たり前だけどかなり時間を食った、というか起動オプションが何が必須で何が必須かわかりにくい…。
コンテナが正しく動かない理由がDockerfileが悪いのか、起動方法が悪いのか、コンテナはログを出せるけど詳細なログまで追う方法が仮想ではないコンソールの環境とは異なるため何が原因か探りにくかった。とにかく確実に動くもの、成功したコマンド、そういうものを積み重ねるか本質的な理解をしないとかなり躓く印象があった。

DockerFileの設定とか起動コマンドとかそのあたりがある程度固まってきた後は割とすんなり。
cloud SQLにSequelで接続する方法としては、GCPから提供されているプロキシを起動した状態でSequelのホストは127.0.0.1:PORTの標準の接続方法でいけた。
これらの設定はプロジェクトが終わった後にきっちりまとめたい。


：3/16追記

・webpackの設定とかいろいろやったけど、結論nuxt使った方が圧倒的に楽...
・ただいきなりnuxtから入ると何がなんやらだったので、フレームワークがやっていることを自分で組み立てて構築することの意義は感じた。やった方がいいとおもう。

:3/19追記

# cloud-runはすごい
例えば、開発中に色々レイアウトをいじってたりする。
クラウドrunはデプロイしたバージョンを管理していて、いつでもお手軽に切り替えられる。
つまり、「昨日イケてないわ〜と思ったあのレイアウトもう１回見たいな〜」とかそういう時に、gitのcommit logからハッシュを探して開発環境を元に戻して・・・とかそういうことをしなくていい。
デプロイしたビルドに名前をつけておけば、開発用のcloud-runの環境があるならいつでも確認できる。
もしバグがあったなら、調査もすぐできるし、他の人にデバッグをお願いする時もURLを渡すだけ。
いちいち環境がどうだったとかまとめてもらう必要はない。
なぜならデプロイされたバージョンで全て再現されているから。

しゅごい、本当にしゅごい・・・（ああ嗚呼あaaaa~〜〜〜〜）
Railsを用いたアプリケーション開発の流れ

#はじめに
Railsを用いてアプリケーション開発をするための流れを簡潔にまとめたいと思います。

##概要
以下の流れで実装を行い、トップページにデータベースに保存してあるデータを表示する機能を作成します。
1.アプリケーションの土台となるものを作る
2.データベースを作る
3.ルーティングの設定
4.コントローラの作成
5.ビューの作成
6.モデルの作成
7.ビューにインスタンス変数を埋め込む

##1.アプリケーションの土台となるものを作る
まずはアプリケーション用のディレクトリを作成してください。
そのディレクトリの直下で以下のコマンドを入力します。x.x.xの部分はrailsのバージョンを入れてください。
```rails _x.x.x_ new アプリケーション名 -d 使用するデータベース``` 
これでコマンドを実行したディレクトリの直下に様々なファイルが作成されたはずです。これがアプリケーションの土台となります。

##2.データベースを作る
以下のコマンドでアプリケーションで使用するデータベースを作成する事ができます。
```rails db:create```
実際にデータベースを確認して見ましょう。「アプリケーション名_development」と「アプリケーション名_test」というデータベースが作成されているはずです。

##3.ルーティングの設定
「1.アプリケーションの土台となるものを作る」を実行していれば、/アプリケーション用のディレクトリ/config/app の配下にroutes.rbというファイルが作成されていると思います。このファイルに「root to: "posts#index"」を追記しましょう。

```ruby
Rails.application.routes.draw do
  root to: "posts#index"
end
```
これで「root」ディレクトリにリクエストがあった場合、
「posts」コントローラに処理が遷移し、
postsコントローラの「index」アクションの処理を行う、となります。

##4.コントローラの作成
以下のコマンドでコントローラーを作成できます。「3.ルーティングの設定」でpostsコントローラに処理が遷移するとしたため、今回はコントローラー名をpostsにしましょう。
```rails g controller コントローラー名```

##5.ビューの作成
今回は、postsコントローラのindexアクションに対応するビューであるため、/アプリケーション用のディレクトリ/app/views/posts の配下にindex.html.erbを作成しましょう。コントローラから受け取るインデックス変数などの処理は後ほど記載します。

##6.モデルの作成
ターミナルで以下のコマンドを実行しましょう。
これでモデル名をpostにすればpostsテーブルに対応するモデルができます。
```rails g model モデル名```

##7.ビューにインスタンス変数を埋め込む
1~6までの流れでテーブルからデータを抽出する事ができ、@posts(インスタンス変数)にデータが格納されました。あとはビューを修正してインスタンス変数を画面に出力するようにすれば完成です。

```ruby
# 修正例
<% @posts.each do |post|%>
  <div>
    <%= post.text %>
  </div>
<% end %>
```

##雑感
３日ほどRubyとRailsについて学び、WEBアプリケーション制作におけるはじめの一歩が踏み出せたのではないかと思います。ちなみに筆者は漫画のはじめの一歩も大好きで、ベストバウトは間柴対木村です。
npmコマンドで順番を無視した引数を使う方法

npmコマンドを書いている中で、オプションを`process.argv[2]`と取りますが、
これの順番を決め打ちで取りに行かない方法を探した結果、`argv`を使うことにしました。

# 前提条件
- npmがインストールされていること
- package.jsonがあること

# インストール
```shell
$ npm install -D argv
```

# 使い方
## 設定

`touch`コマンドでファイルを作成します。

```shell
$ touch test.js option.json
```

argvモジュールの読み込みと、option.jsonの読み込み、
argvのメソッドで引数のデータを取り込みます。

```javascript:test.js
const argv = require('argv')
const option = require('./option')
const args = argv.option(option).run()

console.log(args)
```

引数で使うための名前と型、を設定するオブジェクトを設定します。
配列になっているため、必要な数だけオプションを増やすことが可能です。

```json:option.json
[
  {
    "name": "option",
    "short": "o",
    "type": "string",
    "description": "あなたのスクリプトのオプションを定義します",
    "example": "'script --option=value' or 'script -o value'"
  }
]
```

`npm run test`コマンドでtest.jsを動かすように定義します。
オプションの設定をされていない引数は配列でtargetsとして記録されます。

```json:package.json
{
  "scripts": {
    "test": "node test sample -o aaa"
  }
}
```

## 実行
npmコマンドを実行します。

```shell
$ npm run test
```

## 出力結果
```console
{ targets: [ ‘sample’ ], options: { option: 'aaa' } }
```

オブジェクト形式でデータが取れているので、特定の値を取るときは、
`args.options.option`という形式で`aaa`と取ることができます。

# 参考文献

この記事は以下の情報を参考にして執筆しました。

- [node.jsでコマンドライン引数の処理を行うなら「argv」が便利](https://shimz.me/blog/node-js/1784)
- [argv - npm](https://www.npmjs.com/package/argv)
竹内関数をメモ化で高速化する (物事のやり方は一つではない -- Perl)

# はじめに
Perl で竹内関数をメモ化によって、高速にしようとあれこれやります。
# 竹内関数とは
[これ](https://ja.m.wikipedia.org/wiki/%E7%AB%B9%E5%86%85%E9%96%A2%E6%95%B0)です。Perl で書くとこんな感じです。

```tarai.pl
sub tarai
{
    my ($x, $y, $z) = @_;
    return $y if $x <= $y;
    tarai(  tarai($x-1, $y, $z),
            tarai($y-1, $z, $x),
            tarai($z-1, $x, $y));
}
```
# 簡単な補足
奥村晴彦『C言語による最新アルゴリズム事典』技術評論社では、たらいまわし関数に特に用途はない、と説明されています。
ここでは、プログラムのベンチマークとして利用します。
# ベンチマーク測定
少々心苦しいのですが、[AtCoder：競技プログラミングコンテストを開催する国内最大のサイト](https://atcoder.jp/home) の Language Test 202001 コードテストを使用いたします。
実行時間に加え、メモリの使用量がわかります。
# 素朴な実装

```memo00.pl
use strict;
use warnings;

sub tarai
{
    my ($x, $y, $z) = @_;
    return $y if $x <= $y;
    tarai(  tarai($x-1, $y, $z),
            tarai($y-1, $z, $x),
            tarai($z-1, $x, $y));
}
print tarai(12, 6, 0), "\n";
```
||Perl(v5.18.2)|Perl(v5.26.1)|
|:-----:|:-----:|:-----:|
|実行時間|3523 ms|2342 ms|
|メモリ|300052 KB|980 KB|

おっ、新しいテスト環境は速くなってる。
# メモ化
```memo01.pl
use strict;
use warnings;
use Memoize;

sub tarai
{
    my ($x, $y, $z) = @_;
    return $y if $x <= $y;
    tarai(  tarai($x-1, $y, $z),
            tarai($y-1, $z, $x),
            tarai($z-1, $x, $y));
}
memoize('tarai');

print tarai(12, 6, 0), "\n";
```
||Perl(v5.26.1)|
|:-----:|:-----:|
|実行時間|89 ms|
|メモリ|2164 KB|
メモ化、凄っ。
memoizeって追記しただけなのに。
凄すぎて、パラメータを増やさざるを得ない。

```
print tarai(100, 50, 0), "\n";
```
||Perl(v5.26.1)|
|:-----:|:-----:|
|実行時間|158 ms|
|メモリ|7220 KB|
# クロージャによる遅延評価

```memo03.pl
use strict;
use warnings;

sub tarai
{
    my ($x, $y, $z) = @_;
    return $y if $x <= $y;
    my $zz = $z->();
    tarai(  tarai($x-1, $y, sub { $zz }),
            tarai($y-1, $zz, sub { $x }),
            sub { tarai($zz-1, $x, sub { $y }); });
}
print tarai(100, 50, sub { 0 }), "\n";
```
||Perl(v5.26.1)|
|:-----:|:-----:|
|実行時間|78 ms|
|メモリ|908 KB|
さらに速い。
メモリ使用量も少ない。
# Ruby クロージャによる遅延評価
```memo.rb
def tarai(x, y, z)
  return y if x <= y
  zz = z.call
  tarai(  tarai(x - 1, y, z),
          tarai(y - 1, zz, proc { x }),
          proc { tarai(zz - 1, x, proc { y }) })
end

puts tarai(100, 50, proc {0})
```
||Ruby(2.7.0)|
|:-----:|:-----:|
|実行時間|126 ms|
|メモリ|9140 KB|
オブジェクト指向はメモリ食うよね　~~適当~~

# まとめ
+ メモ化や遅延評価は、思いの外高速化される
+ Lisp 恐るべし
+ 奥村さんはたらいまわし関数に興味がない

参照したサイト
[竹内関数をメモ化で高速化する工程 (Python には負けたくない)](https://qiita.com/kts_h/items/c3afa6eb678d4cd2089c)
[お気楽 Perl プログラミング超入門::メモ化と遅延評価](http://www.nct9.ne.jp/m_hiroi/linux/perl19.html#chap02)
[お気楽 Ruby プログラミング入門.番外編 遅延評価と遅延ストリーム](http://www.nct9.ne.jp/m_hiroi/light/abcruby18.html)
駆け出しエンジニアを自称している方々を見ていて思うこと

近頃、プログラミングに関係したアウトプットが多くなり、勉強会やカンファレンスなどに参加するようになった結果、Twitterにて職業エンジニアの方々と相互フォローになることが増え、タイムラインがエンジニア色になってきました。その結果、「駆け出しエンジニア」というキーワードも多く見かけるようになったのですが、駆け出しエンジニアを自称している方々のツイートを見ていると、「**その学習法、遠回りなんじゃないかなぁ**」と思うことが度々あります。プログラミングを習得したいという心意義は大変素晴らしいと思う一方で、習得するためにしている行動に対して以下のような疑問をよく抱きます。

# プログラミングを学習して何をしたいの？

プログラミングスキルを身につけたとして、何がしたいのでしょうか。あるいはどうなりたいのでしょうか。自分の経験上、具体的な目標設定をすることが学習する上でとても大切です。具体的なゴールがない状態で無闇矢鱈に学習を続けるのは不毛に思えます。とりわけ、プログラミングはソフトウェアを開発するための道具ですから、具体的に作りたいものがないのに、プログラミングを学習するというのが、今の私には意味が分からないです。

そもそも、「プログラミングができるようになりたい」という目標って意味が分からないんですよね（私も一番最初に掲げた目標がこれで、その時は挫折しています）。

プログラミングから離れて考えてみます。例えば、木工スキルを身につける時、「木工ができるようになりたい」と思うでしょうか？「棚を作りたい」とか「机を作りたい」と思う方が動機としては自然な気がします。クギの打ち方や鋸の挽き方からはじめ、何種類もの工作機械の扱い方を全てマスターしてから棚や机を作るのって大変だと思いませんか？恐らく、棚や机など具体的な物を作る際に必要なことをその都度学んでいくのが普通だと思います。それで、効率を向上したいと思ったり、どうしても今持っている道具では難しいとなったり、ワンランク上の表現をしてみたいと思った時に、新しい道具を手に入れて扱い方を学ぶという風にコツコツやっていくのが妥当な気がします。

すなわち、具体性の欠けた目標を掲げるのではなく、具体的な目標を掲げる方が自然ですし、確実に達成していけそうです。他の例であれば、

- 料理ができるようになりたい → 〇〇という料理を美味しく作れるようになりたい
- ピアノが弾けるようになりたい → 〇〇という曲を弾けるようになりたい
- 英語ができるようになりたい → 国際グループチャットで英語で会話できるようになりたい

という風に具体的な目標を掲げた方ができるようになりそうですよね。（この件に付随する話では、やりたい事業が決まっていないのに起業したいって言っている人もよく分からないです。起業家になるのが夢ってものすごく中身がないように見えます。）

したがって、プログラミングにおいても、何か具体的なプロダクトを作るために必要な知識をその都度身につけていく方がスキルの習得には近道だと思います。具体的であればあるほど、やるべきことが明確になり良いと思います。例えば、「プログラミングができるようになりたい」から一歩進んで「アプリを作りたい」という目標にしたとしてもまだ具体性に欠けるのでダメです。もっと具体的な方が良いでしょう。というか、プロダクトのアイデアがないなら、まだ学ぶ時ではないと思って、見送ってもいいかもしれません。そういう意味では、プログラミング未経験でエンジニアではない人が、急にエンジニアに転職しようとして勉強し始めるというのも、今の自分には賢い選択だとは思えません。一方で、趣味で作りたいプロダクトを手がけていて、いつの間にかスキルは身についていたので、転職してみようというのはすごく納得がいきます。ここら辺、プログラミング学習を支援しているサービスを運営している方々はどう思っているのでしょうか。体系的な知識が詰まった教材を与える形式の支援方法よりも、具体的に作りたいものがある人を支援する方が良さそうな気がします。

# 本当はプログラミングができるようになりたいんじゃないのでは？

これは私の偏見がかなり入っていると思うのですが、駆け出しエンジニア宣言していて、自己啓発系のアウトプットが多い方々は、プログラミングができるようになることが目標ではなく、「有名になること」、「楽して稼ぐこと」、「なんとなくかっこいいイメージのあるエンジニアという存在になること」とかが真の目標なのではないかと少々疑ってしまいます。

なんというか、**ものづくりってそういうことじゃないんだよなぁ**と思ったりします。本当にスキルを習得したいなら、ものづくりに対して真摯な態度で望むのが近道な気がします（というかそうであって欲しい）。きかっけは不純でも良いので（不純な方が意外と継続できたりする）、何処かのタイミングでエンジニアリングに対するこだわりを見つけて欲しいですね。
ミルクボーイネタでハッシュ値を説明してみた

# きっかけ

流行りに乗りたかっただけです。
東北の人間なので関西弁はよくわかりません。

# 本編

「うちのオカンがね、パスワードDBの情報をどう管理するか悩んでてな。」
『そうなんや。』
「良さそうなのを見つけたのはいいんやが、その名前を忘れたらしいねん。」
『ほんなら一緒に考えてあげるから、特徴言ってみてー。』

「オカンが言うには、どんな長いパスワードでも決まった長さの値に変換されるらしいねん。」
『そりゃお前、ハッシュやな。ハッシュは元の文とは脈絡のない**固定長の値**に変換するんや。元のパスワードだけでなく文字数も推測できなくなるからええな。』

「俺もハッシュと思ったんやけど、でも変換後の値からパスワードに戻すことができると言うねん。」
『ほなハッシュちゃうかあ。ハッシュは**一方向性**ゆうて、ハッシュ値からパスワードには戻せへん。いちいちパスワードをハッシュ化して結果を突き合わせるしか一致不一致を確認できひんから、元のパスワード情報はDBで持たずハッシュ値だけ管理しておくことでより安全になるんや。』

「そういえば、パスワード秘匿以外にも改竄チェックやウイルスの検知にも使われる技術って言うてたで。」
『ハッシュやないか！**たった１文字、大文字小文字が変わる程度でもハッシュ値は大きく変わる**から、ぱっと見で元データが同じかどうかを判断しやすいんや。』

「でも全然違うオカンとオトンのパスワードは変換すると同じ値になるって言うねん。」
『ほなハッシュちゃうかあ。ハッシュ値のパターンは有限だから複数のパスワードが同じハッシュ値になることはあるんやが、**衝突発見困難性**が保証されてるから、同じハッシュ値を持つパスワードは自力ではまず見つからんで。というかDBはパスワードのハッシュ値しか持たないから認証もハッシュを比較するんや。オカンの言う通りなら他人のパスワードで認証通るからコレ使えへんぞ！』

「あと、データ変換のくせに何故か塩やコショウをまぶすらしいねん。どう言うこっちゃ。」
『そらハッシュしかないやろ！変換アルゴリズムは公開されているから、**レインボーテーブル**っていうパスワードとハッシュ値の対応表を作られたら簡単にパスワードがバレるんや。そのために**ソルト**とか**ペッパー**と呼ばれる乱数を加えてから変換処理して、対応表の作成が面倒になるようにしてんねん。』

「でも、変換後の値を逆算したらソルトを加えたパスワードとは一致したって言うねん。」
『ほなハッシュちゃうかあ。ハッシュ値は**第二現像計算困難性**っていう性質があって、ハッシュ値から別のパスワードを探すことは難しいんや。オカンの言う通りなら今頃悪い奴が勝手にパスワード作り出して不正ログインしてる可能性もあるやんけ。やっぱりコレ使えへんぞ！』

『もうホンマにわからへんやん、今のところ何やと思ってんのよ？』
「オトンが言うにはBashちゃうかって」
『絶対ちゃうやろ、もうええわ。ありがとうございました。』

# 懺悔

この記事書いてからミルクボーイのネタを初めてみました。面白かったです。
docker入門　ubuntuの中にubuntu環境を作る

# 目的
dockerの使い方としてはメジャーではないかもしれないが，ubuntuのdockerコンテナを作成してそこにsshで入って色々と開発をやりたい．

dockerを触るのは初めてで，いろんな資料を見たけど似たような事例が少なかったので備忘録として．

# 流れ
- dockerのインストール
- Dockerfileの作成
- dockerイメージの作成
- dockerコンテナの起動
- dockerコンテナへ接続

# dockerのインストール
[公式サイト](https://docs.docker.com/install/linux/docker-ce/ubuntu/)に従う

```console
$ sudo apt-get remove docker docker-engine docker.io containerd runc

$ sudo apt-get update

$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

$ sudo apt-key fingerprint 0EBFCD88

$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

$ sudo apt-get update

$ sudo apt-get install docker-ce docker-ce-cli containerd.io

$ sudo docker run hello-world
```

これでとりあえずHello world.
このままだといちいちsudo付けないとdockerコマンドを使えなかったので，

```console
$ sudo gpasswd -a <user> docker
```
これでsudo付けなくて良くなる．

# Dockerfileの作成
今回作成したDockerfileは以下の通り．

```Dockerfile
# 使用するubuntuのバージョンを指定
FROM ubuntu:18.04

# 使うコマンドをインストール
RUN \
	apt update && \
	apt -y upgrade && \
	apt install -y build-essential && \
	apt install -y software-properties-common && \
	apt install -y curl git man unzip vim wget sudo

# rootだと色々と不便なので，ユーザーを作成
RUN useradd -m hoge
# ルート権限を付与
RUN gpasswd -a hoge sudo
# パスワードはpassに設定
RUN echo 'hoge:pass' | chpasswd
# sshログイン時のシェルをbashに設定
RUN sudo sed -i 's/hoge:x:1000:1000::\/home\/hoge:\/bin\/sh/hoge:x:1000:1000::\/home\/hoge:\/bin\/bash/g' /etc/passwd

# sshするための設定（公式サイト参考）
RUN apt install -y openssh-server
RUN mkdir /var/run/sshd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
```

# dockerイメージの作成からログインまで
### dockerイメージの作成

```console
$ docker build . -t myubuntu:18.04
```
Dockerfileをおいたディレクトリ内で実行．myubuntu:18.04は任意の名前．
以下のコマンドで確認できる．

```console
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
myubuntu            18.04               iiiiiidddddd        6 minutes ago       496MB
```

### dockerコンテナの起動

```console
$ docker run -d -P --name test myubuntu:18.04
```
dockerイメージからコンテナを作成し，起動する．
`-d`でバックグラウンド実行，
`-P`でECPOSEしたポートをローカルとつなげる，
`--name`でコンテナ名を指定．

### dockerコンテナへssh接続

```console
$ docker port test 22
0.0.0.0:32768
```
で表示されたポートに対してsshする．

```
$ ssh hoge@localhost -p 32768
hoge@localhost's password:<pass>

Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-47-generic x86_64)
...
hoge@nyonyonyo:~$
```

コンテナ内にユーザーhogeでssh接続し，bashを起動することができた！
あとはこの中で開発しまくれる（はず）．

# 参考
https://docs.docker.com/engine/examples/running_ssh_service/
https://qiita.com/techno-tanoC/items/58e9c5c74d90392d9de4
DELL版Windows 2000を仮想環境上にインストールする

Linuxが動いているDELLにWin2kを仮想環境で動かしたくなった人向け。

#既存Windowsからアップグレードインストール

しようとするとこうなります。
![shot1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567899/02933452-1c17-a7c9-d216-17247dbff3af.png)

Windows上でBIOSチェックを行っているという事になります。
これがどういう仕組みなのかは既に先人が調査済です。I386フォルダ内のBCHK32.EXEという隠しファイルがBIOSチェックを行っているようで、DELLのBIOSなら「+++」、そうでないなら「---」を出力し、その結果に応じてセットアッププログラムを起動するかしないかという判定を行っているようです。

そこで、バイナリエディタからBCHK32.EXE に変更を加えてみます。ただし、今回は面倒なのでイメージに抽出したISOファイルを直接いじります。

ISOファイルから「2B 2B 2B 00 25 73 00 00 2D 2D 2D」というバイナリを検索し、最後の2D 2D 2D(---)を2B 2B 2B(+++)にします。
画像はBCHK32.EXEですが、ISOは無圧縮なので直接上書きしても問題ありません。ただし、バイナリを削除するとISOやIMGといったイメージファイルは壊れます。CDイメージのファイル差し替えはAnyBurn、FDイメージのファイル差し替えはDiskExplorerなどを使うと良いです。
![shot2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567899/e735a782-b64a-4ee6-b857-9333e6e0a474.png)

変更して再度実行してみたところ、DELLじゃなくても「+++」とBCHK32.EXEが出力するためにDELLのBIOSと誤認識しセットアッププログラムが起動しました。
![shot3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567899/9f1a6244-8316-cf62-1634-7aded496809f.png)

でも今回やりたいのはこれではなく「新規インストール」なので、この方法ではセットアップできません。

# FDブートからのインストール
通常、DELLのインストールディスクからCDブートを試そうとすると、このような画面になりセットアップできません。
![shot4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567899/a0957e7a-18d3-728e-20a7-c26c466ab730.png)

FDブートならどうだろうかと試してもみました。Windows2000のインストールディスクにはFDブートをさせるための4枚のFDイメージがBOOTDISKフォルダ内に格納されています。DELL版も例外ではありません。

しかし、結果はCDブートと同様、上のようなメッセージが出てきました。

CDBOOT1.IMG内には6つのファイルが格納されています。

```
DISK101
NTDETECT.COM
NTKRNLMP.EX_
SETUPLDR.BIN
TXTSETUP.SIF
BIOSINFO.INF
```

リテール版Windows 2000(SP無し)のCDBOOT1.IMGと比較してみたところ、以下の通りになりました。


```
===内容が同一===
DISK101
BIOSINFO.INF

===内容が異なる===
NTDETECT.COM
NTKRNLMP.EX_
SETUPLDR.BIN
TXTSETUP.SIF
```

TXTSETUP.SIFはセットアップするファイルリストのようなものなので起動には関係がありません。ちなみにDELLのSP2適用済のものより、SP適用無しのリテール版のほうがファイルサイズが大きいのでドライバ関連が異なるのかもしれません。これは後で調べます。

しらみつぶしにDELL版のFDに一つずつ異なっていたファイルをコピーして調査をしてみたところ、原因はSETUPLDR.BINにあることがわかりました。

DELL版のSETUPLDR.BINはリテール版と比べ00000000~000011FFまで余分なヘッダが存在し、そこでDELLのBIOSかDELLでないBIOSかを区別しているものと推測されます。

試しに実験として、DELL版のSETUPLDR.BINを000011FFまで削除し、00001200から始まるファイルとして変更してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567899/f244e6de-5e5e-20d7-6c9f-bdc5f0833285.png)

とりあえずさっきのメッセージは出てこなくなり、セットアッププログラムが起動しました。

画面を進めたところ、普通にセットアップできました。プロダクトキーはDELLの筐体に貼ってあるCOAシール記載のものを入力しました。リテール版のキーは通らなかったです。

#CDブートからのインストール
FDイメージ内のSETUPLDR.BINと、CDのI386フォルダ内のSETUPLDR.BINは同一ファイルなので、先と同様に00000000-000011FFまでを削ったものに差し替えれば起動できます。

#リテール版との比較
検証するにあたってSP適用なしのリテール版のセットアップディスクからもW2Kをインストールしましたが、試しにDELLのキーを入力したところ「無効なキー」としてはねられました。

インストールされるファイルの数をWinMergeで比較してみたところ、内容に差はあっても数については変わらないようです。むしろSP2が適用されたDELL版のほうが多かったです。リテール版にしかないファイルもありましたが動作に影響を与えないようなもの、例えばプロバイダの画像の種類が多いというぐらいでした。DELL版でもリテール版でも内容は違うかもしれませんが、同じ数のドライバがインストールされていました。

つまり、DELL版とリテール版でインストールされる内容は同じでした。
【MySQL 】便利な大文字のテーブル名、カラム名の検索SQL 

###困った問題

テーブル名やカラムは英小文字でという暗黙のルールがある。
ところが幾つか大文字のテーブル名があるというのだ。
あるデータベース内にどれくらい大文字のテーブル、カラムがあるか調べる事になった。
最初は担当しているプロジェクト分のみで
いい事になっていた。
何と言っても、データベース内には5000を超えるテーブルと50000近いカラムがあったからだ。
参考サイトをもとに、下記のSQLを作ってみた。



###DB内のテーブルとカラムの検索

####1.ダサイけど応用が効きそうなSQL

```sql
use information_schema;
select table_name,column_name from columns where table_schema="データベース名"
and (concat(table_name,column_name) like binary "%A%"
or concat(table_name,column_name) like binary "%B%"
or concat(table_name,column_name) like binary "%C%"
or concat(table_name,column_name) like binary "%D%"
or concat(table_name,column_name) like binary "%E%"
or concat(table_name,column_name) like binary "%F%"
or concat(table_name,column_name) like binary "%G%"
or concat(table_name,column_name) like binary "%H%"
or concat(table_name,column_name) like binary "%I%"
or concat(table_name,column_name) like binary "%J%"
or concat(table_name,column_name) like binary "%K%"
or concat(table_name,column_name) like binary "%L%"
or concat(table_name,column_name) like binary "%M%"
or concat(table_name,column_name) like binary "%N%"
or concat(table_name,column_name) like binary "%O%"
or concat(table_name,column_name) like binary "%P%"
or concat(table_name,column_name) like binary "%Q%"
or concat(table_name,column_name) like binary "%R%"
or concat(table_name,column_name) like binary "%S%"
or concat(table_name,column_name) like binary "%T%"
or concat(table_name,column_name) like binary "%U%"
or concat(table_name,column_name) like binary "%V%"
or concat(table_name,column_name) like binary "%W%"
or concat(table_name,column_name) like binary "%X%"
or concat(table_name,column_name) like binary "%Y%"
or concat(table_name,column_name) like binary "%Z%");
```
####2.スタイリッシュなSQL

```sql
use information_schema;
select table_name,column_name from columns where table_schema="データベース名"
and binary concat(table_name,column_name) != binary lower(concat(table_name,column_name))

```

実際に出力されたのは、2つのテーブルの10カラムのみで、目視では100%発見できない。
この威力は凄い。

###参考URL 

[MySQLでテーブル一覧とカラム一覧を同時に取ってくる](https://qiita.com/furusin_oriver/items/f81351c96efbb40432df)
基本情報技術者　ストラテジ系　第1章 システム戦略②


# ②経営戦略の基礎

競争戦略: どのように競争に打ち勝てるか思考し、戦略としたもの

## 競争戦略

### 五つの競争要因

#### 新規参入者の脅威

#### 代替品、代替サービスの脅威

#### 買い手の交渉力

#### 売り手の交渉力

#### 競争相手との敵対関係

### 三つの基本的戦略
競争要因に対抗するための戦略

#### コストリーダーシップ戦略

#### 差別化戦略

#### 集中化戦略(ニッチ戦略)

## マーケティング戦略
基本的な4つのP要素があります。

* Product(製品)
* Price(価格)
* Place(流通)
* Promotion(プロモーション)

### 製品戦略
売れる製品を作る戦略

#### 製品多様化

#### 製品差別化

#### 市場細分化

#### 計画的陳腐化

### 価格戦略

#### 原価志向型

#### 競争志向型

#### 需要志向型

### 流通戦略
売り方の戦略、店舗、ネット販売など

### プロモーション戦略

#### ブル型
TV,新聞なd

#### プッシュ型
訪問や店頭での推奨販売など

## 競争地位とマーケティング戦略
地位によって戦略は変わります。

### リーダ
市場トップ企業、拡大を目指す

### チャレンジャ
2~3位の企業,競合の弱点をつく

### フォロワ
下位の企業,トップの模倣でコスト削減

### ニッチャ
シェアは低いが専門分野に強み

## マーケティング関連用語

### プロダクトライフサイクル
市場の一生を扱う
導入機→成長期→成熟期→衰退期

### 顧客ロイヤリティ
ブランド力のこと

### ライフタイムバリュー
顧客一人の企業に対する一生の損得

### マスケーティング
多くのお客様に提供する

### ワントゥーワンマーケティング
細かなニーズに答える。1対1
【#PowerApps Tip's】いつも出てくるアイツは消して良い

今回はとても軽いネタです。
# 気になりませんか？
Power Apps のアプリを新規作成する際に表示される、コレ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215892/0e9bec24-1444-4f52-cf7f-01c5966a8670.png)

テスト実行した後で、編集画面で表示されるコイツ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215892/a4f37c61-2b82-b01e-0c1f-f30893a4d1ab.png)

これ、慣れてくると・・・邪魔くさいですよね（暴言

# 消せます（ただし初回以外）
編集画面の初回、およびテスト実行後の初回は確実に表示されます。
が「今後このメッセージを表示しない」にチェックを入れてしまえばOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215892/ba60b4c8-56f9-d64f-e880-d79b8aad98d4.png)

上記にチェックを入れた後は、2度と表示されなくなります。
ただし、ブラウザーを閉じるまで・・・。

そう、所謂セッションが破棄されると再度表示されます。なので、安心して「表示しない」にチェックを入れてよいのです。

# こんなネタを投稿した理由
このメッセージを「表示しない」にしてもいいんだよ、って教えるタイミングが思った以上に多くて・・・。この話題を教えた相手に「なぜ消さないの？」と質問すると、殆どの方が下記のように答えるんです。

「これチェック入れたら、ほんとに2度と表示されないんじゃないの？」
「今後、万が一重要な表示だとわかったら取返しつかないんじゃ・・・」

って、不安だったからチェック入れられなかった、と。

個人的に『今後』という先頭の2文字が良くないと思っています。素直にとらえると、2度と表示しない、と受け取られても仕方ないですよね。

安心してください（？）ブラウザーを再起動すれば、何度でも出会えます！ｗ

# 実は・・・
2019年8月に名古屋で開催したコミュニティ勉強会でもお伝えしてるんですよ。

<iframe src="//www.slideshare.net/slideshow/embed_code/key/awr5oHcx6VRCEG?startSlide=54" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/TeruchikaYamada/powerapps-162807949" title="PowerApps 初心者の館？" target="_blank">PowerApps 初心者の館？</a> </strong> from <strong><a href="//www.slideshare.net/TeruchikaYamada" target="_blank">Teruchika Yamada</a></strong> </div>


スライド 53枚目あたりです。

怖くてチェック入れられなかった皆さん。明日からは勇気をもって「表示しない」ってできますね！

ほんの少しの表示内容なんですが、ソレが無いだけで作業効率が変わってくると当方は考えています。初心者の方は、表示された内容を確認することで学びがあるのも重々承知しております。が、慣れてきた方は「表示しない」で全力OKです。

再び出会いたい際は、キャッシュクリア or ブラウザー再起動です！

それでは、皆さま。素晴らしい Power Platform Life を！
GoをAWS Lambdaで動かす一番小さいサンプルメモ

# 前提
- Go 1.x
- ローカル環境でGoが動く
- デプロイは lambroll
- IAMロール作成済み
- 手元にAWSの認証情報がある

# メモ

必要なパッケージのインストール

```zsh
% go get -u github.com/aws/aws-lambda-go/lambda
```

コードの準備
`hogehoge` をログ出力するだけ。引数も戻り値も考慮しない。

```go:hello.go
package main

// 一番最小限のLambda
import (
  "fmt"
  "github.com/aws/aws-lambda-go/lambda"
)

func hello() {
	fmt.Println("hogehoge")
}

func main() {
  lambda.Start(hello)
}
```

ビルド

```zsh
# hello バイナリが出来る
% go build -o hello
```

デプロイ準備

```zsh
% lambroll init --function-name hello-go --region "ap-northeast-1
```

function.json 更新

```json:function.json
{
  "FunctionName": "[Function Name]",
  "Handler": "hello",
  "MemorySize": [MemorySize],
  "Role": "[Role ARN]",
  "Runtime": "go1.x",
  "Timeout": [Timeout Second]
}
```

デプロイ

```zsh
% lambroll deploy --region "ap-northeast-1"
```

あとはマネコン等で適当に実行

# 参考

AWS Lambda で Go が使えるようになったので試してみた ｜ Developers.IO https://dev.classmethod.jp/cloud/aws/aws-lambda-supports-go/

Go の AWS Lambda 関数ハンドラー - AWS Lambda https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/go-programming-model-handler-types.html
mac rbenv バージョンの違うRubyをインストールして切り替えて使用する

# 目的

- home brewを用いてmacにバージョン違いのRubyをインストールする方法をまとめる

# 実施方法概要

1. home brewのインストールリストの更新
1. Rubyのインストール
1. Rubyバージョンの切り替え

# 実施方法詳細

1. home brewのインストールリストの更新
    1. 下記コマンドを実行してhome brewのインストールリストを更新する。

        ```terminal
        $ brew upgrade ruby-build
        ```

1. Rubyのインストール
    1. 下記コマンドを実行して欲しいバージョンのRubyをrbenv経由でインストールする。(X.X.Xがバージョン)

        ```terminal
        $ rbenv install X.X.X
        ```

1. インストール確認
    1. 下記コマンドを実行して先に指定したバージョンのRubyがインストールされていることを確認する。(`*`が付いているものが現在割り当てられているバージョンになる)

        ```terminal
        $ rbenv versions
          system
          2.3.0
          * 2.5.0 (set by /Users/shun/workspace/study/rails/tropical_fish_sns_of_rails/.ruby-version)
          2.6.2
        ```

1. Rubyバージョンの切り替え
    1. 下記コマンドを実行してインストールされているRubyのバージョンを変更する。(X.X.Xはバージョン、`$ rbenv versions`の出力の中から指定する。)

        ```terminal
        $ rbenv global X.X.X
        ```
Salesforce組織のメタデータを自動バックアップするツール作ってみたその3

#今回の成果物
　以前作成したSF組織のメタファイルをスケジュールで自動で取得するファイルをGit管理できるようにしました。今回はリモートへのプッシュは行っておらず、ローカルで個人で管理する用に作成しました。

必要なものは前回のものに追加して以下のもの。
・Gitのインストール

#フォルダ構成

```
myorg/
┣unpackaged
┃ ┗package.xml
┣build.properties
┣build.xml
┣.git
┣executeBackupAndCommit.bat
┣commit.sh
```

今回、新た追加したのは
・executeBackupAndCommit.bat
・commit.sh
の2ファイル。
また、build.xmlを書き換える必要はないので、
xmlを書き換えるプログラムは今回必要ありません。

###executeBackupAndCommit.bat
SF組織からメタデータを取得するコマンドを実行し、commit.shを行う起動するbatファイル

```executeBackupAndCommit.bat
Ant backup & cd C:\Program Files\Git & git-bash "C/Users/userName/Desktop/myorg/commit.sh"
```

※各コマンドを区切らずに、"&"で繋いで1行で書くことが重要です。こちらについては後日、記事を投稿しようと思います。

###commit.sh
指定フォルダで差分をコミットするシェルスクリプト

```commit.sh
#!/usr/bin/bash
cd "/c/Users/userName/Desktop/myorg"
git add --all
git commit --allow-empty -m"autobackup"
```

#バックアップの実行
　上記のフォルダを配置したディレクトリで、executeBackupAndCommit.batをダブルクリックするとタスクが実行されます。（Windowsタスクスケジュラーでスケジュール実行可能）
SF組織からメタデータを取得し、差分をコミットします（今回はgit commit --allow-empty オプションを実行しているので、差分がなくても空コミットを行います。）

#まとめ
　今回の成果物は、コードの記述量が少なかったですが、Antコマンドの後のGitコマンドがなかなか上手く実行されずにかなり躓きました。今回の躓きポイントは別記事で投稿しようと思います。
　また、前回から勉強のためAntを使用しましたが、Salaesforce CLIを使用して、Antコマンドをsfdx force:source:retrieveコマンドに置き換えても同様に動作します。
Javaで正の数と負の数を判別する

### Mathクラスのsignumメソッドを使う

```Mathsignum.java
// double型で返します。
// 正の数であれば1.0、0であれば0.0、負の数であれば-1.0を返します。
System.out.print(Math.signum(10)); // 1.0
System.out.print(Math.signum(0)); // 0.0
System.out.print(Math.signum(-10)); // -1.0
```
#### Mathクラス
>Math クラスは、指数関数、対数関数、平方根、および三角関数といった基本的な数値処理を実行するためのメソッドを含んでいます。  

らしいです。

#### signumメソッド
>引数の符号要素を返します。 引数がゼロの場合はゼロ、引数がゼロより大きい場合は 1.0、引数がゼロより小さい場合は -1.0 です。

言い回しは若干異なりますが、前述のコメントアウトにも書いてあるとおりです。


### 参考
[クラス Math](https://docs.oracle.com/javase/jp/6/api/java/lang/Math.html)
[signumメソッド|Javaコード入門](http://java-code.jp/203)
オーバーウォッチのマッチング通知

#オーバーウォッチのマッチング長すぎん....？
Overwatchというゲームが僕は大好きですが，ここ最近異様にマッチングが長いです
10分越えなんてざらです
マッチング長いし洗濯でもしてるか...
なんてことすると，いつの間にか強制退出くらってます
##ということでマッチングしたらスマホに通知をもらおう
まず，おおまかな仕組みはこんな感じです
![Untitled Diagram (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525883/63474874-3e4d-f3bf-79d2-5961f77e01f8.png)
ミソはマッチの検出とお知らせ方法です
##マッチ検出
おばっちはマッチが始まるとかっこいいBGMと相手味方のメンバーが表示されます
おばっちから直接データをいただくことはできないので（カプセル化させているので）
このBGMか画面の違いを取得することでマッチ検出を行おうと思います
###BGM
音声認識使おうか？
でもcloud speechは無料で一時間までしか使えんしなぁ
やめた
###画面遷移
マッチ後の画面学習させてYOLOかなんかで認識しようかなぁ
でも学習させるのめんどいし（マッチング画面はマップによって異なる）
認識率が心配....
ん？
マップによらず共通なのはマッチ前の画面の文字だけだよな？

[検索中....]←これ

これ認識させて検出できなかったらマッチ始まったってことでいいんじゃね？
##マッチ検出実装
文字の認識にはOCRを使いました
画像から文字を取り出してくれます
C# OCRとググれば先人たちが輝かしいソースを残してくれているのでこれを使いましょう

```
Microsoft.VisualBasic.Interaction.AppActivate("Overwatch");
SendKeys.SendWait("{PRTSC}");

#ここに先人のコードを入れる→pageという名の変数で帰ってくる

if(page.GetText().Contains("検索中")) {
   処理
}

```
####追記
microsoft OCRなるものを最近知りましたので
そちらを使ったものに近日中に編集します

##お知らせ方法
IFTTTです
iPhoneで受け取ろうと思います
１．スマホでiftttのアプリを入れましょう
２．Webhooksからurlで送信できるトリガーを取得しましょう
３．スマホの通知を選択しましょう
４．取得したurlを使ってプログラムを編集しましょう


```
DateTime dt = DateTime.Now;
string result = dt.ToString("yyyy/MM/dd HH:mm:ss");
string lnk = "https://maker.ifttt.com/trigger/match/with/key/#########/?value1=" + result;
System.Diagnostics.Process.Start(lnk);
```
こんな感じです
日時を含めているのはtwitterでもつぶやこうと思ったので
同じ内容の送信をブロックする機能の対策として追加してます

##でげだ！
ツイッターでつぶやかせました
![aaaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525883/9b7747e2-ab55-66c3-0e0b-f70040cc2067.png)


今のところ
検出の誤作動は，ないです
100発100中です
おかげさまでお風呂に入りながらでも，ダッシュで駆けつけることができるようになりました

###おしまい

###追記
なんかぐぐったらDiscordの機能かなんかで同じようなのあって草
ちなみにコードは大事なとこ以外かなり端折ってます

###追記2
端折った内容の1部を説明しておきます(半年以上前の制作物なので記憶違いがある場合があるので悪しからず)
開発環境はvisual studio 2017 expressで
wpfアプリケーションとなっております
適当なボタンイベントを登録して
イベントの動作として上記のプログラムが実装されています
tessarct-ocrは学習データが必要です
このアプリケーションの場合は実行ファイルと同じ階層に学習データを配置する必要があります。
itfffに関してはurlを持ってくるだけなのでそこまで難しくは無いです。また参考にできる記事も多々あります
以上。
Rails新規アプリケーションの作り方

## フレームワークRailsの作成手順（ほぼ備忘録）

ディレクトリ作成からRailsのひな形作成までを簡単にアウトプット練習も兼ねて書いていく。（DB設計は割愛）

開発環境↓

- Railsバージョン5.2.3
- データベース　MySQL


ここからはターミナルを実行してひな形を作っていく。

```ruby:ターミナル
# ディレクトリ作成
$ mkdir ~/test 
```

`Rails new`コマンドで作成

```ruby:ターミナル
$ rails new アプリケーション名 -オプション
```

```ruby:test
#test-appファイルの作成
$ rails _5.2.3_ new test-app -d mysql
```

`$ cd test-app`で`test-app`ファイルに移動

```ruby:test-app
# bundle installしておく
$ bundle install
 ```

これでRailsフレームワークのひな形が完成。

htmlファイルやcssファイル、routes.rbがあることを確認しておく。

これからDBとモデルを作成する。

以上
Chrome派のためのポータブルブラウザのススメ

# Chrome(Chromium)系ブラウザをポータブル利用する問題点

ブラウザをポータブルアプリとしてUSBメモリにインストールできると、どこのPCでも同じブラウジング環境が簡単に再現できて履歴はPCではなくUSBメモリに残せたりと大変便利なのですが…

残念ながらChrome(Chromium)は前回起動時と異なるPCで起動すると設定を初期化し拡張機能、テーマ等を全て消去します(ブックマークは残る模様)
これはChrome(Chromium)が意図して行う動作でバグではないのでポリシーを変えない限り直らないしそれを抑制する設定もありません。
また、Chromiumをベースとしている各種Chromium系ブラウザも特別に対応しない限りこの仕様を引き継ぐことになります。

これではポータブル利用に適さないので(この動作をされても問題がない使い方なら[こっち](https://qiita.com/riafeed/items/51f098b4157441ceda35)をお勧めします)、独自に対応して上記の動作を抑制しているブラウザを紹介します。

なおFirefoxは2020年3月現在そのような動作はしないようなのでFirefox派の人には関係ありません。

# ポータブル利用に対応したChromium系ブラウザ

## Opera

[Opera Portable](https://www.opera.com/ja/computer/portable)として公式にポータブル対応しています。独自エンジン時代からOpera@USBとしてポータブル対応していた影響でしょうか？
[PortableApps](https://portableapps.com/)にも[ある](https://portableapps.com/apps/internet/opera_portable)ので、PortableAppsの他のアプリも一緒に使う場合はこっちにすると一元化できて便利
(PortableAppsにはChromeやChromium系ブラウザのPortable版もありますが、特に上記の問題に対応しているわけではないようなので入れてもこの記事の趣旨的には意味がありません)
いずれも自動的に更新をチェックしてくれます。
現在は中国企業の共同事業体の資本傘下にあるので、そういうのが気になる人でなければ公式に対応を謳っていることもあり最もおすすめです。

公式にはポータブル対応していませんが、OperaGXもOperaと同様の動作をするようです。PortableAppsに[ポータブル版](https://portableapps.com/apps/internet/opera-gx-portable)があります。
OperaGXを起動したままでも快適にPCゲームが動作するというゲーミング対応(?)を謳うだけにOperaに比べて非常に軽いなと感じてます。

##### Vivaldiは非対応
Operaから派生したChromium系ブラウザとしてVivaldiがありますが、スタンドアロンインストールというインストール方法があり、ポータブル（USBインストール）を作成するためにも使用できます(It can also be used to create a portable (USB install) of Vivaldi that you could store on an external disk)と[ヘルプには記載されています](https://help.vivaldi.com/article/standalone-version-of-vivaldi/)が、実際にはChromiumと同じく別のPCで起動すると消去されるようです。
パスワードと拡張機能は各コンピューターのユーザープロファイルに固有のキーで暗号化されているため、転送できません。(Since passwords and extensions are encrypted with a key which is unique to the user profile on each computer, they cannot be transferred.)とのことのようです。

## Brave

公式にはポータブル対応を謳ってはいませんし、特にポータブル利用対応に興味があるわけでもないようですが、[コミュニティに上記のChromiumの動作を抑制するためのいくつかのコマンドラインオプションを追加するコードが提供されていて本体に適用されている](https://github.com/brave/brave-core/pull/795)ようです。
そのためデフォルトではポータブル利用には適さないものの(未確認)、いくつかのコマンドラインオプションをつけて起動することでポータブル利用が可能になっているようです。
上記オプションを自動で適用する[「非公式」のポータブル版](https://portapps.io/app/brave-portable/)があるのでBraveをポータブル利用したい場合はこちらがおすすめです。ただし自動更新は非対応で自分で更新確認と手動でダウンロード・インストール(上書きインストールすると更新できる)をする必要があるようです。

## ungoogled-chromium

[Googleのサービスに依存しないChromiumブラウザ](https://github.com/Eloston/ungoogled-chromium)だそうです、[Braveの上記パッチを取り込んでいる](https://github.com/Eloston/ungoogled-chromium/pull/591)ようです。
[ビルド済みのバイナリが提供されています](https://ungoogled-software.github.io/ungoogled-chromium-binaries/)が、公式ではなく提供したい個人によって提供されているというスタンスで無保証のようです。
Brave同様に[「非公式」のポータブル版](https://portapps.io/app/ungoogled-chromium-portable/)がありますので、こちらを使うのが無難だと思います。
ChromiumというかBlink/V8エンジン以外は徹底的にGoogleを排除する方針らしくGoogleサービス関係サイトへのアクセス自体を根本的にブロックするので拡張機能のインストールすらままなりません([ungoogled chromiumにextensionを追加する方法](https://joppot.info/2017/02/06/3371))。Chromiumは使いたいがGoogleのサービスは一切使わない方には適してるんじゃないでしょうか。逆に言えばGoogleのサービスをちょっとでも使ってる人には向いていません。

# セキュリティリスクは承知しておこう

Chrome(Chromium)がああいうことをするのはセキュリティのためです
(どうせブラウザはネットに繋ぐものなのだから都度ログイン・同期すればいいじゃないと思ってる部分もあるかも)
当然ながら何も対策せずにポータブルアプリが入ってるUSBメモリを紛失すれば拾った人に不正利用されかねません。
そのことを理解して利用しましょう。
円周率計算の高速化 (3) 無駄な計算の除去

- [円周率計算の高速化(1)](https://qiita.com/peria/items/97af2df9845decc108ae) 比較元の再構成と問題設定
- [円周率計算の高速化(2)](https://qiita.com/peria/items/01b4671fae70cbb2bc31) 計算の正しさの確認
- 円周率計算の高速化(3) 無駄な計算の除去。約7％高速に
- [円周率計算の高速化(4)](https://qiita.com/peria/items/d77926fe6e0db6da2410) 並列化。60％の時間削減

円周率計算の高速化シリーズの3本目です。[前回](https://qiita.com/peria/items/01b4671fae70cbb2bc31)と違って今回はちゃんと高速化します。

# 前置き
[Chudnovsky の公式を用いた円周率の計算用メモ](https://qiita.com/peria/items/c02ef9fc18fb0362fb89)で、BS 法の計算では

```math
M_k=\begin{pmatrix} z_k & y_k \\ 0 & x_k \end{pmatrix}
```

のもとで

```math
\begin{pmatrix}Y\\X\end{pmatrix}
= M_0M_1M_2\cdots M_{n-1} \begin{pmatrix}0&1\end{pmatrix}
```

を計算するという説明をしました。ところで$Z$はどこへ行ったのでしょう？

# ということで

そう、$Z$は最後の計算では計算する必要がないのです。ということはその前の段階で$Y$を計算するのに使う$Z$も必要なくて…と再帰的につながります。これをプログラムに導入しましょう。

```cpp
void Computer::drm(const int64_t n0,
                   const int64_t n1,
                   mpz_class& x0,
                   mpz_class& y0,
                   mpz_class& z0,
                   bool need_z) {  // ここに追加
  if (n0 + 1 == n1) {
    setXYZ(n0, x0, y0, z0);
    return;
  }

  mpz_class x1, y1, z1;
  int64_t m = (n0 + n1) / 2;
  drm(n0, m, x0, y0, z0, true);
  drm(m, n1, x1, y1, z1, need_z);

  // y0 = x1 * y0 + y1 * z0;
  y0 *= x1;
  y1 *= z0;
  y0 += y1;

  x0 *= x1;
  if (need_z)  // この if 分岐追加
    z0 *= z1;
}

void Computer::compute() { 
  const int64_t precision = digits_ * std::log2(10) + 10;
  pi_.set_prec(precision); 

  const int64_t n = terms(digits_);
  mpz_class x, y, z;
  drm(0, n, x, y, z, false);  // 最終的に z は要らない
  postProcess(x, y);
}
```

この3行くらい(と対応する.hファイルの関数宣言)を編集するだけです。

#実験

Chudnovsky 公式で 1000 万桁を計算する時間をそれぞれ5回ずつ計測しました。基底変換と出力はGMPライブラリの中の問題なので、それらの時間は含んでいません。

|     |1回目|2回目|3回目|4回目|5回目|平均|
|-----|----|----|----|----|----|---|
|変更前|6.214|6.488|6.545|6.433|6.467|6.429|
|変更後|5.886|5.922|6.004|6.024|6.046|5.976|

ということで7%くらい短時間で計算できているようです。([Git](https://github.com/peria/misc/tree/cc7e499b442e9e3a3b88de57c140cbcb0bb5ee33/qiita/gmppi))

次は[並列化](https://qiita.com/peria/items/d77926fe6e0db6da2410)をしてもっと高速にしましょう。
そのVue.jsのページ、本当に非同期コンポーネントで高速化できてる？

## はじめに
この記事では、Vue.js（+ TypeScript）で作ったSPAページの初期描画の速度を改善したい時の取り組みの1つが紹介しています。

非同期コンポーネントという考えは理解できていたのですが、実際に試すと何だか遅くなったように感じられ、断念していました。
実は使い方が上手くなかったようで、その対処法が分かったのでまとめておきたいと思います。

`prefetch`を使うとコンポーネントがすでに読み込まれているのでページ遷移は速くなりますが、SPAサイトの初期描画が遅くなってしまうというトレードオフがありそうですね。
今回は、初期描画を高速化することにスポットを当てています。


## TL;DR;
- [**公式ページ**](https://jp.vuejs.org/v2/guide/components-dynamic-async.html#%E9%9D%9E%E5%90%8C%E6%9C%9F%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88)にあるように、コンポーネントを非同期に呼び出して描画を高速化できるぞ！
- それだけだとprefetchが行われて高速化しないので、`vue.config.js`に1行追加するんやで！


## 非同期コンポーネント呼び出し
SPAのサイトですが、初期描画を改善したいので何か無いかなといろいろ試していたところでした。

非同期コンポーネントという考え方を発見し、[公式ページ](https://jp.vuejs.org/v2/guide/components-dynamic-async.html#%E9%9D%9E%E5%90%8C%E6%9C%9F%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88)を見た通りに試してみる。

まずは、これはTypeScriptでのオーソドックスな呼び出し方（たぶん）。

```ts:コンポーネントの同期読み込み
import MyComponent from "./MyComponent";

@Component({
  components: {
    MyComponent
  }
})
```

それに対して、次のように変更するだけで非同期コンポーネントが使用できますね。コードの変更は本当にこれだけ。

```diff:非同期読み込みに変更
- import MyComponent from "./MyComponent";

@Component({
  components: {
-     MyComponent
+     MyComponent: () => import("./MyComponent")
  }
})
```


という変更を行って、いざSPAページをリロードして表示してみると、今までには無かった謎のjsファイルの読み込みが。
どうやらこれが非同期読み込みすると起こるっぽい。

非同期コンポーネントの数だけ、jsが分割されてprefetchされる。（加えて、実際にコンポーネントが使用される時に prefetchじゃなく読み込まれる）
これで速くなったの、、、かな？
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412483/4d5f56d3-e18f-e894-c488-eb999135b036.png" width="400px">

でも実際にロード時間を見てみると、何か体感遅くなってる？？？
並列読み込みが足りないのか？`HTTP2` を使えという無言の圧力？？
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412483/6da1409c-01a8-06e7-6c26-770da03a769f.png" width="800px">

という感じで、良く分からなくなってしまったので一旦保留にして、作ったPRは閉じておきました。

## prefetchを行わないようにする
それからしばらくして、ある記事を見つけました。こちらです。
[How to make lazy loading actually work in Vue (CLI 3)](https://medium.com/@mrodal/how-to-make-lazy-loading-actually-work-in-vue-cli-3-7f3f88cfb102)

これや！これが欲しかったんや！
`actually-work`とか書いてあるし、記事のタイトルを見た瞬間にピーんと来てました、まじで。

ということで、記事にも書いてあるように`vue.config.js`にprefetchを制限するための1行を追加しましょう。

```js:vue.config.js
chainWebpack: (config) => {
  config.plugins.delete("prefetch");  # この行を追加
  ...
}
```

この変更を適用させると、非同期コンポーネントのprefetchが無くなり、必要な時になったら必要なコンポーネントが読み込まれる仕組みにできました。

[Matias Rodal](https://medium.com/@mrodal)さん、ありがたや。

## おわりに
ということで、気になっていた非同期コンポーネントを使うと遅くなる問題が解決できたかなと思います。

必要な時に必要なものを用意する、というモノを持たない現代的な生き方にマッチした実装が出来そうです。

私生活でもミニマリスト的に暮らしてみたい。断捨離しよ。

以上
AWS Cloud9でLaravelを構築する際のTips

Cloud9でLaravel開発環境を構築する際にいろいろハマったのでメモしておきます。

<b>・やりたかった事
すでにgithubに上がっているlaravelプロジェクトをcloud9で動作させたい</b>
<b>
・躓いたこと
git clone https:\\hogehogeしても、動かない
</b>


↓↓↓　以下、laravelトップページが表示されるまでの足跡　↓↓↓

cloud9の初期設定はバージョンが古いです。
アップデートしましょう。

参考：https://qiita.com/kidatti/items/2d6a4a24f89dc71eb66e

ちなみにこの記事では7.2をインストールしていますが、現在の最新verは7.3ですね。
まとめると以下のような形でしょうか。

```
sudo yum -y update
sudo yum -y install php73 php73-mbstring php73-pdo
sudo unlink /usr/bin/php
sudo ln -s /etc/alternatives/php7 /usr/bin/php
```

phpのバージョンアップが済んだらcomposer installかcomposer updateを走らせると思います。
僕の場合はここでphpのバージョンが古いと以下のように怒られました。

```
(C9 ﾟДﾟ) ふざけんじゃねぇバカヤロウ!!
This package requires php ^7.2 but your PHP version (7.1; Package overridden via config.platform (actual: 7.1.33)) does not satisfy that requirement
```

さっき最新のバージョン入れたのに、php-vしても7.1しか返ってきません。
同じような症状にあった場合は以下を実行してみてください。

```
sudo yum remove php71*
```

そうすると7.3なり、7.2なりが顔を出してくると思います。

ちなみにcomposer.jsonの設定が古い可能性もあるので、念のため以下のように変更しておきました。

```
composer config platform.php 7.1.13
```

その後、満を期してcomposer updateを実行。
Laravelプロジェクトをgithubにプルした際、Vendorファイルが無くなる現象があります（僕だけ？）
Venderファイル上がってるよって人はこのcomposer updateは不要かも。

あとenvファイルもなかったので、それも復活させます。
参考：https://www.kabanoki.net/2524/

```
cp .env.example .env
php artisan key:generate
php artisan config:clear
```

これで初期設定完了。
なお執筆者はド素人なので皆さんの力を借りつつ何とか設定することが出来ました。
ありがとうございました。
正規表現で特定の文字列を含まない表現にマッチさせる方法

以下の記事の中で重要と思ったことを抜粋
[[正規表現] .*?は最短マッチではない](https://qiita.com/anqooqie/items/191ad215e93237c77811)

#特定の<b>文字</b>を含まない表現にマッチさせる方法
例：`[^Aa]*`　Aとaを含まない表現にマッチ

`<<<hoge>>>`の`<hoge>`部分にマッチさせる方法
`<[^<>]*>`

#特定の<font color="RED"><b>文字列</b></font>を含まない表現にマッチさせる方法
`(?:(?!文字列1|文字列2).)*`　または
`((?!文字列1|文字列2).)*`　マッチさせるだけなら?:は無くても良い　または
`((?!(文字列1|文字列2)).)*`　かっこがあっても良い
文字列1と文字列2を含まない表現にマッチ

`<em>あ<em>いうえ</em>お</em>`の`<em>いうえ</em>`部分にマッチさせる方法
`<em>((?!<em>|</em>).)*</em>`
Sass,BEM,Haml

Sass
CSSの機能を拡張した言語　
BEM
多くの開発者が取り入れているCSS設計。BEMは、厳格なクラスの命名規則が特徴
Block、Element、Modifierのみでクラスを命名することで、クラス名に悩むことがなくなる
Haml
HTMLよりも簡単に書くためのビューテンプレートエンジン

この三つを使いchat-sapaceのフロント実装に入った。
今までコピペばっかで自分でコードを一から書く作業をほとんどしてないし、HTML/CSSでやったブロック要素の部分を忘れていた、この作業で少しでもコード考えて書くということに慣れていきたい。