OmniAICreator/Qiita-1.07M huggingface dataset:
JSUG勉強会 2018年その4 Spring 5 & Spring Boot 2ハンズオン感想

日本Springユーザ会主催の
**JSUG勉強会 2018年その4 Spring 5 & Spring Boot 2ハンズオン**
に行ってきました。

#概要

講師はJJUG CCCなどでも頻繁に発表されているカサレアルの@suke_masaさん。

内容は30分（みごとにぴったりの時間！）の講義と、
残り2時間半のSpring5,SpringBoot2のハンズオンでした。

講義のスライド
https://www.slideshare.net/masatoshitada7/30spring-5-spring-boot-2-103523666

ハンズオンの教材
https://github.com/MasatoshiTada/spring5-boot2-handson

#講義 :初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
Spring初級者向けに、
言語化しづらいDIとは？SpringBootとは？などが胸に落ちる感じで解説してくれました。
Spring5からの機能は
自分も含め、JPAに拒否感が多い（ような気がする）日本では期待のSpring Data JDBCや
JUnit5対応したSpring Testなど。

#ハンズオン
教材のソースコードにはTODOで要修正の箇所が指定されていて、
容易に進めることができました。
Spring5パートでは、Spring Bootでは意識することがない設定ファイルの理解が深まるつくりになっていました。
また、スライドでも触れられていたSpring Data JDBCや@SpringJUnitConfigを使用したテストコードで大変参考になりました。
Spring Data JDBCはJPAと比較すると学習量はかなり低そうなイメージ。
interfaceだけ定義して、起動時に実装クラス作成とのことなので、大規模システムだとどうなるんだろうと思ったり。
回避策はあるのでしょうが。
採用にはページネーションの実装とか、いろいろ調査が必要だけどJPAに変わる選択肢ができたのは嬉しいですねー。

SpringBoot2パートでは、
Spring5パートで作成したconfigがこんなに不要になるよ、と小気味好く理解が進む形式でした。
Spring Boot触っていると、どこかで思ったように動作できなくなって、
AutoCofigureを学習したりするんですが、最初にこのハンズオンやっておくと勘が働くようになりそうです。

#まとめ
SpringBoot1系で実装していた自分にとっては、修正点が短時間で把握できる非常に参考となったハンズオンでした。
@suke_masaさんありがとうございましたー！
googleカレンダーに指定した文字列が含まれる本日の予定をchatworkで通知する

# 方法
## 1. googleカレンダーに通知したい文字列が含んだ予定を登録する。

## 2. カレンダーIDの取得
googleカレンダーの設定でF5をクリックして「カレンダー ID」を入力すれば見つかります。
```idCalendar = 'aaaaaaaaa@gmail.com';```
## 3. グループチャットIDの取得
chatwork　URLの********の部分
```https://www.chatwork.com/#!rid＊＊＊＊＊＊＊＊```

## 4. google apps script でchatwork のライブラリを使用する方法
参考URL http://c-note.chatwork.com/post/69590585422/chatworkapi-gas-library

## 5. google apps script を実行する
google apps script の使い方
参考URL https://qiita.com/rf_p/items/0535ec495df8f9d2b894

## 参考コード
```js
function runApp()
{
  idCalendar = 'aaaaaaaaa@gmail.com';　// カレンダー ID
  value = '買い物';
  var dataCalend=CalendarApp.getCalendarById(idCalendar); // IDを指定してカレンダー情報を取得する
  var events=dataCalend.getEventsForDay(new Date(), {search: value}); //　本日の日付と取得したい予定に含まれる文字列の指定
 
  for (var i=0;i<events.length;i++) {
    var description = events[i].getDescription();
    var title = events[i].getTitle();
  }

  var body = 'message: '+description;
 
  msgChatwork(body);
}

function msgChatwork(body)
{
  
  /* チャットワークにメッセージを送る */
  var cwClient = ChatWorkClient.factory({token: 'プロジェクトキー'});　//チャットワークAPI
  cwClient.sendMessage({
    room_id:＊＊＊＊＊＊＊＊, // chatworkのグループチャットのIDを指定する。個人のチャットワークのIDでも可
    body: body
  });
}
```
MacでApacheの設定ファイルを編集する

#ターミナルを開く
MacはApacheが標準でインストールされてる。
バージョン確認

```
httpd -v
```

で

```
Server version: Apache/2.4.28 (Unix)
```

と出た。

#Apacheの設定をhttpd.confで変更
ターミナルでhttpd.confを開く

```
$ sudo vi /etc/apache2/httpd.conf
```

これは「vi」を使って、httpd.confをターミナル上で変更しますよ、っていう命令
viの操作方法が通常とはまったく違うのでメモ

##文字の入力系
|入力する文字|意味|
|:-----------------|:------------------|
|i|今いるカーソルの位置に入力|
|l|今いる行の先頭に入力|
|a|今いるカーソル位置の直後に入力|
|A|今いる行の末尾に入力|
|esc|挿入モードを終了|

##削除系
|入力する文字|意味|
|:-----------------|:------------------|
|x|1文字の削除|
|dw|1単語の削除|
|dd|1行の削除|

##保存と終了
|入力する文字|意味|
|:-----------------|:------------------|
|:w|保存|
|:wq|保存して終了|
|:q|保存せずに終了（変更点があるときは終了できない）|
|:q!|保存せずに終了（変更点があるときは破棄される）|

で、改めて。
httpd.confをターミナルで編集する

```
#LoadModule php5_module libexec/apache2/libphp5.so
```

この#を外す

ドキュメントルートは変更可能だけど、今回はそのままで。
ちなみに通常のドキュメントルートは以下

```
/Library/WebServer/Documents
```

でも、.htaccessは使えるようにする

```
AllowOverride None
```

を

```
AllowOverride All
```

へ。
そして

```
<IfModule dir_module>
    DirectoryIndex index.php index.html
</IfModule>
```

これで、index.phpでも自動的に表示される

#アクセスしてみる
ブラウザで`http://localhost/`にアクセス
**It works!**とか表示されればオッケー
lodash の path を使う関数でオブジェクト操作が便利になる

