OmniAICreator/Qiita-1.07M huggingface dataset:
PnP PowerShell で Sharepoint を操作しよう: (6) リストにアイテムを追加しよう

皆様こんにちは。
前回まででリストの定義をやってみましたが、今回はアイテムの追加です。

単純なアイテムの追加と、参照型フィールドを含む場合の2ケースを紹介します。

#単純なアイテムの追加

CSVファイルを用意して、1行目にカラム名として"用途コード", "用途名" という行を用意しておきます。ここではタブ区切りのUTF-16 ファイルとしておきます。

使う命令は[`Add-PnPListItem`](https://docs.microsoft.com/en-us/powershell/module/sharepoint-pnp/add-pnplistitem?view=sharepoint-ps)です。

```add-record.ps1
    $File = "some.csv",
    $ListName="リスト名" 

    $items = Import-Csv $File -Delimiter `t
    $items|ForEach-Object{
            $result = Add-PnPListItem -list $ListName -Values @{ "code"=$_.用途コード; "Title"=$_.用途}
    }
```
コードが短いですね。PnPって素敵です。

#参照型フィールドを含むアイテムの追加
今度は少々面倒になります。

参照型フィールドがあるということは、つまるところリレーションシップデータベースっぽいことになっているわけですが、参照型フィールドはその正体を平易なインターフェースで隠しているせいです。
[PnP PowerShell で Sharepoint を操作しよう: (4) 参照フィールドを使ったリストを作ろう](https://qiita.com/Kayo1984/items/edf9bbe11c0bf0f3def2)
でサンプルに使ったリストで説明しましょう。

**参照ありリスト**

| Title | 参照先フィールド |
|:-:|:-:|
| ああああ | うに |
| いいいい | さば |

というリストがあるとすると、内部の作りはこんな感じです。

**参照ありリスト**

| ID | Title | 参照先ID |
|:-:|:-:|:-:|
|  1 |  ああああ | 3 |
|  2 |  いいいい | 4 |

**子リスト**

| ID | Title |
|:-:|:-:|
|  1 |  たこ |
|  2 |  いか |
|  3 |  うに |
|  4 |  さば |

ここで、参照ありリストにレコードを追加しようとしたときは、追加するデータは、「ああああ」と「うに」ではなくて`Title(ああああ)`と`ID(3)`を追加することになります。
IDを先に取得してから、レコードを追加するという処理になります。

ここで使う命令は
[`Get-PnPListItem`](https://docs.microsoft.com/en-us/powershell/module/sharepoint-pnp/get-pnplistitem?view=sharepoint-ps)
[`Add-PnPListItem`](https://docs.microsoft.com/en-us/powershell/module/sharepoint-pnp/add-pnplistitem?view=sharepoint-ps)
です。

```Add-Item-LookupField.ps1
#IDを子リスト/ChildList から得る
   $query = "<View><Query><Where><Eq><FieldRef Name='Title'/><Value Type='Text'>うに</Value></Eq></Where></Query></View>"
   $result =Get-PnPListItem -List "ChildList" -Query $query
   $ID = $result.id

#参照ありリストのアイテムを追加する
        Add-PnPListItem -list "ListWithLookupField" -Values @{ "Title"="ああああ";"LinkedField"= $ID; }
```

-List "ChildList" のところは、DisplayName(日本語名)でもUrl(英語名)でもどちらでも通るみたいです。

#大量の追加だとPnPよりCSOMを

ここで、ちょっとがっかりなお知らせです。
PnP ならなんでも簡単かと思ったら、実は弱点があります。
大量（数千件）のアイテムをCSVから追加しようと思ったら、1件1～2秒くらいかかってしまって、数時間待ちになっちゃうことがわかって、回避策が必要になりました。
結局、レコード数が100件くらいを超えたら、CSOMを使うほうが数十件ごとに追加が行われるのでずっとパフォーマンスがいい、ということが判明したのです。
PnP のコミュニティにもそんな話が載っていたようですが、ヘビーな作業になったら回り道してCSOMも使ってみましょう。

今回はここまでにします。
犬猫判定機

写真に写っているのが犬か猫かを判定する。
https://docs.google.com/spreadsheets/d/1_bmS3AP9ehGqZ8AsJJmfMwy1tU3d_Bt8GFGiU8jfXME/edit#gid=0

#使用するAPI
A3RTの「Image Search API」
https://a3rt.recruit-tech.co.jp/product/imageSearchAPI/

#コード

```コード.js

function ImageConvertText(pic_link) {
 
  var res = UrlFetchApp.fetch("https://api.a3rt.recruit-tech.co.jp/image_search/v1/search_by_image?apikey=APIキー&image=" + pic_link).getContentText();  
  var json = JSON.parse(res);
  var tag = json["result"].txt;
  
  if (tag.indexOf("ネコ") != -1 | tag.indexOf("猫") != -1) {
    return "まんち！";
  } else if (tag.indexOf("イヌ") != -1 | tag.indexOf("犬") != -1) {
    return "わんち！";
  //elseだと何も言わないときがある
  } else if (tag.indexOf("イヌ") == -1 && tag.indexOf("犬") == -1 && tag.indexOf("ネコ") == -1 && tag.indexOf("猫") == -1){
    return "むり！";
  }
  
}


function Results() {
  
  var url = Browser.inputBox("画像のURLを入力");
  Browser.msgBox(ImageConvertText(url));
 
}

```


#やってみる

https://www.pakutaso.com/shared/img/thumb/kakurerukijishironeko171027_TP_V.jpg
![Screenshot from 2019-06-03 19-33-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417037/f36b8f4f-5cf8-f0f3-c96b-30cdece4e46a.png)

https://www.pakutaso.com/shared/img/thumb/AMEMAN17826009_TP_V.jpg
![Screenshot from 2019-06-03 19-39-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417037/d18eed4a-cd74-4961-7919-2454213e25cb.png)

https://www.pakutaso.com/shared/img/thumb/KM19322A053_TP_V.jpg
![Screenshot from 2019-06-03 19-41-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417037/74a91fd8-77f3-3035-f578-22e83e6efe06.png)

画像引用元
https://www.pakutaso.com/
will_paginateをインストールするとエラー表示される件【Railsチュートリアル第10章】

will_paginateをインストールをしたけど、エラーが発生してしまった時の対処方法です。

# バージョン

```
ruby '2.5.3'
rails '~> 5.2.3'
```

# 事象
私の場合はRailsチュートリアルの第10章「10.3.3 ページネーション」を進めている際にエラー表示になりました。

```gemfile.
source 'https://rubygems.org'
・
・
・
gem 'will_paginate', '3.1.6'
gem 'bootstrap-will_paginate', '1.0.0'
```
`bundle install`をしたのちに、`rails server`を再起動させて`users/index.html.erb`に下記のように記載。

```
<% provide(:title, 'All users') %>
<h1>All users</h1>

<%= will_paginate %> #ページネーションを呼び出す

<ul class="users">
  <% @users.each do |user| %>
    <li>
      <%= gravatar_for user, size: 50 %>
      <%= link_to user.name, user %>
    </li>
  <% end %>
</ul>

<%= will_paginate %> #ページネーションを呼び出す
```
```users_controller.rb
  def index
    @users = User.paginate(page: params[:page]) # 追加
  end
```

「よし、確認してみよう！」とローカルで`/users/`にアクセスしてみると、下記のようなエラーが・・・

![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32413/a47602e0-f79e-3ac2-8a29-0dd663bdcf72.png)

おぅぅぅぅ…

# 解決策
どうやら`will_paginate`のバグがあったようで、バージョンをあげてみることに。

```gemfile.
source 'https://rubygems.org'
・
・
・
gem 'will_paginate', '3.1.7' # will_paginateのバージョンをあげた
gem 'bootstrap-will_paginate', '1.0.0'
```
`gem`のバージョンをあげたので、下記のコマンドでアップデート。

```
$ bundle update will_paginate
```


これで改めて`localhost:3000`を開いてみると・・・・表示されたぁぁぁ！！！！！！

ちなみにこの解決方法は、`gem`のGitHubページの`issue`に記載されていました。

https://github.com/mislav/will_paginate/issues/527

今まで`Qiita`や`stackoverflow`しか見ていませんでしたが、githubを見ることも重要なんですね。
勉強になりました！
HTML&CSS道場編を学習中です。

こんにちは[未来電子テクノロジー](https://www.miraidenshi-tech.jp/)でインターンをしている秋吉です。
タイトルの通り、HTML&CSSの道場中級編を学習しています。
下手したら初級編より忘れてるんじゃないだろうかというくらいわからないところがあるので、潔くスライドやレッスンに立ち戻ったり検証使ってめちゃくちゃ写経している状態です。
サイト内の構成がよくわからず、その不安でスライドに戻ったり検証を使ったりしているのですが、こればっかりはお作法な気がするので、とにかく手を動かして型（流れと言ってもいいかも）を覚えるしかなさそう。
例えば、`<body>`内のHTMLの記述。

```
<div class="main-wrapper"><!-- メイン全体（余白も）まるっと含む。というかこれを作ることで、CSSで余白やブロック要素の設定をする -->
<div class="container"><!-- メインの中でもコンテンツの大きな塊。まんまコンテナ。 -->
<div class="contents　a"><!-- コンテナの中身です。 -->
</div>
</div>
</div>
```

雑どころの話ではないですが。
こうやって表示したいコンテンツの内容を大きく分割して、細かいところを記述していくっていうのがサイトを作るときの大きな流れなんだなっていうのが、手を動かしていてやっと腹に落ちたという。
そのうえで、CSSの記述をやりやすくしたり後から内容を変更しやすくしたりっていうときに、ある程度丁寧に分けたほうがやりやすい。
道場コースで自分の書いたコードがそれはもうぐっちゃぐちゃになったときに、一度検証を使って書き直したときに痛感しました。
ちゃんと分けないと、paddingとmarginを設定しても変になったり、別のところで設定したtext-align:centerがなぜか設定していないところに効いてたり……。
なので、こういったある程度「覚えたほうがやりやすい」ものは、しっかり覚えるようにしていきたいと思います。


プログラミング初心者のため、内容に誤りがあるかもしれません。もし誤りがある場合は修正したいのでどんどん指摘してください。
HerokuにNuxtデプロイしようとして「trouble with your network connection」と言われたら

NuxtをHerokuにデプロイしようとしたら、こんなエラーにぶち当たりました。

![スクリーンショット_2019-06-02_21_50_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252687/bdef9d2d-2ea4-6b5f-81ae-43c4ce492d40.png)



えー、なんだよ、タイムアウト系かな？

こちら（[yarnに「There appears to be trouble with your network connection.」と言われたら](https://qiita.com/remin/items/06a3a0dab63531c531e4)）を参考にしましたが、解決しませんでした。。


![スクリーンショット_2019-06-02_21_54_30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252687/daed93ad-0018-2cd2-6562-04ef0d3ed73a.png)

色々試しましたが落ちに落ちまくってるww 


結局、こちら([ESOCKETTIMEDOUT on 31 MB package material-design-icons](https://github.com/yarnpkg/yarn/issues/5540))の方法で解決

![スクリーンショット_2019-06-02_21_50_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252687/3b46cb61-81a5-27d9-1ec8-f3b2de3a5a72.png)

どうやら、`https://registry.yarnpkg.com/material-design-icons/-/material-design-icons-3.0.1.tgz`が大きく(32MB)、インストールに時間がかかりすぎていたようです。なので、タイムアウトになる時間を調整します。

1.プロジェクトのルートに`.yarnrc`ファイルを作成
2.そこに、`network-timeout 600000`と記述

```yarnrc
network-timeout 600000
```

3.保存してpush



これで無事にデプロイが成功どす
![スクリーンショット_2019-06-02_22_00_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252687/4c879455-d539-ec81-2293-529aac380e9f.png)
pytorch 1.1.0 + tensorboard (ssh先でもOK)

# 環境
- python: 3.6.8
- pytorch: 1.1.0

**(注意)tensorboardが標準装備されているのは、pytorch 1.1.0からです。**

# インストール
python, pytorchはインストールされているものとします。

```bash
pip install tb-nightly
pip install future
```

# コーティング
変数`train_loss`と`train_acc`にトレーニングの`lossの値`と`accracyの値`が入っているとします。また、変数`idx`に「何回目の記録か」が入っているとします。

```python
from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter(log_dir=<logを書き込む場所>)

~色々~

writer.add_scalar('train_loss', train_loss, idx)
writer.add_scalar('train_acc', train_acc, idx)
```

これで、`<logを書き込む場所>`の所にlogファイルが生成されます。

ちなみに僕は`<logを書き込む場所>`を`./logs/<modelのid>`みたいな感じにしています。

# いざ、tensorboard

```bash
tensorboard --logdir <logを書き込んだ場所>
```

とすると、ローカルサーバーが立ち上がるので、chromeなどのブラウザにそのURLを打ち込むと立ち上がります。

# ssh先でtensorboard
僕は研究室のサーバーにssh接続して計算させていますので、その場合は少し手順が必要になります。

下のようにオプションをつけてssh接続します。

```bash
ssh ユーザ名@サーバーのIPアドレス -L 6006:localhost:6006
```

6006はTensorBoardのポート番号です。

ログイン後に、ssh先で

```bash
tensorboard --logdir <logを書き込んだ場所>
```

とします。

そして、ローカルで`localhost:6006`をブラウザなどで叩きます。

すると、

![スクリーンショット 2019-06-03 19.23.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221435/8695b089-5a08-94be-9d63-57f5bae843ef.png)

立ち上がります！


# 参考
- [PyTorchのTensorBoardサポートを試してみる](https://qiita.com/nj_ryoo0/items/f3aac1c0e92b3295c101)

- [SSHでログインしてTensorBoardを使用する方法](https://robotics4society.com/2018/03/18/ssh_tensorboard/)
gitに慣れるための最低限のコマンド - 変更内容の記録 編

gitは覚えることが非常に多いため、最初に挫折しないためにも、まずはよく使うコマンドの使い方を覚え、流れに沿って手元で試し、コマンドに慣れることが大事だと考える。

「分散型バージョン管理システムって何？」「リポジトリって何？」という疑問にはこの資料では言及しない。知りたくなった時にググってほしい。

本資料は [gitに慣れるための最低限のコマンド - 環境の構築 編](https://qiita.com/hmaruyama/items/cdd3823b5c6b09a4bc13) を経て、実際にリモートリポジトリに手元の変更をpushするまでを解説する。

ファイルを変更したら、`add`して`commit`して`push`してプルリク！

### 1. cd /path/to/dir/

作業ディレクトリに移動する。例えば作業ディレクトリが`/Users/hikarumaruyama/src/github.com/hmaruyama/test-pages`なら、以下のコマンドになる。

```sh
$ cd /Users/hikarumaruyama/src/github.com/hmaruyama/test-pages
```

### 2. git fetch && git merge origin/master

最新のリモートリポジトリの内容を取り込んで（fetch）、ローカルリポジトリに反映（merge）する。

fetchしてmergeする前に、ローカルリポジトリのmasterブランチにチェックアウトする。

```sh
$ git checkout master
```

```sh
$ git fetch
remote: Enumerating objects: 24, done.
remote: Counting objects: 100% (24/24), done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 24 (delta 7), reused 19 (delta 7), pack-reused 0
Unpacking objects: 100% (24/24), done.
From github.com:hmaruyama/test-pages
   ae59945..778c83b  master     -> origin/master
```

```sh
$ git merge origin/master
Updating ae59945..778c83b
Fast-forward
 src/en/product/ocean/index.html                  | 4 +---
 src/en/product/ripple/index.html                 | 4 +---
 src/en/product/wave/index.html                   | 2 +-
 src/en/products/wave/faq/index.html              | 2 +-
 src/jp/product/ocean/index.html                  | 4 +---
 src/jp/product/ripple/index.html                 | 4 +---
 src/jp/{products => product}/wave/faq/index.html | 2 +-
 src/jp/product/wave/index.html                   | 2 +-
 8 files changed, 8 insertions(+), 16 deletions(-)
 rename src/jp/{products => product}/wave/faq/index.html (99%)
```

### 3. git checkout -b <ブランチ名>

masterブランチでは基本的に作業しない。
ローカルリポジトリのmasterブランチから新しいブランチを作成してチェックアウトする。

```sh
$ git checkout -b fix_bug
```

### 4. git add <ファイル名>


変更したいファイルを変更したら、インデックスに追加する。[インデックスとは？](https://backlog.com/ja/git-tutorial/intro/04/)


ファイル名を指定する代わりに、カレントディレクトリを表す`.`を指定することで、カレントディレクトリに存在する全てのファイルを一気にインデックスに追加することが可能。

```sh
$ git add .
```

### 5. git commit -m "コメント"

インデックスに存在するファイルを作業ブランチにコミットする。
コメント内容は、変更する理由をのべるのが良い（変更箇所はコードを見れば分かるため）。

```sh
$ git commit -m "タイポを修正しました。"
```

### 6. git push origin <ブランチ名>

コミット内容を、リモートリポジトリにプッシュする。

```sh
$ git push origin fix_bug
```
SlackのMessageButtonに反応させようとしたらつまづいた話


#はじめに
タイトルがわかりづらいですね・・・
前回slackのボタン付きメッセージを送れるようにしたんですが、
([Pythonを使ってSlackへボタン付きメッセージを送る](https://qiita.com/flower81/items/e7615f4c546bcf550c82))
ボタンを押してもエラーになってしまうんですね。

![スクリーンショット 2019-06-02 23.04.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152025/8ed36dc8-1863-217a-6665-898d0f08e890.png "スクリーンショット 2019-06-02 23.04.52.png")

なのでちゃんと反応してくれるようにしました。
その時につまづいたところをメモっておきます。

#環境
MacBook Air macOS Sierra 10.12.6
Python 3.6.5
requests 2.19.1
Flask==1.0.2
gunicorn==19.9.0
Heroku
urllib.parse

#本題
どこでつまづいたかと言いますと。

```python:index.py
@route('/', method='POST')
def index():
    params = json.loads(request.params.get('payload'))	# ここ！！
    text = postMsg(params)
    return text

```

これを次のように修正したらうまくできました。

```python:index.py
@app.route("/", methods=["POST"])
def index():
    data = request.get_data()
    str_data = data.decode("UTF-8").replace("payload=", "")
    payload = urllib.parse.unquote(str_data)
    params = json.loads(payload)
    text = postMsg(params)
    return text
```


#たどり着くまで
色々な取得方法を調べた結果、
受け取っていたのが`application / x-www-form-urlencoded`というコンテンツタイプだったこと、
型がbytes型だったこと、
始まりが`payload=%7B%22type%22%3A 〜`だったことから、
上記のようになりました。

やっていることは、以下になります。
・POSTで受け取ったものを`data`に格納。この時`data`はbytes型。
・`data`を文字列型にデコードし、`payload`を削除（置換）し`str_data`に格納。この時`str_data`は文字列型。
・`str_data`を`urllib.parse.unquote`でパースし、`payload`に格納。この時`payload`は文字列型。
・jsonで扱うために、`payload`を`json.loads`で辞書型にし、`params`に格納。

#終わりに
もっといい方法があるはず・・・
Rails6.0のマルチDBを試してみた

Rails6.0で新たに追加されたマルチDBの機能を試してみました。
 
|Railsのバージョン|MySQLのバージョン|
|:-----------:|:------------:|
| 6.0.0.rc1   |  5.6.39      |

- 参照
  - [Part 1 Easy Multi db in Rails: Add basic rake tasks for multi db setup](https://github.com/rails/rails/pull/32274)
  - [Refactor migrations_path command option to database](https://github.com/rails/rails/pull/34021)
  - [Part 4: Multi db improvements, Basic API for connection switching](https://github.com/rails/rails/pull/34052)
  - [Add multi-db support to rails db:migrate:status](https://github.com/rails/rails/pull/34137)

# 1. `database.yml`に`specification`を設定
マルチDBにおいて各DBを識別するための、`specification`という概念が登場しています。`specification`には、任意で好きな名前を設定できます。

```yml:config/database.yml
...
development:
  first:
    <<: *default
    database: rails6_development
  second:
    <<: *default
    database: rails6_development_second
    migrations_paths: "db/second_migrate"
...
test:
  first:
    <<: *default
    database: rails6_test
  second:
    <<: *default
    database: rails6_test_second
    migrations_paths: "db/second_migrate"
...
```
今回は、`first`と`second`という名前を設定しました。
`specification`によってmigrateフォルダは分かれます。`first`はデフォルトの`db/migrate`フォルダが使われ、`second`は`migrations_paths`で指定した`db/second_migrate`が使われます。
# 2. DB create
`database.yml`の設定が完了したら、`db:create`を行います。
`db:create`の後ろにオプションで`specification`を指定することができます。
`specification`を指定しない場合、`first`と`second`両方のDBが作られます。
## 2-1. `first`だけの場合
```bash
$ rails db:create:first
```
## 2-2. `second`だけの場合
```bash
$ rails db:create:second
```
## 2-3. 両方の場合
```bash
$ rails db:create
```

# ３. modelを作る
## ３-1. `database`オプション有りの場合  
`database`オプションで`specification`を指定できます。

```bash
$ rails g model Post content:text posted_at:timestamp --database=first
```
以下1つのmigrateファイルができます。

```bash
db/migrate/20190529024126_create_posts.rb
```
## ３-２. `database`オプション無しの場合  
```bash
$ rails g model User name:string age:integer
```
以下2つのmigrateファイルができます。

```bash
db/migrate/20190524025133_create_users.rb
```
```bash
db/second_migrate/20190524025133_create_users.rb
```
# 4. migrateする
## 4-1. migrate実行
```bash
$ rails db:migrate
```
## 4-2. migrateの状態を確認
```bash
$ rails db:migrate:status
```
各`specification`のmigrate状況が見れます。

```bash
database: rails6_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20190524025133  Create users
   up     20190529024126  Create posts


database: rails6_development_second

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20190524025133  Create users
```
#5. modelで読み込み用と書き込み用のDBを分ける
`connects_to`オプションで`writing`と`reading`を指定できます。

```ruby:app/models/user.rb
  class User < ApplicationRecord
    connects_to database: { writing: :first, reading: :second }
  end
```
これで、`User`モデルは`first`が書き込み用、`second`が読み込み用となりました。
Nginx, Puma, Rails, MySQLのパラメータ設定/チューニング

## 概要
Nginx, Puma, Rails, MySQLのチューニングを行ったときの知見を載せておきます。
ただし、チューニングは色々な要素に依存するため、最終的には自分たちの作っているアプリケーションにあった値を見つけてください。
以下の図のような動きを内部的にしています。では早速、各サービスの設定項目を詳しく見ていきましょう。
<img width="902" alt="スクリーンショット 2019-06-02 23.00.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104056/8d86b1f8-ab15-9fc9-8d1f-fe8e84fbfa26.png">


## Nginx
### worker数
今回自分はNginxがボトルネックにはならなかったので、Nginxの知見はあまり習得していないですが、色々な人のブログを見ていると `auto` にしていることが多そうなので、特に理由がない場合以外は `auto` でいいかと思います。

```nginx:/etc/nginx.conf
worker_processes auto;
```

## Puma
### worker数
workerはCPUのコア数に依存する物理スレッドを示しています。ここで大事なのは、worker数を __サーバーのCPUコア数より大きくはしないことです__ 。
Pumaのworker数は、次のthread数に関係してくるので次で述べます。

### thread数
threadは1worker内での論理スレッド数を示しています。

- 1worker/16threadの場合、計16thread
- 2worker/16threadの場合、計32thread

1worker内の最大thread数は、[ここ](https://github.com/puma/puma/#thread-pool)にも書いてあるように __16__ より大きくしないほうが良さそうです。
※workerとthreadの関係は[こちら](https://github.com/puma/puma/#clustered-mode)に記載

実際に設定ファイルに書くときは、2worker/16threadの計32threadの場合は以下の通りに書いてください。

```ruby:config/puma.rb
# 環境変数 RAILS_MAX_THREADS に 16 をセット
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }

...

# 環境変数 WEB_CONCURRENCY に 2 をセット
workers ENV.fetch("WEB_CONCURRENCY") { 2 }
```

実験を行った結果、もちろんサーバーのリソース(今回はCPUコア数: 2)にもよりますが以下のようにサーバーが処理できるキャパシティが変わりました。thread数が少ないともちろんさばける処理数が減るため、サーバーのリソースが余っているにもかかわらず、unhealthyになります。つまり、レスポンスで過負荷を示す503 errorが返却されます。

- 1worker/5threadの場合、CPU15%ぐらいでunhealthyになる
- 1worker/10threadの場合、CPU30%ぐらいでunhealthyになる
- 1worker/16threadの場合、CPU45%ぐらいでunhealthyになる
- 2worker/16threadの場合、CPU90%ぐらいでunhealthyになる

ここで気をつけないといけないのは、アプリケーションサーバーのCPU使用率だけに目がいくとメモリを圧迫してメモリが原因で処理ができなくなる場合もあるので、メモリもしっかり監視してください。また、データベースに負荷のかかる処理を行うような場合はデータベースのCPUやメモリにも注意してベストな組み合わせを見つけてください。
上記の実験条件下で、かつメモリに余裕がある場合は、2worker/16threadがベストだと考えることができます(リソースを無駄なく使いきるという意味です)。

## Rails
### pool数
database.yml内の `pool` は、MySQLとの接続数を示しています。
`puma worker * puma thread > pool` になってしまうと`ActiveRecord::ConnectionTimeoutError` が発生してしまいます。なので、 `pool` は `puma worker * puma thread == pool` になるように設定しましょう。
その逆で、MySQLの最大コネクション数を超えるとMySQLの `Too many connections` エラーが出ます(式で表すと: `pool > max_connections` )。このコネクション数の最大は、 MySQLの設定に依存しますので、次で詳しく説明します。

## MySQL
### max_connections数
`max_connections` は、MySQLの最大コネクション数になります。DBインスタンスの性能によって最大値を変えるのがいいと思いますが、AWSのRDSは初期値が以下の通りに設定されています(インスタンスによって異なります)。

`t2.micro` : 66
`t2.small` : 150
`t2.medium` : 312

上記はRDSの推奨っぽいので、上限を上げることはできますが、あまりおすすめはしません。
最大コネクション数は、以下のSQLで確認可能です。

```sql
show variables like "%max_connections%";
```

## まとめ

最初に貼りましたが最終的に以下のように内部的に動いていますので、先程紹介した設定値を参考にしてみてください。ただ、繰り返しにはなりますがサーバーのリソースやアプリケーションの処理する内容によってベストな設定値が変わります。なので、この数値にすればOK!というものがありません。これがチューニングの難しいところです。自社にあった設定値を地道に探していきましょう。その中で、この記事の内容がお役に立てれば幸いです。

<img width="902" alt="スクリーンショット 2019-06-02 23.00.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104056/8d86b1f8-ab15-9fc9-8d1f-fe8e84fbfa26.png">
※上記画像のthread数を5にしているのは矢印線を16本引くのが大変だったので5にしているだけで推奨値とかではありません
HerokuのPostgreSQLの使い方【ローカルテスト辺】

# はじめに

[前回の記事](https://qiita.com/mickie895/items/9d9e95f2b2efb1b961df)の続きです。ローカル環境を構築してからherokuにアップロードするまで。

# PostgreSQLのローカル環境でのテスト

前回の記事でPostgresをインストールした際、管理用のパスワードを聞かれますので忘れないようにしておきましょう。

インストールが終わるとスタートメニューにPostgreSQLのCLIが追加されます。
![ログイン画面.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395414/ce848edd-5d26-2272-8481-97181b3da029.png)

空欄のままEnterキーを押すとデフォルト値が入力されます。
サーバー・データベース・ポート・ユーザー名・クライアントの文字コードはデフォルトのままでOK、パスワードを先程インストールしたときに打ち込んだパスワードを入力します。

[参考の日本語サイト](https://www.dbonline.jp/postgresql/)から使い方を確認し、データベース、スキーマ、テーブルを作成します。

なお、最終的にはラインボットを作る予定なので、リードオンリーのラインボット用アカウントを[GitHub上の参考リンク](https://gist.github.com/oinopion/4a207726edba8b99fd0be31cb28124d0)を見て作成しています。

# herokuへアップロード

自分の場合、下記のように打ち込めばいいと思ったが何度かエラーが出ました。

```
heroku pg:push postgres HEROKU_POSTGRESQL_MAGENTA --app mickie-test-app
```

正しくは次のようにやっていきます。(Windowsの場合)

1. postgresqlのユーザー名・パスワードを環境変数としてセットします。
![環境変数.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395414/659b1611-12e8-7bbd-af99-e1d8fa0c3772.png)

2. ```heroku pg:push postgres DATABASE_URL --app mickie-test-app```を打ち込みます。
DATABASE_URLがPostgreSQLの場所を示しているようです。
![PostageSQLpush.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395414/a9b238e1-bfc7-5ca7-6608-2eb2c9b46f36.png)

3. ```heroku pg:psql```でデータベースにアクセス、\dnコマンドでアップロードできていることを確認。
![リスト表記.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395414/2dbaef4f-ea50-caa5-523f-2259f359233d.png)

[次回](https://qiita.com/mickie895/items/15ab1008dc64bcc7391b)はこのデータベースをpythonでアクセスし、利用するところま。
Google Apps Script(GAS)でWebAPIを公開してAndroidから取得する

# やりたいこと
 - Google Apps ScriptでWebAPIを公開する
  - ゼロから書こうかと思いましたが、細かい記事がありましたのでGASの部分は下記をそのまま使用しています
  
    [今から10分ではじめる Google Apps Script(GAS) で Web API公開](https://qiita.com/riversun/items/c924cfe70e16ee3fe3ba)

 - 公開したWebAPIをAndroidから叩いて取得する

# 実装
```AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
```

```activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

    <TextView
            android:id="@+id/result_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>

</android.support.constraint.ConstraintLayout>
```

```MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        fetch()
    }

    private fun fetch() {
        Thread(Runnable { // 非同期
            try {
                val url = URL("公開したWebAPIのurl?text=testes") // ?text=testes は query
                // queryは設定しなくても正常に　"Please say something!" が返却される
                val urlConnection = url.openConnection() as HttpURLConnection
                urlConnection.requestMethod = "GET"
                urlConnection.connect()

                val sb = StringBuilder()
                val br = BufferedReader(InputStreamReader(urlConnection.inputStream))
                br.readLines().forEach {
                    sb.append(it)
                }
                br.close()

                println("result:$sb")
                runOnUiThread { // ui thread
                    result_text.text = sb.toString()
                }
            } catch (ex: Exception) {
                println("failure:$ex")
            }
        }).start()
    }
}
```

# おわりに
ネイティブの実装が先に進んでてAPIが未完の時に使えるかと
Python じゃんけんゲーム

# 目的
Pythonの基本文法を得ること(初心者向け)

# 内容
**プログラムが楽しい**と思うゲームを試してもらいたい
ある漫画のキャラクターをバトルに出してみました。

# じゃんけんゲーム

- Pythonで出来る簡易的な**じゃんけんゲーム**

```python:hands_game.py
from random import randint
hands = {0:"グー",1:"チョキ",2:"パー"}
rules = {(0,0):"あいこ",(0,1):"勝ち",(0,2):"負け",
(1,0):"負け",(1,1):"あいこ",(1,2):"勝ち",
(2,0):"勝ち",(2,1):"負け",(2,2):"あいこ",}

while True:
    pc_hand = randint(0,2)

    user_hand_str = input("0:グー 1:チョキ 2:パー 3:やめる")
    if user_hand_str == "3":
        break
    if user_hand_str not in ("0","1","2"):
        #print("その数字は対応してません。もう一度やり直してください")
        continue
    user_hand = int(user_hand_str)
    print("ゴンさん : "+hands[user_hand]+"    コンピュータ : "+hands[pc_hand])
    print("")
    print(rules[user_hand,pc_hand])
```
- プログラムを改良すれば、もっと面白くできそうな雰囲気はありますね。

```
0:グー 1:チョキ 2:パー 3:やめる
ゴンさん : グー、コンピュータ : チョキ
勝ち
0:グー 1:チョキ 2:パー 3:やめる
ゴンさん : チョキ、コンピュータ : パー
勝ち
0:グー 1:チョキ 2:パー 3:やめる
ゴンさん : パー、コンピュータ : パー
あいこ
0:グー 1:チョキ 2:パー 3:やめる
```
- 結果は、こういった感じです。 改行とかで見やすくしたほうがよさそうです。

---

# もうこれで終わってもいい　だからありったけを
---
ピザのトッピングを視覚化してみたよ

## はじめに
　トッピングの有無をチェックボックスのクリックだけで済ますのは物足りなかったので、
　視覚的にわかるようにしてみたよ。

##　概要
　jQueryを使ってチェックボックスと画像を紐付けてみる。

　imgのクラスをチェックボックスのvalueと同じ名前にしてリンクさせる。

```index.html
<div class="checkbox">
  <label><input type="checkbox" name="topping" value="cheese">チーズ</label>
  <label><input type="checkbox" name="topping" value="tomato">トマト</label>
  <label><input type="checkbox" name="topping" value="sarami">サラミ</label>
</div>
<div class="relative">
  <img class="kiji" src="images/kiji.png">
  <img class="cheese" src="images/cheese.png">
  <img class="tomato" src="images/tomato.png">
  <img class="sarami" src="images/sarami.png">
</div>
```
　セレクタに変数を入れることができるらしいのでval()でvalueを取得し、先頭に.を連結することで
　紐づけ完了。

```app.js
$(function(){
  // チェックボックスを押したとき
  $('input[name="topping"]').change(function(){
    // すべてのチェックボックスに対して
    $('input[name="topping"]').each(function(){
      //  チェックがあれば
      if($(this).prop('checked')){
        // 表示
        $("." + $(this).val()).css('display', 'block');
      // チェックがなければ
      }else{
        // 非表示
        $("." + $(this).val()).css('display', 'none');
      }
    });
  });
});
```
　画像を透過する必要があるので[PEKO STEP](https://www.peko-step.com/tool/alphachannel.html)というサイトを使ってみた。かなり楽だった。
　

<img width="490" alt="スクリーンショット 2019-06-03 17.44.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371735/3841a412-e831-5a4a-46de-3e79cd824710.png">
　　　　　　　　　　　　　　　↓
<img width="516" alt="スクリーンショット 2019-06-03 17.31.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371735/0844865a-53ba-076b-ba1e-5e81cd96e567.png">

　サラミの脂？を#FFFに指定したので背景色と被り、脂も透過してしまった...
初心者見たほうが良い記事, おすすめソフト（日本語記事）

# エンジニアより

### Programmer

https://b.hatena.ne.jp/hotentry/it
https://www.publickey1.jp/tool-ide-programming/
https://qiita.com/tag-feed

### Git
https://git-scm.com/book/ja/v2

### SE
https://tech.nikkeibp.co.jp/genre/systems/

### Infra
https://dev.classmethod.jp/category/cloud/aws/

# デザインより

https://coliss.com/
https://uxmilk.jp/

# IT業界おる方

https://logmi.jp/tech
https://jp.techcrunch.com/
https://www.itmedia.co.jp/news/
https://japanese.engadget.com/
https://internet.watch.impress.co.jp/
https://pc.watch.impress.co.jp/category/market/trend/hp/
https://www.afpbb.com/category/it

# ソフト
LaravelのAPIリソース（JsonResource）の仕様


## 前提条件
Laravel5.8
公式ドキュメント：https://readouble.com/laravel/5.8/ja/eloquent-resources.html

# JsonResourceの実装
## １．__costruct()で、引数resourceを保持。
(vendor\laravel\framework\src\Illuminate\Http\Resources\Json\JsonResource.php)

```php

    public function __construct($resource)
    {
        $this->resource = $resource;
    }
```

## ２．クラスのpropertyに存在しないデータにアクセス
←__get($key)でresourceのpropetyにアクセスするように設定してある
(vendor\laravel\framework\src\Illuminate\Http\Resources\DelegatesToResource.php)

```php

/**
     * Dynamically get properties from the underlying resource.
     *
     * @param  string  $key
     * @return mixed
     */
    public function __get($key)
    {
        return $this->resource->{$key};
    }
```

## ３．クラスのMethodに存在しないメソッドを呼び出し
←__call($method, $parameters)でresourceのメソッドを呼ぶように定義してある

```php
    /**
     * Dynamically pass method calls to the underlying resource.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        return $this->forwardCallTo($this->resource, $method, $parameters);
    }
```
【Mac】iTerm2をポケモンターミナルに

[Macでターミナルの背景をポケモンにする(iTerm)  - Qiita](https://qiita.com/ryoma-tokushige/items/e5ac32c67d7318e7cb8a)
[GitHub - LazoCoder/Pokemon-Terminal: Pokemon terminal themes.](https://github.com/LazoCoder/Pokemon-Terminal)

## こんなときに
* 仕事中、ポケモンを感じたい


## 手順
### 1. python3を公式サイトから落とす。
（[Download Python | Python.org](https://www.python.org/downloads/)）
### 2. 展開してインストーラーを実行。
### 3. iTermに移動。コマンドが反応するか確認。
```bash
python3

pip3.7
```
pip3.7[=バージョン数]
コマンドが反応したらOK。

### 4. pipを使ってgithubからポケモンターミナルを落としてくる
```bash
pip3.7 install git+https://github.com/LazoCoder/Pokemon-Terminal.git
```

### 5. pathを通す。（iTermは落としてくると自動で通った。
```bash
source ~/.bash_profile
```

### 6. `pokemon`を叩けばランダムで背景がセットされる。
### 7. 幸せ

![スクリーンショット 2019-06-03 18.14.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235781/b96f8676-4cc2-7c62-7c25-e37eeb248396.png)


## カスタマイズ
GitHubを読めば書いてあること。

### ポケモンを指定
```bash
pokemon eevee
```
英語名なので注意。
no.719まで、第六(xy)世代,ディアンシーまで対応してるとのこと。

### 地方ごとにランダム
```bash
pokemon -r hoenn;
```
{kanto,johto,hoenn,sinnoh,unova,kalos}

### タイプごとにランダム
```
pokemon -t fire
```
{normal,fire,fighting,water,flying,grass,poison,electric,ground,psychic,rock,ice,bug,dragon,ghost,dark,steel,fairy}


### iTerm起動時に `pokemon`を自動で打たせる
環境設定 -> Profiles  -> Command
の
Send text at start: …
の部分に `pokemon; clear`を入力。

![スクリーンショット 2019-06-03 18.24.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235781/9f010332-ae1b-81f7-055b-c9ebbf97d0a1.png)


clearはターミナルの画面をまっさらにするやつ。
論文読んでてわかんなかった英語

英語で専門用語言われてもわかんないよね！

|English|日本語|
|---|---|
|derivative|導関数|
|activation|活性化|
|empirically|経験的に|
|relativistic|相対論的|
|coefficients|係数|
|drawback|障害|
|marginal|些細な|
|interpolate|加筆する|
|artifact|生成物?|
|in conjunction with|併用して、合わせて|
入力可能なリストボックス

# 前置きというか言い訳というか
自分が知らなかっただけなんですが、ググっても良さそうな記事も見つけられなかったので、備忘録を兼ねて。
# やりたいこと
Webシステムで、例えば備考ようの定型文があるとして、

- 定型文から選択する（入力の簡易性のため）
- 自由入力をする（入力の自由性のため）

の両方を実現させたい。

# 結論
`<input type="textbox" list="fuga">`と`<datalist id="fuga">`を使う。

# サンプルソース（要点のみ）
``` html:hoge.aspx
<asp:TextBox ID="txtBiko" runat="server"></asp:TextBox>
<datalist runat="server" id="dlBiko"></datalist>
```

``` vb:hoge.aspx.vb
' DB等から dtTbl As DataTable にデータを取って来ている前提で・・・
Dim strOption As String = ""
For Each dRow As DataRow In dtTbl.Rows
    strOption += "<option>" + dRow("VALUE1").ToString + "</option>"
Next
Me.dlBiko.InnerHtml = strOption
Me.txtBiko.Attributes("list") = Me.dlBiko.ClientID
```

`Me.dlBiko.ClientID`としているのは、asp.netのマスター画面を使っていて、
クライアントIDとサーバー側IDが同一のものにならないので、その対策です。

# 結果
ちょっと画像をつけるのが面倒なのでサボりますが、
テキストボックスにカーソルが当たると、選択項目の一覧が直下（または直上）に
ずらっと出てきて選ぶことができるようになりました。
テキストボックスなので、文字を削除したり自由に入力したりもできます。

ちなみに厳密に言うと
「入力文字列を条件として選択項目を ~~前方一致~~ 部分一致で絞り込んだ結果を
　選択可能な一覧として表示する」
という仕組みです。

そのため、テキストボックスが空欄であればすべての選択項目の一覧から
選ぶことができますが、
すでに入力がある場合はある程度絞り込まれた一覧から選択することとなります。
JIRAトランジション設定メモ

###JIRAのワークフローのトランジションでの設定メモ

**トリガー：**開発ツール等からJIRAのワークフローの遷移を自動で行うことが可能
　　　　　（開発ツール：Bitbucket, GitHub, Fisheye/Crucible）

**条件：**そのトランジションを実行するための前提条件を設定できる
　　　（実行するユーザー権限の条件、フィールドの状態 等々）

**検証：**そのトランジションが実行でのバリデーションを設定できる
　　　（必須項目のチェック、ユーザー権限チェック、日付のチェック 等々）

**事後操作：**トランジションが発生した後に処理する内容が設定できる
　　　（フィールドコピー、フィールドクリア、メール送信 等々）
　　　　※下記の記述位置の場合、JIRA履歴へ処理内容が記述されなくなる。
　　　　　- Createトランジションの場合、「課題を最初に作成」よりも前に記述する
　　　　　- その他のトランジションでは、「課題をデータベースに保存します」よりも後に記述


*JIRA Softwareバージョンは7.12.1*
BoostnoteをGoogleDriveと連携させる(Macユーザー向け)

Macの標準メモをずっと使っていたのですが、Markdown記法しにくく、パッと共有できないのが難点でした。
そこで見つけたのが、無料かつMarkdownに対応、さらにドライブで共有もできる **Boostnote**。
今回は、GoogleDrive(G Suiteアカウント)と連携する手順、使ってみて分かってきた長所と短所をまとめます。

(注)この記事はMacユーザかつGoogleアカウントをG Suiteで管理している場合を想定して書いています。
普通のGoogleアカウントの場合、インストールするものが変わるのでご注意を。
https://www.google.com/intl/ja_ALL/drive/download/

## 導入方法

1. Boostnoteをインストール。
[Boostnote \| Boost Happiness, Productivity, and Creativity.](https://boostnote.io/ja/)


1. Googleドライブと連携するために、
 ```brew cask install google-drive-file-stream``` でインストール。
 
1. アプリケーションから**google-drive-file-stream** を開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390780/3041c56f-fa3b-36d4-b311-c5f0b115b0b0.png)
この際にmacのセキュリティでアプリの起動が弾かれると思うので、
macのシステム環境設定＞セキュリティとプライバシー＞一般からアプリケーションの実行を許可する。

1. 無事起動できたら、メニューバーにアイコンが追加される。
<img width="486" alt="スクリーンショット 2019-06-05 17.58.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390780/887d5fa5-4023-2e1c-c983-e42efdd0eeb6.png">

1. アプリを起動し、Googleアカウントでログインする。

1. GoogleDriveからデータが同期されるのを待つ。
ここで、ドライブに**boostnote用のフォルダ**作っておく。


1. Boostnoteを開き、**設定/ストレージ** 画面へ


1. **+ストレージロケーションの追加**を選択


1. **名前**は自分が分かりやすいようにつける。
  **ロケーション**でPC上のGoogleDrive(2で入れたやつ)を選択する(ダブルクリックしたら開ける)。

## 長所
- 無料
- Markdownがすっきり見える
- 共有ドライブを設定すればチームメンバーとノートの共有が可能

## 短所
- スマホアプリがない(スマホ上でノートを確認できない)
- なぜか日本語で全文検索できない
- フォルダを階層構造にできない

***
参考記事
 [BoostnoteのノートをGoogleドライブを使って複数PC間で共有・同期する方法 \| プラスガジェット](https://plusablog.me/?p=4863)
plunkerでsimcirjs その10

#概要

plunkerでsimcirjsやってみた。
式から回路作ってみた。

#写真

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/b5c4a056-af41-412f-9661-fab697d86ae5.png)


#成果物

https://embed.plnkr.co/R0fYAxTwIXOksfbfcc6P/

以上。
なぜredirect_to @userでユーザーページにリダイレクトできるのか詰まったのでその訳を説明する

Rails turtorialの7.4.1「フォームの完成」の章をやっている際、redirect_to @userでなぜユーザーページにリダイレクトのか分からず詰まったのでそれに関して説明していきます。




まず初めに以下のコードをご覧ください。


```app/controllers/users_controller.rb
class UsersController < ApplicationController
 .
 .
 .
 def create
   @user = User.new(user_params)
   if @user.save
     redirect_to @user
   else
     render 'new'
   end
 end

 private

   def user_params
     params.require(:user).permit(:name, :email, :password,
                                  :password_confirmation)
   end
end 
```

ここで、
`redirect_to @user`
といった行がありますが、これは次のコードと等価になります。
`redirect_to user_url(@user)`

これは`redirect_to @user`というコードから`user_url(@user)`といったコードを実行したいということを、Railsが推察してくれた結果になります。

つまりuser_urlにリダイレクトするという記述が省略されているという事。


ではここで、次の疑問として`user_url(@user)`の`(@user)`は何を表しているのという疑問があります。

これは結論から言うと`user_url`にリダイレクトした時にエラーを返さない様にする為です。


基本的に`user_url` は`/users/:id`の様なURLになっていることが多いです。

以下参照
![スクリーンショット 2019-06-03 17.28.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396216/09e6bb93-6e8c-97cf-aec2-3ba71fef78ff.png)


`redirect_to user_url`だけでは`:id`の部分に何が入るのか分からない為、`/user/:id`にアクセスした時にエラーとなります。
この`:id`の部分に何が入るかを指定するのが`(@user)`の部分です。
引数に`@user`と指定することでその変数に格納されたレコードに該当するページへのURLとなります。

つまりこの`(@user)`はインスタンス変数ではなく`:id`を入れる為にあるもの。

まとめると、
・`redirect_to @user`というコードは`user_url(@user)`といったコードを実行したいということを、Railsが推察してくれた結果である。
・`(@user)`は`user_url`にリダイレクトした時にエラーを返さない様にする為にある。
Craft CMS で管理画面での操作ログなどを確認する

何が見れるのか細かく見てないけど。
この辺のプラグインで見れる様子。

> Activity Log
> https://plugins.craftcms.com/activitylog
> 
> Audit
> https://plugins.craftcms.com/audit

あとで試してみよう。
CentOSを令和対応する

メモです。

# 現状

```shell
% date -d "2020/01/01 12:00:00" +"%EY"
平成32年
```

# 対応
dateコマンドをアップデートすれば良いので

```shell

% sudo yum update glibc
% date -d "2020/01/01 12:00:00" +"%EY"
令和2年
```
旧 MacBook (A1181: Early 2006 - Mid 2009) に OS を入れるあれこれ

旧 MacBook (A1181: Early 2006 - Mid 2009) で、いろいろお試しした結果を綴っただけのメモです。
Early 2008 (MB40x) については別枠で。

### 1. MacBook Early 2006 モデルには、Linux Mint 32 bit がサクっと入る

※ EFI からインターネット リカバリーができないモデルなので、インストール可能なバージョンの OS X のインストール メディアを持っていないと何かあった場合に元に戻せないなど大変なことになります。十分ご注意ください。

Early 2006 の MA254*/A, MA255*/A, MA472*/A の日本語モデルはデフォルトでメモリが 512 MB x 2 = 1 GB、多くの方は 1 GB x 2 = 2 GB (最大) に換装して使って、それを中古に投げてきてるんで、何気に使えるのかと思いきや、CPU が CoreDuo なので 32 bit しかない。

また、このモデルは OS X が 10.6 Snow Leopard までしか入らないので、Web ブラウザ事情がすこぶる悪く、Intel で Waterfox が使えない (Waterfox は 10.7 Lion 以上)、PowerPC G3/G4 の Tiger / Leopard の TenFourFox が使えない、とほぼ絶望的な状況に追い込まれます。

かと言って、このモデルで BootCamp は Windows XP / Vista しかサポートが無くて Windows 7 すら公式にはサポートしていないのを承知の上で、Windows Vista → Windows 7 → Windows 10 と多段階で入れるだけの価値があるのか？と言えばかなり疑問だったりします。

そんなときこそ、Linux があるじゃないですか！という話になるかと思いきや、32 bit。今となっては選択肢も減ってきてるという寂しさ。それでもまあ、人気の Linux Mint を入れてみましょう。

Snow Leopard の最後までフル アップデートして、すべてのファームウェアのアップデートを行った状態では、ディスクをまっさらにして Linux Mint だけを入れるにしても、rEFInd とか入れてデュアルブート構成するとかにしても、さくっと一発で Linux Mint 19.1 は入りました。メモリ DDR2 667 PC2-5300 2 GB で Cinnamon が結構いい感じで動いてます。思ったよりはストレス少なめ。

何と言っても、Mint 19.1 では Firefox が Quantum 66 で LibreOffice も 6 ですよ。蘇生とか蘇るとか言えるレベル。大いに価値ありますね。しかし、起動に難あり。GMA 950 と相性が良くないのかもしれず。ブートの途中で再起動入って、デフォルト モードになっちゃって GRUB メニューが表示されて 30 秒のカウント ダウンになるとか、あんまりピリッとしない感じ。

### 2. ポリカーボネートの Early 2009 と Mid 2009 は、Mojave Patcher で Mojave 入れてから BootCamp 使いたい場合に面倒

※ EFI からインターネット リカバリーができないモデルなので、インストール可能なバージョンの OS X のインストール メディアを持っていないと何かあった場合に元に戻せないなど大変なことになります。十分ご注意ください。

MB881*/A, MC240*/A はちょっと面倒ですね。このモデルだと、メモリに DDR2 800 を使えるので、今ではお安く 2 GB x 2 = 4 GB にして、Mojave Patcher に手を染めるというのが基本的なセオリーになるのではないかと思いますが、問題は Mojave を入れたあとに Windows も入れようとする場合。

まず、このモデルについては Windows 7 までの 32 bit しかサポートがないので、64 bit 版入れたければ、いろいろもがくしかないでしょう。ちなみに、メモリを 4 GB 以上積んでる状態で 32 Bit Windows 10 を入れると、最大使用可能メモリは 2.73 GB まで減ります。

Mojave の BootCamp アシスタントでは、Windows 10 64 bit のメディアが必須となります。つまり、Windows 10 64 bit のメディアをセットして、USB ドライブには BootCamp のモジュールをあらかじめ突っ込んでおいた上で Windows のセットアップだけを実行するようにして、再起動のタイミングで一旦電源をブチ切ってメディアを目的のものに差し替えるという、めんどくさいごまかしをする必要性が出てきます。

### 3. MB881*/A (Early 2009) に Mojave Patcher で Mojave 入れると、トラックパッドがマウスとして動く

Early 2009 の MB881*/A に Mojave を Patcher で無理やり入れたときに、トラックパッドはマウスと同じ振る舞い。このモデルは 1 ボタンなので、右クリックの代わりが [Ctrl] + [Click] であることを知ってないといけないですね。たぶん、解決方法はないのかもね。
pipコマンドでパッケージをインストール

#pipコマンドでパッケージをインストール
[「venv仮想環境の作成」](https://qiita.com/pappapa/items/60c204ea284137791fbb)
まずは上の記事に目を通して頂けると理解できるかと思います。

##パッケージをインストール
```python:qiita.py
$ python3.7 -m venv pappapa
$ source pappapa/bin/activate
(pappapa) $ pip install numpy
```
"numpy"の部分はインストールしたいパッケージ名に変更

###動作確認

```python:qiita.py
(pappapa) $ python
>>> import numpy
>>> quit()
```

##パッケージをアンインストール

```python:qiita.py
(pappapa) $ pip uninstall numpy
#以下、全て"y"を入力
```
###動作確認

```python:qiita.py
(pappapa) $ python
>>> import numpy
#ここにエラーが出る
>>> quit()
```

##バージョン指定

```python:qiita.py
(pappapa) $ pip install numpy===1.14.1
```

##最新版に更新

```python:qiita.py
(pappapa) $ pip install -U numpy
```

##インストール済みパッケージ一覧を確認

```python:qiita.py
(pappapa) $ pip list
```

##新バージョンがあるかの確認

```pyton:qiita.py
(pappapa) $ pip list -o
```

##pipコマンドを最新にする

```python:qiita.py
(pappapa) $ pip install -U pip
```
Twitter民の年収が低いことを明らかにしてはいけなかった 【小ネタ】

前回の記事 「[Twitter民の年収は低い 【Nuxt.js】](https://qiita.com/Harusugi/items/caa1922d27ebea451aad)」の続きです。

Twitter APIでユーザのツイートを取得後、[COTOHA API](https://api.ce-cotoha.com/contents/index.html)で言語処理することでユーザの属性を推定する、というアプリを[【tweet-analytics.com】](https://tweet-analytics.com/)としてGoogle App Engineに載せて公開しました。
その後いろいろ起こったので、知見になるかと思い、メモ書き程度に公開しておきます。

# 記事&サービス公開後起こったこと

大きく２つの事が起こりました。


1. アクセスが増えてApp Engineの課金がすごいことになった
2. Twitterアカウントが凍結されてサービス利用不可になった

それぞれについて書いていきます。

## 1. アクセスが増えてApp Engineの課金がすごいことに

前回の記事公開後、おかげさまでたくさんの反響をいただきました。ありがとうございました。
なんと[GIGAZINE様](https://gigazine.net/news/20190521-tweet-analytics/)にも紹介されました。
ただ、その分Google App Engineの課金がすごいことになりました。

|![Screenshot](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287075/c1643dd0-d45d-1e02-4d77-568f3590fb19.jpeg)|
|:-:|

**一日70$超。** 

サービスの性質上キャッシュなどもあまりできず対策が打ちにくいので、そのままいくと月額20万超えるんじゃないかと思ってわりと焦りました。
App Engineって無料枠あるしそんなに高くないイメージがあったんですが、アクセスが増えると急に牙を剥く、ということを身をもって体感しました。。。

対策として以下の３つほど実施しました。

### max_instancesを減らす
App Engineのインスタンス数上限を設定してみました。
ただ、やはりアクセスが多いときは500エラーが頻発するようになってしまったので、
あんまりたくさん減らすことはできず。
(最大20インスタンスとかにしてもピーク時は捌ききれず・・・)

### 寄付を募る
恥を忍んで、PayPayとKyashのQRコードを貼ることで寄付を募ってみました。
こちらは思ってたよりもずっとたくさんの方にご支援いただき、
17人の方から計5170円の寄付をいただきました。
本当にありがとうございました。
私も今度から困ってるエンジニアを積極的に支援できるような人間になりたいと思いました(小並)

あと、これから個人でWebサービス作る方はとりあえずQRコード貼っとくと良いのかも、と思いました。

### 広告を入れる
Adsense申請をしてみたのですが、コンテンツが少なすぎと言われ審査落ち。
まぁそうですよね・・・
昔スマホアプリで[nend](https://nend.net/)を使っていたので、そういやnendもWeb対応してたよなということを思い出し申請。
無事に2日後くらいから広告が配信され始めました。(ただしスマホのみ)
ただ、直後に↓の凍結があったのでほとんど効果はなし・・・

## 2. Twitter凍結

人生初めてTwitterアカウントを凍結されました。
最初はTwitter側から、「規約違反だから凍結したよ」としか連絡が来なかったので、てっきり他の人に「いいね！」押しまくったのが原因かなと素で思ってました。
(サービス使った人に「いいね!」押しまくってた。)

2日後くらいにTwitter社からメールが来て、凍結理由が明かされました。
https://developer.twitter.com/en/developer-terms/more-on-restricted-use-cases

>Sensitive information
You should be careful about using Twitter data to derive or infer potentially sensitive characteristics about Twitter users. Never derive or infer, or store derived or inferred, information about a Twitter user’s:

>Health (including pregnancy)
>Negative financial status or condition
>Political affiliation or beliefs
>Racial or ethnic origin
>Religious or philosophical affiliation or beliefs
>Sex life or sexual orientation
>Trade union membership
>Alleged or actual commission of a crime


＞**Negative financial status or condition**

つまり経済状態が良くないという情報を明かしてはいけないとのことです。
完全に一致。
すいませんちゃんと規約確認してませんでした・・・。


### その後

年収出す機能削除して、メールでアカウント凍結解除してくれというメールを送ったら、6日ほどで解除されました。
サービスとしては８日ほど使えなかったことになります。
ちゃんと規約読んでおけばよかった・・・。

# まとめ

 - App Engineはアクセスくると高いので注意。
 - 寄付窓口つけておくと心優しい方が寄付してくれるかもしれない
 - Twitter API使う方は規約をちゃんと読みましょう。

現在、年収以外の機能は復旧させてますので、よろしければご利用下さい。
[tweet-analytics.com](https://tweet-analytics.com/)
(ただ、インスタンス数は絞ってます。つながらない場合はお時間を変えてお試し下さい。)
mysql2がbundle installできない時の対処方法

# bundle installできない

```
$ bundle install

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /Users/naoya.ohsaki/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/extensions/x86_64-darwin-18/2.6.0-static/mysql2-0.5.2/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /Users/naoya.ohsaki/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/mysql2-0.5.2 for
inspection.
Results logged to
/Users/naoya.ohsaki/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/extensions/x86_64-darwin-18/2.6.0-static/mysql2-0.5.2/gem_make.out

An error occurred while installing mysql2 (0.5.2), and Bundler cannot continue.
Make sure that `gem install mysql2 -v '0.5.2' --source 'https://rubygems.org/'` succeeds before bundling.
```

## 解決策の中でもググったものが使えない

```
$ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib --with-cppflags=-I/usr/local/opt/openssl/include"
```

このコマンドは海外のさいとにもあるし、日本のエンジニアの方もあちこちで載せてくれているコマンドですが、私の場合、無反応でした。

```
$ cat /Users/ユーザー名/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/extensions/x86_64-darwin-18/2.6.0-static/mysql2-0.5.2/mkmf.log
```

mkmf.logを見に行きます。

```
clang: error: unsupported option '--with-cppflags=-I/usr/local/opt/openssl/include'
```

と書いてあるので、さっきのコマンドのcppflagsオプションを外して、

```
$ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib"
```

とし、

```
$ bundle install
```

してみます。

```
$ Bundle complete! 22 Gemfile dependencies, 85 gems now installed.
```

できました。

## 結論
mkmf.logを見にいくってのが大事なことです。
しかし、なんでこんな面倒なことが起こるのかというと、

結論としては、opensslのビルドオプションに問題があるからです。
どうやらmysql2のgemってのはC言語で書かれているみたいで、ビルドする際にオプション指定する必要があるみたいですね。他の記事では両方指定してやってることが多いですが、ログを見ると片方アンサポートになったようですねぇ。二つもいらんということなので変更されたってことなんでしょうね。

## 参考文献
[【Rails】MySQL2がbundle installできない時の対応方法
](https://qiita.com/fukuda_fu/items/463a39406ce713396403)

[mysql2 gemインストール時のトラブルシュート
](https://qiita.com/HrsUed/items/ca2e0aee6a2402571cf6)

[【Rails環境構築】MySQL2が原因で「bundle install」失敗した時の対処法
](https://qiita.com/4EAE_Learner/items/110f7e025b1d842d4bee)
【備忘録】Service Worker 概要

## Service Worker とは

Service Workerとは、PWAの根幹を支える機能。

今までのWebアプリでは不可能だった機能を追加し、ネイティブアプリと同等レベルまで高めてくれる。
従来のWebアプリはページを開いていないとデータ受信できない。

モダンwebのアーキテクチャの機能を使用したWebアプリでも、ネイティブアプリにかなわない機能があった。
→ 主に、バックグラウンドでの処理（アプリ停止時のPush通知とか更新処理)



従来のwebアプリでは、外部との通信のやり取りを行うにはアプリのページが開かれていることが前提であった。そのため、ページを閉じている時には、バックグラウンドでの更新やPush通知の受信ができない。
Service Workerはこの課題を解決する。


**・Service Worker 不使用のWebアプリ**
<img width="545" alt="スクリーンショット 2019-06-03 12.31.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180939/65eb41b1-1d29-d18c-605e-a9e1da4cb38d.png">


**・Service Worker を使用したWebアプリ**
<img width="629" alt="スクリーンショット 2019-06-03 12.31.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180939/cd31dfc2-e991-1785-ba60-648e7d5a7785.png">


## Service Worker でよく使う機能

### アプリケーションキャッシュ

ブラウザからアクセスがなくても設定ファイルに基づき、アプリの起動時にダウンロードを行いキャッシュする。（プリフェッチ機能）

プリフェッチ機能を使用すると、これから見る予定のページも事前にダウンロードできるので、アプリを初めて起動した直後からオフライン対応ができる。

アプリ起動後は、ブラウザと外部との通信を中継し、事前に設定したルールに基づきキャッシュする。
キャッシュしたデータの保管は、ブラウザのキャッシュAPIが行う。

<img width="564" alt="スクリーンショット 2019-06-03 14.58.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180939/940a21be-e29c-77e2-8720-67dccfba2a37.png">
①〜②アプリ起動時、指定したデータをダウンロードしてキャッシュに保存（プリフェッチ機能）
③〜⑥Service Worker は、ブラウザとサーバーとのやり取りをプロキシのように中継し、受信データをキャッシュへ保存
⑦〜⑧Service Worker は、キャッシュ済みデータをブラウザへ応答


### サーバーからのPush通知
サーバーからのPush通知を漏らすことなく受信する。
※ ブラウザ本体が終了している時の動作は、PCではブラウザが次に開いた時にまとめて通知。
　スマートフォンの場合、受診してすぐに通知。

受信した通知は、通知API（Notification API）を使って、OSの通知ダイアログに表示する。
<img width="476" alt="スクリーンショット 2019-06-03 15.47.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180939/9e85e324-37b5-889e-759e-34ee9f1246c3.png">
①Service WorkerがサーバーからのPush通知を受信
②Service Workerが通知APIを呼び出し
③通知APIがOSに対し通知ダイアログの表示を要求

## Service Workerのセキュリティ
Service Workerには、セキュリティ上の安全を守るため、その制御をどのページにまで及ぼすことができるのかが定められている。

Service Workerの機能はとても強力で、キャッシュを利用したオフライン対応などの用途に使うのであればよいが、悪意を持った者がWebページのリクエストを盗み取るためにService Workerを利用しては問題となる。

そのため、Service WorkerはHTTPS（またはlocalhost）で提供されているWebページでしか登録できない。

これによって、Service Workerが改ざんを受けていないことを保証する。


## 参考
[Service Worker API技術情報](https://developer.mozilla.org/ja/docs/Web/API/ServiceWorker_API)
SageMakerの組み込みアルゴリズムで作成したモデルのデプロイと推論を、ローカルのJupyter notebookから実行

# はじめに
今回はSageMakerの組み込みアルゴリズムで作成したモデルのデプロイ、推論をローカルのJupyter notebook から実行したので、その内容を掲載します。

※今回私は ObjectDetection を利用したモデルで、デプロイ、推論を行います。

# 前提

- S3 上に SageMaker の組み込みアルゴリズムで作成したモデルがある。




# モデルのデプロイ

まず、aws 上のノートブックでで利用している boto3 と sagemaker をインストールします。

```
pip install boto3
pip install sagemaker
```

#### IAMロールの取得

- SageMaker と　S3 へのアクセスを許可するロール名を入力する。

```Python
role = 'ロール名'
```

- ロールは以下のコードで一覧表示できます。

```Python
import boto3

client = boto3.client('iam')

client.list_roles()
```

#### モデルをデプロイ

- デプロイ自体はSageMaker上のノートブックとコードは変わりません。
 - model_data : 先ほどモデルを保存したパス
 - image : 推論時に利用する Docker イメージ名  
 Docker イメージ名は**[こちら](https://docs.aws.amazon.com/ja_jp/sagemaker/latest/dg/sagemaker-algo-docker-registry-paths.html)**から参照してください。

```Python
import sagemaker
from sagemaker import get_execution_role
from sagemaker.model import Model

import boto3
import json

model =  Model(model_data='s3://dog-face/model/model.tar.gz',
               image='501404015308.dkr.ecr.ap-northeast-1.amazonaws.com/object-detection:latest',
               role=role)

model.deploy(initial_instance_count=1, instance_type='ml.m4.xlarge')

```

実行結果

- - の後に ! がついたら、モデルのデプロイ完了です。

```
----------------------------------------------------------------------------------------------------------------!
```

# 推論
- まず、作成したエンドポイント名を確認します。

```Python
client = boto3.client('sagemaker')

client.list_endpoints()
```

- エンドポイント名を確認したら、推論を行います。

```Python
#推論
file_name = '推論するファイル名'

with open(file_name, 'rb') as image:
    f = image.read()
    b = bytearray(f)

endpoint_response = boto3.client('sagemaker-runtime').invoke_endpoint(
    EndpointName='先ほど確認したエンドポイント名',
    Body=b,
    ContentType='image/jpeg'
)
results = endpoint_response['Body'].read()
detections = json.loads(results)
print(detections)
```

# エンドポイントの削除
- エンドポイントは時間単位で課金が発生するので、使い終わったら削除しておきましょう。

```Python
client.delete_endpoint(
    EndpointName='先ほど確認したエンドポイント名'
)
```

# 最後に
今回は、ローカルのJupyter notebook からモデルのデプロイと、推論を行いました。
SageMaker 上で同じことをしたい、という方は[**こちらの記事**](https://qiita.com/NendaiHiroki/items/d324893337430aa67cac)で紹介していますので、参考にしてください。
SQL構文

# SQLの構文の書き方
私はMYSQL（2年以上）とBIGQUERY(1年)書いてきました。
書き方の宗教などは特にございませんが、可読性や処理速度を気にして書くことが大事だと思います。

#　基礎構文
```sql
SELECT
  カラム名1,
  カラム名2,
FROM
　テーブル名を指定
```

##　sample_table
例えばこんなテーブルがあったとして

|id|name|
|----|----|
|1|AA|
|2|BB|
|3|CC|
|4|DD|

### 基本のSQL
```sql
SELECT
  sample_table.id
FROM
  sample_table 
```
実行結果

|id|
|----|
|1|
|2|
|3|
|4|

実際のテーブル名の指定の仕方は``` `project名.dataset名.テーブル名` ```（BigQueryだと多分こんな感じ）のように絶対パスで指定した方が事故が起きない

## WHERE句
除外したい条件をWHERE句で書くことができます。

```sql
SELECT
  sample_table.id
FROM
  sample_table 
WHERE
  sample_table.name = 'BB'
```
実行結果

id|
---
2|

## GROUP BY
GROUP BY句は集計するために使います

|id|name|salary|
|----|----|----|
|1|AA|200000|
|2|BB|150000|
|3|CC|130000|
|4|DD|120000|

### 平均算出SQL

```sql
SELECT
  AVG(sample_table.salary) AS average_salary
FROM
  sample_table 
GROUP BY
  sample_table.salary
```
実行結果

|average_salary|
|---|
|150000|

AVG以外にもたくさん集計関数はあります。（SUMとか）
Bigqueryは公式のリファレンスが親切なので一読することをお勧めします。
GROUP BY句は何列目かの数字でも指定できますが可読性が失われるのできちんと名前で指定してあげた方がいいかと思います。
venv環境を作成(mac OS)

#macOSでvenv環境を作成（仮想環境の作成）

[pipコマンドでパッケージをインストール](https://qiita.com/pappapa/items/7a9f1aff305bb76b051a)

##macOSでvenv環境を作成
```python:qiita.py
$ python3.7 -m venv pappapa
$ ls pappapa
$ source pappapa/bin/activate#仮想環境起動
```
**pappapa** の部分は自分で決める（環境名）
（以下、(pappapa)環境での実行例）

##pythonコマンド使用の確認
```
(pappapa) $ which python
```

##仮想環境を抜けるには
```
(pappapa) $ deactivate
```

##仮想環境の削除
```
$ rm -rf pappapa
```
**pappapa** の部分は削除したい環境名を入力