JavaScript を使っているなら [lodash](https://lodash.com/docs/) は大変便利なのですが、関数が多すぎてどれ使ったらいいのか解りづらいのが難点です。

ここではその中でも `'a.b[0].c'` のような path を使ってオブジェクトを操作できる関数が便利なので紹介します。


値取得
======

[get](https://lodash.com/docs/4.17.10#get), [at](https://lodash.com/docs/4.17.10#at), [result](https://lodash.com/docs/4.17.10#result), [invoke](https://lodash.com/docs/4.17.10#invoke)

```js
var object = { 'a': [{ 'b': { 'c': 3, 'd': _func(4) } }, 5, [1, 2, 3, 4]] };

_.get(object, 'a[0].b.c')           // => 3          // 単一の値を得る
_.get(object, 'a[99].z.y')          // => undefined  // ヌルポは出ないので便利
_.get(object, ['a', '0', 'b', 'c']) // => 3          // path は配列でもいい
_.get(object, 'a.b.c', 'default')   // => 'default'  // デフォルト値の指定も可能
 
_.result(object, 'a[0].b.d')                   // => 4 // 関数として実行し、その結果を返す
_.result(object, 'a[0].b.c')                   // => 3 // 関数じゃないなら、get と同様
_.result(object, 'a[0].b.e', _func('default')) // => 'default'
_.result(object, 'a[0].b.e', 'default') 　     // => 'default'

_.invoke(object, 'a[1].slice', 1, 3)           // => [2, 3] // 関数として実行。引数を渡せる

_.at(object, ['a[0].b.c', 'a[1]']) // => [3, 5] // 複数のパスを指定して、値の配列を得る
```

パスの存在チェック
======

[has](https://lodash.com/docs/4.17.10#has), [hasIn](https://lodash.com/docs/4.17.10#hasIn)

```js
var object = { 'a': { 'b': 2 } };
var other = _.create({ 'a': { 'b': 2 } }); // 継承した子クラスを作る

_.has(object, 'a.b') // => true
_.has(other, 'a')    // => false // 親クラスまでは辿らない

_.hasIn(other, 'a')    // => false // 親クラスを辿る
```

- `In` はたぶん `inherited` (継承された) の略。


更新
======

[set](https://lodash.com/docs/4.17.10#set), [update](https://lodash.com/docs/4.17.10#update), [unset](https://lodash.com/docs/4.17.10#unset)

```js
var object = { 'a': [{ 'b': { 'c': 3 } }] };

// 単純な更新
_.set(object, 'a[0].b.c', 4); // object.a[0].b.c を 4 に更新
_.set(object, 'z[0].b.c', 4); // object.z[0].b.c を追加。中間の object や array が無ければ作成する

// 関数で更新
_.update(object, 'a[0].b.c', n => n * n); // object.a[0].b.c を 9 に更新
_.update(object, 'x[0].y.z', n => n ? n + 1 : 0); // キーが存在しないなら undefined

// キー削除
_.unset(object, 'a[0].b.c'); // { 'a': [{ 'b': {} }] } に更新して true (更新した) を返す
```

- いずれも引数で渡した `object` 自体を変更する (破壊的)



lodash関連の記事
======

- [lodash の path を使う関数でオブジェクト操作が便利になる](https://qiita.com/waterada/items/8c57f37d3decdbc583fe)
- [lodash の forEach/map/reduce 系の関数を紹介](https://qiita.com/waterada/items/22ef4c618050ea766137)
- [lodash ちょっとマニアックだけど便利な関数](https://qiita.com/waterada/items/63eb186e2150d38bb6ed)
- [lodash の debounce や throttle で簡単に負荷対策](https://qiita.com/waterada/items/986660d31bc107dbd91c)
Dockerで自然言語処理を簡単に行う方法

## 概要

近年の機械学習・ディープラーニングブームもあり、自然言語を対象とする機会が増えてきました。しかし、自然言語処理関連の環境構築は簡単ではありません。いろいろなところに散らばっているパッケージを集めてビルドを行う必要があります。自分はPythonで自然言語処理をしたいだけなのに！と考える皆様。もう苦労する必要はありません。

ということで、Dockerで自然言語処理のパッケージを作成し、それをDocker Hubに登録しました。みなさんが行うべきことは

```bash
$ docker run -p 8888:8888 kangaechu/nlp-jp-jupyter
```

たったこれだけです。[^1]

あとはブラウザで http://localhost:8888 を開き、ターミナルに表示されたtoken=以降の文字列をコピーして貼り付けしょう。そこにJupyter Notebookの世界が広がっています。
MeCab、JUMAN++、KNPが使えます。

## 対応しているパッケージ

- [MeCab (+ IPADIC)](http://taku910.github.io/mecab/)
- [Juman](http://nlp.ist.i.kyoto-u.ac.jp/EN/index.php?JUMAN)
- [KNP](http://nlp.ist.i.kyoto-u.ac.jp/?KNP)
- [Juman++](https://github.com/ku-nlp/jumanpp)

## 公開しているもの

- [Docker Image](https://hub.docker.com/r/kangaechu/docker-alpine-nlp-jp/): MeCab, Juman, KNP, Juman++をコマンドラインから使う
- [Dockerfile](https://github.com/kangaechu/docker-alpine-nlp-jp):  上記Docker ImageのDockerfileです。
- Alpine APK レポジトリ: ビルド済みのパッケージ。`apk add`コマンドでインストール可能。
- [Packeage build source](https://github.com/kangaechu/alpine-nlp-jp): MeCab, Juman, KNPなどのapkパッケージを作成するためのファイル。


## やったこと

### apkパッケージの作成

DockerならAlpine Linuxです。しかし自然言語処理関連のパッケージは公式レポジトリには登録されていないので独自レポジトリを作成しました。

https://github.com/kangaechu/alpine-nlp-jp

https://wiki.alpinelinux.org/wiki/Creating_an_Alpine_package

[^1]: ただ時間はすごいかかるので注意
Vue.jsメモ（用語まとめ）

# 個人的まとめです

初学者なので間違っていればご指摘いただければ幸いです。

随時更新。

## データバインディング

- データ（`Javascript`）と描画（`html`）を結びつける仕組み
- データに変化があれば自動的にDOMを更新することが可能

従来の場合

```javascript:legacy.js
var el = document.getElementById('app')
el.innerText = 'Hello Vue.js'
```

Vue.jsの場合

```javascript:vue.js
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  }
})
```

- `el: #app` - mountする要素
- `data: {}` - アプリケーションで使用するデータ

行数的には長く見えるが、従来のDOM更新（ライブラリを使用しない）は数が増えると同じ手続きが増えてしまう。

## ディレクティブ

- `v-`から始まる属性
- データバインディングに使用
- アプリケーション内のデータ用オブジェクトのプロパティを生成

e.g. `v-bind :value .sync = "message"`
左から、**ディレクティブ**, **引数**, **修飾子**, **値(JavaScriptの式)**

一例：
`v-model`, `v-on`, `v-bind`, `v-if`, `v-else-if`, `v-else`, `v-show`, `v-for`

## データ駆動(data-driven)

- データを中心としたアプリケーション設計
- データの状態によって動的に（自動的に）、描画やアクションなどが変わる

## Nuxt.js(ナクスジェーエス)、VuePress

- Vue.jsの拡張フレームワーク

## ライフサイクルフック

- Vueインスタンスの特定のタイミングでの自動呼び出し

## リアクティブデータ、リアクティブシステム

- `get`したとき`set`したときのフック処理が登録された反応できるデータ
- リアクティブシステムのひとつにデータバインディングがある

機能

- DOM更新の最適化
- 加工したデータの同期
- 変更の検知⇒フックした処理の自動実行

## Mustache(マスタッシュ)

- `{{ hoge }}`で記述する記法
- `hoge`プロパティをbindする（常に同期するので、DOM更新のためのコードを記述しなくてよい）
Kotlin DSL でパスの木構造を記述できるようにしてみた

# 概要

Kotlin DSL で，パスをスラッシュ区切り（`operator fun div`）で書けるようにしてみました．
パスは単純に `"path1" / "path2" / "path3"` のように記述することもできますし，

```kotlin
"path1" / {
  - "path1-1" / "path1-1-1"
  - "path1-2" / {
    - "path1-2-1"
    - "path1-2-2"
  }
}
```

のように木構造を書くこともできます．

実装はこちらです．
https://github.com/hmiyado/kuri

# 背景

[Kotlin Developers Meetup](https://kotlin.connpass.com/event/90679/) に参加しました．
そこで，Hadi 氏によるライブ Kotlin DSL 構築や，LT での有限オートマトンのDSLによる記述といった発表を見て，自分でも少し書いてみようと思いました．

何を書くかで思い当たったのが，パスの組み立てです．
普段は Android を書いていますが，URIを組み立てるために，パスの記述が各所に記述が散らばってしまっていました．
URI全体の一覧性がない，各所でタイプミスのリスクがある，等の問題があります．
まず，手始めに，一覧性がない問題を解決するため，木構造を持ったパスを記述できるようにしました．

# 実装

## パスの連結の実装

最も重要な実装は `operator fun div` を用いた文字列の拡張です．

```kotlin
operator fun String.div(path: String): KPath
```

これで，文字列の後に `/` を置いてパスを連結することができます（`KPath` は木構造でないパスを保持するクラスです）．
`/` を連続して書いてパスを連結させるためには，`KPath` 自身も `div` を実装する必要があります．

```kotlin
operator fun KPath.div(path: String): KPath
```

## 木構造の実装

パスの連結の実装によって， `/` の後に文字列を書いてパスを連結していくことができるようになりました．
木構造を書くためには， `/` の後にラムダ式を取れるようにする必要があります．

```kotlin
"path" / { /* ラムダ式 */ }
```

木構造を保持するクラスを `KNode` ，そのビルダーを `KNode.Builder` としましょう．
以下の拡張関数を実装すれば，見た目を合わせることができます．

```kotlin
operator fun String.div(builder: KNode.Builder.()->Unit):KNode = KNode.Builder().apply(builder).build()
```

これで木構造自体は書けるようになりました．

次に，木構造の中身，子のパスを増やす部分を書くために，ラムダ式の中に目を向けてみましょう．

```kotlin
"path" / {
  - "subpath1"
  - "subpath2"
}
```

文字列の前に `-` がついています．
これは， 子のパスを追加するために付けざるを得なかった記号で，kotlinでいうところの `operator fun unaryMinus` を使っています．

```kotlin
operator fun String.unaryMinus(): KPath
```

この拡張関数の中で， `KNode.Builder` が内部的に保持するコレクションに，文字列を追加するという処理を行っています．
もしこれがなければ，以下のような書き方になりますが，

```kotlin
"path" / {
  "subpath1"
  "subpath2"
}
```

これだと単にラムダ式の中に文字列が2つあるというだけになってしまい，ビルダーに文字列をパスとして追加するタイミングがありません．
無理やり `unaryMinus` をつけることで，なるべくDSLの見た目に違和感を出さないようにしつつ，ビルダーにパスを登録できるようにしています．

# 感想

DSLの見た目から逆算して各演算子を実装したため，内部的な実装がきれいになりませんでした．
特に，木構造を記述するためにビルダーのプロパティに値をセットするのではなく，演算子（`-`）がついていればコレクションに追加するという実装になっています．
そのあたりの関係で，結構煩雑な実装を強いられる箇所がありました．
プロパティを明示せずにきれいに DSL を書く知見がありましたらぜひ教えてください．

今回の実装は，構造をパースできるようにしてみた，という状態で終わっており，まだ実用に耐えうる段階にはありません．
将来的には，上記DSLで定義したパスから，クラスファイルを自動生成する，パスの中にID等の変数を許容し，型安全にパスを生成できるようにする，等の発展的実装をしたいです．
【Rubyアンチパターン】ensure節でreturnしてはならない

# ensureでreturnすると...

rubyで例外処理を書くとき、ensureに「return」を書いてはいけません。

```rb
# ヤバい例
def div(x, y)
  puts "=== 計算開始 ==="
  ret = {}
  ret[:answer] = x / y
  ret[:message] = "割り算成功！"
rescue ZeroDivisionError => e
  ret[:answer] = nil
  ret[:message] = "割り算失敗..."
ensure
  puts "=== 計算終了 ==="
  return ret
end
```

なぜなら、ensureでreturnすると、**rescueで指定していない例外ももみ消す**という恐ろしい挙動をするからです。
下記の実行例を見てください。

```rb
# 実行例１
div(10,2)
=== 計算開始 ===
=== 計算終了 ===
#=> {:answer=>5, :message=>"割り算成功！"}

# 実行例２
div(10,0)
=== 計算開始 ===
=== 計算終了 ===
#=> {:answer=>nil, :message=>"割り算失敗..."}

# 実行例３
div(10,"abc")
=== 計算開始 ===
=== 計算終了 ===
#=> {}
```

実行例１・２は、想定どおりの動作かも知れません。
でも、実行例３はどうでしょうか？
「10 ÷ "abc"」は計算できないので、TypeErrorが発生しそうに思えますが、実際は例外が発生せず、空のハッシュが返されています。

このようなコードは、出るべき例外を隠してしまうので、バグの温床となる上、デバッグがしづらくなり、とても厄介です。

# 改善例

ensureでreturnするのではなく、本体とrescueの最後に、戻り値に指定したい値を書くようにしましょう。

```rb
# 改善例
def div(x, y)
  puts "=== 計算開始 ==="
  ret = {}
  ret[:answer] = x / y
  ret[:message] = "割り算成功！"
  return ret
rescue ZeroDivisionError => e
  ret[:answer] = nil
  ret[:message] = "割り算失敗..."
  return ret
ensure
  puts "=== 計算終了 ==="
end
```

```rb
# 実行例１
div(10,2)
=== 計算開始 ===
=== 計算終了 ===
#=> {:answer=>5, :message=>"割り算成功！"}

# 実行例２
div(10,0)
=== 計算開始 ===
=== 計算終了 ===
#=> {:answer=>nil, :message=>"割り算失敗..."}

# 実行例３
div(10,"abc")
=== 計算開始 ===
=== 計算終了 ===
TypeError: "abc" can't be coerced into Integer
```

実行例１・２の動作は変わらず、実行例３の問題が解決されているのが分かると思います。

# 補足：言語仕様について

divメソッドは、必ず最後に

```rb
  puts "=== 計算終了 ==="
```

を処理するため、戻り値がnilになってしまうのでは、と考える方もいるかも知れませんが、心配無用です。
rubyは、言語仕様として、ensure節の評価値を無視するようになっているからです。

https://docs.ruby-lang.org/ja/latest/doc/spec=2fcontrol.html#begin
> begin式全体の評価値は、本体／rescue節／else節のうち 最後に評価された文の値です。また各節において文が存在しなかったときの値 はnilです。いずれにしてもensure節の値は無視されます。

ちなみに、上記の仕様は、「Ruby技術者認定試験 Silver」でも問題として出題されます。
Ruby技術者認定試験で問われる知識は、他にも実践で役立つものが多い印象です。
ruby初心者で、まだ受けたことのない人は、是非1度受けてみると良いと思います。
BokehのRangeToolをつかってみる

どうも、Bokeh芸人のどりらんです。

Bokeh 0.13からRangeToolが使えるようになりました。
直近の時系列データみたいが、過去を遡ってみたい場合などに便利です。
グラフの範囲選択ツールで、[Highstock](https://www.highcharts.com/products/highstock/) などでは時系列データを可視化する際にデフォルトでついている機能だったりします。

おおまかな手順は下記のとおりです。

1. RangeToolを描画するfigureインスタンス(図)を作成する
2. RangeToolインスタンスを作成する
3. 1. の `add_tools` メソッドの引数に 2. を渡す

`RangeTool` クラスにキーワード引数 `x_range` または `y_range` に `Range1d` インスタンスを渡すことで、X軸、Y軸の範囲を設定できます。

`Range1d` クラスとはなんぞやというかたは [Jupyter本](http://gihyo.jp/book/2017/978-4-7741-9223-9) を読むと幸せになれるでしょう。

実際に時系列データを描画するとこんな感じになります。

```python
import numpy as np
import pandas as pd
from bokeh.layouts import Column
from bokeh.models import RangeTool
from bokeh.plotting import figure, output_notebook, show

output_notebook()  # Jupyter Notebookに出力する場合

# データを乱数で適当に作成
x = pd.date_range("2018-01-01", periods=365)
np.random.seed(10)
y = np.random.uniform(-0.1, 0.1, 365)
y[0] = 1
y = y.cumsum()

# メインのfigure
p1 = figure(
    plot_height=300,
    plot_width=800,
    x_axis_type="datetime",
    x_range=(x[-100], x[-1]),  # X値の描画範囲, Range1dオブジェクトが作成される (1)
)
p1.line(x, y)

# RangeToolのfigure
p2 = figure(
    plot_height=150,
    plot_width=800,
    y_range=p1.y_range,
    x_axis_type="datetime",
    toolbar_location=None,
)
p2.line(x, y)
range_rool = RangeTool(x_range=p1.x_range)  # (1) で作成されたRange1dオブジェクト
p2.add_tools(range_rool)

show(Column(p1, p2))
```

![Peek 2018-06-29 21-46.gif](https://qiita-image-store.s3.amazonaws.com/0/22023/64b4eb00-4a5a-1fd8-e3ef-b7d5acbbb421.gif)

実際にぐりぐり動かしてみたいかたは [ブログ](https://drillan.github.io/notebooks/bokeh_rangetool.html) でどうぞ。

RangeToolの書式を設定できます。詳細についてはドキュメントなどを参照してください。
本記事のコードは[公式ドキュメントのGALLERY](https://bokeh.pydata.org/en/latest/docs/gallery/range_tool.html) の内容を端折って書いています。
Rails5.1で一括登録フォームを実装する

複数レコードを一括で更新できるようなフォームを以前にもRails5(5.0.6)で作っていて、Rails5.1(5.1.6)で再利用しようとしたらエラーが出た。

# Rails5.0における一括更新の実装

以前はこちらを参考にさせていただいた。

[Rails4、fields_forを使って一括更新する処理のベストプラクティスは何だろう](http://j-caw.co.jp/blog/?p=1590)

記載されているコードを引用させていただく

```erb:_form.html.erb
<%= form_tag items_path, method: :put do %>
  <% @items.each do |item| %>
    <%= fields_for "items[]", item do |fi| %>
      <%= fi.text_field :name %>
      <%= fi.text_field :price %>
      <br />
    <% end %>
  <% end %>
  <%= submit_tag %>
<% end %>
```

```rb:items_controller.rb
class ItemsController < ApplicationController
  respond_to :html

  def edit
    @items = Item.all
  end

  def update
    @items = items_params.map do |id, item_param|
      item = Item.find(id)
      item.update_attributes(item_param)
      item
    end
    respond_with(@items, location: edit_items_path)
  end

  private
    def items_params
      params.permit(items: [:name, :price])[:items]
    end
end
```

上記のようなフォームからsubmitすると、

```
Parameters:
{ "items" =>
  {
    "1" => {"name" => "hoge", "price" => "1000"},
    "2" => {"name" => "fuga", "price" => "2000"}
  }
}
```

のように、イテレートされたitemのidをkey、フォームから送信されたパラメータをvalueに持つハッシュ形式のパラメータが送信される。

それをコントローラ側で受け取り、

1. params[:items]の中身をitems_paramsに格納
2. items_paramsをmapメソッドでイテレートし、keyをidに、valueをitem_paramに格納
3. 該当するitemをfindしてupdate

という処理を行っている。

Rails5.0はこれでうまくいっていたので5.1でもそのまま使おうと思っていたらエラーが出た。

# 5.1で出たエラー

> undefined method `map' for #<ActionController::Parameters:0x007f3db55ab370>
> Did you mean?  tap (NoMethodError)

メソッドがない???
5.1で消されたってことかな。。

# 5.0の更新処理を見直してみる

5.0の方のログに何かヒントがないかと思い、一括更新のフォームで更新を行った際のログを見直してみたところ、以下のような警告が出ていた。

> DEPRECATION WARNING: Method map is deprecated and will be removed in Rails 5.1, as `ActionController::Parameters` no longer inherits from hash.
> Using this deprecated behavior exposes potential security problems.
> If you continue to use this method you may be creating a security vulnerability in your app that can be exploited.
>Instead, consider using one of these documented methods which are not deprecated: http://api.rubyonrails.org/v5.0.6/classes/ActionController/Parameters.html

つまり、Hashにセキュリティリスクが存在するため、ActionController::ParametersはHashクラスからの継承をやめており、そのためmapメソッドが使えなくなっていたためにエラーが発生していた。

# 代替手段

なんか別の方法ないかな？と思いActionController::Parametersの[公式ドキュメント(Ruby on Rails 5.1.6)](http://api.rubyonrails.org/v5.1/classes/ActionController/Parameters.html#method-i-5B-5D)を見てみた。

keysメソッドを使ってパラメータのkeyになっているidだけ取り出してeachで回せば解決しそう。
というわけでコントローラーを修正してみる。



```rb:items_controller.rb
class ItemsController < ApplicationController

...

  def update
    @items = items_params.keys.each do |id|
      item = Item.find(id)
      item.update_attributes(item_params[id])
      item
    end
    respond_with(@items, location: edit_items_path)
  end

...

end
```

これで処理が通るようになった。
でも、そもそもこれでセキュリティ上のリスクって解消できてるのかな？

# 感想とか

- NoMethodErrorが出た時点で公式ドキュメント見れば良かったし、そもそも5.0で実装した段階でエラーに気づいとけよと
- 結局公式ドキュメント見るのが一番早いってよく見かけるけど最近やっとその実感が出てきた
- セキュアなアプリケーションの作り方とか、そもそもどんなリスクがあるのかとか知りたい。設計する段階から考えたいし。
matplotlibを使って小学校の頃一度は作ったであろう幾何学模様をグラフで表現する

突然ですが皆さんこの模様をご存知ですか？

>![IMG_4149.jpg](https://qiita-image-store.s3.amazonaws.com/0/263905/4e7335f5-b430-e92d-1df5-e93e3b481402.jpeg)
>一度は見たことあるはず

つい懐かしくなってさらっと書いちゃいました(笑)。
書いた後に塗りつぶしてアレンジしたりと、応用が効いて当時は楽しんでいた記憶があります。図工の時間で作ったっけ？

>![IMG_4150.jpg](https://qiita-image-store.s3.amazonaws.com/0/263905/aa4bb749-de10-0906-77c3-e12f69c20042.jpeg)
>チェック模様の音〜(水素の音風に)

いつか完璧に綺麗な模様を描きたいと強く願っていました。そしてついにPythonのグラフ描画ライブラリmatplotlibを使って簡単に実装できたのでご紹介します。

※この模様の正式名称はなんだろ...読者の方で知ってる方が居ましたらコメントお願いします！(そもそも作ったことある？？)

# まずはシンプルに
先の画像と同じデザインのグラフを描画してみます。

```flow_glaph.py
import matplotlib.pyplot as plt

LINES = 20

j = LINES
for i in range(0, LINES + 1, 1):
	plt.plot([i, 0], [0, j])
	j -= 1

plt.show()
```

出力がこちら。

![Figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/263905/a7d48a33-a0e4-9f2e-8a5e-bff817d3fc0b.png)

デフォルトでは線の色が統一されてないうえに目がチカチカするので黒に統一しましょう。
ここから先は線の描画部分のみ記載していきます。

```
# 線を黒に変更
plt.plot([i, 0], [0, j], color = '#000000')
```

![Figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/263905/a4b5e0bd-fdb9-4611-ce6e-61f82d341f81.png)

こちらの方が見やすいですね。

# 2つ組み合わせて目の形に
先のグラフの対角線上にもう１つ同じものを作成して目の形を作ってみましょう。

```
# 左下に表示
plt.plot([i, 0], [0, j], color = '#000000')
# 右上に表示
plt.plot([i, LINES], [LINES, j], color = '#000000')
```

![Figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/263905/dcb1304d-b7f5-2af8-213a-5c480a28fb26.png)

for文で回して描画するので一行だけで増やすことができます。

# 思い切って４つ作る
さらに2つ増やして4つ作ってみます。

```
# 左下に表示
plt.plot([i, 0], [0, j], color = '#000000')
# 左上に表示
plt.plot([0, i], [i, LINES], color = '#000000')
# 右下に表示
plt.plot([LINES, j], [j, 0], color = '#000000')
# 右上に表示
plt.plot([i, LINES], [LINES, j], color = '#000000')
```

![Figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/263905/2ebf9105-57c4-80bd-4395-8e0cd49e7cf7.png)

複雑怪奇な模様もPython × matplotlibなら簡単に表現できますね！

# 線の数を変更してみる
デフォルトでは20本の線を引くように指定しています。
変更するにはLINESの値を増減させてみてください。

#### LINES = 5の場合

![Figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/263905/3b4df36c-8f7e-e9d7-518f-87535a2745bf.png)

見違えるほどシンプルになりました(笑)。
四角形が回転しているように見えますね。

#### LINES = 100の場合

![Figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/263905/08c330f8-23ca-0db2-003f-57c6d3a2a2be.png)

細かすぎて見えない...
5本の時と比較すると20倍に線の数が増えたので描画に数秒ほど時間がかかりました。

# まとめ

- 手書きとプログラムどっちで書いても楽しい
- 線や模様の数を容易に変更できるのでプログラムなら超時短につながる
- 実用性は皆無だけど暇つぶしに作ってみると割と面白い
- 失敗から生まれる未知な模様の発見↓

>![Figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/263905/8ca2148d-0312-e54a-9b0e-1034581e8aaf.png)
>某大手スポーツメーカーのロゴを彷彿する模様(

最後にこの模様の名前を知っている方はコメントしていただくと幸いです。
yield a, b と yield [a, b] は違う

```ruby
def yield_two_args
  p yield 1, 2
end

def yield_array
  p yield [1, 2]
end
```

この2つのメソッドの違いを確認します。

## ブロック引数が2つの場合
`yield_two_args`と`yield_array`は同じ挙動なので、この使い方をする限り利用する側には2メソッドの違いが見えない

```ruby
yield_two_args {|a, b| a + b } #=> 3
yield_array {|a, b| a + b } #=> 3
```

## ブロック引数が1つの場合
このときに挙動が異なる

```ruby
yield_two_args {|a| a } #=> 1
yield_array {|a| a } #=> [1, 2]
```

# Hash#each
ちなみに、`Hash#each`はkeyとvalueのペアがブロックに渡ってきますが、

```ruby
{ key: "value" }.each {|a| p a} #=> [:key, "value"]
```

ということで、`yield [key, val]`形式です
userDefaultsを使った配列の保存・取得・操作

userDefaultsを使用した1次元配列・2次元配列の扱い方について備忘録として掲載します。
仕様上、大量のデータの保存には向いていません。その際はDBを使った方が高速に動作するでしょう。

# 1次元配列の保存・取得

```swift:ViewController.swift
import UIKit

class ViewController: UIViewController {
    
    //  userDefaultsの定義
    var userDefaults = UserDefaults.standard

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        // userDefaultsに格納したい値
        let maxSpeed: [Double] = [120.05, 134.25, 80.5]
        // 配列の保存
        userDefaults.set(maxSpeed, forKey: "udMaxSpeed")
        
        // userDefaultsに保存された値の取得
        let getMaxSpeed:[Double] = userDefaults.array(forKey: "udMaxSpeed") as! [Double]
        print(getMaxSpeed)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}
```

```console:console
[120.05, 134.25, 80.5]
```

## 値の追加

ここから先はViewDidLoad()内の処理のみ記載します。

```swift:ViewController.swift
// userDefaultsに格納したい値
let maxSpeed: [Double] = [120.05, 134.25, 80.5]
// 配列の保存
userDefaults.set(maxSpeed, forKey: "udMaxSpeed")

// userDefaultsに保存された値の取得
var getMaxSpeed:[Double] = userDefaults.array(forKey: "udMaxSpeed") as! [Double]
// 値の追加
let addMaxSpeed: Double = 100.0
getMaxSpeed.append(addMaxSpeed)
print(getMaxSpeed)
```

```console:console
[120.05, 134.25, 80.5, 100.0]
```

# 2次元配列の保存・取得

```swift:ViewController.swift
// userDefaultsに格納したい値
let count: [[Int]] = [[20, 34, 50, 12], [21, 44, 38, 40]]
// 配列の保存
userDefaults.set(count, forKey: "udCount")

// userDefaultsに保存された値の取得
let getCount: [[Int]] = userDefaults.array(forKey: "udCount") as! [[Int]]
print(getCount)
```

```console:console
[[20, 34, 50, 12], [21, 44, 38, 40]]
```

## 1次元配列のデータを末尾に追加する

```swift:ViewController.swift
// userDefaultsに格納したい値
let count: [[Int]] = [[20, 34, 50, 12], [21, 44, 38, 40]]
// 配列の保存
userDefaults.set(count, forKey: "udCount")

// userDefaultsに保存された値の取得
var getCount: [[Int]] = userDefaults.array(forKey: "udCount") as! [[Int]]
// 追加したい値
let addData: [Int] = [10, 37, 62, 19, 43,85]
// 値の追加
getCount.append(addData)
print(getCount)
```

```console:console
[[20, 34, 50, 12], [21, 44, 38, 40], [10, 37, 62, 19, 43, 85]]
```

## 追加したデータの削除

```swift:ViewController.swift
// userDefaultsに格納したい値
let count: [[Int]] = [[20, 34, 50, 12], [21, 44, 38, 40]]
// 配列の保存
userDefaults.set(count, forKey: "udCount")

// userDefaultsに保存された値の取得
var getCount: [[Int]] = userDefaults.array(forKey: "udCount") as! [[Int]]
// 追加したい値
let addData: [Int] = [10, 37, 62, 19, 43,85]
// 値の追加
getCount.append(addData)

// 末尾の1次元配列を削除
getCount.removeLast()
print(getCount)
```

```console:console
[[20, 34, 50, 12], [21, 44, 38, 40]]
```
[Android]ビルド時の"Duplicate files copied in APK META-INF/LICENSE"対策

各種ライブラリをアップデートしたりすると、ビルド時に以下のようなエラーが出てくることがあります。

```
Error:Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'. > 
com.android.build.api.transform.TransformException: 
com.android.builder.packaging.DuplicateFileException: Duplicate files copied in APK META-INF/LICENSE
```

対策方法として、appフォルダ以下のbuild.gradleファイルに以下を追加編集することで解決できます。

```
android {
    ～(中略)

    packagingOptions {
        exclude 'META-INF/LICENSE'
    }

    ～(中略)
}
```
[Android] アクティビティ起動時の"Caused by: android.view.InflateException: Binary XML file line #25: Error inflating class <unknown>"対策

アクティビティ起動時のonCreateメソッド実行時に以下のエラーでクラッシュすることがまれにあります。

# クラッシュレポート
```
Caused by: android.view.InflateException: Binary XML file line #25: Error inflating class <unknown>
```

原因が全く分からなかったのですが、ヒープメモリ不足状態でImageViewなどで画像ロード（特に拡大縮小やると致命的）してクラッシュしたときに出るログの様子です。

# 対策方法
適度にガーベッジコレクションを意図的に実行する、拡大縮小しない、largeヒープを使うなど。

# 参考文献
* [android.view.InflateException: Binary XML file line #: Error inflating class](
https://stackoverflow.com/questions/38146238/android-view-inflateexception-binary-xml-file-line-error-inflating-class)
* [android.view.InflateException: Binary XML file line #24: Error inflating class <unknown>](https://stackoverflow.com/questions/45712476/android-view-inflateexception-binary-xml-file-line-24-error-inflating-class)
* [「OutOfMemoryError」のテスト](http://www115.sakura.ne.jp/~byunbyun/android1/android24.html)
AdMob ネイティブアドバンス広告の実装

AdMobネイティブアドバンス広告の対応方法について説明します。

# Androidでの導入手順
## AdMob管理画面
広告作成画面で以下のように選択出来る用になります。
![4d70bb045cc973c05388798f4bb9838c.png](https://qiita-image-store.s3.amazonaws.com/0/259963/d8cbeeac-995f-20ec-9632-b4c0282f7f15.png)

## 実装コード
[AdMob for AndroidのNative Ads Advancedページ](https://developers.google.com/admob/android/native-advanced?hl=ja)
[ネイティブ広告とカスタム レンダリング - SDK for DFP Users on Android](https://developers.google.com/admob/android/native-advanced?hl=ja)
に必要な情報がまとまっています。まずはこちらを軽く目を通すと、概要や実装方法が分かると思います。

簡単にまとめると、ネイティブ広告表示用のレイアウトを自前で用意して、リクエスト帰ってきたデータをそのレイアウトの適切な場所に表示するだけです。

手っ取り早く実装するのであれば、[GitHubのサンプル](https://github.com/googleads/googleads-mobile-android-examples/tree/master/java/admob/NativeAdvancedExample)をダウンロードし、ローカルでビルドして動きを確認しつつ、自分用にカスタマイズするのがお勧めです。

# 広告の種類について
~~AppInstallAdとContentAdの2種類があります。AppInstallAdはアプリインストールを促進する広告で、ContentAdはAdsenseなどWeb系の静的コンテンツ広告です。どちらか一方をリクエスト出来ますが、両方リクエストした場合に最終的にどちらが表示されるかは、収益性などを考慮してGoogle側で自動で決定されているようです。~~

現在はUnifiedNativeAdを利用することが推奨されています。収益性が高いように自動で最適なコンテンツを表示してくれます。ソースコードは、[ここ](https://github.com/googleads/googleads-mobile-android-examples/blob/master/java/admob/NativeAdvancedExample/app/src/main/java/com/google/example/gms/nativeadvancedexample/MainActivity.java)のサンプルがそのまま利用出来ると思います。

## テスト専用IDについて
テスト時は広告ユニットIDとして[AdMob指定](https://developers.google.com/admob/android/test-ads)の以下を指定します。

```
ca-app-pub-3940256099942544/2247696110
```

バナーやインタースティシャル等の見慣れたテスト広告とは異なり、いまいま？は以下のように、本物の広告が出る様子で、本当にクリックしてもいいか悩みますが、クリックしても収益にはならず大丈夫っぽいです。けど、クリックするのは気が引けますね…。
<img width="615" alt="スクリーンショット 2020-04-23 18.51.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259963/25b0d379-712c-bc91-59cc-6c353e5d2c78.png">

## テストデバイス設定
テストデバイス設定をしておくことで、本番用の広告であってもテスト項目として認識してくれる様子ですので、自分の誤クリックを防ぐためにも設定しておくべきです。ただ、Galaxy系のデバイスは同一デバイスであってもなぜかテストデバイスIDがコロコロ変わっているような…。

```
AdRequest adRequest = new AdRequest.Builder()
                .addTestDevice("XXXXXXXXXXXXXXXXXXXXX") // あなたのテストデバイスを追加
                .build();
adLoader.loadAd(adRequest);
```

# 安定性
~~一時期はクラッシュが頻発していたりしますが、割と安定してきているのではないでしょうか。ただ、まだ一般公開されていないということは問題を色々と抱えているのでしょう。~~

現在は全く問題なく使えます。この広告起因のクラッシュも基本起きていないと思います。
Rの便利なライブラリ（dplyr）


## dplyr

データの抽出・変数の追加・ソートなどの操作を行うライブラリ。

### ライブラリ読み込み

```
library(dplyr)
```

### サンプルデータを作成

```
> sample1 <- data.frame(x=1:10, y=6:15, z=21:30)
> sample1
    x  y  z
1   1  6 21
2   2  7 22
3   3  8 23
4   4  9 24
5   5 10 25
6   6 11 26
7   7 12 27
8   8 13 28
9   9 14 29
10 10 15 30
```

`<-`は代入演算子です。変数`sample1`に`data.frame`で作成したデータを代入しています。

`A %>% B()`とすると、Bの第1引数にAが渡されます。

- filter

データ抽出

`sample1`のデータから、`x > 5`の条件を満たす行を抽出します。


```
> sample2 <- sample1 %>%
  dplyr::filter(x > 5)
> sample2
   x  y  z
1  6 11 26
2  7 12 27
3  8 13 28
4  9 14 29
5 10 15 30

# AND条件は,区切り、OR条件は|区切りで入れます
> sample3 <- sample1 %>%
  dplyr::filter(z < 22 | x > 5, y < 14)
> sample3
  x  y  z
1 1  6 21
2 6 11 26
3 7 12 27
4 8 13 28
```


- select

列の抽出

```
> sample4 <- sample1 %>%
  dplyr::select(x,y)
> sample4
    x  y
1   1  6
2   2  7
3   3  8
4   4  9
5   5 10
6   6 11
7   7 12
8   8 13
9   9 14
10 10 15
```

- mutate

変数の追加

```
> sample5 <- sample1 %>%
  dplyr::mutate(sum = x + y + z)
> sample5
    x  y  z sum
1   1  6 21  28
2   2  7 22  31
3   3  8 23  34
4   4  9 24  37
5   5 10 25  40
6   6 11 26  43
7   7 12 27  46
8   8 13 28  49
9   9 14 29  52
10 10 15 30  55
```

---

※適宜追記していきます。
TouchDesigner | Primitive SOP でColorを付け加える

SphereはPolygon
![screenshot 2018-06-30 10.25.51.png](https://qiita-image-store.s3.amazonaws.com/0/199903/861c1960-747f-b169-0e22-12a3a7f72f78.png)

```
tdu.rand(me.inputPrim.index+1)
```
<br />
![screenshot 2018-06-30 10.25.38.png](https://qiita-image-store.s3.amazonaws.com/0/199903/64ecd7c2-8a07-b927-a380-9045754c65b5.png)
アイテムの取得〜持ち物画面への反映まで実装する。 

機能作成にあたり、下記が大変大変参考になりました。感謝！

【参考】[UnityでScriptableObjectを使ってアイテムデータベースを作成する]
(https://gametukurikata.com/program/scriptableobjectitemdatabase)



```Item.cs
//アイテムの情報を作成する
[Serializable]
[CreateAssetMenu(fileName = "Item", menuName = "CreateItem")]
public class Item : ScriptableObject
{

    public enum KindOfItem
    {
        Weapon,
        UseItem
    }

    //　アイテムの種類
    [SerializeField]
    private KindOfItem kindOfItem;
    //　アイテムのアイコン
    [SerializeField]Sprite icon;
    //　アイテムの名前
    [SerializeField]
    private string itemName;
    //　アイテムの情報
    [SerializeField]
    private string information;

    public KindOfItem GetKindOfItem()
    {
        return kindOfItem;
    }

    public Sprite GetIcon()
    {
        return icon;
    }

    public string GetItemName()
    {
        return itemName;
    }

    public string GetInformation()
    {
        return information;
    }
```
```ItemController.cs
//アイテム取得のためのクラス。
public class ItemController : MonoBehaviour
{
    [SerializeField] Item iteminfo; //さっきのアイテム情報をアタッチ
    Collider other;

    private void Start()
    {
        this.OnTriggerStayAsObservable()
            .Where(other => other.gameObject.tag == "Player")
            .Where(_ => PlayersItem.itemLists.Count < 6)
            .Where(_ => Input.GetKeyUp(KeyCode.LeftControl))
            .Subscribe(_ => AddItem())
            .AddTo(this.gameObject);
    }

    void AddItem(){
        PlayersItem.itemLists.Add(iteminfo);
        Destroy(this.gameObject);
    }
}
```
```PlayersItem.cs
//プレイヤーの所持アイテムはここで管理
using UnityEngine;
using UniRx;

[CreateAssetMenu(fileName = "PlayersItem", menuName = "CreatePlayersItem")]

public class PlayersItem : ScriptableObject
{
    public static ReactiveCollection<Item> itemLists = new ReactiveCollection<Item>();

    //アイテムリストを返す
    public ReactiveCollection<Item> GetItemLists()
    {
        return itemLists;

    }
}
```
```ItemMenue.cs
//所持アイテムをアイテム画面に映す。改良の余地あり
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UniRx;
public class ItemMenue : MonoBehaviour
{

    [SerializeField] List<Image> itemSlots = new List<Image>();

    // Use this for initialization
    void Start()
    {
        PlayersItem.itemLists.ObserveAdd()
                   .Subscribe(_ => ReloadItemSlots());
        PlayersItem.itemLists.ObserveRemove()
                   .Subscribe(_ => ReloadItemSlots());
    }

    void ReloadItemSlots()
    {
        for (int i = 0; i < PlayersItem.itemLists.Count; i++)
        {
            itemSlots[i].sprite = PlayersItem.itemLists[i].GetIcon();
        }
    }
}
```
Galaxy S8などの新しい画面サイズ(18:9)の対応方法

Galaxy S8などの最新スマホで出てきた、18.5:9といったアスペクトの画面サイズに対応する方法の備忘録です。

# 対応方法
対応方法は至って簡単で、AndroidManifest.xmlファイルにandroid.max_aspectでサポートする最大のアスペクト比率を指定するだけです。

```AndroidManifest.xml
<meta-data android:name="android.max_aspect" android:value="2.1" />
```


# 参考文献
<a href="https://developers-jp.googleblog.com/2017/04/update-your-app-to-take-advantage-of.html" target="_blank">アプリをアップデートして Android の新しいハイエンド端末で大きなアスペクト比を活用する</a>
vimにtaglist導入

## ctagsインストール

https://qiita.com/maeharin/items/9f98c0d63ab764ee21a8

```
$ brew install ctags
```

Macにデフォルトで入っている`ctags`より優先して今回入れる`ctags`を使うようにしたいから、

```
$ ls /usr/local/Cellar/ctags/
5.8_1

$ vim /.bash_profile
+ alias ctags='/usr/local/Cellar/ctags/5.8_1/bin/ctags'
```

これで使えるようになった。

```
$ ctags -R
```
でディレクトリ内を再帰的にタグ生成。
homestead の migrate で SQLSTATE[HY000] [2002] Connection refused 

# 注意
Qiita に保存されていた昔の下書きから当記事を投稿しているのでバージョンなど情報が古いかもしれません＼(^o^)／
ポイントは homestead データベースとユーザーでパスワードが secret というところですね。

`homestead up` をしたあとに `migrate`をしたら失敗してしまいました。

# migrateが失敗

```
php artisan migrate
                                                                                                                                                    
  [Illuminate\Database\QueryException]                                                                                                                 
  SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = homestead and table_name = migrations)  
                                                                                                                                                                                                   
  [PDOException]                             
  SQLSTATE[HY000] [2002] Connection refused                                               
```
データベースに接続できないというエラーが出ています。

# 環境
Macで`homestead up`したばかりのLaravelプロジェクトです。

# データベースがあるのか確認
`homestead ssh`してMySQLにアクセスできるかどうかを確認します。
適当にrootユーザーでMySQLにログインを試しました。

```
mysql -u root
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
```
だめです。何か根本的に足りないみたいです。

# .envを確認
.envに設定が書いてあるそうです。

```
vim .env

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
```
homesteadユーザーでsecretでログインできるのですね。

# homestead provision
データベースを作成するためにコマンドの実行が必要みたいで。

```
homestead provision
```
なにやらいっぱい実行されました。データベースが作成されたはずです。

# データベースの確認
`homestead ssh`からMySQLの確認します。

```
mysql -u homestead -p
```
パスワードは`secret`ですね。
ログインできたので、データベースを確認します。

```
show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| homestead          |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)
```
データベース`homestead`が作成されていました。

# 再度migrateを実行
こんどはうまくいきました。


# 参考
- http://minotaur.badwitch.io/getting-started-laravel-database/
アプリにおける排他制御 -楽観的/悲観的ロックの違いと使い所-

# 対象読者
-「楽観的」とか「排他的」とか聞いたことあるけどよくわかっていない方

# 楽観的ロックと悲観的ロック
##楽観的ロック
更新対象のデータが、**データの取得時点から更新されていないことを確認したうえで更新する**ことでデータの整合性を保証する
##悲観的ロック
更新対象のデータを取得時点から**明示的にロックしてから更新する**（＝他トランザクションによる更新を防ぐ）ことでデータの整合性を保証する
##表で見る楽観的ロック・悲観的ロック
|   |楽観的ロック|悲観的ロック|
|:------|:-------|:---|
|排他制御の主体|アプリケーション|データベース<br>(DBMS)|
|実現手段|・データ取得時の最終更新日時またはバージョン番号を条件に含めて更新する*1|・「SELECT <font color="red">FOR UPDATE</font>」によってデータを取得して更新する|
|使いどころ|・更新頻度が高くない<br>・同時更新されることがあまりない|・トランザクションが短い<br>・更新頻度が高い<br>・同時更新されることが多い|
|アプリ方式としての採用状況<br>※私見|よく使われる*2|あまり使われない|

*1 最終更新日時の場合、同一時点に更新処理が実行された場合の一意性を保証できないため、基本的にはバージョン用カラム（更新の度に+1することで更新状態を把握するためのカラム）を使用することをおすすめします

*2 以下が参考になりました
>So which one should you pick?
>
>**The answer is that, there is no correct answer – it depends. You should pick your locking scheme based on your application requirements.**
>
>Unless you expect a document to be heavily contended, **optimistic locking is going to be much lower overhead than pessimistic locking** – grab the item you need, update it quickly and attemp to apply it. If some other actor in the system beat you to it, you can just retry till you succeed.

[Optimistic or pessimistic locking – Which one should you pick?](https://blog.couchbase.com/optimistic-or-pessimistic-locking-which-one-should-you-pick/)

# 最後に
今後追記します。たぶん。

# 参考
[データの同時更新を防ぐための排他制御](https://codezine.jp/article/detail/6764)
Laravel で MariaDB から MongoDB へデータベースを切り替える

Laravel は、MVC なので、Model 部分の変更だけで、データベースを切り替えることが出来ます。
例として、次で作成したものを切り替えてみました。
[Laravel で MariaDB の API を作成](https://qiita.com/ekzemplaro/items/c5d4f59fd2e850052257)
MariaDB も、MongoDB も
>データベース　city
ユーザー　scott
パスワード　tiger123
として、データの移行はすんでいるとします。

1) ライブラリーのインストール

```bash
composer require jenssegers/mongodb
```

2) config/app.php の編集

```php:config/app.php
'providers' => [
// 略
        Jenssegers\Mongodb\MongodbServiceProvider::class,
 ],

    'aliases' => [
// 略
         'Moloquent' => Jenssegers\Mongodb\Eloquent\Model::class,
 ],
```

3) .env の編集

```text:.env
DB_CONNECTION=mongodb
DB_PORT=27017
```

4) config/database.php の編集

```php:config/database.php
'default' => env('DB_CONNECTION', 'mongodb'),
    // 略
    'connections' => [
        'mongodb' => [
            'driver' => 'mongodb',
            'host' => env('DB_HOST'),
            'port' => env('DB_PORT'),
            'database' => env('DB_DATABASE'),
        'username' => env('DB_USERNAME'),
        'password' => env('DB_PASSWORD'),
        ],
    ],
```

5) キャッシュのクリア

```bash
php artisan cache:clear
```

6) モデルの編集

```php:app/Models/City.php
<?php

namespace App\Models;

class City extends \Moloquent
{
protected $collection = 'saitama';
}
```

7) サーバーの起動

```bash
php artisan serve --host 0.0.0.0
```

8) クライアントでアクセス

```bash
curl http://localhost:8000/api/city
curl http://localhost:8000/api/all
curl http://localhost:8000/api/where/岡山
curl http://localhost:8000/api/between/30000/50000
```
勤怠管理システムの各機能の実装

#管理者は個人情報を修正できないようにする

###URLベタ打ちで編集画面に飛べないようにする


```/attendance_management/app/controllers/attendance_controller.rb

if current_user.admin?
　redirect_to :action => 'index'
end
```

```/attendance_management/app/controllers/users_controller.rb
if current_user.admin?
  redirect_to :action => 'index'
end
```


###管理者でログインした場合、ヘッダーメニューから「個人情報の修正」リンクを削除する

```/attendance_management/app/views/layouts/_header.html.erb

<% if current_user.admin? %>
  <li class="dropdown">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown">
      アカウント <b class="caret"></b>
    </a>
    <ul class="dropdown-menu">
      <li><%= link_to "個人情報の修正", edit_user_path(current_user) %></li>
      <li class="divider"></li>
      <li>
      <%= link_to "ログアウト", logout_path, method: "delete" %>
      </li>
    </ul>
  </li>
<% else %>
```

#翌日チェックボックスの追加

```/attendance_management/app/views/attendance/edit.html.erb

<!-- 翌日のチェックボックスの表示  -->
<td class="table-body">
  <%= check_box_tag 'check[]', attendance.day %>
</td>
```

```/attendance_management/app/controllers/attendance_controller.rb

# チェックがあれば翌日の時間で退社扱い
if !params[:check].nil? && !attendance.edited_work_end.nil?
  if params[:check].include?(attendance.day.to_s)
          attendance.update_column(:edited_work_end, attendance.edited_work_end+1.day)
  end
end
```

#指定勤務時間の表示

```/attendance_management/app/views/users/_overtime_work.html.erb

<!-- 指定勤務時間の表示  -->
<td class="table-body">
  <%= format("%.2f", 
 ((@user.designated_work_time.strftime("%H").to_i*60.0) + @user.designated_work_time.strftime("%M").to_i)/60) %>
</td>
```


#在社時間ーでエラー表示

```/attendance_management/app/controllers/attendance_controller.rb

# 在社時間ーでエラー表示
if (item["work_start(4i)"]+item["work_start(5i)"]).to_i > (item["work_end(4i)"]+item["work_end(5i)"]).to_i
  if params[:check].nil?
    flash[:danger] = '在社時間がーになっています'
      redirect_back(fallback_location: root_path) and return
  else
    # 申請者が入力されていたら『申請中』に変更する
    if !item[:authorizer_user_id_of_attendance].blank?
      attendance.applying1! 
      # 申請者の番号も保持
      @user.update_attributes(applied_last_time_user_id: item[:authorizer_user_id_of_attendance])
    end
  end
else
  # 申請者が入力されていたら『申請中』に変更する
  if !item[:authorizer_user_id_of_attendance].blank?
    attendance.applying1! 
    # 申請者の番号も保持
    @user.update_attributes(applied_last_time_user_id: item[:authorizer_user_id_of_attendance])
  end
end
```
[学習用]Herokuでサブドメインなしの独自ドメインとSSLを設定する方法。Heroku内で完結。Cloudflare は使わない方法。


多分簡単。
けっこうハマって右往左往したけど結局簡単だったお話。

まず本番環境じゃなく、ドメイン設定してしまっていたらドメイン設定をHerokuから消そう。


#DNSの設定
##1.Add-ons PointDNSを入れる
![pointdns.png](https://qiita-image-store.s3.amazonaws.com/0/132580/62f832e4-85e7-7e3a-c9a1-72ecebe55dcd.png)

##2.PointDNSにドメイン名を入れる
![pointdns02.png](https://qiita-image-store.s3.amazonaws.com/0/132580/d3bed138-c760-75aa-a381-5ea300053c75.png)

右上の Domain name にドメイン入れて Add を押す。

##3.dns～をメモする
![Point03.png](https://qiita-image-store.s3.amazonaws.com/0/132580/58787f8e-b29e-a741-7e55-bcd12cdff81d.png)

このDNSをメモする
dns12.pointhq.com
dns15.pointhq.com
dns8.pointhq.com

##4.ネームサーバーを記入
![Point04.png](https://qiita-image-store.s3.amazonaws.com/0/132580/33ecb9a1-6152-c7f3-a324-28f338383225.png)

これをドメイン取得したサイトに行ってネームサーバーへ記入する。

これで待つこと数時間から1日で独自ドメインは反映される。

##ハマったこと
他のサイトには、無料でなんとか設定しようとしていることや
サブドメインなしの設定をCDN使って迂回しながら行っている様で
自分の理解が追い付かず、ハマってしまった。

heroku だとサブドメインなしが出来ないって書いたあったが、実際は上の設定だけで簡単に出来ました。

#SSLの設定
##1.HerokuでSSLを設定する
![pointdns04png.png](https://qiita-image-store.s3.amazonaws.com/0/132580/c158a9b1-6048-e1f8-d77e-09d3784d2be8.png)

Herokuにて Configure SSLをクリックしてSSL設定する。

##2.DNS Target の値をメモ
HerokuのDNS Target の値をメモしておく。
例：ドメイン名.herokudns.com って値
sample.com.herokudns.com の様な感じになっているはず。
よくよく確認すると、heroku.comではなく 「 heroku d n s .com 」「dns.com」になっている点に注意。

##3.PointDNSの設定
![pointdns03png.png](https://qiita-image-store.s3.amazonaws.com/0/132580/f5493f53-c6df-4dda-7af7-d1e33aaa0928.png)

先ほどメモッた値(例：sample.com.herokudns.com)を 
ALIAS
CNAME
の２つを鉛筆マークの編集ボタンから編集して書き換える。
※元の値は 「アプリ名.herokuapp.com 」「sample-app.herokuapp.com」の様になっていると思う。

これで問題無く無事に解決した。

##ハマったこと
SSL設定するときに、ドメイン名.herokudns.com を変更する様にっていう警告みたいな文章をきちんと読まなかったこと。
勝手に値が変わるみたいな感じで解釈してしまった。
そのため、SSLにはなったが、hedokuのドメイン名のままだった。

###その他
ALIAS、CNAME の設定で CNAMEがWWW のままだけど問題無い。
wwwは消せないけど、そのままでサブドメインなしのSSLで運用出来ます。
確認済。

◆参考
[Ruby on Rails5でコメント付きブログを簡単に作成してデザインも一緒にする手順　初心者向けの無料講座](https://yokoyamadesuga.com/ruby-on-rails5-beginners-free-course/)
[プログラミングで挫折しそうなら読むべき記事](https://yokoyamadesuga.com/beginner-programming-learning-school/)
[Ionic]アプリの基本動作「タブバーの自動スクロール」と「引っ張り更新」

##　アプリの基本動作
調べると比較的にすぐ出てくるが、覚えがき

### タブバー
タブバー上でタブを選択すると以下の動作となることが一般的と思われる。
・タブの切り替え(Ionicでタブのプロジェクトで作成すれば、特に修正不要)
・アクティブなタブの上にページがスタックされた状態でタブをクリック
　→上のページがクリアされる（こちらのNavControllerを利用していれば、特に修正不要）
・アクティブなタブの上にページがスタックされていない状態でタブをクリック
　→ページが一番上（または下）に自動スクロール（今回記載）

### 引っ張り更新
下に引っ張るとリロード

## 対応
### タブバーの自動スクロール
対象のページのtsの修正が必要

```TypeScript
// 必要なimport
import {ViewChild} from '@angular/core';
import {Content} from 'ionic-angular';

export class HomePage {
  @ViewChild(Content) content: Content;

  // アクティブかつページがスタックされていない状態で呼ばれるevent
  ionSelected() {
    this.content.scrollToTop();
    // scrollBottom()等あるので、スクロール方法に合わせる
  }
}
```

### 引っ張り更新
対象のページ(ion-content内が自動でスクロールされる)の
html, ts, 背景白色になるので、背景色を変えている場合は、scssの修正が必要

```Html
<ion-content>
  <ion-refresher
    (ionRefresh)="doRefresh($event)">
    <ion-refresher-content>
    </ion-refresher-content>
  </ion-refresher>

  ここにリストなどの表示処理を記載
</ion-content>
```

引っ張り更新イベントの処理を書く

```TypeScript
export class HomePage {
  doRefresh(refresher) {
    // ここに更新時の処理を追加

    setTimeout(() => {
      refresher.complete();
    }, 2000);
  }
}
```

背景を透過したかったので、SCSSで背景色を消す

```SCSS
  ion-content {
    background-color: rgba(0,0,0,0) !important;
  }
```
[GAS] GmailでCSSを反映させた下書きを生成する方法

# ゴール
以下を**下書き**メールとして生成すること。
<img width="208" alt="スクリーンショット 2018-06-30 4.47.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/159680/0fe70ed7-235c-3ce9-8248-ef1414295c75.png">

# 前提
## GAS
htmlファイルをTemplateとして読み込み、`createDraft`で下書きを生成したい。
以下のようなコードを書いた時、CSSをどう書くかという話。

```sample.js
function createGreetingEmail() {
  // index.htmlファイルをテンプレートとして読み込む
  var template = HtmlService.createTemplateFromFile("index");
  // テンプレートの変数に値を代入
  template.name = "tarou";
  // 文字列として生成
  var html = template.evaluate().getContent();

  GmailApp.createDraft(
    "done@example.com",
    "Greeting",
    "htmlが表示できません...",
    {htmlBody: html}
  );
}
```

# HTML & CSS の書き方
## こう書く
**createDraft**でスタイルを反映させるには、**<font color="ORANGE">インライン形式</font>**で書くしかない。

```index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <h1 style=color:red;> hello <?= name ?> </h1>
  </body>
</html>
```

補足: `<?= hogehoge ?>`という書き方で、GASの変数を代入できる。

## 失敗例
`<head>`や`<body>`内に書く

```index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <style type="text/css">
      h1 {color:red;}
    </style>
  </head>
  <body>
    <h1 >hello <?= name ?> </h1>
  </body>
</html>
```

# ちなみに、sendEmailではちょっと違う
`createDraft`ではなく、**`sendEmail`**の場合は、**`<head>`や`<body>`内に書いてもOK**。

不便だなぁ、、なんでだろう??...

# 参考
- [Class GmailApp リファレンス](https://developers.google.com/apps-script/reference/gmail/gmail-app#createdraftrecipient-subject-body-options)
- [Class HtmlService リファレンス](https://developers.google.com/apps-script/reference/html/html-service)
PythonとKerasによるディープラーング　詰み回避

#はじめに
[PythonとKerasによるディープラーング](https://book.mynavi.jp/ec/products/detail/id=90124)の中で、個人的に詰まったところをメモします。

##p.198 IMDbデータセットのダウンロード
「IMDbデータセットを元の状態でダウンロードし[4]、展開します。」
とありますが、[4]に表記されている[url](http://mng.bz/0tlo)のページに進んでもどこからダウンロードすればよいやら分かりませんでした。
ここからダウンロードできます。
http://files.fast.ai/data/aclImdb.tgz
Postfixのインストール（ソースから）

試しにやってみたのでメモ

# 手順
1. 必要なパッケージをインストール

    ```
    # yum -y install gcc libdb-devel
    ```

2. sendmailや古いPostfixをアンインストール

    ```
    # yum -y remove postfix
    ```

3. ソースをダウンロード

    ```
    # curl -LkvOf ftp://ftp.riken.jp/net/postfix/postfix-release/official/postfix-3.3.1.tar.gz
    ```

4. ダウンロードしたソースを展開

    ```
    # tar -zxf postfix-3.3.1.tar.gz
    # cd postfix-3.3.1
    ```

5. コンパイルを実行

    ```
    # make
    ```

6. sendmailバイナリのバックアップ

    ```
    # mv /usr/sbin/sendmail /usr/sbin/sendmail.OFF
    # mv /usr/bin/newaliases /usr/bin/newaliases.OFF
    # mv /usr/bin/mailq /usr/bin/mailq.OFF
    # chmod 755 /usr/sbin/sendmail.OFF /usr/bin/newaliases.OFF /usr/bin/mailq.OFF
    ```

7. ユーザとグループを作成

    ```
    # useradd -M -s /sbin/nologin postfix
    # groupadd postdrop
    ```

8. インストール

    ```
    # make install
    ```

あとで [postfixadmin/postfixadmin のインストール](https://github.com/postfixadmin/postfixadmin/blob/master/INSTALL.TXT)もやれたらやってみよう

# 参考
- [Postfix Installation From Source Code](http://www.postfix.org/INSTALL.html#4)
- [ソース コードからの Postfix インストール](http://www.postfix-jp.info/trans-2.2/jhtml/INSTALL.html)
Vue.js2とFirebaseでLINEライクなチャットアプリを作ってみる。

#目次
1.目標
2.使った技術
3.実装
4.成果物
5.苦労した点
6.今後の展望
#使った技術
- Vue.js2
- Vuefire
- firebaseRTDB
- firebaseAuth
- Google様

#実装
目に見える部分から実装していきました。ログイン、サインアップページを作成しタブバーのコンポーネントを作成。
続いて各ページのコンポーネントとデータベースの構築（といってもFirebaseなので構造を考える）
それぞれのデザインを統一してデバッグしてひと段落といった感じです。

#成果物

https://line-no-pakuri.firebaseapp.com/

メールアドレスで友だち登録できるタイプのチャットアプリが出来上がりました。一つの話題について話せるパブリックグループも実装されています。

#苦労した点
なんといってもRDBでない形式のデータベース構造が大変なことになってしまい大変だった。
最初Vuetifyという素晴らしいマテリアルデザインのフレームワークを使い実装していたのだが、使い方が悪いのかバグが多すぎて結局最終的にほぼ全てが素のCSSに置き換えることになった。~~もう二度とつかわないです。~~
#今後の展望
さらに様々な機能を追加できる拡張性があるので未来は無限大といった感じですが、折角なのでここまでの実装をもう少し詳しく解説する記事でも書こうかなと思います。Vueは学習コストの低いフレームワークらしいですが実際にはライブラリのドキュメントが古かったりVue１時代の記事と混じったりて以外と苦労したので現時点での最新をアウトプットできれば良いなと思います。

※追記作ってる途中でVueNativeとかいう便利ツールができたらしいので使えばよかった、、
intlのメソッドをyamlから生成してくれるintl-yaml作ってみました(後日編集予定)

☠ 注意 ☠ 

この記事は結構適当です(AM 02:30の眠気眼でかいてます)。

後日修正予定なので、`こんな記事あるのかー`程度に認識していただければと思います。
リポジトリ先も適当です。後日アプデするので、お待ちいただくか。プルリクしていただくと最高にうれC

## 経緯

Flutterでi18n対応となると、`intl`を使用したものが出てきます。

https://pub.dartlang.org/packages/intl

使用感は特に問題なくて、問題なのはGlobalizeするデータ作成でした。

作成手順は以下のとおり

1. i18n対応する文字のgetter作成
2. getterコードからarbファイル出力
3. arbファイルを言語別に複製、修正
4. 3.のデータからGlobalize用のメソッド出力

Globalizeする元ファイル(arbファイル)を生成するのにまずgetterメソッドを書く必要があります。

```dart

  String helloUser(user) => Intl.message(
      'hello ${user}',
      locale: _localeName,
      name: 'helloUser',
      args: [user],
      examples: const {'user': 'Guest'}
  );

```

...めんどくさいねーん

## intl-yaml誕生

https://github.com/tanakeiQ/intl_yaml

## なにができるか

1. yamlファイル作成
2. CLIから実行

で、先の工程を済ませられます。

\\\\楽ちんチン!!!//

ただし、出力方式は２つしかありません。自分で使う文にはこの２つで良かったので。

1. そのまま出力

```yaml

hello: 'こんにちわ'
```
2. Named parameter

```yaml
helloUser:
  value: ':user さん こんにちわ!'
  examples:
    user: 'ゲスト'
```
AngularのComponentで{children}みたいなことをしたい

##  状況

AngularでアプリケーションをラップするようなContainer Componentを作ろうとしたら

## 解決

Reactで言うところの`{children}`にあたる、コンポーネントの小要素を表示できるようなスニペットがなかなか見つかりませんでした

調べて見ると、Angularでは小要素は`<ng-content>`というタグがこれに当たるようです

```html
<!-- React -->
<div className="container">
  {children}
</div>
```

これが

```html
<!-- Angular -->
<div class="container">
  <ng-content></ng-content>
</div>
```

こうなります

## おわりに

Reactの脳みそで検索をかけていたので`angular children`みたいな感じで調べていましたが、いまいちヒットせず、、

同じような方がこの記事にたどり着いてくれたら嬉しいです

## 参考

* [Creating a container component in Angular2](https://asp.net-hacker.rocks/2016/09/28/container-component-in-angular2.html)